addr2line输出问号怎么办

前言

使用backtrace等工具将程序异常运行的堆栈打印出来,然后再结合使用addr2line将堆栈地址转为文件行,将对于定位故障非常有帮助,但有时使用addr2line却输出为??:0 !

从addr2line的man手册中看确实没有分C和C++语言的区别,而且还有特殊的选项-C针对于C++编译器的函数重命名,所以,输出??:0 ,应该是找不到对应行号了,特别是使用地址信息的不正确。

结合个人实践,将对backtrace输出的地址信息进行分类!

backtrace显示地址分类

/lib/x86_64-linux-gnu/libc.so.6(clone+0x43) [0x7faf347b3133]

  • **()**中携带的地址信息为模块内地址,分为+0x0ffsetsymbol+0x0ffset两种情况,其中+0x0ffset可以直接作为addr2line的地址参数;symbol+0x0ffset地址在多几步处理后,可以作为addr2line的地址参数,特别是结合objdump -D工具。
  • **[]**中携带的地址为函数运行时地址,所以,一般是不能直接用的

在没有**()内地址信息时,[]**的地址可以作为地址参数

如果您确定堆栈信息与运行程序和依赖库是一致的话,且程序携带-g的调试信息,那么可以深入使用objdump -D工具进行人工分析。

-rdynamic

-rdynamic编译选项,从个人实践来看,作用被夸大了。携带此参数后,显示出来的symbol+0ffset的地址信息,无法直接作为addr2line的地址参数,去掉选项后,反而得到了能够直接使用的(+0xOffset)的地址

对于动态库的适应

如果SO库本身携带有调试信息的话,同样可以用addr2line -e /path/to/so addr,定位到SO库某文件中的某行。

[]地址的特殊性

从一个很小的青蛙例子,可以backtrace打印出**类[]的地址,多运行几次发现类[]**地址存在动态变化,所以,不能直接作为addr2line进行使用。反而是(+0xOffset)(Symbol+0xOffset)的地址非常稳定,比较适合作为addr2line的参数进行使用!

(+0xOffset)中的0xOffset可以直接作为addr2line的地址参数来使用

symbol+0xffset地址结合objdump

纯手工计算

   # template
   objdump -D /path/to/relocatable_object | grep -A20 ‘symbol’

   # example 
   objdump -D a.out |grep -A20 'main'

   # output
   ...
    0000000000003920 <main>:
    3920:	f3 0f 1e fa          	endbr64 
    3924:	55                   	push   %rbp
    3925:	48 89 e5             	mov    %rsp,%rbp
    3928:	53                   	push   %rbx

# 对于解析不出来的symbol+0xOffset进行特殊处理,特别关注的位置
# 对于无法识别的`addr2line -e a.out main+0x1fc`

addr2line -e a.out $(printf '%x' $((0x3920 + 0x1fc)))
  • objdump -D将程序或库进行汇编输出,可以看到符号在模块内的地址
  • grep -A选项打印匹配行后多少行;另外,-C为匹配行的上下多少行,-B为匹配行前多少行,在监控动态输出日志时非常有帮助

固化

#!/bin/bash
# file: queryRowNo.sh

addr="$2"

name=${addr%+*}
offset=${addr#*+}

base=$(objdump -D $1 | grep "<$name>" | awk '{print $1}')

if [ -z "$base" ]; then
  echo "can't get the base addr of $name"
  exit
fi

base="0x$base"

addr2line -e "$1" $(printf '%x' $((base + offset)))

# example using shell script file
./queryRowNo.sh /lib/libACE.so.6.5.19 _ZN15ACE_Sig_Handler8dispatchEiP9siginfo_tP10ucontext_t+0x55

参考

  • man backtrace
  • man addr2line
  • addr2line & objdump

你可能感兴趣的:(笔记,c&c++技术,小工具,linux,addr2line,objdump,输出问号)