esp32 h2 功耗樂鑫科技芯片代理商RISC-V鏈接腳本,鏈接器把一個或多個輸人文件合成一個輸出文件。輸人文件包括二進制目標X件,二進制庫文件和鏈接腳本文件,輸出文件是二進制目標文件、二進制庫文件或”執行文件。
每個目標文件中都包含符號表(SYMBOL TABLE)。esp32 h2 功耗樂鑫科技芯片代理商表中含有全局(global)變量,靜態(static)變量和函數名等已定義的符號,以及未定義符號信息。每個符號映射到一個內存地址,即符號值。
鏈接器在鏈接過程中讀取鏈接腳本文件( *.lds)中的命令和信息,并根據從腳本文件中所讀取的內容,確定輸入文件內的段(section)合并到輸出文件的方式,并控制輸出文件內各部分在虛擬(邏輯)內存空間內的分布,完成鏈接過程。
腳本格式
鏈接腳本由一系列命令組成,每個命令都由一個關鍵字或一條符號的賦值語句組成,命令之間用分號“;”隔開。
1.常用鏈接命令
(1)ENTRY(SYMBOL)
將符號 SYMBOL 設置為程序的入口地址。
人口地址是進程執行的第一條指令在程序空間的地址。鏈接器 ld 中其他設置
程序入口地址的方式包括:
1、采用ld 命令行的參數-e;
2、如果定義了 start 符號,則使用 start 符號值;
3、如果存在.text section,則使用.text section 的第一字節的位置值。
(2)INCLUDE filename
包含名稱為 filename 的其他鏈接腳本文件。
(3) INPUT( file , file,... )
將括號內的文件作為鏈接過程的輸入文件。
(4)GROUP( file, file,...)
指定需要重復搜索符號的多個輸人文件。file 必須是庫文件,且 file 文件被 ld重復掃描,直到不再有新的未定義的引用出現。
(5)OUTPUT(filename)
定義輸出文件的名字,等同于 ld 命令行參數“-o filename”。如果同時使用腳本文件和命令行參數,則命令行參數的優先級更高。
(6)STARTUP(filename)
指定 filename 為第一個輸人文件。
(7) OUTPUT ARCH(BFDARCH
設置輸出文件對應的處理器架構。
(8)OUTPUT FORMAT(BFNAME
設置輸出文件使用的 BFD格式,等同于 ld 命令行參數“-o format BFDNAME”如果同時使用腳本文件和命令行參數,則命令行參數的優先級更高。
2.SECTIONS 命令
SBCTIONS命令告訴鏈接器輸入和輸人文件中段的處理方式,包括,如何把人文件的段映射到輸出文件的各個段,如何將輸人段合并為輸出段,以及如何把輸”段成人虛擬內存地址空間(Virtual Memory Addres,VMA)和加載地址空間(LMemory Address,LMA)。esp32 h2 功耗樂鑫科技芯片代理商LMA 是序代碼和數據裝載到內存空間的物理地VMA是程序運行時代碼和數據的虛擬地址。對于實模式,VMA 與內存的物理地一致。如果 SECTIONS中 VMA與 LMA 不相同,則運行程序前需要將程序指
數據從 LMA 位置復制到 VMA 位置。
(1)SECTONS 格式
SECTIONS 命令給出輸人文件的 section 映射到輸出文件中的各種 section 方式。包括,將輸入 section 合并為輸出 section,以及把輸出 section 映射到 VMA和LMA 中。命令格式如下:
SECTIONS
{
SECTIONS- COMMAND
SECTIONS- COMMAND
...
}
在 SECTIONS 命令格式中,包括以下 SECTIONS-COMMAND 命令:
1、 ENTRY命令;
2、符號賦值語句;
3、輸出段描述(output section description);
4、段疊加描述(overlay description)。
如果鏈接腳本內沒有 SECTIONS 命令,那么 ld 將所有同名輸人段合成為一個輸出段,各段的輸入順序為它們被鏈接器發現的順序。esp32 h2 功耗樂鑫科技芯片代理商如果某輸人段沒有出現在SECTIONS 命令中,則將該段直接復制到輸出段
(2) 輸出段描述
輸出段是目標文件中的塊。多個塊組成可執行目標程序文件。輸出段描述格式
如下:
SECTION_NAME [ADDRESS] [(TYPE)] :[AT(LMA)]
{
OUTPUT - SECTION - COMMAND
OUTPUT - SECTION - COMMAND
...
}
在段描述中,[]中的內容為可選項。大多數情況下,不需要使用可選屬性。
SECTION NAME 是輸出段的名稱,必須符合輸出文件格式要求。在僅支持有限段數的格式中,段名稱必須是該格式支持的名稱之一(例如,a.out 中僅有“.text”.data”或“.bss”段)。段名稱可以由任何字符序列組成,但包含任何不尋常字符(如逗號)的名稱必須加引號。
[ADDRESS]用于設置輸出段的 VMA 地址。如果沒有該選項,且有 REGION選項,那么鏈接器將根據 REGION 設置 VMA。如果也沒有 REGION 選項,那么鏈接器將根據定位符號“”的位置設置該段的 VMA。ld 將調整定位符號的值,以滿足輸出段對齊的要求。
[(TYPE )] 設置輸出段的類型,常用的選項是 NOLOAD,表示在程序運行時不將該段載入內存。esp32 h2 功耗樂鑫科技芯片代理商[AT(LMA)]和[AT]> LMA REGION] 指定該段在 LMA 地址的范圍中,主要用于構建 ROM 鏡像。
[>REGION]指定 VMA 分配范圍。
[:PHDR :PHDR ...] 將輸出段放入預先定義的程序段(program segment)內。
[= FILLEXP]設置填充值。
OUTPUT-SECTION-COMMAND 為下列4種之一:
1符號賦值語句;
2、輸人段描述;
3、直接包含的數據值;
4、特殊關鍵字
(3)輸入段描述輸人段描述表示輸人文件中的段,其語法格式如下:
filename([EXCLUDE_FILE (filenamel filename2 ...) SECTION1 SECTION2 ...)
其中:
filename,文件名,是一個特定的文件名稱,也可以是一個字符串模式。
EXCLUDE_FILE,排除在外的文件。
SECTION名字,可以是特定的段名字,也可以是一個字符串模式。
例如,“* (.text)”表示所有輸人文件的.text 段,“data.o(.data)”表示 data,o文件中的.data 段,“data.o”表示 data.o 文件中的所有段。“*(.text.data)”表示所有文件的.text 段和data 段,排列順序為:第一個文的.text 段,第一個文件的.data 段,第二個文件的.text 段,第二個文件的.data 段....“*(.text) * (.data)”表示所有文件的.text 段和.data 段。排列順序為:第~文件的.text 段,第二個文件的.text 段,··,esp32 h2 功耗樂鑫科技芯片代理商后一個文件的.text 段;第一個文件的data 段,第二個文件的.data 段,··,后一個文件的.data 段。
字符串模式常用兩種通配符,“*”表示任意多個字符,“?”表示任意一個字符下面是一個簡單輸出段描述的示例:
SECTIONS
{
. = 0x10000;
.text :{ * (.text) }
. = 0x8000000;
.data :( * (.data)}
.bss :( *(.bss) }
}
在輸出段描述示例中:
每一行起始位置的“.”是定位符號,確定本行的起始地址;
“.=0x10000;”把定位符號的地址置為 0x10000(若不指定,則該符號的初始值為 0);
“.text :{ * (.text)}”將所有輸入文件的.text 段合并成一個,text 段,該段的地址由定位符號的值指定,即 0x10000;
“.= 0x8000000;”把定位符號的地址置為 0x8000000;
“.data :{*(.data)}”將所有輸入文件的.data 段合并成一個.data 段,將該段的起始地址置為 0x8000000;
“.bss :{ * (.bss)}”將所有輸入文件的.bss 段合并成一個,bss 段,將該段的起始地址置為 0x8000000+SIZEOF(.data)。
腳本示例
在esp32 h2 功耗樂鑫科技芯片代理商公司發布的 RISC-V 處理器開發平臺 HBird-E-SDK 中,提供了一個鏈接腳本文件 link_flashxip.lds。使用該文件,鏈接生成映射到 Flash 空間并在Flash 中直接運行的程序。鏈接腳本文件包含程序入口、目標板內存資源以及段描述。段描述中包含.init、.text 和.data 等輸出段描述。
1、程序入口和存儲資源描述
ENTRY(_start) //程序人口為_start標簽
MEMORY
{
flash rom(rxai!w):ORIGIN= 0x20000000,LENGTH=4M //聲明 Flash ROM 區域
ram(wxa !ri):ORIGION = 0x90000000,LENGTH= 64K //聲明 RAM區域
}
將目標系統中 Flash 區域命名為 flash_rom,該區域起始地址為 0x20000000,長度4 MB,只讀(r,!w)、可分配(a)、需初始化(i)和可執行(x)。
將目標系統中 RAM 區域命名為 ram,該區域起始地址是 0x90000000,長度64 KB,可分配(a)、無須初始化(!i)、可執行(x)和可讀/寫(!r,w)。
2.段描述
SECTIONS 中有兩個程序指令輸出段.init 和text。裝載和運行時,程序指令都在 Flash 中。而SECTIONS 中的程序數據輸出段data,esp32 h2 功耗樂鑫科技芯片代理商裝載時在 Flash 中,運行時在 RAM中。
link flashxip.lds 文件內容:
SECTIONS
{/* 定義棧和堆的大小 * /
__stack size = DEFINED( __stack_size) ?__stack_size:2K;
__heap_size= DEFINED( __heap_size) ?_ heap_size;2K;
*代碼輸出段 */
.init:
{
KEEP ( *(SORT NONE(.init)))
}>flash_rom AT>flash_rom //裝載和運行都在 flash rom 中
//創建標簽
.ilalign :
{
.= ALIGN(4); //4字節對齊
PROVIDE( itcm Ima =.); //創建標簽_itcm_Ima
}>flash_rom AT>flash rom //裝載和運行都在 flash_rom 中
/*代碼輸出段*/
.text:
{
*(.text.startup .text.startup. * ) //所有輸人文件的段及其子段
*(.text .text.*) //所有輸人文件的.text 段及其子段
}>flash rom AT>flash rom //裝載和運行都在 flash_rom 中
/* 數據輸出段 */
.data :
{
*(.rdata) //所有輸人文件的.rdata 段
* (.rodata .rodata. * ) //所有輸人文件的.rodata 段及其子段
.= ALIGN(8);
PROVIDE( global pointer$ =,+ 0x800); //創建標簽__global_pointer
*(.sdata .sdata.*) //所有輸人文件的.sdata 段
*(.srodata .srodata.*) //所有輸人文件的.srodata 段及其子段
}>ram AT>flash rom //裝載時在 flash rom 中,運行時在 ram中
}