《程序员的自我修养》读书笔记2——使用KEIL研究ELF文件的符号表

本文深入解析了b.o文件的ELF格式结构,详细分析了文件头部信息、各节段特性、符号表和节名字符串表等内容,揭示了ARM架构下目标文件的内部组织方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

代码

参考第4章,使用如下代码:

 

建立工程:

 

编译结果:

 

目标文件分析

先看b.o文件:

fromelf -v b.o

打印结果:

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

** ELF Header Information

    File Name: b.o

    Machine class: ELFCLASS32 (32-bit)
    Data encoding: ELFDATA2LSB (Little endian)
    Header version: EV_CURRENT (Current version)
    Operating System ABI: none
    ABI Version: 0
    File Type: ET_REL (Relocatable object) (1)
    Machine: EM_ARM (ARM)

    Entry offset (in SHF_ENTRYSECT section): 0x00000000
    Flags: None (0x05000000)

    ARM ELF revision: 5 (ABI version 2)

    Header size: 52 bytes (0x34)
    Program header entry size: 0 bytes (0x0)
    Section header entry size: 40 bytes (0x28)

    Program header entries: 0
    Section header entries: 11

    Program header offset: 0 (0x00000000)
    Section header offset: 1096 (0x00000448)

    Section header string table index: 8

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

** Section #1

    Name        : i.swap
    Type        : SHT_PROGBITS (0x00000001)
    Flags       : SHF_ALLOC + SHF_EXECINSTR (0x00000006)
    Addr        : 0x00000000
    File Offset : 52 (0x34)
    Size        : 22 bytes (0x16)
    Link        : SHN_UNDEF
    Info        : 0
    Alignment   : 2
    Entry Size  : 0


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

** Section #2

    Name        : .arm_vfe_header
    Type        : SHT_PROGBITS (0x00000001)
    Flags       : None (0x00000000)
    Addr        : 0x00000000
    File Offset : 76 (0x4c)
    Size        : 4 bytes (0x4)
    Link        : SHN_UNDEF
    Info        : 0
    Alignment   : 4
    Entry Size  : 0


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

** Section #3

    Name        : .comment
    Type        : SHT_PROGBITS (0x00000001)
    Flags       : None (0x00000000)
    Addr        : 0x00000000
    File Offset : 80 (0x50)
    Size        : 375 bytes (0x177)
    Link        : SHN_UNDEF
    Info        : 0
    Alignment   : 1
    Entry Size  : 0

    Component: ARM Compiler 5.06 update 6 (build 750) Tool: ArmCC [4d3637]
    ArmCC --c99 --split_sections -c --gnu -o.\objects\b.o --depend=.\objects\b.d --cpu=Cortex-M3 --apcs=interwork -O0 --diag_suppress=9931 -I.\RTE\_DebugOnFlash -IC:\Keil_v5\ARM\Packs\Keil\STM32F1xx_DFP\2.3.0\Device\Include -IC:\Keil_v5\ARM\CMSIS\Include -D__UVISION_VERSION=529 -DSTM32F10X_XL ..\..\src\b.c

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

** Section #4

    Name        : .data
    Type        : SHT_PROGBITS (0x00000001)
    Flags       : SHF_ALLOC + SHF_WRITE (0x00000003)
    Addr        : 0x00000000
    File Offset : 456 (0x1c8)
    Size        : 4 bytes (0x4)
    Link        : SHN_UNDEF
    Info        : 0
    Alignment   : 4
    Entry Size  : 0


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

** Section #5

    Name        : .debug_frame
    Type        : SHT_PROGBITS (0x00000001)
    Flags       : None (0x00000000)
    Addr        : 0x00000000
    File Offset : 460 (0x1cc)
    Size        : 68 bytes (0x44)
    Link        : SHN_UNDEF
    Info        : 0
    Alignment   : 1
    Entry Size  : 0


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

** Section #7

    Name        : .rel.debug_frame
    Type        : SHT_REL (0x00000009)
    Flags       : None (0x00000000)
    Addr        : 0x00000000
    File Offset : 688 (0x2b0)
    Size        : 16 bytes (0x10)
    Link        : Section 6 (.symtab)
    Info        : Section 5 (.debug_frame)
    Alignment   : 4
    Entry Size  : 8


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

