DESCRIPTION
ld.elf_so is a self-contained, position independent program image providing run-time support for loading and link-editing shared objects into a process' address space. It uses information stored in data structures within the binary (see
elf(5)) and environment variables to determine which shared objects are needed. These shared objects are loaded at a convenient virtual address using the
mmap(2) system call. After all shared objects have been successfully loaded,
ld.elf_so proceeds to resolve external references from both the main program and all objects loaded. Once all required references are resolved control is passed to the program via its entry point.
Startup
On the execution of a dynamically linked binary the kernel will load the program and its run-time linker as specified in the PT_INTERP section in the program header. At this point, instead of passing control directly to the program, the kernel passes control to the specified linker. An auxiliary vector of information is passed that includes the address of the program header, the size of each entry in the header, and the number of entries. The entry point of the program and the base address of where ld.elf_so is loaded is also supplied.
Finding objects
Each
elf(5) object file may contain information in its dynamic (PT_DYNAMIC) section about which shared objects it requires (often referred to as dependencies). These dependencies are specified in the optional DT_NEEDED entry within the dynamic section. Each DT_NEEDED entry refers to a filename string of the shared object that is to be searched for.
The linker will search for libraries in three lists of paths:
-
A user defined list of paths as specified in LD_LIBRARY_PATH and ld.so.conf(5).
The use of ld.so.conf should be avoided as the setting of a global search path can present a security risk.
-
A list of paths specified within a shared object using a DT_RPATH entry in the dynamic section. This is defined at shared object link time.
-
The list of default paths which is set to /usr/lib.
ld.elf_so will expand the following variables if present in the paths:
-
$HWCAP
-
Processor hardware capabilities, for example FPU, MMX, SSE. Currently unimplemented.
-
$ISALIST
-
List of instructions sets this processor can execute. Currently unimplemented.
-
$ORIGIN
-
The directory of the main object. Implemented in ld.elf_so but the kernel support is currently disabled.
-
$OSNAME
-
The value of the kern.ostype sysctl(3).
-
$OSREL
-
The value of the kern.osrelease sysctl(3).
-
$PLATFORM
-
The value of the hw.machine_arch sysctl(3).
Both ${VARIABLE} and $VARIABLE are recognized.
The filename string can be considered free form, however, it will almost always take the form lib<name>.so.<number>, where name specifies the ‘library' name and number is conceptually the library's major version number.
This name and another of the form lib<name>.so are normally symbolic links to the real shared object which has a filename of the form lib<name>.so.<major>.<minor>[.<teeny>]. This naming convention allows a versioning scheme similar to a.out(5).
Relocation
ld.elf_so will perform all necessary relocations immediately except for relocations relating to the Procedure Linkage Table (PLT). The PLT is used as a indirection method for procedure calls to globally defined functions. It allows, through the use of intermediate code, the delayed binding of a call to a globally defined function to be performed at procedure call time. This ‘lazy' method is the default (see LD_BIND_NOW).
Initialization
A mechanism is provided for initialization and termination routines to be called, on a per-object basis before execution of the program proper begins or after the program has completed. This gives a shared object an opportunity to perform any extra set-up or completion work.
The DT_INIT and DT_FINI entries in the dynamic section specify the addresses of the initialization and termination functions, respectively, for the shared object. ld.elf_so arranges for each initialization function to be called before control is passed to the program and for the termination functions to be called by using atexit(3).
This mechanism is exploited by the system-supplied constructor initialization and destructor code located in /usr/lib/crtbeginS.o and /usr/lib/crtendS.o. These files are automatically included by cc(1) and c++(1) in the list of object-code files passed to ld(1) when building a shared C or C++ object.