g++ -fPIC not producing position independent code

1.6k views Asked by At

I've read the topic GCC -fPIC option

So I've created my testlib.cpp.

int foo(int num)
{   
    int result;

    if (num != 0)
    {
        result = 1;
    }
    else
    {
        result = 2;
    }

    return result;
}

When I compile as g++ -c -o testlib.o testlib.cpp and as g++ -fPIC -c -o testlib.o testlib.cpp the corresponding objdumps of testlib.o are identical:

objdump -d testlib.o -M intel

testlib.o:     file format elf32-i386

Disassembly of section .text:

00000000 <_Z3fooi>:
   0:   55                      push   ebp
   1:   89 e5                   mov    ebp,esp
   3:   83 ec 10                sub    esp,0x10
   6:   83 7d 08 00             cmp    DWORD PTR [ebp+0x8],0x0
   a:   74 09                   je     15 <_Z3fooi+0x15>
   c:   c7 45 fc 01 00 00 00    mov    DWORD PTR [ebp-0x4],0x1
  13:   eb 07                   jmp    1c <_Z3fooi+0x1c>
  15:   c7 45 fc 02 00 00 00    mov    DWORD PTR [ebp-0x4],0x2
  1c:   8b 45 fc                mov    eax,DWORD PTR [ebp-0x4]
  1f:   c9                      leave  
  20:   c3                      ret   

And I expected the addresses of arguments of jump and je commands to be position independent when compiling with -fPIC. So the two objdumps should be different. What do I understand wrong?

2

There are 2 answers

7
Jean-François Fabre On

-fPIC is on by default in newer gcc versions. The code is position independent even without the option:

eb 07                   jmp    1c <_Z3fooi+0x1c>

this is position independent, looking at the 2-byte opcode, even if the disassembly prints the symbol and its offset for clarity.

Note that it's very likely that the compiler would produce position-independent code for that kind of short jumps whatever the options.

So this flag is not very useful now. BUT you can disable PIC with -fno-PIC switch.

2
AnT stands with Russia On

GCC compiler does not have capability to deliberately generate position-dependent code. Such capability would make no practical sense whatsoever.

What GCC can do is actually generate either position-independent code (with -fPIC option), or "whatever" code (without -fPIC option). When you use "whatever" mode, the compiler simply ignores the matters of position-dependency and bases its decisions about code generation on other considerations. This means that even when you are not requesting -fPIC, you might still easily end up with position-independent code purely "by accident": because it just so happened that position-independent code worked best for other reasons (is more compact, runs faster etc.)

If you want to observe a difference, you need a more representative example. In your example all jumps are near jumps. They are naturally implemented through relative (offset-based) jump instructions. Any sensible compiler will use such relative jumps in such situations. And the side-effect of that is that you end up with position-independent code even if you did not explicitly request it. Position-independence comes "for free" in this case.

If you want to observe a difference, you need an example where position-independence would not come "for free". You need something that would involve a clear trade-off between position-independence and other important factors, like efficiency and/or size. If you come up with such an example, you will see the difference that -fPIC makes.