** Section #6

    Name        : .symtab
    Type        : SHT_SYMTAB (0x00000002)
    Flags       : None (0x00000000)
    Addr        : 0x00000000
    File Offset : 528 (0x210)
    Size        : 160 bytes (0xa0)
    Link        : Section 9 (.strtab)
    Info        : Last local symbol no = 6
    Alignment   : 4
    Entry Size  : 16


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

** Section #8

    Name        : .shstrtab
    Type        : SHT_STRTAB (0x00000003)
    Flags       : None (0x00000000)
    Addr        : 0x00000000
    File Offset : 704 (0x2c0)
    Size        : 98 bytes (0x62)
    Link        : SHN_UNDEF
    Info        : 0
    Alignment   : 1
    Entry Size  : 0


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

** Section #9

    Name        : .strtab
    Type        : SHT_STRTAB (0x00000003)
    Flags       : None (0x00000000)
    Addr        : 0x00000000
    File Offset : 802 (0x322)
    Size        : 222 bytes (0xde)
    Link        : SHN_UNDEF
    Info        : 0
    Alignment   : 1
    Entry Size  : 0


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

** Section #10

    Name        : .ARM.attributes
    Type        : SHT_ARM_ATTRIBUTES (0x70000003)
    Flags       : None (0x00000000)
    Addr        : 0x00000000
    File Offset : 1024 (0x400)
    Size        : 72 bytes (0x48)
    Link        : SHN_UNDEF
    Info        : 0
    Alignment   : 1
    Entry Size  : 0

    'aeabi' file build attributes:
    0x000000:   43 32 2e 30 39 00 05 43 6f 72 74 65 78 2d 4d 33    C2.09..Cortex-M3
    0x000010:   00 06 0a 07 4d 09 02 11 01 12 02 14 02 17 01 18    ....M...........
    0x000020:   01 19 01 1a 01 1e 06 22 01                         .......".
        Tag_conformance = "2.09"
        Tag_CPU_name = "Cortex-M3"
        Tag_CPU_arch = ARM v7 (=10)
        Tag_CPU_arch_profile = The microcontroller profile 'M' (e.g. for Cortex M3) (=77)
        Tag_THUMB_ISA_use = Thumb2 instructions were permitted (implies Thumb instructions permitted) (=2)
        Tag_ABI_PCS_GOT_use = Data are imported directly (=1)
        Tag_ABI_PCS_wchar_t = Size of wchar_t is 2 (=2)
        Tag_ABI_FP_denormal = This code was permitted to require that the sign of a flushed-to-zero number be preserved in the sign of 0 (=2)
        Tag_ABI_FP_number_model = This code was permitted to use only IEEE 754 format FP numbers (=1)
        Tag_ABI_align_needed = Code was permitted to depend on the 8-byte alignment of 8-byte data items (=1)
        Tag_ABI_align_preserved = Code was required to preserve 8-byte alignment of 8-byte data objects (=1)
        Tag_ABI_enum_size = Enum values occupy the smallest container big enough to hold all values (=1)
        Tag_ABI_optimization_goals = Optimized for best debugging illusion, speed and small size sacrificed (=6)
        Tag_CPU_unaligned_access = The producer was permitted to generate architecture v6-style unaligned data accesses (=1)

    'ARM' file build attributes:
    0x000000:   12 01                                              ..


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

从文件头部信息中可以得知:

b.o是可重定位对象(ET_REL):b.o不是最终的可执行文件,而是中间目标文件。

Entry offset 为0。

没有程序头表(Program header entries)

有11个节表头,从0x0448开始。每40个字节(0x28)表示一个。

 

空节

第0#节为全零:(0x0448~0x46F).

 

节名字符串表

文件头中指明,节名字符串表在第8个节。起始地址在0x0448 + 0x28 * 8 = 0x0588

字节内容为:

与结构体的元素相对应的关系为:

元素数值
sh_name0x19
sh_type0x03
sh_flags0x00
sh_addr0x00
sh_offset0x02C0
sh_size0x62
sh_link0x00
sh_info0x00
sh_addralign0x01
sh_entsize0x00

 

