Search code examples
c++gccposition-independent-code

objdump gives the same output for object files generated with and without -fPIC


I have two files, a.h and a.cpp:

// a.h
extern "C" void a();

// a.cpp
#include "a.h"
#include <stdio.h>

void a()
{
    printf("a\n");
}

I compiled this both with and without -fPIC, and then objdumped both. Weirdly, I got the same output for both files. For a(), I get this in both cases:

callq 15 <a+0x15>

I also tried to compile object files with -no-pie, still no luck.


Solution

  • Compile your code (or anything) in verbose mode (-v), inspect the output, and you will find:

    Configured with:  ... --enable-default-pie ...
    

    which, since GCC 6, means the toolchain is built to compile PIC code and link PIE executables by default.

    To insist on a non-PIC compilation, run e.g.

    g++ -Wall -c -fno-PIC -o anopic.o a.cpp
    

    And to insist on a PIC compilation, run e.g.

    g++ -Wall -c -fPIC -o apic.o a.cpp
    

    Then run:

    $ objdump -d anopic.o 
    
    anopic.o:     file format elf64-x86-64
    
    
    Disassembly of section .text:
    
    0000000000000000 <a>:
       0:   55                      push   %rbp
       1:   48 89 e5                mov    %rsp,%rbp
       4:   bf 00 00 00 00          mov    $0x0,%edi
       9:   e8 00 00 00 00          callq  e <a+0xe>
       e:   90                      nop
       f:   5d                      pop    %rbp
      10:   c3                      retq     
    

    and:

    $ objdump -d apic.o 
    
    apic.o:     file format elf64-x86-64
    
    
    Disassembly of section .text:
    
    0000000000000000 <a>:
       0:   55                      push   %rbp
       1:   48 89 e5                mov    %rsp,%rbp
       4:   48 8d 3d 00 00 00 00    lea    0x0(%rip),%rdi        # b <a+0xb>
       b:   e8 00 00 00 00          callq  10 <a+0x10>
      10:   90                      nop
      11:   5d                      pop    %rbp
      12:   c3                      retq
    

    and you will see the difference.

    You can interleave the relocations with the assembly by:

    $ objdump --reloc -d anopic.o 
    
    anopic.o:     file format elf64-x86-64
    
    
    Disassembly of section .text:
    
    0000000000000000 <a>:
       0:   55                      push   %rbp
       1:   48 89 e5                mov    %rsp,%rbp
       4:   bf 00 00 00 00          mov    $0x0,%edi
                5: R_X86_64_32  .rodata
       9:   e8 00 00 00 00          callq  e <a+0xe>
                a: R_X86_64_PC32    puts-0x4
       e:   90                      nop
       f:   5d                      pop    %rbp
      10:   c3                      retq
    

    and:

    $ objdump --reloc -d apic.o 
    
    apic.o:     file format elf64-x86-64
    
    
    Disassembly of section .text:
    
    0000000000000000 <a>:
       0:   55                      push   %rbp
       1:   48 89 e5                mov    %rsp,%rbp
       4:   48 8d 3d 00 00 00 00    lea    0x0(%rip),%rdi        # b <a+0xb>
                7: R_X86_64_PC32    .rodata-0x4
       b:   e8 00 00 00 00          callq  10 <a+0x10>
                c: R_X86_64_PLT32   puts-0x4
      10:   90                      nop
      11:   5d                      pop    %rbp
      12:   c3                      retq