测试在 32 位 Linux x86 上进行。使用gcc
4.6.3 和 GNU ld
2.22。
所以我试图在链接期间获取“链接器解析了多少符号”的信息?以及如何列出所有已解析符号的信息?比如说,符号名称,内存地址。
我想我应该操纵链接器来这样做,但我不知道该怎么做。我有一些使用链接脚本为链接器提供的经验,但我没有在链接脚本中找到与已解析符号信息相关的任何内容。
谁能给我一些帮助?我真的很感激!谢谢!
测试在 32 位 Linux x86 上进行。使用gcc
4.6.3 和 GNU ld
2.22。
所以我试图在链接期间获取“链接器解析了多少符号”的信息?以及如何列出所有已解析符号的信息?比如说,符号名称,内存地址。
我想我应该操纵链接器来这样做,但我不知道该怎么做。我有一些使用链接脚本为链接器提供的经验,但我没有在链接脚本中找到与已解析符号信息相关的任何内容。
谁能给我一些帮助?我真的很感激!谢谢!
大约在链接时解析的符号,包括符号名和内存地址信息,可以通过获取通过执行ld
与-M
选项加要链接的目标文件的名称:
$ ld -M <OBJECT FILE>
这将导致链接映射被打印到 STDOUT。当然,这个输出也可以重定向到一个文件:
$ ld -M <OBJECT FILE> > <OUTPUT FILE>
ld(1)-M
的手册页以及 ld的sourceware.org 文档中的第 2.1 节“命令行选项”中给出了该选项的以下描述:
-M
--打印地图
将链接映射打印到标准输出。链接图提供有关链接的信息,包括以下内容:
目标文件被映射到内存的地方。
如何分配公共符号。
链接中包含的所有存档成员,并提及导致存档成员被引入的符号。
分配给符号的值。
注意 - 其值由涉及对同一符号的先前值的引用的表达式计算的符号可能不会在链接图中显示正确的结果。这是因为链接器丢弃中间结果,只保留表达式的最终值。在这种情况下,链接器将显示用方括号括起来的最终值。因此,例如一个包含以下内容的链接描述文件:
foo = 1 foo = foo * 4 foo = foo + 8
如果使用 -M 选项,将在链接映射中产生以下输出:
0x00000001 foo = 0x1 [0x0000000c] foo = (foo * 0x4) [0x0000000c] foo = (foo + 0x8)
以下是 i386 ELF32 目标文件的示例链接映射片段:
<<= snip =>>
.plt.got
*(.plt.got)
.text 0x0000000008048074 0xa
*(.text.unlikely .text.*_unlikely .text.unlikely.*)
*(.text.exit .text.exit.*)
*(.text.startup .text.startup.*)
*(.text.hot .text.hot.*)
*(.text .stub .text.* .gnu.linkonce.t.*)
.text 0x0000000008048074 0xa test.o
0x0000000008048074 main
*(.gnu.warning)
.fini
*(SORT(.fini))
[!provide] PROVIDE (__etext, .)
[!provide] PROVIDE (_etext, .)
[!provide] PROVIDE (etext, .)
.rodata
*(.rodata .rodata.* .gnu.linkonce.r.*)
.rodata1
*(.rodata1)
.eh_frame_hdr
*(.eh_frame_hdr)
*(.eh_frame_entry .eh_frame_entry.*)
.eh_frame 0x0000000008048080 0x38
*(.eh_frame)
.eh_frame 0x0000000008048080 0x38 test.o
*(.eh_frame.*)
<<= snip =>>
如果这不足以满足您的目的并且想要使用自定义脚本操作链接器,sourceware.org 上的“ 3:链接器脚本”部分可能会有所帮助。链接编辑器命令语言的一些文档也可以在AT&T UNIX™ PC Model 7300 Unix System V Programmers Guide 的第 524 页上找到。
更多信息也可以在发现ld.texinfo文件,该文件是金源ld
。还有一个名为The GNU Linker的文档,其中讨论了 40 页左右的链接器脚本。