9    Program Loading and Dynamic Linking

Executable files and shared library files are used to create a process image when a program is started by the system. This chapter describes the object file structures that relate to program execution and also describes how the process image is created from executable and shared object files.

This chapter addresses the following topics:


9.1    Object File Considerations

The following sections describe several general factors that are involved in the linking and loading process.


9.1.1    Structures

The following object file structures contain information that is used in linking and loading operations:

See Chapter 7 for further details on file headers, optional headers, and section headers.


9.1.2    Base Addresses

Executable files and shared library files have a base address, which is the lowest virtual address associated with the process image of the program. The base address is used to relocate the process image during dynamic linking.

During program loading, the base address is calculated from the memory load address, the maximum page size, and the lowest virtual address of the program's loadable segment.


9.1.3    Segment Access Permissions

A program that is to be loaded by the system must have at least one loadable segment, even though this is not required by the file format. When the process image is created, the segments are assigned access permissions, which are determined by the type of segment and type of program image. Table 9-1 shows the access permissions for the various segment and image types.

Table 9-1: Segment Access Permissions

Image Segment Access Permissions
OMAGIC text, data, bss Read, Write, Execute
NMAGIC text Read, Execute
NMAGIC data, bss Read, Write, Execute
ZMAGIC text Read, Execute
ZMAGIC data, bss Read, Write, Execute


9.1.4    Segment Contents

An object file segment can contain one or more sections. The number of sections in a segment is not important for program loading, but specific information must be present for linking and execution. Figure 9-1 illustrates typical segment contents for executable files and shared object files. The order of sections within a segment may vary.

Text segments contain instructions and read-only data, and data segments contain writable data. Text segments and data segments typically include the sections shown in Figure 9-1.

Figure 9-1: Text and Data Segments of Object Files


9.2    Program Loading

As the system creates or augments a process image, it logically copies a file's segment to a virtual memory segment. The time at which the system physically reads the file depends on the program's execution behavior, system load, and other factors. A process does not require a physical page unless it references the logical page during execution.

Processes commonly leave many pages unreferenced. This improves system performance because delaying physical reads frequently obviates them. To obtain this efficiency in practice, shared executable files and shared library files must have segment images whose virtual addresses are zero, modulo the file system block size.

Virtual addresses for the text and data segments must be aligned on 64KB (0x10000) or larger power of 2 boundaries. File offsets must be aligned on 8KB (0x2000) or larger power of 2 boundaries.

Because the page size can be larger than the alignment restrictions of a segment's file offset, up to seven file pages (depending on page size) can hold text or data that is not logically part of the segment. The contents of the various file pages are as follows:

Logically, the system enforces the memory permissions as if each segment were complete and separate; segment's addresses are adjusted to ensure that each logical page in the address space has a single set of permissions.

The end of the data segment requires special handling for uninitialized data, which must be set to zero. 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 contents of the executable file.


9.3    Dynamic Linking

An executable file is loaded at fixed addresses; the system creates its segments using the virtual addresses from the optional header. The system transfers control directly to the entry point of the executable file.

An executable file that uses dynamic linking requires one or more shared libraries to be loaded in addition to the executable file. Instead of loading the executable file, the system loads the dynamic loader, which in turn loads the executable file and its shared libraries.


9.3.1    Dynamic Loader

When building an executable file that uses dynamic linking, the linker adds the flag F_MIPS_CALL_SHARED to the f_flags field of the file header. This flag tells the system to invoke the dynamic loader to load the executable file. Typically, the dynamic loader requested is /sbin/loader, the default loader. The exec function and the dynamic loader cooperate to create the process image. Creating the process image involves the following operations:

To assist the dynamic loader, the linker also constructs the following data items for shared library files and shared executable files:

These data items are located in loadable segments and are available during execution.

Shared library files may be located at virtual addresses that differ from the addresses in the optional header. The dynamic loader relocates the memory image and updates absolute addresses before control is given to the program.

