nuttx link script

僅僅用於自己學習做筆記使用,總結很不全。

1, .text, .bss, .data, .rodata, stack and heap
.text code
.data global and static init variable, 即佔文件空間,又佔用運行時內存空間的
.bss uninit global and static variable只佔運行時的內存空間,而不佔文件空間
.rodata const data
Stack local variable and param
Heap malloc

2, link script

MEMORY
{
    flash (rx) : ORIGIN = 0x00000000, LENGTH = 448K
    sram (rwx) : ORIGIN = 0x21004000, LENGTH = 176K
}
//flash (rx) 標記爲flash,該部分是可讀可執行,
 //ORIGIN標記該部分存儲的起始地址
//LENGTH 
ENTRY(_stext)						//通常ENTRY()表示的是entry function
SECTIONS
{
    .text : {
        _stext = ABSOLUTE(.);		//獲取.text section 的起始地址(當前的絕對地址)
        KEEP(*(.vectors))				//保留.vectors的部分,將其鏈接進.text section中

        /* explictly specify the offset of link tags */
        . = 0x400;							//將當前的地址定位符設置爲0x400
        /* image magic */
        LONG(0x21494350)			//設置image的header magic,用於image的check
        LONG(_stext)
        LONG(_eflash - _stext)
        LONG(__start)

        *(.text .text.*)						//將所有.text 以及 .text.*的數據放到.text section中
        *(.fixup)
        *(.gnu.warning)
        _srodata = ABSOLUTE(.);		//標記rodata的起始地址
        *(.rodata .rodata.*)
        _erodata = ABSOLUTE(.);		//標記rodata的結束地址
        *(.gnu.linkonce.t.*)
        *(.glue_7)
        *(.glue_7t)
        *(.got)
         *(.got)
        *(.gcc_except_table)
        *(.gnu.linkonce.r.*)
        _etext = ABSOLUTE(.);		//獲取.text section 的結束地址
    } > flash

    .init_section : {							//自己定義的section,用於將我們定義的用init_section標記出來的都放入到 .init_section 段中。
        _sinit = ABSOLUTE(.);
        KEEP(*(.init_array .init_array.*))		//不管該函數有沒有被調用,都要保留該部分,不允許優化掉
        _einit = ABSOLUTE(.);
    } > flash

    .ARM.extab : {
        *(.ARM.extab*)
    } > flash

    __exidx_start = ABSOLUTE(.);
    .ARM.exidx : {
        *(.ARM.exidx*)
    } > flash
    __exidx_end = ABSOLUTE(.);

    _eronly = LOADADDR(.data);
    .data : {
        _sdata = ABSOLUTE(.);
        *(.data .data.*)
        *(.gnu.linkonce.d.*)
        CONSTRUCTORS
        _edata = ABSOLUTE(.);
    } > sram AT > flash
// > sram AT > flash的含義是.data的運行區是在sram上,但是它的LMA是在flash上,當你使用的時候,你需要將其從flash上拷貝到sram中。
    _eflash = LOADADDR(.data) + SIZEOF(.data);

    .noload (NOLOAD) : {
        *(.dma .dma.*)
        *(.ram_vectors .ram_vectors.*)
    } > sram

    .bss : {
        _sbss = ABSOLUTE(.);
        *(.bss .bss.*)
        *(.gnu.linkonce.b.*)
        *(COMMON)
        . = ALIGN(8);
        _ebss = ABSOLUTE(.);
    } > sram

    _eheap = _sdumplog;		//heap區的結束地址是dump log的起始地址

    _sdumplog = _edumplog - _dumplogsize;
    _edumplog = ORIGIN(sram) + LENGTH(sram);
    _dumplogsize = 4096;
    //對於我們來說,我們用sram的最後4K做dump log使用

用原始的nuttx上的樣例:
nuttx\boards\arm\c5471\c5471evm\scripts\ld.script
OUTPUT_ARCH(arm)		//聲明處理器的架構
ENTRY(_stext)					//通常ENTRY()表示的是entry function
SECTIONS
{
    /* Interrupt vector trampoline and command line parameters
     * are provided in IRAM by the rrload bootloader.  Vectors will be
     * copied into _svectors.
     */

    . = 0xffc00000;				//將當前的地址定位符設置爲0xffc00000
    _svectors = ABSOLUTE(.);		//獲取當前的起始絕對地址

    /* These are locations in IRAM where the rrload bootloader passes
     * information to the running program
     */

    . = 0xffc00020;	//將當前的地址定位符設置爲0xffc00020
    __KernCommandLineMagicStr = .;  /* magic pattern string == "kcmdline-->" */
    . = 0xffc0002C;                 /* advance to .+strlen("kcmdline-->")+1 */ //將當前的地址定位符設置爲0xffc0002C
    __KernCommandLineOverride = .;  /* location of kernel command line string */

    . = 0xffc00100;
    __EtherMACMagicStr = .;         /* magic pattern string == "etherMAC-->" */
    . = 0xffc0010C;                 /* advance to .+strlen("etherMAC-->")+1 */
    __EtherMAC = .;


    /* The OS entry point is here */

    . = 0x10300000;
    .text : {
        _stext = ABSOLUTE(.);		//獲取.text section的起始絕對地址
        *(.text)
        *(.fixup)
        *(.gnu.warning)
        *(.rodata)
        *(.glue_7)
        *(.glue_7t)
         *(.got)                    /* Global offset table */
        _etext = ABSOLUTE(.);	//獲取.text section的結束絕對地址
    }

    _eronly = ABSOLUTE(.);          /* See below */
    . = ALIGN(4096);			//設置當前地址按照4096的大小去做對齊的處理

    .data : ALIGN(4) {	//.data 的數據按照4 字節大小對齊的方式做數據排布。
        _sdata = ABSOLUTE(.);	             //獲取.data section的開始絕對地址
        *(.data)
        CONSTRUCTORS
        . = ALIGN(4);
        _edata = ABSOLUTE(.);	             //獲取.data section的結束絕對地址
    }

    .bss : ALIGN(4) {               /* BSS */
    _sbss = ABSOLUTE(.);
        *(.bss)
        *(COMMON)
        . = ALIGN(4);
        _ebss = ABSOLUTE(.);
    }

3,How to use variable in link script
Hence when you are using a linker script defined symbol in source code you should always
take the address of the symbol, and never attempt to use its value. For example suppose
you want to copy the contents of a section of memory called .ROM into a section called
.FLASH and the linker script contains these declarations:
start_of_ROM
= .ROM;
end_of_ROM
= .ROM + sizeof (.ROM) - 1;
start_of_FLASH = .FLASH;
Then the C source code to perform the copy would be:
extern char start_of_ROM, end_of_ROM, start_of_FLASH;
memcpy (& start_of_FLASH, & start_of_ROM, & end_of_ROM - & start_of_ROM);

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章