前言
我們可以使用link script來規劃程式擺放在記憶體的位址
VMA & LMA
硬體中的記憶體, 有兩種格式, 一種是ROM, 用來存放程式, 一種是RAM用來存放程式執行時所需要的資料
link script 中設計了兩種記憶體命令, VMA和LMA, 也就是相對於我們硬體中的ROM和RAM
我們只要將不同的程式區段指定到VMA或LMA, 就完成的指定程式到記憶體的工作
section
此命令定義程式的段落, 程式可能有包含程式碼, 常數, 有初值的變數, 和無初值變數
可以用section 分別定義成, text, rodata, data, bss, 再分別指定VMA或LMA給這些section即可
symbol
定義的函數, 全域變數
objdunp
我們可以使用objdump -h 來觀察, 一個object 包含哪些section, 然後來編輯link script
也可以使用objdump -t 來觀察, 包含哪些symbol
objdump -f 看硬體架構
example
假設ROM的位址是0x00000000, 而RAM的位址是0x01000000, 而程式包含code, 變數, 初始變數, 常數
則 link script 的命令可以如下:
SECTIONS
{
. = 0x00000000;
.text : { *(.text) }
.rodata:{*(.rodata)}
. = 0x01000000;
.data : { *(.data) }
.bss : { *(.bss) }
}
命令
------------------------------------------------------------------------------------------
.= (location counter)
用來命令現在記憶體assign到哪一個位址, 例如, 在例子中起始位址從0x00000000
開始assign text, 和rodata 區段, 然後再從位址0x01000000 assign data和bss 區段
------------------------------------------------------------------------------------------
.text : { *(.text) }, (assign section)
用來設定一個section, 並且命令所有的輸入檔案中的text, (也就是code)都放到這個section中
-------------------------------------------------------------------------------------------
ENTRY(symbol)
可以設定程式的進入點, 有幾種方式可以定義, 在link script 下此命令, 若沒有下命令則可能進入點會設在
程式有定義start的地方, .text的第一個byte, 或 address 0
---------------------------------------------------------------------------------------------
OUTPUT_FORMAT(
default,
big,
little)
產生不同的format, 例如:OUTPUT_FORMAT(elf32-big
, elf32-
big, elf32-
little)
若用-EB,則會產生elf32-big,若用-EL則會產生elf32-little
----------------------------------------------------------------
REGION_ALIAS(alias, region)
可以指定哪一個區段, 到哪一個memory, 是一種很有彈性的作法,使用者可以依據不同的系統
去搭配不同的記憶體
例如:現在有3個系統, R1, R2, R3
R1使用一顆flash, 和1顆sdram, R2使用一顆flash, Instruction(ILM), 和 Data local memory(DLM),
R3只使用instruction 和data location memory, 可規劃如下
SECTION R1 R2 R3
-------------------------------------------------
.text flash ILM ILM
.rodata flash flash ILM
.data sdram DLM DLM
.bss sdram DLM DLM
---------------------------------------------------
INCLUDE linkcmds.memory
SECTIONS
{
.text :
{
*(.text)
} > REGION_TEXT
.rodata :
{
*(.rodata)
rodata_end = .;
} > REGION_RODATA
.data : AT (rodata_end)
{
data_start = .;
*(.data)
} > REGION_DATA
data_size = SIZEOF(.data);
data_load_start = LOADADDR(.data);
.bss :
{
*(.bss)
} > REGION_BSS
}
-------------------------------------------------
linkcmds.memory
//R1---------------->
MEMORY
{
ROM : ORIGIN = 0, LENGTH = 2M
RAM : ORIGIN = 0x20000000, LENGTH = 1M
}
REGION_ALIAS("REGION_TEXT", ROM);
REGION_ALIAS("REGION_RODATA", ROM);
REGION_ALIAS("REGION_DATA", RAM);
REGION_ALIAS("REGION_BSS", RAM);
//R2-------->
MEMORY
{
ROM : ORIGIN = 0, LENGTH = 3M
ILM : ORIGIN = 0x01000000 LENGTH = 1M
DLM : ORIGIN = 0x02000000, LENGTH = 1M
}
REGION_ALIAS("REGION_TEXT", ILM);
REGION_ALIAS("REGION_RODATA", ROM);
REGION_ALIAS("REGION_DATA", DLM);
REGION_ALIAS("REGION_BSS", DLM);
//R3------->
MEMORY
{
ILM : ORIGIN = 0, LENGTH = 1M
DLM : ORIGIN = 0x010000000, LENGTH = 4M
}
REGION_ALIAS("REGION_TEXT", ILM);
REGION_ALIAS("REGION_RODATA", ILM);
REGION_ALIAS("REGION_DATA", DLM);
REGION_ALIAS("REGION_BSS", DLM);
-----------------------------------------------------
#include <string.h>
extern char data_start [];
extern char data_size [];
extern char data_load_start [];
void copy_data(void)
{
if (data_start != data_load_start)
{
memcpy(data_start, data_load_start, (size_t) data_size);
}
}
---------------------------------------------
OUTPUT_ARCH(
bfdarch)
指定硬體架構
---------------------------------------------
Symbol 定義變數
floating_point = 0;
SECTIONS
{
.text :
{
*(.text)
_etext = .;
}
_bdata = (. + 3) & ~ 3;
.data : { *(.data) }
}
-----------------------------------------------
PROVIDE
參考
http://sourceware.org/binutils/docs/ld/Scripts.html