Linux addr2line命令返回??:0

时间:2019-05-08 17:05:18

标签: linux command-line

我用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

1 个答案:

答案 0 :(得分:0)

从磁盘加载EXE后,您获得的0x55XXXXXXXXXX地址很可能是该函数的内存地址。 addr2line仅识别VMA地址,例如您通过与objdump拆卸而获得的地址。

enter image description here

让我们调用函数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;
}