If the environment variable LD_BIND_NOW has a non-null value, the dynamic loader processes all relocations before transferring control to the program. The dynamic loader may use the lazy binding technique to evaluate procedure linkage table entries, avoiding symbol resolution and relocation for functions that are not called. (See Section 9.3.3.1 for information about lazy binding.)

The following sections describe the various dynamic linking sections. The C language definitions are in the header files elf_abi.h and elf_mips.h.


9.3.2    Dynamic Section (.dynamic)

The dynamic section acts as a table of contents for dynamic linking information within the object. Dynamic sections are present only in shared executable files and shared library files.

The dynamic section is located by its section header. This section header is identified by its name (.dynamic) or its section type (STYP_DYNAMIC) in the flags field (s_flags).

The dynamic section is an array with entries of the following type:

typedef struct {
    Elf32_Sword     d_tag;
    union {
        Elf32_Word  d_val;
        Elf32_Addr  d_ptr;
    } d_un;
} Elf32_Dyn;

The structure and union members in the preceding structure definition provide the following information:

d_tag
Indicates how the d_un field is to be interpreted.

d_val
Represents integer values.


d_ptr
Represents program virtual addresses. A file's virtual addresses may not match the memory virtual addresses during execution. The dynamic loader computes actual addresses based on the virtual address from the file and the memory base address. Object files do not contain relocation entries to correct addresses in the dynamic section.

The d_tag requirements for shared executable files and shared library files are summarized in Table 9-2. "Mandatory" indicates that the dynamic linking array must contain an entry of that type; "optional" indicates that an entry for the tag may exist but is not required.

Table 9-2: Dynamic Array Tags (d_tag)

Name Value d_un Executable Shared Object
DT_NULL 0 ignored mandatory mandatory
DT_NEEDED 1 d_val optional optional
DT_PLTRELSZ[Table Note 1] 2 d_val optional optional
DT_PLTGOT 3 d_ptr optional optional
DT_HASH 4 d_ptr mandatory mandatory
DT_STRTAB 5 d_ptr mandatory mandatory
DT_SYMTAB 6 d_ptr mandatory mandatory
DT_RELA[Table Note 1] 7 d_ptr mandatory optional
DT_RELASZ[Table Note 1] 8 d_val mandatory optional
DT_RELAENT[Table Note 1] 9 d_val mandatory optional
DT_STRSZ 10 d_val mandatory mandatory
DT_SYMENT 11 d_val mandatory mandatory
DT_INIT 12 d_ptr optional optional
DT_FINI 13 d_ptr optional optional
DT_SONAME 14 d_val ignored optional
DT_RPATH 15 d_val optional ignored
DT_SYMBOLIC 16 ignored ignored optional
DT_REL 17 d_ptr mandatory optional
DT_RELSZ 18 d_val mandatory optional
DT_RELENT 19 d_val mandatory optional
DT_PLTREL[Table Note 1] 20 d_val optional optional
DT_DEBUG[Table Note 1] 21 d_ptr optional ignored
DT_TEXTREL[Table Note 1] 22 ignored optional optional
DT_JMPREL[Table Note 1] 23 d_ptr optional optional
DT_LOPROC 0x70000000 unspecified unspecified unspecified
DT_HIPROC 0x7fffffff unspecified unspecified unspecified

Table Notes:

  1. Not used by the default system linker and loader.

The uses of the various dynamic array tags are as follows:

DT_NULL
Marks the end of the array.

DT_NEEDED
Contains the string table offset of a null terminated string that is the name of a needed library. The offset is an index into the table indicated in the DT_STRTAB entry. The dynamic array may contain multiple entries of this type. The order of these entries is significant.

DT_PLTRELSZ
Contains the total size in bytes of the relocation entries associated with the procedure linkage table. If an entry of type DT_JMPREL is present, it must have an associated DT_PLTRELSZ entry. (Not used by the default system linker and loader.)

DT_PLTGOT
Contains an address associated with either the procedure linkage table, the global offset table, or both.

DT_HASH
Contains the address of the symbol hash table.

DT_STRTAB
Contains the address of the string table.

