Go to main content

Oracle® Solaris 11.4 Linkers and Libraries Guide

Exit Print View

Updated: March 2019
 
 

Mapfile Structure and Syntax

Mapfile directives can span more than one line, and can have any amount of white space, including new lines.

For all syntax discussions, the following notations apply.

  • Spaces, or newlines, can appear anywhere except in the middle of a name or value.

  • Comments beginning with a hash character (#) and ending at a newline can appear anywhere that a space can appear. Comments are not interpreted by the link-editor, and exist solely for documentation purposes.

  • All directives are terminated by a semicolon (;). The final semicolon within a {....} section can be omitted.

  • All entries in constant width, all colons (:), semicolons (;), assignment (=, +=, -=), and {....} brackets are typed in literally.

  • All entries in italics are substitutable.

  • [ .... ]  brackets are used to delineate optional syntax. The brackets are not literal, and do not appear in the actual directives.

  • Names are case sensitive strings. Figure 2, Table 2, Names And Other Widely Used Strings Found In Mapfiles contains a list of names and other strings commonly found in mapfiles. Names can be specified in three different forms.

    • Unquoted

      An unquoted name is a sequence of letters and digits. The first character must be a letter, followed by zero or more letters or digits. The characters percent (%), slash (/), period (.), and underscore (_) count as a letter. The characters dollar ($), and hyphen (-) count as a digit.

    • Single Quotes

      Within single quotes ('), a name can contain any character other than a single quote, or newline. All characters are interpreted as literal characters. This form of quoting is convenient when specifying file paths, or other names that contain normal printable characters that are not allowed in an unquoted name.

    • Double Quotes

      Within double quotes ("), a name can contain any character other than a double quote, or newline. Backslash(\) is an escape character which operates similarly to the way it is used in the C programming language within a string literal. Characters prefixed by a backslash are replaced by the character they represent, as shown in Figure 1, Table 1, Double Quoted Text Escape Sequences. Any character following a backslash, other than the ones shown in Figure 1, Table 1, Double Quoted Text Escape Sequences is an error.

  • value represents a numeric value, and can be hexadecimal, decimal, or octal, following the rules used by the C language for integer constants. All values are unsigned integer values, and are 32-bit for 32-bit output objects, and 64-bit for 64-bit output objects.

  • segment_flags specify memory access permissions as a space separated list of one or more of the values given in Figure 3, Table 3, Segment Flags, which correspond to the PF_ values defined in <sys/elf.h>.

Table 1  Double Quoted Text Escape Sequences
Escape Sequence
Meaning
\a
alert (bell)
\b
backspace
\f
formfeed
\n
newline
\r
return
\t
horizontal tab
\v
vertical tab
\\
backslash
\'
single quote
\"
double quote
\ooo
An octal constant, where ooo is one to three octal digits (0....7)
Table 2  Names And Other Widely Used Strings Found In Mapfiles
Name
Purpose
segment_name
Name of ELF segment
section_name
Name of ELF section
symbol_name
Name of ELF symbol
file_path
A UNIX file path of slash (/) delimited names used to reference an ELF object, or an archive that contains ELF objects
file_basename
Final component (basename(1)) of a file_path
objname
Either a file_basename or the name of an object contained within an archive
soname
Sharable object name, as used for the SONAME of a sharable object (e.g. libc.so.1)
version_name
Name of a symbol version, as used within an ELF versioning section
inherited_version_name
Name of a symbol version inherited by another symbol version
Table 3  Segment Flags
Flag Value
Meaning
READ
Segment is readable
WRITE
Segment is writable
EXECUTE
Segment is executable
0
All permission flags are cleared
DATA
The combination of READ, WRITE, and EXECUTE flags appropriate for a data segment on the target platform
STACK
The combination of READ, WRITE, and EXECUTE flags appropriate for the target platform, as defined by the platform ABI

Mapfile Version

The first non-comment, non-empty, line in a mapfile is expected to be a mapfile version declaration. This declaration establishes the version of the mapfile language used by the remainder of the file. The mapfile language documented in this manual is version 2.

        $mapfile_version 2

A mapfile that does not begin with a version declaration is assumed to be written in the original mapfile language defined for System V Release 4 UNIX (SVR4) by AT&T. The link-editor retains the ability to process such mapfiles. Their syntax is documented in System V Release 4 (Version 1) Mapfiles.

Conditional Input

Lines within a mapfile can be conditionalized to only apply to a specific ELFCLASS (32 or 64-bit) or machine type.

        $if expr
        ....
        [$elif expr]
        ....
        [$else]
        ....
        $endif

A conditional input expression evaluates to a logical true or false value. Each of the directives ($if, $elif, $else, and $endif) appear alone on a line. The expressions in $if and subsequent $elif lines are evaluated in order until an expression that evaluates to true is found. Text following a line with a false value is discarded. The text following a successful directive line is treated normally. Text here refers to any material, that is not part of the conditional structure. Once a successful $if or $elif has been found, and its text processed, succeeding $elif and $else lines, together with their text, are discarded. If all the expressions are zero, and there is a $else, the text following the $else is treated normally.

The scope of an $if directive cannot extend across multiple mapfiles. An $if directive must be terminated by a matching $endif within the mapfile that uses the $if directive, or the link-editor issues an error.

The link-editor maintains an internal table of names that can be used in the logical expressions evaluated by $if and $elif. At startup, this table is initialized with each of the names in the following table that apply to the output object being created.

Table 4  Predefined Conditional Expression Names
Name
Meaning
_ELF32
32-bit object
_ELF64
64-bit object
_ET_DYN
shared object
_ET_EXEC
executable object
_ET_REL
relocatable object
_sparc
SPARC machine (32 or 64-bit)
_x86
x86 machine (32 or 64-bit)
true
Always defined

The names are case sensitive, and must be used exactly as shown. For example, true is defined, but TRUE is not. Any of these names can be used by themselves as a logical expression. For example.

        $if _ELF64
        ....
        $endif

This example will evaluate to true, and allow the link-editor to process the enclosed text, when the output object is 64-bit. Although numeric values are not allowed in these logical expressions, a special exception is made for the value 1, which evaluates to true, and 0 for false.

Any undefined name evaluates to false. It is common to use the undefined name false to mark lines of input that should be unconditionally skipped.

        $if false
        ....
        $endif

More complex logical expressions can be written, using the operators shown in the following table.

Table 5  Conditional Expression Operators
Operator
Meaning
&&
Logical AND
||
Logical OR
( expr )
Sub-expression
!
Negate boolean value of following expression

Expressions are evaluated from left to right. Sub-expressions are evaluated before enclosing expressions.

For example, the lines in the following construct will be evaluated when building 64-bit objects for x86 platforms.

        $if _ELF64 && _x86
        ....
        $endif

The $add directive can be used to add a new name to the link-editor's table of known names. Using the previous example, it might be convenient to define the name amd64 to stand for 64-bit x86 objects, in order to simplify $if directives.

        $if _ELF64 && _x86
        $add amd64
        $endif

This can be used to simplify the previous example.

        $if amd64
        ....
        $endif

New names can also be added to the link-editor's table of known names by using the link-editor's –z mapfile-add option. This option is useful when mapfile input needs to be conditionally enabled based on an attribute of the external environment, such as the compiler being used.

The $clear directive is the reverse of the $add directive. It is used to remove names from the internal table.

        $clear amd64

The effect of the $add directive persists beyond the end of the mapfile that uses $add, and is visible to any subsequent mapfile that is processed by the link-editor in the same link operation. If this is not desired, use $clear at the end of the mapfile containing the $add to remove the definition.

Finally, the $error directive causes the link-editor to print all remaining text on the line as a fatal error, and halt the link operation. The $error directive can be used to ensure that a programmer porting an object to a new machine type will not be able to silently build an incorrect object that is missing a necessary mapfile definition.

        $if _sparc
        ....
        $elif _x86
        ....
        $else
        $error unknown machine type
        $endif

C language programmers will recognize that the syntax used for mapfile conditional input resembles that of the C preprocessor macro language. This similarity is intentional. However, mapfile conditional input directives are by design considerably less powerful than those provided by the C preprocessor. They provide only the most basic facilities required to support linking operations in a cross platform environment.

Among the significant differences between the two languages.

  • The C preprocessor defines a full macro language, and the macros are applied to both the source text, and to the expressions evaluated by the #if and #elif preprocessor statements. Link-editor mapfiles do not implement a macro capability.

  • The expressions evaluated by the C preprocessor involve numeric types, and a rich set of operators. Mapfile logical expressions involve boolean true and false values, and a limited set of operators.

  • C preprocessor expressions involve arbitrary numeric values, possibly defined as macros, and defined() is used to evaluate whether a given macro is defined or not, yielding a true (nonzero) or false (zero) value. Mapfile logical expressions only manipulate boolean values, and names are used directly without a defined() operation. The specified names are considered to be true if they exist in the link-editor's table of known names, and false otherwise.

Those requiring more sophisticated macro processing should consider using an external macro processor, such as m4 (1) .

Directive Syntax

Mapfile directives exist to specify many aspects of the output object. These directives share a common syntax, using name value pairs for attributes, and {....} constructs to represent hierarchy and grouping.

The syntax of mapfile directives is based on the following generic forms.

The simplest form is a directive name without a value.

        directive;

The next form is a directive name with a value, or a white space separated list of values.

        directive = value....;

In addition to the "=" assignment operator shown, the "+=" and "-=" forms of assignment are allowed. The "=" operator sets the given directive to the given value, or value list. The "+=" operator is used to add the value on the right hand side to the current value, and the "-=" operator is used to remove values.

More complex directives manipulate items that take multiple attributes enclosed within {....} brackets to group the attributes together as a unit.

        directive [name] {
                attribute [directive = value];
        ....
        } [name];

There can be a name before the opening brace ({), which is used to name the result of the given statement. Similarly, one or more optional names can follow the closing brace (}), prior to the terminating semicolon (;). These names are used to express that the defined item has a relationship with other named items.

Note that the format for attributes within a grouping use the same syntax as simple directives with a value, with an assignment operator (=, +=, -=) followed by a value, or white space separated list of values, terminated with a semicolon (;).

A directive can have attributes that in turn have sub-attributes. In such cases, the sub-attributes are also grouped within nested {....} brackets to reflect this hierarchy.

        directive [name] {
                attribute {
                        subattribute [= value];
                ....
                };
        } [name....];

The mapfile syntax grammar puts no limit on the depth to which such nesting is allowed. The depth of nesting depends solely on the requirements of the directive.

MATCH and MATCHREF Expressions

MATCH and MATCHREF expressions provide the ability to match strings against a pattern, and to generate new strings that incorporate substrings from the original string. Their specific use is described by the documentation for each mapfile directive that supports these expressions, in the sections that follow.

A MATCH expression allows strings to be matched against a pattern, delimited by slash (/) characters.

        MATCH(g/match-pattern/[i])
        MATCH(r/match-pattern/[i])
        MATCH(t/match-pattern/[i])

The type of matching to be done is specified by a single character code that precedes the pattern. The type of matching to be done defines the syntax of the match-pattern.

g

Glob pattern matching. The match-pattern is specified using the glob syntax described by fnmatch(7).

r

Regular Expression matching. The match-pattern is specified using the extended regular expression (ERE) syntax described by regex(7).

t

Plain text matching. The match-pattern follows the standard mapfile syntax for double quoted strings, where the slash (/) character is used in place of the usual (") quote character. The rules for double quoted strings are described in Mapfile Structure and Syntax.

By default, case sensitive pattern matching is employed. Case insensitive matching can be specified by specifying the character 'i' immediately following the closing slash (/) character.

The MATCHREF expression is used to generate a new string, based on a template string, which can incorporate substrings matched by a previous MATCH. MATCHREF, particularly in conjunction with a regular expression MATCH, provides a flexible mechanism for renaming.

        MATCHREF(/template-string/)

The template-string follows the standard mapfile syntax for double quoted strings, where the slash (/) character is used in place of the usual quote (") character. The rules for double quoted strings are described in Mapfile Structure and Syntax.

Within template-string, substrings to be copied from the related MATCH expression are indicated by tokens of the form ${cN}, where c is a single character that identifies a MATCH directive, and N is an integer that identifies a substring within that MATCH. The identifier characters allowed with MATCHREF depend on the mapfile directive that employs the MATCHREF. The documentation for each mapfile directive that supports the use of MATCH and MATCHREF defines the set of MATCHREF identifier characters that are allowed by that directive.

The string that results from a MATCHREF expression consists of the template-string, with all ${cN} tokens replaced by the MATCH substrings that they refer to. The zeroth token, ${c0}, represents the full string matched by the MATCH expression, and is supported with all MATCH expressions. Tokens specifying a value of n larger than 0 are only supported with regular expression MATCH expressions. When used with a regular expression, a value of n larger than 0 corresponds to the nth open parenthesis found in the MATCH pattern, and represents the substring matched by that subpart of the regular expression.

If a given ${cN} does not correspond to any MATCH substring, an empty ("") string is substituted. This occurs for any non-zero value of n with glob or text matching, or for a value of n greater than the number of parenthesis within a regular expression pattern.

Example: Redirecting Sections

Normally, the link-editor copies input sections to the output object, creating output sections with the same names as the input. The LOAD_SEGMENT directive allows the use of MATCH and MATCHREF to match sections by name, and optionally to redirect them to differently named output sections. The following mapfile redirects all non-writable allocable sections with a name staring with the string ".appXtext.", and redirects each section to an output section named by replacing this prefix with ".text.".

        $mapfile_version 2

        LOAD_SEGMENT text {
                ASSIGN_SECTION apptext {
                        IS_NAME = MATCH(r/^\.appXtext\.(.*)$/);
                        FLAGS = ALLOC !WRITE;
                        OUTPUT_SECTION {
                                NAME = MATCHREF(/.text.${n1}/);
                        };
                };
        };

Example: Matching and Renaming Symbols

The SYMBOL_SCOPE and SYMBOL_VERSION directives allow the use of MATCH and MATCHREF to match symbols by name, and optionally to rename them. The following mapfile matches all symbols starting with the letter "i" followed by an integer value, and gives them protected scope.

        $mapfile_version 2

        SYMBOL_SCOPE {
            protected:
                MATCH(r/^i[0-9]+$/);

        };
                

The following mapfile renames all symbols starting with the letter "i" followed by an integer value to have the prefix "interface_", and gives them protected scope.

        $mapfile_version 2

        SYMBOL_SCOPE {
            protected:
                MATCH(r/^i([0-9]+)$/)
                    { RENAME = MATCHREF(/interface_$(n1}/) };
        };