接下来的系列,来自GNU ld manual的学习,侧重于使用。理论方面的学习,在Linkers & Loaders分类里面。
ld将目标文件和静态库文件结合在一起,重定向他们的数据,合并符号引用。编译程序的最后一步通常是运行ld。
ld接受AT&T链接编辑命令语言语法(AT&T Link Editor Command Language syntax)格式的链接命令语言(Linker Command Language)文件,来显式地控制整个链接过程。
ld使用BFD库操作目标文件,这允许ld支持链接不同格式的目标文件。
许多链接器在发生错误后立即停止执行,而GNU ld尽可能继续执行,便于定位更多的错误。
链接器支持一大堆命令行选项,但是在任何特定的环境,都只有少量的选项被使用。例如,最基本的链接命令:
ld -o a.out /lib/crt0.o hello.o -lc
上述命令告诉ld,链接crt0.o,hello.o和libc.a或者libc.so产生一个可执行文件a.out。
一些选项可以出现在任何位置。然而涉及文件的命令,如-l或者-T,文件会在命令出现的位置被读入。保持和目标文件及其它文件选项的相对位置。后面可以看到,这些顺序是重要的。
非文件选项重复,且其参数与之前的不同。或者没有影响,或者覆盖之前(命令行左侧)的参数。出现多次有意义的参数在后面会提到。
非选项参数是要被链接的目标文件或者静态库文件,他们可以出现任何位置。
链接脚本可以用非选项参数的方式设置,链接器会先将其当成目标文件格式,当不能识别目标文件的格式时,他将其当成一个链接脚本。这种方式的链接脚本,增大主链接器脚本,而不是替换。主链接器脚本是缺省链接脚本,或者-T指定的链接脚本。
单字符选项,前面有且仅有一个破折号(dash),参数或者选项连在一起,或者作为一个独立的参数,立即跟在选项后面。如"-lc" 或者"-l c"。
多字符选项,选项名前有一个或两个破折号(dash),如"-trace-symbol"与"--trace-symbol"是一样的。唯一的例外是,o开头的多字符选项必须使用双破折号,如"--omagic",这是为了避免和-o冲突。
多字符选项的参数同样有两种形式,或者使用=、或者作为一个独立的参数立即跟在选项后面,如"--trace-symbol=foo"与"--trace-symbol foo"是一样的。
如果链接器不是直接被调用,而是通过一个编译器驱动(如gcc),那么所有的链接器选项应当使用一个前缀"-Wl,",或者其它编译器驱动支持的形式,如
gcc -Wl,--start-group foo.o bar.o -Wl,--end-group
这很重要,因为上层驱动可能默默地丢掉链接选项。
如果选项带参数,空格会导致上层驱动误解,这时可以使用不带空格形式,单字符选项连在一起,多字符选项使用=。如
gcc foo.o bar.o -Wl,-eENTRY -Wl,-Map=a.map
或者将整个链接选项用引号(我认为可以,手册没提到这种用法),如:
gcc foo.o bar.o "-Wl,-e ENTRY" "-Wl,-Map a.map"