Support Interface Example
The following example creates a support library that prints the section name of any relocatable object file processed as part of a 32-bit link-edit.
$ cat support.c #include <link.h> #include <stdio.h> static int indent = 0; void ld_start(const char * name, const Elf32_Half type, const char * caller) { (void) printf("output image: %s\n", name); } void ld_file(const char * name, const Elf_Kind kind, int flags, Elf * elf) { if (flags & LD_SUP_EXTRACTED) indent = 4; else indent = 2; (void) printf("%*sfile: %s\n", indent, "", name); } void ld_section(const char * name, Elf32_Shdr * shdr, Elf32_Word sndx, Elf_Data * data, Elf * elf) { Elf32_Ehdr * ehdr = elf32_getehdr(elf); if (ehdr->e_type == ET_REL) (void) printf("%*s section [%ld]: %s\n", indent, "", (long)sndx, name); } |
This support library is dependent upon libelf to provide the ELF access function elf32_getehdr(3ELF) that is used to determine the input file type. The support library is built using:
$ cc -o support.so.1 -G -K pic support.c -lelf -lc |
The following example shows the section diagnostics resulting from the construction of a trivial application from a relocatable object and a local archive library. The invocation of the support library, in addition to default debugging information processing, is brought about by the -S option usage.
$ LD_OPTIONS="-S./support.so.1 -Slibldstab.so.1" \ cc -o prog main.c -L. -lfoo output image: prog file: /opt/COMPILER/crti.o section [1]: .shstrtab section [2]: .text ....... file: /opt/COMPILER/crt1.o section [1]: .shstrtab section [2]: .text ....... file: /opt/COMPILER/values-xt.o section [1]: .shstrtab section [2]: .text ....... file: main.o section [1]: .shstrtab section [2]: .text ....... file: ./libfoo.a file: ./libfoo.a(foo.o) section [1]: .shstrtab section [2]: .text ....... file: /usr/lib/libc.so file: /opt/COMPILER/crtn.o section [1]: .shstrtab section [2]: .text ....... file: /usr/lib/libdl.so.1 |
Note - The number of sections displayed in this example have been reduced to simplify the output. Also, the files included by the compiler driver can vary.
Runtime Linker Auditing Interface
This section describes the rtld-audit interface that enables a process to access runtime linking information regarding itself. One example of the use of this mechanism is the runtime profiling of shared objects described in "Profiling Shared Objects".
The rtld-audit interface is implemented as an audit library that offers one or more auditing interface routines. If this library is loaded as part of a process, then the audit routines are called by the runtime linker at various stages of process execution. These interfaces enable the audit library to access:
The search for dependencies. Search paths may be substituted by the audit library.
Information regarding loaded objects.
Symbol bindings that occur between these loaded objects. These bindings can be altered by the audit library.
Exploitation of the lazy binding mechanism provided by procedure linker table entries to allow auditing of function calls and their return values. The arguments to a function and its return value can be modified by the audit library. See "Procedure Linkage Table (Processor-Specific)".
Some of these facilities can be achieved by preloading specialized shared objects. A preloaded object exists within the same namespace as the objects of a process. This often restricts or complicates the implementation of the preloaded shared object. The rtld-audit interface offers the user a unique namespace in which to execute their audit libraries. This namespace ensures that the audit library does not intrude upon the normal bindings that occur within the process.
Establishing a Namespace
When the runtime linker binds a dynamic executable with its dependencies, it generates a linked list of link-maps to describe the process. The link-map structure describes each object within the process and is defined in /usr/include/sys/link.h. The symbol search mechanism required to bind objects of an application traverses this list of link-maps. This link-map list is said to provide the namespace for process symbol resolution.
The runtime linker itself is also described by a link-map. This link-map is maintained on a different list from that of the application objects. The runtime linker therefore resides in its own unique name space, which prevents any direct binding of the application to services within the runtime linker. An application can only call upon the public services of the runtime linker by the filter libdl.so.1.
The rtld-audit interface employs its own link-map list on which it maintains any audit libraries. The audit libraries are thus isolated from the symbol binding requirements of the application. Inspection of the application link-map list is possible with dlmopen(3DL). When used with the RTLD_NOLOAD flag, dlmopen(3DL) allows the audit library to query an object's existence without causing its loading.
Two identifiers are defined in /usr/include/link.h to define the application and runtime linker link-map lists:
#define LM_ID_BASE 0 /* application link-map list */ #define LM_ID_LDSO 1 /* runtime linker link-map list */ |
Each rtld-audit support library is assigned a unique free link-map identifier.