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?
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 permissionsr-xp
(executable segment).Let's say the base address is
0x556c59bec000
. Then the address inside_Z14dummy_functionv
in the .text map table is0x556c59bed2da
minus0x556c59bec000
is12da
. Pass it toaddr2line
.