DT_SYMTAB
Contains the address of the symbol table with Elf32_Sym entries.

DT_RELA
Contains the address of a relocation table. Entries in the table have explicit addends, such as Elf32_Rela. An object file may have multiple relocation sections. When the linker builds the relocation table for an shared executable file or shared object file, these sections are concatenated to form a single table. While the sections are independent in the object file, the dynamic loader sees a single table. When the dynamic loader creates a process image or adds a shared library file to a process image, it reads the relocation table and performs the associated actions. If this entry is present, the dynamic structure must also contain DT_RELASZ and DT_RELAENT entries. When relocation is mandatory for a file, either DT_RELA or DT_REL may be present. (Not used by the default system linker and loader.)

DT_RELASZ
Contains the size in bytes of the DT_RELA relocation table. (Not used by the default system linker and loader.)

DT_RELAENT
Contains the size in bytes of a DT_RELA relocation table entry. (Not used by the default system linker and loader.)

DT_STRSZ
Contains the size in bytes of the string table.

DT_SYMENT
Contains the size in bytes of a symbol table entry.

DT_INIT
Contains the address of the initialization function.

DT_FINI
Contains the address of the termination function.

DT_SONAME
Contains the string table offset of a null-terminated string that gives the name of the shared library file. The offset is an index into the table indicated in the DT_STRTAB entry.

DT_RPATH
Contains the string table offset of a null-terminated library search path string. The offset is an index into the table indicated in the DT_STRTAB entry.

DT_SYMBOLIC
If this entry is present, the dynamic loader uses a different symbol resolution algorithm for references within a library. The symbol search starts from the shared library file instead of the shared executable file. If the shared library file does not supply the referenced symbol, the shared executable file and other shared library file are searched.

DT_REL
Contains the address of the relocation table. An object file can have multiple relocation sections. When the linker builds the relocation table for a shared executable file or shared library file, these sections are concatenated to form a single table. While the sections are independent in the object file, the dynamic loader sees a single table. When the dynamic loader creates a process image or adds a shared library file to a process image, it reads the relocation table and performs the associated actions. If this entry is present, the dynamic structure must contain the DT_RELSZ entry.

DT_RELSZ
Contains the size in bytes of the relocation table pointed to by the DT_REL entry.

DT_RELENT
Contains the size in bytes of a DT_REL entry.


DT_PLTREL
Specifies the type of relocation entry referred to by the procedure linkage table. The d_val member holds DT_REL or DT_RELA, as appropriate. All relocations in a procedure linkage table must use the same relocation. (Not used by the default system linker and loader.)

DT_DEBUG
Used for debugging. The contents of this entry are not specified. (Not used by the default system linker and loader.)

DT_TEXTREL
If this entry is not present, no relocation entry should cause a modification to a nonwritable segment. If this entry is present, one or more relocations might request modifications to a nonwritable segment. (Not used by the default system linker and loader.)

DT_JMPREL
If this entry is present, its d_ptr field contains the address of relocation entries associated only with the procedure linkage table. The dynamic loader may ignore these entries during process initialization if lazy binding is enabled. See Section 9.3.3.1 for information about lazy binding. (Not used by the default system linker and loader.)

DT_LOPROC through DT_HIPROC
Reserved for processor-specific semantics.

Table 9-3: Processor-Specific Dynamic Array Tags (d_tag)

Name Value d_un Executable Shared Object
DT_MIPS_RLD_VERSION 0x70000001 d_val mandatory mandatory
DT_MIPS_TIME_STAMP 0x70000002 d_val optional optional
DT_MIPS_ICHECKSUM 0x70000003 d_val optional optional
DT_MIPS_IVERSION 0x70000004 d_val optional optional
DT_MIPS_FLAGS 0x70000005 d_val mandatory mandatory
DT_MIPS_BASE_ADDRESS 0x70000006 d_ptr mandatory mandatory
DT_MIPS_CONFLICT 0x70000008 d_ptr optional optional
DT_MIPS_LIBLIST 0x70000009 d_ptr optional optional
DT_MIPS_LOCAL_GOTNO 0x7000000A d_val mandatory mandatory
DT_MIPS_CONFLICTNO 0x7000000B d_val optional optional
DT_MIPS_LIBLISTNO 0x70000010 d_val optional optional
DT_MIPS_SYMTABNO 0x70000011 d_val optional optional
DT_MIPS_UNREFEXTNO 0x70000012 d_val optional optional
DT_MIPS_GOTSYM 0x70000013 d_val mandatory mandatory
DT_MIPS_HIPAGENO[Table Note 1] 0x70000014 d_val mandatory mandatory

