Linker

What is linker

What does the linker do?

  1. Collect together all pieces of a program
  2. Coalesce like segments
  3. Fix addresses of code and data so the program can run

So linker is for linking object code and library to elf file, like the following figure.

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

Why can’t compiler do this?

  • Limited world view: sees one file, rather than all files

jserv ppt

The linker needs a script to discript how does the different sections in object should be merged.

Linker script includes:

  1. code and data map to memory address and memory size information.
  2. how do sections in these object files map to create a binary file.

main command section:

ENTRY:
  • this is used to set "Entry point" information for elf file header
  • Not mandatory, if not existing, the linker will use .text section or address 0 for start entry.
x86 use ENTRY(_start) for default.
MEMORY:
  • Describing the different memories present in and their start address and size information
  • The linker uses these informations mentioned in this command to assign addresses to merged sections.
  • This also helps linker to calculate total code and data memory consumed
  • Calculating and fine-tune various memorise available and allow different sections to use different memory.
SECTIONS:
  • Creating different output sections in the final elf
  • Instructing the linker how to merge the input sections to an output section.
  • Controling different output sections ordering appear in the elf file.
  • Placement the section (.text/ .bssetc) into specific memory region.

.:Location counter

  • This symbol means the current location(address)
  • The location counter is incremented by the szie of the output section

Detail command section:

ENTRY

ENTRY($ENTRY_NAME)

MEMORY

MEMORY
{
    $name(attribute): ORIGIN=$start_address, LENGTH=$memory_size
}

ORIGIN, LENGTH are keywords.
$name, $start_address, $memory_size are varialbes

Attribute will be:

attirbute meaning
R read-only
W read/write
X contain executeable code
A Allocated section
I Initialize section
L the same as I
! invert ther sense of any of the following attributes.

Example: linkcmds.memory

MEMORY 
{
    FLASH(rx) : ORIGIN = 0x08000000, LENGTH = 1024K
    SRAM1(rwx) : ORIGIN = 0x20000000, LENGTH = 116K
    SRAM2(rwx) : ORIGIN = 0x20000000+116K-4, LENGTH = 16K
}

REGION_ALIAS("REGION_TEXT", SRAM1);
REGION_ALIAS("REGION_RODATA", FLASH);
REGION_ALIAS("REGION_DATA", SRAM1);
REGION_ALIAS("REGION_BSS", SRAM2);

You can use expression to Calculate the starting address.

SECTIONS

SECTION [address] [(type)] :
  [AT(lma)]
  [ALIGN(section_align) | ALIGN_WITH_INPUT]
  [SUBALIGN(subsection_align)]
  [constraint]
  {
    output-section-command
    output-section-command
    …
  } [>region] [AT>lma_region] [:phdr :phdr …] [=fillexp]

  • What is LAM/ VMA:
LMA (Load Memory Address) VMA (Virtual Memory Address)
memory ROM/Flash RAM
meaning saving the code section executing the code section
  • AT(LMA): this section should load data form LAM to VMA
  • AT>lma_region: load the section to LAM region.

Example:

INCLUDE linkcmds.memory

SECTIONS
{
    .text :
    {
        // .=VMA
        // _stext = .;
        *(.text)
        end_of_text = .;
        // _etext = .;
    } > REGION_TEXT
    .rodata :
    {
        *(.rodata)
        rodata_end = .;
        // _erodata = .;
    } > REGION_RODATA
    .data : AT (rodata_end)
    {
        
        data_start = .;
        *(.data)
        _edata = .;
    } > REGION_DATA
    data_size = SIZEOF(.data); // this can export the data_size to other c file.
    data_load_start = LOADADDR(.data);
    .bss :
    {
        _sbss = .;
        *(.bss)
        
    } > REGION_BSS
    
    // This is for only some specific files 
    // you want to add in this section
    .include_file : 
    {
        foo.o(.include_file)
    }
    
    // This is for only some specific files
    // you do not want to add in this section
    .exclude_file
    {
        *(EXCLUDE_FILE(*foo.o *bar.o).exclude_file)
    }
    
}

for export value, we can use these symbol.

extern uint32_t _sidata;
extern uint32_t data_size;

PROVIDE(_sdata = .): using the command can prevent redefine problem in C and linker script.

After linker script

Let we take a example

test.ld

MEMORY
{
  FLASH(rx): ORIGIN = 0x08000000, LENGTH = 128K
  SRAM1(rwx): ORIGIN = 0x20000000, LENGTH = 20K
}

SECTIONS
{
	. = 0x10000;
	.text : { 
		*(.text) 
	} > FLASH
	. = 0x8000000;
	.data : 
	{ 
		*(.data) 
	} > FLASH AT > SRAM1
	.bss : 
	{ 
		*(.bss) 
	} AT > SRAM1
}

Use ld -T test.ld main.o test.o to build output file, the using objdump -h a.out to get sections.


a.out:     file format elf64-x86-64

Sections:
Idx Name          Size      VMA               LMA               File off  Algn
  0 .text         0000004f  0000000008000000  0000000008000000  00001000  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  1 .eh_frame     00000058  0000000008000050  0000000008000050  00001050  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  2 .note.gnu.property 00000020  00000000080000a8  00000000080000a8  000010a8  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  3 .data         00000004  00000000080000c8  0000000020000000  000010c8  2**2
                  CONTENTS, ALLOC, LOAD, DATA
  4 .bss          00000004  0000000020000004  0000000020000004  00002004  2**2
                  ALLOC
  5 .comment      0000002b  0000000000000000  0000000000000000  000010cc  2**0
                  CONTENTS, READONLY

we can see that ".text" at VMA address is 0000000008000000, this is mapping to FLASH(rx): ORIGIN = 0x08000000, LENGTH = 128K and .text : { *(.text) } > FLASH

the ".data" section is the same, VMA is following prevous section and LMA maps to 0000000020000000

So, the the program will be loaded by follow layout
擷取選取區域_092

gcc -Wl,-verbose file.c can help you to read gcc linker script.

Reference

from Source to Binary: How GNU Toolchain Works - jserv

How A Compiler Works: GNU Toolchain - jserv

Link Script doc

linker script 簡單教學

Linker script 簡介

Linker Script初探 - GNU Linker Ld手冊略讀

Bare metal embedded lecture-4: Writing linker scripts and section placement