Contents|Index|Previous|Next

The linker script

The linker script accomplishes the following processes to result.

- Sets up the memory map for the application.
When your application is loaded into memory, it allocates some RAM, some disk space for I/O, and some registers. The linker script makes a memory map of this memory allocation which is important to embedded systems because, having no OS, you have the ability then to manage the behavior of the chip.
- For G++, sets up the constructor and destructor tables.
The actual section names vary depending on your object file format. For a.out and coff, the three main sections are .text, .data and .bss.
- Sets the default values for variables used elsewhere.

These default variables are used by sbrk()and the crt0 file, typically called by _bss_start and _end.

There are two ways to ensure the memory map is correct.

- By having the linker create the memory map by using the option, -Map.
- By, after linking, using the nm utility to check critical addresses like start, bss_end and _etext.

The following is an example of a linker script for an m68k-based target board.

1.
Use the STARTUP command which loads the file so that it executes first.

    STARTUP(crt0.o)

The m68k-coff configuration default does not link in crt0.o because it assumes that a developer has crt0. This behavior is controlled in the config file for each architecture in a macro called STARTFILE_SPEC. If STARTFILE_SPEC is set to NULL, gcc formats its command line and doesn’t add crt0.o. Any filename can be specified with STARTUP although the default is always crt0.o.

If you use only ld to link, you control whether or not to link in crt0.o on the command line.

If you have multiple crt0 files, you can leave STARTUP out, and link in crt0.o in the makefile or use different linker scripts. Sometimes this option is used to initialize floating point values or to add device support.

2.
Using GROUP, load the specified file.

    GROUP(-lgcc-liop-lc)

In this case, the file is a relocated library that contains the definitions for the low-level functions needed by libc.a. The file to load could have also been specified on the command line, but as it’s always needed, it might as well be here as a default.

3.
SEARCH_DIR specifies the path in which to look for files.

    SEARCH_DIR(.)

4.
Using _DYNAMIC, specify whether or not there are shared dynamic libraries. In the following example’s case, there are no shared libraries.

    __DYNAMIC = 0;

5.
Set _stack, the variable for specifying RAM for the ROM monitor.

6.
Specify a name for a section that can be referred to later in the script. In the following example’s case, it’s only a pointer to the beginning of free RAM space with an upper limit at 2M. If the output file exceeds the upper limit, MEMORY produces an error message. First, in this case, we’ll set up the memory map of the board’s stack for high memory for both the rom68k and mon68k monitors.

    MEMORY
    {
        ram     :     ORIGIN = 0x10000, LENGTH = 2M
    }

- Setting up constructor and destructor tables for G++

1.
Set up the .text section, using the following example’s input.

    SECTIONS
    {
       .text :
       {
          CREATE_OBJECT_SYMBOLS
          *(.text)
          etext = .;
          __CTOR_LIST__ = .;
          LONG((__CTOR_END__ - __CTOR_LIST__) / 4 - 2)
          *(.ctors)
          LONG(0)
          __CTOR_END__ = .;
          __DTOR_LIST__ = .;

          LONG((__DTOR_END__ - __DTOR_LIST__) / 4 - 2)
          *(.dtors)
          LONG(0)
          __DTOR_END__ = .;
          *(.lit)
          *(.shdata) }
       > ram
       .shbss SIZEOF(.text) + ADDR(.text) : {
          *(.shbss)
       }

In a coff file, all the actual instructions reside in .text for also setting up the constructor and destructor tables for G++. Notice that the section description redirects itself to the RAM variable that was set up earlier.

2.
Set up the .data section.

       .talias : { } > ram
       .data : {
       *(.data)
       CONSTRUCTORS
       _edata = .;
    } > ram

In a coff file, this is where all of the initialized data goes. CONSTRUCTORS is a special command used by ld.

- Setting default values for variables, _bss_start and _end

Set up the .bss section:

       .bss SIZEOF(.data) + ADDR(.data) :
       {
       __bss_start = ALIGN(0x8);
       *(.bss)
       *(COMMON)
          end = ALIGN(0x8);
          _end = ALIGN(0x8);
          __end = ALIGN(0x8);
       }
       .mstack : { } > ram
       .rstack : { } > ram
       .stab . (NOLOAD) :
       {
          [ .stab ]
       }
       .stabstr . (NOLOAD) :
       {
          [ .stabstr ]
       }
    }

In a coff file, this is where uninitialized data goes. The default values for _bss_start and _end are set here for use by the crt0 file when it zeros the .bss section.