I don't find any useful information on the differences between "-fno-pie" and "-no-pie". Are they gcc flags or ld flags? Are they both necessary or not?
I found a piece of makefile that uses these lines:
CC = @gcc -fno-pie -no-pie
LD = @gcc -fno-pie -no-pie
So it uses gcc for linking instead of a direct call to ld but I don't understand the differences between the flags and if they are both necessary to compiling and linking stage
TLDR;
-fno-pieis a "code generation option" while-no-pieis a "linker option". You need both.-fno-pietell GCC that you don't want to make a PIE. If you are not making a PIE you are making either a shared object (using-shared) or an ordinary executable.Ordinary executables are loaded below the 4GiB and at a fixed address, furthermore their symbols cannot be interposed so
-fno-pietell GCC that can translate an expression like&fooin something likemov eax, OFFSET FLAT foo.It doesn't have to use the GOT since the symbols are not interposed and it doesn't have to use RIP-relative addressing since a 32-bit address fits in the 32-bit immediate/displacement of x86-64 instructions.
Check out what
-fpie/-fno-piedo in terms of assembly instructions.An instruction like
mov eax, OFFSET FLAT foocreates aR_X86_64_32relocation, this relocation is used in 64-bit programs when the compiler is sure that an address will always fit 32 bits (i.e. is below 4GiB).However
-fno-piedoesn't stop GCC from passing-pieto the linker.So the linker sees a
R_X86_64_32relocation and is still instructed to make a PIE executable. The relocation promises that the address will be below 4GiB but the-pieflag promises that the executable is meant to be loaded anywhere, including above 4GiB.These contrast each other and the linker is required to check this stalemate and produce an error.
To tell the linker that indeed you did not want to link a PIE executable, you need to pass
-no-pieto GCC.You can pass
-vto GCC while compiling a file to see what options are passed tocollect2(a wrapper to the linker).Regardless of the presence of
-fno-pie,-pieis still passed tocollect2.Adding
-no-pieto GCC will suppress-piein thecollect2command line.Note: Older distributions built GCC without defaulting to
-fpie -pie.