简体   繁体   中英

Linux addr2line command returns ??:0

I created a simple code in c++ that need to be crashed. 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.

So I used:

addr2line -e /prbsft/bins/prbMain 0x5594262a8d80

But all I got is 0:?? .

I have also tried to use 0x14 address instead of 0x5594262a8d80 but it returns the same result.

I'm using Ubuntu. addr2line version is:

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. addr2line only recognizes VMA addresses like the ones that you got from disassembling with objdump.

在此处输入图片说明

Let's call your function Foo. addr2line expects Foo VMA or if you're using --section=.text, then Foo file - text file . Functions like backtrace returns Foo mem . One easy way that works most of the time is to calculate Foo VMA = Foo file = Foo mem - ELF mem . But that assumes VMA base = 0, which is not true for all linkers (ie linker scripts). Examples would be the GCC 5.4 on Ubuntu 16 (0x400000) and clang 11 on MacOS (0x100000000). Here's an example that uses dladdr & dladdr1 to translate it to the VMA address.

#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;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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