Table Notes:

  1. Not used by the default system linker and loader.

The uses of the various processor-specific dynamic array tags are as follows:

DT_MIPS_RLD_VERSION
Holds an index into the object file's string table, which holds the version of the run-time linker interface. The version is 1 for executable objects that have a single GOT and 2 for executable objects that have multiple GOTs.

DT_MIPS_TIME_STAMP
Contains a 32-bit time stamp.

DT_MIPS_ICHECKSUM
Contains a value that is the sum of all of the COMMON sizes and the names of defined external symbols.

DT_MIPS_IVERSION
Contains the string table offset of a series of colon-separated version strings. An index value of zero means no version string was specified.


DT_MIPS_FLAGS
Contains a set of 1-bit flags. The following flags are defined for DT_MIPS_FLAGS:
Flag Value Meaning
RHF_QUICKSTART 0x00000001 Object may be quickstarted by loader
RHF_NOTPOT 0x00000002 Hash size not a power of two
RHF_NO_LIBRARY_REPLACEMENT 0x00000004 Use default system libraries only
RHF_NO_MOVE 0x00000008 Do not relocate
RHF_RING_SEARCH 0x10000000 Symbol resolution same as DT_SYMBOLIC
RHF_DEPTH_FIRST 0x20000000 Depth first symbol resolution
RHF_USE_31BIT_ADDRESSES 0x40000000 TASO (Truncated Address Support Option) objects

DT_MIPS_BASE_ADDRESS
Contains the base address.

DT_MIPS_CONFLICT
Contains the address of the .conflict section.

DT_MIPS_LIBLIST
Contains the address of the .liblist section.


DT_MIPS_LOCAL_GOTNO
Contains the number of local GOT entries. The dynamic array contains one of these entries for each GOT.

DT_MIPS_CONFLICTNO
Contains the number of entries in the .conflict section and is mandatory if there is a .conflict section.

DT_MIPS_LIBLISTNO
Contains the number of entries in the .liblist section.

DT_MIPS_SYMTABNO
Indicates the number of entries in the .dynsym section.

DT_MIPS_UNREFEXTNO
Holds an index into the dynamic symbol table. The index is the entry of the first external symbol that is not referenced within the object.

DT_MIPS_GOTSYM
Holds the index of the first dynamic symbol table entry that corresponds to an entry in the global offset table. The dynamic array contains one of these entries for each GOT.

DT_MIPS_HIPAGENO
Holds the number of page table entries in the global offset table. A page table entry here refers to 64KB of data space. This entry is used by the profiling tools and is optional. (Not used by the default system linker and loader.)

All other tag values are reserved. Entries may appear in any order, except for the relative order of the DT_NEEDED entries and the DT_NULL entry at the end of the array.


9.3.2.1    Shared Object Dependencies

When the linker processes an archive library, library members are extracted and copied into the output object file. These statically linked services are available during execution and do not involve the dynamic loader. Shared executable files also provide services that require the dynamic loader to include the appropriate shared library files in the process image. To accomplish this, shared executable files and shared library files must describe their dependencies.

The dependencies, indicated by the DT_NEEDED entries of the dynamic structure, indicate which shared library files are required for the program. The dynamic loader builds a process image by connecting the referenced shared library files and their dependencies. When resolving symbolic references, the dynamic loader looks first at the symbol table of the shared executable program, then at the symbol tables of the DT_NEEDED entries (in order), then at the second-level DT_NEEDED entries, and so on. Shared library files must be readable by the process.

