]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm-project/lldb/tools/lldb-mi/MICmdCmdThread.cpp
Unbreak DRM KMS build by adding the needed compatibility field in the LinuxKPI.
[FreeBSD/FreeBSD.git] / contrib / llvm-project / lldb / tools / lldb-mi / MICmdCmdThread.cpp
1 //===-- MICmdCmdThread.cpp --------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 // Overview:    CMICmdCmdThreadInfo     implementation.
10
11 // Third Party Headers:
12 #include "lldb/API/SBBreakpointLocation.h"
13 #include "lldb/API/SBThread.h"
14
15 // In-house headers:
16 #include "MICmdArgValNumber.h"
17 #include "MICmdCmdThread.h"
18 #include "MICmnLLDBDebugSessionInfo.h"
19 #include "MICmnLLDBDebugger.h"
20 #include "MICmnMIResultRecord.h"
21 #include "MICmnMIValueConst.h"
22
23 //++
24 // Details: CMICmdCmdThreadInfo constructor.
25 // Type:    Method.
26 // Args:    None.
27 // Return:  None.
28 // Throws:  None.
29 //--
30 CMICmdCmdThreadInfo::CMICmdCmdThreadInfo()
31     : m_bSingleThread(false), m_bThreadInvalid(true),
32       m_constStrArgNamedThreadId("thread-id"), m_bHasCurrentThread(false) {
33   // Command factory matches this name with that received from the stdin stream
34   m_strMiCmd = "thread-info";
35
36   // Required by the CMICmdFactory when registering *this command
37   m_pSelfCreatorFn = &CMICmdCmdThreadInfo::CreateSelf;
38 }
39
40 //++
41 // Details: CMICmdCmdThreadInfo destructor.
42 // Type:    Overrideable.
43 // Args:    None.
44 // Return:  None.
45 // Throws:  None.
46 //--
47 CMICmdCmdThreadInfo::~CMICmdCmdThreadInfo() { m_vecMIValueTuple.clear(); }
48
49 //++
50 // Details: The invoker requires this function. The parses the command line
51 // options
52 //          arguments to extract values for each of those arguments.
53 // Type:    Overridden.
54 // Args:    None.
55 // Return:  MIstatus::success - Functional succeeded.
56 //          MIstatus::failure - Functional failed.
57 // Throws:  None.
58 //--
59 bool CMICmdCmdThreadInfo::ParseArgs() {
60   m_setCmdArgs.Add(
61       new CMICmdArgValNumber(m_constStrArgNamedThreadId, false, true));
62   return ParseValidateCmdOptions();
63 }
64
65 //++
66 // Details: The invoker requires this function. The command does work in this
67 // function.
68 //          The command is likely to communicate with the LLDB SBDebugger in
69 //          here.
70 // Type:    Overridden.
71 // Args:    None.
72 // Return:  MIstatus::success - Functional succeeded.
73 //          MIstatus::failure - Functional failed.
74 // Throws:  None.
75 //--
76 bool CMICmdCmdThreadInfo::Execute() {
77   CMICMDBASE_GETOPTION(pArgThreadId, Number, m_constStrArgNamedThreadId);
78   MIuint nThreadId = 0;
79   if (pArgThreadId->GetFound() && pArgThreadId->GetValid()) {
80     m_bSingleThread = true;
81     nThreadId = static_cast<MIuint>(pArgThreadId->GetValue());
82   }
83
84   CMICmnLLDBDebugSessionInfo &rSessionInfo(
85       CMICmnLLDBDebugSessionInfo::Instance());
86   lldb::SBProcess sbProcess = rSessionInfo.GetProcess();
87   lldb::SBThread thread = sbProcess.GetSelectedThread();
88
89   if (m_bSingleThread) {
90     thread = sbProcess.GetThreadByIndexID(nThreadId);
91     m_bThreadInvalid = !thread.IsValid();
92     if (m_bThreadInvalid)
93       return MIstatus::success;
94
95     CMICmnMIValueTuple miTuple;
96     if (!rSessionInfo.MIResponseFormThreadInfo(
97             m_cmdData, thread,
98             CMICmnLLDBDebugSessionInfo::eThreadInfoFormat_AllFrames, miTuple))
99       return MIstatus::failure;
100
101     m_miValueTupleThread = miTuple;
102
103     return MIstatus::success;
104   }
105
106   // Multiple threads
107   m_vecMIValueTuple.clear();
108   const MIuint nThreads = sbProcess.GetNumThreads();
109   for (MIuint i = 0; i < nThreads; i++) {
110     lldb::SBThread thread = sbProcess.GetThreadAtIndex(i);
111     if (thread.IsValid()) {
112       CMICmnMIValueTuple miTuple;
113       if (!rSessionInfo.MIResponseFormThreadInfo(
114               m_cmdData, thread,
115               CMICmnLLDBDebugSessionInfo::eThreadInfoFormat_AllFrames, miTuple))
116         return MIstatus::failure;
117
118       m_vecMIValueTuple.push_back(miTuple);
119     }
120   }
121
122   // -thread-info with multiple threads ends with the current thread id if any
123   if (thread.IsValid()) {
124     const CMIUtilString strId(CMIUtilString::Format("%d", thread.GetIndexID()));
125     CMICmnMIValueConst miValueCurrThreadId(strId);
126     m_miValueCurrThreadId = miValueCurrThreadId;
127     m_bHasCurrentThread = true;
128   }
129
130   return MIstatus::success;
131 }
132
133 //++
134 // Details: The invoker requires this function. The command prepares a MI Record
135 // Result
136 //          for the work carried out in the Execute().
137 // Type:    Overridden.
138 // Args:    None.
139 // Return:  MIstatus::success - Functional succeeded.
140 //          MIstatus::failure - Functional failed.
141 // Throws:  None.
142 //--
143 bool CMICmdCmdThreadInfo::Acknowledge() {
144   if (m_bSingleThread) {
145     if (m_bThreadInvalid) {
146       const CMICmnMIValueConst miValueConst("invalid thread id");
147       const CMICmnMIValueResult miValueResult("msg", miValueConst);
148       const CMICmnMIResultRecord miRecordResult(
149           m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error,
150           miValueResult);
151       m_miResultRecord = miRecordResult;
152       return MIstatus::success;
153     }
154
155     // MI print
156     // "%s^done,threads=[{id=\"%d\",target-id=\"%s\",frame={},state=\"%s\"}]
157     const CMICmnMIValueList miValueList(m_miValueTupleThread);
158     const CMICmnMIValueResult miValueResult("threads", miValueList);
159     const CMICmnMIResultRecord miRecordResult(
160         m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done,
161         miValueResult);
162     m_miResultRecord = miRecordResult;
163     return MIstatus::success;
164   }
165
166   // Build up a list of thread information from tuples
167   VecMIValueTuple_t::const_iterator it = m_vecMIValueTuple.begin();
168   if (it == m_vecMIValueTuple.end()) {
169     const CMICmnMIValueConst miValueConst("[]");
170     const CMICmnMIValueResult miValueResult("threads", miValueConst);
171     const CMICmnMIResultRecord miRecordResult(
172         m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done,
173         miValueResult);
174     m_miResultRecord = miRecordResult;
175     return MIstatus::success;
176   }
177   CMICmnMIValueList miValueList(*it);
178   ++it;
179   while (it != m_vecMIValueTuple.end()) {
180     const CMICmnMIValueTuple &rTuple(*it);
181     miValueList.Add(rTuple);
182
183     // Next
184     ++it;
185   }
186
187   CMICmnMIValueResult miValueResult("threads", miValueList);
188   if (m_bHasCurrentThread) {
189     CMIUtilString strCurrThreadId = "current-thread-id";
190     miValueResult.Add(strCurrThreadId, m_miValueCurrThreadId);
191   }
192   const CMICmnMIResultRecord miRecordResult(
193       m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done,
194       miValueResult);
195   m_miResultRecord = miRecordResult;
196
197   return MIstatus::success;
198 }
199
200 //++
201 // Details: Required by the CMICmdFactory when registering *this command. The
202 // factory
203 //          calls this function to create an instance of *this command.
204 // Type:    Static method.
205 // Args:    None.
206 // Return:  CMICmdBase * - Pointer to a new command.
207 // Throws:  None.
208 //--
209 CMICmdBase *CMICmdCmdThreadInfo::CreateSelf() {
210   return new CMICmdCmdThreadInfo();
211 }