Dynamic Linker
**************

The dynamic linker is responsible for loading dynamically linked programs and their dependencies (in the form of shared objects).  The dynamic linker in theglibc also supports loading shared objects (such as plugins) later at run time.

Dynamic linkers are sometimes called dynamic loaders.

Dynamic Linker Invocation
=========================

When a dynamically linked program starts, the operating system automatically loads the dynamic linker along with the program. Theglibc also supports invoking the dynamic linker explicitly to launch a program.  This command uses the implied dynamic linker (also sometimes called the program interpreter):

     sh -c 'echo "Hello, world!"'

This command specifies the dynamic linker explicitly:

     ld.so /bin/sh -c 'echo "Hello, world!"'

Note that ld.so does not search the PATH environment variable, so the full file name of the executable needs to be specified.

The ld.so program supports various options.  Options start -- and need to come before the program that is being launched. Some of the supported options are listed below.

--list-diagnostics
     Print system diagnostic information in a machine-readable format. See Dynamic Linker Diagnostics.

Dynamic Linker Diagnostics
--------------------------

The ld.so --list-diagnostics produces machine-readable diagnostics output.  This output contains system data that affects the behavior of theglibc, and potentially application behavior as well.

The exact set of diagnostic items can change between releases of theglibc.  The output format itself is not expected to change radically.

The following table shows some example lines that can be written by the diagnostics command.

dl_pagesize=0x1000
     The system page size is 4096 bytes.

env[0x14]="LANG=en_US.UTF-8"
     This item indicates that the 21st environment variable at process startup contains a setting for LANG.

env_filtered[0x22]="DISPLAY"
     The 35th environment variable is DISPLAY.  Its value is not included in the output for privacy reasons because it is not recognized as harmless by the diagnostics code.

path.prefix="/usr"
     This means that theglibc was configured with --prefix=/usr.

path.system_dirs[0x0]="/lib64/"
path.system_dirs[0x1]="/usr/lib64/"
     The built-in dynamic linker search path contains two directories, /lib64 and /usr/lib64.

Dynamic Linker Diagnostics Format
.................................

As seen above, diagnostic lines assign values (integers or strings) to a sequence of labeled subscripts, separated by ..  Some subscripts have integer indices associated with them.  The subscript indices are not necessarily contiguous or small, so an associative array should be used to store them.  Currently, all integers fit into the 64-bit unsigned integer range.  Every access path to a value has a fixed type (string or integer) independent of subscript index values.  Likewise, whether a subscript is indexed does not depend on previous indices (but may depend on previous subscript labels).

A syntax description in ABNF (RFC 5234) follows.  Note that %x30-39 denotes the range of decimal digits.  Diagnostic output lines are expected to match the line production.

     HEXDIG = %x30-39 / %x61-6f ; lowercase a-f only
     ALPHA = %x41-5a / %x61-7a / %x7f ; letters and underscore
     ALPHA-NUMERIC = ALPHA / %x30-39 / "_"
     DQUOTE = %x22 ; "

     ; Numbers are always hexadecimal and use a 0x prefix.
     hex-value-prefix = %x30 %x78
     hex-value = hex-value-prefix 1*HEXDIG

     ; Strings use octal escape sequences and \\, \".
     string-char = %x20-21 / %x23-5c / %x5d-7e ; printable but not "\
     string-quoted-octal = %x30-33 2*2%x30-37
     string-quoted = "\" ("\" / DQUOTE / string-quoted-octal)
     string-value = DQUOTE *(string-char / string-quoted) DQUOTE

     value = hex-value / string-value

     label = ALPHA *ALPHA-NUMERIC
     index = "[" hex-value "]"
     subscript = label [index]

     line = subscript *("." subscript) "=" value

Dynamic Linker Diagnostics Values
.................................

As mentioned above, the set of diagnostics may change between theglibc releases.  Nevertheless, the following table documents a few common diagnostic items.  All numbers are in hexadecimal, with a 0x prefix.

dl_dst_lib=STRING
     The $LIB dynamic string token expands to STRING.

dl_hwcap=INTEGER
dl_hwcap2=INTEGER
     The HWCAP and HWCAP2 values, as returned for getauxval, and as used in other places depending on the architecture.

dl_pagesize=INTEGER
     The system page size is INTEGER bytes.

dl_platform=STRING
     The $PLATFORM dynamic string token expands to STRING.

dso.libc=STRING
     This is the soname of the shared libc object that is part of theglibc.  On most architectures, this is libc.so.6.

