为什么编译阶段没有看到函数名称,但链接阶段看到名称?

时间:2016-10-04 15:36:41

标签: linux gcc assembly x86 objdump

我的理解是:

(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文件中没有名字,而在链接后,名字出现但不是最终地址?

0 个答案:

没有答案