__attribute__之section详解,物联网嵌入式开发面试必看书籍

44 阅读2分钟
struct _s_application_init _s_a_init_##function  __app_init_section = {function}

static int application_init_a(void) { printf("execute funtion : %s\n", FUNCTION); return 0; } __application_init(application_init_a);

static int application_init_b(void) { printf("execute funtion : %s\n", FUNCTION); return 0; } __application_init(application_init_b);

static int application_init_c(void) { printf("execute funtion : %s\n", FUNCTION); return 0; } __application_init(application_init_c);

int main(int argc, char *argv) { / * 从段的起始地址开始获取数据,直到末尾地址 */ struct _s_application_init *pf_init = &_init_start; do { printf("Load init function from address %p\n", pf_init); pf_init->function(); ++pf_init; } while (pf_init < &_init_end); return 0; }


然后我们还需要编写lds文件,首先使用命令生成默认的文件:



seven@root:~/section/ldverbose>main.ldsseven@root: /section/ ld --verbose > main.lds seven@root:~/section/ cat main.lds GNU ld (GNU Binutils for Ubuntu) 2.26.1 Supported emulations: elf_i386 i386linux elf_iamcu elf32_x86_64 elf_x86_64 elf_l1om elf_k1om i386pep i386pe using internal linker script:

