我想知道链接器如何解析以下汇编代码中的printf符号。
#include<stdio.h>
void main()
{
printf("Hello ");
}
.file "test.c"
.def ___main; .scl 2; .type 32; .endef
.section .rdata,"dr"
LC0:
.ascii "Hello \0"
.text
.globl _main
.def _main; .scl 2; .type 32; .endef
_main:
pushl %ebp
movl %esp, %ebp
subl $8, %esp
andl $-16, %esp
movl $0, %eax
addl $15, %eax
addl $15, %eax
shrl $4, %eax
sall $4, %eax
movl %eax, -4(%ebp)
movl -4(%ebp), %eax
call __alloca
call ___main
movl $LC0, (%esp)
**call _printf**
leave
ret
.def **_printf**; .scl 3; .type 32; .endef
低级别解释将受到高度赞赏。
提前致谢。
答案 0 :(得分:17)
假设ELF文件格式,汇编器将在目标文件中生成未定义的符号引用。这看起来像这样:
Symbol table '.symtab' contains 11 entries: Num: Value Size Type Bind Vis Ndx Name 0: 00000000 0 NOTYPE LOCAL DEFAULT UND 1: 00000000 0 FILE LOCAL DEFAULT ABS test.c 2: 00000000 0 SECTION LOCAL DEFAULT 1 3: 00000000 0 SECTION LOCAL DEFAULT 3 4: 00000000 0 SECTION LOCAL DEFAULT 4 5: 00000000 0 SECTION LOCAL DEFAULT 5 6: 00000000 0 SECTION LOCAL DEFAULT 6 7: 00000000 0 SECTION LOCAL DEFAULT 7 8: 00000000 52 FUNC GLOBAL DEFAULT 1 main 9: 00000000 0 NOTYPE GLOBAL DEFAULT UND printf 10: 00000000 0 NOTYPE GLOBAL DEFAULT UND exit
它还将创建一个重定位条目,指向代码映像的一部分,需要由链接器使用正确的地址进行更新。它看起来像这样:
tool2 0>readelf -r test.o Relocation section '.rel.text' at offset 0x358 contains 3 entries: Offset Info Type Sym.Value Sym. Name 0000001f 00000501 R_386_32 00000000 .rodata 00000024 00000902 R_386_PC32 00000000 printf 00000030 00000a02 R_386_PC32 00000000 exit
然后链接器的工作是遍历重定位表,用最终的符号地址修复代码映像。
有一本很好的书,但我现在找不到详细信息(而且已经绝版了)。但是,这似乎有用:http://www.linuxjournal.com/article/6463
戴夫。
答案 1 :(得分:1)
关于链接过程的好书,请参阅Linkers&amp; John Levine的装载机。您可以使用HTML格式here获取稿件章节。
答案 2 :(得分:1)
Ulrich Drepper撰写的How To Write Shared Libraries文章可能对您有所帮助。 Ulritch Linux glibc维护者,他是ELF的权威。
尽管本文是关于如何编写共享库以及如何导出或不导出符号,但它解释了如何在具有ELF格式的exe文件中动态解析这些符号。
我想它可能会回答你的问题。
答案 3 :(得分:1)