File indexing completed on 2024-05-12 04:40:07
0001 /* 0002 SPDX-FileCopyrightText: 2016 Aetf <aetf@unlimitedcodeworks.xyz> 0003 0004 SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0005 */ 0006 0007 #include "framestackmodel.h" 0008 0009 #include "debuglog.h" 0010 #include "debugsession.h" 0011 #include "mi/micommand.h" 0012 0013 #include <KLocalizedString> 0014 0015 namespace { 0016 0017 QString getFunctionOrAddress(const KDevMI::MI::Value &frame) 0018 { 0019 if (frame.hasField(QStringLiteral("func"))) 0020 return frame[QStringLiteral("func")].literal(); 0021 else 0022 return frame[QStringLiteral("addr")].literal(); 0023 } 0024 0025 } 0026 0027 using namespace KDevMI::LLDB; 0028 using namespace KDevMI::MI; 0029 using namespace KDevMI; 0030 0031 LldbFrameStackModel::LldbFrameStackModel(DebugSession *session) 0032 : MIFrameStackModel(session) 0033 , stoppedAtThread(-1) 0034 { 0035 connect(session, &DebugSession::inferiorStopped, this, &LldbFrameStackModel::inferiorStopped); 0036 } 0037 0038 DebugSession* LldbFrameStackModel::session() 0039 { 0040 return static_cast<DebugSession *>(FrameStackModel::session()); 0041 } 0042 0043 void LldbFrameStackModel::inferiorStopped(const MI::AsyncRecord& r) 0044 { 0045 if (session()->debuggerStateIsOn(s_shuttingDown)) return; 0046 0047 if (r.hasField(QStringLiteral("thread-id"))) { 0048 stoppedAtThread = r[QStringLiteral("thread-id")].toInt(); 0049 } 0050 } 0051 0052 void LldbFrameStackModel::fetchThreads() 0053 { 0054 // TODO: preliminary test shows there might be a bug in lldb-mi 0055 // that's causing std::logic_error when executing -thread-info with 0056 // more than one threads. Find a workaround for this (and report bug 0057 // if it truly is). 0058 session()->addCommand(ThreadInfo, QString(), this, &LldbFrameStackModel::handleThreadInfo); 0059 } 0060 0061 void LldbFrameStackModel::handleThreadInfo(const ResultRecord& r) 0062 { 0063 const Value& threads = r[QStringLiteral("threads")]; 0064 0065 QVector<FrameStackModel::ThreadItem> threadsList; 0066 threadsList.reserve(threads.size()); 0067 for (int gidx = 0; gidx != threads.size(); ++gidx) { 0068 FrameStackModel::ThreadItem i; 0069 const Value & threadMI = threads[gidx]; 0070 i.nr = threadMI[QStringLiteral("id")].toInt(); 0071 if (threadMI[QStringLiteral("state")].literal() == QLatin1String("stopped")) { 0072 // lldb-mi returns multiple frame entry for each thread 0073 // so can't directly use threadMI["frame"] 0074 auto &th = static_cast<const TupleValue&>(threadMI); 0075 Value *topFrame = nullptr; 0076 for (auto res : th.results) { 0077 if (res->variable == QLatin1String("frame")) { 0078 if (!topFrame || (*res->value)[QStringLiteral("level")].toInt() < (*topFrame)[QStringLiteral("level")].toInt()) { 0079 topFrame = res->value; 0080 } 0081 } 0082 } 0083 i.name = getFunctionOrAddress(*topFrame); 0084 } else { 0085 i.name = i18n("(running)"); 0086 } 0087 threadsList << i; 0088 } 0089 setThreads(threadsList); 0090 if (r.hasField(QStringLiteral("current-thread-id"))) { 0091 int currentThreadId = r[QStringLiteral("current-thread-id")].toInt(); 0092 0093 setCurrentThread(currentThreadId); 0094 0095 if (session()->hasCrashed()) { 0096 setCrashedThreadIndex(currentThreadId); 0097 } 0098 } 0099 // lldb-mi doesn't have current-thread-id field. Use the thread-id field when inferiorStopped 0100 if (stoppedAtThread != -1) { 0101 setCurrentThread(stoppedAtThread); 0102 } 0103 stoppedAtThread = -1; 0104 } 0105 0106 #include "moc_framestackmodel.cpp"