-
Notifications
You must be signed in to change notification settings - Fork 232
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Libbacktrace fails to resolve symbols, even though the debug information is present #109
Comments
The erroneous output is from using g++-10, -std=c++11, and ubuntu-22.04 |
libbacktrace works by looking up a PC value in the address ranges recorded by functions. The mere presence of the function name in the info section doesn't tell us much. What matters is the associated address ranges, and whether the PC values found on the stack are in those ranges. Is there a way that I can reproduce the problem? |
Hi, thanks so much for the reply. I have my implementation at
As an update, I was able to get at least the symbol names by falling back to backtrace_syminfo Is there a reason why the file/line information would not be retrievable but the symbol would be? |
I have constructed a better reproducible example that reproduces locally for me: repro_lib.cpp#include <iostream>
#include <vector>
#include <string>
#include <cstddef>
#include <linux/limits.h>
#include <unistd.h>
#include <backtrace.h>
struct stacktrace_frame {
uintptr_t address;
int line;
int col;
std::string filename;
std::string symbol;
};
struct trace_data {
std::vector<stacktrace_frame>& frames;
size_t& skip;
};
int full_callback(void* data_pointer, uintptr_t address, const char* file, int line, const char* symbol) {
trace_data& data = *reinterpret_cast<trace_data*>(data_pointer);
if(data.skip > 0) {
data.skip--;
} else {
data.frames.push_back({
address,
line,
-1,
file ? file : "",
symbol ? symbol : ""
});
}
return 0;
}
void syminfo_callback(void* data, uintptr_t, const char* symbol, uintptr_t, uintptr_t) {
stacktrace_frame& frame = *static_cast<stacktrace_frame*>(data);
frame.symbol = symbol ? symbol : "";
}
void error_callback(void*, const char*, int) {
// nothing for now
}
backtrace_state* get_backtrace_state() {
// backtrace_create_state must be called only one time per program
static backtrace_state* state = nullptr;
static bool called = false;
if(!called) {
state = backtrace_create_state(nullptr, true, error_callback, nullptr);
called = true;
}
return state;
}
std::vector<stacktrace_frame> generate_trace(size_t skip) {
std::vector<stacktrace_frame> frames;
skip++; // add one for this call
trace_data data { frames, skip };
backtrace_full(get_backtrace_state(), 0, full_callback, error_callback, &data);
for(auto& frame : frames) {
if(frame.symbol.empty()) {
// fallback, try to at least recover the symbol name with backtrace_syminfo
backtrace_syminfo(
get_backtrace_state(),
reinterpret_cast<uintptr_t>(frame.address),
syminfo_callback,
error_callback,
&frame
);
}
}
return frames;
} repro.cpp#include <iostream>
#include <vector>
#include <string>
#include <cstddef>
struct stacktrace_frame {
uintptr_t address;
int line;
int col;
std::string filename;
std::string symbol;
};
std::vector<stacktrace_frame> generate_trace(size_t skip);
void trace() {
for(const auto& frame : generate_trace(0)) {
std::cout
<< frame.filename
<< "||"
<< frame.line
<< "||"
<< frame.symbol
<< std::endl;
}
}
void foo(int n) {
if(n == 0) {
trace();
} else {
foo(n - 1);
}
}
template<typename... Args>
void foo(int x, Args... args) {
foo(args...);
}
void function_two(int, float) {
foo(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
}
void function_one(int) {
function_two(0, 0);
}
int main() {
function_one(0);
} /usr/bin/c++ -g -std=c++14 -fPIC -Wall -Wextra -Werror=return-type -Wshadow -o repro_lib.o -c repro_lib.cpp
/usr/bin/ar qc librepro_lib.a repro_lib.o
/usr/bin/ranlib librepro_lib.a
/usr/bin/c++ -g -fPIE -o repro.o -c repro.cpp
/usr/bin/c++ -g repro.o -o repro librepro_lib.a -lbacktrace It is an issue with static linking it seems. Doing it as a shared library works. /usr/bin/c++ -g -std=c++14 -fPIC -Wall -Wextra -Werror=return-type -Wshadow -o repro_lib.o -c repro_lib.cpp
/usr/bin/c++ -fPIC -g -shared -Wl,-soname,repro_lib.so -o repro_lib.so repro_lib.o -lbacktrace
/usr/bin/c++ -g -fPIE -o repro.o -c repro.cpp
/usr/bin/c++ -g repro.o -o repro -Wl,-rpath,. repro_lib.so |
It looks like I'm running into the same issues when I have an executable -> a.so -> b.so (which then invokes libbacktrace). |
I am trying to generate stacktraces with libbacktrace. They are working locally, but on a github workflow runner I'm seeing this
I expect to see this:
When I run
readelf --debug-dump=info test | grep foo
on the github workflow runner I get this:The symbols are present in the binary, but for some reason libbacktrace fails to resolve them. What could cause this?
The text was updated successfully, but these errors were encountered: