summaryrefslogtreecommitdiffstats
path: root/src/corelib
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2022-02-18 12:25:22 -0800
committerThiago Macieira <thiago.macieira@intel.com>2022-03-03 19:05:11 -0800
commitff2535de5c3d0cdcd9232780f53fd4ff00ea822a (patch)
tree7a4f239939033c636487e23166456281529011a5 /src/corelib
parent1cad4ed6a1f3e5f091f7bf1cb9998383d226a4b2 (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.cmake21
-rw-r--r--src/corelib/global/qlogging.cpp35
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);