How to use backtrace() with addr2line to get line numbers of the call stack?

339 views Asked by At

I'm trying to use backtrace() in conjunction with addr2line to obtain line numbers for a call stack.

Here's the content of my main.cpp:

#include <execinfo.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

void print_stack_trace() {
  void *array[10];
  size_t size;
  char **strings;
  size_t i;

  // Get the current call stack
  size = backtrace(array, 20);

  // Convert it into an array of strings
  strings = backtrace_symbols(array, size);

  if (strings == NULL) {
    perror("backtrace_symbols");
    exit(EXIT_FAILURE);
  }

  // Print all the stack trace symbols
  for (i = 0; i < size; i++) {
    printf("%s\n", strings[i]);
  }

  free(strings);
}

void dummy_function() {
  // Generate a stack trace
  print_stack_trace();
}

int main(void) {
  // Call a function and then print the stack trace within that function
  dummy_function();
  return 0;
}

I compiled the code with the following command:

g++ -rdynamic -g3 main.cpp -o main.out

When I run the executable:

./main.out

The output is:

./main.out(_Z17print_stack_tracev+0x2c) [0x556c59bed235]
./main.out(_Z14dummy_functionv+0xd) [0x556c59bed2da]
./main.out(main+0xd) [0x556c59bed2ea]
/lib/x86_64-linux-gnu/libc.so.6(+0x29d90) [0x7f9128c7bd90]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0x80) [0x7f9128c7be40]
./main.out(_start+0x25) [0x556c59bed145]

According to the backtrace_symbols() man page, the addresses in the brackets (e.g., 0x556c59bed2da) are return addresses. I've compiled with the -g option and used addr2line as follows:

addr2line -f -e ./main.out 0x556c59bed2da

But the output is:

??
??:0

I checked the function addresses with objdump:

objdump -S -l -d ./main.out

The addresses seem to start with 0000, like so:

0000000000001209 <_Z17print_stack_tracev>:
00000000000012cd <_Z14dummy_functionv>:

These do not match the backtrace_symbols() output (0x556c59bed2da).

How can I use addr2line to determine the line numbers of the call stack correctly?

1

There are 1 answers

0
273K On

Find the base address of your process in memory by examining the /proc/<PID>/maps while your program is running. This is a line that has the name of your program and the permissions r-xp (executable segment).

Let's say the base address is 0x556c59bec000. Then the address inside _Z14dummy_functionv in the .text map table is 0x556c59bed2da minus 0x556c59bec000 is 12da. Pass it to addr2line.