Logging: add support for decoding backtraces using dladdr()
I'm pretty sure that's what backtrace_symbols() uses internally anyway, so skip the middle-man. Change-Id: Ic15405335d804bdea761fffd16d4fb2a1b0c2171 Reviewed-by: Alexey Edelev <alexey.edelev@qt.io> Reviewed-by: hjk <hjk@qt.io> Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
This commit is contained in:
parent
1cad4ed6a1
commit
ff2535de5c
@ -176,6 +176,23 @@ std::filesystem::copy(
|
||||
"
|
||||
)
|
||||
|
||||
# dladdr
|
||||
qt_config_compile_test(dladdr
|
||||
LABEL "dladdr"
|
||||
LIBRARIES
|
||||
dl
|
||||
CODE
|
||||
"#define _GNU_SOURCE 1
|
||||
#include <dlfcn.h>
|
||||
int i = 0;
|
||||
int main(void)
|
||||
{
|
||||
Dl_info info;
|
||||
dladdr(&i, &info);
|
||||
return 0;
|
||||
}"
|
||||
)
|
||||
|
||||
# eventfd
|
||||
qt_config_compile_test(eventfd
|
||||
LABEL "eventfd"
|
||||
@ -543,6 +560,10 @@ qt_feature("cxx17_filesystem" PUBLIC
|
||||
LABEL "C++17 <filesystem>"
|
||||
CONDITION TEST_cxx17_filesystem
|
||||
)
|
||||
qt_feature("dladdr" PRIVATE
|
||||
LABEL "dladdr"
|
||||
CONDITION QT_FEATURE_dlopen AND TEST_dladdr
|
||||
)
|
||||
qt_feature("eventfd" PUBLIC
|
||||
LABEL "eventfd"
|
||||
CONDITION NOT WASM AND TEST_eventfd
|
||||
|
@ -109,6 +109,9 @@ extern char *__progname;
|
||||
#ifndef QT_BOOTSTRAPPED
|
||||
#if __has_include(<cxxabi.h>) && QT_CONFIG(backtrace) && QT_CONFIG(regularexpression)
|
||||
# include <qregularexpression.h>
|
||||
# if QT_CONFIG(dladdr)
|
||||
# include <dlfcn.h>
|
||||
# endif
|
||||
# include BACKTRACE_HEADER
|
||||
# include <cxxabi.h>
|
||||
# define QLOGGING_HAVE_BACKTRACE
|
||||
@ -1310,12 +1313,17 @@ static QStringList backtraceFramesForLogMessage(int frameCount)
|
||||
return false;
|
||||
};
|
||||
|
||||
auto demangled = [](QString &function) {
|
||||
auto demangled = [](auto &function) -> QString {
|
||||
if (!function.startsWith(QLatin1String("_Z")))
|
||||
return function;
|
||||
|
||||
// we optimize for the case where __cxa_demangle succeeds
|
||||
QByteArray fn = std::move(function).toUtf8();
|
||||
auto fn = [&]() {
|
||||
if constexpr (sizeof(function.at(0)) == 1)
|
||||
return function.data(); // -> const char *
|
||||
else
|
||||
return std::move(function).toUtf8(); // -> QByteArray
|
||||
}();
|
||||
QScopedPointer<char, QScopedPointerPodDeleter> demangled;
|
||||
demangled.reset(abi::__cxa_demangle(fn, nullptr, nullptr, nullptr));
|
||||
|
||||
@ -1325,7 +1333,29 @@ static QStringList backtraceFramesForLogMessage(int frameCount)
|
||||
return QString::fromUtf8(fn); // restore
|
||||
};
|
||||
|
||||
# if QT_CONFIG(dladdr)
|
||||
// use dladdr() instead of backtrace_symbols()
|
||||
auto decodeFrame = [&](const void *addr) -> DecodedFrame {
|
||||
Dl_info info;
|
||||
if (!dladdr(addr, &info))
|
||||
return {};
|
||||
|
||||
// These are actually UTF-8, so we'll correct below
|
||||
QLatin1String fn(info.dli_sname);
|
||||
QLatin1String lib;
|
||||
if (const char *lastSlash = strrchr(info.dli_fname, '/'))
|
||||
lib = QLatin1String(lastSlash + 1);
|
||||
else
|
||||
lib = QLatin1String(info.dli_fname);
|
||||
|
||||
if (shouldSkipFrame(lib, fn))
|
||||
return {};
|
||||
|
||||
QString library = QString::fromUtf8(lib.data(), lib.size());
|
||||
QString function = demangled(fn);
|
||||
return { library, function };
|
||||
};
|
||||
# else
|
||||
// The results of backtrace_symbols looks like this:
|
||||
// /lib/libc.so.6(__libc_start_main+0xf3) [0x4a937413]
|
||||
// The offset and function name are optional.
|
||||
@ -1350,6 +1380,7 @@ static QStringList backtraceFramesForLogMessage(int frameCount)
|
||||
function = demangled(function);
|
||||
return { library, function };
|
||||
};
|
||||
# endif
|
||||
|
||||
for (void *&addr : buffer) {
|
||||
DecodedFrame frame = decodeFrame(addr);
|
||||
|
Loading…
Reference in New Issue
Block a user