Note

Even if a shared object is referenced more than once in the dependency list, the dynamic loader includes only one instance of the object in the process image.

Names in the dependency list are copies of the DT_SONAME strings.

If a shared library name has one or more slash characters in its name, such as /usr/lib/libz, the dynamic loader uses the string as the pathname. If the name has no slashes, such as liba, the object is searched as follows:

  1. The dynamic array tag DT_RPATH may give a string that holds a list of directories separated by colons, such as /usr/newlib:/usr/local/lib. The dynamic loader searches these directories in order and, if a library is not located, it then searches the current directory.

  2. The environment variable LD_LIBRARY_PATH can hold a list of colon-separated directories, optionally followed by a semicolon and another directory list. These directories are searched after those specified by DT_RPATH.

  3. If the library was not located in any of the directories specified by DT_RPATH or LD_LIBRARY_PATH, the dynamic loader searches /usr/shlib, /usr/ccs/lib, /usr/lib/cmplrs/cc, /usr/lib, and then /usr/local/lib.

The following environment variables are defined:
_RLD_ARGS Argument to dynamic loader
_RLD_ROOT Prefix that the dynamic loader adds to all paths except those
specified by LD_LIBRARY_PATH

Note

For security, the dynamic loader ignores environmental search specifications, such as LD_LIBRARY_PATH, for set-user-ID and set-group-ID programs.


9.3.3    Global Offset Table (.got)

Position-independent code cannot contain absolute virtual addresses. Global offset tables (GOTs) hold absolute addresses in private data, thus making the addresses available without compromising the position-independence and sharability of a program's text. A program references its global offset table using position-independent addressing and extracts absolute values, thus redirecting position-independent references to absolute locations.

The global offset table is split into two logically separate subtables - local and external:

After the system creates memory segments for a loadable object file, the dynamic loader may process the relocation entries. The only relocation entries remaining are type R_REFQUAD or R_REFLONG, referring to local entries in the GOT and data items containing addresses. The dynamic loader determines the associated symbol (or section) values, calculates their absolute addresses, and sets the proper values. Although the absolute addresses may be unknown when the linker builds an object file, the dynamic loader knows the addresses of all memory segments and can find the correct symbols and calculate the absolute addresses.

If a program requires direct access to the absolute address of a symbol, it uses the appropriate GOT entry. Because the shared executable file and shared library file have separate global offset tables, a symbol's address may appear in several tables. The dynamic loader processes all necessary relocations before giving control to the process image, thus ensuring the absolute addresses are available during execution.

The zero (first) entry of the .dynsym section is reserved and holds a null symbol table entry. The corresponding zero entry in the GOT is reserved to hold the address of the entry point in the dynamic loader to call when using lazy binding to resolve text symbols (see Section 9.3.3.1 for information about resolving text symbols using lazy binding).

The system may choose different memory segment addresses for the same shared library file in different programs; it may 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 single GOT can hold a maximum of 8190 local and global entries. If a program references 8K or more global symbols, it will have multiple GOTs. Each GOT in a multiple-GOT object is referenced by means of a different global pointer value. A single .got section holds all of the GOTs in a multiple-GOT object.

The DT_MIPS_LOCAL_GOTNO and DT_PLTGOT entries of the dynamic section describe the attributes of the global offset table.


9.3.3.1    Resolving Calls to Position-Independent Functions

The GOT is used to hold addresses of position-independent functions as well as data addresses. It is not possible to resolve function calls from one shared executable file or shared library file to another at static link time, so all of the function address entries in the GOT would normally be resolved at run time by the dynamic loader. Through the use of specially constructed pieces of code known as stubs, this run-time resolution can be deferred through a technique known as lazy binding.

Using the lazy binding technique, the linker builds a stub for each called function and allocates GOT entries that initially point to the stubs. Because of the normal calling sequence for position-independent code, the call invokes the stub the first time that the call is made.

