一、实例1 不同长度
1、代码
#include <stdio.h> /* Simple shorthand for a section definition */ #ifndef __section #define __section(s) __attribute__((__section__(#s))) #endif #define __packed __attribute__((__packed__)) #define DEBUG_SECTION #ifdef DEBUG_SECTION #define __init __section(.init.usb.text) #define __initdata __section(.init.usb.data) #define __initconst __section(.init.usb.rodata) #define __exitdata __section(.exit.usb.data) #define __exit __section(.exit.usb.text) #else /*!DEBUG_SECTION*/ #define __init #define __initdata #define __initconst #define __exitdata #define __exit #endif typedef unsigned char uint8_t; typedef unsigned short uint16_t; struct usb_desc_header { uint8_t bLength; uint8_t bDescriptorType; } __packed; /** USB Standard Device Descriptor defined in spec. Table 9-8 */ struct usb_device_descriptor { uint8_t bLength; uint8_t bDescriptorType; uint16_t bcdUSB; uint8_t bDeviceClass; uint8_t bDeviceSubClass; uint8_t bDeviceProtocol; uint8_t bMaxPacketSize0; uint16_t idVendor; uint16_t idProduct; uint16_t bcdDevice; uint8_t iManufacturer; uint8_t iProduct; uint8_t iSerialNumber; uint8_t bNumConfigurations; } __packed; /** USB Standard Configuration Descriptor defined in spec. Table 9-10 */ struct usb_cfg_descriptor { uint8_t bLength; uint8_t bDescriptorType; uint16_t wTotalLength; uint8_t bNumInterfaces; uint8_t bConfigurationValue; uint8_t iConfiguration; uint8_t bmAttributes; uint8_t bMaxPower; } __packed; usb_desc_header gs_1 __initdata {}; __initdata usb_device_descriptor gs_2 ; static usb_cfg_descriptor gs_3 __initdata; static int gs_4 __initdata; void my_print(void) { static int gs_5 __initdata = 0x13; static int gs_6 __initdata; } int main() { my_print(); return 0; }
2、lds
SECTION_DATA_PROLOGUE(usb_descriptor,,SUBALIGN(1)) { __usb_descriptor_start = .; *(".usb.descriptor") KEEP(*(SORT_BY_NAME(".usb.descriptor*"))) __usb_descriptor_end = .; } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
3、编译
gcc -O0 -Wall -DDEBUG_SECTION -o t_section main.cpp
4、elf
# 查看 section readelf -a t_section | grep .init.usb.data [24] .init.usb.data PROGBITS 0000000000004010 00003010 05 .init_array .fini_array .dynamic .got .data .init.usb.data .bss # 查看 变量 readelf -a t_section | grep gs Key to Flags: W (write), A (alloc), X (execute), M (merge), S (strings), I (info), FileSiz MemSiz Flags Align 12: 0000000000004038 9 OBJECT LOCAL DEFAULT 24 _ZL4gs_3 13: 0000000000004044 4 OBJECT LOCAL DEFAULT 24 _ZL4gs_4 14: 0000000000004048 4 OBJECT LOCAL DEFAULT 24 _ZZ8my_printvE4gs_5 15: 000000000000404c 4 OBJECT LOCAL DEFAULT 24 _ZZ8my_printvE4gs_6 22: 0000000000004020 18 OBJECT GLOBAL DEFAULT 24 gs_2 33: 0000000000004010 2 OBJECT GLOBAL DEFAULT 24 gs_1
5、遍历下一个
static int usb_fix_descriptor(struct usb_desc_header *head) { while (head->bLength != 0U) { /* Move to next descriptor */ head = (struct usb_desc_header *)((uint8_t *)head + head->bLength); } if ((head + 1) != __usb_descriptor_end) { LOG_DBG("try to fix next descriptor at %p", head + 1); return usb_fix_descriptor(head + 1); } return 0; }
二、实例2 相同类型
1、代码
/* shows in which sections varaibles are stored in. * globle var, static var, local var. etc... */ #include <stdio.h> /*shorthand for attribute section*/ /* #ifndef __section #define __seciton(s) __attribute__((__section__(#s))) #endif */ /* Simple shorthand for a section definition */ #ifndef __section #define __section(s) __attribute__((__section__(#s))) #endif #define __packed __attribute__((__packed__)) #define DEBUG_SECTION #ifdef DEBUG_SECTION #define __init __section(.init.usb.text) #define __initdata __section(.init.usb.data) #define __initconst __section(.init.usb.rodata) #define __exitdata __section(.exit.usb.data) #define __exit __section(.exit.usb.text) #else /*!DEBUG_SECTION*/ #define __init #define __initdata #define __initconst #define __exitdata #define __exit #endif typedef unsigned char uint8_t; typedef unsigned short uint16_t; struct usb_desc_header { uint8_t bLength; uint8_t bDescriptorType; } __packed; /** USB Standard Device Descriptor defined in spec. Table 9-8 */ struct usb_device_descriptor { uint8_t bLength; uint8_t bDescriptorType; uint16_t bcdUSB; uint8_t bDeviceClass; uint8_t bDeviceSubClass; uint8_t bDeviceProtocol; uint8_t bMaxPacketSize0; uint16_t idVendor; uint16_t idProduct; uint16_t bcdDevice; uint8_t iManufacturer; uint8_t iProduct; uint8_t iSerialNumber; uint8_t bNumConfigurations; } __packed; /** USB Standard Configuration Descriptor defined in spec. Table 9-10 */ struct usb_cfg_descriptor { uint8_t bLength; uint8_t bDescriptorType; uint16_t wTotalLength; uint8_t bNumInterfaces; uint8_t bConfigurationValue; uint8_t iConfiguration; uint8_t bmAttributes; uint8_t bMaxPower; } __packed; usb_desc_header gs_1 __initdata{}; __initdata usb_desc_header gs_2; static usb_desc_header gs_3 __initdata; static usb_desc_header gs_4 __initdata; extern usb_desc_header __init_usb_data_start[]; extern usb_desc_header __init_usb_data_end[]; void my_print(void) { static usb_desc_header gs_5 __initdata; static usb_desc_header gs_6 __initdata; int cnt = 0; for (auto p = __init_usb_data_start; p < __init_usb_data_end; p++) { cnt++; } printf("cnt:%d\n", cnt); } int main() { my_print(); return 0; }
2、lds
t.lds
SECTIONS { PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x400000)); . = SEGMENT_START("text-segment", 0x400000) + 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) } .rela.dyn : { *(.rela.init) *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) *(.rela.fini) *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) *(.rela.ctors) *(.rela.dtors) *(.rela.got) *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) *(.rela.ldata .rela.ldata.* .rela.gnu.linkonce.l.*) *(.rela.lbss .rela.lbss.* .rela.gnu.linkonce.lb.*) *(.rela.lrodata .rela.lrodata.* .rela.gnu.linkonce.lr.*) *(.rela.ifunc) } .rela.plt : { *(.rela.plt) PROVIDE_HIDDEN (__rela_iplt_start = .); *(.rela.iplt) PROVIDE_HIDDEN (__rela_iplt_end = .); } .relr.dyn : { *(.relr.dyn) } . = ALIGN(CONSTANT (MAXPAGESIZE)); .init : { KEEP (*(SORT_NONE(.init))) } .plt : { *(.plt) *(.iplt) } .plt.got : { *(.plt.got) } .plt.sec : { *(.plt.sec) } .text : { *(.text.unlikely .text.*_unlikely .text.unlikely.*) *(.text.exit .text.exit.*) *(.text.startup .text.startup.*) *(.text.hot .text.hot.*) *(SORT(.text.sorted.*)) *(.text .stub .text.* .gnu.linkonce.t.*) /* .gnu.warning sections are handled specially by elf.em. */ *(.gnu.warning) } .fini : { KEEP (*(SORT_NONE(.fini))) } PROVIDE (__etext = .); PROVIDE (_etext = .); PROVIDE (etext = .); . = ALIGN(CONSTANT (MAXPAGESIZE)); /* Adjust the address for the rodata segment. We want to adjust up to the same address within the page on the next page up. */ . = SEGMENT_START("rodata-segment", ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1))); .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*) } /* 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*) } /* Thread Local Storage sections */ .tdata : { PROVIDE_HIDDEN (__tdata_start = .); *(.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) >= 24 ? 24 : 0, .); .got.plt : { *(.got.plt) *(.igot.plt) } .data : { *(.data .data.* .gnu.linkonce.d.*) SORT(CONSTRUCTORS) } .data1 : { *(.data1) } _edata = .; PROVIDE (edata = .); . = .; __init_usb_data_start = .; .init.usb.data : { *(.init.usb.data) } __init_usb_data_end = .; __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 do not pad the .data section. */ . = ALIGN(. != 0 ? 64 / 8 : 1); } .lbss : { *(.dynlbss) *(.lbss .lbss.* .gnu.linkonce.lb.*) *(LARGE_COMMON) } . = ALIGN(64 / 8); . = SEGMENT_START("ldata-segment", .); .lrodata ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) : { *(.lrodata .lrodata.* .gnu.linkonce.lr.*) } .ldata ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) : { *(.ldata .ldata.* .gnu.linkonce.l.*) . = ALIGN(. != 0 ? 64 / 8 : 1); } . = ALIGN(64 / 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) } .gnu.build.attributes : { *(.gnu.build.attributes .gnu.build.attributes.*) } /* 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 5. */ .debug_addr 0 : { *(.debug_addr) } .debug_line_str 0 : { *(.debug_line_str) } .debug_loclists 0 : { *(.debug_loclists) } .debug_macro 0 : { *(.debug_macro) } .debug_names 0 : { *(.debug_names) } .debug_rnglists 0 : { *(.debug_rnglists) } .debug_str_offsets 0 : { *(.debug_str_offsets) } .debug_sup 0 : { *(.debug_sup) } .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) } /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) } }
3、编译
gcc -Tt.lds -o t_section main.cpp
cmake_minimum_required(VERSION 3.11.0) project(t2 VERSION 0.1.0 LANGUAGES C CXX) set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -T ${CMAKE_SOURCE_DIR}/t.lds") include(CTest) enable_testing() add_executable(t2 main.cpp) set(CPACK_PROJECT_NAME ${PROJECT_NAME}) set(CPACK_PROJECT_VERSION ${PROJECT_VERSION}) include(CPack)
4、elf
# 查看 .init.usb.data readelf -a t_section | grep .init.usb.data [27] .init.usb.data PROGBITS 0000000000404030 00003030 05 .init_array .fini_array .dynamic .got .got.plt .data .init.usb.data .bss 34: 000000000040403c 0 NOTYPE GLOBAL DEFAULT 27 __init_usb_data_end 38: 0000000000404030 0 NOTYPE GLOBAL DEFAULT 27 __init_usb_data_start # 查看 gs readelf -a t_section | grep gs Key to Flags: W (write), A (alloc), X (execute), M (merge), S (strings), I (info), FileSiz MemSiz Flags Align 12: 0000000000404034 2 OBJECT LOCAL DEFAULT 27 _ZL4gs_3 13: 0000000000404036 2 OBJECT LOCAL DEFAULT 27 _ZL4gs_4 14: 0000000000404038 2 OBJECT LOCAL DEFAULT 27 _ZZ8my_printvE4gs_5 15: 000000000040403a 2 OBJECT LOCAL DEFAULT 27 _ZZ8my_printvE4gs_6 22: 0000000000404032 2 OBJECT GLOBAL DEFAULT 27 gs_2 35: 0000000000404030 2 OBJECT GLOBAL DEFAULT 27 gs_1
5、遍历下一个
int cnt = 0; for (auto p = __init_usb_data_start; p < __init_usb_data_end; p++) { cnt++; } printf("cnt:%d\n", cnt);