10分鐘讀懂 linker scripts

背景知識:

  • 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 觀察上述事實:


簡單範例:

通常 linker script 都是很和藹可親的。

舉例而言,你的程式有程式碼、初始化變數與未初始化變數,他們分別會放在不同的 section: .text.data.bss 之中。而我們想要把 code 放到 0x10000,data 放到 0x8000000,以下就是符合我們要求的 linker script

以下逐一講解各行意義:

  • 第一行:使用 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)

應該要能看懂了。只有4個沒看過的地方:

  • ENTRY(reset_handler): man ENTRY
    function ENTRY 在 linker script 中可以指定 entry point,也就是程式執行時第一個執行的指令開始位置。這邊設定 reset_handler 作為 entry point。
  • MEMORY: man MEMORY
    command MEMORY 可以用來設定記憶體區段的屬性,起始位置以及長度。其 syntax 為:

    這邊我們設定一個 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)

看完上面的看這個,應該就會幾乎都懂了。

VMA / LMA 與 AT keyword 解釋

請先參考:linker_script_vma_lma_example

Reference




如果你覺得這篇文章不錯,歡迎打賞 IOTA:RFHEIVXVIZWJFXTZORZZRCMHZF9PSGFUFWAAKXTFNZE9JQUY9HFQREJYYSPSXDRLECKXCAQQDOMSMYJYDKPCKWXBKD

或是點選下方圖片贊助我一杯咖啡:

1 comments On 10分鐘讀懂 linker scripts

Leave a reply:

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.