使用binutils工具解析目标文件符号表(叁)
目录
1.前言
2.示例代码
3.使用objdump命令输出目标文件符号表
4.解析输出的符号表
前言
本小节主要是对使用binutils工具输出的目标文件符号表信息进行分析。由于在Windows系统中使用objdump命令输出符号表的信息与使用readelf命令输出的符号表信息有出入,并且Windows系统中的信息更复杂且难以理解,所以本小节对这些内容进行解析。
示例代码
本篇博客的示例C语言代码如下:
int shared = 1;void swap(int* a, int* b){*a ^= *b ^= *a ^= *b;
}
使用objdump命令输出目标文件符号表
在使用gcc -c指令将代码编译成目标文件以后,我们使用以下命令输出目标文件的符号表信息:
objdump -t xx.o
使用了objdump命令输出的符号表信息如下:
SYMBOL TABLE:
[ 0](sec -2)(fl 0x00)(ty 0)(scl 103) (nx 1) 0x0000000000000000 test3_b.c
File
[ 2](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 1) 0x0000000000000000 swap
AUX tagndx 0 ttlsiz 0x0 lnnos 0 next 0
[ 4](sec 1)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x0000000000000000 .text
AUX scnlen 0x4b nreloc 0 nlnno 0
[ 6](sec 2)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x0000000000000000 .data
AUX scnlen 0x4 nreloc 0 nlnno 0
[ 8](sec 3)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x0000000000000000 .bss
AUX scnlen 0x0 nreloc 0 nlnno 0
[ 10](sec 4)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x0000000000000000 .xdata
AUX scnlen 0x8 nreloc 0 nlnno 0
[ 12](sec 5)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x0000000000000000 .pdata
AUX scnlen 0xc nreloc 3 nlnno 0
[ 14](sec 6)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x0000000000000000 .rdata$zzz
AUX 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代表的数字如下表所示:
值 | 名称 | 含义 |
---|---|---|
0 | C_EFCN | 伪函数结束(COFF 调试用,已废弃) |
1 | C_NULL | 无效符号(空) |
2 | C_AUTO | 自动变量(栈上,函数内局部变量) |
3 | C_EXT | 外部符号(external,可能在其他文件定义) |
4 | C_STAT | 静态符号(static,全局静态变量或静态函数) |
5 | C_REG | 寄存器变量 |
6 | C_EXTDEF | 外部定义符号(external definition) |
7 | C_LABEL | 分支标签(label) |
8 | C_ULABEL | 未定义的标签 |
9 | C_MOS | 结构体成员(member of structure) |
10 | C_ARG | 函数参数 |
11 | C_STRTAG | 结构体标签 |
12 | C_MOU | 联合体成员 |
13 | C_UNTAG | 联合体标签 |
14 | C_TPDEF | 类型定义(typedef) |
15 | C_USTATIC | 未初始化的静态变量(未链接时存在) |
16 | C_ENTAG | 枚举标签 |
17 | C_MOE | 枚举成员 |
18 | C_REGPARM | 寄存器参数 |
19 | C_FIELD | 位域成员 |
20 | C_BLOCK | 代码块开始/结束标记 |
21 | C_FCN | 函数开始/结束标记 |
22 | C_EOS | 结构/联合/枚举结束 |
23 | C_FILE | 文件名(符号表中表示文件) |
24 | C_SECTION | 段(section)符号 |
25 | C_WEAKEXT | 弱外部符号(weak external) |
26 | C_CLRFILE | 清理文件记录(很少用) |
100 | C_BLOCK_END | 代码块结束(扩展) |
101 | C_FCN_END | 函数结束(扩展) |
102 | C_SECT_EXT | 段外部(扩展) |
103 | C_FILE_NAME | 文件名(扩展,MinGW/objdump 常用) |
6.下一个符号索引:格式为(nx N),其中N代表数字,含义是表示后续是否存在条目,例如(nx 1)
剩下的地址和符号名没有多的其他含义
PS:欢迎各位读者对作者的文章进行勘误,万分感谢!!!