Tuesday, November 19, 2019

[Linker Script Tutorial] $4 - Assigning Values to Symbols

You may assign a value to a symbol in a linker script. This will define the symbol and place it into the symbol table with a global scope.

1 Simple Assignments

You may assign to a symbol using any of the C assignment operators:
symbol = expression ;
symbol += expression ;
symbol -= expression ;
symbol *= expression ;
symbol /= expression ;
symbol <<= expression ;
symbol >>= expression ;
symbol &= expression ;
symbol |= expression ;
The first case will define symbol to the value of expression. In the other cases, symbol must already be defined, and the value will be adjusted accordingly.
The special symbol name ‘.’ indicates the location counter. You may only use this within a SECTIONS command. See Location Counter.
The semicolon after expression is required.
Expressions are defined below; see Expressions.
You may write symbol assignments as commands in their own right, or as statements within a SECTIONS command, or as part of an output section description in a SECTIONS command.
The section of the symbol will be set from the section of the expression; for more information, see Expression Section.
Here is an example showing the three different places that symbol assignments may be used:
floating_point = 0;
SECTIONS
{
  .text :
    {
      *(.text)
      _etext = .;
    }
  _bdata = (. + 3) & ~ 3;
  .data : { *(.data) }
}
In this example, the symbol ‘floating_point’ will be defined as zero. The symbol ‘_etext’ will be defined as the address following the last ‘.text’ input section. The symbol ‘_bdata’ will be defined as the address following the ‘.text’ output section aligned upward to a 4 byte boundary.


2 HIDDEN

For ELF targeted ports, define a symbol that will be hidden and won’t be exported. The syntax is HIDDEN(symbol = expression).
Here is the example from Simple Assignments, rewritten to use HIDDEN:
HIDDEN(floating_point = 0);
SECTIONS
{
  .text :
    {
      *(.text)
      HIDDEN(_etext = .);
    }
  HIDDEN(_bdata = (. + 3) & ~ 3);
  .data : { *(.data) }
}

In this case none of the three symbols will be visible outside this module.


3 PROVIDE

In some cases, it is desirable for a linker script to define a symbol only if it is referenced and is not defined by any object included in the link. For example, traditional linkers defined the symbol ‘etext’. However, ANSI C requires that the user be able to use ‘etext’ as a function name without encountering an error. The PROVIDE keyword may be used to define a symbol, such as ‘etext’, only if it is referenced but not defined. The syntax is PROVIDE(symbol = expression).
Here is an example of using PROVIDE to define ‘etext’:
SECTIONS
{
  .text :
    {
      *(.text)
      _etext = .;
      PROVIDE(etext = .);
    }
}
In this example, if the program defines ‘_etext’ (with a leading underscore), the linker will give a multiple definition error. If, on the other hand, the program defines ‘etext’ (with no leading underscore), the linker will silently use the definition in the program. If the program references ‘etext’ but does not define it, the linker will use the definition in the linker script.

Note - the PROVIDE directive considers a common symbol to be defined, even though such a symbol could be combined with the symbol that the PROVIDE would create. This is particularly important when considering constructor and destructor list symbols such as ‘__CTOR_LIST__’ as these are often defined as common symbols.


4 PROVIDE_HIDDEN


Similar to PROVIDE. For ELF targeted ports, the symbol will be hidden and won’t be exported.









No comments:

Post a Comment

Back to Top