#### 3.4.4 Assign alias names to memory regions

Alias names can be added to existing memory regions created with the 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 that deals with the output sections follows. It includes the system dependent `linkcmds.memory` file that describes the memory layout:

    INCLUDE linkcmds.memory

    SECTIONS
      {
        .text :
          {
            *(.text)
          } > REGION_TEXT
        .rodata :
          {
            *(.rodata)
            rodata_end = .;
          } > REGION_RODATA
        .data : AT (rodata_end)
          {
            data_start = .;
            *(.data)
          } > REGION_DATA
        data_size = SIZEOF(.data);
        data_load_start = LOADADDR(.data);
        .bss :
          {
            *(.bss)
          } > REGION_BSS
      }

Now we need three different `linkcmds.memory` files to define memory regions and alias names. The content of `linkcmds.memory` 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_BSS", RAM);

`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_BSS", RAM);

`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_BSS", RAM);

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);
        }
    }