Linker command file nightmare

Sebastian Huber sebastian.huber at embedded-brains.de
Fri Apr 3 15:19:23 UTC 2009


Hi,

currently we have a situation in which most BSPs have there own linker command
file (or more than one).  This is not good for maintainability.  Whenever a
update of the linker command file is necessary due to some GCC or binutils
changes we have to review many files.  It leads also to different startup
variants throughout the boards.  We need a way to reduce the complexity and
variants of linker command files.  The general idea is to have a base file for
each architecture (maybe it is even possible to use one for all architectures)
and board dependent files that define only the memory layout and usage of a
particular board.  One way to accomplish this is a recent feature of the GNU
linker (excerpt from the CVS documentation):

3.4.4 Assign alias names to memory regions
------------------------------------------

Alias names can be added to existing memory regions created with the
*note MEMORY:: command.  Each name corresponds to at most one memory
region.

     REGION_ALIAS(ALIAS, REGION)

   The `REGION_ALIAS' function creates an alias name ALIAS for the
memory region REGION.  This allows a flexible mapping of output sections
to memory regions.  An example follows.

   Suppose we have an application for embedded systems which come with
various memory storage devices.  All have a general purpose, volatile
memory `RAM' that allows code execution or data storage.  Some may have
a read-only, non-volatile memory `ROM' that allows code execution and
read-only data access.  The last variant is a read-only, non-volatile
memory `ROM2' with read-only data access and no code execution
capability.  We have four output sections:

   * `.text' program code;

   * `.rodata' read-only data;

   * `.data' read-write initialized data;

   * `.bss' read-write zero initialized data.

   The goal is to provide a linker command file that contains a system
independent part defining the output sections and a system dependent
part mapping the output sections to the memory regions available on the
system.  Our embedded systems come with three different memory setups
`A', `B' and `C':
Section            Variant A          Variant B          Variant C
.text              RAM                ROM                ROM
.rodata            RAM                ROM                ROM2
.data              RAM                RAM/ROM            RAM/ROM2
.bss               RAM                RAM                RAM
   The notation `RAM/ROM' or `RAM/ROM2' means that this section is
loaded into region `ROM' or `ROM2' respectively.  Please note that the
load address of the `.data' section starts in all three variants at the
end of the `.rodata' section.

   The base linker script `linkcmds.base' that deals with the output
sections follows.  It will be included in the system dependent
`linkcmds' file that describes the memory layout:
     SECTIONS
       {
         .text :
           {
             *(.text)
           } > REGION_TEXT
         .rodata :
           {
             *(.rodata)
           } > REGION_RODATA
         .data :
           {
             data_start = .;
             *(.data)
           } > REGION_DATA AT > REGION_DATA_LOAD
         data_size = SIZEOF(.data);
         data_load_start = LOADADDR(.data);
         .bss :
           {
             *(.bss)
           } > REGION_BSS
       }

   Now we need three different `linkcmds' files to define memory
regions and alias names.  They include also the `linkcmds.base' file
containing the output section definitions.  The content of `linkcmds'
for the three variants `A', `B' and `C':
`A'
     Here everything goes into the `RAM'.
          MEMORY
            {
              RAM : ORIGIN = 0, LENGTH = 4M
            }

          REGION_ALIAS("REGION_TEXT", RAM);
          REGION_ALIAS("REGION_RODATA", RAM);
          REGION_ALIAS("REGION_DATA", RAM);
          REGION_ALIAS("REGION_DATA_LOAD", RAM);
          REGION_ALIAS("REGION_BSS", RAM);

          INCLUDE linkcmds.base

`B'
     Program code and read-only data go into the `ROM'.  Read-write
     data goes into the `RAM'.  An image of the initialized data is
     loaded into the `ROM' and will be copied during system start into
     the `RAM'.
          MEMORY
            {
              ROM : ORIGIN = 0, LENGTH = 3M
              RAM : ORIGIN = 0x10000000, LENGTH = 1M
            }

          REGION_ALIAS("REGION_TEXT", ROM);
          REGION_ALIAS("REGION_RODATA", ROM);
          REGION_ALIAS("REGION_DATA", RAM);
          REGION_ALIAS("REGION_DATA_LOAD", ROM);
          REGION_ALIAS("REGION_BSS", RAM);

          INCLUDE linkcmds.base

`C'
     Program code goes into the `ROM'.  Read-only data goes into the
     `ROM2'.  Read-write data goes into the `RAM'.  An image of the
     initialized data is loaded into the `ROM2' and will be copied
     during system start into the `RAM'.
          MEMORY
            {
              ROM : ORIGIN = 0, LENGTH = 2M
              ROM2 : ORIGIN = 0x10000000, LENGTH = 1M
              RAM : ORIGIN = 0x20000000, LENGTH = 1M
            }

          REGION_ALIAS("REGION_TEXT", ROM);
          REGION_ALIAS("REGION_RODATA", ROM2);
          REGION_ALIAS("REGION_DATA", RAM);
          REGION_ALIAS("REGION_DATA_LOAD", ROM2);
          REGION_ALIAS("REGION_BSS", RAM);

          INCLUDE linkcmds.base

   It is possible to write a common system initialization routine to
copy the `.data' section from `ROM' or `ROM2' into the `RAM' if
necessary:
     #include <string.h>

     extern char data_start [];
     extern char data_size [];
     extern char data_load_start [];

     void copy_data(void)
     {
       if (data_start != data_load_start)
         {
           memcpy(data_start, data_load_start, (size_t) data_size);
         }
     }

End of documentation excerpt.

Unfortunately this feature is only available in the current CVS version of the
Binutils.

-- 
Sebastian Huber, Embedded Brains GmbH

Address : Obere Lagerstr. 30, D-82178 Puchheim, Germany
Phone   : +49 89 18 90 80 79-6
Fax     : +49 89 18 90 80 79-9
E-Mail  : sebastian.huber at embedded-brains.de
PGP     : Public key available on request

Diese Nachricht ist keine geschäftliche Mitteilung im Sinne des EHUG.



More information about the users mailing list