Undefined symbols for architecture x86_64:

这里是说链接器找不到符号的定义。代码改改就好,但实际上整个编译链接的过程可以了解一下。

1 void test();
2 
3 int main(int argc, char **argv) {
4     test();
5     return 0;
6 }

 编译:

gcc -c -g a.c

得到a.o目标文件,看看编译后的代码段:

objdump -S a.o
 1 a.o:    file format Mach-O 64-bit x86-64
 2 
 3 Disassembly of section __TEXT,__text:
 4 _main:
 5 ; int main(int argc, char **argv) {
 6        0:    55     pushq    %rbp
 7        1:    48 89 e5     movq    %rsp, %rbp
 8        4:    48 83 ec 10     subq    $16, %rsp
 9        8:    c7 45 fc 00 00 00 00     movl    $0, -4(%rbp)
10        f:    89 7d f8     movl    %edi, -8(%rbp)
11       12:    48 89 75 f0     movq    %rsi, -16(%rbp)
12 ; test();
13       16:    b0 00     movb    $0, %al
14       18:    e8 00 00 00 00     callq    0 <_main+0x1d>
15       1d:    31 c0     xorl    %eax, %eax
16 ; return 0;
17       1f:    48 83 c4 10     addq    $16, %rsp
18       23:    5d     popq    %rbp
19       24:    c3     retq

可以看到对应test的调用指令为:

e8 00 00 00 00

由于a.c里没有对test进行定义,所以编译器只能暂且将test的地址用00 00 00 00来代替,同时将这个需要重定位的地方记录在a.o的重定位表里:

➜  ld_test objdump -r a.o

a.o:    file format Mach-O 64-bit x86-64

RELOCATION RECORDS FOR [__text]:
0000000000000019 X86_64_RELOC_BRANCH _test

假如说最终链接的时候还是找不到该符号的定义,自然就报最开始那个错误提示了。而如果在另外的模块里有定义这个test,那链接器自然就能以正确的地址替换那个00 00 00 00了。

对了,这里只说静态链接,动态链接会更复杂一些。

 posted on 2019-04-14 18:58  万事屋madao  阅读(389)  评论(0编辑  收藏  举报