# 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. ![擷取選取區域_090](https://hackmd.io/_uploads/By-Rq6fTA.jpg) :::info Why can’t compiler do this? * Limited world view: sees one file, rather than all files ::: [jserv ppt](https://www.slideshare.net/slideshow/from-source-to-binary-how-gnu-toolchain-works/7528437#46) ## Link script 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: :::spoiler {state="open"} 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. ``` ::: :::spoiler {state="open"} 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. ::: :::spoiler {state="open"} 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/ .bss...etc) into specific memory region. :::info ==.==: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. ```c extern uint32_t _sidata; extern uint32_t data_size; ``` :::success 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](https://hackmd.io/_uploads/Hkbo02BpA.jpg) :::info ```gcc -Wl,-verbose file.c``` can help you to read gcc linker script. ::: ## Reference [from Source to Binary: How GNU Toolchain Works - jserv](https://www.slideshare.net/slideshow/from-source-to-binary-how-gnu-toolchain-works/7528437) [How A Compiler Works: GNU Toolchain - jserv](https://www.slideshare.net/slideshow/how-a-compiler-works-gnu-toolchain/45294966) [Link Script doc](https://sourceware.org/binutils/docs/ld/Scripts.html) [linker script 簡單教學](https://evshary.com/2018/06/02/linker-script-%E7%B0%A1%E5%96%AE%E6%95%99%E5%AD%B8/#%E7%B0%A1%E4%BB%8B) [Linker script 簡介](https://yodalee.blogspot.com/2015/04/linker-script.html) [Linker Script初探 - GNU Linker Ld手冊略讀](https://wen00072.github.io/blog/2014/03/14/study-on-the-linker-script/) [Bare metal embedded lecture-4: Writing linker scripts and section placement](https://www.youtube.com/watch?v=B7oKdUvRhQQ&t=254s)