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