PIE requires position-independent code, costing a small amount of performance. (Or a large amount like 15% on ISAs like 32-bit x86 that don't easily support PC-relative addressing). See 32-bit absolute addresses no longer allowed in x86-64 Linux?.
With ASLR disabled, e.g. when running under GDB or with it disabled system-wide, Linux chooses a base address of 0x0000555555555000
to map the executable, so objdump -d
addresses relative to the file start like 0x4000
end up at that high virtual address.
A PIE executable is an ELF shared object (like a .so
), as opposed to an ELF "executable". An ELF executable has a base address in the ELF headers, set by the linker, so absolute addresses can be hard-coded into the machine code and data without needing relocations for fixups. (That's why there's no way to ASLR a proper ELF executable, only a PIE).
The mechanism that supports PIE was originally just a fun hack of putting an entry point in a library. Later people realized it would be useful for ASLR for static code/data in executables to be possible, so this existing support became official. (Or something like that; I haven't read up on the history.)
But anyway, ASLR is enabled by PIE, but PIE is a thing even with ASLR disabled, if you want the most general non-technical description.