c++ 如何使用backtrace()和addr2line来获取调用堆栈的行号?

mznpcxlj  于 11个月前  发布在  其他
关注(0)|答案(1)|浏览(128)

我尝试将backtrace()addr2line结合使用,以获取调用堆栈的行号。
以下是我的main.cpp的内容:

#include <execinfo.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

void print_stack_trace() {
  void *array[10];
  size_t size;
  char **strings;
  size_t i;

  // Get the current call stack
  size = backtrace(array, 20);

  // Convert it into an array of strings
  strings = backtrace_symbols(array, size);

  if (strings == NULL) {
    perror("backtrace_symbols");
    exit(EXIT_FAILURE);
  }

  // Print all the stack trace symbols
  for (i = 0; i < size; i++) {
    printf("%s\n", strings[i]);
  }

  free(strings);
}

void dummy_function() {
  // Generate a stack trace
  print_stack_trace();
}

int main(void) {
  // Call a function and then print the stack trace within that function
  dummy_function();
  return 0;
}

字符串
我使用以下命令编译了代码:

g++ -rdynamic -g3 main.cpp -o main.out


运行可执行文件时:

./main.out


输出为:

./main.out(_Z17print_stack_tracev+0x2c) [0x556c59bed235]
./main.out(_Z14dummy_functionv+0xd) [0x556c59bed2da]
./main.out(main+0xd) [0x556c59bed2ea]
/lib/x86_64-linux-gnu/libc.so.6(+0x29d90) [0x7f9128c7bd90]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0x80) [0x7f9128c7be40]
./main.out(_start+0x25) [0x556c59bed145]


根据backtrace_symbols()手册页,括号中的地址(例如,0x556c59bed2da)是返回地址。我已经使用-g选项进行编译,并使用addr2line如下:

addr2line -f -e ./main.out 0x556c59bed2da


但输出是:

??
??:0


我用objdump检查了函数地址:

objdump -S -l -d ./main.out


地址似乎以0000开头,如下所示:

0000000000001209 <_Z17print_stack_tracev>:
00000000000012cd <_Z14dummy_functionv>:


这些与backtrace_symbols()输出(0x556c59bed2da)不匹配。
如何使用addr2line来正确确定调用堆栈的行号?

s4chpxco

s4chpxco1#

当程序运行时,通过检查/proc/<PID>/maps来查找进程在内存中的基址。这是一行,包含程序名和权限r-xp(可执行段)。
假设基址是0x556c59bec000。那么.textMap表中_Z14dummy_functionv内部的地址是0x556c59bed2da减去0x556c59bec00012da。将其传递给addr2line

相关问题