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

问题描述 投票:0回答:1

我正在尝试将

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
正确确定调用堆栈的行号?

c++ c debugging backtrace debug-backtrace
1个回答
0
投票

通过在运行时检查

/proc/self/maps
来查找进程在内存中的基址。这一行包含您的程序名称和权限
r-xp
(可执行段)。

假设基地址是

0x556c59bec000
。那么.text映射表中
_Z14dummy_functionv
内的地址就是
0x556c59bed2da
减去
0x556c59bec000
就是
12da
。传给
addr2line

© www.soinside.com 2019 - 2024. All rights reserved.