]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdThread.cpp
MFV r348568: 9466 add JSON output support to channel programs
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / tools / lldb-mi / MICmdCmdThread.cpp
1 //===-- MICmdCmdThread.cpp --------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 // Overview:    CMICmdCmdThreadInfo     implementation.
11
12 // Third Party Headers:
13 #include "lldb/API/SBBreakpointLocation.h"
14 #include "lldb/API/SBThread.h"
15
16 // In-house headers:
17 #include "MICmdArgValNumber.h"
18 #include "MICmdCmdThread.h"
19 #include "MICmnLLDBDebugSessionInfo.h"
20 #include "MICmnLLDBDebugger.h"
21 #include "MICmnMIResultRecord.h"
22 #include "MICmnMIValueConst.h"
23
24 //++
25 //------------------------------------------------------------------------------------
26 // Details: CMICmdCmdThreadInfo constructor.
27 // Type:    Method.
28 // Args:    None.
29 // Return:  None.
30 // Throws:  None.
31 //--
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";
37
38   // Required by the CMICmdFactory when registering *this command
39   m_pSelfCreatorFn = &CMICmdCmdThreadInfo::CreateSelf;
40 }
41
42 //++
43 //------------------------------------------------------------------------------------
44 // Details: CMICmdCmdThreadInfo destructor.
45 // Type:    Overrideable.
46 // Args:    None.
47 // Return:  None.
48 // Throws:  None.
49 //--
50 CMICmdCmdThreadInfo::~CMICmdCmdThreadInfo() { m_vecMIValueTuple.clear(); }
51
52 //++
53 //------------------------------------------------------------------------------------
54 // Details: The invoker requires this function. The parses the command line
55 // options
56 //          arguments to extract values for each of those arguments.
57 // Type:    Overridden.
58 // Args:    None.
59 // Return:  MIstatus::success - Functional succeeded.
60 //          MIstatus::failure - Functional failed.
61 // Throws:  None.
62 //--
63 bool CMICmdCmdThreadInfo::ParseArgs() {
64   m_setCmdArgs.Add(
65       new CMICmdArgValNumber(m_constStrArgNamedThreadId, false, true));
66   return ParseValidateCmdOptions();
67 }
68
69 //++
70 //------------------------------------------------------------------------------------
71 // Details: The invoker requires this function. The command does work in this
72 // function.
73 //          The command is likely to communicate with the LLDB SBDebugger in
74 //          here.
75 // Type:    Overridden.
76 // Args:    None.
77 // Return:  MIstatus::success - Functional succeeded.
78 //          MIstatus::failure - Functional failed.
79 // Throws:  None.
80 //--
81 bool CMICmdCmdThreadInfo::Execute() {
82   CMICMDBASE_GETOPTION(pArgThreadId, Number, m_constStrArgNamedThreadId);
83   MIuint nThreadId = 0;
84   if (pArgThreadId->GetFound() && pArgThreadId->GetValid()) {
85     m_bSingleThread = true;
86     nThreadId = static_cast<MIuint>(pArgThreadId->GetValue());
87   }
88
89   CMICmnLLDBDebugSessionInfo &rSessionInfo(
90       CMICmnLLDBDebugSessionInfo::Instance());
91   lldb::SBProcess sbProcess = rSessionInfo.GetProcess();
92   lldb::SBThread thread = sbProcess.GetSelectedThread();
93
94   if (m_bSingleThread) {
95     thread = sbProcess.GetThreadByIndexID(nThreadId);
96     m_bThreadInvalid = !thread.IsValid();
97     if (m_bThreadInvalid)
98       return MIstatus::success;
99
100     CMICmnMIValueTuple miTuple;
101     if (!rSessionInfo.MIResponseFormThreadInfo(
102             m_cmdData, thread,
103             CMICmnLLDBDebugSessionInfo::eThreadInfoFormat_AllFrames, miTuple))
104       return MIstatus::failure;
105
106     m_miValueTupleThread = miTuple;
107
108     return MIstatus::success;
109   }
110
111   // Multiple threads
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(
119               m_cmdData, thread,
120               CMICmnLLDBDebugSessionInfo::eThreadInfoFormat_AllFrames, miTuple))
121         return MIstatus::failure;
122
123       m_vecMIValueTuple.push_back(miTuple);
124     }
125   }
126
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;
133   }
134
135   return MIstatus::success;
136 }
137
138 //++
139 //------------------------------------------------------------------------------------
140 // Details: The invoker requires this function. The command prepares a MI Record
141 // Result
142 //          for the work carried out in the Execute().
143 // Type:    Overridden.
144 // Args:    None.
145 // Return:  MIstatus::success - Functional succeeded.
146 //          MIstatus::failure - Functional failed.
147 // Throws:  None.
148 //--
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,
156           miValueResult);
157       m_miResultRecord = miRecordResult;
158       return MIstatus::success;
159     }
160
161     // MI print
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,
167         miValueResult);
168     m_miResultRecord = miRecordResult;
169     return MIstatus::success;
170   }
171
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,
179         miValueResult);
180     m_miResultRecord = miRecordResult;
181     return MIstatus::success;
182   }
183   CMICmnMIValueList miValueList(*it);
184   ++it;
185   while (it != m_vecMIValueTuple.end()) {
186     const CMICmnMIValueTuple &rTuple(*it);
187     miValueList.Add(rTuple);
188
189     // Next
190     ++it;
191   }
192
193   CMICmnMIValueResult miValueResult("threads", miValueList);
194   if (m_bHasCurrentThread) {
195     CMIUtilString strCurrThreadId = "current-thread-id";
196     miValueResult.Add(strCurrThreadId, m_miValueCurrThreadId);
197   }
198   const CMICmnMIResultRecord miRecordResult(
199       m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done,
200       miValueResult);
201   m_miResultRecord = miRecordResult;
202
203   return MIstatus::success;
204 }
205
206 //++
207 //------------------------------------------------------------------------------------
208 // Details: Required by the CMICmdFactory when registering *this command. The
209 // factory
210 //          calls this function to create an instance of *this command.
211 // Type:    Static method.
212 // Args:    None.
213 // Return:  CMICmdBase * - Pointer to a new command.
214 // Throws:  None.
215 //--
216 CMICmdBase *CMICmdCmdThreadInfo::CreateSelf() {
217   return new CMICmdCmdThreadInfo();
218 }