We can convince the linker to produce a shared library in which all
the symbols will be relocated at load-time, eg.:
$ gcc -shared foo.o -o libfoo.so
produces a libfoo.so in which all the symbols will be dynamically
relocated. Check it with
$ objdump --dymamic-reloc libfoo.os
to get the dynamic relocations,
$ objdump --dymamic-syms libfoo.os
to get the dynamic exports, and
$ objdump --disassemble libfoo.os
to get the full disassembly.
We don't have to produce position-independent code, but we do get the
penalty of full load-time linking which touches pages all over the
shared library image, and so the library doesn't end up shared at all.
PROBLEM
-------
We can't convince the linker to construct the program this way. When
making a binary, the linker attempts to put all the relocations
together, using tricks:
- relocatable function references turn into a jump table. Jumps
from the code point to the jump table, the jump table gets
its entries relocated at load-time.
- relocatable data is allocated statically in the bss section.
The contents are *copied* in from the shared library at load-time,
and references from the shared library are relocated to point to
the location in the bss.
The .type and .size directives in the assembly file supply the
information that the linker needs to perform the above shenannigans.
This is all bad for us, because our functions are not C-type
functions, so the jump table doesn't work properly. Furthermore, our
data runs backwards from the pointer sometimes, so the linker's
copying semantics for data won't work.
We really need the linker to just do ordinary linking at load-time on
the binary.