0

My understanding was:

(1) In compilation phase ,gcc -c will make every external function call to have a name as place holder,like 'call strlen', 'call write'.

(2) In linking phase, gcc know the real address of 'strlen' and 'write' functions, so it replaces those function names with real function address(hex numbers).

But my experiment show the opposite result, like this. First, I've got 2 .c files, one with 'main' function, one with 'a' function,

$ 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));
}

I used gcc -c to compile them, and see their dis-assembly:

$ 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   

We could see that in a.o file the 2 calls don't have corresponding function names, but like 'callq 18' and 'callq 2c'. Then I

$ gcc m.o a.o -o m
$ objdump -d m

Now I can see the disassembly:

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)

This time, with function names.

  • Where did I get wrong in my understanding?

  • Why in compilation phase, there's only address but no name in .o file, while after linking, names appeared but not the final address?

Michael Petch
  • 46,082
  • 8
  • 107
  • 198
Troskyvs
  • 7,537
  • 7
  • 47
  • 115
  • @orlp : This isn't a duplicate of what you are linking this question to. This isn't asking about extra/useless `callq` instructions. This question is asking why symbol names don't appear in the object file but they appear in the final linked executable. – Michael Petch Oct 05 '16 at 01:14
  • @MichaelPetch The titles aren't the same, but the answer is the same to both. – orlp Oct 05 '16 at 06:37

0 Answers0