1 //===-- MICmdCmdThread.cpp --------------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // Overview: CMICmdCmdThreadInfo implementation.
12 // Third Party Headers:
13 #include "lldb/API/SBBreakpointLocation.h"
14 #include "lldb/API/SBThread.h"
17 #include "MICmdArgValNumber.h"
18 #include "MICmdCmdThread.h"
19 #include "MICmnLLDBDebugSessionInfo.h"
20 #include "MICmnLLDBDebugger.h"
21 #include "MICmnMIResultRecord.h"
22 #include "MICmnMIValueConst.h"
25 //------------------------------------------------------------------------------------
26 // Details: CMICmdCmdThreadInfo constructor.
32 CMICmdCmdThreadInfo::CMICmdCmdThreadInfo()
33 : m_bSingleThread(false), m_bThreadInvalid(true),
34 m_constStrArgNamedThreadId("thread-id"), m_bHasCurrentThread(false) {
35 // Command factory matches this name with that received from the stdin stream
36 m_strMiCmd = "thread-info";
38 // Required by the CMICmdFactory when registering *this command
39 m_pSelfCreatorFn = &CMICmdCmdThreadInfo::CreateSelf;
43 //------------------------------------------------------------------------------------
44 // Details: CMICmdCmdThreadInfo destructor.
45 // Type: Overrideable.
50 CMICmdCmdThreadInfo::~CMICmdCmdThreadInfo() { m_vecMIValueTuple.clear(); }
53 //------------------------------------------------------------------------------------
54 // Details: The invoker requires this function. The parses the command line
56 // arguments to extract values for each of those arguments.
59 // Return: MIstatus::success - Functional succeeded.
60 // MIstatus::failure - Functional failed.
63 bool CMICmdCmdThreadInfo::ParseArgs() {
65 new CMICmdArgValNumber(m_constStrArgNamedThreadId, false, true));
66 return ParseValidateCmdOptions();
70 //------------------------------------------------------------------------------------
71 // Details: The invoker requires this function. The command does work in this
73 // The command is likely to communicate with the LLDB SBDebugger in
77 // Return: MIstatus::success - Functional succeeded.
78 // MIstatus::failure - Functional failed.
81 bool CMICmdCmdThreadInfo::Execute() {
82 CMICMDBASE_GETOPTION(pArgThreadId, Number, m_constStrArgNamedThreadId);
84 if (pArgThreadId->GetFound() && pArgThreadId->GetValid()) {
85 m_bSingleThread = true;
86 nThreadId = static_cast<MIuint>(pArgThreadId->GetValue());
89 CMICmnLLDBDebugSessionInfo &rSessionInfo(
90 CMICmnLLDBDebugSessionInfo::Instance());
91 lldb::SBProcess sbProcess = rSessionInfo.GetProcess();
92 lldb::SBThread thread = sbProcess.GetSelectedThread();
94 if (m_bSingleThread) {
95 thread = sbProcess.GetThreadByIndexID(nThreadId);
96 m_bThreadInvalid = !thread.IsValid();
98 return MIstatus::success;
100 CMICmnMIValueTuple miTuple;
101 if (!rSessionInfo.MIResponseFormThreadInfo(
103 CMICmnLLDBDebugSessionInfo::eThreadInfoFormat_AllFrames, miTuple))
104 return MIstatus::failure;
106 m_miValueTupleThread = miTuple;
108 return MIstatus::success;
112 m_vecMIValueTuple.clear();
113 const MIuint nThreads = sbProcess.GetNumThreads();
114 for (MIuint i = 0; i < nThreads; i++) {
115 lldb::SBThread thread = sbProcess.GetThreadAtIndex(i);
116 if (thread.IsValid()) {
117 CMICmnMIValueTuple miTuple;
118 if (!rSessionInfo.MIResponseFormThreadInfo(
120 CMICmnLLDBDebugSessionInfo::eThreadInfoFormat_AllFrames, miTuple))
121 return MIstatus::failure;
123 m_vecMIValueTuple.push_back(miTuple);
127 // -thread-info with multiple threads ends with the current thread id if any
128 if (thread.IsValid()) {
129 const CMIUtilString strId(CMIUtilString::Format("%d", thread.GetIndexID()));
130 CMICmnMIValueConst miValueCurrThreadId(strId);
131 m_miValueCurrThreadId = miValueCurrThreadId;
132 m_bHasCurrentThread = true;
135 return MIstatus::success;
139 //------------------------------------------------------------------------------------
140 // Details: The invoker requires this function. The command prepares a MI Record
142 // for the work carried out in the Execute().
145 // Return: MIstatus::success - Functional succeeded.
146 // MIstatus::failure - Functional failed.
149 bool CMICmdCmdThreadInfo::Acknowledge() {
150 if (m_bSingleThread) {
151 if (m_bThreadInvalid) {
152 const CMICmnMIValueConst miValueConst("invalid thread id");
153 const CMICmnMIValueResult miValueResult("msg", miValueConst);
154 const CMICmnMIResultRecord miRecordResult(
155 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error,
157 m_miResultRecord = miRecordResult;
158 return MIstatus::success;
162 // "%s^done,threads=[{id=\"%d\",target-id=\"%s\",frame={},state=\"%s\"}]
163 const CMICmnMIValueList miValueList(m_miValueTupleThread);
164 const CMICmnMIValueResult miValueResult("threads", miValueList);
165 const CMICmnMIResultRecord miRecordResult(
166 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done,
168 m_miResultRecord = miRecordResult;
169 return MIstatus::success;
172 // Build up a list of thread information from tuples
173 VecMIValueTuple_t::const_iterator it = m_vecMIValueTuple.begin();
174 if (it == m_vecMIValueTuple.end()) {
175 const CMICmnMIValueConst miValueConst("[]");
176 const CMICmnMIValueResult miValueResult("threads", miValueConst);
177 const CMICmnMIResultRecord miRecordResult(
178 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done,
180 m_miResultRecord = miRecordResult;
181 return MIstatus::success;
183 CMICmnMIValueList miValueList(*it);
185 while (it != m_vecMIValueTuple.end()) {
186 const CMICmnMIValueTuple &rTuple(*it);
187 miValueList.Add(rTuple);
193 CMICmnMIValueResult miValueResult("threads", miValueList);
194 if (m_bHasCurrentThread) {
195 CMIUtilString strCurrThreadId = "current-thread-id";
196 miValueResult.Add(strCurrThreadId, m_miValueCurrThreadId);
198 const CMICmnMIResultRecord miRecordResult(
199 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done,
201 m_miResultRecord = miRecordResult;
203 return MIstatus::success;
207 //------------------------------------------------------------------------------------
208 // Details: Required by the CMICmdFactory when registering *this command. The
210 // calls this function to create an instance of *this command.
211 // Type: Static method.
213 // Return: CMICmdBase * - Pointer to a new command.
216 CMICmdBase *CMICmdCmdThreadInfo::CreateSelf() {
217 return new CMICmdCmdThreadInfo();