nm命令和其内容详解

nm命令用于将二进制文件或可执行文件进行剖析

常用参数

// 可以直接man
-A 或-o或 --print-file-name:打印出每个符号属于的文件
-a或--debug-syms:打印出所有符号,包括debug符号
-B:BSD码显示
-C或--demangle[=style]:对低级符号名称进行解码,C++文件需要添加
--no-demangle:不对低级符号名称进行解码,默认参数
-D 或--dynamic:显示动态符号而不显示普通符号,一般用于动态库
-f format或--format=format:显示的形式,默认为bsd,可选为sysv和posix
-g或--extern-only:仅显示外部符号
-h或--help:国际惯例,显示命令的帮助信息
-n或-v或--numeric-sort:显示的符号以地址排序,而不是名称排序
-p或--no-sort:不对显示内容进行排序
-P或--portability:使用POSIX.2标准
-V或--version:国际管理,查看版本

下面来进行一段代码解析

// co.c
#include <stdio.h>
int a = 1;
int b;
void func() {
    printf("Hello World\n");
}
int main() {
    int a = 1;
    func();
    return 0;
}

进行编译(预处理器,编译器,汇编器)生成.o重定向文件

gcc co.c

用nm命令来查看

➜  C nm -C co.o

0000000000000000 D a
0000000000000004 C b
0000000000000000 T func
                 U _GLOBAL_OFFSET_TABLE_
0000000000000017 T main
                 U puts

下面我们再来解析输出信息中各部分所代表的意思吧

  • 首先,前面那一串数字,指的就是地址
  • 然后,我们发现,每一个条目前面还有一个字母,类似’U’,‘B’,'D等等,其实这些符号代表的就是当前条目所对应的内存所在部分
  • 最右边的就是对应的符号内容了

首先来看看这些符号的含义

A     :符号的值是绝对值,不会被更改
B或b  :未被初始化的全局数据,放在.bss段
D或d  :已经初始化的全局数据
G或g  :指被初始化的数据,特指small objects
I     :另一个符号的间接参考
N     :debugging 符号
p     :位于堆栈展开部分
R或r  :属于只读存储区
S或s  :指为初始化的全局数据,特指small objects
T或t  :代码段的数据,.test段
U     :符号未定义
W或w  :符号为弱符号,当系统有定义符号时,使用定义符号,当系统未定义符号且定义了弱符号时,使用弱符号。
?    :unknown符号

由上可知,
标识为D的是已经初始化的全局数据,所以初始地址为0000000000000000;func是在代码段的.test段,这个地址其实是相对于不同数据区的起始地址。(这些都是由操作系统分配的虚拟地址,操作系统内部会还有一个偏移地址来确定最终的分配到存储体上的物理地址的)。

所以后面的
main放在代码段,由前面可知func也是代码段,占用了17个bit,所以main代码段从17开始;至于前面没有地址的标识U这些是链接库中没有被使用的,只是在库文件中进行了使用,没有具体实现

至于其他可见manual手册

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

妖怪喜欢风

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值