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

目录
相关文章
|
9天前
|
Linux
Linux系统之whereis命令的基本使用
Linux系统之whereis命令的基本使用
50 23
Linux系统之whereis命令的基本使用
|
3月前
|
Linux 网络安全 数据安全/隐私保护
Linux 超级强大的十六进制 dump 工具:XXD 命令,我教你应该如何使用!
在 Linux 系统中,xxd 命令是一个强大的十六进制 dump 工具,可以将文件或数据以十六进制和 ASCII 字符形式显示,帮助用户深入了解和分析数据。本文详细介绍了 xxd 命令的基本用法、高级功能及实际应用案例,包括查看文件内容、指定输出格式、写入文件、数据比较、数据提取、数据转换和数据加密解密等。通过掌握这些技巧,用户可以更高效地处理各种数据问题。
347 8
|
3月前
|
监控 Linux
如何检查 Linux 内存使用量是否耗尽?这 5 个命令堪称绝了!
本文介绍了在Linux系统中检查内存使用情况的5个常用命令:`free`、`top`、`vmstat`、`pidstat` 和 `/proc/meminfo` 文件,帮助用户准确监控内存状态,确保系统稳定运行。
1134 6
|
3月前
|
Linux
在 Linux 系统中,“cd”命令用于切换当前工作目录
在 Linux 系统中,“cd”命令用于切换当前工作目录。本文详细介绍了“cd”命令的基本用法和常见技巧,包括使用“.”、“..”、“~”、绝对路径和相对路径,以及快速切换到上一次工作目录等。此外,还探讨了高级技巧,如使用通配符、结合其他命令、在脚本中使用,以及实际应用案例,帮助读者提高工作效率。
201 3
|
3月前
|
监控 安全 Linux
在 Linux 系统中,网络管理是重要任务。本文介绍了常用的网络命令及其适用场景
在 Linux 系统中,网络管理是重要任务。本文介绍了常用的网络命令及其适用场景,包括 ping(测试连通性)、traceroute(跟踪路由路径)、netstat(显示网络连接信息)、nmap(网络扫描)、ifconfig 和 ip(网络接口配置)。掌握这些命令有助于高效诊断和解决网络问题,保障网络稳定运行。
144 2
|
22天前
|
网络协议 Unix Linux
深入解析:Linux网络配置工具ifconfig与ip命令的全面对比
虽然 `ifconfig`作为一个经典的网络配置工具,简单易用,但其功能已经不能满足现代网络配置的需求。相比之下,`ip`命令不仅功能全面,而且提供了一致且简洁的语法,适用于各种网络配置场景。因此,在实际使用中,推荐逐步过渡到 `ip`命令,以更好地适应现代网络管理需求。
34 11
|
2月前
|
Linux Shell
Linux 10 个“who”命令示例
Linux 10 个“who”命令示例
101 14
Linux 10 个“who”命令示例
|
2月前
|
Ubuntu Linux
Linux 各发行版安装 ping 命令指南
如何在不同 Linux 发行版(Ubuntu/Debian、CentOS/RHEL/Fedora、Arch Linux、openSUSE、Alpine Linux)上安装 `ping` 命令,详细列出各发行版的安装步骤和验证方法,帮助系统管理员和网络工程师快速排查网络问题。
214 20