Search code examples
clinkerobjdump

Are the addresses displayed by objdump final addresses or just offsets?


Assume this C code, compiled with gcc file.c:

int main(){
 return 0;
}

Generated output with objdump:

0000000000000660 <main>:
660:    55                      push   %rbp
661:    48 89 e5                mov    %rsp,%rbp
664:    b8 00 00 00 00          mov    $0x0,%eax
669:    5d                      pop    %rbp
66a:    c3                      retq   
66b:    0f 1f 44 00 00          nopl   0x0(%rax,%rax,1)

Notice the first address is 660.

Here is the same output from GDB:

0x555555554660 <main>                   push   %rbp
0x555555554661 <main+1>                 mov    %rsp,%rbp
0x555555554664 <main+4>                 mov    $0x0,%eax
0x555555554669 <main+9>                 pop    %rbp
0x55555555466a <main+10>                retq

Notice the added 5s to left of each address.

Here are my questions:

1- What are the 5s on the left? why doesn't objdump have them?

2- Are these just offsets? or final addresses hard coded in the binary which will be loaded in virtual memory.

3- If these are offsets than what is the difference between a regular executable and PIE? I thought only PIE code is position independent and has random addresses assigned to it during load time, I didn't compile with -fpie option. I have also used -fno-pie and it made no difference.


Solution

  • 1- What are the 5s on the left? why doesn't objdump have them?

    555…55516 is one-third of 1000…00016. You are seeing multiple fives just because somebody divided some particular region of memory into three pieces. objdump does not have them because it is just showing offsets.

    2- Are these just offsets? or final addresses hard coded in the binary which will be loaded in virtual memory.

    They are offsets relative to the start of the section of the program they are in.

    3- If these are offsets than what is the difference between a regular executable and PIE? I thought only PIE code is position independent and has random addresses assigned to it during load time, I didn't compile with -fpie option. I have also used -fno-pie and it made no difference.

    A position-independent executable calculates its addresses during program execution. It uses a base register or other information given to it to locate things, or it uses addresses relative to the program counter, or other forms of addressing that are independent of the program location.

    In contrast, a program that is not position independent may use absolute forms of addressing. However, the absolute addresses are not necessarily built into the object module. The addresses in the object module may still be offsets relative to a program section or other reference point. When the program is loaded, the loader chooses where it will put the program sections, and it adjusts all the addresses that are built into instructions, changing them from offsets to absolute addresses. The object module and the final executable file contain data structures that describe all the locations where these “fix-ups” are needed.

    Position-independent code can be used at two different virtual memory addresses in two difference processes at the same time. Because it constructs all its addresses using relative forms of addressing, the location of the code is irrelevant. Code that uses addresses fixed-up by the loader is tied to specific addresses; once the loader is done, the code has specific addresses embedded in its instructions, so it cannot be moved to other locations.