Linux addr2line命令返回???:0 我创建了一个简单的C++代码,需要崩溃。我将返回一个带有此错误的回溯跟踪: /prbsft/bins/Main(_Z5FuncCv+0x14)[0x5571ea64dd80]

Linux addr2line命令返回???:0 我创建了一个简单的C++代码,需要崩溃。我将返回一个带有此错误的回溯跟踪: /prbsft/bins/Main(_Z5FuncCv+0x14)[0x5571ea64dd80],linux,command-line,Linux,Command Line,现在我尝试使用addr2line来获取函数中的错误行 所以我用了: addr2line -e /prbsft/bins/prbMain 0x5594262a8d80 但我得到的只是0:?? 我还尝试使用0x14地址代替0x5594262a8d80,但它返回相同的结果 我在用Ubuntu添加行版本为: GNU addr2line (GNU Binutils for Ubuntu) 2.30 谢谢 以下是输出: Program received signal SIGSEGV, Segmenta

现在我尝试使用addr2line来获取函数中的错误行

所以我用了:

addr2line -e /prbsft/bins/prbMain 0x5594262a8d80
但我得到的只是
0:??

我还尝试使用0x14地址代替0x5594262a8d80,但它返回相同的结果

我在用Ubuntu<代码>添加行版本为:

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
程序接收信号SIGSEGV,分段故障。main.cpp:34处FuncC()中的0x00005554D80
警告:源文件比可执行文件更新。

34 std::cout n您获得的0x55xxxxxxxxx地址很可能是从磁盘加载EXE后函数的内存地址。addr2line只识别VMA地址,就像使用objdump进行反汇编时得到的地址一样

让我们调用你的函数Foo。addr2line需要FooVMA,或者如果您使用--section=.text,则使用Foofile-textfile。像backtrace这样的函数返回Foomem。一种在大多数情况下有效的简单方法是计算FooVMA=Foofile=Foomem-ELFmem。但这假设VMAbase=0,这对于所有链接器(即链接器脚本)都不是真的。例如Ubuntu 16上的GCC 5.4(0x400000)和MacOS上的Clang11(0x100000000)。下面是一个使用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;
}
#包括
#包括
#包括
#包括
//将函数在内存中的地址转换为可执行文件中的VMA地址。VMA是addr2line所期望的
尺寸转换器至VMA(尺寸地址)
{
Dl_信息;
链接地图*链接地图;
dladdr1((void*)地址和信息,(void**)链接地图,RTLD链接地图);
返回addr-link\u map->l\u addr;
}
void PrintCallStack()
{
void*callstack[128];
int frame_count=backtrace(callstack,sizeof(callstack)/sizeof(callstack[0]);
对于(int i=0;i
您获得的0x55xxxxxxxxx地址很可能是从磁盘加载EXE后函数的内存地址。addr2line只识别VMA地址,就像使用objdump进行反汇编时得到的地址一样

让我们调用你的函数Foo。addr2line需要FooVMA,或者如果您使用--section=.text,则使用Foofile-textfile。像backtrace这样的函数返回Foomem。一种在大多数情况下有效的简单方法是计算FooVMA=Foofile=Foomem-ELFmem。但这假设VMAbase=0,这对于所有链接器(即链接器脚本)都不是真的。例如Ubuntu 16上的GCC 5.4(0x400000)和MacOS上的Clang11(0x100000000)。下面是一个使用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;
}
#包括
#包括
#包括
#包括
//将函数在内存中的地址转换为可执行文件中的VMA地址。VMA是addr2line所期望的
尺寸转换器至VMA(尺寸地址)
{
Dl_信息;
链接地图*链接地图;
dladdr1((void*)地址和信息,(void**)链接地图,RTLD链接地图);
返回addr-link\u map->l\u addr;
}
void PrintCallStack()
{
void*callstack[128];
int frame_count=backtrace(callstack,sizeof(callstack)/sizeof(callstack[0]);
对于(int i=0;i
您是否使用调试信息编译代码?你有堆芯垃圾吗。是(使用-rdynamic-g)2。是的(但我在虚拟机上运行)我发现了一些非常奇怪的东西。。我在我的bin文件中调用了objdump,当我搜索地址14或5594262a8d80时,我没有找到任何关于这些地址的信息。但是,当我试图用objdump上提到的地址调用addr2line时,输出是正常的(而不是0:??),您安装了gdb吗?您可以通过发出“bt”命令在核心转储上使用它进行回溯。是的,我知道,但我的问题是为什么addr2line不工作?您是否使用调试信息编译代码?你有堆芯垃圾吗。是(使用-rdynamic-g)2。是的(但我在虚拟机上运行)我发现了一些非常奇怪的东西。。我在我的bin文件中调用了objdump,当我搜索地址14或5594262a8d80时,我没有找到任何关于这些地址的信息。但是,当我试图用objdump上提到的地址调用addr2line时,输出是正常的(而不是0:??),您安装了gdb吗?您可以通过发出“bt”命令在核心转储上使用它进行回溯。是的,我知道,但我的问题是为什么addr2line不工作?它应该是
struct link\u map*link\u map应该是
struct link\u map*link\u map