env[INDEX]=STRING
env_filtered[INDEX]=STRING
     An environment variable from the process environment.  The integer INDEX is the array index in the environment array.  Variables under env include the variable value after the = (assuming that it was present), variables under env_filtered do not.

path.prefix=STRING
     This indicates that theglibc was configured using --prefix=STRING.

path.sysconfdir=STRING
     Theglibc was configured (perhaps implicitly) with --sysconfdir=STRING (typically /etc).

path.system_dirs[INDEX]=STRING
     These items list the elements of the built-in array that describes the default library search path.  The value STRING is a directory file name with a trailing /.

path.rtld=STRING
     This string indicates the application binary interface (ABI) file name of the run-time dynamic linker.

version.release="stable"
version.release="development"
     The value "stable" indicates that this build of theglibc is from a release branch.  Releases labeled as "development" are unreleased development versions.

version.version="MAJOR.MINOR"
version.version="MAJOR.MINOR.9000"
     Theglibc version.  Development releases end in .9000.

auxv[INDEX].a_type=TYPE
auxv[INDEX].a_val=INTEGER
auxv[INDEX].a_val_string=STRING
     An entry in the auxiliary vector (specific to Linux).  The values TYPE (an integer) and INTEGER correspond to the members of struct auxv.  If the value is a string, a_val_string is used instead of a_val, so that values have consistent types.

     The AT_HWCAP and AT_HWCAP2 values in this output do not reflect adjustment by theglibc.

uname.sysname=STRING
uname.nodename=STRING
uname.release=STRING
uname.version=STRING
uname.machine=STRING
uname.domain=STRING
     These Linux-specific items show the values of struct utsname, as reported by the uname function.  See Platform Type.

aarch64.cpu_features....
     These items are specific to the AArch64 architectures.  They report data theglibc uses to activate conditionally supported features such as BTI and MTE, and to select alternative function implementations.

aarch64.processor[INDEX]....
     These are additional items for the AArch64 architecture and are described below.

aarch64.processor[INDEX].requested=KERNEL-CPU
     The kernel is told to run the subsequent probing on the CPU numbered KERNEL-CPU.  The values KERNEL-CPU and INDEX can be distinct if there are gaps in the process CPU affinity mask.  This line is not included if CPU affinity mask information is not available.

aarch64.processor[INDEX].observed=KERNEL-CPU
     This line reports the kernel CPU number KERNEL-CPU on which the probing code initially ran.  If the CPU number cannot be obtained, this line is not printed.

aarch64.processor[INDEX].observed_node=NODE
     This reports the observed NUMA node number, as reported by the getcpu system call.  If this information cannot be obtained, this line is not printed.

aarch64.processor[INDEX].midr_el1=VALUE
     The value of the midr_el1 system register on the processor INDEX.  This line is only printed if the kernel indicates that this system register is supported.

aarch64.processor[INDEX].dczid_el0=VALUE
     The value of the dczid_el0 system register on the processor INDEX.

x86.cpu_features....
     These items are specific to the i386 and x86-64 architectures.  They reflect supported CPU features and information on cache geometry, mostly collected using the CPUID instruction.

x86.processor[INDEX]....
     These are additional items for the i386 and x86-64 architectures, as described below.  They mostly contain raw data from the CPUID instruction.  The probes are performed for each active CPU for the ld.so process, and data for different probed CPUs receives a uniqe INDEX value.  Some CPUID data is expected to differ from CPU core to CPU core.  In some cases, CPUs are not correctly initialized and indicate the presence of different feature sets.

x86.processor[INDEX].requested=KERNEL-CPU
     The kernel is told to run the subsequent probing on the CPU numbered KERNEL-CPU.  The values KERNEL-CPU and INDEX can be distinct if there are gaps in the process CPU affinity mask.  This line is not included if CPU affinity mask information is not available.

x86.processor[INDEX].observed=KERNEL-CPU
     This line reports the kernel CPU number KERNEL-CPU on which the probing code initially ran.  If the CPU number cannot be obtained, this line is not printed.

x86.processor[INDEX].observed_node=NODE
     This reports the observed NUMA node number, as reported by the getcpu system call.  If this information cannot be obtained, this line is not printed.

x86.processor[INDEX].cpuid_leaves=COUNT
     This line indicates that COUNT distinct CPUID leaves were encountered.  (This reflects internal ld.so storage space, it does not directly correspond to CPUID enumeration ranges.)

x86.processor[INDEX].ecx_limit=VALUE
     The CPUID data extraction code uses a brute-force approach to enumerate subleaves (see the .subleaf_eax lines below).  The last %rcx value used in a CPUID query on this probed CPU was VALUE.

