我的理解是:
(1)在编译阶段,gcc -c将使每个外部函数调用都有一个名称作为占位符,例如调用strlen',' call write'。
(2)在链接阶段,gcc知道' strlen'的真实地址。并且'写'函数,所以它用实际函数地址(十六进制数)替换那些函数名。
但我的实验显示了相反的结果,就像这样。 首先,我有2个.c文件,其中一个有' main'功能,一个与' a'功能,
$ cat m.c
void a(char*);
int main(int argc,char*argv[])
{
char s[]="hello\n";
a(s);
return 0;
}
$ cat a.c
#include<unistd.h>
#include<string.h>
void a(char*s)
{
write(1,s,strlen(s));
}
我使用gcc -c编译它们,看看它们的拆卸:
$ objdump -d a.o
Disassembly of section .text:
0000000000000000 <a>:
0: 55 push %rbp
1: 48 89 e5 mov %rsp,%rbp
4: 48 83 ec 10 sub $0x10,%rsp
8: 48 89 7d f8 mov %rdi,-0x8(%rbp)
c: 48 8b 45 f8 mov -0x8(%rbp),%rax
10: 48 89 c7 mov %rax,%rdi
13: e8 00 00 00 00 callq 18 <a+0x18>
18: 48 89 c2 mov %rax,%rdx
1b: 48 8b 45 f8 mov -0x8(%rbp),%rax
1f: 48 89 c6 mov %rax,%rsi
22: bf 01 00 00 00 mov $0x1,%edi
27: e8 00 00 00 00 callq 2c <a+0x2c>
2c: 90 nop
2d: c9 leaveq
2e: c3 retq
我们可以看到,在a.o文件中,2个电话没有相应的功能名称,但是像#callq 18&#39;和&#39; callq 2c&#39;。然后我
$ gcc m.o a.o -o m
$ objdump -d m
现在我可以看到反汇编:
000000000040062c <a>:
40062c: 55 push %rbp
40062d: 48 89 e5 mov %rsp,%rbp
400630: 48 83 ec 10 sub $0x10,%rsp
400634: 48 89 7d f8 mov %rdi,-0x8(%rbp)
400638: 48 8b 45 f8 mov -0x8(%rbp),%rax
40063c: 48 89 c7 mov %rax,%rdi
40063f: e8 5c fe ff ff callq 4004a0 <strlen@plt>
400644: 48 89 c2 mov %rax,%rdx
400647: 48 8b 45 f8 mov -0x8(%rbp),%rax
40064b: 48 89 c6 mov %rax,%rsi
40064e: bf 01 00 00 00 mov $0x1,%edi
400653: e8 38 fe ff ff callq 400490 <write@plt>
400658: 90 nop
400659: c9 leaveq
40065a: c3 retq
40065b: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1)
这次是功能名称。
我的理解在哪里出错了?
为什么在编译阶段,只有地址但在.o文件中没有名字,而在链接后,名字出现但不是最终地址?