Linux Section

简介: Linux Section

一、实例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

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)

如何在 CMake 中使用特定的链接脚本(*.lds)

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

目录
相关文章
|
5天前
|
Linux
在 Linux 系统中,“cd”命令用于切换当前工作目录
在 Linux 系统中,“cd”命令用于切换当前工作目录。本文详细介绍了“cd”命令的基本用法和常见技巧,包括使用“.”、“..”、“~”、绝对路径和相对路径,以及快速切换到上一次工作目录等。此外,还探讨了高级技巧,如使用通配符、结合其他命令、在脚本中使用,以及实际应用案例,帮助读者提高工作效率。
23 3
|
5天前
|
监控 安全 Linux
在 Linux 系统中,网络管理是重要任务。本文介绍了常用的网络命令及其适用场景
在 Linux 系统中,网络管理是重要任务。本文介绍了常用的网络命令及其适用场景,包括 ping(测试连通性)、traceroute(跟踪路由路径)、netstat(显示网络连接信息)、nmap(网络扫描)、ifconfig 和 ip(网络接口配置)。掌握这些命令有助于高效诊断和解决网络问题,保障网络稳定运行。
18 2
|
13天前
|
缓存 监控 Linux
|
16天前
|
Linux Shell 数据安全/隐私保护
|
17天前
|
域名解析 网络协议 安全
|
23天前
|
运维 监控 网络协议
|
24天前
|
监控 Linux Shell
|
5天前
|
安全 网络协议 Linux
本文详细介绍了 Linux 系统中 ping 命令的使用方法和技巧,涵盖基本用法、高级用法、实际应用案例及注意事项。
本文详细介绍了 Linux 系统中 ping 命令的使用方法和技巧,涵盖基本用法、高级用法、实际应用案例及注意事项。通过掌握 ping 命令,读者可以轻松测试网络连通性、诊断网络问题并提升网络管理能力。
23 3