|
On May 30, 2014 8:57 PM, "Sean Conner" <sean@conman.org> wrote:
>
> It was thus said that the Great Coroutines once stated:
(I'm clipping everything they once stated, but since I started reading their name as "Coroutínes"--think "Martínez"--I thought that should be styled "Coroutínes Magno". Except I really don't know how to write gender-unknown Spanish. Or regular Spanish, for that matter.)
> I've often wondered why more applications aren't themselves linkable
> libraries [1].
Probably because it was not possible or desirable on many architectures for many reasons for a long time.
> [1] I've thought this since 1991 when I got my Amiga
"Aztec or Lattice?"
> and realized that
> the object file format and the executable format were identical [2]
> [2] Unlike MS-DOS/Windows. The object format is distinct from the
> executable format. I think the same was true for Unix until the ELF
> standard came about.
In the bad old days, executables were statically linked. All symbols were resolved at that (static) program link time. On architectures with fixed process address layout, an executable really could be just a file you read() into memory at 0x10000. There is just not that much structure there. Check out the V7 a.out man page.
On architectures where placement in memory was not known at link time, relocation records had to be stored with the executable. These records told the linker how to patch up the code and data to match the place it had been loaded this time. The relocation records were not useful after the load process was finished, so they were left on disk.
If the only kind of patches needed were just "take the signed 32-bit value at location x and add the load address to it" there still was not much format to speak of. IIRC, what forced Unix people away from simple a.out to more structured executable formats like ECOFF was the combination of dynamic linking and architectures which needed a wider variety of relocation records. On MIPS, there's no way to load a 32-bit immediate operand; you have to load the top half, then add in the bottom half. So now you need a way to split up a patch over two instructions.
When looking at objects with unresolved symbols (think .o files) you needed more kinds of relocation records, to talk about how to patch up operands relative to some named symbol.
The book you want to read is John Levine's _Linkers and Loaders_, http://linker.iecc.com/ and for a more ecumenical view, some non-i386 ELF processor-specific extensions for the SVR4 ABI ("psABI"). I am most familiar with MIPS, but somebody posting from "nop.com" probably has a cognitive bias in favor of architected delay slots.
Anyway, _Linkers and Loaders_ will tell you about all the...fun the SVR4 shared library system has to handle the case where your program has symbols named malloc and free. SVR4 attempts to preserve the semantics you would have in that situation using a static link.
People ask: why is libtool so painful? And at one point the answer was that it supported things like AIX shared libraries, which had many restrictions similar to DLLs.
Jay