ld链接文件解析
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| .flash_contents 0x6000004C : AT (0x6000004C) { _mtext = .; . = . + (_text_end - _text_start); _mdummy = .; . = . + (_dummy_end - _dummy_start); _mdata = .; . = . + (_data_end - _data_start); flash_contents_end = .; } > xSPI0_CS0_SPACE .text 0x00102000 : AT (_mtext) { _text_start = .; _fvector_start = .; KEEP(*(.intvec)) _fvector_end = .;
_dummy_start = .; KEEP(*(.dummy)); _dummy_end = .;
*(.text*)
KEEP(*(.reset_handler)) KEEP(*(.init)) KEEP(*(.fini))
/* .ctors */ *crtbegin.o(.ctors) *crtbegin?.o(.ctors) *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) *(SORT(.ctors.*)) *(.ctors) _ctor_end = .;
/* .dtors */ *crtbegin.o(.dtors) *crtbegin?.o(.dtors) *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) *(SORT(.dtors.*)) *(.dtors) _dtor_end = .;
KEEP(*(.eh_frame*)) } > RAM
|
1
| .flash_contents 0x6000004C : AT (0x6000004C)
|
这里左边的0x6000004C是虚拟地址,是运行时的地址。右边的0x6000004C是加载地址,从右边的0x6000004C加载到左边的0x6000004C。
1
| .text 0x00102000 : AT (_mtext)
|
如上解释,0x00102000是虚拟地址,这里是RAM地址,右边的AT (_mtext) 表示从mtext地址加载到0x00102000,而 _mtext 就是在 flash_contents 分配的
第一个 * 表示包括所有括号里面的段,第二个 * 表示 .text 开头的所有子段
类似于c语言的volatile关键字
没有使用 KEEP
指令,链接器在进行链接操作时,会依据其默认的垃圾回收机制(garbage collection)来处理节。当链接器认为某个节在最终的可执行文件中没有被引用时,就会将其丢弃,也就是不包含在最终的输出文件里。当使用 KEEP(*(.reset_handler))
时,KEEP
指令会告知链接器,无论这个节是否被其他部分引用,都要强制将其保留在最终的可执行文件中。也就是说,链接器不会对 KEEP
所指定的节执行垃圾回收操作。
在 .reset_handler
节的场景中,复位处理函数对于系统的启动至关重要,无论链接器是否能检测到它的引用,都必须确保该节被包含在最终的可执行文件里。使用 KEEP
指令可以保证 .reset_handler
节中的复位处理函数代码被正确地链接到最终的程序中,从而确保系统在复位时能够正常启动。
1 2 3 4 5 6 7 8
| .heap (NOLOAD) : { . = ALIGN(8); __HeapBase = .; /* Place the STD heap here. */ KEEP(*(.heap)) __HeapLimit = .; } > SYSTEM_RAM
|
(NOLOAD)属性表示不把该段加载进固件