背景知識:
- linker: 將多個 input files 輸出為一個 output file.
- output file 與 input files 的格式是一種特殊資料格式稱做 object file format (目的檔格式),每個檔案則稱做 object file (目的檔),輸出檔則常稱做 executable (可執行檔),當然也能稱為 object file。
- 每個 object file 都有一個 section list。
- input section: 在 input file 的 section。
- output section: 在 output file 的 section。
Sections:
- 每個 section 在 object file 中都有至少有 名子 (name) 跟 大小 (size)
- 幾乎每個 section 都還會有資料,稱做 section contents。
- section 可以被標記為 LOADABLE,表示這些 contents 在 output file (executable) 運行時需要被載入到記憶體當中。
- section 可以被標記為 ALLOCATABLE,當 (翻書)
- 非 LOADABLE 或是 ALLOCATABLE 的 section,通常是裝載著 debugging information。
Section Address
- 每個 loadable 或是 allocatable output section 都有兩個 addresses。
- VMA (virtual memory address): 當 output file 運作時,section 會得到這個 address。
- LMA (load memory address): 當 section 被載入 (loaded) 時,會放置到這個 address。
- 通常時候 VMA = LMA。
- 舉例不相同的時候: 當 data section 被載入到 ROM,接著當程式開始 starts up 時再被 copy 到 RAM 內。這個例子 ROM address 會是 LMA,RAM 位置會是 VMA。
- 可用
objdump -h
觀察上述事實:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
> arm–none–eabi–objdump –h hello.elf hello.elf: file format elf32–littlearm Sections: Idx Name Size VMA LMA File off Algn 0 .foo 00000014 00080000 00080000 00020000 2**2 CONTENTS, ALLOC, LOAD, DATA 1 .text 000000d8 00000000 00000000 00010000 2**2 CONTENTS, ALLOC, LOAD, READONLY, CODE 2 .rodata 00000016 000000d8 000000d8 000100d8 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA 3 .comment 0000001d 00000000 00000000 00020014 2**0 CONTENTS, READONLY 4 .ARM.attributes 00000033 00000000 00000000 00020031 2**0 CONTENTS, READONLY |
簡單範例:
通常 linker script 都是很和藹可親的。
舉例而言,你的程式有程式碼、初始化變數與未初始化變數,他們分別會放在不同的 section: .text
、.data
、.bss
之中。而我們想要把 code 放到 0x10000
,data 放到 0x8000000
,以下就是符合我們要求的 linker script
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
SECTIONS { . = 0x10000; .text : { *(.text) } . = 0x8000000; .data : { *(.data) } .bss : { *(.bss) } } |
以下逐一講解各行意義:
- 第一行:使用
SECTIONS
keyword 來表示開始宣告 SECTIONS。 - 第三行:
.
是 linker script 中非常重要的東西,稱做 location counter。location counter 表示目前的 location,當從SECTIONS
開始的時候,其初始值為 0,location counter 會隨著 output section 的增加而增加,並且可以對 location counter 賦值。第二行就是將 location counter 移動到(賦值)0x10000。
- 第四行:定義一個 output section
.text
在大括號裏面,可以擺放想要放入這個 section 的 contents。 - 第六行:將所有 input files 的 .text input section 放入這個地方。
*
是一個 wildcard 符號,會比對所有符合的檔名。 - 當然,因為
.text
在定義的時候,location counter 是在 0x10000,因此 linker 會將 output file 中的.text
從 0x10000 開始。 - 第八行:將 location counter 移動到 0x8000000。
- 後面就是一樣的了。
- linker 會自動 align section 的位置!
簡單範例2 (mini-arm-os)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
ENTRY(reset_handler) MEMORY { FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 128K } SECTIONS { .text : { KEEP(*(.isr_vector)) *(.text) } >FLASH } |
應該要能看懂了。只有4個沒看過的地方:
- ENTRY(reset_handler): man ENTRY
function ENTRY 在 linker script 中可以指定 entry point,也就是程式執行時第一個執行的指令開始位置。這邊設定reset_handler
作為 entry point。 - MEMORY: man MEMORY
command MEMORY 可以用來設定記憶體區段的屬性,起始位置以及長度。其 syntax 為:
12345MEMORY{name [(attr)] : ORIGIN = origin, LENGTH = len...}
這邊我們設定一個 Memory region 叫作 FLASH,可以 read and execute,起始位置為 0x00000,長度為128K。 - KEEP: man KEEP
當有開啟 link-time garbage collection 的時候,有時候我們希望某個區段不要被回收掉,這時候就可以使用 KEEP,使用方式為將 input section wildcard entry 放入 KEEP 中。e.g.KEEP(*(.init))
或是KEEP(SORT_BY_NAME(*)(.ctors))
。 - >FLASH: man >region
把 output section 置入該 memory region,BJ4。
中等範例 (mini-arm-os)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
ENTRY(reset_handler) MEMORY { FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 128K RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 40K } SECTIONS { .text : { KEEP(*(.isr_vector)) *(.text) *(.text.*) *(.rodata) _sromdev = .; _eromdev = .; _sidata = .; } >FLASH .data : AT(_sidata) { _sdata = .; *(.data) *(.data*) _edata = .; } >RAM .bss : { _sbss = .; *(.bss) _ebss = .; } >RAM _estack = ORIGIN(RAM) + LENGTH(RAM); } |
看完上面的看這個,應該就會幾乎都懂了。
VMA / LMA 與 AT keyword 解釋
請先參考:mlouielu/linker_script_vma_lma_example
Reference
- wen00072, Linker Script初探 – GNU Linker Ld手冊略讀, http://wen00072.github.io/blog/2014/03/14/study-on-the-linker-script/
- department of mathematics, utah university, Using LD, the GNU linker – Command Language, https://www.math.utah.edu/docs/info/ld_3.html
- sourceware.org, 3 Linker Script, https://sourceware.org/binutils/docs/ld/Scripts.html
Leave a Reply