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);

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