简体   繁体   中英

Libunwind PC value not working with addr2line

I am trying to follow along with an example from the link: https://eli.thegreenplace.net/2015/programmatic-access-to-the-call-stack-in-c/

However I have run into a few issues. I have a piece of code like so that uses libunwind to print backtrace information:

test.cpp

#define UNW_LOCAL_ONLY
#include <libunwind.h>
#include <stdio.h>

// Call this function to get a backtrace.
void backtrace() {
  unw_cursor_t cursor;
  unw_context_t context;

  // Initialize cursor to current frame for local unwinding.
  unw_getcontext(&context);
  unw_init_local(&cursor, &context);

  // Unwind frames one by one, going up the frame stack.
  while (unw_step(&cursor) > 0) {
    unw_word_t offset, pc;
    unw_get_reg(&cursor, UNW_REG_IP, &pc);
    if (pc == 0) {
      break;
    }
    printf("0x%lx:", pc);

    char sym[256];
    if (unw_get_proc_name(&cursor, sym, sizeof(sym), &offset) == 0) {
      printf(" (%s+0x%lx)\n", sym, offset);
    } else {
      printf(" -- error: unable to obtain symbol name for this frame\n");
    }
  }
}

void foo() {
  backtrace(); // <-------- backtrace here!
}

void bar() {
  foo();
}

int main(int argc, char **argv) {
  bar();

  return 0;
}

Running this code produces output like so ie the program counter value: (function_name+0xoffset)

$ gcc -o libunwind_backtrace -Wall -g test.cpp -lunwind
$ LD_LIBRARY_PATH=/usr/local/lib ./libunwind_backtrace
0x56154da9c9c3: (_Z3foov+0x9)
0x56154da9c9cf: (_Z3barv+0x9)
0x56154da9c9e6: (main+0x14)
0x7facd1cc82e1: (__libc_start_main+0xf1)
0x56154da9c7da: (_start+0x2a)

As mentioned in the link above the program counter value to the left of the function name can be fed to addr2line to obtain file name and line number information. However whenever I try to do so (eg. for the function foo):

$ addr2line 56154da9c9c3 -e libunwind_backtrace
??:0

After looking at the objdump file I have found that function foo has a debug entry:

$ objdump --dwarf=info libunwind_backtrace
...
<1><723>: Abbrev Number: 27 (DW_TAG_subprogram)
   <724>   DW_AT_external    : 1
   <724>   DW_AT_name        : foo
   <728>   DW_AT_decl_file   : 1
   <729>   DW_AT_decl_line   : 32
   <72a>   DW_AT_linkage_name: (indirect string, offset: 0x1cb): _Z3foov
   <72e>   DW_AT_low_pc      : 0x9ba
   <736>   DW_AT_high_pc     : 0xc
   <73e>   DW_AT_frame_base  : 1 byte block: 9c     (DW_OP_call_frame_cfa)
   <740>   DW_AT_GNU_all_tail_call_sites: 1
...

and when I enter the value for DW_at_low_pc into addrline it manages to produce the correct output.

addr2line 0x9c6 -e libunwind_backtrace
/root/Desktop/test.cpp:36
  1. Firstly why does the PC value returned by libunwind differ from that of the DW_AT_low_pc?

  2. It seems like libunwind is returning an incorrect value for the PC but if this is the case then how is libunwind able to obtain the function names?

  3. Is there any way given the PC value from libunwind that I can obtain the file name and file number using addr2line or some other command line tool?

Thank you for reading, I know its a kinda long question.

  1. DW_AT_low_pc is the relocated address of the first instruction associated with (in this case) the function. Looking at the addresses in your stack trace, it seems that your executable has been loaded at 0x56154da9c000 and that foo() begins at 0x56154da9c9ba , ie 0x56154da9c000 + 0x9ba . The program counter is 0x56154da9c9c3 which, as libunwind suggests, is 0x56154da9c9ba + 0x9 .

  2. I haven't looked at libunwind but it's worth pointing out that address->function name mapping doesn't require DWARF; in general, the ELF symbol table will suffice (and is much faster to navigate).

  3. I suggest trying the unrelocated program counter, ie 0x9c3.

libunwind is good at fetching addresses from the call stack, but it does not do much more than this. addr2line works well when no relocation is involved, but ASLR as made relocations much more common.

Nowadays, the right tool is libbacktrace by Ian Lance Taylor . It provides the functionality of both libunwind and addr2line combined in a single library.

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