简体   繁体   English

Linux addr2line 命令返回 ??:0

[英]Linux addr2line command returns ??:0

I created a simple code in c++ that need to be crashed.我在 C++ 中创建了一个需要崩溃的简单代码。 I am getting back a backtrace with this error:我正在返回带有此错误的回溯:

/prbsft/bins/Main(_Z5FuncCv+0x14)[0x5571ea64dd80]

Now I'm trying to use addr2line to get the error line in the function.现在我正在尝试使用 addr2line 来获取函数中的错误行。

So I used:所以我使用了:

addr2line -e /prbsft/bins/prbMain 0x5594262a8d80

But all I got is 0:??但我得到的只是0:?? . .

I have also tried to use 0x14 address instead of 0x5594262a8d80 but it returns the same result.我也尝试使用 0x14 地址而不是 0x5594262a8d80 但它返回相同的结果。

I'm using Ubuntu.我正在使用 Ubuntu。 addr2line version is: addr2line版本是:

GNU addr2line (GNU Binutils for Ubuntu) 2.30

Any idea?任何的想法?


Here is the output:这是输出:

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

The 0x55XXXXXXXXXX address you got is most likely the memory address of the function after the EXE is loaded from disk.您得到的 0x55XXXXXXXXXX 地址很可能是从磁盘加载 EXE 后函数的内存地址。 addr2line only recognizes VMA addresses like the ones that you got from disassembling with objdump. addr2line 只识别 VMA 地址,就像你用 objdump 反汇编得到的那些地址一样。

在此处输入图片说明

Let's call your function Foo.让我们调用您的函数 Foo。 addr2line expects Foo VMA or if you're using --section=.text, then Foo file - text file . addr2line 需要 Foo VMA,或者如果您正在使用 --section=.text,则 Foo文件- 文本文件 Functions like backtrace returns Foo mem .像 backtrace 这样的函数返回 Foo mem One easy way that works most of the time is to calculate Foo VMA = Foo file = Foo mem - ELF mem .大多数情况下有效的一种简单方法是计算 Foo VMA = Foo file = Foo mem - ELF mem But that assumes VMA base = 0, which is not true for all linkers (ie linker scripts).但这假设 VMA基数= 0,这对于所有链接器(即链接器脚本)而言并非如此。 Examples would be the GCC 5.4 on Ubuntu 16 (0x400000) and clang 11 on MacOS (0x100000000).示例是 Ubuntu 16 (0x400000) 上的 GCC 5.4 和 MacOS (0x100000000) 上的 clang 11。 Here's an example that uses dladdr & dladdr1 to translate it to the VMA address.这是一个使用 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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM