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
|
# eventfd
|
||||||
qt_config_compile_test(eventfd
|
qt_config_compile_test(eventfd
|
||||||
LABEL "eventfd"
|
LABEL "eventfd"
|
||||||
@ -543,6 +560,10 @@ qt_feature("cxx17_filesystem" PUBLIC
|
|||||||
LABEL "C++17 <filesystem>"
|
LABEL "C++17 <filesystem>"
|
||||||
CONDITION TEST_cxx17_filesystem
|
CONDITION TEST_cxx17_filesystem
|
||||||
)
|
)
|
||||||
|
qt_feature("dladdr" PRIVATE
|
||||||
|
LABEL "dladdr"
|
||||||
|
CONDITION QT_FEATURE_dlopen AND TEST_dladdr
|
||||||
|
)
|
||||||
qt_feature("eventfd" PUBLIC
|
qt_feature("eventfd" PUBLIC
|
||||||
LABEL "eventfd"
|
LABEL "eventfd"
|
||||||
CONDITION NOT WASM AND TEST_eventfd
|
CONDITION NOT WASM AND TEST_eventfd
|
||||||
|
@ -109,6 +109,9 @@ extern char *__progname;
|
|||||||
#ifndef QT_BOOTSTRAPPED
|
#ifndef QT_BOOTSTRAPPED
|
||||||
#if __has_include(<cxxabi.h>) && QT_CONFIG(backtrace) && QT_CONFIG(regularexpression)
|
#if __has_include(<cxxabi.h>) && QT_CONFIG(backtrace) && QT_CONFIG(regularexpression)
|
||||||
# include <qregularexpression.h>
|
# include <qregularexpression.h>
|
||||||
|
# if QT_CONFIG(dladdr)
|
||||||
|
# include <dlfcn.h>
|
||||||
|
# endif
|
||||||
# include BACKTRACE_HEADER
|
# include BACKTRACE_HEADER
|
||||||
# include <cxxabi.h>
|
# include <cxxabi.h>
|
||||||
# define QLOGGING_HAVE_BACKTRACE
|
# define QLOGGING_HAVE_BACKTRACE
|
||||||
@ -1310,12 +1313,17 @@ static QStringList backtraceFramesForLogMessage(int frameCount)
|
|||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
auto demangled = [](QString &function) {
|
auto demangled = [](auto &function) -> QString {
|
||||||
if (!function.startsWith(QLatin1String("_Z")))
|
if (!function.startsWith(QLatin1String("_Z")))
|
||||||
return function;
|
return function;
|
||||||
|
|
||||||
// we optimize for the case where __cxa_demangle succeeds
|
// 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;
|
QScopedPointer<char, QScopedPointerPodDeleter> demangled;
|
||||||
demangled.reset(abi::__cxa_demangle(fn, nullptr, nullptr, nullptr));
|
demangled.reset(abi::__cxa_demangle(fn, nullptr, nullptr, nullptr));
|
||||||
|
|
||||||
@ -1325,7 +1333,29 @@ static QStringList backtraceFramesForLogMessage(int frameCount)
|
|||||||
return QString::fromUtf8(fn); // restore
|
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:
|
// The results of backtrace_symbols looks like this:
|
||||||
// /lib/libc.so.6(__libc_start_main+0xf3) [0x4a937413]
|
// /lib/libc.so.6(__libc_start_main+0xf3) [0x4a937413]
|
||||||
// The offset and function name are optional.
|
// The offset and function name are optional.
|
||||||
@ -1350,6 +1380,7 @@ static QStringList backtraceFramesForLogMessage(int frameCount)
|
|||||||
function = demangled(function);
|
function = demangled(function);
|
||||||
return { library, function };
|
return { library, function };
|
||||||
};
|
};
|
||||||
|
# endif
|
||||||
|
|
||||||
for (void *&addr : buffer) {
|
for (void *&addr : buffer) {
|
||||||
DecodedFrame frame = decodeFrame(addr);
|
DecodedFrame frame = decodeFrame(addr);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user