解析结果为:

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

** Section #8

    Name        : .shstrtab
    Type        : SHT_STRTAB (0x00000003)
    Flags       : None (0x00000000)
    Addr        : 0x00000000
    File Offset : 704 (0x2c0)
    Size        : 98 bytes (0x62)
    Link        : SHN_UNDEF
    Info        : 0
    Alignment   : 1
    Entry Size  : 0


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

可以看出,字符串在ELF文件的偏移量为0x02C0,总长度为0x62

本节的名称在0x19处,即文件中的0x02c0 + 0x0019 = 0x02d9开始:正是“.shstrtab”

 

代码节

第1个节为代码。看看0x0470~0x0497:

与结构体的元素相对应的关系为:

元素数值
sh_name0x5B
sh_type0x01
sh_flags0x06
sh_addr0x00
sh_offset0x34
sh_size0x16
sh_link0x00
sh_info0x00
sh_addralign0x02
sh_entsize0x00

解析结果为:

** Section #1

    Name        : i.swap
    Type        : SHT_PROGBITS (0x00000001)
    Flags       : SHF_ALLOC + SHF_EXECINSTR (0x00000006)
    Addr        : 0x00000000
    File Offset : 52 (0x34)
    Size        : 22 bytes (0x16)
    Link        : SHN_UNDEF
    Info        : 0
    Alignment   : 2
    Entry Size  : 0


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

同样的,名称在节名字符串表中的偏移量为0x5B,即:"i.swap"

代码内容在0x34,长度为0x16。

正是函数swap的汇编指令:

通过-c参数也要打印出来:

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

