
本文共 10273 字,大约阅读时间需要 34 分钟。
目录
ld
gcc加了-c选项,会做预处理、编译、汇编,不连接,然后用ld来连接。会将gcc -c 产生的OBJ文件、系统库的OBJ文件、系统库文件连接起来,生成可以在指定平台运行的可执行文件。
参数
参数
含义
-Ttext address
指定代码段的起始地址
-Tdata address
指定数据段的起始地址
-Tbss address
指定bss段的起始地址
-T scrip-file
指定链接脚本
-o FILE
指定输出的文件名称
-Map map-file
把链接时的符号和地址生成映射文件
-Bstatic
(或-aarchive)
不连接共享库。表示此选项之后的“-l”只链接静态库(.a)。
例:gcc -L. -o main main.c -Bstatic -ltest1
此时,只会搜索libtest1.a,而不会搜索libtest1.so。
-Bdynamic
(或-ashared或-adefault)
连接共享库。表示此选项之后的"-l”链接动态库(.so)和静态库(.a)
例:gcc -L. -o main main.c -Bstatic -ltest1 -Bdynamic -ltest2
此时:只会搜索libtest1.a,而不会搜索libtest1.so。libtest2.so和libtest2.a都会搜索。
其他参数见《ld中文手册完全版.doc》
例: arm-linux-ld -Ttext 0 start.o init.o led_on.o -o led.elf 1.代码段起始地址为0x00000000,由于没有指明数据段和bss,他们会默认的依次放在后面 2.可以指定多个文件输出一个elf文件。 注意:start.o一定要放在第一个,init.o等用于代码重定位、要在重定位以前使用的代码,要靠前写, 保证它在4k之内。 3.当用.lds文件来作为-T选项时,也受文件执行顺序的影响链接脚本
另见:
完整链接脚本格式:
SECTIONS { ... secname start BLOCK(align) (NOLOAD) : AT ( ldadr ) { contents } >region :phdr =fill ... } secname和contents是必须的,其他都是选项,可有可无。AT ( ldadr )较常用,其他基本用不到。 secname用来命名这个段,contents用来确定代码中什么部分放在这个段中。 运行地址可称为重定位地址,也可称为链接地址。start: 这个段重定位地址,也称为运行地址。如果代码中有位置无关的指令,程序在运行时这个段必须放在这个地址上。 ALIGN(align): 虽然start指定了运行地址,但是仍可以使用BLOCK(align)来指定对齐的要求—这个对齐的地址才是 真正的运行地址。 (NOLOAD): 告诉加载器,在运行时不加载这个段。显然,这个选项只有在有操作系统的情况下才有意义。 AT(Idadr): 指定这个段在编评出来的映象文件中的地址---加载地址(loadaddress)。 如果不使用这个选项,则加载地址等于运行地址。通过这个选项,可以控制各段分别保存输出文件中 不同的位置,便于把文件保存到到单板上:A段放在A处,B段放在B处,运行前再把A、B段分別读出来组装 成一个完整的执行程序
注意:
1. ALIGN(align) 和 BLOCK(align)是一样的。BLOCK(align)是为了向前兼容。 2. ALIGN(align)用法: 1. .rodata ALIGN(4) : {*(.rodata)} 2. . = ALIGN(4); 3. 下边三种表示是一样的 .bss : { . = ALIGN(4); bss_start = .; *(.bss) *(.COMMON) bss_end = .; } **************************** . = ALIGN(4); bss_start = .; .bss : { *(.bss) *(.COMMON) } bss_end = .; *********************************** .bss ALIGN(4) : { bss_start = .; *(.bss) *(.COMMON) bss_end = .; }例1:
例2:
见新1期《 第013课_代码重定位_第002节_链接脚本的引入与简单测试_P》
objcopy
作用:拷贝一个目标文件的内容到另一个目标文件中,可以将一种格式的目标文件转换成另一种格式的目标文件
通常用法: arm-linux-ld -Ttext 0 start.o led.o uart.o init.o main.o -o sdram.elf arm-linux-objcopy -O binary -S sdram.elf sdram.bin
格式:objcopy [options] input-file [output-file]
选项:
选项
Desc
input-file / output-file
源文件/目标文件
-I bfdname
--input-target=bfdname
明确告诉Objcopy,源文件的格式是什么,bfdname是BFD库中描述的标准格式名。若不指明,则objcopy会自己分析源文件的格式,然后与BFD中的格式比较,来得知源文件格式。
例:elf32-little,elf32-big
-O bfdname
--output-target=bfdname
使用指定的格式来写输出文件(即目标文件),bfdname是BFD库中描述的标准格式名。
例:
-O binary //产生二进制文件
-O srec //产生s-record文件
-F bfdname
--target=bfdname
指定输入、输出文件的bfdname,目标文件格式
-j sectionname
--only-section=sectionname
只将由sectionname指定的section拷贝到输出文件
-R sectionname
--remove-section=sectionname
从输出文件中删掉所有名为sectionname的段。这个选项可以多次使用。
注意:不恰当地使用这个选项可能会导致输出文件不可用。
-S
--strip-all
去掉源文件的符号信息和relocation信息
-g
--strip-debug
去除掉调试符号信息和相关的段。即不从源文件中拷贝调试符号到输出文件(目的文件)中去。
-K symbolname
--keep-symbol=symbolname
保留由symbolname指定的符号信息
-N symbolname
--strip-symbol=symbolname
去除掉由symbolname指定的符号信息
-b byte
--byte=byte
每byteth byte中保留1 byte
-i interleave
--interleave=interleave
每隔interleave字节拷贝1 byte
--gap-fill val
在section的空隙中填充val
--set-start val
设定新文件的start address
--change-start incr
--adjust-start incr
调整start address
--change-address incr
--adjust-vma incr
调整所有sections的VMA(virtual memory address)和LMA(linear memory address)。
--change-section-address
section{=,+,-}val
--adjust-section-vma section
{=,+,-}val
调整指定section的VMA/LMA地址
--set-section-flags section=flag
指定指定section的flag,flag的取值可以alloc,contents, load, noload, readonly, code, data, rom, share, debug
--add-section sectionname=filename
添加一个section,该section的内容为filenmae的内容
--rename-section oldname=
newname[,flags]
更改section的名
-V
--version
objcopy的version number
-G symbolname
--keep-global-symbol=symbolname
-L symbolname
--localize-symbol=symbolname
-W symbolname
--weaken-symbol=symbolname
-w
--wildcard
-x
--discard-all
-X
--discard-locals
处理
作用:显示ELF文件,通常用来查看反汇编代码。
ELF文件有如下几种:
1. 可重定位的对象文件(Relocatable file) : .o文件 .a文件 .ko文件
2. 可执行的对象文件(Executable file) : .bin文件 可执行文件(如:gcc -o hello hello.c产生的hello)
3. 可被共享的对象文件(Shared object file): .so文件
objdump
示例:
arm-linux-ld -Ttext 0 start.o led.o uart.o init.o main.o -o sdram.elf arm-linux-objcopy -O binary -S sdram.elf sdram.bin 1.将elf格式文件转换为反汇编文件: arm-linux-objdump -D sdram.elf > sdram.dis 2.将bin格式文件转换为反汇编文件: arm-linux-objdump -D -b binary -m arm sdram.bin > sdram.dis-b bfdname (或--target=bfdname) 指定目标码格式。例如-b binary arm-linux-objdump -i 可以给出这里可以指定的目标码格式列表 -d (或--disassemble) 反汇编可执行段(executable session)-D (或--disassemble-all) 反汇编所有段.-m machine (或--architecture=machine) 指定反汇编目标文件时使用的架构。例如:-m arm 可以用-i选项列出这里能够指定的架构-EB (或-EL 或--endian={big|little} ) 指定字节序(大端或者小端)-i (或--info ) 显示对于 -b 或者 -m 选项可用的架构和目标格式列表。-f (或--file-headers ) 显示objfile中每个文件的整体头部摘要信息。-h (或--section-headers 或--headers ) 显示目标文件各个section的头部摘要信息addr2line
作用:把程序地址转换为文件名和行号。在命令行中给它一个地址和一个可执行文件名,它就会使用这个可执行文件的调试信息指出在给出的地址上是哪个文件以及行号。
ar
作用
建立、修改、提取归档文件(.a文件)。归档文件:包含多个文件内容, 其结构保证了可以恢复原始文件内容。
等价于gcc -shared
格式
ar [-] [abcfilNoPsSuvV] [membername] [count] archivefiles... //选项前可以有“-”也可以没有。
示例
生成.a文件:
gcc -c -o func.o func.cgcc -c -o func1.o func1.c
ar cr func.a func.o func1.o
使用.a文件:
gcc -c -o main.o main.c
gcc -o test main.o -lfunc 或者 gcc -o test main.o ./func.a
选项及其含义
选项
含义
r
在库中插入模块(替换)。当插入的模块名已经在库中存在,则替换同名的模块。如果若干模块中有一个模块在库中不存在,ar显示一个错误消息,并不替换其他同名模块。默认的情况下,新的成员增加在库的结尾处,可以使用其他任选项来改变增加的位置。
c
创建一个库。不管库是否存在,都将创建
s
写入一个目标文件索引到库中,或者更新一个存在的目标文件索引。甚至对于没有任何变化的库也作该动作。对一个库做ars等同于对该库做ranlib。
v
该选项用来显示执行操作选项的附加信息
V
显示ar的版本
d
从库中删除模块。按模块原来的文件名指定要删除的模块。如果使用了任选项v则列出被删除的每个模块
m
该操作是在一个库中移动成员。当库中如果有若干模块有相同的符号定义(如函数定义),则成员的位置顺序很重要。如果没有指定任选项,任何指定的成员将移到库的最后。也可以使用’a’,’b’,或’I’任选项移动到指定的位置。
p
显示库中指定的成员到标准输出。如果指定任选项v,则在输出成员的内容前,将显示成员的名字。如果没有指定成员的名字,所有库中的文件将显示出来。
q
q:快速追加。增加新模块到库的结尾处。并不检查是否需要替换。’a’,’b’,或’I’任选项对此操作没有影响,模块总是追加的库的结尾处。如果使用了任选项v则列出每个模块。这时,库的符号表没有更新,可以用’ars’或ranlib来更新库的符号表索引。
t
t:显示库的模块表清单。一般只显示模块名。
x
x:从库中提取一个成员。如果不指定要提取的模块,则提取库中所有的模块。
a
a:在库的一个已经存在的成员后面增加一个新的文件。如果使用任选项a,则应该为命令行中membername参数指定一个已经存在的成员名。
b
b:在库的一个已经存在的成员前面增加一个新的文件。如果使用任选项b,则应该为命令行中membername参数指定一个已经存在的成员名。
f
f:在库中截短指定的名字。缺省情况下,文件名的长度是不受限制的,可以使用此参数将文件名截短,以保证与其它系统的兼容。
i
i:在库的一个已经存在的成员前面增加一个新的文件。如果使用任选项i,则应该为命令行中membername参数指定一个已经存在的成员名(类似任选项b)。
l
l:暂未使用
N
N:与count参数一起使用,在库中有多个相同的文件名时指定提取或输出的个数。
o
o:提取成员时,保留成员的原始数据。如果不指定该任选项,则提取出的模块的时间将标为提取出的时间。
P
P:进行文件名匹配时使用全路径名。ar在创建库时不能使用全路径名(这样的库文件不符合POSIX标准),但是有些工具可以。
S
S:不创建目标文件索引,这在创建较大的库时能加快时间。
u
u:一般说来,命令arr…插入所有列出的文件到库中,如果你只想插入列出文件中那些比库中同名文件新的文件,就可以使用该任选项。该任选项只用于r操作选项。
nm
作用
显示关于指定 File 中符号的信息,文件可以是对象文件、可执行文件或对象文件库。默认以十进制显示数字值
格式
nm [ -A ] [ -C ] [ -X {32|64|32_64}] [ -f ] [ -h ] [ -l ] [ -p ] [ -r ] [ -T ] [ -v ] [ -B | -P ] [ -e | -g | -u ] [ -d | -o | -x | -t Format ] File ...
示例
nm hello
选项及其含义
选项
含义
-A、-o
或--print-file-name:
在找到的各个符号的名字前加上,而不是在此文件的所有符号前只出现文件名一次。
-a
列出所有符号
-d
用十进制显示符号的值和大小。这是缺省的。
-e
只显示静态的和外部的(全局)符号
-f
显示完整的输出,包括冗余的 .text、 .data 以及 .bss 符号,这些在通常都是被限制的。
-g
只显示外部的(全局)符号。
-h
限制输出头数据的显示。
-I
利用调试信息找出文件名以及符号的行号。对于一个已定义符号,将会找出这个符号定义的行号,对于未定义符号,显示为空
-n
根据符号的地址来排序,默认是按符号名称的字母顺序排序的
-o
用八进制而不是十进制数来显示符号的值和大小。
-P
-P 以标准可移植输出格式显示信息: 库/对象名 名称 类型 值 大小
该格式以十六进制符号表示法显示数字值,除非您用 -t、-d 或 -o 标志指定不同的格式。
-p
不排序。输出按符号表顺序打印。
-r
倒序排序
-T
把可能会溢出它的列的每个名字截短,使显示的名字的最后一个字符是星号(*)。
缺省情况下,nm 显示列出的符号的全名,并且一个比为其设置的列的宽度长的名称会引起名称后的每个列无法对齐。
-t format
显示指定格式下的数字值,其中 format 参数是以下符号表示法之一:
d 十进制符号表示法。这是 nm 命令的缺省格式。
o 八进制符号表示法。
x 十六进制符号表示法。
-u或
--undefined-only
只列出未定义符号,而"--defined-only"将只列出已定义符号
-v
按值而不是按字母表顺序排序输出。
-X mode
指定 nm 应该检查的对象文件的类型。 mode 必须是下列之一:
32
只处理 32 位对象文件
64
只处理 64 位对象文件
32_64
处理 32 位和 64 位对象文件
缺省是处理 32 位对象文件(忽略 64 位对象)。 mode 也可以 OBJECT_MODE 环境变量来设置。
例如,OBJECT_MODE=64 使 nm 处理任何 64 位对象并且忽略 32 位对象。 -X 标志覆盖 OBJECT_MODE 变量
-x
用十六进制而不是十进制数来显示符号的值和大小。
结果的含义
A
该符号的值是绝对的,在以后的链接过程中,不允许进行改变。
这样的符号值,常常出现在中断向量表中,例如用符号来表示各个中断向量函数在中断向量表中的位置。
B/b
该符号的值出现在非初始化数据段(bss)中。
例如,在一个文件中定义全局static int test。则该符号test的类型为B,位于bss section中。
其值表示该符号在bss段中的偏移。一般而言,bss段分配于RAM中
C
该符号为common。common symbol是未初始化数据段。
该符号没有包含于一个普通section中。只有在链接过程中才进行分配。符号的值表示该符号需要的字节数。
例如在一个c文件中,定义int test,并且该符号在别的地方会被引用,则该符号类型即为C。否则其类型为B。
补充:该符号所占的空间并不存在于执行文件中,而在初始化执行环境时分配此空间,但不会清零,可读写。
D/d
该符号位于初始话数据段中。一般来说,分配到data section中。
例如定义全局int baud_table[5] = {9600, 19200, 38400, 57600, 115200},则会分配于初始化数据段中。
补充:该符号所占用的空间存在于执行文件中,在初始化执行环境时分配,并复制数据到此空间,可读写。
G/g
该符号也位于初始化数据段中。主要用于small object提高访问small data object的一种方式。
I
该符号是对另一个符号的间接引用。
N
该符号是一个debugging符号。
R/r
该符号位于只读数据区。
例如定义全局const int test[] = {123, 123};则test就是一个只读数据区的符号。
注意在cygwin下如果使用gcc直接编译成MZ格式时,源文件中的test对应_test,并且其符号类型为D,即初始化数据段中。
但是如果使用m6812-elf-gcc这样的交叉编译工具,源文件中的test对应目标文件的test,即没有添加下划线,并且其符号
类型为R。一般而言,位于rodata section。
值得注意的是,如果在一个函数中定义const char *test = “abc”, const char test_int = 3。
使用nm都不会得到符号信息,但是字符串“abc”分配于只读存储器中,test在rodata section中,大小为4。
补充:此符号所占用的空间存在于执行文件中,是否使用副本空间并不确定。只读。
S/s
符号位于非初始化数据区,用于small object。
T
该符号位于代码区text section。例如定义了一个函数function,则function就是这种符号
U
该符号在当前文件中是未定义的,即该符号的定义在别的文件中。
例如,当前文件调用另一个文件中定义的函数,在这个被调用的函数在当前就是未定义的;但是在定义它的文件中类型是T。但是对于全局变量来说,在定义它的文件中,其符号类型为C,在使用它的文件中,其类型为U。
u
唯一的(unique)全局符号。
这是GNU对标准ELF符号集连接的扩展。对于这样的符号,动态链接器将保证在整个处理过程中,
只有一个拥有此名字和类型的符号被使用。
V/v
该符号是一个weak object。
W/w
The symbol is a weak symbol that has not been specifically tagged as a weak object symbol.
-
该符号是a.out格式文件中的stabs symbol。
?
该符号类型没有定义
strings
作用
打印查找可打印的字符串。字符串是4个或更多可打印字符的任意序列,以换行符或空字符结束。 strings命令对识别随机对象文件很有用。
格式
strings [ -a ] [ - ] [ -o ] [ -t Format ] [ -n Number ] [ -Number ] [ file ... ]
示例
strings hello
选项及其含义
选项
含义
-a或--all
在找到的各个符号的名字前加上,而不是在此文件的所有符号前只出现文件名一次。
-f或
–print-file-name
在显示字符串前先显示文件名
-n或
–bytes=[number]
找到并且输出所有NUL终止符序列
-
设置显示的最少的字符数,默认是4个字符
-t 或
--radix={o,d,x}
输出字符的位置,基于八进制,十进制或者十六进制
-T或
--target=
指定二进制文件格式
-e或
--encoding={s,S,b,l,B,L}
选择字符大小和排列顺序:s = 7-bit, S = 8-bit, {b,l} = 16-bit, {B,L} = 32-bit
@
读取选中项
其他工具
as 主要用来编译GNU C编译器gcc输出的汇编文件,产生的目标文件由连接器ld连接。
c++flit 连接器使用它来过滤 C++ 和 Java 符号,防止重载函数冲突。 c++ 将c++代码编译成一个可执行程序 cpp 将cpp代码编译成一个可执行程序 g++ linux下将c++代码编译成一个可执行程序 gcc 将c代码编译成一个可执行程序 gcov 测试代码覆盖率,分析代码性能 gdb 调试代码 gprof 显示程序调用段的各种数据。 ld 连接器,它把一些目标和归档文件结合在一起,重定位数据,并连接符号引用。通常, 建立一个新编译程序的最后一步就是调用ld。 objcopy 把一种目标文件中的内容复制到另一种类型的目标文件中。 objdump 显示一个或者更多目标文件的信息。使用选项来控制其显示的信息 ranlib 产生归档文件索引,并将其保存到这个归档文件中。在索引中列出了归档文件各成员所定义的可重分配目标文件。 readelf 显示elf格式可执行文件的信息。 size 列出目标文件每一段的大小以及总体的大小。默认情况下,对于每个目标文件或者一个 归 档文件中的每个模块只产生一行输出。 strings 打印某个文件的可打印字符串,这些字符串最少4个字符长,也可以使用选项-n设置字 符串的最小长度。默认情况下,它只打印目标文件初始化和可加载段中的可打印字符;对 于其他类型的文件它打印整个文件的可打印字符。这个程序对于了解非文本文件的内容很 有帮助。 strip 丢弃目标文件中的全部或者特定符号。
发表评论
最新留言
关于作者
