2

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?

Community
  • 1
  • 1
JenyaKh
  • 2,040
  • 17
  • 25
  • In x86 short jumps (<±127 bytes) are always position-relative - I mean, every jump in 32 bit mode *can* be written using an explicit full address, but then it's 5 bytes instead of 2, no assembler in its sane mind would emit such an instruction. – Matteo Italia Dec 24 '16 at 09:55
  • @MatteoItalia, thank you for your comment! Sorry, I've voted it up but incidentally undo my vote on my smartphone and can't upvote it again as SO forbids it. :((( – JenyaKh Dec 24 '16 at 15:07
  • 1
    don't worry, it happens all the time =) – Matteo Italia Dec 24 '16 at 18:20

2 Answers2

2

-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.

Jean-François Fabre
  • 137,073
  • 23
  • 153
  • 219
  • 1
    Thank you for the answer. Now I understand that it's the position independent code: "74 09" means to jump 09 bytes further and "eb 07" to jump 07 bytes further, right? But now I've tried to compile as g++ -fno-pic -c -o testlib.o testlib.cpp and still got the same objdump. Why does -fno-pic not work? – JenyaKh Dec 24 '16 at 09:31
  • right about the asm. have you tried `-fno-PIC` ? and maybe it doesn't apply to jumps. – Jean-François Fabre Dec 24 '16 at 09:46
  • @Jean-FrançoisFabre "-fPIC is on by default in newer gcc versions" - any prooflink? – yugr Dec 24 '16 at 09:48
  • @Jean-FrançoisFabre, yes, I've tried -fno-PIC too. It also produces the same objdump, unfortunately. – JenyaKh Dec 24 '16 at 14:58
  • @yugr: fait enough. at least for x86 it has no effect: http://stackoverflow.com/questions/20637310/does-one-still-need-to-use-fpic-when-compiling-with-gcc. Probably because it's easy to write PIC code on a x86 (as opposed to 68k for instance, where you cannot write to memory PC-relative, you have to use an address register) – Jean-François Fabre Dec 24 '16 at 16:34
  • @Jean-FrançoisFabre "it's easy to write PIC code on a x86" - I assume you meant x86_64 because on 32-bit x86 PIC comes with significant penalty... – yugr Dec 24 '16 at 17:55
  • err yes, you're right. But maybe it's not the only argument. compiler developpers may have set this by default to avoid trouble when compiling .so files. – Jean-François Fabre Dec 24 '16 at 17:57
2

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.

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
  • Thank you very much for your answer. It's very sensible. However, in the other answer it's proposed to use -fno-PIC compiler option in order to get position dependent code. I've tried it but it didn't help. Could you comment anything on this point? I just really want to have a look at position dependent code. – JenyaKh Dec 24 '16 at 15:01
  • 1
    @JenyaKh: As I said above, it is not possible (for your example). You can request from GCC only one of two things: "I want position-independent code" (`-fpic`, `-fPIC`, position-independence guaranteed), or "I don't care" (`-fno-pic`, `-fno-PIC`, position-independence not guaranteed). No matter what options you use, you only switch between these two modes. There's no option to make GCC to somehow deliberately force its generated code to be "position-dependent". Such option would make no sense at all. If you want to see a difference - you need a different example. – AnT stands with Russia Dec 24 '16 at 18:47