stub_xyz:
    ldq  t12, .got_index(gp)
    lda  $at, .dynsym_index_low(zero)
    ldah $at, .dynsym_index_high($at)
    jmp  t12, (t12)

The stub code loads register t12 with an entry from the GOT. The entry loaded into register t12 is the address of the procedure in the dynamic loader that handles lazy binding. The stub code also loads register $at with the index into the .dynsym section of the referenced external symbol. The code then transfers control to the dynamic loader and loads register t12 with the address following the stub. The dynamic loader determines the correct address for the called function and replaces the address of the stub in the GOT with the address of the function.

Most undefined text references can be handled by lazy text evaluation, except when the address of a function is used in other than a jsr instruction. In the exception case, the program uses the address of the stub instead of the actual address of the function. Determining which case is in effect is based on the following processing:

The LD_BIND_NOW environment variable can also change dynamic loader behavior. If its value is non-null, the dynamic loader evaluates all symbol-table entries of type STT_FUNC, replacing their stub addresses in the GOT with the actual address of the referenced function.

Note

Lazy binding generally improves overall application performance because unused symbols do not incur the dynamic loader overhead. Two situations, however, make lazy binding undesirable for some applications:

By turning off lazy binding, the dynamic loader forces the failure to occur during process initialization, before the application receives control.


9.3.4    Dynamic Symbol Section (.dynsym)

The dynamic symbol section provides information on all external symbols, either imported or exported from an object.

All externally visible symbols, both defined and undefined, must be hashed into the hash table (seeSection 9.3.7).

Undefined symbols of type STT_FUNC that have been referenced only by jsr instructions may contain nonzero values in their st_value field denoting the stub address used for lazy evaluation for this symbol. The dynamic loader uses this to reset the GOT entry for this external symbol to its stub address when unloading a shared library file. All other undefined symbols must contain zero in their st_value fields.

Defined symbols in a shared executable file cannot be preempted. The symbol table in the shared executable file is always searched first to resolve any symbol references.


The dynamic symbol section contains an array of entries of the following type:

typedef struct {
    Elf32_Word      st_name;
    Elf32_Addr      st_value;
    Elf32_Word      st_size;
    unsigned char   st_info;
    unsigned char   st_other;
    Elf32_Half      st_shndx;
} Elf32_Sym;

The structure members in the preceding structure definition provide the following information:

st_name
Contains the offset of the symbol's name in the dynamic string section.

st_value
Contains the value of the symbol for those symbols defined within the object; otherwise, contains the value zero.

st_size
Identifies the size of symbols with common storage allocation; otherwise, contains the value zero. For STB_DUPLICATE symbols, the size field holds the index of the primary symbol.

st_info
Identifies the symbol's binding and type. The macros ELF32_ST_BIND and ELF32_ST_TYPE are used to access the individual values.

A symbol's binding determines the linkage visibility and behavior. The binding is encoded in the st_info field and can have one of the following values:
Value Description
STB_LOCAL Indicates that the symbol is local to the object.
STB_GLOBAL Indicates that the symbol is visible to other objects.
STB_WEAK Indicates that the symbol is a weak global symbol.
STB_DUPLICATE Indicates the symbol is a duplicate. (Used for objects that have multiple GOTs.)

A symbol's type identifies its use. The type is encoded in the st_info field and can have one of the following values:
Value Description
STT_NOTYPE Indicates that the symbol has no type or its type is unknown.
STT_OBJECT Indicates that the symbol is a data object.
STT_FUNC Indicates that the symbol is a function.
STT_SECTION Indicates that the symbol is associated with a program section.
STT_FILE Indicates that the symbol as the name of a source file.


st_other
Currently holds a value of zero and has no defined meaning.

st_shndx
Identifies the section to which this symbol is related.

All symbols are defined relative to some program section. The st_shndx field identifies the section and can have one of the following values:
Value Description
SHN_UNDEF Indicates that the symbol is undefined.
SHN_ABS Indicates that the symbol has an absolute value.
SHN_COMMON Indicates that the symbol has common storage (unallocated).
SHN_MIPS_ACOMMON Indicates that the symbol has common storage (allocated).
SHN_MIPS_TEXT Indicates that the symbol is in a text segment.
SHN_MIPS_DATA Indicates that the symbol is in a data segment.

