1 //===-- MICmdCmdMiscellanous.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: CMICmdCmdGdbExit implementation.
11 // CMICmdCmdListThreadGroups implementation.
12 // CMICmdCmdInterpreterExec implementation.
13 // CMICmdCmdInferiorTtySet implementation.
15 // Third Party Headers:
16 #include "lldb/API/SBCommandInterpreter.h"
17 #include "lldb/API/SBThread.h"
20 #include "MICmdArgValFile.h"
21 #include "MICmdArgValListOfN.h"
22 #include "MICmdArgValNumber.h"
23 #include "MICmdArgValOptionLong.h"
24 #include "MICmdArgValOptionShort.h"
25 #include "MICmdArgValString.h"
26 #include "MICmdArgValThreadGrp.h"
27 #include "MICmdCmdMiscellanous.h"
28 #include "MICmnLLDBDebugSessionInfo.h"
29 #include "MICmnLLDBDebugger.h"
30 #include "MICmnMIOutOfBandRecord.h"
31 #include "MICmnMIResultRecord.h"
32 #include "MICmnMIValueConst.h"
33 #include "MICmnStreamStderr.h"
34 #include "MICmnStreamStdout.h"
35 #include "MIDriverBase.h"
38 //------------------------------------------------------------------------------------
39 // Details: CMICmdCmdGdbExit constructor.
45 CMICmdCmdGdbExit::CMICmdCmdGdbExit() {
46 // Command factory matches this name with that received from the stdin stream
47 m_strMiCmd = "gdb-exit";
49 // Required by the CMICmdFactory when registering *this command
50 m_pSelfCreatorFn = &CMICmdCmdGdbExit::CreateSelf;
54 //------------------------------------------------------------------------------------
55 // Details: CMICmdCmdGdbExit destructor.
56 // Type: Overrideable.
61 CMICmdCmdGdbExit::~CMICmdCmdGdbExit() {}
64 //------------------------------------------------------------------------------------
65 // Details: The invoker requires this function. The command does work in this
67 // The command is likely to communicate with the LLDB SBDebugger in
71 // Return: MIstatus::success - Functional succeeded.
72 // MIstatus::failure - Functional failed.
75 bool CMICmdCmdGdbExit::Execute() {
76 CMICmnLLDBDebugger::Instance().GetDriver().SetExitApplicationFlag(true);
77 const lldb::SBError sbErr = m_rLLDBDebugSessionInfo.GetProcess().Destroy();
78 // Do not check for sbErr.Fail() here, m_lldbProcess is likely !IsValid()
80 return MIstatus::success;
84 //------------------------------------------------------------------------------------
85 // Details: The invoker requires this function. The command prepares a MI Record
87 // for the work carried out in the Execute().
90 // Return: MIstatus::success - Functional succeeded.
91 // MIstatus::failure - Functional failed.
94 bool CMICmdCmdGdbExit::Acknowledge() {
95 const CMICmnMIResultRecord miRecordResult(
96 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Exit);
97 m_miResultRecord = miRecordResult;
99 // Prod the client i.e. Eclipse with out-of-band results to help it 'continue'
100 // because it is using LLDB debugger
101 // Give the client '=thread-group-exited,id="i1"'
102 m_bHasResultRecordExtra = true;
103 const CMICmnMIValueConst miValueConst2("i1");
104 const CMICmnMIValueResult miValueResult2("id", miValueConst2);
105 const CMICmnMIOutOfBandRecord miOutOfBand(
106 CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupExited, miValueResult2);
107 m_miResultRecordExtra = miOutOfBand.GetString();
109 return MIstatus::success;
113 //------------------------------------------------------------------------------------
114 // Details: Required by the CMICmdFactory when registering *this command. The
116 // calls this function to create an instance of *this command.
117 // Type: Static method.
119 // Return: CMICmdBase * - Pointer to a new command.
122 CMICmdBase *CMICmdCmdGdbExit::CreateSelf() { return new CMICmdCmdGdbExit(); }
124 //---------------------------------------------------------------------------------------
125 //---------------------------------------------------------------------------------------
126 //---------------------------------------------------------------------------------------
129 //------------------------------------------------------------------------------------
130 // Details: CMICmdCmdListThreadGroups constructor.
136 CMICmdCmdListThreadGroups::CMICmdCmdListThreadGroups()
137 : m_bIsI1(false), m_bHaveArgOption(false), m_bHaveArgRecurse(false),
138 m_constStrArgNamedAvailable("available"),
139 m_constStrArgNamedRecurse("recurse"), m_constStrArgNamedGroup("group"),
140 m_constStrArgNamedThreadGroup("i1") {
141 // Command factory matches this name with that received from the stdin stream
142 m_strMiCmd = "list-thread-groups";
144 // Required by the CMICmdFactory when registering *this command
145 m_pSelfCreatorFn = &CMICmdCmdListThreadGroups::CreateSelf;
149 //------------------------------------------------------------------------------------
150 // Details: CMICmdCmdListThreadGroups destructor.
151 // Type: Overrideable.
156 CMICmdCmdListThreadGroups::~CMICmdCmdListThreadGroups() {
157 m_vecMIValueTuple.clear();
161 //------------------------------------------------------------------------------------
162 // Details: The invoker requires this function. The parses the command line
164 // arguments to extract values for each of those arguments.
167 // Return: MIstatus::success - Functional succeeded.
168 // MIstatus::failure - Functional failed.
171 bool CMICmdCmdListThreadGroups::ParseArgs() {
173 new CMICmdArgValOptionLong(m_constStrArgNamedAvailable, false, true));
175 new CMICmdArgValOptionLong(m_constStrArgNamedRecurse, false, true,
176 CMICmdArgValListBase::eArgValType_Number, 1));
178 new CMICmdArgValListOfN(m_constStrArgNamedGroup, false, true,
179 CMICmdArgValListBase::eArgValType_Number));
181 new CMICmdArgValThreadGrp(m_constStrArgNamedThreadGroup, false, true));
182 return ParseValidateCmdOptions();
186 //------------------------------------------------------------------------------------
187 // Details: The invoker requires this function. The command does work in this
189 // The command is likely to communicate with the LLDB SBDebugger in
191 // Synopsis: -list-thread-groups [ --available ] [ --recurse 1 ] [
193 // This command does not follow the MI documentation exactly. Has an
195 // argument "i1" to handle.
197 // http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Miscellaneous-Commands.html#GDB_002fMI-Miscellaneous-Commands
200 // Return: MIstatus::success - Functional succeeded.
201 // MIstatus::failure - Functional failed.
204 bool CMICmdCmdListThreadGroups::Execute() {
205 if (m_setCmdArgs.IsArgContextEmpty())
206 // No options so "top level thread groups"
207 return MIstatus::success;
209 CMICMDBASE_GETOPTION(pArgAvailable, OptionLong, m_constStrArgNamedAvailable);
210 CMICMDBASE_GETOPTION(pArgRecurse, OptionLong, m_constStrArgNamedRecurse);
211 CMICMDBASE_GETOPTION(pArgThreadGroup, ThreadGrp,
212 m_constStrArgNamedThreadGroup);
214 // Got some options so "threads"
215 if (pArgAvailable->GetFound()) {
216 if (pArgRecurse->GetFound()) {
217 m_bHaveArgRecurse = true;
218 return MIstatus::success;
221 m_bHaveArgOption = true;
222 return MIstatus::success;
224 // "i1" as first argument (pos 0 of possible arg)
225 if (!pArgThreadGroup->GetFound())
226 return MIstatus::success;
229 CMICmnLLDBDebugSessionInfo &rSessionInfo(
230 CMICmnLLDBDebugSessionInfo::Instance());
231 lldb::SBProcess sbProcess = rSessionInfo.GetProcess();
233 // Note do not check for sbProcess is IsValid(), continue
235 m_vecMIValueTuple.clear();
236 const MIuint nThreads = sbProcess.GetNumThreads();
237 for (MIuint i = 0; i < nThreads; i++) {
238 // GetThreadAtIndex() uses a base 0 index
239 // GetThreadByIndexID() uses a base 1 index
240 lldb::SBThread thread = sbProcess.GetThreadAtIndex(i);
242 if (thread.IsValid()) {
243 CMICmnMIValueTuple miTuple;
244 if (!rSessionInfo.MIResponseFormThreadInfo(
246 CMICmnLLDBDebugSessionInfo::eThreadInfoFormat_NoFrames, miTuple))
247 return MIstatus::failure;
249 m_vecMIValueTuple.push_back(miTuple);
253 return MIstatus::success;
257 //------------------------------------------------------------------------------------
258 // Details: The invoker requires this function. The command prepares a MI Record
260 // for the work carried out in the Execute().
263 // Return: MIstatus::success - Functional succeeded.
264 // MIstatus::failure - Functional failed.
267 bool CMICmdCmdListThreadGroups::Acknowledge() {
268 if (m_bHaveArgOption) {
269 if (m_bHaveArgRecurse) {
270 const CMICmnMIValueConst miValueConst(
271 MIRSRC(IDS_WORD_NOT_IMPLEMENTED_BRKTS));
272 const CMICmnMIValueResult miValueResult("msg", miValueConst);
273 const CMICmnMIResultRecord miRecordResult(
274 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error,
276 m_miResultRecord = miRecordResult;
278 return MIstatus::success;
281 const CMICmnMIValueConst miValueConst1("i1");
282 const CMICmnMIValueResult miValueResult1("id", miValueConst1);
283 CMICmnMIValueTuple miTuple(miValueResult1);
285 const CMICmnMIValueConst miValueConst2("process");
286 const CMICmnMIValueResult miValueResult2("type", miValueConst2);
287 miTuple.Add(miValueResult2);
289 CMICmnLLDBDebugSessionInfo &rSessionInfo(
290 CMICmnLLDBDebugSessionInfo::Instance());
291 if (rSessionInfo.GetProcess().IsValid()) {
292 const lldb::pid_t pid = rSessionInfo.GetProcess().GetProcessID();
293 const CMIUtilString strPid(CMIUtilString::Format("%lld", pid));
294 const CMICmnMIValueConst miValueConst3(strPid);
295 const CMICmnMIValueResult miValueResult3("pid", miValueConst3);
296 miTuple.Add(miValueResult3);
299 const CMICmnMIValueConst miValueConst4(
300 MIRSRC(IDS_WORD_NOT_IMPLEMENTED_BRKTS));
301 const CMICmnMIValueResult miValueResult4("num_children", miValueConst4);
302 miTuple.Add(miValueResult4);
304 const CMICmnMIValueConst miValueConst5(
305 MIRSRC(IDS_WORD_NOT_IMPLEMENTED_BRKTS));
306 const CMICmnMIValueResult miValueResult5("cores", miValueConst5);
307 miTuple.Add(miValueResult5);
309 const CMICmnMIValueList miValueList(miTuple);
310 const CMICmnMIValueResult miValueResult6("groups", miValueList);
311 const CMICmnMIResultRecord miRecordResult(
312 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done,
314 m_miResultRecord = miRecordResult;
316 return MIstatus::success;
320 const CMICmnMIValueConst miValueConst1("i1");
321 const CMICmnMIValueResult miValueResult1("id", miValueConst1);
322 CMICmnMIValueTuple miTuple(miValueResult1);
324 const CMICmnMIValueConst miValueConst2("process");
325 const CMICmnMIValueResult miValueResult2("type", miValueConst2);
326 miTuple.Add(miValueResult2);
328 CMICmnLLDBDebugSessionInfo &rSessionInfo(
329 CMICmnLLDBDebugSessionInfo::Instance());
330 if (rSessionInfo.GetProcess().IsValid()) {
331 const lldb::pid_t pid = rSessionInfo.GetProcess().GetProcessID();
332 const CMIUtilString strPid(CMIUtilString::Format("%lld", pid));
333 const CMICmnMIValueConst miValueConst3(strPid);
334 const CMICmnMIValueResult miValueResult3("pid", miValueConst3);
335 miTuple.Add(miValueResult3);
338 if (rSessionInfo.GetTarget().IsValid()) {
339 lldb::SBTarget sbTrgt = rSessionInfo.GetTarget();
340 const char *pDir = sbTrgt.GetExecutable().GetDirectory();
341 const char *pFileName = sbTrgt.GetExecutable().GetFilename();
342 const CMIUtilString strFile(
343 CMIUtilString::Format("%s/%s", pDir, pFileName));
344 const CMICmnMIValueConst miValueConst4(strFile);
345 const CMICmnMIValueResult miValueResult4("executable", miValueConst4);
346 miTuple.Add(miValueResult4);
349 const CMICmnMIValueList miValueList(miTuple);
350 const CMICmnMIValueResult miValueResult5("groups", miValueList);
351 const CMICmnMIResultRecord miRecordResult(
352 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done,
354 m_miResultRecord = miRecordResult;
355 return MIstatus::success;
358 // Build up a list of thread information from tuples
359 VecMIValueTuple_t::const_iterator it = m_vecMIValueTuple.begin();
360 if (it == m_vecMIValueTuple.end()) {
361 const CMICmnMIValueConst miValueConst("[]");
362 const CMICmnMIValueResult miValueResult("threads", miValueConst);
363 const CMICmnMIResultRecord miRecordResult(
364 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done,
366 m_miResultRecord = miRecordResult;
367 return MIstatus::success;
369 CMICmnMIValueList miValueList(*it);
371 while (it != m_vecMIValueTuple.end()) {
372 const CMICmnMIValueTuple &rTuple(*it);
373 miValueList.Add(rTuple);
379 const CMICmnMIValueResult miValueResult("threads", miValueList);
380 const CMICmnMIResultRecord miRecordResult(
381 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done,
383 m_miResultRecord = miRecordResult;
385 return MIstatus::success;
389 //------------------------------------------------------------------------------------
390 // Details: Required by the CMICmdFactory when registering *this command. The
392 // calls this function to create an instance of *this command.
393 // Type: Static method.
395 // Return: CMICmdBase * - Pointer to a new command.
398 CMICmdBase *CMICmdCmdListThreadGroups::CreateSelf() {
399 return new CMICmdCmdListThreadGroups();
402 //---------------------------------------------------------------------------------------
403 //---------------------------------------------------------------------------------------
404 //---------------------------------------------------------------------------------------
407 //------------------------------------------------------------------------------------
408 // Details: CMICmdCmdInterpreterExec constructor.
414 CMICmdCmdInterpreterExec::CMICmdCmdInterpreterExec()
415 : m_constStrArgNamedInterpreter("interpreter"),
416 m_constStrArgNamedCommand("command") {
417 // Command factory matches this name with that received from the stdin stream
418 m_strMiCmd = "interpreter-exec";
420 // Required by the CMICmdFactory when registering *this command
421 m_pSelfCreatorFn = &CMICmdCmdInterpreterExec::CreateSelf;
425 //------------------------------------------------------------------------------------
426 // Details: CMICmdCmdInterpreterExec destructor.
427 // Type: Overrideable.
432 CMICmdCmdInterpreterExec::~CMICmdCmdInterpreterExec() {}
435 //------------------------------------------------------------------------------------
436 // Details: The invoker requires this function. The parses the command line
438 // arguments to extract values for each of those arguments.
441 // Return: MIstatus::success - Functional succeeded.
442 // MIstatus::failure - Functional failed.
445 bool CMICmdCmdInterpreterExec::ParseArgs() {
447 new CMICmdArgValString(m_constStrArgNamedInterpreter, true, true));
449 new CMICmdArgValString(m_constStrArgNamedCommand, true, true, true));
450 return ParseValidateCmdOptions();
454 //------------------------------------------------------------------------------------
455 // Details: The invoker requires this function. The command does work in this
457 // The command is likely to communicate with the LLDB SBDebugger in
461 // Return: MIstatus::success - Functional succeeded.
462 // MIstatus::failure - Functional failed.
465 bool CMICmdCmdInterpreterExec::Execute() {
466 CMICMDBASE_GETOPTION(pArgInterpreter, String, m_constStrArgNamedInterpreter);
467 CMICMDBASE_GETOPTION(pArgCommand, String, m_constStrArgNamedCommand);
469 // Handle the interpreter parameter by do nothing on purpose (set to 'handled'
471 // the arg definition above)
472 const CMIUtilString &rStrInterpreter(pArgInterpreter->GetValue());
473 MIunused(rStrInterpreter);
475 const CMIUtilString &rStrCommand(pArgCommand->GetValue());
476 CMICmnLLDBDebugSessionInfo &rSessionInfo(
477 CMICmnLLDBDebugSessionInfo::Instance());
478 const lldb::ReturnStatus rtn =
479 rSessionInfo.GetDebugger().GetCommandInterpreter().HandleCommand(
480 rStrCommand.c_str(), m_lldbResult, true);
483 return MIstatus::success;
487 //------------------------------------------------------------------------------------
488 // Details: The invoker requires this function. The command prepares a MI Record
490 // for the work carried out in the Execute().
493 // Return: MIstatus::success - Functional succeeded.
494 // MIstatus::failure - Functional failed.
497 bool CMICmdCmdInterpreterExec::Acknowledge() {
498 if (m_lldbResult.GetOutputSize() > 0) {
499 const CMIUtilString line(m_lldbResult.GetOutput());
500 const bool bEscapeQuotes(true);
501 CMICmnMIValueConst miValueConst(line.Escape(bEscapeQuotes));
502 CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_ConsoleStreamOutput, miValueConst);
503 const bool bOk = CMICmnStreamStdout::TextToStdout(miOutOfBandRecord.GetString());
505 return MIstatus::failure;
507 if (m_lldbResult.GetErrorSize() > 0) {
508 const CMIUtilString line(m_lldbResult.GetError());
509 const bool bEscapeQuotes(true);
510 CMICmnMIValueConst miValueConst(line.Escape(bEscapeQuotes));
511 CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_LogStreamOutput, miValueConst);
512 const bool bOk = CMICmnStreamStdout::TextToStdout(miOutOfBandRecord.GetString());
514 return MIstatus::failure;
517 const CMICmnMIResultRecord miRecordResult(
518 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done);
519 m_miResultRecord = miRecordResult;
521 return MIstatus::success;
525 //------------------------------------------------------------------------------------
526 // Details: Required by the CMICmdFactory when registering *this command. The
528 // calls this function to create an instance of *this command.
529 // Type: Static method.
531 // Return: CMICmdBase * - Pointer to a new command.
534 CMICmdBase *CMICmdCmdInterpreterExec::CreateSelf() {
535 return new CMICmdCmdInterpreterExec();
538 //---------------------------------------------------------------------------------------
539 //---------------------------------------------------------------------------------------
540 //---------------------------------------------------------------------------------------
543 //------------------------------------------------------------------------------------
544 // Details: CMICmdCmdInferiorTtySet constructor.
550 CMICmdCmdInferiorTtySet::CMICmdCmdInferiorTtySet() {
551 // Command factory matches this name with that received from the stdin stream
552 m_strMiCmd = "inferior-tty-set";
554 // Required by the CMICmdFactory when registering *this command
555 m_pSelfCreatorFn = &CMICmdCmdInferiorTtySet::CreateSelf;
559 //------------------------------------------------------------------------------------
560 // Details: CMICmdCmdInferiorTtySet destructor.
561 // Type: Overrideable.
566 CMICmdCmdInferiorTtySet::~CMICmdCmdInferiorTtySet() {}
569 //------------------------------------------------------------------------------------
570 // Details: The invoker requires this function. The command does work in this
572 // The command is likely to communicate with the LLDB SBDebugger in
576 // Return: MIstatus::success - Functional succeeded.
577 // MIstatus::failure - Functional failed.
580 bool CMICmdCmdInferiorTtySet::Execute() {
583 return MIstatus::success;
587 //------------------------------------------------------------------------------------
588 // Details: The invoker requires this function. The command prepares a MI Record
590 // for the work carried out in the Execute().
593 // Return: MIstatus::success - Functional succeeded.
594 // MIstatus::failure - Functional failed.
597 bool CMICmdCmdInferiorTtySet::Acknowledge() {
598 const CMICmnMIResultRecord miRecordResult(
599 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error);
600 m_miResultRecord = miRecordResult;
602 return MIstatus::success;
606 //------------------------------------------------------------------------------------
607 // Details: Required by the CMICmdFactory when registering *this command. The
609 // calls this function to create an instance of *this command.
610 // Type: Static method.
612 // Return: CMICmdBase * - Pointer to a new command.
615 CMICmdBase *CMICmdCmdInferiorTtySet::CreateSelf() {
616 return new CMICmdCmdInferiorTtySet();