nm命令和其内容详解
nm命令用于将二进制文件或可执行文件(尤其是动态库)进行剖析
常用参数
1 // 可以直接man 2 -A 或-o或 --print-file-name:打印出每个符号属于的文件 3 -a或--debug-syms:打印出所有符号,包括debug符号 4 -B:BSD码显示 5 -C或--demangle[=style]:对低级符号名称进行解码,C++文件需要添加 6 --no-demangle:不对低级符号名称进行解码,默认参数 7 -D 或--dynamic:显示动态符号而不显示普通符号,一般用于动态库 8 -f format或--format=format:显示的形式,默认为bsd,可选为sysv和posix 9 -g或--extern-only:仅显示外部符号 10 -h或--help:国际惯例,显示命令的帮助信息 11 -n或-v或--numeric-sort:显示的符号以地址排序,而不是名称排序 12 -p或--no-sort:不对显示内容进行排序 13 -P或--portability:使用POSIX.2标准 14 -V或--version:国际管理,查看版本
下面来进行一段代码解析
1 // co.c 2 #include <stdio.h> 3 int a = 1; 4 int b; 5 void func() { 6 printf("Hello World\n"); 7 } 8 int main() { 9 int a = 1; 10 func(); 11 return 0; 12 }
进行编译(预处理器,编译器,汇编器)生成.o重定向文件
1 gcc co.c
用nm命令来查看
1 ➜ C nm -C co.o 2 3 0000000000000000 D a 4 0000000000000004 C b 5 0000000000000000 T func 6 U _GLOBAL_OFFSET_TABLE_ 7 0000000000000017 T main 8 U puts
下面我们再来解析输出信息中各部分所代表的意思吧
- 首先,前面那一串数字,指的就是地址
- 然后,我们发现,每一个条目前面还有一个字母,类似’U’,‘B’,'D等等,其实这些符号代表的就是当前条目所对应的内存所在部分
- 最右边的就是对应的符号内容了
首先来看看这些符号的含义
1 A :符号的值是绝对值,不会被更改 2 B或b :未被初始化的全局数据,放在.bss段 3 D或d :已经初始化的全局数据 4 G或g :指被初始化的数据,特指small objects 5 I :另一个符号的间接参考 6 N :debugging 符号 7 p :位于堆栈展开部分 8 R或r :属于只读存储区 9 S或s :指为初始化的全局数据,特指small objects 10 T或t :代码段的数据,.test段 11 U :符号未定义 12 W或w :符号为弱符号,当系统有定义符号时,使用定义符号,当系统未定义符号且定义了弱符号时,使用弱符号。 13 ? :unknown符号
由上可知,
标识为D的是已经初始化的全局数据,所以初始地址为0000000000000000;func是在代码段的.test段,这个地址其实是相对于不同数据区的起始地址。(这些都是由操作系统分配的虚拟地址,操作系统内部会还有一个偏移地址来确定最终的分配到存储体上的物理地址的)。
所以后面的
main放在代码段,由前面可知func也是代码段,占用了17个bit,所以main代码段从17开始;至于前面没有地址的标识U这些是链接库中没有被使用的,只是在库文件中进行了使用,没有具体实现
至于其他可见manual手册
转自:https://blog.csdn.net/qq_48322523/article/details/118027964