1. Introduction to the Oracle Solaris Link Editors
5. Application Binary Interfaces and Versioning
Relocation Types (Processor-Specific)
64-bit SPARC: Relocation Types
Symbol Table Layout and Conventions
Program Loading (Processor-Specific)
Global Offset Table (Processor-Specific)
Procedure Linkage Table (Processor-Specific)
32-bit SPARC: Procedure Linkage Table
64-bit SPARC: Procedure Linkage Table
A. Link-Editor Quick Reference
C. Establishing Dependencies with Dynamic String Tokens
E. System V Release 4 (Version 1) Mapfiles
This section describes the object file information and system actions that create running programs. Most information here applies to all systems. Information specific to one processor resides in sections marked accordingly.
Executable and shared object files statically represent application programs. To execute such programs, the system uses the files to create dynamic program representations, or process images. A process image has segments that contain its text, data, stack, and so on. The following major subsections are provided.
Program Header describes object file structures that are directly involved in program execution. The primary data structure, a program header table, locates segment images in the file and contains other information that is needed to create the memory image of the program.
Program Loading (Processor-Specific) describes the information used to load a program into memory.
Runtime Linker describes the information used to specify and resolve symbolic references among the object files of the process image.
An executable or shared object file's program header table is an array of structures. Each structure describes a segment or other information that the system needs to prepare the program for execution. An object file segment contains one or more sections, as described in Segment Contents.
Program headers are meaningful only for executable and shared object files. A file specifies its own program header size with the ELF header's e_phentsize and e_phnum members.
A program header has the following structure. See sys/elf.h.
typedef struct { Elf32_Word p_type; Elf32_Off p_offset; Elf32_Addr p_vaddr; Elf32_Addr p_paddr; Elf32_Word p_filesz; Elf32_Word p_memsz; Elf32_Word p_flags; Elf32_Word p_align; } Elf32_Phdr; typedef struct { Elf64_Word p_type; Elf64_Word p_flags; Elf64_Off p_offset; Elf64_Addr p_vaddr; Elf64_Addr p_paddr; Elf64_Xword p_filesz; Elf64_Xword p_memsz; Elf64_Xword p_align; } Elf64_Phdr;
The kind of segment this array element describes or how to interpret the array element's information. Type values and their meanings are specified in Table 7-25.
The offset from the beginning of the file at which the first byte of the segment resides.
The virtual address at which the first byte of the segment resides in memory.
The segment's physical address for systems in which physical addressing is relevant. Because the system ignores physical addressing for application programs, this member has unspecified contents for executable files and shared objects.
The number of bytes in the file image of the segment, which can be zero.
The number of bytes in the memory image of the segment, which can be zero.
Flags that are relevant to the segment. Type values and their meanings are specified in Table 7-26.
Loadable process segments must have congruent values for p_vaddr and p_offset, modulo the page size. This member gives the value to which the segments are aligned in memory and in the file. Values 0 and 1 mean no alignment is required. Otherwise, p_align should be a positive, integral power of 2, and p_vaddr should equal p_offset, modulo p_align. See Program Loading (Processor-Specific).
Some entries describe process segments. Other entries give supplementary information and do not contribute to the process image. Segment entries can appear in any order, except as explicitly noted. Defined type values are listed in the following table.
Table 7-25 ELF Segment Types
|
Unused. Member values are undefined. This type enables the program header table to contain ignored entries.
Specifies a loadable segment, described by p_filesz and p_memsz. The bytes from the file are mapped to the beginning of the memory segment. If the segment's memory size (p_memsz) is larger than the file size (p_filesz), the extra bytes are defined to hold the value 0. These bytes follow the initialized area of the segment. The file size can not be larger than the memory size. Loadable segment entries in the program header table appear in ascending order, and are sorted on the p_vaddr member.
Specifies dynamic linking information. See Dynamic Section.
Specifies the location and size of a null-terminated path name to invoke as an interpreter. This type is mandatory for dynamic executable files. This type can occur in shared objects. This type cannot occur more than once in a file. This type, if present, must precede any loadable segment entries. See Program Interpreter for details.
Specifies the location and size of auxiliary information. See Note Section for details.
Reserved but has unspecified semantics.
Specifies the location and size of the program header table, both in the file and in the memory image of the program. This segment type cannot occur more than once in a file. Moreover, this segment can occur only if the program header table is part of the memory image of the program. This type, if present, must precede any loadable segment entry. See Program Interpreter for details.
Specifies a thread-local storage template. See Thread-Local Storage Section for details.
Values in this inclusive range are reserved for OS-specific semantics.
This segment contains the stack unwind tables.
This segment contains the stack unwind table. PT_SUNW_EH_FRAME is equivalent to PT_SUNW_EH_UNWIND.
Values in this inclusive range are reserved for Sun-specific semantics.
The same attributes as a PT_LOAD element and used to describe a .SUNW_bss section.
Describes a process stack. Only one PT_SUNWSTACK element can exist. Only access permissions, as defined in the p_flags field, are meaningful.
Reserved for internal use by dtrace(1M).
Specifies capability requirements. See Capabilities Section for details.
Values in this inclusive range are reserved for processor-specific semantics.
Note - Unless specifically required elsewhere, all program header segment types are optional. A file's program header table can contain only those elements that are relevant to its contents.
Executable and shared object files have a base address, which is the lowest virtual address associated with the memory image of the program's object file. One use of the base address is to relocate the memory image of the program during dynamic linking.
An executable or shared object file's base address is calculated during execution from three values: the memory load address, the maximum page size, and the lowest virtual address of a program's loadable segment. The virtual addresses in the program headers might not represent the actual virtual addresses of the program's memory image. See Program Loading (Processor-Specific).
To compute the base address, you determine the memory address that are associated with the lowest p_vaddr value for a PT_LOAD segment. You then obtain the base address by truncating the memory address to the nearest multiple of the maximum page size. Depending on the kind of file being loaded into memory, the memory address might not match the p_vaddr values.
A program to be loaded by the system must have at least one loadable segment, although this restriction is not required by the file format. When the system creates loadable segment memory images, the system gives access permissions, as specified in the p_flags member. All bits that are included in the PF_MASKPROC mask are reserved for processor-specific semantics.
Table 7-26 ELF Segment Flags
|
If a permission bit is 0, that bit's type of access is denied. Actual memory permissions depend on the memory management unit, which can vary between systems. Although all flag combinations are valid, the system can grant more access than requested. In no case, however, will a segment have write permission unless this permission is specified explicitly. The following table lists both the exact flag interpretation and the allowable flag interpretation.
Table 7-27 ELF Segment Permissions
|
For example, typical text segments have read and execute, but not write permissions. Data segments normally have read, write, and execute permissions.
An object file segment consists of one or more sections, though this fact is transparent to the program header. Whether the file segment holds one section or many sections, is also immaterial to program loading. Nonetheless, various data must be present for program execution, dynamic linking, and so on. The following diagrams illustrate segment contents in general terms. The order and membership of sections within a segment can vary.
Text segments contain read-only instructions and data. Data segments contain writable-data and instructions. See Table 7-10 for a list of all special sections.
A PT_DYNAMIC program header element points at the .dynamic section. The .got and .plt sections also hold information related to position-independent code and dynamic linking.
The .plt can reside in a text or a data segment, depending on the processor. See Global Offset Table (Processor-Specific) and Procedure Linkage Table (Processor-Specific) for details.
Sections of type SHT_NOBITS occupy no space in the file, but contribute to the segment's memory image. Normally, these uninitialized data reside at the end of the segment, thereby making p_memsz larger than p_filesz in the associated program header element.
As the system creates or augments a process image, the system logically copies a file's segment to a virtual memory segment. When, and if, the system physically reads the file depends on the program's execution behavior, system load, and so forth.
A process does not require a physical page unless the process references the logical page during execution. Processes commonly leave many pages unreferenced. Therefore, delaying physical reads can improve system performance. To obtain this efficiency in practice, executable files and shared object files must have segment images whose file offsets and virtual addresses are congruent, modulo the page size.
Virtual addresses and file offsets for 32–bit segments are congruent modulo 64K (0x10000). Virtual addresses and file offsets for 64–bit segments are congruent modulo 1 megabyte (0x100000). By aligning segments to the maximum page size, the files are suitable for paging regardless of physical page size.
By default, 64–bit SPARC programs are linked with a starting address of 0x100000000. The whole program is located above 4 gigabytes, including its text, data, heap, stack, and shared object dependencies. This helps ensure that 64–bit programs are correct because the program will fault in the least significant 4 gigabytes of its address space if the program truncates any of its pointers. While 64–bit programs are linked above 4 gigabytes, you can still link programs below 4 gigabytes by using a mapfile and the -M option to the link-editor. See /usr/lib/ld/sparcv9/map.below4G.
The following figure presents the SPARC version of the executable file.
Figure 7-8 SPARC: Executable File (64K alignment)
The following table defines the loadable segment elements for the previous figure.
Table 7-28 SPARC: ELF Program Header Segments (64K alignment)
|
The following figure presents the x86 version of the executable file.
Figure 7-9 32-bit x86: Executable File (64K alignment)
The following table defines the loadable segment elements for the previous figure.
Table 7-29 32-bit x86: ELF Program Header Segments (64K alignment)
|
The example's file offsets and virtual addresses are congruent modulo the maximum page size for both text and data. Up to four file pages hold impure text or data depending on page size and file system block size.
The first text page contains the ELF header, the program header table, and other information.
The last text page holds a copy of the beginning of data.
The first data page has a copy of the end of text.
The last data page can contain file information not relevant to the running process. Logically, the system enforces the memory permissions as if each segment were complete and separate The segments addresses are adjusted to ensure that each logical page in the address space has a single set of permissions. In the previous examples, the region of the file holding the end of text and the beginning of data is mapped twice: at one virtual address for text and at a different virtual address for data.
Note - The previous examples reflect typical Oracle Solaris OS binaries that have their text segments rounded.
The end of the data segment requires special handling for uninitialized data, which the system defines to begin with zero values. If a file's last data page includes information not in the logical memory page, the extraneous data must be set to zero, not the unknown contents of the executable file.
Impurities in the other three pages are not logically part of the process image. Whether the system expunges these impurities is unspecified. The memory image for this program is shown in the following figures, assuming 4 Kbyte (0x1000) pages. For simplicity, these figures illustrate only one page size.
Figure 7-10 32-bit SPARC: Process Image Segments
Figure 7-11 x86: Process Image Segments
One aspect of segment loading differs between executable files and shared objects. Executable file segments typically contain absolute code. For the process to execute correctly, the segments must reside at the virtual addresses used to create the executable file. The system uses the p_vaddr values unchanged as virtual addresses.
On the other hand, shared object segments typically contain position-independent code. This code enables a segment's virtual address change between different processes, without invalidating execution behavior.
Though the system chooses virtual addresses for individual processes, it maintains the relative positions of the segments. Because position-independent code uses relative addressing between segments, the difference between virtual addresses in memory must match the difference between virtual addresses in the file.
The following tables show possible shared object virtual address assignments for several processes, illustrating constant relative positioning. The tables also include the base address computations.
Table 7-30 32-bit SPARC: ELF Example Shared Object Segment Addresses
|
Table 7-31 32-bit x86: ELF Example Shared Object Segment Addresses
|
A dynamic executable or shared object that initiates dynamic linking can have one PT_INTERP program header element. During exec(2), the system retrieves a path name from the PT_INTERP segment and creates the initial process image from the interpreter file's segments. The interpreter is responsible for receiving control from the system and providing an environment for the application program.
In the Oracle Solaris OS, the interpreter is known as the runtime linker, ld.so.1(1).
When creating a dynamic object that initiates dynamic linking, the link-editor adds a program header element of type PT_INTERP to an executable file. This element instructing the system to invoke the runtime linker as the program interpreter. exec(2) and the runtime linker cooperate to create the process image for the program.
The link-editor constructs various data for executable and shared object files that assist the runtime linker. These data reside in loadable segments, thus making the data available during execution. These segments include.
A .dynamic section with type SHT_DYNAMIC that holds various data. The structure residing at the beginning of the section holds the addresses of other dynamic linking information.
The .got and .plt sections with type SHT_PROGBITS that hold two separate tables: the global offset table and the procedure linkage table. Sections that follow, explain how the runtime linker uses and changes the tables to create memory images for object files.
The .hash section with type SHT_HASH that holds a symbol hash table.
Shared objects can occupy virtual memory addresses that are different from the addresses that are recorded in the file's program header table. The runtime linker relocates the memory image, updating absolute addresses before the application gains control.
If an object file participates in dynamic linking, its program header table will have an element of type PT_DYNAMIC. This segment contains the .dynamic section. A special symbol, _DYNAMIC, labels the section, which contains an array of the following structures. See sys/link.h.
typedef struct { Elf32_Sword d_tag; union { Elf32_Word d_val; Elf32_Addr d_ptr; Elf32_Off d_off; } d_un; } Elf32_Dyn; typedef struct { Elf64_Xword d_tag; union { Elf64_Xword d_val; Elf64_Addr d_ptr; } d_un; } Elf64_Dyn;
For each object with this type, d_tag controls the interpretation of d_un.
These objects represent integer values with various interpretations.
These objects represent program virtual addresses. A file's virtual addresses might not match the memory virtual addresses during execution. When interpreting addresses contained in the dynamic structure, the runtime linker computes actual addresses, based on the original file value and the memory base address. For consistency, files do not contain relocation entries to correct addresses in the dynamic structure.
In general, the value of each dynamic tag determines the interpretation of the d_un union. This convention provides for simpler interpretation of dynamic tags by third party tools. A tag whose value is an even number indicates a dynamic section entry that uses d_ptr. A tag whose value is an odd number indicates a dynamic section entry that uses d_val, or that the tag uses neither d_ptr nor d_val. Tags with values in the following special compatibility ranges do not follow these rules. Third party tools must handle these exception ranges explicitly on an item by item basis.
Tags whose values are less than the special value DT_ENCODING.
Tags with values that fall between DT_LOOS and DT_SUNW_ENCODING.
Tags with values that fall between DT_HIOS and DT_LOPROC.
The following table summarizes the tag requirements for executable and shared object files. If a tag is marked mandatory, then the dynamic linking array must have an entry of that type. Likewise, optional means an entry for the tag can appear but is not required.
Table 7-32 ELF Dynamic Array Tags
|
Marks the end of the _DYNAMIC array.
The DT_STRTAB string table offset of a null-terminated string, giving the name of a needed dependency. The dynamic array can contain multiple entries of this type. The relative order of these entries is significant, though their relation to entries of other types is not. See Shared Object Dependencies.
The total size, in bytes, of the relocation entries associated with the procedure linkage table. See Procedure Linkage Table (Processor-Specific).
An address associated with the procedure linkage table or the global offset table. See Procedure Linkage Table (Processor-Specific) and Global Offset Table (Processor-Specific).
The address of the symbol hash table. This table refers to the symbol table indicated by the DT_SYMTAB element. See Hash Table Section.
The address of the string table. Symbol names, dependency names, and other strings required by the runtime linker reside in this table. See String Table Section.
The address of the symbol table. See Symbol Table Section.
The address of a relocation table. See Relocation Sections.
An object file can have multiple relocation sections. When creating the relocation table for an executable or shared object file, the link-editor catenates those sections to form a single table. Although the sections can remain independent in the object file, the runtime linker sees a single table. When the runtime linker creates the process image for an executable file or adds a shared object to the process image, the runtime linker reads the relocation table and performs the associated actions.
This element requires the DT_RELASZ and DT_RELAENT elements also be present. When relocation is mandatory for a file, either DT_RELA or DT_REL can occur.
The total size, in bytes, of the DT_RELA relocation table.
The size, in bytes, of the DT_RELA relocation entry.
The total size, in bytes, of the DT_STRTAB string table.
The size, in bytes, of the DT_SYMTAB symbol entry.
The address of an initialization function. See Initialization and Termination Sections.
The address of a termination function. See Initialization and Termination Sections.
The DT_STRTAB string table offset of a null-terminated string, identifying the name of the shared object. See Recording a Shared Object Name.
The DT_STRTAB string table offset of a null-terminated library search path string. This element's use has been superseded by DT_RUNPATH. See Directories Searched by the Runtime Linker.
Indicates the object contains symbolic bindings that were applied during its link-edit. This elements use has been superseded by the DF_SYMBOLIC flag. See Using the -B symbolic Option.
Similar to DT_RELA, except its table has implicit addends. This element requires that the DT_RELSZ and DT_RELENT elements also be present.
The total size, in bytes, of the DT_REL relocation table.
The size, in bytes, of the DT_REL relocation entry.
Indicates the type of relocation entry to which the procedure linkage table refers, either DT_REL or DT_RELA. All relocations in a procedure linkage table must use the same relocation. See Procedure Linkage Table (Processor-Specific). This element requires a DT_JMPREL element also be present.
Used for debugging.
Indicates that one or more relocation entries might request modifications to a non-writable segment, and the runtime linker can prepare accordingly. This element's use has been superseded by the DF_TEXTREL flag. See Position-Independent Code.
The address of relocation entries that are associated solely with the procedure linkage table. See Procedure Linkage Table (Processor-Specific). The separation of these relocation entries enables the runtime linker to ignore these entries when the object is loaded with lazy binding enabled. This element requires the DT_PLTRELSZ and DT_PLTREL elements also be present.
Various state flags which are applied to the DT_ element immediately following. See Table 7-35.
Indicates that all relocations for this object must be processed before returning control to the program. The presence of this entry takes precedence over a directive to use lazy binding when specified through the environment or by means of dlopen(3C). This element's use has been superseded by the DF_BIND_NOW flag. See When Relocations Are Performed.
The address of an array of pointers to initialization functions. This element requires that a DT_INIT_ARRAYSZ element also be present. See Initialization and Termination Sections.
The address of an array of pointers to termination functions. This element requires that a DT_FINI_ARRAYSZ element also be present. See Initialization and Termination Sections.
The total size, in bytes, of the DT_INIT_ARRAY array.
The total size, in bytes, of the DT_FINI_ARRAY array.
The DT_STRTAB string table offset of a null-terminated library search path string. See Directories Searched by the Runtime Linker.
Flag values specific to this object. See Table 7-33.
Dynamic tag values that are greater than or equal to DT_ENCODING, and less than or equal to DT_LOOS, follow the rules for the interpretation of the d_un union.
The address of an array of pointers to pre-initialization functions. This element requires that a DT_PREINIT_ARRAYSZ element also be present. This array is processed only in an executable file. This array is ignored if contained in a shared object. See Initialization and Termination Sections.
The total size, in bytes, of the DT_PREINIT_ARRAY array.
The number of positive dynamic array tag values.
Values in this inclusive range are reserved for operating system-specific semantics. All such values follow the rules for the interpretation of the d_un union.
The DT_STRTAB string table offset of a null-terminated string that names one or more per-symbol, auxiliary filtees. See Generating Auxiliary Filters.
Reserved for internal use by the runtime-linker.
The DT_STRTAB string table offset of a null-terminated string that names one or more per-symbol, standard filtees. See Generating Standard Filters.
The address of the capabilities section. See Capabilities Section.
The address of the symbol table containing local function symbols that augment the symbols provided by DT_SYMTAB. These symbols are always adjacent to, and immediately precede the symbols provided by DT_SYMTAB. See Symbol Table Section.
The combined size of the symbol tables given by DT_SUNW_SYMTAB and DT_SYMTAB.
Dynamic tag values that are greater than or equal to DT_SUNW_ENCODING, and less than or equal to DT_HIOS, follow the rules for the interpretation of the d_un union.
The size, in bytes, of the DT_SUNW_SYMSORT and DT_SUNW_TLSSORT symbol sort entries.
The address of the array of symbol table indices that provide sorted access to function and variable symbols in the symbol table referenced by DT_SUNW_SYMTAB. See Symbol Sort Sections.
The total size, in bytes, of the DT_SUNW_SYMSORT array.
The address of the array of symbol table indices that provide sorted access to thread local symbols in the symbol table referenced by DT_SUNW_SYMTAB. See Symbol Sort Sections.
The total size, in bytes, of the DT_SUNW_TLSSORT array.
The address of the array of symbol table indices that provide the association of symbols to their capability requirements. See Capabilities Section.
The total size, in bytes, of the unused reserved space at the end of the dynamic string table. If DT_SUNW_STRPAD is not present in an object, no reserved space is available.
The address of the array of capability family indices. Each family of indices is terminated with a 0 entry.
The machine architecture of the link-editor that produced the object. DT_SUNW_LDMACH uses the same EM_ integer values used for the e_machine field of the ELF header. See ELF Header. DT_SUNW_LDMACH is used to identify the class, 32–bit or 64–bit, and the platform of the link-editor that built the object. This information is not used by the runtime linker, but exists purely for documentation.
The size, in bytes, of the DT_SUNW_CAPCHAIN entries.
The total size, in bytes, or the DT_SUNW_CAPCHAIN chain.
The address of the symbol information table. This element requires that the DT_SYMINENT and DT_SYMINSZ elements also be present. See Syminfo Table Section.
The size, in bytes, of the DT_SYMINFO information entry.
The total size, in bytes, of the DT_SYMINFO table.
The address of the version definition table. Elements within this table contain indexes into the string table DT_STRTAB. This element requires that the DT_VERDEFNUM element also be present. See Version Definition Section.
The number of entries in the DT_VERDEF table.
The address of the version dependency table. Elements within this table contain indexes into the string table DT_STRTAB. This element requires that the DT_VERNEEDNUM element also be present. See Version Dependency Section.
The number of entries in the DT_VERNEEDNUM table.
Indicates the RELATIVE relocation count, which is produced from the concatenation of all Elf32_Rela, or Elf64_Rela relocations. See Combined Relocation Sections.
Indicates the RELATIVE relocation count, which is produced from the concatenation of all Elf32_Rel relocations. See Combined Relocation Sections.
The DT_STRTAB string table offset of a null-terminated string that names one or more auxiliary filtees. See Generating Auxiliary Filters.
The DT_STRTAB string table offset of a null-terminated string that names one or more standard filtees. See Generating Standard Filters.
A simple checksum of selected sections of the object. See gelf_checksum(3ELF).
The size, in bytes, of the DT_MOVETAB move entries.
The total size, in bytes, of the DT_MOVETAB table.
The address of a move table. This element requires that the DT_MOVEENT and DT_MOVESZ elements also be present. See Move Section.
The DT_STRTAB string table offset of a null-terminated string defining a configuration file. The configuration file is only meaningful in an executable, and is typically unique to this object. See Configuring the Default Search Paths.
The DT_STRTAB string table offset of a null-terminated string defining one or more audit libraries. See Runtime Linker Auditing Interface.
The DT_STRTAB string table offset of a null-terminated string defining one or more audit libraries. See Runtime Linker Auditing Interface.
Flag values specific to this object. See Table 7-34.
Values in this inclusive range use the d_un.d_val field of the dynamic structure.
Values in this inclusive range use the d_un.d_ptr field of the dynamic structure. If any adjustment is made to the ELF object after the object has been built, these entries must be updated accordingly.
The index of an STT_SPARC_REGISTER symbol within the DT_SYMTAB symbol table. One dynamic entry exists for every STT_SPARC_REGISTER symbol in the symbol table. See Register Symbols.
Values in this inclusive range are reserved for processor-specific semantics.
Except for the DT_NULL element at the end of the dynamic array and the relative order of DT_NEEDED and DT_POSFLAG_1 elements, entries can appear in any order. Tag values not appearing in the table are reserved.
Table 7-33 ELF Dynamic Flags, DT_FLAGS
|
Indicates that the object requires $ORIGIN processing. See Locating Associated Dependencies.
Indicates that the object contains symbolic bindings that were applied during its link-edit. See Using the -B symbolic Option.
Indicates that one or more relocation entries might request modifications to a non-writable segment, and the runtime linker can prepare accordingly. See Position-Independent Code.
Indicates that all relocations for this object must be processed before returning control to the program. The presence of this entry takes precedence over a directive to use lazy binding when specified through the environment or by means of dlopen(3C). See When Relocations Are Performed.
Indicates that the object contains code using a static thread-local storage scheme. Static thread-local storage should not be used in objects that are dynamically loaded, either using dlopen(3C), or using lazy loading.
Table 7-34 ELF Dynamic Flags, DT_FLAGS_1
|
Indicates that all relocations for this object must be processed before returning control to the program. The presence of this flag takes precedence over a directive to use lazy binding when specified through the environment or by means of dlopen(3C). See When Relocations Are Performed.
Indicates that the object is a member of a group. This flag is recorded in the object using the link-editor's -B group option. See Object Hierarchies.
Indicates that the object cannot be deleted from a process. If the object is loaded in a process, either directly or as a dependency, with dlopen(3C), the object cannot be unloaded with dlclose(3C). This flag is recorded in the object using the link-editor -z nodelete option.
Meaningful only for filters. Indicates that all associated filtees be processed immediately. This flag is recorded in the object using the link-editor's -z loadfltr option. See Filtee Processing.
Indicates that this object's initialization section be run before any other objects loaded. This flag is intended for specialized system libraries only, and is recorded in the object using the link-editor's -z initfirst option.
Indicates that the object cannot be added to a running process with dlopen(3C). This flag is recorded in the object using the link-editor's -z nodlopen option.
Indicates that the object requires $ORIGIN processing. See Locating Associated Dependencies.
Indicates that the object should use direct binding information. See Appendix D, Direct Bindings.
Indicates that the objects symbol table is to interpose before all symbols except the primary load object, which is typically the executable. This flag is recorded with the link-editor's -z interpose option. See Runtime Interposition.
Indicates that the search for dependencies of this object ignores any default library search paths. This flag is recorded in the object using the link-editor's -z nodefaultlib option. See Directories Searched by the Runtime Linker.
Indicates that this object is not dumped by dldump(3C). Candidates for this option include objects with no relocations that might get included when generating alternative objects using crle(1). This flag is recorded in the object using the link-editor's -z nodump option.
Identifies this object as a configuration alternative object generated by crle(1). This flag triggers the runtime linker to search for a configuration file $ORIGIN/ld.config.app-name.
Meaningful only for filtees. Terminates a filters search for any further filtees. This flag is recorded in the object using the link-editor's -z endfiltee option. See Reducing Filtee Searches.
Indicates that this object has displacement relocations applied. The displacement relocation records no longer exist within the object as the records were discarded once the relocation was applied. See Displacement Relocations.
Indicates that this object has displacement relocations pending. The displacement relocations exits within the object so the relocation can be completed at runtime. See Displacement Relocations.
Indicates that this object contains symbols that can not be directly bound to. See SYMBOL_SCOPE / SYMBOL_VERSION Directives.
Reserved for internal use by the kernel runtime-linker.
Reserved for internal use by the kernel runtime-linker.
Reserved for internal use by the kernel runtime-linker.
Indicates that this object has been edited or has been modified since the objects original construction by the link-editor. This flag serves as a warning to debuggers that an object might have had an arbitrary change made since the object was originally built.
Reserved for internal use by the kernel runtime-linker.
Indicates that the object contains individual symbols that should interpose before all symbols except the primary load object, which is typically the executable. This flag is recorded when the object is built using a mapfile and the INTERPOSE keyword. See SYMBOL_SCOPE / SYMBOL_VERSION Directives.
Indicates that the dynamic executable requires global auditing. See Recording Global Auditors.
Indicates that the object defines, or makes reference to singleton symbols. See SYMBOL_SCOPE / SYMBOL_VERSION Directives.
Table 7-35 ELF Dynamic Position Flags, DT_POSFLAG_1
|
Identifies the following DT_NEEDED entry as an object to be lazy loaded. This flag is recorded in the object using the link-editor's -z lazyload option. See Lazy Loading of Dynamic Dependencies.
Identifies the following DT_NEEDED entry as an object to be loaded as a group. This flag is recorded in the object using the link-editor's -z groupperm option. See Isolating a Group.
Position-independent code cannot, in general, contain absolute virtual addresses. Global offset tables hold absolute addresses in private data. Addresses are therefore available without compromising the position-independence and shareability of a program's text. A program references its GOT using position-independent addressing and extracts absolute values. This technique redirects position-independent references to absolute locations.
Initially, the GOT holds information as required by its relocation entries. After the system creates memory segments for a loadable object file, the runtime linker processes the relocation entries. Some relocations can be of type R_xxxx_GLOB_DAT, referring to the GOT.
The runtime linker determines the associated symbol values, calculates their absolute addresses, and sets the appropriate memory table entries to the proper values. Although the absolute addresses are unknown when the link-editor creates an object file, the runtime linker knows the addresses of all memory segments and can thus calculate the absolute addresses of the symbols contained therein.
If a program requires direct access to the absolute address of a symbol, that symbol will have a GOT entry. Because the executable file and shared objects have separate a GOT, a symbol's address can appear in several tables. The runtime linker processes all the GOT relocations before giving control to any code in the process image. This processing ensures that absolute addresses are available during execution.
The table's entry zero is reserved to hold the address of the dynamic structure, referenced with the symbol _DYNAMIC. This symbol enables a program, such as the runtime linker, to find its own dynamic structure without having yet processed its relocation entries. This method is especially important for the runtime linker, because it must initialize itself without relying on other programs to relocate its memory image.
The system can choose different memory segment addresses for the same shared object in different programs. The system can even choose different library addresses for different executions of the same program. Nonetheless, memory segments do not change addresses once the process image is established. As long as a process exists, its memory segments reside at fixed virtual addresses.
A GOT format and interpretation are processor-specific. The symbol _GLOBAL_OFFSET_TABLE_ can be used to access the table. This symbol can reside in the middle of the .got section, allowing both negative and nonnegative subscripts into the array of addresses. The symbol type is an array of Elf32_Addr for 32–bit code, and an array of Elf64_Addr for 64–bit code.
extern Elf32_Addr _GLOBAL_OFFSET_TABLE_[]; extern Elf64_Addr _GLOBAL_OFFSET_TABLE_[];
The global offset table converts position-independent address calculations to absolute locations. Similarly the procedure linkage table converts position-independent function calls to absolute locations. The link-editor cannot resolve execution transfers such as function calls between different dynamic objects. So, the link-editor arranges to have the program transfer control to entries in the procedure linkage table. The runtime linker thus redirects the entries without compromising the position-independence and shareability of the program's text. Executable files and shared object files have separate procedure linkage tables.
For 32–bit SPARC dynamic objects, the procedure linkage table resides in private data. The runtime linker determines the absolute addresses of the destinations and modifies the procedure linkage table's memory image accordingly.
The first four procedure linkage table entries are reserved. The original contents of these entries are unspecified, despite the example that is shown in Table 7-36. Each entry in the table occupies 3 words (12 bytes), and the last table entry is followed by a nop instruction.
A relocation table is associated with the procedure linkage table. The DT_JMP_REL entry in the _DYNAMIC array gives the location of the first relocation entry. The relocation table has one entry, in the same sequence, for each non-reserved procedure linkage table entry. The relocation type of each of these entries is R_SPARC_JMP_SLOT. The relocation offset specifies the address of the first byte of the associated procedure linkage table entry. The symbol table index refers to the appropriate symbol.
To illustrate procedure linkage tables, Table 7-36 shows four entries. Two of the four are initial reserved entries. The third entry is a call to name101. The fourth entry is a call to name102. The example assumes that the entry for name102 is the table's last entry. A nop instruction follows this last entry. The left column shows the instructions from the object file before dynamic linking. The right column illustrates a possible instruction sequence that the runtime linker might use to fix the procedure linkage table entries.
Table 7-36 32-bit SPARC: Procedure Linkage Table Example
|
The following steps describe how the runtime linker and program jointly resolve the symbolic references through the procedure linkage table. The steps that are described are for explanation only. The precise execution-time behavior of the runtime linker is not specified.
When the memory image of the program is initially created, the runtime linker changes the initial procedure linkage table entries. These entries are modified so that control can be transferred to one of the runtime linker's own routines. The runtime linker also stores a word of identification information in the second entry. When the runtime linker receives control, this word is examined to identify the caller.
All other procedure linkage table entries initially transfer to the first entry. Thus, the runtime linker gains control at the first execution of a table entry. For example, the program calls name101, which transfers control to the label .PLT101.
The sethi instruction computes the distance between the current and the initial procedure linkage table entries, .PLT101 and .PLT0, respectively. This value occupies the most significant 22 bits of the %g1 register.
Next, the ba,a instruction jumps to .PLT0, establishing a stack frame, and calls the runtime linker.
With the identification value, the runtime linker gets its data structures for the object, including the relocation table.
By shifting the %g1 value and dividing by the size of the procedure linkage table entries, the runtime linker calculates the index of the relocation entry for name101. Relocation entry 101 has type R_SPARC_JMP_SLOT. This relocation offset specifies the address of .PLT101, and its symbol table index refers to name101. Thus, the runtime linker gets the symbol's real value, unwinds the stack, modifies the procedure linkage table entry, and transfers control to the desired destination.
The runtime linker does not have to create the instruction sequences under the memory segment column. If the runtime linkers does, some points deserve more explanation.
To make the code re-entrant, the procedure linkage table's instructions are changed in a particular sequence. If the runtime linker is fixing a function's procedure linkage table entry and a signal arrives, the signal handling code must be able to call the original function with predictable and correct results.
The runtime linker changes three words to convert an entry. The runtime linker can update only a single word atomically with regard to instruction execution. Therefore, re-entrancy is achieved by updating each word in reverse order. If a re-entrant function call occurs just prior to the last patch, the runtime linker gains control a second time. Although both invocations of the runtime linker modify the same procedure linkage table entry, their changes do not interfere with each other.
The first sethi instruction of a procedure linkage table entry can fill the delay slot of the previous entry's jmp1 instruction. Although the sethi changes the value of the %g1 register, the previous contents can be safely discarded.
After conversion, the last procedure linkage table entry, .PLT102, needs a delay instruction for its jmp1. The required, trailing nop fills this delay slot.
Note - The different instruction sequences that are shown for .PLT101, and .PLT102 demonstrate how the update can be optimized for the associated destination.
The LD_BIND_NOW environment variable changes dynamic linking behavior. If its value is non-null, the runtime linker processes R_SPARC_JMP_SLOT relocation entries before transferring control to the program.
For 64–bit SPARC dynamic objects, the procedure linkage table resides in private data. The runtime linker determines the absolute addresses of the destination and modifies the procedure linkage table's memory image accordingly.
The first four procedure linkage table entries are reserved. The original contents of these entries are unspecified, despite the example that is shown in Table 7-37. Each of the first 32,768 entries in the table occupies 8 words (32 bytes), and must be aligned on a 32–byte boundary. The table as a whole must be aligned on a 256–byte boundary. If more than 32,768 entries are required, the remaining entries consist of 6 words (24 bytes) and 1 pointer (8 bytes). The instructions are collected together in blocks of 160 entries followed by 160 pointers. The last group of entries and pointers can contain less than 160 items. No padding is required.
Note - The numbers 32,768 and 160 are based on the limits of branch and load displacements respectively with the second rounded down to make the divisions between code and data fall on 256–byte boundaries so as to improve cache performance.
A relocation table is associated with the procedure linkage table. The DT_JMP_REL entry in the _DYNAMIC array gives the location of the first relocation entry. The relocation table has one entry, in the same sequence, for each non-reserved procedure linkage table entry. The relocation type of each of these entries is R_SPARC_JMP_SLOT. For the first 32,767 slots, the relocation offset specifies the address of the first byte of the associated procedure linkage table entry, the addend field is zero. The symbol table index refers to the appropriate symbol. For slots 32,768 and beyond, the relocation offset specifies the address of the first byte of the associated pointer. The addend field is the unrelocated value -(.PLTN + 4). The symbol table index refers to the appropriate symbol.
To illustrate procedure linkage tables, Table 7-37 shows several entries. The first three show initial reserved entries. The following three show examples of the initial 32,768 entries together with possible resolved forms that might apply if the target address was +/- 2 Gbytes of the entry, within the lower 4 Gbytes of the address space, or anywhere respectively. The final two show examples of later entries, which consist of instruction and pointer pairs. The left column shows the instructions from the object file before dynamic linking. The right column demonstrates a possible instruction sequence that the runtime linker might use to fix the procedure linkage table entries.
Table 7-37 64-bit SPARC: Procedure Linkage Table Example
|
The following steps describe how the runtime linker and program jointly resolve the symbolic references through the procedure linkage table. The steps that are described are for explanation only. The precise execution-time behavior of the runtime linker is not specified.
When the memory image of the program is initially created, the runtime linker changes the initial procedure linkage table entries. These entries are modified so that control is transfer to the runtime linker's own routines. The runtime linker also stores an extended word of identification information in the third entry. When the runtime linker receives control, this word is examined to identify the caller.
All other procedure linkage table entries initially transfer to the first or second entry. These entries establish a stack frame and call the runtime linker.
With the identification value, the runtime linker gets its data structures for the object, including the relocation table.
The runtime linker computes the index of the relocation entry for the table slot.
With the index information, the runtime linker gets the symbol's real value, unwinds the stack, modifies the procedure linkage table entry, and transfers control to the desired destination.
The runtime linker does not have to create the instruction sequences under the memory segment column. If the runtime linker does, some points deserve more explanation.
To make the code re-entrant, the procedure linkage table's instructions are changed in a particular sequence. If the runtime linker is fixing a function's procedure linkage table entry and a signal arrives, the signal handling code must be able to call the original function with predictable and correct results.
The runtime linker can change up to eight words to convert an entry. The runtime linker can update only a single word atomically with regard to instruction execution. Therefore, re-entrancy is achieved by first overwriting the nop instructions with their replacement instructions, and then patching the ba,a, and the sethi if using a 64–bit store. If a re-entrant function call occurs just prior to the last patch, the runtime linker gains control a second time. Although both invocations of the runtime linker modify the same procedure linkage table entry, their changes do not interfere with each other.
If the initial sethi instruction is changed, the instruction can only be replaced by a nop.
Changing the pointer as done for the second form of entry is done using a single atomic 64–bit store.
Note - The different instruction sequences that are shown for .PLT101, .PLT102, and .PLT103 demonstrate how the update can be optimized for the associated destination.
The LD_BIND_NOW environment variable changes dynamic linking behavior. If its value is non-null, the runtime linker processes R_SPARC_JMP_SLOT relocation entries before transferring control to the program.
For 32–bit x86 dynamic objects, the procedure linkage table resides in shared text but uses addresses in the private global offset table. The runtime linker determines the absolute addresses of the destinations and modifies the global offset table's memory image accordingly. The runtime linker thus redirects the entries without compromising the position-independence and shareability of the program's text. Executable files and shared object files have separate procedure linkage tables.
Table 7-38 32-bit x86: Absolute Procedure Linkage Table Example
|
Table 7-39 32-bit x86: Position-Independent Procedure Linkage Table Example
|
Note - As the preceding examples show, the procedure linkage table instructions use different operand addressing modes for absolute code and for position-independent code. Nonetheless, their interfaces to the runtime linker are the same.
The following steps describe how the runtime linker and program cooperate to resolve the symbolic references through the procedure linkage table and the global offset table.
When the memory image of the program is initially created, the runtime linker sets the second and third entries in the global offset table to special values. The following steps explain these values.
If the procedure linkage table is position-independent, the address of the global offset table must be in %ebx. Each shared object file in the process image has its own procedure linkage table, and control transfers to a procedure linkage table entry only from within the same object file. So, the calling function must set the global offset table base register before calling the procedure linkage table entry.
For example, the program calls name1, which transfers control to the label .PLT1.
The first instruction jumps to the address in the global offset table entry for name1. Initially, the global offset table holds the address of the following pushl instruction, not the real address of name1.
The program pushes a relocation offset (offset) on the stack. The relocation offset is a 32–bit, nonnegative byte offset into the relocation table. The designated relocation entry has the type R_386_JMP_SLOT, and its offset specifies the global offset table entry used in the previous jmp instruction. The relocation entry also contains a symbol table index, which the runtime linker uses to get the referenced symbol, name1.
After pushing the relocation offset, the program jumps to .PLT0, the first entry in the procedure linkage table. The pushl instruction pushes the value of the second global offset table entry (got_plus_4 or 4(%ebx)) on the stack, giving the runtime linker one word of identifying information. The program then jumps to the address in the third global offset table entry (got_plus_8 or 8(%ebx)), to jump to the runtime linker.
The runtime linker unwinds the stack, checks the designated relocation entry, gets the symbol's value, stores the actual address of name1 in its global offset entry table, and jumps to the destination.
Subsequent executions of the procedure linkage table entry transfer directly to name1, without calling the runtime linker again. The jmp instruction at .PLT1 jumps to name1 instead of falling through to the pushl instruction.
The LD_BIND_NOW environment variable changes dynamic linking behavior. If its value is non-null, the runtime linker processes R_386_JMP_SLOT relocation entries before transferring control to the program.
For x64 dynamic objects, the procedure linkage table resides in shared text but uses addresses in the private global offset table. The runtime linker determines the absolute addresses of the destinations and modifies the global offset table's memory image accordingly. The runtime linker thus redirects the entries without compromising the position-independence and shareability of the program's text. Executable files and shared object files have separate procedure linkage tables.
Table 7-40 x64: Procedure Linkage Table Example
|
The following steps describe how the runtime linker and program cooperate to resolve the symbolic references through the procedure linkage table and the global offset table.
When the memory image of the program is initially created, the runtime linker sets the second and third entries in the global offset table to special values. The following steps explain these values.
Each shared object file in the process image has its own procedure linkage table, and control transfers to a procedure linkage table entry only from within the same object file.
For example, the program calls name1, which transfers control to the label .PLT1.
The first instruction jumps to the address in the global offset table entry for name1. Initially, the global offset table holds the address of the following pushq instruction, not the real address of name1.
The program pushes a relocation index (index1) on the stack. The relocation offset is a 32–bit, nonnegative index into the relocation table. The relocation table is identified by the DT_JUMPREL dynamic section entry. The designated relocation entry has the type R_AMD64_JMP_SLOT, and its offset specifies the global offset table entry used in the previous jmp instruction. The relocation entry also contains a symbol table index, which the runtime linker uses to get the referenced symbol, name1.
After pushing the relocation index, the program jumps to .PLT0, the first entry in the procedure linkage table. The pushq instruction pushes the value of the second global offset table entry (GOT+8) on the stack, giving the runtime linker one word of identifying information. The program then jumps to the address in the third global offset table entry (GOT+16), to jump to the runtime linker.
The runtime linker unwinds the stack, checks the designated relocation entry, gets the symbol's value, stores the actual address of name1 in its global offset entry table, and jumps to the destination.
Subsequent executions of the procedure linkage table entry transfer directly to name1, without calling the runtime linker again. The jmp instruction at .PLT1 jumps to name1 instead of falling through to the pushq instruction.
The LD_BIND_NOW environment variable changes dynamic linking behavior. If its value is non-null, the runtime linker processes R_AMD64_JMP_SLOT relocation entries before transferring control to the program.