linker - Understanding the linkerscript for an ARM Cortex-M microcontroller -
i using stm32f746ng microcontroller stmicroelectronics. device based on arm cortex-m7 architecture. invested quite time in understanding linkerscript example projects. figured out basics, still cannot grasp big parts of it. please me understand parts.
start of linkerscript
the linkerscript starts follows:
/* entry point */ entry(reset_handler) /* function named 'reset_handler' defined */ /* in 'startup.s' assembly file. */ /* highest address of user mode stack */ /* remember: stack points downwards */ _estack = 0x20050000; /* end of ram */ /* generate link error if heap , stack don't fit ram */ _min_heap_size = 0x200; /* required amount of heap */ _min_stack_size = 0x400; /* required amount of stack */ /* --------------------------------------------------------------------*/ /* memory areas */ /* --------------------------------------------------------------------*/ memory { /* flash memory */ /* ------------ */ /* remember: flash memory on device can */ /* accessed through either axim bus or */ /* itcm bus. accesses on itcm bus start @ */ /* address 0x0020 0000. accesses on axim bus */ /* @ address 0x0800 0000. */ flash (rx) : origin = 0x08000000, length = 1024k /* flash (rx) : origin = 0x00200000, length = 1024k */ /* ram memory */ /* ---------- */ ram (xrw) : origin = 0x20000000, length = 320k }
vector table , program code
after defining memory areas, linkerscript proceeds defining sections. first section defined in linkerscript vector table. has end in first bytes of flash memory.
/* --------------------------------------------------------------------*/ /* output sections */ /* --------------------------------------------------------------------*/ sections { /****************************/ /* vector table */ /****************************/ .isr_vector : { . = align(4); keep(*(.isr_vector)) /* vector table */ . = align(4); } >flash
after vector table inserted, it's time program code:
/****************************/ /* program code */ /****************************/ .text : { . = align(4); *(.text) /* .text sections (code) */ *(.text*) /* .text* sections (code) */ *(.glue_7) /* glue arm thumb code */ *(.glue_7t) /* glue thumb arm code */ *(.eh_frame) /* note: function ‘.text.reset_handler’ 1 of *(.text*) sections, */ /* such gets linked output .text section somewhere here. */ /* can verify exact spot reset_handler section positioned, */ /* examining second entry of vector table. */ /* test has given following results: /* flash (rx) : origin = 0x0800 0000 ==> reset_handler = 0x0800 1c91 */ /* flash (rx) : origin = 0x0020 0000 ==> reset_handler = 0x0020 1cb9 */ /* /* in both cases, reset_handler section ends few hundred bytes after */ /* vector table in flash. in first case, “reset_handler” symbol points */ /* reset-code through axim-interface, whereas in latter case points */ /* reset-code through itcm-interface. */ keep (*(.init)) keep (*(.fini)) . = align(4); _etext = .; /* define global symbol @ end of code */ } >flash
the linkerscript defines e_text
global symbol represents address program code in flash ends.
constant data
the read-only data ends in flash memory (it makes no sense put in ram, volatile). linkerscript defines .rodata
section should in flash:
/****************************/ /* constant data */ /****************************/ .rodata : { . = align(4); *(.rodata) /* .rodata sections (constants, strings, etc.) */ *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ . = align(4); } >flash
mysterious sections in flash
after defining constant read-only data should go, linkerscript defines few 'mysterious' sections should end in flash well:
.arm.extab : { *(.arm.extab* .gnu.linkonce.armextab.*) } >flash .arm : { __exidx_start = .; *(.arm.exidx*) __exidx_end = .; } >flash .preinit_array : { provide_hidden (__preinit_array_start = .); keep (*(.preinit_array*)) provide_hidden (__preinit_array_end = .); } >flash .init_array : { provide_hidden (__init_array_start = .); keep (*(sort(.init_array.*))) keep (*(.init_array*)) provide_hidden (__init_array_end = .); } >flash .fini_array : { provide_hidden (__fini_array_start = .); keep (*(sort(.fini_array.*))) keep (*(.fini_array*)) provide_hidden (__fini_array_end = .); } >flash
i have no idea sections are. let first question. these sections, , in object files show up? know, linkerscript needs link object files. have no idea in object files these mysterious sections exist:
.arm.extab
.arm
.preinit_array
.init_array
.fini_array
this end of allocations flash memory. linkerscript continues defining sections end in ram.
sections in ram
the .data
, .bss
sections clear me. no questions this.
/****************************/ /* initialized data */ /****************************/ _sidata = loadaddr(.data); .data : { . = align(4); _sdata = .; /* create global symbol @ data start */ *(.data) /* .data sections */ *(.data*) /* .data* sections */ . = align(4); _edata = .; /* define global symbol @ data end */ } >ram at> flash /****************************/ /* uninitialized data */ /****************************/ . = align(4); .bss : { _sbss = .; /* define global symbol @ bss start */ __bss_start__ = _sbss; *(.bss) *(.bss*) *(common) . = align(4); _ebss = .; /* define global symbol @ bss end */ __bss_end__ = _ebss; } >ram
the linkerscript defines ._user_heap_stack
section:
/****************************/ /* user_heap_stack section */ /****************************/ /* user_heap_stack section, used check there enough ram left */ ._user_heap_stack : { . = align(8); provide ( end = . ); provide ( _end = . ); . = . + _min_heap_size; . = . + _min_stack_size; . = align(8); } >ram
apparently section not used immediately. defined check if ram has still enough space stack , heap. linker error thrown when not case (the .
exceeds top ram address).
the end of linkerscript
this how linkerscript ends. , honestly, have no idea does. second question: following mean?
/* remove information standard libraries */ /discard/ : { libc.a ( * ) libm.a ( * ) libgcc.a ( * ) } .arm.attributes 0 : { *(.arm.attributes) } } /* end of linkerscript */
.arm.extab , .arm.exidx related unwinding. can find more information here http://infocenter.arm.com/help/topic/com.arm.doc.ihi0044e/index.html. don't need them if don't care unwinding (unwinding useful c++ exception , debugging).
these symbols related c / c++ constructor , destructor startup , tear down code called before / after main(). sections named .init, .ctors, .preinit_array, , .init_array initialization of c/c++ objects, , sections .fini, .fini_array, , .dtors tear down. start , end symbols define beginning , end of code sections related such operations , might referenced other parts of runtime support code.
the .preinit_array , .init_array sections contain arrays of pointers functions called on initialization. .fini_array array of functions called on destruction. presumably start , end labels used walk these lists.
heap: not really, part permits reserve space heap , space stack. rises error if sum of reserved areas goes outside ram boundaries. example:
_min_heap_size = 0; /* required amount of heap / _min_stack_size = 0x400; / required amount of stack */
._user_heap_stack : { . = align(4); provide ( end = . ); provide ( _end = . ); . = . + _min_heap_size; . = . + _min_stack_size; . = align(4); } >ram
to link libraries prefer different notation, example bare-metal no rtos c++ project: group(libgcc.a libc_nano.a libstdc++_nano.a libm.a libcr_newlib_nohost.a crti.o crtn.o crtbegin.o crtend.o)
Comments
Post a Comment