x86.processor[INDEX].cpuid.eax[QUERY_EAX].eax=EAX
x86.processor[INDEX].cpuid.eax[QUERY_EAX].ebx=EBX
x86.processor[INDEX].cpuid.eax[QUERY_EAX].ecx=ECX
x86.processor[INDEX].cpuid.eax[QUERY_EAX].edx=EDX
     These lines report the register contents after executing the CPUID instruction with %rax == QUERY_EAX and %rcx == 0 (a leaf).  For the first probed CPU (with a zero INDEX), only leaves with non-zero register contents are reported.  For subsequent CPUs, only leaves whose register contents differs from the previously probed CPUs (with INDEX one less) are reported.

     Basic and extended leaves are reported using the same syntax.  This means there is a large jump in QUERY_EAX for the first reported extended leaf.

x86.processor[INDEX].cpuid.subleaf_eax[QUERY_EAX].ecx[QUERY_ECX].eax=EAX
x86.processor[INDEX].cpuid.subleaf_eax[QUERY_EAX].ecx[QUERY_ECX].ebx=EBX
x86.processor[INDEX].cpuid.subleaf_eax[QUERY_EAX].ecx[QUERY_ECX].ecx=ECX
x86.processor[INDEX].cpuid.subleaf_eax[QUERY_EAX].ecx[QUERY_ECX].edx=EDX
     This is similar to the leaves above, but for a subleaf.  For subleaves, the CPUID instruction is executed with %rax == QUERY_EAX and %rcx == QUERY_ECX, so the result depends on both register values.  The same rules about filtering zero and identical results apply.

x86.processor[INDEX].cpuid.subleaf_eax[QUERY_EAX].ecx[QUERY_ECX].until_ecx=ECX_LIMIT
     Some CPUID results are the same regardless the QUERY_ECX value. If this situation is detected, a line with the .until_ecx selector ins included, and this indicates that the CPUID register contents is the same for %rcx values between QUERY_ECX and ECX_LIMIT (inclusive).

x86.processor[INDEX].cpuid.subleaf_eax[QUERY_EAX].ecx[QUERY_ECX].ecx_query_mask=0xff
     This line indicates that in an .until_ecx range, the CPUID instruction preserved the lowested 8 bits of the input %rcx in the output %rcx registers.  Otherwise, the subleaves in the range have identical values.  This special treatment is necessary to report compact range information in case such copying occurs (because the subleaves would otherwise be all different).

x86.processor[INDEX].xgetbv.ecx[QUERY_ECX]=RESULT
     This line shows the 64-bit RESULT value in the %rdx:%rax register pair after executing the XGETBV instruction with %rcx set to QUERY_ECX.  Zero values and values matching the previously probed CPU are omitted.  Nothing is printed if the system does not support the XGETBV instruction.

Dynamic Linker Introspection
============================

Theglibc provides various functions for querying information from the dynamic linker.

 -- Function: int dlinfo (void *HANDLE, int REQUEST, void *ARG)
     GNU, dlfcn.h This function returns information about HANDLE in the memory location ARG, based on REQUEST.  The HANDLE argument must be a pointer returned by dlopen or dlmopen; it must not have been closed by dlclose.

     On success, dlinfo returns 0 for most request types; exceptions are noted below.  If there is an error, the function returns -1, and dlerror can be used to obtain a corresponding error message.

     The following operations are defined for use with REQUEST:

     RTLD_DI_LINKMAP
          The corresponding struct link_map pointer for HANDLE is written to *ARG.  The ARG argument must be the address of an object of type struct link_map *.

     RTLD_DI_LMID
          The namespace identifier of HANDLE is written to *ARG.  The ARG argument must be the address of an object of type Lmid_t.

     RTLD_DI_ORIGIN
          The value of the $ORIGIN dynamic string token for HANDLE is written to the character array starting at ARG as a null-terminated string.

          This request type should not be used because it is prone to buffer overflows.

     RTLD_DI_SERINFO
     RTLD_DI_SERINFOSIZE
          These requests can be used to obtain search path information for HANDLE.  For both requests, ARG must point to a Dl_serinfo object.  The RTLD_DI_SERINFOSIZE request must be made first; it updates the dls_size and dls_cnt members of the Dl_serinfo object.  The caller should then allocate memory to store at least dls_size bytes and pass that buffer to a RTLD_DI_SERINFO request.  This second request fills the dls_serpath array.  The number of array elements was returned in the dls_cnt member in the initial RTLD_DI_SERINFOSIZE request.  The caller is responsible for freeing the allocated buffer.

          This interface is prone to buffer overflows in multi-threaded processes because the required size can change between the RTLD_DI_SERINFOSIZE and RTLD_DI_SERINFO requests.

     RTLD_DI_TLS_DATA
          This request writes the address of the TLS block (in the current thread) for the shared object identified by HANDLE to *ARG. The argument ARG must be the address of an object of type void *.  A null pointer is written if the object does not have any associated TLS block.

     RTLD_DI_TLS_MODID
          This request writes the TLS module ID for the shared object HANDLE to *ARG.  The argument ARG must be the address of an object of type size_t.  The module ID is zero if the object does not have an associated TLS block.

     RTLD_DI_PHDR
          This request writes the address of the program header array to *ARG.  The argument ARG must be the address of an object of type const ElfW(Phdr) * (that is, const Elf32_Phdr * or const Elf64_Phdr *, as appropriate for the current architecture).  For this request, the value returned by dlinfo is the number of program headers in the program header array.

     The dlinfo function is a GNU extension.