The entries of the dynamic symbol section are ordered as follows:

Figure 9-2 shows the layout of the .dynsym section and its relationship to the .got section.

Figure 9-2: Relationship Between .dynsym and .got

The DT_SYMENT and DT_SYMTAB entries of the dynamic section describe the attributes of the dynamic symbol table.


9.3.5    Dynamic Relocation Section (.rel.dyn)

The dynamic relocation section describes all locations within the object that must be adjusted if the object is loaded at an address other than its linked base address.

Only one dynamic relocation section is used to resolve addresses in data items, and it must be called .rel.dyn. Shared executable files can contain normal relocation sections in addition to a dynamic relocation section. The normal relocation sections may contain resolutions for any absolute values in the main program. The dynamic linker does not resolve these or relocate the main program.

As noted previously, only R_REFQUAD and R_REFLONG relocation entries are supported in the dynamic relocation section.

The dynamic relocation section is an array of entries of the following type:

typedef struct {
    Elf32_Addr      r_offset;
    Elf32_Word      r_info;
} Elf32_Rel;

The structure members in the preceding structure definition provide the following information:

r_offset
Identifies the location within the object to be adjusted.

r_info
Identifies the relocation type and the index of the symbol that is referenced. The macros ELF32_R_SYM and ELF32_R_TYPE access the individual attributes. The relocation type must be either R_REFQUAD or R_REFLONG.

The entries of the dynamic relocation section are ordered by symbol index value.

The DT_REL and DT_RELSZ entries of the dynamic section describe the attributes of the dynamic relocation section.


9.3.6    Msym Section (.msym)

The optional .msym section contains precomputed hash values and dynamic relocation indexes for each entry in the dynamic symbol table. Each entry in the .msym section maps directly to an entry in the .dynsym section. The .msym section is an array of entries of the following type:

typedef struct
{
    Elf32_Word  ms_hash_value;
    Elf32_Word  ms_info;
} Elf32_Msym;

The structure members in the preceding structure definition provide the following information:

ms_hash_value
The hash value computed from the name of the corresponding dynamic symbol.

ms_info
Contains both the dynamic relocation index and the symbol flags field. The macros ELF32_MS_REL_INDEX and ELF32_MS_FLAGS are used to acess the individual values.

The dynamic relocation index identifies the first entry in the .rel.dyn section that references the dynamic symbol corresponding to this msym entry. If the index is 0, no dynamic relocations are associated with the symbol.

The symbol flags field is reserved for future use.

The DT_MIPS_MSYM entry of the dynamic section contains the address of the .msym section.


9.3.7    Hash Table Section (.hash)

A hash table of Elf32_Word entries provides fast access to symbol entries in the dynamic symbol section. Figure 9-3 shows the contents of a hash table.

Figure 9-3: Hash Table Section

The entries in the hash table contain the following information:

The hashing function accepts a symbol name and returns a value that can be used to compute a bucket index. If the hashing function returns the value X for a name, bucket[X % nbucket] gives an index, Y, into the symbol table and chain array. If the symbol table entry indicated is not the correct one, chain[Y] indicates the next symbol table entry with the same hash value. The chain links can be followed until the correct symbol table entry is located or until the chain entry contains the value STN_UNDEF.

The DT_HASH entry of the dynamic section contains the address of the hash table section.


9.3.8    Dynamic String Section (.dynstr)

The dynamic string section is the repository for all strings referenced by the dynamic linking sections. Strings are referenced by using a byte offset within the dynamic string section. The end of the string is denoted by a byte containing the value zero.

The DT_STRTAB and DT_STRSZ entries of the dynamic section describe the attributes of the dynamic string section.


9.3.9    Initialization and Termination Functions