/* Script for -z combreloc: combine and sort reloc sections / / Copyright (C) 2014-2015 Free Software Foundation, Inc. Copying and distribution of this script, with or without modification, are permitted in any medium without royalty provided the copyright notice and this notice are preserved. / OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") OUTPUT_ARCH(i386) ENTRY(_start) SEARCH_DIR("=/usr/local/lib/i386-linux-gnu"); SEARCH_DIR("=/lib/i386-linux-gnu"); SEARCH_DIR("=/usr/lib/i386-linux-gnu"); SEARCH_DIR("=/usr/local/lib32"); SEARCH_DIR("=/lib32"); SEARCH_DIR("=/usr/lib32"); SEARCH_DIR("=/usr/local/lib"); SEARCH_DIR("=/lib"); SEARCH_DIR("=/usr/lib"); SEARCH_DIR("=/usr/i686-linux-gnu/lib32"); SEARCH_DIR("=/usr/i686-linux-gnu/lib"); SECTIONS { / Read-only sections, merged into text segment: */ PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x08048000)); . = SEGMENT_START("text-segment", 0x08048000) + SIZEOF_HEADERS; .interp : { *(.interp) } .note.gnu.build-id : { *(.note.gnu.build-id) } .hash : { *(.hash) } .gnu.hash : { *(.gnu.hash) } .dynsym : { (.dynsym) } .dynstr : { (.dynstr) } .gnu.version : { (.gnu.version) } .gnu.version_d : { (.gnu.version_d) } .gnu.version_r : { (.gnu.version_r) } .rel.dyn : { (.rel.init) (.rel.text .rel.text. .rel.gnu.linkonce.t.) (.rel.fini) (.rel.rodata .rel.rodata. .rel.gnu.linkonce.r.) (.rel.data.rel.ro .rel.data.rel.ro. .rel.gnu.linkonce.d.rel.ro.) (.rel.data .rel.data. .rel.gnu.linkonce.d.) (.rel.tdata .rel.tdata. .rel.gnu.linkonce.td.) (.rel.tbss .rel.tbss. .rel.gnu.linkonce.tb.) (.rel.ctors) (.rel.dtors) (.rel.got) (.rel.bss .rel.bss. .rel.gnu.linkonce.b.) (.rel.ifunc) } .rel.plt : { (.rel.plt) PROVIDE_HIDDEN (__rel_iplt_start = .); (.rel.iplt) PROVIDE_HIDDEN (__rel_iplt_end = .); } .init : { KEEP ((SORT_NONE(.init))) } .plt : { (.plt) (.iplt) } .plt.got : { (.plt.got) } .text : { (.text.unlikely .text._unlikely .text.unlikely.) (.text.exit .text.exit.) (.text.startup .text.startup.) (.text.hot .text.hot.) (.text .stub .text. .gnu.linkonce.t.) / .gnu.warning sections are handled specially by elf32.em. / (.gnu.warning) } .fini : { KEEP ((SORT_NONE(.fini))) } PROVIDE (__etext = .); PROVIDE (_etext = .); PROVIDE (etext = .); .rodata : { (.rodata .rodata. .gnu.linkonce.r.) } .rodata1 : { (.rodata1) } .eh_frame_hdr : { (.eh_frame_hdr) (.eh_frame_entry .eh_frame_entry.) } .eh_frame : ONLY_IF_RO { KEEP ((.eh_frame)) (.eh_frame.) } .gcc_except_table : ONLY_IF_RO { (.gcc_except_table .gcc_except_table.) } .gnu_extab : ONLY_IF_RO { (.gnu_extab) } / These sections are generated by the Sun/Oracle C++ compiler. / .exception_ranges : ONLY_IF_RO { (.exception_ranges .exception_ranges) } / Adjust the address for the data segment. We want to adjust up to the same address within the page on the next page up. / . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE)); / Exception handling / .eh_frame : ONLY_IF_RW { KEEP ((.eh_frame)) (.eh_frame.) } .gnu_extab : ONLY_IF_RW { (.gnu_extab) } .gcc_except_table : ONLY_IF_RW { (.gcc_except_table .gcc_except_table.) } .exception_ranges : ONLY_IF_RW { (.exception_ranges .exception_ranges) } / Thread Local Storage sections / .tdata : { (.tdata .tdata. .gnu.linkonce.td.) } .tbss : { (.tbss .tbss. .gnu.linkonce.tb.) (.tcommon) } .preinit_array : { PROVIDE_HIDDEN (__preinit_array_start = .); KEEP ((.preinit_array)) PROVIDE_HIDDEN (__preinit_array_end = .); } .init_array : { PROVIDE_HIDDEN (__init_array_start = .); KEEP ((SORT_BY_INIT_PRIORITY(.init_array.) SORT_BY_INIT_PRIORITY(.ctors.))) KEEP ((.init_array EXCLUDE_FILE (crtbegin.o crtbegin?.o crtend.o crtend?.o ) .ctors)) PROVIDE_HIDDEN (__init_array_end = .); } .fini_array : { PROVIDE_HIDDEN (__fini_array_start = .); KEEP ((SORT_BY_INIT_PRIORITY(.fini_array.) SORT_BY_INIT_PRIORITY(.dtors.))) KEEP ((.fini_array EXCLUDE_FILE (*crtbegin.o crtbegin?.o crtend.o crtend?.o ) .dtors)) PROVIDE_HIDDEN (__fini_array_end = .); } .ctors : { / gcc uses crtbegin.o to find the start of the constructors, so we make sure it is first. Because this is a wildcard, it doesn't matter if the user does not actually link against crtbegin.o; the linker won't look for a file to match a wildcard. The wildcard also means that it doesn't matter which directory crtbegin.o is in. / KEEP (crtbegin.o(.ctors)) KEEP (crtbegin?.o(.ctors)) / We don't want to include the .ctor section from the crtend.o file until after the sorted ctors. The .ctor section from the crtend file contains the end of ctors marker and it must be last / KEEP ((EXCLUDE_FILE (crtend.o crtend?.o ) .ctors)) KEEP ((SORT(.ctors.))) KEEP ((.ctors)) } .dtors : { KEEP (crtbegin.o(.dtors)) KEEP (crtbegin?.o(.dtors)) KEEP ((EXCLUDE_FILE (crtend.o crtend?.o ) .dtors)) KEEP ((SORT(.dtors.))) KEEP ((.dtors)) } .jcr : { KEEP ((.jcr)) } .data.rel.ro : { (.data.rel.ro.local .gnu.linkonce.d.rel.ro.local.) (.data.rel.ro .data.rel.ro. .gnu.linkonce.d.rel.ro.) } .dynamic : { *(.dynamic) } .got : { *(.got) *(.igot) } . = DATA_SEGMENT_RELRO_END (SIZEOF (.got.plt) >= 12 ? 12 : 0, .); .got.plt : { *(.got.plt) (.igot.plt) } .data : { (.data .data. .gnu.linkonce.d.) SORT(CONSTRUCTORS) } .data1 : { (.data1) } _edata = .; PROVIDE (edata = .); . = .; __bss_start = .; .bss : { (.dynbss) (.bss .bss. .gnu.linkonce.b.) (COMMON) / Align here to ensure that the .bss section occupies space up to end. Align after .bss to ensure correct alignment even if the .bss section disappears because there are no input sections. FIXME: Why do we need it? When there is no .bss section, we don't pad the .data section. / . = ALIGN(. != 0 ? 32 / 8 : 1); } . = ALIGN(32 / 8); . = SEGMENT_START("ldata-segment", .); . = ALIGN(32 / 8); _end = .; PROVIDE (end = .); . = DATA_SEGMENT_END (.); / Stabs debugging sections. */ .stab 0 : { *(.stab) } .stabstr 0 : { *(.stabstr) } .stab.excl 0 : { *(.stab.excl) } .stab.exclstr 0 : { *(.stab.exclstr) } .stab.index 0 : { *(.stab.index) } .stab.indexstr 0 : { *(.stab.indexstr) } .comment 0 : { (.comment) } / DWARF debug sections. Symbols in the DWARF debugging sections are relative to the beginning of the section so we begin them at 0. / / DWARF 1 */ .debug 0 : { *(.debug) } .line 0 : { (.line) } / GNU DWARF 1 extensions */ .debug_srcinfo 0 : { *(.debug_srcinfo) } .debug_sfnames 0 : { (.debug_sfnames) } / DWARF 1.1 and DWARF 2 */ .debug_aranges 0 : { *(.debug_aranges) } .debug_pubnames 0 : { (.debug_pubnames) } / DWARF 2 */ .debug_info 0 : { (.debug_info .gnu.linkonce.wi.) } .debug_abbrev 0 : { *(.debug_abbrev) } .debug_line 0 : { (.debug_line .debug_line. .debug_line_end ) } .debug_frame 0 : { *(.debug_frame) } .debug_str 0 : { *(.debug_str) } .debug_loc 0 : { *(.debug_loc) } .debug_macinfo 0 : { (.debug_macinfo) } / SGI/MIPS DWARF 2 extensions */ .debug_weaknames 0 : { *(.debug_weaknames) } .debug_funcnames 0 : { *(.debug_funcnames) } .debug_typenames 0 : { *(.debug_typenames) } .debug_varnames 0 : { (.debug_varnames) } / DWARF 3 */ .debug_pubtypes 0 : { *(.debug_pubtypes) } .debug_ranges 0 : { (.debug_ranges) } / DWARF Extension. */ .debug_macro 0 : { (.debug_macro) } .gnu.attributes 0 : { KEEP ((.gnu.attributes)) } /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto) } }

==================================================


然后我们修改这个文件:


首先我们需要将默认文件的首尾“==================================================”包含这一行要删除,不然会报格式错误


/usr/bin/ld:test.lds:1: syntax error  
 collect2: error: ld returned 1 exit status


然后选择在“\_\_bss\_start”前添加我们自己的段



...

. = .;

_init_start = .;/* 获取当前的地址赋值给__init_start,在源码中有使用到,指向“.application_init”段的起始地址 */ .application_init : { (.application_init) }/ 将“.application_init”的所有内容放在这一段 / _init_end = .;/ 获取当前的地址赋值给__init_end,表示“.application_init”段的结束地址 */

__bss_start = .;

...


 然后我们在*链接*的时候使用一下命令:




**收集整理了一份《2024年最新物联网嵌入式全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升的朋友。**
![img](https://p3-xtjj-sign.byteimg.com/tos-cn-i-73owjymdk6/21b3a8c0216447a999269d011c5fb531~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5py65Zmo5a2m5Lmg5LmL5b-DQUk=:q75.awebp?rk3s=f64ab15b&x-expires=1771251189&x-signature=X4x0oqo6evS5NvhMr6f4wPd5tkk%3D)
![img](https://p3-xtjj-sign.byteimg.com/tos-cn-i-73owjymdk6/6cae8752e4e540f0a8b744b07ef4549e~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5py65Zmo5a2m5Lmg5LmL5b-DQUk=:q75.awebp?rk3s=f64ab15b&x-expires=1771251189&x-signature=LPQrHifjeNg1HH2bQ%2FKMyVH700o%3D)

**[如果你需要这些资料,可以戳这里获取](https://gitee.com/vip204888)**

**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人**

**都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**