Loading Relocatable Objects at Runtime - Very Expensive |
Rod Evans Wednesday February 02, 2005
The runtime linker, ld.so.1(1), is capable of loading relocatable objects. This capability arrived somewhat by accident, and as a side effect of some other projects related to the link-editor, ld(1). But, it was thought that this capability could prove useful within a development environment. A user can preload relocatable objects, and this technique might provide a quick prototyping turnaround instead of having to first combine the relocatable objects into some huge shared object.
However, this capability doesn't come cheap, and it was never thought to be useful for production software. Recently, a customer problem uncovered a regression in relocatable object processing. But, it was a surprise to see that this technique, in this case the dlopen(3c) of a relocatable object, was being used in production code.
The runtime linker only knows how to deal with dynamic objects, that is, dynamic executables and shared objects. When a relocatable object is encountered, the runtime linker first loads the link-editor. The link-editor then converts the relocatable object into a shared object memory image within the process. The runtime linker then processes this memory image as it would any other shared object.
The link-editor is really a family of libraries, and you can see these if you inspect the link-maps of a process that has triggered the loading of a relocatable object.
% mdb main > ::bp exit > :r > ::Rt_maps Link-map lists (dynlm_list): 0x8045f38 ---------------------------------------------- Lm_list: 0xfeffa204 (LM_ID_BASE) ---------------------------------------------- Link_map\* ADDR() NAME() ---------------------------------------------- 0xfeffc8f4 0x08050000 main 0xfeffccc4 0xfeef0000 /lib/libc.so.1 ---------------------------------------------- Lm_list: 0xfeffa1c8 (LM_ID_LDSO) ---------------------------------------------- 0xfeffc590 0xfefc8000 /lib/ld.so.1 0xfeee06e4 0xfee60000 /lib/libld.so.2 0xfeee0af0 0xfed90000 /lib/libc.so.1 0xfed80068 0xfed50000 /lib/libelf.so.1
As you can see, the runtime linkers link-map list (LM_ID_LDSO) contains the runtime linker itself, and all the libraries that effectively make up the link-editor.
Besides loading all these support libraries, the shared object image adds additional overhead. Relocatable objects are typically non-pic, and thus require considerable more relocation than their pic (position independent) counterparts. This relocation overhead is passed on to the shared object memory image.
And, because the image is created in memory, each process that uses this technique creates it's own private image. There is no sharing of text pages from the shared object image, as is common for shared objects. This customers application forked off a number of processes that all dlopen()'ed the same relocatable object.
So, this technique may have some use within a development environment, but there are expenses:
the link-editor must be loaded into the process,
the relocatable object is then converted into a shared object memory image,
there are typically many more relocations to process in the memory image than there would be from a comparable pic shared object, and
the resulting shared object image isn't sharable between processes.
Personally, I'd recommend not using this technique in production software.
A relocatable object is output from the compilers. The link-editor typically combines a number of relocatable objects so as to create a dynamic executable or shared object.
Dynamic executables and shared objects are mapped directly from the file system, thus their read-only text segments can be shared between multiple processes. This shareablity is common to many OS's.
The subject of this posting is the translation of an input relocatable object into a shared object memory image. As the resultant shared object image is wriiten into memory and is not backed by any file, the image is private to the process that created it.
Interposition occurs when the symbol in one library is found before a symbol of the same name in another library, during the runtime linkers symbol search.
You can force interposition with the initial dependencies that are loaded by building the library with <code>-z interpose</code>.
[12] Interface Creation (compilers) | [14] Relocations Don't Fit |