After the dynamic loader has created the process image and performed relocations, each shared object file gets the opportunity to execute initialization code. The initialization functions are called in reverse-dependency order. Each shared object file's initialization functions are called
only after the initialization functions for its dependencies have been executed. All initialization of shared object files occurs before the executable file gains control.

Similarly, shared object files can have termination functions that are executed by the atexit mechanism when the process is terminating. Termination functions are called in dependency order - the exact opposite of the order in which initialization functions are called.

Shared object files designate initialization and termination functions through the DT_INIT and DT_FINI entries in the dynamic structure. Typically, the code for these functions resides in the .init and .fini sections.

Note

Although atexit termination processing normally is done, it is not guaranteed to have executed when the process terminates. In particular, the process does not execute the termination processing if it calls _exit or if the process terminates because it received a signal that it neither caught nor ignored.


9.3.10    Quickstart

The quickstart capability provided by the assembler supports several sections that are useful for faster startup of programs that have been linked with shared library files. Some ordering constraints are imposed on these sections. The group of structures defined in these sections and the ordering constraints allow the dynamic loader to operate more efficiently. These additional sections are also used for more complete dynamic shared library file version control.


9.3.10.1    Shared Object List (.liblist)

A shared object list section is an array of Elf32_Lib structures that contains information about the various dynamic shared library files used to statically link the shared object file. Each shared library file used has an entry in the array. Each entry has the following format:

typedef struct {
    Elf32_Word l_name;
    Elf32_Word l_time_stamp;
    Elf32_Word l_checksum;
    Elf32_Word l_version;
    Elf32_Word l_flags;
} Elf32_Lib;

The structure members in the preceding structure definition provide the following information:

l_name
Specifies the name of a shared library file. Its value is a string table index. This name can be a full pathname, relative pathname, or file name.

l_time_stamp
Contains a 32-bit time stamp. The value can be combined with the l_checksum value and the l_version string to form a unique identifier for this shared library file.

l_checksum
Contains the sum of all common sizes and all string names of externally visible symbols.

l_version
Specifies the interface version. Its value is a string table index. The interface version is a string containing no colons. It is compared to a colon separated string of versions pointed to by a dynamic section entry of the shared library file. Shared library file with matching names may be considered incompatible if the interface version strings are deemed incompatible. An index value of zero means no version string is specified and is equivalent to the string _null.

l_flags
Specifies a set of 1-bit flags.

The l_flags field can have one or both of the following flags set:
LL_EXACT_MATCH At run time, use a unique ID composed of the l_time_stamp, l_checksum, and l_version fields to demand that the run-time dynamic shared library file match exactly the shared library file used at static link time.
LL_IGNORE_INT_VER At run time, ignore any version incompatibility between the dynamic shared library file and the shared library file used at static link time.

Normally, if neither LL_EXACT_MATCH nor LL_IGNORE_INT_VER bits are set, the dynamic loader requires that the version of the dynamic shared library match at least one of the colon separated version strings indexed by the l_version string table index.

The DT_MIPS_LIBLIST and DT_MIPS_LIBLISTNO entries of the dynamic section describe the attributes of the shared object list section.


9.3.10.2    Conflict Section (.conflict)

Each .conflict section is an array of indexes into the .dynsym section. Each index entry identifies a symbol that is multiply defined in either of the following ways:

The shared library files that the shared object file depends on are identified at static link time.

The symbols identified in this section must be resolved by the dynamic loader, even if the object is quickstarted. The dynamic loader resolves all references of a multiply-defined symbol to a single definition.

The .conflict section is an array of Elf32_Conflict elements:

typedef Elf32_Word Elf32_Conflict;

The DT_MIPS_CONFLICT and DT_MIPS_CONFLICTNO entries of the dynamic section describe the attributes of the conflict section.


9.3.10.3    Ordering of Sections

In order to take advantage of the quickstart capability, ordering constraints are imposed on the .rel.dyn section. The .rel.dyn section must have all local entries first, followed by the external entries. Within these subsections, the entries must be ordered by symbol index. This groups each symbol's relocations together.