GCC -fPIC option [c++]


Answers

I'll try to explain what has already been said in a simpler way.

Whenever a shared lib is loaded, the loader (the code on the OS which load any program you run) changes some addresses in the code depending on where the object was loaded to.

In the above example, the "111" in the non-PIC code is written by the loader the first time it was loaded.

For not shared objects, you may want it to be like that because the compiler can make some optimizations on that code.

For shared object, if another process will want to "link" to that code he must read it to the same virtual addresses or the "111" will make no sense. but that virtual-space may already be in use in the second process.

Question

I have read about GCC's Options for Code Generation Conventions, but could not understand what "Generate position-independent code (PIC)" does. Please give an example to explain me what does it mean.




Disable and re-enable address space layout randomization only for myself

The documentation for the randomize_va_space sysctl setting is in Documentation/sysctl/kernel.txt in the kernel source tree. Basically,

0 - Turn the process address space randomization off.

1 - Make the addresses of mmap base, stack and VDSO page randomized.

2 - Additionally enable heap randomization.




What does .rodata and -fPIC mean when compiling OpenSSL?

/usr/bin/ld: libcrypto.a(wp_block.o): relocation R_X86_64_32S against `.rodata' can not be used when making a shared object; recompile with -fPIC libcrypto.a(wp_block.o): error adding symbols: Bad value

Effectively, it means you are building a shared object, but you did not specify -fPIC. PIC is position independent code, and it ensures addresses are relative to the program counter, so the code can be easily relocated (the module's base address can be changed easily and stuff just works).

I believe I've seen this issue on Fedora. Since you claim you are using it in your CFLAGS, try this instead:

$ make clean && make dclean
$ export CFLAGS="-fPIC"
$ ./config shared no-ssl2 ...
$ make
...

The make clean && make dclean will ensure all artifacts (including old object files) are cleaned.

Newer versions of OpenSSL respond to make distclean, not make dclean.


I am unsure what is libcrypto.a but apparently it is part of openssl.

That's the library where OpenSSL places the crypto and helper stuff, like AES, Cameilla, SHA, big integers, etc. libssl.a is where the SSL and TLS stuff goes. libssl.a depends upon libcrypto.a.


Newer version of OpenSSL cannot find their shared libraries after install. Also see Issue 3993, libssl.so.1.1: cannot open shared object file in the OpenSSL bug tracker.

You want to use static linking so the libraries do not break your executable. If so, then you may want to find uses of -lssl and -lcrypto in the Makefiles, and change them to -l:libssl.a and -l:libcrypto.a.




On some architectures, including x86, -fPIC generates much worse code (i.e. a function call) for loads/stores of data. While this is tolerable for libraries, it is undesirable for executables.

One of the major selling points of the amd64 instruction set (and also the recent gnu-x32 ABI) was the addition of "PC-relative load/store" instructions, which solve the efficiency problem.

Note that hardened systems usually do enable -fPIE for all executables, because it allows address-space layout randomness.