我用c ++创建了一个简单的代码,该代码需要崩溃。我正在回溯此错误:
/prbsft/bins/Main(_Z5FuncCv+0x14)[0x5571ea64dd80]
现在我正在尝试使用addr2line在函数中获取错误行。
所以我用过:
addr2line -e /prbsft/bins/prbMain 0x5594262a8d80
但是我只有0:??
。
我也尝试使用0x14地址而不是0x5594262a8d80,但它返回的结果相同。
我正在使用Ubuntu。 addr2line
版本是:
GNU addr2line (GNU Binutils for Ubuntu) 2.30
谢谢。
以下是输出:
Program received signal SIGSEGV, Segmentation fault. 0x0000555555554d80 in FuncC () at main.cpp:34
warning: Source file is more recent than executable.
34 std::cout << k->n << std::endl;
(gdb) bt
#0 0x0000555555554d80 in FuncC () at main.cpp:34
#1 0x0000555555554db1 in FuncB () at main.cpp:39
#2 0x0000555555554dbd in FuncA () at main.cpp:44
#3 0x0000555555554dda in main () at main.cpp:53
答案 0 :(得分:0)
从磁盘加载EXE后,您获得的0x55XXXXXXXXXX地址很可能是该函数的内存地址。 addr2line仅识别VMA地址,例如您通过与objdump拆卸而获得的地址。
让我们调用函数Foo。 addr2line需要Foo VMA ,或者,如果您使用的是--section = .text,则Foo file -text file 。诸如backtrace之类的函数会返回Foo mem 。大多数情况下一种简单的方法是计算Foo VMA = Foo file = Foo mem -ELF mem 。但这假设VMA base = 0,这并非对所有链接器(即链接器脚本)都适用。例如在Ubuntu 16(0x400000)上的GCC 5.4和在MacOS(0x100000000)上的clang 11。这是一个使用dladdr和dladdr1将其转换为VMA地址的示例。
#include <execinfo.h>
#include <link.h>
#include <stdlib.h>
#include <stdio.h>
// converts a function's address in memory to its VMA address in the executable file. VMA is what addr2line expects
size_t ConvertToVMA(size_t addr)
{
Dl_info info;
link_map* link_map;
dladdr1((void*)addr,&info,(void**)&link_map,RTLD_DL_LINKMAP);
return addr-link_map->l_addr;
}
void PrintCallStack()
{
void *callstack[128];
int frame_count = backtrace(callstack, sizeof(callstack)/sizeof(callstack[0]));
for (int i = 0; i < frame_count; i++)
{
char location[1024];
Dl_info info;
if(dladdr(callstack[i],&info))
{
// use addr2line; dladdr itself is rarely useful (see doc)
char command[256];
size_t VMA_addr=ConvertToVMA((size_t)callstack[i]);
//if(i!=crash_depth)
VMA_addr-=1; // https://stackoverflow.com/questions/11579509/wrong-line-numbers-from-addr2line/63841497#63841497
snprintf(command,sizeof(command),"addr2line -e %s -Ci %zx",info.dli_fname,VMA_addr);
system(command);
}
}
}
void Foo()
{
PrintCallStack();
}
int main()
{
Foo();
return 0;
}