Search code examples
linuxassemblyx86-64disassemblyobject-files

What are the meanings of callq command parameters?


I'm aware what the callq instruction does; it is described in this answer. The instruction should have one parameter, which should be the address of the function called.

However, when disassembling an object file I see the following line showing a callq instruction with two values instead of one parameter:

  1e:   e8 00 00 00 00          callq  23 <main+0x19>

I assume that 23 is the return address and <main+0x19> is the address of the function to be called. However, the function which is called is not located at address main+0x19.

What is the meaning of the two values 23 and main+0x19 shown in the disassembly of the callq instruction?


Original C code:

#include <stdio.h>

void fun(int a)
{
}

int main()
{
    int a = 1234;
    fun(a);
}

objdump -D main.o main.asm Disassambly code:

0000000000000000 <fun>:
   0:   55                      push   %rbp
   1:   48 89 e5                mov    %rsp,%rbp
   4:   89 7d fc                mov    %edi,-0x4(%rbp)
   7:   90                      nop
   8:   5d                      pop    %rbp
   9:   c3                      retq   

000000000000000a <main>:
   a:   55                      push   %rbp
   b:   48 89 e5                mov    %rsp,%rbp
   e:   48 83 ec 10             sub    $0x10,%rsp
  12:   c7 45 fc 03 00 00 00    movl   $0x3,-0x4(%rbp)
  19:   8b 45 fc                mov    -0x4(%rbp),%eax
  1c:   89 c7                   mov    %eax,%edi
  1e:   e8 00 00 00 00          callq  23 <main+0x19>
  23:   b8 00 00 00 00          mov    $0x0,%eax
  28:   c9                      leaveq 
  29:   c3                      retq   


Solution

  • The callq instruction has only one operand, not two as implied in the question. The disassembler displays it in two forms, as an address and as a symbol + offset.

    You are looking at disassembly of an unlinked object file. Since the file being disassembled isn't linked, the destination address shown isn't the address of fun. The assembler puts 0 in the operand field of the instruction and creates a relocation record for the linker to fill in the offset to the final address of the destination.

    The operand of the call instruction is an offset, relative to the address of the next instruction after the call. So a value of 0 in the operand field causes the disassembler to display the address of the next instruction as the destination of the call. In the disassembly shown, that is address 23.

    If you make fun a static function, the assembler may fill in the true offset of the function, since it won't require relocation, and you will see it in the disassembly. (This may depend on the exact tools and options you are using.)

    If you disassemble a linked executable, the disassembler will show the true destination address of the call.

    You can also use objdump -drwC (optionally with -Mintel) to show relocations as comments on instructions when disassembling a file like a .o that has some placeholders with relocations.