0

When I compile a piece of code without fPIC and then write the following command. I get this error. How to resolve this?

└──╼ $gcc -shared -o libmlpic.so ml_mainpic.o
/usr/bin/ld: ml_mainpic.o: warning: relocation against `myglob' in read-only section `.text'
/usr/bin/ld: ml_mainpic.o: relocation R_X86_64_PC32 against symbol `myglob' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: final link failed: bad value
collect2: error: ld returned 1 exit status
cup
  • 7,589
  • 4
  • 19
  • 42
NobinPegasus
  • 545
  • 2
  • 16
  • I'm no expert but you attempt to make a shared library without making the code position-independent. This is simply wrong/impossible so ld simply mentions that to you with an error. – user123 Feb 28 '22 at 05:40
  • If I understand well, by default, gcc compiles with -fpie on so your code is "position-independent" but with a start address. -fPIC/-fpic makes your code suitable for a shared library. – user123 Feb 28 '22 at 05:45
  • See: https://stackoverflow.com/questions/16023637/difference-between-pic-vs-pie – user123 Feb 28 '22 at 05:46
  • Actually, I read further and it has more to do with the relocation type produced by -fpie rather than with the "start address". For more info, see: https://tecnocode.co.uk/2014/10/01/dynamic-relocs-runtime-overflows-and-fpic/ – user123 Feb 28 '22 at 06:16
  • As I understand the issue, globals are placed in the data segment of the executable and, with -fpie, are accessed with an offset from RIP which is limited to a 32 bits offset. Shared libraries are meant to appear anywhere in the virtual address space so they can be further away from another executable, which was loaded alongside it, than a 32 bits offset. The linker thus complains that the 32 bits limited offset may have an overflow if the shared library is to be loaded further away than a 32 bits offset. – user123 Feb 28 '22 at 06:39

1 Answers1

0

The short answer to your question is that you should remove the -shared option in your compilation command. This will produce a "normal" executable that will have a start address and that must have a main function.

While answering your question, I came up with a question myself that I asked on StackOverflow which you can browse at: In shared objects, why does gcc relocate through the GOT for global variables which are defined in the same shared object?.

The main reason for having to remove -shared is that the -fpie option is on by default when you compile with gcc. This produces position-independent code that will access the data segment of the executable using RIP-relative addressing. As stated in my own question (linked above), RIP-relative addressing is limited to a 32 bits offset (due to x86-64 machine code limitations). Now I wondered why this is a problem. The problem really lies with symbol interposition. If you redefine a symbol in another shared library or in the main program loaded alongside your own shared library, then this symbol may be "chosen" to be the actual symbol that is going to be used during execution. This is a problem because, if the shared library is farther away than a 32 bits offset from this redefinition, then it will overflow and the code of the shared library will not be able to access that symbol.

This is the cause of the relocation R_X86_64_PC32 against symbol `myglob' can not be used when making a shared object; recompile with -fPIC error which states that a RIP-relative addressing relocation is illegal in a shared object for accessing a symbol that is exported because that symbol may be interposed.

You can avoid exporting symbols by making the symbol hidden with __attribute__ ((visibility ("hidden"))). This will prevent gcc from exporting the symbol and thus interposition possibility becomes non-existent. The symbol will thus be accessed using RIP-relative addressing without indirection through the GOT.

user123
  • 2,510
  • 2
  • 6
  • 20