nm命令详解

摘要:
如果文件中没有包含符号信息,nm报告该情况,单不把他解释为出错。-A选项用于显示每个标识符的文件名信息;对于C++代码,常用的还有-C选项,它也为解码这些标识符;objdump、readld命令可以完成同样的任务。

前言

nm是name的缩写,它显示指定文件中的符号信息,文件可以是对象文件、可执行文件或对象文件库。如果文件中没有包含符号信息,nm报告该情况,单不把他解释为出错。nm缺省情况下报告十进制符号表示法下的数字值。

选项

  • -a/--debug-syms:显示所有符号,包括debugger-only symbols
  • -B:等同于--format=bsd,兼容 MIPS nm
  • -C/--demangle:将低级符号名解析成用户级名字。这样可以使得C++函数名具有可读性。
  • --no-demangle:默认选项,不将低级符号名解析成用户级名字。
  • -D/--dynamic:显示动态符号。这个选项只对动态目标(比如特定类型的共享库)有意义。
  • -f format/--format=format:使用format格式输出。format可以选取bsd、sysv或posix,该选项在GNU的nm中有用。默认为bsd
  • -g/--extern-only:只显示外部符号
  • -l/--line-numbers:对于每一个符号,使用debug信息找到文件名和行号。
  • -n/-v/--numeric-sort:按符号对应地址的顺序排序,而不是按符号名字符顺序排序
  • -p/--no-sort:按照目标文件中遇到的符号顺序显示,不排序
  • -P/--portability:按照POSIX2.0标准格式输出,等同于使用 -f posix
  • -r/--reverse-sort:反转排序
  • -s/--print-armap:当列出库中成员的符号时,包含索引。索引的内容包括:哪些模块包含哪些名字的映射
  • -u/--undefined-only:只显示未定义符号
  • --defined-only:只显示定义的符号

符号说明

对于每一个符号来说,其类型如果是小写的,则表明该符号是local的。大写则表明该符号是global(external)的

  • A:该符号的值是绝对的,在以后的链接过程中,不允许改变。这样的符号,常常出现在中断向量表中,例如用符号来表示各个中断向量函数在中断向量表中的位置。
  • B:该符号的值出现在非初始化数据段BSS中。例如,一个文件中定义全局 static int s_int。则符号s_int 类型为b,位于bss section中。其值表示该符号在bss段的偏移。一般而言,bss段分配于RAM中。
  • C:该符号为common。common symbol是未初始化数据段。该符号没有包含于一个普通section中。只有在链接过程中才进行分配。符号的值表示要分配的字节数。例如,在一个c文件中,定义 int g_no_init,并且该符号在别的地方会被引用,则该符号类型就是C,否则为B。
  • D:该符号位于初始化数据段中。一般来说,分配到data section中。比如,全局变量 int g_init = 2;
  • G:该符号也位于初始化数据段。主要用于small object,提高访问small data object的一种方式。
  • I:该符号是对另一个符号的间接引用。
  • N:该符号是一个debugging符号
  • R:该符号位于只读数据区。比如,全局变量const int const_int = 0;如果在一个函数中定义 const char* test = "abc"; const int a = 2; 使用nm都不会得到符号信息。但是字符串"abc"分配于只读存储器中,test 在rodata section中,大小为4
  • S:符号位于非初始化数据区,用于 small object
  • T:符号位于代码区 text section
  • U:符号在当前文件中是未定义的,即该符号的定义在别的文件中。比如,当前文件中调用另一个文件中的函数,在这个本目标文件中,函数就是未定义的。但是在定义它的文件中,类型为T。但是对于全局变量来说,在定义它的文件中,符号类型是C,在使用它的文件中,类型是U。
  • V:该符号是一个weak object
  • ?:该符号类型没有定义

示例

寻找特殊标识

有时会碰到一个编译了但没有链接的代码,那是因为它缺失了标识符;这种情况,可以用nm和objdump、readelf命令来查看程序的符号表;所有这些命令做的工作基本一样;
比如连接器报错有未定义的标识符;大多数情况下,会发生在库的缺失或企图链接一个错误版本的库的时候;浏览目标代码来寻找一个特殊标识符的引用:

nm -uCA *.o | grep foo

-u选项限制了每个目标文件中未定义标识符的输出。-A选项用于显示每个标识符的文件名信息;对于C++代码,常用的还有-C选项,它也为解码这些标识符;

objdump、readld命令可以完成同样的任务。等效命令为: $objdump -t $readelf -s

只显示外部的定义的符号

nm add.o --defined-only -g

免责声明:文章转载自《nm命令详解》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇cookie中数据无法读取,HttpOnly属性react + antd Table实现表格数据合并下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Centos7 初始化硬盘分区、挂载

通过命令fdisk-l查看硬盘信息 可以看到有两块硬盘/dev/vda和/dev/vdb,启动vda是系统盘vdb是我们新增的数据盘。 2.执行以下命令,进入fdisk模式,开始对新增数据盘执行分区操作。 fdisk 新增数据盘 以新挂载的数据盘“/dev/xvdb”为例: fdisk /dev/xvdb 回显类似如下信息: 3.输入“n”,按“Ent...

superset docker 部署

公众号原文有更多效果图哦 一、使用自己的数据库 1. 拉取项目 // 创建目录用于存放项目 mkdir -p /mnt/superset cd /mnt/superset git clone https://github.com/amancevice/superset.git 2. 配置数据库等 这里默认你已创建了你自己的空数据库和具有读写该数据库权限的...

VC++ MFC Progress Control 进度条

1.常用函数 SetRange(0,100)设置范围; SetStep(int i)设置步长; StepIt();单步递增进度; int SetPos(int nPos) 设置当前位置,可以用来初始化; int GetPos()获得当前进度; 2.设置控件Progress Control控件变量。 3. m_ProgressFile.Se...

KEIL 中结构体对指定元素(函数指针)初始化的探索(呼吸灯为例)

结构体对指定元素初始化就是类似下面的操作: 1 struct lzh { int x; int y; }; 2 struct lzh xianjue = 3 { .x = 1, 4 .y = 2 5 }; 在KEIL MDK中使用却报错:“expected an expression”。其实就是编译器不支持C99标准,我们可以打开C99模式让编...

转:程序内存空间(代码段、数据段、堆栈段)

https://blog.csdn.net/ywcpig/article/details/52303745 在冯诺依曼的体系结构中,一个进程必须有:代码段,堆栈段,数据段。 进程的虚拟地址空间图示如下: BSS段:BSS段(bss segment)通常是指用来存放程序中未初始化的全局变量的一块内存区域。BSS是英文Block Started by Sym...

C++ 构造和析构

1、继承关系可认为,子类在父类的基础上进行。从这个角度讲,可把它认为穿衣脱衣的过程。穿衣是:先穿内衣,再穿外套。脱衣是:先脱外套,在脱内衣。构造是:先调用父类构造方法,再调用子类构造方法。析构是:先调用子类析构方法,再调用父类析构方法。 2、构造可分为两个步骤:初始化列表和方法内赋值。前者的使用场景是:初始化,即copy构造。后者的使用场景是:赋值,即co...