]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm-project/lldb/tools/lldb-mi/MICmdCmdTarget.cpp
MFC r355940:
[FreeBSD/FreeBSD.git] / contrib / llvm-project / lldb / tools / lldb-mi / MICmdCmdTarget.cpp
1 //===-- MICmdCmdTarget.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:    CMICmdCmdTargetSelect           implementation.
10
11 // Third Party Headers:
12 #include "lldb/API/SBStream.h"
13 #include "lldb/API/SBError.h"
14
15 // In-house headers:
16 #include "MICmdArgValNumber.h"
17 #include "MICmdArgValOptionLong.h"
18 #include "MICmdArgValOptionShort.h"
19 #include "MICmdArgValString.h"
20 #include "MICmdCmdTarget.h"
21 #include "MICmnLLDBDebugSessionInfo.h"
22 #include "MICmnLLDBDebugger.h"
23 #include "MICmnMIOutOfBandRecord.h"
24 #include "MICmnMIResultRecord.h"
25 #include "MICmnMIValueConst.h"
26
27 //++
28 // Details: CMICmdCmdTargetSelect constructor.
29 // Type:    Method.
30 // Args:    None.
31 // Return:  None.
32 // Throws:  None.
33 //--
34 CMICmdCmdTargetSelect::CMICmdCmdTargetSelect()
35     : m_constStrArgNamedType("type"),
36       m_constStrArgNamedParameters("parameters") {
37   // Command factory matches this name with that received from the stdin stream
38   m_strMiCmd = "target-select";
39
40   // Required by the CMICmdFactory when registering *this command
41   m_pSelfCreatorFn = &CMICmdCmdTargetSelect::CreateSelf;
42 }
43
44 //++
45 // Details: CMICmdCmdTargetSelect destructor.
46 // Type:    Overrideable.
47 // Args:    None.
48 // Return:  None.
49 // Throws:  None.
50 //--
51 CMICmdCmdTargetSelect::~CMICmdCmdTargetSelect() = default;
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 CMICmdCmdTargetSelect::ParseArgs() {
64   m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgNamedType, true, true));
65   m_setCmdArgs.Add(
66       new CMICmdArgValString(m_constStrArgNamedParameters, true, true));
67   return ParseValidateCmdOptions();
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 //          Synopsis: -target-select type parameters ...
76 //          Ref:
77 //          http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Target-Manipulation.html#GDB_002fMI-Target-Manipulation
78 // Type:    Overridden.
79 // Args:    None.
80 // Return:  MIstatus::success - Functional succeeded.
81 //          MIstatus::failure - Functional failed.
82 // Throws:  None.
83 //--
84 bool CMICmdCmdTargetSelect::Execute() {
85   CMICMDBASE_GETOPTION(pArgType, String, m_constStrArgNamedType);
86   CMICMDBASE_GETOPTION(pArgParameters, String, m_constStrArgNamedParameters);
87
88   CMICmnLLDBDebugSessionInfo &rSessionInfo(
89       CMICmnLLDBDebugSessionInfo::Instance());
90   lldb::SBTarget target = rSessionInfo.GetTarget();
91
92   // Check we have a valid target.
93   // Note: target created via 'file-exec-and-symbols' command.
94   if (!target.IsValid()) {
95     SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_TARGET_CURRENT),
96                                    m_cmdData.strMiCmd.c_str()));
97     return MIstatus::failure;
98   }
99
100   // Verify that we are executing remotely.
101   const CMIUtilString &rRemoteType(pArgType->GetValue());
102   if (rRemoteType != "remote") {
103     SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_TARGET_TYPE),
104                                    m_cmdData.strMiCmd.c_str(),
105                                    rRemoteType.c_str()));
106     return MIstatus::failure;
107   }
108
109   // Create a URL pointing to the remote gdb stub.
110   const CMIUtilString strUrl =
111       CMIUtilString::Format("connect://%s", pArgParameters->GetValue().c_str());
112
113   lldb::SBError error;
114   // Ask LLDB to connect to the target port.
115   const char *pPlugin("gdb-remote");
116   lldb::SBProcess process = target.ConnectRemote(
117       rSessionInfo.GetListener(), strUrl.c_str(), pPlugin, error);
118
119   // Verify that we have managed to connect successfully.
120   if (!process.IsValid()) {
121     SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_TARGET_PLUGIN),
122                                    m_cmdData.strMiCmd.c_str(),
123                                    error.GetCString()));
124     return MIstatus::failure;
125   }
126
127   // Set the environment path if we were given one.
128   CMIUtilString strWkDir;
129   if (rSessionInfo.SharedDataRetrieve<CMIUtilString>(
130           rSessionInfo.m_constStrSharedDataKeyWkDir, strWkDir)) {
131     lldb::SBDebugger &rDbgr = rSessionInfo.GetDebugger();
132     if (!rDbgr.SetCurrentPlatformSDKRoot(strWkDir.c_str())) {
133       SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_FNFAILED),
134                                      m_cmdData.strMiCmd.c_str(),
135                                      "target-select"));
136       return MIstatus::failure;
137     }
138   }
139
140   // Set the shared object path if we were given one.
141   CMIUtilString strSolibPath;
142   if (rSessionInfo.SharedDataRetrieve<CMIUtilString>(
143           rSessionInfo.m_constStrSharedDataSolibPath, strSolibPath))
144     target.AppendImageSearchPath(".", strSolibPath.c_str(), error);
145
146   return HandleSBError(error);
147 }
148
149 //++
150 // Details: The invoker requires this function. The command prepares a MI Record
151 // Result
152 //          for the work carried out in the Execute().
153 // Type:    Overridden.
154 // Args:    None.
155 // Return:  MIstatus::success - Functional succeeded.
156 //          MIstatus::failure - Functional failed.
157 // Throws:  None.
158 //--
159 bool CMICmdCmdTargetSelect::Acknowledge() {
160   const CMICmnMIResultRecord miRecordResult(
161       m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Connected);
162   m_miResultRecord = miRecordResult;
163
164   CMICmnLLDBDebugSessionInfo &rSessionInfo(
165       CMICmnLLDBDebugSessionInfo::Instance());
166   lldb::pid_t pid = rSessionInfo.GetProcess().GetProcessID();
167   // Prod the client i.e. Eclipse with out-of-band results to help it 'continue'
168   // because it is using LLDB debugger
169   // Give the client '=thread-group-started,id="i1"'
170   m_bHasResultRecordExtra = true;
171   const CMICmnMIValueConst miValueConst2("i1");
172   const CMICmnMIValueResult miValueResult2("id", miValueConst2);
173   const CMIUtilString strPid(CMIUtilString::Format("%lld", pid));
174   const CMICmnMIValueConst miValueConst(strPid);
175   const CMICmnMIValueResult miValueResult("pid", miValueConst);
176   CMICmnMIOutOfBandRecord miOutOfBand(
177       CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupStarted, miValueResult2);
178   miOutOfBand.Add(miValueResult);
179   m_miResultRecordExtra = miOutOfBand.GetString();
180
181   return MIstatus::success;
182 }
183
184 //++
185 // Details: Required by the CMICmdFactory when registering *this command. The
186 // factory
187 //          calls this function to create an instance of *this command.
188 // Type:    Static method.
189 // Args:    None.
190 // Return:  CMICmdBase * - Pointer to a new command.
191 // Throws:  None.
192 //--
193 CMICmdBase *CMICmdCmdTargetSelect::CreateSelf() {
194   return new CMICmdCmdTargetSelect();
195 }
196
197 //++
198 // Details: CMICmdCmdTargetAttach constructor.
199 // Type:    Method.
200 // Args:    None.
201 // Return:  None.
202 // Throws:  None.
203 //--
204 CMICmdCmdTargetAttach::CMICmdCmdTargetAttach()
205     : m_constStrArgPid("pid"), m_constStrArgNamedFile("n"),
206       m_constStrArgWaitFor("waitfor") {
207   // Command factory matches this name with that received from the stdin stream
208   m_strMiCmd = "target-attach";
209
210   // Required by the CMICmdFactory when registering *this command
211   m_pSelfCreatorFn = &CMICmdCmdTargetAttach::CreateSelf;
212 }
213
214 //++
215 // Details: CMICmdCmdTargetAttach destructor.
216 // Type:    Overrideable.
217 // Args:    None.
218 // Return:  None.
219 // Throws:  None.
220 //--
221 CMICmdCmdTargetAttach::~CMICmdCmdTargetAttach() {}
222
223 //++
224 // Details: The invoker requires this function. The parses the command line
225 // options
226 //          arguments to extract values for each of those arguments.
227 // Type:    Overridden.
228 // Args:    None.
229 // Return:  MIstatus::success - Functional succeeded.
230 //          MIstatus::failure - Functional failed.
231 // Throws:  None.
232 //--
233 bool CMICmdCmdTargetAttach::ParseArgs() {
234   m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgPid, false, true));
235   m_setCmdArgs.Add(
236       new CMICmdArgValOptionShort(m_constStrArgNamedFile, false, true,
237                                   CMICmdArgValListBase::eArgValType_String, 1));
238   m_setCmdArgs.Add(
239       new CMICmdArgValOptionLong(m_constStrArgWaitFor, false, true));
240   return ParseValidateCmdOptions();
241 }
242
243 //++
244 // Details: The invoker requires this function. The command does work in this
245 // function.
246 //          The command is likely to communicate with the LLDB SBDebugger in
247 //          here.
248 //          Synopsis: -target-attach file
249 //          Ref:
250 //          http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Target-Manipulation.html#GDB_002fMI-Target-Manipulation
251 // Type:    Overridden.
252 // Args:    None.
253 // Return:  MIstatus::success - Functional succeeded.
254 //          MIstatus::failure - Functional failed.
255 // Throws:  None.
256 //--
257 bool CMICmdCmdTargetAttach::Execute() {
258   CMICMDBASE_GETOPTION(pArgPid, Number, m_constStrArgPid);
259   CMICMDBASE_GETOPTION(pArgFile, OptionShort, m_constStrArgNamedFile);
260   CMICMDBASE_GETOPTION(pArgWaitFor, OptionLong, m_constStrArgWaitFor);
261
262   CMICmnLLDBDebugSessionInfo &rSessionInfo(
263       CMICmnLLDBDebugSessionInfo::Instance());
264
265   // If the current target is invalid, create one
266   lldb::SBTarget target = rSessionInfo.GetTarget();
267   if (!target.IsValid()) {
268     target = rSessionInfo.GetDebugger().CreateTarget(nullptr);
269     if (!target.IsValid()) {
270       SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_TARGET_CURRENT),
271                                      m_cmdData.strMiCmd.c_str()));
272       return MIstatus::failure;
273     }
274   }
275
276   lldb::SBError error;
277   lldb::SBListener listener;
278   if (pArgPid->GetFound() && pArgPid->GetValid()) {
279     lldb::pid_t pid;
280     pid = pArgPid->GetValue();
281     target.AttachToProcessWithID(listener, pid, error);
282   } else if (pArgFile->GetFound() && pArgFile->GetValid()) {
283     bool bWaitFor = (pArgWaitFor->GetFound());
284     CMIUtilString file;
285     pArgFile->GetExpectedOption<CMICmdArgValString>(file);
286     target.AttachToProcessWithName(listener, file.c_str(), bWaitFor, error);
287   } else {
288     SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_ATTACH_BAD_ARGS),
289                                    m_cmdData.strMiCmd.c_str()));
290     return MIstatus::failure;
291   }
292
293   lldb::SBStream errMsg;
294   if (error.Fail()) {
295     SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_ATTACH_FAILED),
296                                    m_cmdData.strMiCmd.c_str(),
297                                    errMsg.GetData()));
298     return MIstatus::failure;
299   }
300
301   return MIstatus::success;
302 }
303
304 //++
305 // Details: The invoker requires this function. The command prepares a MI Record
306 // Result
307 //          for the work carried out in the Execute().
308 // Type:    Overridden.
309 // Args:    None.
310 // Return:  MIstatus::success - Functional succeeded.
311 //          MIstatus::failure - Functional failed.
312 // Throws:  None.
313 //--
314 bool CMICmdCmdTargetAttach::Acknowledge() {
315   const CMICmnMIResultRecord miRecordResult(
316       m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done);
317   m_miResultRecord = miRecordResult;
318
319   CMICmnLLDBDebugSessionInfo &rSessionInfo(
320       CMICmnLLDBDebugSessionInfo::Instance());
321   lldb::pid_t pid = rSessionInfo.GetProcess().GetProcessID();
322   // Prod the client i.e. Eclipse with out-of-band results to help it 'continue'
323   // because it is using LLDB debugger
324   // Give the client '=thread-group-started,id="i1"'
325   m_bHasResultRecordExtra = true;
326   const CMICmnMIValueConst miValueConst2("i1");
327   const CMICmnMIValueResult miValueResult2("id", miValueConst2);
328   const CMIUtilString strPid(CMIUtilString::Format("%lld", pid));
329   const CMICmnMIValueConst miValueConst(strPid);
330   const CMICmnMIValueResult miValueResult("pid", miValueConst);
331   CMICmnMIOutOfBandRecord miOutOfBand(
332       CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupStarted, miValueResult2);
333   miOutOfBand.Add(miValueResult);
334   m_miResultRecordExtra = miOutOfBand.GetString();
335
336   return MIstatus::success;
337 }
338
339 //++
340 // Details: Required by the CMICmdFactory when registering *this command. The
341 // factory
342 //          calls this function to create an instance of *this command.
343 // Type:    Static method.
344 // Args:    None.
345 // Return:  CMICmdBase * - Pointer to a new command.
346 // Throws:  None.
347 //--
348 CMICmdBase *CMICmdCmdTargetAttach::CreateSelf() {
349   return new CMICmdCmdTargetAttach();
350 }
351
352 //++
353 // Details: CMICmdCmdTargetDetach constructor.
354 // Type:    Method.
355 // Args:    None.
356 // Return:  None.
357 // Throws:  None.
358 //--
359 CMICmdCmdTargetDetach::CMICmdCmdTargetDetach() {
360   // Command factory matches this name with that received from the stdin stream
361   m_strMiCmd = "target-detach";
362
363   // Required by the CMICmdFactory when registering *this command
364   m_pSelfCreatorFn = &CMICmdCmdTargetDetach::CreateSelf;
365 }
366
367 //++
368 // Details: CMICmdCmdTargetDetach destructor.
369 // Type:    Overrideable.
370 // Args:    None.
371 // Return:  None.
372 // Throws:  None.
373 //--
374 CMICmdCmdTargetDetach::~CMICmdCmdTargetDetach() {}
375
376 //++
377 // Details: The invoker requires this function. The parses the command line
378 // options
379 //          arguments to extract values for each of those arguments.
380 // Type:    Overridden.
381 // Args:    None.
382 // Return:  MIstatus::success - Functional succeeded.
383 //          MIstatus::failure - Functional failed.
384 // Throws:  None.
385 //--
386 bool CMICmdCmdTargetDetach::ParseArgs() { return MIstatus::success; }
387
388 //++
389 // Details: The invoker requires this function. The command does work in this
390 // function.
391 //          The command is likely to communicate with the LLDB SBDebugger in
392 //          here.
393 //          Synopsis: -target-attach file
394 //          Ref:
395 //          http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Target-Manipulation.html#GDB_002fMI-Target-Manipulation
396 // Type:    Overridden.
397 // Args:    None.
398 // Return:  MIstatus::success - Functional succeeded.
399 //          MIstatus::failure - Functional failed.
400 // Throws:  None.
401 //--
402 bool CMICmdCmdTargetDetach::Execute() {
403   CMICmnLLDBDebugSessionInfo &rSessionInfo(
404       CMICmnLLDBDebugSessionInfo::Instance());
405
406   lldb::SBProcess process = rSessionInfo.GetProcess();
407
408   if (!process.IsValid()) {
409     SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_PROCESS),
410                                    m_cmdData.strMiCmd.c_str()));
411     return MIstatus::failure;
412   }
413
414   process.Detach();
415
416   return MIstatus::success;
417 }
418
419 //++
420 // Details: The invoker requires this function. The command prepares a MI Record
421 // Result
422 //          for the work carried out in the Execute().
423 // Type:    Overridden.
424 // Args:    None.
425 // Return:  MIstatus::success - Functional succeeded.
426 //          MIstatus::failure - Functional failed.
427 // Throws:  None.
428 //--
429 bool CMICmdCmdTargetDetach::Acknowledge() {
430   const CMICmnMIResultRecord miRecordResult(
431       m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done);
432   m_miResultRecord = miRecordResult;
433   return MIstatus::success;
434 }
435
436 //++
437 // Details: Required by the CMICmdFactory when registering *this command. The
438 // factory
439 //          calls this function to create an instance of *this command.
440 // Type:    Static method.
441 // Args:    None.
442 // Return:  CMICmdBase * - Pointer to a new command.
443 // Throws:  None.
444 //--
445 CMICmdBase *CMICmdCmdTargetDetach::CreateSelf() {
446   return new CMICmdCmdTargetDetach();
447 }