File indexing completed on 2024-05-05 05:51:19
0001 /* This file is part of the KDE project 0002 SPDX-FileCopyrightText: 2008-2014 Dominik Haumann <dhaumann kde org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-only 0005 */ 0006 0007 #include "btparser.h" 0008 0009 #include <QDebug> 0010 #include <QRegularExpression> 0011 #include <QStringList> 0012 0013 static QString eolDelimiter(const QString &str) 0014 { 0015 // find the split character 0016 QString separator(QLatin1Char('\n')); 0017 if (str.indexOf(QLatin1String("\r\n")) != -1) { 0018 separator = QStringLiteral("\r\n"); 0019 } else if (str.indexOf(QLatin1Char('\r')) != -1) { 0020 separator = QLatin1Char('\r'); 0021 } 0022 return separator; 0023 } 0024 0025 static bool lineNoLessThan(const QString &lhs, const QString &rhs) 0026 { 0027 const QRegularExpression rx(QStringLiteral("^#(\\d+)")); 0028 QRegularExpressionMatch match = rx.match(lhs); 0029 int ilhs = match.capturedStart(0); 0030 int lhsLn = match.captured(1).toInt(); 0031 match = rx.match(rhs); 0032 int irhs = match.capturedStart(0); 0033 int rhsLn = match.captured(1).toInt(); 0034 if (ilhs != -1 && irhs != -1) { 0035 return lhsLn < rhsLn; 0036 } else { 0037 return lhs < rhs; 0038 } 0039 } 0040 0041 static QStringList normalizeBt(const QStringList &l) 0042 { 0043 QStringList normalized; 0044 0045 bool append = false; 0046 0047 for (int i = 0; i < l.size(); ++i) { 0048 QString str = l[i].trimmed(); 0049 if (str.length()) { 0050 if (str[0] == QLatin1Char('#')) { 0051 normalized << str; 0052 append = true; 0053 } else if (append) { 0054 normalized.last() += QLatin1Char(' ') + str; 0055 } 0056 } else { 0057 append = false; 0058 } 0059 } 0060 0061 std::sort(normalized.begin(), normalized.end(), lineNoLessThan); 0062 0063 // now every single line contains a whole backtrace info 0064 return normalized; 0065 } 0066 0067 static BtInfo parseBtLine(const QString &line) 0068 { 0069 // the syntax types we support are 0070 // a) #24 0xb688ff8e in QApplication::notify (this=0xbf997e8c, receiver=0x82607e8, e=0xbf997074) at kernel/qapplication.cpp:3115 0071 // b) #39 0xb634211c in g_main_context_dispatch () from /usr/lib/libglib-2.0.so.0 0072 // c) #41 0x0805e690 in ?? () 0073 // d) #5 0xffffe410 in __kernel_vsyscall () 0074 0075 // try a) cap #number(1), address(2), function(3), filename(4), linenumber(5) 0076 static const QRegularExpression rxa(QStringLiteral("^#(\\d+)\\s+(0x\\w+)\\s+in\\s+(.+)\\s+at\\s+(.+):(\\d+)$")); 0077 QRegularExpressionMatch match = rxa.match(line); 0078 if (match.hasMatch()) { 0079 BtInfo info; 0080 info.original = line; 0081 info.filename = match.captured(4); 0082 info.function = match.captured(3); 0083 info.address = match.captured(2); 0084 info.line = match.captured(5).toInt(); 0085 info.step = match.captured(1).toInt(); 0086 info.type = BtInfo::Source; 0087 return info; 0088 } 0089 0090 // try b) cap #number(1), address(2), function(3), lib(4) 0091 static const QRegularExpression rxb(QStringLiteral("^#(\\d+)\\s+(0x\\w+)\\s+in\\s+(.+)\\s+from\\s+(.+)$")); 0092 match = rxb.match(line); 0093 if (match.hasMatch()) { 0094 BtInfo info; 0095 info.original = line; 0096 info.filename = match.captured(4); 0097 info.function = match.captured(3); 0098 info.address = match.captured(2); 0099 info.line = -1; 0100 info.step = match.captured(1).toInt(); 0101 info.type = BtInfo::Lib; 0102 return info; 0103 } 0104 0105 // try c) #41 0x0805e690 in ?? () 0106 static const QRegularExpression rxc(QStringLiteral("^#(\\d+)\\s+(0x\\w+)\\s+in\\s+\\?\\?\\s+\\(\\)$")); 0107 match = rxc.match(line); 0108 if (match.hasMatch()) { 0109 BtInfo info; 0110 info.original = line; 0111 info.filename = QString(); 0112 info.function = QString(); 0113 info.address = match.captured(2); 0114 info.line = -1; 0115 info.step = match.captured(1).toInt(); 0116 info.type = BtInfo::Unknown; 0117 return info; 0118 } 0119 0120 // try d) #5 0xffffe410 in __kernel_vsyscall () 0121 static const QRegularExpression rxd(QStringLiteral("^#(\\d+)\\s+(0x\\w+)\\s+in\\s+(.+)$")); 0122 match = rxd.match(line); 0123 if (match.hasMatch()) { 0124 BtInfo info; 0125 info.original = line; 0126 info.filename = QString(); 0127 info.function = match.captured(3); 0128 info.address = match.captured(2); 0129 info.line = -1; 0130 info.step = match.captured(1).toInt(); 0131 info.type = BtInfo::Unknown; 0132 return info; 0133 } 0134 0135 qDebug() << "Unknown backtrace line:" << line; 0136 0137 BtInfo info; 0138 info.type = BtInfo::Invalid; 0139 return info; 0140 } 0141 0142 QList<BtInfo> KateBtParser::parseBacktrace(const QString &bt) 0143 { 0144 QStringList l = bt.split(eolDelimiter(bt), Qt::SkipEmptyParts); 0145 0146 l = normalizeBt(l); 0147 0148 QList<BtInfo> btList; 0149 for (int i = 0; i < l.size(); ++i) { 0150 BtInfo info = parseBtLine(l[i]); 0151 if (info.type != BtInfo::Invalid) { 0152 btList.append(parseBtLine(l[i])); 0153 } 0154 } 0155 0156 return btList; 0157 } 0158 0159 // kate: space-indent on; indent-width 4; replace-tabs on;