LeetCode Logo

分享|ELF文件中的符号类型

50
2026.11.05
2026.11.05
发布于 广东
以下是 GNU nm 常见的完整符号类型。通常大写表示全局符号,小写表示局部符号,但 U、u 等有特殊含义。
类型
含义
A
Absolute,绝对地址符号,不会因重定位改变
B / b
BSS 段中的全局/局部符号,通常用于零初始化或未显式初始化的数据
C / c
Common symbol,未分配段的公共符号,链接时合并或分配
D / d
已初始化数据段中的全局/局部符号
G / g
small data 段中的已初始化全局/局部符号
I
对另一个符号的间接引用
i
间接函数(GNU IFUNC);在 PE 文件中也可能表示 DLL 相关符号
N
调试符号
n
局部只读数据或目标格式定义的特殊只读符号
P / p
栈展开、过程描述或目标架构特定段中的符号
R / r
只读数据段中的全局/局部符号,例如常量和字符串
S / s
small BSS 段中的未初始化全局/局部符号
T / t
代码段中的全局/局部符号,通常是函数
U
Undefined,当前目标文件引用了该符号,但没有提供定义
u
GNU unique global symbol,动态链接时整个进程中保持唯一
V / v
弱对象符号;未定义时链接不会报错
W / w
弱非对象符号,通常是弱函数;未定义时链接不会报错
-
a.out 文件中的 STABS 调试符号
?
未知类型或目标文件格式特有的符号

常见示例:
T functionName # 全局函数 t localFunction # 当前 .cc 内的局部函数 D globalValue # 已初始化全局变量 B zeroInitialized # BSS 全局对象 b localStatic # BSS 局部静态对象 R constTable # 只读全局数据 U externalFunction # 引用其他 .o 提供的函数 W weakFunction # 弱函数

small BSS 和普通 BSS 在语义上相同,都存放零初始化或未显式初始化的静态存储期对象。区别主要在访问方式和目标平台优化:
对比项
BSS
small BSS
常见段名
.bss
.sbss
nm 类型
B / b
S / s
数据特点
零初始化、通常不占可执行文件的数据空间
同样为零初始化
对象大小
没有特殊限制
通常放较小对象
访问方式
普通地址加载
可通过全局指针等短偏移指令访问
目的
保存零初始化数据
减少指令数量和代码体积、提高访问效率
例如在支持 small data 的架构上:
C++
int largeBuffer[1024]; // 通常进入 .bss
int smallCounter;      // 可能进入 .sbss
small BSS 常见于 MIPS、PowerPC、RISC-V 等嵌入式工具链。编译器把尺寸低于某个阈值的对象放入 .sbss,代码可以通过全局指针寄存器加较短的偏移量访问:
C++
普通 BSS:构造完整地址 -> 访问数据
small BSS:gp 寄存器 + 短偏移 -> 访问数据
对象是否进入 .sbss 由以下因素决定:
- 目标 CPU 和 ABI 是否支持 small data;
- 编译器的 small-data 阈值;
- 编译选项,例如部分工具链的 -G <size>;
- 链接脚本对 .sbss 的布局;
- 对象的大小和可见性。

因此,B 和 S 不代表 C++ 生命周期或初始化逻辑不同,只代表链接器把对象放到了不同的段中。两者在程序启动时都被清零,通常都属于 ELF 的 NOBITS 段,不需要在二进制文件中保存完整的零数据。
评论 (0)