** Section #1 'i.swap' (SHT_PROGBITS) [SHF_ALLOC + SHF_EXECINSTR]
    Size   : 22 bytes (alignment 2)
    Address: 0x00000000

    $t
    i.swap
    swap
        0x00000000:    6802        .h      LDR      r2,[r0,#0]
        0x00000002:    680b        .h      LDR      r3,[r1,#0]
        0x00000004:    405a        Z@      EORS     r2,r2,r3
        0x00000006:    6002        .`      STR      r2,[r0,#0]
        0x00000008:    680b        .h      LDR      r3,[r1,#0]
        0x0000000a:    405a        Z@      EORS     r2,r2,r3
        0x0000000c:    600a        .`      STR      r2,[r1,#0]
        0x0000000e:    6803        .h      LDR      r3,[r0,#0]
        0x00000010:    405a        Z@      EORS     r2,r2,r3
        0x00000012:    6002        .`      STR      r2,[r0,#0]
        0x00000014:    4770        pG      BX       lr

 

 

符号表

第6节为符号表。表头位置在0x0448 + 0x28 * 6 = 0x0538

与结构体的元素相对应的关系为:

元素数值
sh_name0x34
sh_type0x02
sh_flags0x00
sh_addr0x00
sh_offset0x0210
sh_size0xA0
sh_link0x09
sh_info0x07
sh_addralign0x04
sh_entsize0x10

解析结果为:

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

** Section #6

    Name        : .symtab
    Type        : SHT_SYMTAB (0x00000002)
    Flags       : None (0x00000000)
    Addr        : 0x00000000
    File Offset : 528 (0x210)
    Size        : 160 bytes (0xa0)
    Link        : Section 9 (.strtab)
    Info        : Last local symbol no = 6
    Alignment   : 4
    Entry Size  : 16


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

说明:符号表的内容在文件0x0210处,总大小为0xA0(160个字符)。每个符号的描述符有16个字节,因此,共有10个符号项。

符号表项

一个符号表表项的数据结构定义如下:

/* Symbol table entry.  */
 
typedef struct
{
  Elf32_Word    st_name;                /* Symbol name (string tbl index) */
  Elf32_Addr    st_value;               /* Symbol value */
  Elf32_Word    st_size;                /* Symbol size */
  unsigned char st_info;                /* Symbol type and binding */
  unsigned char st_other;               /* Symbol visibility */
  Elf32_Section st_shndx;               /* Section index */
} Elf32_Sym;
 

其中,st_info字节分为两部分,高4位为绑定属性,低4位为类型。

高4位定义符号的绑定[binding ]:

  •     STB_LOCAL (0) symbol is local to the file
  •     STB_GLOBAL (1) symbol is visible to all object files
  •     STB_WEAK (2) symbol is global with lower precedence

低4位定义符号的类型:

  •     STT_NOTYPE (0)    无类型
  •     STT_OBJECT (1)    数据对象(变量)
  •     STT_FUNC (2)      函数
  •     STT_SECTION (3)   section名
  •     STT_FILE (4)      文件名

 

st_shndx:定义符号section的索引.特殊的section数包括:

  •     SHN_UNDEF (0x0000)   未定义section
  •     SHN_ABS (0xfff1)     绝对, 不可重定位符号
  •     SHN_COMMON (0xfff2) 不分配, 外部变量

 

 

具体分析

第0个符号表项的内容为全零。

以第1个符号表项来分析:

元素数值
st_name0x000000D0
st_value0x00000000
st_size0x00000000
st_info0x04
st_other0x00
st_shndx0xFFF1

st_name: 这里不再是相对shstrtab的偏移,而是基于strtab的。第9个节为strtab,起始地址为0x322(是接在shstrtab的后面),其名称字符串地址为0x0322+0x00D0=03F2,内容为:“..\..\src\b.c”

st_info=0x04.  高4位=0=STB_LOCAL;低4位=4=STT_FILE。

st_shndx=0xFFF1=SHN_ABS=绝对符号,不可重定位。

 

 

再看第7个:起始地址为0x0280。

元素数值
st_name0x00000016
st_value0x00000000
st_size0x00000004
st_info0x11
st_other0x02
st_shndx0x0004

st_name=0x0322+0x0016=0x0338="shared",是代码中变量shared的名字。

st_value=0x00000000。在段.data中的偏移量。

st_size=0x04=变量的大小(int型,32位,占4个字节)

st_info=0x11.  高4位=Binding=1=STB_GLOBAL;低4位=Type=1=STT_OBJECT=数据对象,即变量。

st_shndx=0x0004  --> section #4(.data节)

 

最后,再来看第8个:起始地址为0x0290。

元素数值
st_name0x000000C2
st_value0x00000001
st_size0x00000016
st_info0x12
st_other0x02
st_shndx0x0001

st_name=0x0322+0x00C2=0x03E4="swap"

st_value=0x00000001。在段i.swap中的偏移量。本来应该是0,但由于是thumb指令,需要加1.

st_size=0x16=swap函数代码的大小,参见“代码节”

st_info=0x12.  高4位=Binding=1=STB_GLOBAL;低4位=Type=2=STT_FUNC

st_shndx=0x0001  --> section #1(i.swap节)

 

验证

使用命令打印符号表:fromelf -s b.o

** Section #6 '.symtab' (SHT_SYMTAB)
    Size   : 160 bytes (alignment 4)
    String table #9 '.strtab'
    Last local symbol no. 6

    Symbol table .symtab (9 symbols, 6 local)

      #  Symbol Name                Value      Bind  Sec  Type  Vis  Size
    ========================================================================

      1  ..\..\src\b.c              0x00000000   Lc  Abs  File  De
      2  $t                         0x00000000   Lc    1   --   De
      3  .data                      0x00000000   Lc    4  Sect  De   0x4
      4  i.swap                     0x00000000   Lc    1  Sect  De
      5  BuildAttributes$$THM_ISAv4$P$D$K$B$S$PE$A:L22UL41UL21$X:L11$S22US41US21$IEEE1$IW$USESV6$~STKCKD$USESV7$~SHL$OSPACE$EBA8$REQ8$PRES8$EABIv2
                                    0x00000000   Lc  Abs   --   De
      6  __ARM_grp_.debug_frame$5   0x00000000   Lc    5  Data  De
      7  shared                     0x00000000   Gb    4  Data  Hi   0x4
      8  swap                       0x00000001   Gb    1  Code  Hi   0x16
      9  Lib$$Request$$armlib       0x00000000   Wk  Ref  Code  Hi

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值