summaryrefslogtreecommitdiffstats
path: root/src/corelib/global/qlogging.cpp
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2022-02-18 11:34:30 -0800
committerThiago Macieira <thiago.macieira@intel.com>2022-03-03 19:05:11 -0800
commit1cad4ed6a1f3e5f091f7bf1cb9998383d226a4b2 (patch)
tree4fcaf575e4b0ded1dd0cf091ed0c3dfa900d6af6 /src/corelib/global/qlogging.cpp
parentee7166e1761c3b5ca885bab299a7d036e884c2e7 (diff)
Logging: reorganize the backtrace code for simplicity and readability
Also removed the Qt::CaseInsensitive searching, which was slow. Change-Id: Ic15405335d804bdea761fffd16d4f863847c360b Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
Diffstat (limited to 'src/corelib/global/qlogging.cpp')
-rw-r--r--src/corelib/global/qlogging.cpp104
1 files changed, 68 insertions, 36 deletions
diff --git a/src/corelib/global/qlogging.cpp b/src/corelib/global/qlogging.cpp
index 11a43f73efc..8eaade62474 100644
--- a/src/corelib/global/qlogging.cpp
+++ b/src/corelib/global/qlogging.cpp
@@ -1283,10 +1283,49 @@ __attribute__((optimize("omit-frame-pointer")))
#endif
static QStringList backtraceFramesForLogMessage(int frameCount)
{
+ struct DecodedFrame {
+ QString library;
+ QString function;
+ };
+
QStringList result;
if (frameCount == 0)
return result;
+ QVarLengthArray<void *, 32> buffer(TypicalBacktraceFrameCount + frameCount);
+ int n = backtrace(buffer.data(), buffer.size());
+ if (n <= 0)
+ return result;
+ buffer.resize(n);
+
+ auto shouldSkipFrame = [&result](const auto &library, const auto &function) {
+ if (!result.isEmpty() || !library.contains(QLatin1String("Qt6Core")))
+ return false;
+ if (function.isEmpty())
+ return true;
+ if (function.contains(QLatin1String("6QDebug")))
+ return true;
+ if (function.contains(QLatin1String("Message")) || function.contains(QLatin1String("_message")))
+ return true;
+ return false;
+ };
+
+ auto demangled = [](QString &function) {
+ if (!function.startsWith(QLatin1String("_Z")))
+ return function;
+
+ // we optimize for the case where __cxa_demangle succeeds
+ QByteArray fn = std::move(function).toUtf8();
+ QScopedPointer<char, QScopedPointerPodDeleter> demangled;
+ demangled.reset(abi::__cxa_demangle(fn, nullptr, nullptr, nullptr));
+
+ if (demangled)
+ return QString::fromUtf8(qCleanupFuncinfo(demangled.data()));
+ else
+ return QString::fromUtf8(fn); // restore
+ };
+
+
// The results of backtrace_symbols looks like this:
// /lib/libc.so.6(__libc_start_main+0xf3) [0x4a937413]
// The offset and function name are optional.
@@ -1294,46 +1333,39 @@ static QStringList backtraceFramesForLogMessage(int frameCount)
// This code is protected by QMessagePattern::mutex so it is thread safe on all compilers
static const QRegularExpression rx(QStringLiteral("^(?:[^(]*/)?([^(/]+)\\(([^+]*)(?:[\\+[a-f0-9x]*)?\\) \\[[a-f0-9x]*\\]$"));
- QVarLengthArray<void *, 32> buffer(TypicalBacktraceFrameCount + frameCount);
- int n = backtrace(buffer.data(), buffer.size());
- if (n > 0) {
- int numberPrinted = 0;
- for (int i = 0; i < n && numberPrinted < frameCount; ++i) {
- QScopedPointer<char*, QScopedPointerPodDeleter> strings(backtrace_symbols(buffer.data() + i, 1));
- QString trace = QString::fromUtf8(strings.data()[0]);
- QRegularExpressionMatch m = rx.match(trace);
- if (m.hasMatch()) {
- QString library = m.captured(1);
- QString function = m.captured(2);
-
- // skip the trace from QtCore that are because of the qDebug itself
- if (!numberPrinted && library.contains(QLatin1String("Qt6Core"))
- && (function.isEmpty() || function.contains(QLatin1String("Message"), Qt::CaseInsensitive)
- || function.contains(QLatin1String("QDebug")))) {
- continue;
- }
+ auto decodeFrame = [&](void *&addr) -> DecodedFrame {
+ QScopedPointer<char*, QScopedPointerPodDeleter> strings(backtrace_symbols(&addr, 1));
+ QString trace = QString::fromUtf8(strings.data()[0]);
+ QRegularExpressionMatch m = rx.match(trace);
+ if (!m.hasMatch())
+ return {};
- if (function.startsWith(QLatin1String("_Z"))) {
- QScopedPointer<char, QScopedPointerPodDeleter> demangled(
- abi::__cxa_demangle(function.toUtf8(), nullptr, nullptr, nullptr));
- if (demangled)
- function = QString::fromUtf8(qCleanupFuncinfo(demangled.data()));
- }
+ QString library = m.captured(1);
+ QString function = m.captured(2);
- if (function.isEmpty()) {
- result.append(QLatin1Char('?') + library + QLatin1Char('?'));
- } else {
- result.append(function);
- }
- } else {
- if (numberPrinted == 0) {
- // innermost, unknown frames are usually the logging framework itself
- continue;
- }
+ // skip the trace from QtCore that are because of the qDebug itself
+ if (shouldSkipFrame(library, function))
+ return {};
+
+ function = demangled(function);
+ return { library, function };
+ };
+
+ for (void *&addr : buffer) {
+ DecodedFrame frame = decodeFrame(addr);
+ if (!frame.library.isEmpty()) {
+ if (frame.function.isEmpty())
+ result.append(QLatin1Char('?') + frame.library + QLatin1Char('?'));
+ else
+ result.append(frame.function);
+ } else {
+ // innermost, unknown frames are usually the logging framework itself
+ if (!result.isEmpty())
result.append(QStringLiteral("???"));
- }
- numberPrinted++;
}
+
+ if (result.size() == frameCount)
+ break;
}
return result;
}