技术书籍精读笔记:程序员的自我修养-链接,转载与库(叁)

本文分析了使用binutils工具输出的目标文件符号表信息。通过编译示例C代码并使用objdump命令,展示了Windows系统下符号表的复杂输出格式。重点解析了符号表各列的含义,包括索引、节区索引、标志位、符号类型和存储类别等关键信息。其中详细说明了节区索引的数值含义、标志位的十六进制组合表示方法,以及存储类别的具体分类。文章特别指出工具输出中的ty20与代码定义差异的原因,并提供了完整的存储类别值对照表。最后提醒读者注意工具对十六进制值的简化表示可能导致的解读差异。

作者
WildPointer
发布
2025.08.10
专栏
技术书籍精读笔记
阅读
约 5 分钟 / 755 次原文浏览
技术书籍精读笔记:程序员的自我修养-链接,转载与库(叁)

前言

本小节主要是对使用binutils工具输出的目标文件符号表信息进行分析。由于在Windows系统中使用objdump命令输出符号表的信息与使用readelf命令输出的符号表信息有出入,并且Windows系统中的信息更复杂且难以理解,所以本小节对这些内容进行解析。


示例代码

本篇博客的示例C语言代码如下:

cpp
int shared = 1;void swap(int* a, int* b){	*a ^= *b ^= *a ^= *b;	}

使用objdump命令输出目标文件符号表

在使用gcc -c指令将代码编译成目标文件以后,我们使用以下命令输出目标文件的符号表信息:

bash
objdump -t xx.o

使用了objdump命令输出的符号表信息如下:

bash
SYMBOL TABLE:[  0](sec -2)(fl 0x00)(ty   0)(scl 103) (nx 1) 0x0000000000000000 test3_b.cFile[  2](sec  1)(fl 0x00)(ty  20)(scl   2) (nx 1) 0x0000000000000000 swapAUX tagndx 0 ttlsiz 0x0 lnnos 0 next 0[  4](sec  1)(fl 0x00)(ty   0)(scl   3) (nx 1) 0x0000000000000000 .textAUX scnlen 0x4b nreloc 0 nlnno 0[  6](sec  2)(fl 0x00)(ty   0)(scl   3) (nx 1) 0x0000000000000000 .dataAUX scnlen 0x4 nreloc 0 nlnno 0[  8](sec  3)(fl 0x00)(ty   0)(scl   3) (nx 1) 0x0000000000000000 .bssAUX scnlen 0x0 nreloc 0 nlnno 0[ 10](sec  4)(fl 0x00)(ty   0)(scl   3) (nx 1) 0x0000000000000000 .xdataAUX scnlen 0x8 nreloc 0 nlnno 0[ 12](sec  5)(fl 0x00)(ty   0)(scl   3) (nx 1) 0x0000000000000000 .pdataAUX scnlen 0xc nreloc 3 nlnno 0[ 14](sec  6)(fl 0x00)(ty   0)(scl   3) (nx 1) 0x0000000000000000 .rdata$zzzAUX scnlen 0x3f nreloc 0 nlnno 0[ 16](sec  2)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x0000000000000000 shared

解析输出的符号表

结合objdump命令输出的符号表信息,我们先将输出的信息划分为具体的列,每一列代表的含义如图所示:

图1.符号表列的含义

在了解了每一个列的含义以后,我将详细分析每一个列的具体信息。具体如下:
1.索引:符号在符号表中的唯一标识

2.节区索引:如同(sec -2)和(sec 1)这两个节去索引所示,主要的节区的索引格式为(sec N)。其中N代表符号所属的节区,具体的含义如下表:

N含义
-2文件信息
0未定义(需要链接时确定的符号)
1.text代码段
2.data已初始化数据段
3.bss未初始化数据段

表1.节区索引含义表

3.标志位:该信息主要由十六进制值来表示,通过与fl结合表示应该符号属性的组合,如fl 0x00,具体所能表示的含义如下表:

标识含义十六进制值
l局部符号0x01
g全局符号0x02
!符号定义冲突0x03
u唯一全局0x04
w弱符号0x80
c构造函数0x100
d调试符号0x200
D动态符号0x400
I间接引用0x800
F函数0x08
O数据对象0x10
f文件名0x20
S节区0x40

表2.标志位含义表

PS:有时候标志位的值是0x12或者0x0A等,但是参考标志位含义表是不存在的,这是由于工具对十六进制简化表示导致的。例如:0x12 = 0x02(全局) + 0x10(对象)故该含义代表全局对象,而0x0A = 0x02(全局) + 0x80(弱符号) + 0x08(函数)故该含义代表弱全局函数

4.符号类型:符号类型分位为低四位(BaseType)和高四位(ComplexType),具体的含义可以参考下表,例如:ty 20代表的含义是int *,这跟代码中sawp符号的定义有出入,这主要原因是工具的简化结果。

图2.符号类型参考图

5.存储类别:存储类别格式为(scl N),其中N代表的数字如下表所示:

值名称含义
0C_EFCN伪函数结束(COFF 调试用,已废弃)
1C_NULL无效符号(空)
2C_AUTO自动变量(栈上,函数内局部变量)
3C_EXT外部符号(external,可能在其他文件定义)
4C_STAT静态符号(static,全局静态变量或静态函数)
5C_REG寄存器变量
6C_EXTDEF外部定义符号(external definition)
7C_LABEL分支标签(label)
8C_ULABEL未定义的标签
9C_MOS结构体成员(member of structure)
10C_ARG函数参数
11C_STRTAG结构体标签
12C_MOU联合体成员
13C_UNTAG联合体标签
14C_TPDEF类型定义(typedef)
15C_USTATIC未初始化的静态变量(未链接时存在)
16C_ENTAG枚举标签
17C_MOE枚举成员
18C_REGPARM寄存器参数
19C_FIELD位域成员
20C_BLOCK代码块开始/结束标记
21C_FCN函数开始/结束标记
22C_EOS结构/联合/枚举结束
23C_FILE文件名(符号表中表示文件)
24C_SECTION段(section)符号
25C_WEAKEXT弱外部符号(weak external)
26C_CLRFILE清理文件记录(很少用)
100C_BLOCK_END代码块结束(扩展)
101C_FCN_END函数结束(扩展)
102C_SECT_EXT段外部(扩展)
103C_FILE_NAME文件名(扩展,MinGW/objdump 常用)

6.下一个符号索引:格式为(nx N),其中N代表数字,含义是表示后续是否存在条目,例如(nx 1)

剩下的地址和符号名没有多的其他含义


PS:欢迎各位读者对作者的文章进行勘误,万分感谢!!!

23次原文点赞;这里的喜欢仅保存在本机
WildPointer

专注系统编程、工程实践与底层技术,记录 C++、Qt、OpenCV 与 VTK 的学习和实践。