Go to main content

Oracle® Solaris 11.3 Linkers and Libraries Guide

Exit Print View

Updated: March 2018
 
 

Link-Editor Internals: Section and Segment Processing

The internal process used by the link-editor to assign sections to output segments is described here. This information is not necessary in order to use mapfiles. This information is primarily of interest to those interested in link-editor internals, and for those who want a deep understanding of how segment mapfile directives are interpreted and executed by the link-editor.

Section To Segment Assignment

The process of assigning input sections to output segments involves the following data structures.

  • Input Sections

    Input sections are read from relocatable objects input to the link editor. Some are examined and processed by the link-editor, while others are simply passed to the output without examination of their contents (e.g. PROGBITS).

  • Output Sections

    Output sections are sections that are written to the output object. Some are formed from the concatenation of sections passed through from the input objects. Others, such as symbol tables and relocation sections are generated by the link-editor itself, often incorporating information read from the input objects.

    When the link-editor passes an input section through to become an output section, the section usually retains the input section name. However, the link-editor can modify the name in certain circumstances. For instance, the link-editor translates input section names of the form name%XXX, dropping the % character and any characters following from the output section name.

  • Segment Descriptors

    The link-editor maintains a list of known segments. This list initially contains the predefined segments, described in Predefined Segments. When a LOAD_SEGMENT, NOTE_SEGMENT, or NULL_SEGMENT mapfile directive is used to create a new segment, an additional segment descriptor for the new segment is added to this list. The new segment goes at the end of the list following other segments of the same type, unless explicitly ordered by setting a virtual address (LOAD_SEGMENT), or by using the SEGMENT_ORDER directive.

    When creating the output object, the link-editor only creates program headers for the segments that receive a section. Empty segments are quietly ignored. Hence, user specified segment definitions have the power to completely replace the use of the predefined segments definitions, despite the fact that there is no explicit facility for removing a segment definition from the link-editor list.

  • Entrance Criteria

    A set of section attributes required in order to place that section in a given segment is called an entrance criterion for the segment. A given segment can have an arbitrary number of entrance criteria.

    The link-editor maintains an internal list of all defined entrance criteria. This list is used to place sections into segments, as described below. Each mapfile inserts the entrance criterion created by the ASSIGN_SECTION attribute to the LOAD_SEGMENT, NOTE_SEGMENT, or NULL_SEGMENT mapfile directive at the top of this list, in the order they are encountered in the mapfile. The entrance criteria for the built-in segments discussed in Predefined Segments are placed at the end of this list. Therefore, mapfile defined entrance criteria take precedence over the built in rules, and mapfiles at the end of the command line take precedence over those found at the beginning.

For each section written to the output object, the link-editor performs the following steps to place the section in an output segment.

  1. The attributes of the section are compared to each record in the internal entrance criteria list, starting at the head of the list and considering each entrance criterion in turn. A match occurs when every attribute in the entrance criterion matches exactly, and the segment associated with the entrance criterion is not disabled. The search stops with the first entrance criterion that matches, and the section is directed to the associated segment.

    If no Entrance Criterion match is found, the section is placed at the end of the output file after all other segments. No program header entry is created for this information. Most non-allocable sections (e.g. debug sections) end up in this area.

  2. When the section falls into a segment, the link-editor checks the list of existing output sections in that segment as follows.

    If the section attribute values match those of an existing output section exactly, the section is placed at the end of the list of sections associated with that output section.

    If no matching output section is found, a new output section is created with the attributes of the section being placed, and the input section is placed within the new output section. This new output section is positioned within the segment following any other output sections with the same section type, or at the end of the segment if there are none.


    Note -  If the input section has a user-defined section type value between SHT_LOUSER and SHT_HIUSER, the section is treated as a PROGBITS section. No method exists for naming this section type value in the mapfile, but these sections can be redirected using the other attribute value specifications (section flags, section name) in the entrance criterion.

Mapfile Directives for Predefined Segments and Entrance Criteria

The link-editor provides a predefined set of output segment descriptors and entrance criteria, as described in Predefined Segments. The link-editor already knows about these sections, so mapfile directives are not required to create them. The mapfile directives that could be used to produce them are shown for illustrative purposes, and as an example of a relatively complex mapfile specification. Mapfile segment directives can be used to modify or augment these built in definitions.

Normally, section to segment assignments are done within a single segment directive. However, the predefined sections have more complex requirements, requiring their entrance criteria to be processed in a different order than the segments are laid out in memory. Two passes are used to achieve this, the first to define all the segments in the desired order, and the second to establish entrance criteria in an order that will achieve the desired results. It is rare for a user mapfile to require this strategy.

        # Predefined segments and entrance criteria for the Oracle Solaris
        # link-editor
        $mapfile_version 2

        # The lrodata and ldata segments only apply to x86-64 objects.
        # Establish amd64 as a convenient token for conditional input
        $if _ELF64 && _x86
        $add amd64
        $endif

        # Pass 1: Define the segments and their attributes, but
        # defer the entrance criteria details to the 2nd pass.
        LOAD_SEGMENT text {
                FLAGS = READ EXECUTE;
        };
        LOAD_SEGMENT data {
                FLAGS = READ WRITE EXECUTE;
        };
        LOAD_SEGMENT bss {
                DISABLE;
                FLAGS=DATA;
        };
        $if amd64
        LOAD_SEGMENT lrodata {
                FLAGS = READ
        };
        LOAD_SEGMENT ldata {
                FLAGS = READ WRITE;
        };
        $endif
        NOTE_SEGMENT note;
        NULL_SEGMENT extra;

        # Pass 2: Define ASSIGN_SECTION attributes for the segments defined
        # above, in the order the link-editor should evaluate them.

        # All SHT_NOTE sections go to the note segment
        NOTE_SEGMENT note {
                ASSIGN_SECTION {
                        TYPE = NOTE;
                };
        };
        $if amd64
        # Medium/large model x86-64 readonly sections to lrodata
        LOAD_SEGMENT lrodata {
                ASSIGN_SECTION {
                        FLAGS = ALLOC AMD64_LARGE;
                };
        };
        $endif

        # text receives all readonly allocable sections
        LOAD_SEGMENT text {
                ASSIGN_SECTION {
                        FLAGS = ALLOC !WRITE;
                };
        };

        # If bss is enabled, it takes the writable NOBITS sections
        # that would otherwise end up in ldata or data.
        LOAD_SEGMENT bss {
                DISABLE;
                ASSIGN_SECTION {
                        FLAGS = ALLOC WRITE;
                        TYPE = NOBITS;
                };
        };

        $if amd64
        # Medium/large model x86-64 writable sections to ldata
        LOAD_SEGMENT ldata {
                ASSIGN_SECTION {
                        FLAGS = ALLOC WRITE AMD64_LARGE;
                };
                ASSIGN_SECTION {
                        TYPE = NOBITS;
                        FLAGS = AMD64_LARGE
                };
        };
        $endif

        # Any writable allocable sections not taken above go to data
        LOAD_SEGMENT data {
                ASSIGN_SECTION {
                        FLAGS = ALLOC WRITE;
                };
        };

        # Any section that makes it to this point ends up at the
        # end of the object file in the extra segment. This accounts
        # for the bulk of non-allocable sections.
        NULL_SEGMENT extra {
                ASSIGN_SECTION;
        };