From ff2535de5c3d0cdcd9232780f53fd4ff00ea822a Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Fri, 18 Feb 2022 12:25:22 -0800 Subject: [PATCH] Logging: add support for decoding backtraces using dladdr() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I'm pretty sure that's what backtrace_symbols() uses internally anyway, so skip the middle-man. Change-Id: Ic15405335d804bdea761fffd16d4fb2a1b0c2171 Reviewed-by: Alexey Edelev Reviewed-by: hjk Reviewed-by: Tor Arne Vestbø --- src/corelib/configure.cmake | 21 ++++++++++++++++++++ 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 249e84cb01c..101e7a6ec7c 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 +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 " 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 8eaade62474..a94dd1eeaac 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() && QT_CONFIG(backtrace) && QT_CONFIG(regularexpression) # include +# if QT_CONFIG(dladdr) +# include +# endif # include BACKTRACE_HEADER # include # 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 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);