arm-linux连接以及连接脚本
一.目标文件格式与类型
GNU C compiler根据源文件的后缀名来对文件进行预处理、汇编或编译操作。在编译链接时,生成的目标文件都是ELF格式的(可执行链接格式,Executable and Linking Format)。Object文件格式有三种类型:
(1)可重定位(relocatable)文件:用来和其他的object文件一起链接为一个可执行文件(executable)或一个共享文件(.so文件,shared object)。
(2)可执行(executable)文件;
(3)共享目标文件(shared object file):用于被下面的两个链接器链接。一是链接编辑器(ld),可以和其他的relocatable或shared object file来创建其他的目标文件,例如.so共享库(可用file命令查看其属性);二是动态链接器,联合一个可执行文件和其他的shared object file来创建一个进程映像。
二.链接与链接脚本
链接器ld把object文件中的每个section都作为一个整体,为其分配运行的地址(memory layout),这个过程就是重定位(relocation);最后把所有目标文件合并为一个目标文件。
链接通过一个linker script来控制,这个脚本描述了输入文件的sections到输出文件的映射,以及输出文件的memory layout。
因此,linker总会使用一个linker script,如果不特别指定,则使用默认的script;可以使用‘-T’命令行选项来指定一个linker script。
1. 映像文件的输入段与输出段
linker把多个输入文件合并为一个输出文件。输出文件和输入文件都是目标文件(object file),输出文件通常被称为可执行文件(executable)。
每个目标文件都有一系列section,输入文件的section称为input section,输出文件的section则称为output section。
一个section可以是loadable的,即输出文件运行时需要将这样的section加载到memory(类似于RO&RW段);也可以是allocatable的,这样的section没有任何内容,某些时候用0对相应的memory区域进行初始化(类似于ZI段);如果一个section既非loadable也非allocatable,则它通常包含的是调试信息。
每个loadable或allocatable的output section都有两个地址,一是VMA(virtual memory address),是该section的运行时域地址;二是LMA(load memory address),是该section的加载时域地址。
可以通过objdump工具附加-h选项来查看目标文件中的sections。
2. 简单的Linker script
(1) SECTIONS命令:
The SECTIONS command tells the linker how to map input sections into output sections, and how to place the output sections in memory.
命令格式如下:
SECTIONS
{
sections-command
sections-command
......
}
其中sections-command可以是ENTRY命令,符号赋值,输出段描述,也可以是overlay描述。
(2)地址计数器‘.’(location counter):
该符号只能用于SECTIONS命令内部,初始值为‘0’,可以对该符号进行赋值,也可以使用该符号进行计算或赋值给其他符号。它会自动根据SECTIONS命令内部所描述的输出段的大小来计算当前的地址。
(3)输出段描述(output section description):
前面提到在SECTIONS命令中可以作输出段描述,描述的格式如下:
sectionname [address] [(type)] : [AT(lma)]
{
output-section-command
output-section-command
...
} [>region] [AT>lma_region] [:phdr :phdr ...] [=fillexp]
很多附加选项是用不到的。其中的output-section-command又可以是符号赋值,输入段描述,要直接包含的数据值,或者某一特定的输出段关键字。
3. 举例
下面看一个常用的用于分散加载(即存储或加载地址<加载域>和链接或运行地址<运行域>不同)的格式:
SECTIONS {
...
secname start BLOCK(align) (NOLOAD) : AT ( ldadr )
{ contents } >region :phdr =fill
...
}
secname和contents是必须的,其他的都是可选的。下面挑几个常用的看看:
(1)secname:段名
(2)contents:决定哪些内容放在本段,可以是整个目标文件,也可以是目标文件中的某段(代码段、数据段等)
(3)start:本段连接(运行)的地址,如果没有使用AT(ldadr),本段存储的地址也是start。GNU网站上说start可以用任意一种描述地址的符号来描述。
(4)AT(ldadr):定义本段存储(加载)的地址。
SECTIONS {
firtst 0x00000000 : { head.o init.o }
second 0x30000000 : AT(4096) { main.o }
}
以上,head.o放在0x00000000地址开始处,init.o放在head.o后面,
arm-linux连接连接脚 相关文章:
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)