The remainder of this section documents the _dl_find_object function and supporting types and constants.

 -- Data Type: struct dl_find_object
     GNU, dlfcn.h This structure contains information about a main program or loaded object.  The _dl_find_object function uses it to return result data to the caller.

     unsigned long long int dlfo_flags
          Currently unused and always 0.

     void *dlfo_map_start
          The start address of the inspected mapping.  This information comes from the program header, so it follows its convention, and the address is not necessarily page-aligned.

     void *dlfo_map_end
          The end address of the mapping.

     struct link_map *dlfo_link_map
          This member contains a pointer to the link map of the object.

     void *dlfo_eh_frame
          This member contains a pointer to the exception handling data of the object.  See DLFO_EH_SEGMENT_TYPE below.

     This structure is a GNU extension.

 -- Macro: int DLFO_STRUCT_HAS_EH_DBASE
     GNU, dlfcn.h On most targets, this macro is defined as 0.  If it is defined to 1, struct dl_find_object contains an additional member dlfo_eh_dbase of type void *.  It is the base address for DW_EH_PE_datarel DWARF encodings to this location.

     This macro is a GNU extension.

 -- Macro: int DLFO_STRUCT_HAS_EH_COUNT
     GNU, dlfcn.h On most targets, this macro is defined as 0.  If it is defined to 1, struct dl_find_object contains an additional member dlfo_eh_count of type int.  It is the number of exception handling entries in the EH frame segment identified by the dlfo_eh_frame member.

     This macro is a GNU extension.

 -- Macro: int DLFO_EH_SEGMENT_TYPE
     GNU, dlfcn.h On targets using DWARF-based exception unwinding, this macro expands to PT_GNU_EH_FRAME.  This indicates that dlfo_eh_frame in struct dl_find_object points to the PT_GNU_EH_FRAME segment of the object.  On targets that use other unwinding formats, the macro expands to the program header type for the unwinding data.

     This macro is a GNU extension.

 -- Function: int _dl_find_object (void *ADDRESS, struct dl_find_object *RESULT)
     GNU, dlfcn.h On success, this function returns 0 and writes about the object surrounding the address to *RESULT.  On failure, -1 is returned.

     The ADDRESS can be a code address or data address.  On architectures using function descriptors, no attempt is made to decode the function descriptor.  Depending on how these descriptors are implemented, _dl_find_object may return the object that defines the function descriptor (and not the object that contains the code implementing the function), or fail to find any object at all.

     On success ADDRESS is greater than or equal to RESULT->dlfo_map_start and less than RESULT->dlfo_map_end, that is, the supplied code address is located within the reported mapping.

     This function returns a pointer to the unwinding information for the object that contains the program code ADDRESS in RESULT->dlfo_eh_frame.  If the platform uses DWARF unwinding information, this is the in-memory address of the PT_GNU_EH_FRAME segment.  See DLFO_EH_SEGMENT_TYPE above. In case ADDRESS resides in an object that lacks unwinding information, the function still returns 0, but sets RESULT->dlfo_eh_frame to a null pointer.

     _dl_find_object itself is thread-safe.  However, if the application invokes dlclose for the object that contains ADDRESS concurrently with _dl_find_object or after the call returns, accessing the unwinding data for that object or the link map (through RESULT->dlfo_link_map) is not safe.  Therefore, the application needs to ensure by other means (e.g., by convention) that ADDRESS remains a valid code address while the unwinding information is processed.

     This function is a GNU extension.