在Linux下写C/C++程序的程序员,时常与Core Dump相见。在内存越界访问,收到不能处理的信号,除零等错误出现时,我们精心或不精心写就的程序就直接一命呜呼了,Core Dump是Linux仁慈地留下的程序的尸体,帮助程序员们解决了一个又一个问题。
有时配置不给力,Linux直接毁尸灭迹,没有了Core文件;又有时,刚好磁盘空间不足,Core文件写不下了。没有Core文件的时候,如何知道程序在什么地方出错了呢?addr2line就在这时派上用场。有Core就采用nm查看内核挂死配置处理,没有内核挂死记录就只能根据挂死前的符号,采用addr2line定位挂死地方!
NM用途
显示关于对象文件、可执行文件以及对象文件库里的符号信息。
语法
nm [ -A ] [ -C ] [ -X {32|64|32_64}] [ -f ] [ -h ] [ -l ] [ -p ] [ -r ] [ -T ] [ -v ] [ -B | -P ] [ -e | -g | -u ] [ -d | -o | -x | -t Format ] File ...
描述
nm 命令显示关于指定 File 中符号的信息,文件可以是对象文件、可执行文件或对象文件库。如果文件没有包含符号信息,nm 命令报告该情况,但不把它解释为出错条件。 nm 命令缺省情况下报告十进制符号表示法下的数字值。
nm 命令把以下符号信息写入标准输出:
库或对象名
如果您指定了 -A 选项,则 nm 命令只报告与该文件有关的或者库或者对象名。
符号名称
符号类型
nm 命令使用以下符号(用同样的字符表示弱符号作为全局符号)之一来表示文件符号类型:
A Global absolute 符号。
a Local absolute 符号。
B Global bss 符号。
b Local bss 符号。
D Global data 符号。
d Local data 符号。
f 源文件名称符号。
T Global text 符号。
t Local text 符号。
U 未定义符号。
值
大小
如果可应用,nm 命令报告与符号有关的大小。
标志
-A 每行或者显示全路径名称或者显示对象库名。
-B 在 Berkeley 软件分发(BSD)格式中显示输出:
值 类型 名称
-C 限制解码(demangle) C++ 名称。缺省是解码所有 C++ 符号名。
注:
C++ 对象文件中的符号在被使用前它们的名称已经被解码了。
-d 用十进制显示符号的值和大小。这是缺省的。
-e 只显示静态的和外部的(全局)符号。
-f 显示完整的输出,包括冗余的 .text、 .data 以及 .bss 符号,这些在通常都是被限制的。
-g 只显示外部的(全局)符号。
-h 限制输出头数据的显示。
-l 通过给 WEAK 符号的编码键附加一个 * 来区分 WEAK 和 GLOBAL 符号。如果和 -P 选项一起使用, WEAK 符号的符号类型显示如下:
V
Weak Data 符号
W
Weak Text 符号
w
Weak 未定义符号
Z
Weak bss 符号
-o 用八进制而不是十进制数来显示符号的值和大小。
-P 以标准可移植输出格式显示信息:
库/对象名 名称 类型 值 大小
该格式以十六进制符号表示法显示数字值,除非您用 -t、-d 或 -o 标志指定不同的格式。
如果您指定了 -A 标志 -P 标志只显示 库/对象名字段。同样,-P 标志只显示大小适用的符号大小字段。
-p 不排序。输出按符号表顺序打印。
-r 倒序排序。
-T 把可能会溢出它的列的每个名字截短,使显示的名字的最后一个字符是星号(*)。缺省情况下,nm 显示列出的符号的全名,并且一个比为其设置的列的宽度长的名称会引起名称后的每个列无法对齐。
-t Format 显示指定格式下的数字值,其中 Format 参数是以下符号表示法之一:
d
十进制符号表示法。这是 nm 命令的缺省格式。
o
八进制符号表示法。
x
十六进制符号表示法。
-u 只显示未定义符号。
-v 按值而不是按字母表顺序排序输出。
-x 用十六进制而不是十进制数来显示符号的值和大小。
-X mode 指定 nm 应该检查的对象文件的类型。 mode 必须是下列之一:
32
只处理 32 位对象文件
64
只处理 64 位对象文件
32_64
处理 32 位和 64 位对象文件
缺省是处理 32 位对象文件(忽略 64 位对象)。 mode 也可以 OBJECT_MODE 环境变量来设置。例如,OBJECT_MODE=64 使 nm 处理任何 64 位对象并且忽略 32 位对象。 -X 标志覆盖 OBJECT_MODE 变量。
注:
nm 命令支持 -- (双连字符)标志。如果文件名会被曲解为一个选项,该标志区别于 File 操作数。例如,要指定文件名以连字符开始,请使用 -- 标志。
退出状态
该命令返回下列出口值:
0 成功完成。
>0 发生错误。
示例
列出 a.out 对象文件的静态和外部符号,请输入:
nm -e a.out
以十六进制显示符号大小和值并且按值排序符号,请输入:
nm -xv a.out
显示 libc.a 中所有 64 位对象符号,忽略所有 32 位对象:
nm -X64 /usr/lib/libc.a
文件
/usr/ccs/bin/nm 包含 nm 命令。
addr2line
-a --addresses Show addresses
-b --target=<bfdname> Set the binary file format
-e --exe=<executable> Set the input file name (default is a.out)
-i --inlines Unwind inlined functions
-j --section=<name> Read section-relative offsets instead of addresses
-p --pretty-print Make the output easier to read for humans
-s --basenames Strip directory names
-f --functions Show function names
-C --demangle[=style] Demangle function names
-h --help Display this information
-v --version Display the program's version
1.找到编译镜像的没有裁剪的文件,找到符号表,具体操作如下:
wupeng@ubuntu:~/cmc1017/cmts/CmtsApp/build/Linux/BCM3380$ nm-A linux_cmts_sym
linux_cmts_sym:00f51000 T netsnmp_container_find
linux_cmts_sym:00f50ef8T netsnmp_container_find_factory
linux_cmts_sym:00f50fb4T netsnmp_container_find_noalloc
linux_cmts_sym:00f50828T netsnmp_container_get
linux_cmts_sym:00f51900T netsnmp_container_get_binary_array
linux_cmts_sym:00f517f4T netsnmp_container_get_binary_array_factory
linux_cmts_sym:00f51858T netsnmp_container_get_binary_array_noalloc
linux_cmts_sym:00f507e0T netsnmp_container_get_factory
linux_cmts_sym:00f50860T netsnmp_container_get_noalloc
linux_cmts_sym:00f51198T netsnmp_container_init_list
linux_cmts_sym:00f51038T netsnmp_container_register
linux_cmts_sym:012c0054b netsnmp_ds_booleans
linux_cmts_sym:012bfed0b netsnmp_ds_configs
linux_cmts_sym:00f41ad0T netsnmp_ds_get_boolean
linux_cmts_sym:00f41b20T netsnmp_ds_get_int
linux_cmts_sym:00f41b64T netsnmp_ds_get_string
linux_cmts_sym:00f41ba8T netsnmp_ds_get_void
2.找到挂死的log,查看sc_pc = 9d00c4对应的十六进制编码,如果在符号表中能查找到则直接找到函数值,如果找不到找最相近的
linux_cmts_sym:009d0260 T_ZNK13BcmMacAddress5PrintERSo
egister dump:
$ 0 : 00000000 1000d300 00000020 2c3299d1
$ 4 : 0000008c 2c3299cc 2c3299cd 2c3299ce
$ 8 : 00000020 2a777570 656e6720 72656d6f
$12 : 76652043 4d206672 6f6d206c 6f616420
$16 : 2abf2718 2aabfffc 00000020 015c32a0
$20 : 00fa1f04 012a4148 00fa35d4 00fa0000
$24 : 00000000 2ab7c890
$28 : 0121dde0 2c329998 012a4204 009d02dc
uc_stack.ss_sp =00000000
uc_stack.ss_size= 00000000
uc_stack.ss_flags= 00000002
sc_regmask =2aabfffc
sc_status =00000000
sc_pc = 9d00c4
sc_fpc_csr =00635084
sc_used_math =00000000
sc_dsp =2abf3150
sc_mdhi = 0
sc_mdlo = 0
sc_hi1 = fa35d4
sc_lo1 = fa1f04
sc_hi2 = 12a4148
sc_lo2 =2ab9a3b8
sc_hi3 = 121dde0
sc_lo3 =ff0bd271
****** Stack Pointer: 0x2c329998
2c329198 :00000000 00000030 00000000 00000001
2c3291a8:00000002 00000100 00000000 00000008
3. 根据符号的值在编译器运行如下指令就可以查看到具体的函数
c++filt _ZNK13BcmMacAddress5PrintERSo
wupeng@ubuntu:~/cmc1017/cmts/CmtsApp/build/Linux/BCM3380$c++filt _ZNK13BcmMacAddress5PrintERSo
BcmMacAddress::Print(std::basic_ostream<char,std::char_traits<char> >&) const
[heshuanglai@localhost ucp]$ addr2line -e ../images/CC8800/image_cc8800e/debug/V1.3.1.0/bin/dolagent.app00657704
/home/heshuanglai/project/b_dol_v226x/dol/cmtsVpn/agt/agtCmtsVpnCom.c:82
[heshuanglai@localhostucp]$