I don't think I am.klange wrote:Yes, you'll find that my relocatable object loader loads relocatable objects. There is an executable loader in the function below that, though. There's also a dynamic linker but that is in userspace...alexfru wrote:So, it looks like you're loading object files, not executable ones?Don't confuse position independence with dynamic executables: you can have one, the other, both, or neither.alexfru wrote:Do I understand it correctly that a proper ELF executable that can be loaded anywhere (because of ASLR or lack of page translation) needs to have a whole bunch of extra sections for the dynamic loader, even where a simple object file would suffice?
Right.klange wrote:Time for some rambling:
Object files can represent any sort of code: executable, library; static, dynamic; position-independent or not... But regardless of what's in them, you absolutely need a linker to turn them into a final product - they are only an intermediary format. Object files consist only of sections, and lack the program headers found in executables and shared objects.
Let me sort of rephrase or explain myself... I kinda know how to handle ELF object files (I have written a linker that links them statically) and I know how to make ELF executable files (with 2 segments for code and data and nothing else) that are non-relocatable. I also know how to make PE executable files that are relocatable (there's a very simple relocation table in the file in addition to the segments/sections containing code/data). If I wanted relocatable ELF executables similar to relocatable PE executables, how would I do that?klange wrote:On most architectures, position-independent executables and libraries can actually be built statically and without any extra sections through the use of "thunks" and native IP-relative addressing schemes. On x86-32 these were notably slower at runtime than patched up absolute code, which was a very good reason to pick relocatable objects for device drivers. x86-64 and various other architectures don't suffer from the same speed impact, with x86-64 in particular introducing RIP-relative instructions.
The main benefit behind position-independent code, even when it does involve relocations - which it will in the case of a dynamic library that references other libraries as relocations are what fills in the addresses of runtime-resolved symbols - is that the relocations are moved away from the code so that the number of pages that need to be modified per-process is minimized (usually through a global offset table). This means you can "load once, run anywhere" in the sense that you can have a shared library in physical memory once and then map it into userspace memory layouts for every process that references that library, and they'll only need their own private copies of the small set of pages with relocations.
Can I just slap relocations onto an ELF executable?
Or maybe instead slap program segments onto an ELF object file?
Or do I need to do something different altogether? Like really produce position independent code in the first place, but then how would I tell the OS/loader that it may safely load it anywhere instead of the address(es) mentioned in the various ELF headers?
Technically, to relocate an executable at load time (for simplicity, say, x86-32), the simplest solution is to just add a constant to a bunch of locations within the executable file to adjust the addresses up or down (and a table would tell which locations those are). I'm pretty much describing what happens with PEs in Windows. But what's the equivalent for this in the ELF executables? How do I express it? Do I make an ELF file that has both relocations and program segments? Do I use some of all of those things from the dynamic loader world even if I don't intend to link to e.g. glibc's printf()?