diff options
author | Thiago Macieira <thiago.macieira@intel.com> | 2022-02-18 12:25:22 -0800 |
---|---|---|
committer | Thiago Macieira <thiago.macieira@intel.com> | 2022-03-03 19:05:11 -0800 |
commit | ff2535de5c3d0cdcd9232780f53fd4ff00ea822a (patch) | |
tree | 7a4f239939033c636487e23166456281529011a5 /src/corelib | |
parent | 1cad4ed6a1f3e5f091f7bf1cb9998383d226a4b2 (diff) |
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>
Diffstat (limited to 'src/corelib')
-rw-r--r-- | src/corelib/configure.cmake | 21 | ||||
-rw-r--r-- | src/corelib/global/qlogging.cpp | 35 |
2 files changed, 54 insertions, 2 deletions
diff --git a/src/corelib/configure.cmake b/src/corelib/configure.cmake index 249e84cb01..101e7a6ec7 100644 --- a/src/corelib/configure.cmake +++ b/src/corelib/configure.cmake @@ -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 diff --git a/src/corelib/global/qlogging.cpp b/src/corelib/global/qlogging.cpp index 8eaade6247..a94dd1eeaa 100644 --- a/src/corelib/global/qlogging.cpp +++ b/src/corelib/global/qlogging.cpp @@ -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); |