]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - tools/lldb-mi/MICmdCmdData.cpp
Vendor import of lldb release_39 branch r276489:
[FreeBSD/FreeBSD.git] / tools / lldb-mi / MICmdCmdData.cpp
1 //===-- MICmdCmdData.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:    CMICmdCmdDataEvaluateExpression     implementation.
11 //              CMICmdCmdDataDisassemble            implementation.
12 //              CMICmdCmdDataReadMemoryBytes        implementation.
13 //              CMICmdCmdDataReadMemory             implementation.
14 //              CMICmdCmdDataListRegisterNames      implementation.
15 //              CMICmdCmdDataListRegisterValues     implementation.
16 //              CMICmdCmdDataListRegisterChanged    implementation.
17 //              CMICmdCmdDataWriteMemoryBytes       implementation.
18 //              CMICmdCmdDataWriteMemory            implementation.
19 //              CMICmdCmdDataInfoLine               implementation.
20
21 // Third Party Headers:
22 #include <inttypes.h> // For PRIx64
23 #include "lldb/API/SBCommandInterpreter.h"
24 #include "lldb/API/SBThread.h"
25 #include "lldb/API/SBInstruction.h"
26 #include "lldb/API/SBInstructionList.h"
27 #include "lldb/API/SBStream.h"
28
29 // In-house headers:
30 #include "MICmdCmdData.h"
31 #include "MICmnMIResultRecord.h"
32 #include "MICmnMIValueConst.h"
33 #include "MICmnLLDBDebugger.h"
34 #include "MICmnLLDBDebugSessionInfo.h"
35 #include "MICmnLLDBProxySBValue.h"
36 #include "MICmdArgValNumber.h"
37 #include "MICmdArgValString.h"
38 #include "MICmdArgValThreadGrp.h"
39 #include "MICmdArgValOptionLong.h"
40 #include "MICmdArgValOptionShort.h"
41 #include "MICmdArgValListOfN.h"
42 #include "MICmdArgValConsume.h"
43 #include "MICmnLLDBDebugSessionInfoVarObj.h"
44 #include "MICmnLLDBUtilSBValue.h"
45 #include "MIUtilParse.h"
46
47 //++ ------------------------------------------------------------------------------------
48 // Details: CMICmdCmdDataEvaluateExpression constructor.
49 // Type:    Method.
50 // Args:    None.
51 // Return:  None.
52 // Throws:  None.
53 //--
54 CMICmdCmdDataEvaluateExpression::CMICmdCmdDataEvaluateExpression()
55     : m_bExpressionValid(true)
56     , m_bEvaluatedExpression(true)
57     , m_strValue("??")
58     , m_bFoundInvalidChar(false)
59     , m_cExpressionInvalidChar(0x00)
60     , m_constStrArgExpr("expr")
61 {
62     // Command factory matches this name with that received from the stdin stream
63     m_strMiCmd = "data-evaluate-expression";
64
65     // Required by the CMICmdFactory when registering *this command
66     m_pSelfCreatorFn = &CMICmdCmdDataEvaluateExpression::CreateSelf;
67 }
68
69 //++ ------------------------------------------------------------------------------------
70 // Details: CMICmdCmdDataEvaluateExpression destructor.
71 // Type:    Overrideable.
72 // Args:    None.
73 // Return:  None.
74 // Throws:  None.
75 //--
76 CMICmdCmdDataEvaluateExpression::~CMICmdCmdDataEvaluateExpression()
77 {
78 }
79
80 //++ ------------------------------------------------------------------------------------
81 // Details: The invoker requires this function. The parses the command line options
82 //          arguments to extract values for each of those arguments.
83 // Type:    Overridden.
84 // Args:    None.
85 // Return:  MIstatus::success - Functional succeeded.
86 //          MIstatus::failure - Functional failed.
87 // Throws:  None.
88 //--
89 bool
90 CMICmdCmdDataEvaluateExpression::ParseArgs()
91 {
92     m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgExpr, true, true, true, true));
93     return ParseValidateCmdOptions();
94 }
95
96 //++ ------------------------------------------------------------------------------------
97 // Details: The invoker requires this function. The command does work in this function.
98 //          The command is likely to communicate with the LLDB SBDebugger in here.
99 // Type:    Overridden.
100 // Args:    None.
101 // Return:  MIstatus::success - Functional succeeded.
102 //          MIstatus::failure - Functional failed.
103 // Throws:  None.
104 //--
105 bool
106 CMICmdCmdDataEvaluateExpression::Execute()
107 {
108     CMICMDBASE_GETOPTION(pArgExpr, String, m_constStrArgExpr);
109
110     const CMIUtilString &rExpression(pArgExpr->GetValue());
111     CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
112     lldb::SBProcess sbProcess = rSessionInfo.GetProcess();
113     lldb::SBThread thread = sbProcess.GetSelectedThread();
114     m_bExpressionValid = (thread.GetNumFrames() > 0);
115     if (!m_bExpressionValid)
116         return MIstatus::success;
117
118     lldb::SBFrame frame = thread.GetSelectedFrame();
119     lldb::SBValue value = frame.EvaluateExpression(rExpression.c_str());
120     m_Error = value.GetError();
121     if (!value.IsValid() || m_Error.Fail())
122         value = frame.FindVariable(rExpression.c_str());
123     const CMICmnLLDBUtilSBValue utilValue(value, true);
124     if (!utilValue.IsValid() || utilValue.IsValueUnknown())
125     {
126         m_bEvaluatedExpression = false;
127         return MIstatus::success;
128     }
129     if (!utilValue.HasName())
130     {
131         if (HaveInvalidCharacterInExpression(rExpression, m_cExpressionInvalidChar))
132         {
133             m_bFoundInvalidChar = true;
134             return MIstatus::success;
135         }
136
137         m_strValue = rExpression;
138         return MIstatus::success;
139     }
140     if (rExpression.IsQuoted())
141     {
142         m_strValue = rExpression.Trim('\"');
143         return MIstatus::success;
144     }
145     m_strValue = utilValue.GetValue(true).Escape().AddSlashes();
146     return MIstatus::success;
147 }
148
149 //++ ------------------------------------------------------------------------------------
150 // Details: The invoker requires this function. The command prepares a MI Record Result
151 //          for the work carried out in the Execute().
152 // Type:    Overridden.
153 // Args:    None.
154 // Return:  MIstatus::success - Functional succeeded.
155 //          MIstatus::failure - Functional failed.
156 // Throws:  None.
157 //--
158 bool
159 CMICmdCmdDataEvaluateExpression::Acknowledge()
160 {
161     if (m_bExpressionValid)
162     {
163         if (m_bEvaluatedExpression)
164         {
165             if (m_bFoundInvalidChar)
166             {
167                 const CMICmnMIValueConst miValueConst(
168                     CMIUtilString::Format("Invalid character '%c' in expression", m_cExpressionInvalidChar));
169                 const CMICmnMIValueResult miValueResult("msg", miValueConst);
170                 const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult);
171                 m_miResultRecord = miRecordResult;
172                 return MIstatus::success;
173             }
174
175             const CMICmnMIValueConst miValueConst(m_strValue);
176             const CMICmnMIValueResult miValueResult("value", miValueConst);
177             const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult);
178             m_miResultRecord = miRecordResult;
179             return MIstatus::success;
180         }
181         CMIUtilString mi_error_msg = "Could not evaluate expression";
182         if (const char* err_msg = m_Error.GetCString())
183             mi_error_msg = err_msg;
184         const CMICmnMIValueConst miValueConst(mi_error_msg.Escape(true));
185         const CMICmnMIValueResult miValueResult("msg", miValueConst);
186         const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult);
187         m_miResultRecord = miRecordResult;
188         return MIstatus::success;
189     }
190
191     const CMICmnMIValueConst miValueConst("Invalid expression");
192     const CMICmnMIValueResult miValueResult("msg", miValueConst);
193     const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult);
194     m_miResultRecord = miRecordResult;
195
196     return MIstatus::success;
197 }
198
199 //++ ------------------------------------------------------------------------------------
200 // Details: Required by the CMICmdFactory when registering *this command. The factory
201 //          calls this function to create an instance of *this command.
202 // Type:    Static method.
203 // Args:    None.
204 // Return:  CMICmdBase * - Pointer to a new command.
205 // Throws:  None.
206 //--
207 CMICmdBase *
208 CMICmdCmdDataEvaluateExpression::CreateSelf()
209 {
210     return new CMICmdCmdDataEvaluateExpression();
211 }
212
213 //++ ------------------------------------------------------------------------------------
214 // Details: Examine the expression string to see if it contains invalid characters.
215 // Type:    Method.
216 // Args:    vrExpr          - (R) Expression string given to *this command.
217 //          vrwInvalidChar  - (W) True = Invalid character found, false = nothing found.
218 // Return:  bool - True = Invalid character found, false = nothing found.
219 // Throws:  None.
220 //--
221 bool
222 CMICmdCmdDataEvaluateExpression::HaveInvalidCharacterInExpression(const CMIUtilString &vrExpr, char &vrwInvalidChar)
223 {
224     static const std::string strInvalidCharacters(";#\\");
225     const size_t nInvalidCharacterOffset = vrExpr.find_first_of(strInvalidCharacters);
226     const bool bFoundInvalidCharInExpression = (nInvalidCharacterOffset != CMIUtilString::npos);
227     vrwInvalidChar = bFoundInvalidCharInExpression ? vrExpr[nInvalidCharacterOffset] : 0x00;
228     return bFoundInvalidCharInExpression;
229 }
230
231 //---------------------------------------------------------------------------------------
232 //---------------------------------------------------------------------------------------
233 //---------------------------------------------------------------------------------------
234
235 //++ ------------------------------------------------------------------------------------
236 // Details: CMICmdCmdDataDisassemble constructor.
237 // Type:    Method.
238 // Args:    None.
239 // Return:  None.
240 // Throws:  None.
241 //--
242 CMICmdCmdDataDisassemble::CMICmdCmdDataDisassemble()
243     : m_constStrArgAddrStart("s")
244     , m_constStrArgAddrEnd("e")
245     , m_constStrArgMode("mode")
246     , m_miValueList(true)
247 {
248     // Command factory matches this name with that received from the stdin stream
249     m_strMiCmd = "data-disassemble";
250
251     // Required by the CMICmdFactory when registering *this command
252     m_pSelfCreatorFn = &CMICmdCmdDataDisassemble::CreateSelf;
253 }
254
255 //++ ------------------------------------------------------------------------------------
256 // Details: CMICmdCmdDataDisassemble destructor.
257 // Type:    Overrideable.
258 // Args:    None.
259 // Return:  None.
260 // Throws:  None.
261 //--
262 CMICmdCmdDataDisassemble::~CMICmdCmdDataDisassemble()
263 {
264 }
265
266 //++ ------------------------------------------------------------------------------------
267 // Details: The invoker requires this function. The parses the command line options
268 //          arguments to extract values for each of those arguments.
269 // Type:    Overridden.
270 // Args:    None.
271 // Return:  MIstatus::success - Functional succeeded.
272 //          MIstatus::failure - Functional failed.
273 // Throws:  None.
274 //--
275 bool
276 CMICmdCmdDataDisassemble::ParseArgs()
277 {
278     m_setCmdArgs.Add(
279         new CMICmdArgValOptionShort(m_constStrArgAddrStart, true, true, CMICmdArgValListBase::eArgValType_StringQuotedNumber, 1));
280     m_setCmdArgs.Add(
281         new CMICmdArgValOptionShort(m_constStrArgAddrEnd, true, true, CMICmdArgValListBase::eArgValType_StringQuotedNumber, 1));
282     m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgMode, true, true));
283     return ParseValidateCmdOptions();
284 }
285
286 //++ ------------------------------------------------------------------------------------
287 // Details: The invoker requires this function. The command does work in this function.
288 //          The command is likely to communicate with the LLDB SBDebugger in here.
289 // Type:    Overridden.
290 // Args:    None.
291 // Return:  MIstatus::success - Functional succeeded.
292 //          MIstatus::failure - Functional failed.
293 // Throws:  None.
294 //--
295 bool
296 CMICmdCmdDataDisassemble::Execute()
297 {
298     CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread);
299     CMICMDBASE_GETOPTION(pArgAddrStart, OptionShort, m_constStrArgAddrStart);
300     CMICMDBASE_GETOPTION(pArgAddrEnd, OptionShort, m_constStrArgAddrEnd);
301     CMICMDBASE_GETOPTION(pArgMode, Number, m_constStrArgMode);
302
303     // Retrieve the --thread option's thread ID (only 1)
304     MIuint64 nThreadId = UINT64_MAX;
305     if (pArgThread->GetFound() && !pArgThread->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nThreadId))
306     {
307         SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_THREAD_INVALID), m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str()));
308         return MIstatus::failure;
309     }
310     CMIUtilString strAddrStart;
311     if (!pArgAddrStart->GetExpectedOption<CMICmdArgValString, CMIUtilString>(strAddrStart))
312     {
313         SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_DISASM_ADDR_START_INVALID), m_cmdData.strMiCmd.c_str(),
314                                        m_constStrArgAddrStart.c_str()));
315         return MIstatus::failure;
316     }
317     MIint64 nAddrStart = 0;
318     if (!strAddrStart.ExtractNumber(nAddrStart))
319     {
320         SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_DISASM_ADDR_START_INVALID), m_cmdData.strMiCmd.c_str(),
321                                        m_constStrArgAddrStart.c_str()));
322         return MIstatus::failure;
323     }
324
325     CMIUtilString strAddrEnd;
326     if (!pArgAddrEnd->GetExpectedOption<CMICmdArgValString, CMIUtilString>(strAddrEnd))
327     {
328         SetError(
329             CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_DISASM_ADDR_END_INVALID), m_cmdData.strMiCmd.c_str(), m_constStrArgAddrEnd.c_str()));
330         return MIstatus::failure;
331     }
332     MIint64 nAddrEnd = 0;
333     if (!strAddrEnd.ExtractNumber(nAddrEnd))
334     {
335         SetError(
336             CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_DISASM_ADDR_END_INVALID), m_cmdData.strMiCmd.c_str(), m_constStrArgAddrEnd.c_str()));
337         return MIstatus::failure;
338     }
339     const MIuint nDisasmMode = pArgMode->GetValue();
340
341     CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
342     lldb::SBTarget sbTarget = rSessionInfo.GetTarget();
343     lldb::addr_t lldbStartAddr = static_cast<lldb::addr_t>(nAddrStart);
344     lldb::SBInstructionList instructions = sbTarget.ReadInstructions(lldb::SBAddress(lldbStartAddr, sbTarget), nAddrEnd - nAddrStart);
345     const MIuint nInstructions = instructions.GetSize();
346     // Calculate the offset of first instruction so that we can generate offset starting at 0
347     lldb::addr_t start_offset = 0;
348     if(nInstructions > 0)
349         start_offset = instructions.GetInstructionAtIndex(0).GetAddress().GetOffset();
350
351     for (size_t i = 0; i < nInstructions; i++)
352     {
353         const char *pUnknown = "??";
354         lldb::SBInstruction instrt = instructions.GetInstructionAtIndex(i);
355         const char *pStrMnemonic = instrt.GetMnemonic(sbTarget);
356         pStrMnemonic = (pStrMnemonic != nullptr) ? pStrMnemonic : pUnknown;
357         const char *pStrComment = instrt.GetComment(sbTarget);
358         CMIUtilString strComment;
359         if (pStrComment != nullptr && *pStrComment != '\0')
360             strComment = CMIUtilString::Format("; %s", pStrComment);
361         lldb::SBAddress address = instrt.GetAddress();
362         lldb::addr_t addr = address.GetLoadAddress(sbTarget);
363         const char *pFnName = address.GetFunction().GetName();
364         pFnName = (pFnName != nullptr) ? pFnName : pUnknown;
365         lldb::addr_t addrOffSet = address.GetOffset() - start_offset;
366         const char *pStrOperands = instrt.GetOperands(sbTarget);
367         pStrOperands = (pStrOperands != nullptr) ? pStrOperands : pUnknown;
368         const size_t instrtSize = instrt.GetByteSize();
369
370         // MI "{address=\"0x%016" PRIx64 "\",func-name=\"%s\",offset=\"%lld\",inst=\"%s %s\"}"
371         const CMICmnMIValueConst miValueConst(CMIUtilString::Format("0x%016" PRIx64, addr));
372         const CMICmnMIValueResult miValueResult("address", miValueConst);
373         CMICmnMIValueTuple miValueTuple(miValueResult);
374         const CMICmnMIValueConst miValueConst2(pFnName);
375         const CMICmnMIValueResult miValueResult2("func-name", miValueConst2);
376         miValueTuple.Add(miValueResult2);
377         const CMICmnMIValueConst miValueConst3(CMIUtilString::Format("%lld", addrOffSet));
378         const CMICmnMIValueResult miValueResult3("offset", miValueConst3);
379         miValueTuple.Add(miValueResult3);
380         const CMICmnMIValueConst miValueConst4(CMIUtilString::Format("%d", instrtSize));
381         const CMICmnMIValueResult miValueResult4("size", miValueConst4);
382         miValueTuple.Add(miValueResult4);
383         const CMICmnMIValueConst miValueConst5(CMIUtilString::Format("%s %s%s", pStrMnemonic, pStrOperands, strComment.Escape(true).c_str()));
384         const CMICmnMIValueResult miValueResult5("inst", miValueConst5);
385         miValueTuple.Add(miValueResult5);
386
387         if (nDisasmMode == 1)
388         {
389             lldb::SBLineEntry lineEntry = address.GetLineEntry();
390             const MIuint nLine = lineEntry.GetLine();
391             const char *pFileName = lineEntry.GetFileSpec().GetFilename();
392             pFileName = (pFileName != nullptr) ? pFileName : pUnknown;
393
394             // MI "src_and_asm_line={line=\"%u\",file=\"%s\",line_asm_insn=[ ]}"
395             const CMICmnMIValueConst miValueConst(CMIUtilString::Format("0x%u", nLine));
396             const CMICmnMIValueResult miValueResult("line", miValueConst);
397             CMICmnMIValueTuple miValueTuple2(miValueResult);
398             const CMICmnMIValueConst miValueConst2(pFileName);
399             const CMICmnMIValueResult miValueResult2("file", miValueConst2);
400             miValueTuple2.Add(miValueResult2);
401             const CMICmnMIValueList miValueList(miValueTuple);
402             const CMICmnMIValueResult miValueResult3("line_asm_insn", miValueList);
403             miValueTuple2.Add(miValueResult3);
404             const CMICmnMIValueResult miValueResult4("src_and_asm_line", miValueTuple2);
405             m_miValueList.Add(miValueResult4);
406         }
407         else
408         {
409             m_miValueList.Add(miValueTuple);
410         }
411     }
412
413     return MIstatus::success;
414 }
415
416 //++ ------------------------------------------------------------------------------------
417 // Details: The invoker requires this function. The command prepares a MI Record Result
418 //          for the work carried out in the Execute().
419 // Type:    Overridden.
420 // Args:    None.
421 // Return:  MIstatus::success - Functional succeeded.
422 //          MIstatus::failure - Functional failed.
423 // Throws:  None.
424 //--
425 bool
426 CMICmdCmdDataDisassemble::Acknowledge()
427 {
428     const CMICmnMIValueResult miValueResult("asm_insns", m_miValueList);
429     const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult);
430     m_miResultRecord = miRecordResult;
431
432     return MIstatus::success;
433 }
434
435 //++ ------------------------------------------------------------------------------------
436 // Details: Required by the CMICmdFactory when registering *this command. The factory
437 //          calls this function to create an instance of *this command.
438 // Type:    Static method.
439 // Args:    None.
440 // Return:  CMICmdBase * - Pointer to a new command.
441 // Throws:  None.
442 //--
443 CMICmdBase *
444 CMICmdCmdDataDisassemble::CreateSelf()
445 {
446     return new CMICmdCmdDataDisassemble();
447 }
448
449 //---------------------------------------------------------------------------------------
450 //---------------------------------------------------------------------------------------
451 //---------------------------------------------------------------------------------------
452
453 //++ ------------------------------------------------------------------------------------
454 // Details: CMICmdCmdDataReadMemoryBytes constructor.
455 // Type:    Method.
456 // Args:    None.
457 // Return:  None.
458 // Throws:  None.
459 //--
460 CMICmdCmdDataReadMemoryBytes::CMICmdCmdDataReadMemoryBytes()
461     : m_constStrArgByteOffset("o")
462     , m_constStrArgAddrExpr("address")
463     , m_constStrArgNumBytes("count")
464     , m_pBufferMemory(nullptr)
465     , m_nAddrStart(0)
466     , m_nAddrNumBytesToRead(0)
467 {
468     // Command factory matches this name with that received from the stdin stream
469     m_strMiCmd = "data-read-memory-bytes";
470
471     // Required by the CMICmdFactory when registering *this command
472     m_pSelfCreatorFn = &CMICmdCmdDataReadMemoryBytes::CreateSelf;
473 }
474
475 //++ ------------------------------------------------------------------------------------
476 // Details: CMICmdCmdDataReadMemoryBytes destructor.
477 // Type:    Overrideable.
478 // Args:    None.
479 // Return:  None.
480 // Throws:  None.
481 //--
482 CMICmdCmdDataReadMemoryBytes::~CMICmdCmdDataReadMemoryBytes()
483 {
484     if (m_pBufferMemory != nullptr)
485     {
486         delete[] m_pBufferMemory;
487         m_pBufferMemory = nullptr;
488     }
489 }
490
491 //++ ------------------------------------------------------------------------------------
492 // Details: The invoker requires this function. The parses the command line options
493 //          arguments to extract values for each of those arguments.
494 // Type:    Overridden.
495 // Args:    None.
496 // Return:  MIstatus::success - Functional succeeded.
497 //          MIstatus::failure - Functional failed.
498 // Throws:  None.
499 //--
500 bool
501 CMICmdCmdDataReadMemoryBytes::ParseArgs()
502 {
503     m_setCmdArgs.Add(new CMICmdArgValOptionShort(m_constStrArgByteOffset, false, true, CMICmdArgValListBase::eArgValType_Number, 1));
504     m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgAddrExpr, true, true, true, true));
505     m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgNumBytes, true, true));
506     return ParseValidateCmdOptions();
507 }
508
509 //++ ------------------------------------------------------------------------------------
510 // Details: The invoker requires this function. The command does work in this function.
511 //          The command is likely to communicate with the LLDB SBDebugger in here.
512 // Type:    Overridden.
513 // Args:    None.
514 // Return:  MIstatus::success - Function succeeded.
515 //          MIstatus::failure - Function failed.
516 // Throws:  None.
517 //--
518 bool
519 CMICmdCmdDataReadMemoryBytes::Execute()
520 {
521     CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread);
522     CMICMDBASE_GETOPTION(pArgFrame, OptionLong, m_constStrArgFrame);
523     CMICMDBASE_GETOPTION(pArgAddrOffset, OptionShort, m_constStrArgByteOffset);
524     CMICMDBASE_GETOPTION(pArgAddrExpr, String, m_constStrArgAddrExpr);
525     CMICMDBASE_GETOPTION(pArgNumBytes, Number, m_constStrArgNumBytes);
526
527     // get the --thread option value
528     MIuint64 nThreadId = UINT64_MAX;
529     if (pArgThread->GetFound() && !pArgThread->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nThreadId))
530     {
531         SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND),
532                  m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str()));
533         return MIstatus::failure;
534     }
535
536     // get the --frame option value
537     MIuint64 nFrame = UINT64_MAX;
538     if (pArgFrame->GetFound() && !pArgFrame->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nFrame))
539     {
540         SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND),
541                  m_cmdData.strMiCmd.c_str(), m_constStrArgFrame.c_str()));
542         return MIstatus::failure;
543     }
544
545     // get the -o option value
546     MIuint64 nAddrOffset = 0;
547     if (pArgAddrOffset->GetFound() && !pArgAddrOffset->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nAddrOffset))
548     {
549         SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND),
550                  m_cmdData.strMiCmd.c_str(), m_constStrArgByteOffset.c_str()));
551         return MIstatus::failure;
552     }
553
554     CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
555     lldb::SBProcess sbProcess = rSessionInfo.GetProcess();
556     if (!sbProcess.IsValid())
557     {
558         SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_PROCESS), m_cmdData.strMiCmd.c_str()));
559         return MIstatus::failure;
560     }
561
562     lldb::SBThread thread = (nThreadId != UINT64_MAX) ?
563                             sbProcess.GetThreadByIndexID(nThreadId) : sbProcess.GetSelectedThread();
564     if (!thread.IsValid())
565     {
566         SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_THREAD_INVALID), m_cmdData.strMiCmd.c_str()));
567         return MIstatus::failure;
568     }
569
570     lldb::SBFrame frame = (nFrame != UINT64_MAX) ?
571                           thread.GetFrameAtIndex(nFrame) : thread.GetSelectedFrame();
572     if (!frame.IsValid())
573     {
574         SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_FRAME_INVALID), m_cmdData.strMiCmd.c_str()));
575         return MIstatus::failure;
576     }
577
578     const CMIUtilString &rAddrExpr = pArgAddrExpr->GetValue();
579     lldb::SBValue addrExprValue = frame.EvaluateExpression(rAddrExpr.c_str());
580     lldb::SBError error = addrExprValue.GetError();
581     if (error.Fail())
582     {
583         SetError(error.GetCString());
584         return MIstatus::failure;
585     }
586     else if (!addrExprValue.IsValid())
587     {
588         SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_EXPR_INVALID), rAddrExpr.c_str()));
589         return MIstatus::failure;
590     }
591
592     MIuint64 nAddrStart = 0;
593     if (!CMICmnLLDBProxySBValue::GetValueAsUnsigned(addrExprValue, nAddrStart))
594     {
595         SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_EXPR_INVALID), rAddrExpr.c_str()));
596         return MIstatus::failure;
597     }
598
599     nAddrStart += nAddrOffset;
600     const MIuint64 nAddrNumBytes = pArgNumBytes->GetValue();
601
602     m_pBufferMemory = new unsigned char[nAddrNumBytes];
603     if (m_pBufferMemory == nullptr)
604     {
605         SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_MEMORY_ALLOC_FAILURE), m_cmdData.strMiCmd.c_str(), nAddrNumBytes));
606         return MIstatus::failure;
607     }
608
609     const MIuint64 nReadBytes = sbProcess.ReadMemory(static_cast<lldb::addr_t>(nAddrStart), (void *)m_pBufferMemory, nAddrNumBytes, error);
610     if (nReadBytes != nAddrNumBytes)
611     {
612         SetError(
613             CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_LLDB_ERR_NOT_READ_WHOLE_BLK), m_cmdData.strMiCmd.c_str(), nAddrNumBytes, nAddrStart));
614         return MIstatus::failure;
615     }
616     if (error.Fail())
617     {
618         lldb::SBStream err;
619         const bool bOk = error.GetDescription(err);
620         MIunused(bOk);
621         SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_LLDB_ERR_READ_MEM_BYTES), m_cmdData.strMiCmd.c_str(), nAddrNumBytes, nAddrStart,
622                                        err.GetData()));
623         return MIstatus::failure;
624     }
625
626     m_nAddrStart = nAddrStart;
627     m_nAddrNumBytesToRead = nAddrNumBytes;
628
629     return MIstatus::success;
630 }
631
632 //++ ------------------------------------------------------------------------------------
633 // Details: The invoker requires this function. The command prepares a MI Record Result
634 //          for the work carried out in the Execute().
635 // Type:    Overridden.
636 // Args:    None.
637 // Return:  MIstatus::success - Functional succeeded.
638 //          MIstatus::failure - Functional failed.
639 // Throws:  None.
640 //--
641 bool
642 CMICmdCmdDataReadMemoryBytes::Acknowledge()
643 {
644     // MI: memory=[{begin=\"0x%016" PRIx64 "\",offset=\"0x%016" PRIx64" \",end=\"0x%016" PRIx64 "\",contents=\" \" }]"
645     const CMICmnMIValueConst miValueConst(CMIUtilString::Format("0x%016" PRIx64, m_nAddrStart));
646     const CMICmnMIValueResult miValueResult("begin", miValueConst);
647     CMICmnMIValueTuple miValueTuple(miValueResult);
648     const MIuint64 nAddrOffset = 0;
649     const CMICmnMIValueConst miValueConst2(CMIUtilString::Format("0x%016" PRIx64, nAddrOffset));
650     const CMICmnMIValueResult miValueResult2("offset", miValueConst2);
651     miValueTuple.Add(miValueResult2);
652     const CMICmnMIValueConst miValueConst3(CMIUtilString::Format("0x%016" PRIx64, m_nAddrStart + m_nAddrNumBytesToRead));
653     const CMICmnMIValueResult miValueResult3("end", miValueConst3);
654     miValueTuple.Add(miValueResult3);
655
656     // MI: contents=\" \"
657     CMIUtilString strContent;
658     strContent.reserve((m_nAddrNumBytesToRead << 1) + 1);
659     for (MIuint64 i = 0; i < m_nAddrNumBytesToRead; i++)
660     {
661         strContent += CMIUtilString::Format("%02hhx", m_pBufferMemory[i]);
662     }
663     const CMICmnMIValueConst miValueConst4(strContent);
664     const CMICmnMIValueResult miValueResult4("contents", miValueConst4);
665     miValueTuple.Add(miValueResult4);
666     const CMICmnMIValueList miValueList(miValueTuple);
667     const CMICmnMIValueResult miValueResult5("memory", miValueList);
668
669     const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult5);
670     m_miResultRecord = miRecordResult;
671
672     return MIstatus::success;
673 }
674
675 //++ ------------------------------------------------------------------------------------
676 // Details: Required by the CMICmdFactory when registering *this command. The factory
677 //          calls this function to create an instance of *this command.
678 // Type:    Static method.
679 // Args:    None.
680 // Return:  CMICmdBase * - Pointer to a new command.
681 // Throws:  None.
682 //--
683 CMICmdBase *
684 CMICmdCmdDataReadMemoryBytes::CreateSelf()
685 {
686     return new CMICmdCmdDataReadMemoryBytes();
687 }
688
689 //---------------------------------------------------------------------------------------
690 //---------------------------------------------------------------------------------------
691 //---------------------------------------------------------------------------------------
692
693 //++ ------------------------------------------------------------------------------------
694 // Details: CMICmdCmdDataReadMemory constructor.
695 // Type:    Method.
696 // Args:    None.
697 // Return:  None.
698 // Throws:  None.
699 //--
700 CMICmdCmdDataReadMemory::CMICmdCmdDataReadMemory()
701 {
702     // Command factory matches this name with that received from the stdin stream
703     m_strMiCmd = "data-read-memory";
704
705     // Required by the CMICmdFactory when registering *this command
706     m_pSelfCreatorFn = &CMICmdCmdDataReadMemory::CreateSelf;
707 }
708
709 //++ ------------------------------------------------------------------------------------
710 // Details: CMICmdCmdDataReadMemory destructor.
711 // Type:    Overrideable.
712 // Args:    None.
713 // Return:  None.
714 // Throws:  None.
715 //--
716 CMICmdCmdDataReadMemory::~CMICmdCmdDataReadMemory()
717 {
718 }
719
720 //++ ------------------------------------------------------------------------------------
721 // Details: The invoker requires this function. The command does work in this function.
722 //          The command is likely to communicate with the LLDB SBDebugger in here.
723 // Type:    Overridden.
724 // Args:    None.
725 // Return:  MIstatus::success - Functional succeeded.
726 //          MIstatus::failure - Functional failed.
727 // Throws:  None.
728 //--
729 bool
730 CMICmdCmdDataReadMemory::Execute()
731 {
732     // Do nothing - command deprecated use "data-read-memory-bytes" command
733     return MIstatus::success;
734 }
735
736 //++ ------------------------------------------------------------------------------------
737 // Details: The invoker requires this function. The command prepares a MI Record Result
738 //          for the work carried out in the Execute().
739 // Type:    Overridden.
740 // Args:    None.
741 // Return:  MIstatus::success - Functional succeeded.
742 //          MIstatus::failure - Functional failed.
743 // Throws:  None.
744 //--
745 bool
746 CMICmdCmdDataReadMemory::Acknowledge()
747 {
748     // Command CMICmdCmdSupportListFeatures sends "data-read-memory-bytes" which causes this command not to be called
749     const CMICmnMIValueConst miValueConst(MIRSRC(IDS_CMD_ERR_NOT_IMPLEMENTED_DEPRECATED));
750     const CMICmnMIValueResult miValueResult("msg", miValueConst);
751     const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult);
752     m_miResultRecord = miRecordResult;
753
754     return MIstatus::success;
755 }
756
757 //++ ------------------------------------------------------------------------------------
758 // Details: Required by the CMICmdFactory when registering *this command. The factory
759 //          calls this function to create an instance of *this command.
760 // Type:    Static method.
761 // Args:    None.
762 // Return:  CMICmdBase * - Pointer to a new command.
763 // Throws:  None.
764 //--
765 CMICmdBase *
766 CMICmdCmdDataReadMemory::CreateSelf()
767 {
768     return new CMICmdCmdDataReadMemory();
769 }
770
771 //---------------------------------------------------------------------------------------
772 //---------------------------------------------------------------------------------------
773 //---------------------------------------------------------------------------------------
774
775 //++ ------------------------------------------------------------------------------------
776 // Details: CMICmdCmdDataListRegisterNames constructor.
777 // Type:    Method.
778 // Args:    None.
779 // Return:  None.
780 // Throws:  None.
781 //--
782 CMICmdCmdDataListRegisterNames::CMICmdCmdDataListRegisterNames()
783     : m_constStrArgRegNo("regno")
784     , m_miValueList(true)
785 {
786     // Command factory matches this name with that received from the stdin stream
787     m_strMiCmd = "data-list-register-names";
788
789     // Required by the CMICmdFactory when registering *this command
790     m_pSelfCreatorFn = &CMICmdCmdDataListRegisterNames::CreateSelf;
791 }
792
793 //++ ------------------------------------------------------------------------------------
794 // Details: CMICmdCmdDataReadMemoryBytes destructor.
795 // Type:    Overrideable.
796 // Args:    None.
797 // Return:  None.
798 // Throws:  None.
799 //--
800 CMICmdCmdDataListRegisterNames::~CMICmdCmdDataListRegisterNames()
801 {
802 }
803
804 //++ ------------------------------------------------------------------------------------
805 // Details: The invoker requires this function. The parses the command line options
806 //          arguments to extract values for each of those arguments.
807 // Type:    Overridden.
808 // Args:    None.
809 // Return:  MIstatus::success - Functional succeeded.
810 //          MIstatus::failure - Functional failed.
811 // Throws:  None.
812 //--
813 bool
814 CMICmdCmdDataListRegisterNames::ParseArgs()
815 {
816     m_setCmdArgs.Add(new CMICmdArgValListOfN(m_constStrArgRegNo, false, false, CMICmdArgValListBase::eArgValType_Number));
817     return ParseValidateCmdOptions();
818 }
819
820 //++ ------------------------------------------------------------------------------------
821 // Details: The invoker requires this function. The command does work in this function.
822 //          The command is likely to communicate with the LLDB SBDebugger in here.
823 // Type:    Overridden.
824 // Args:    None.
825 // Return:  MIstatus::success - Functional succeeded.
826 //          MIstatus::failure - Functional failed.
827 // Throws:  None.
828 //--
829 bool
830 CMICmdCmdDataListRegisterNames::Execute()
831 {
832     CMICMDBASE_GETOPTION(pArgRegNo, ListOfN, m_constStrArgRegNo);
833
834     CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
835     lldb::SBProcess sbProcess = rSessionInfo.GetProcess();
836     if (!sbProcess.IsValid())
837     {
838         SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_PROCESS), m_cmdData.strMiCmd.c_str()));
839         return MIstatus::failure;
840     }
841
842     const CMICmdArgValListBase::VecArgObjPtr_t &rVecRegNo(pArgRegNo->GetExpectedOptions());
843     if (!rVecRegNo.empty())
844     {
845         // List of required registers
846         CMICmdArgValListBase::VecArgObjPtr_t::const_iterator it = rVecRegNo.begin();
847         while (it != rVecRegNo.end())
848         {
849             const CMICmdArgValNumber *pRegNo = static_cast<CMICmdArgValNumber *>(*it);
850             const MIuint nRegIndex = pRegNo->GetValue();
851             lldb::SBValue regValue = GetRegister(nRegIndex);
852             if (regValue.IsValid())
853             {
854                 const CMICmnMIValueConst miValueConst(CMICmnLLDBUtilSBValue(regValue).GetName());
855                 m_miValueList.Add(miValueConst);
856             }
857
858             // Next
859             ++it;
860         }
861     }
862     else
863     {
864         // List of all registers
865         lldb::SBThread thread = sbProcess.GetSelectedThread();
866         lldb::SBFrame frame = thread.GetSelectedFrame();
867         lldb::SBValueList registers = frame.GetRegisters();
868         const MIuint nRegisters = registers.GetSize();
869         for (MIuint i = 0; i < nRegisters; i++)
870         {
871             lldb::SBValue value = registers.GetValueAtIndex(i);
872             const MIuint nRegChildren = value.GetNumChildren();
873             for (MIuint j = 0; j < nRegChildren; j++)
874             {
875                 lldb::SBValue regValue = value.GetChildAtIndex(j);
876                 if (regValue.IsValid())
877                 {
878                     const CMICmnMIValueConst miValueConst(CMICmnLLDBUtilSBValue(regValue).GetName());
879                     m_miValueList.Add(miValueConst);
880                 }
881             }
882         }
883     }
884
885     return MIstatus::success;
886 }
887
888 //++ ------------------------------------------------------------------------------------
889 // Details: The invoker requires this function. The command prepares a MI Record Result
890 //          for the work carried out in the Execute().
891 // Type:    Overridden.
892 // Args:    None.
893 // Return:  MIstatus::success - Functional succeeded.
894 //          MIstatus::failure - Functional failed.
895 // Throws:  None.
896 //--
897 bool
898 CMICmdCmdDataListRegisterNames::Acknowledge()
899 {
900     const CMICmnMIValueResult miValueResult("register-names", m_miValueList);
901     const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult);
902     m_miResultRecord = miRecordResult;
903
904     return MIstatus::success;
905 }
906
907 //++ ------------------------------------------------------------------------------------
908 // Details: Required by the CMICmdFactory when registering *this command. The factory
909 //          calls this function to create an instance of *this command.
910 // Type:    Static method.
911 // Args:    None.
912 // Return:  CMICmdBase * - Pointer to a new command.
913 // Throws:  None.
914 //--
915 CMICmdBase *
916 CMICmdCmdDataListRegisterNames::CreateSelf()
917 {
918     return new CMICmdCmdDataListRegisterNames();
919 }
920
921 //++ ------------------------------------------------------------------------------------
922 // Details: Required by the CMICmdFactory when registering *this command. The factory
923 //          calls this function to create an instance of *this command.
924 // Type:    Method.
925 // Args:    None.
926 // Return:  lldb::SBValue - LLDB SBValue object.
927 // Throws:  None.
928 //--
929 lldb::SBValue
930 CMICmdCmdDataListRegisterNames::GetRegister(const MIuint vRegisterIndex) const
931 {
932     lldb::SBThread thread = CMICmnLLDBDebugSessionInfo::Instance().GetProcess().GetSelectedThread();
933     lldb::SBFrame frame = thread.GetSelectedFrame();
934     lldb::SBValueList registers = frame.GetRegisters();
935     const MIuint nRegisters = registers.GetSize();
936     MIuint nRegisterIndex(vRegisterIndex);
937     for (MIuint i = 0; i < nRegisters; i++)
938     {
939         lldb::SBValue value = registers.GetValueAtIndex(i);
940         const MIuint nRegChildren = value.GetNumChildren();
941         if (nRegisterIndex >= nRegChildren)
942         {
943             nRegisterIndex -= nRegChildren;
944             continue;
945         }
946
947         lldb::SBValue value2 = value.GetChildAtIndex(nRegisterIndex);
948         if (value2.IsValid())
949         {
950             return value2;
951         }
952     }
953
954     return lldb::SBValue();
955 }
956
957 //---------------------------------------------------------------------------------------
958 //---------------------------------------------------------------------------------------
959 //---------------------------------------------------------------------------------------
960
961 //++ ------------------------------------------------------------------------------------
962 // Details: CMICmdCmdDataListRegisterValues constructor.
963 // Type:    Method.
964 // Args:    None.
965 // Return:  None.
966 // Throws:  None.
967 //--
968 CMICmdCmdDataListRegisterValues::CMICmdCmdDataListRegisterValues()
969     : m_constStrArgSkip("skip-unavailable")
970     , m_constStrArgFormat("fmt")
971     , m_constStrArgRegNo("regno")
972     , m_miValueList(true)
973 {
974     // Command factory matches this name with that received from the stdin stream
975     m_strMiCmd = "data-list-register-values";
976
977     // Required by the CMICmdFactory when registering *this command
978     m_pSelfCreatorFn = &CMICmdCmdDataListRegisterValues::CreateSelf;
979 }
980
981 //++ ------------------------------------------------------------------------------------
982 // Details: CMICmdCmdDataListRegisterValues destructor.
983 // Type:    Overrideable.
984 // Args:    None.
985 // Return:  None.
986 // Throws:  None.
987 //--
988 CMICmdCmdDataListRegisterValues::~CMICmdCmdDataListRegisterValues()
989 {
990 }
991
992 //++ ------------------------------------------------------------------------------------
993 // Details: The invoker requires this function. The parses the command line options
994 //          arguments to extract values for each of those arguments.
995 // Type:    Overridden.
996 // Args:    None.
997 // Return:  MIstatus::success - Functional succeeded.
998 //          MIstatus::failure - Functional failed.
999 // Throws:  None.
1000 //--
1001 bool
1002 CMICmdCmdDataListRegisterValues::ParseArgs()
1003 {
1004     m_setCmdArgs.Add(new CMICmdArgValOptionLong(m_constStrArgThread, false, false, CMICmdArgValListBase::eArgValType_Number, 1));
1005     m_setCmdArgs.Add(new CMICmdArgValOptionLong(m_constStrArgSkip, false, false));
1006     m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgFormat, true, true));
1007     m_setCmdArgs.Add(new CMICmdArgValListOfN(m_constStrArgRegNo, false, true, CMICmdArgValListBase::eArgValType_Number));
1008     return ParseValidateCmdOptions();
1009 }
1010
1011 //++ ------------------------------------------------------------------------------------
1012 // Details: The invoker requires this function. The command does work in this function.
1013 //          The command is likely to communicate with the LLDB SBDebugger in here.
1014 // Type:    Overridden.
1015 // Args:    None.
1016 // Return:  MIstatus::success - Functional succeeded.
1017 //          MIstatus::failure - Functional failed.
1018 // Throws:  None.
1019 //--
1020 bool
1021 CMICmdCmdDataListRegisterValues::Execute()
1022 {
1023     CMICMDBASE_GETOPTION(pArgFormat, String, m_constStrArgFormat);
1024     CMICMDBASE_GETOPTION(pArgRegNo, ListOfN, m_constStrArgRegNo);
1025
1026     const CMIUtilString &rStrFormat(pArgFormat->GetValue());
1027     if (rStrFormat.length() != 1)
1028     {
1029         SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_FORMAT_TYPE), m_cmdData.strMiCmd.c_str(), rStrFormat.c_str()));
1030         return MIstatus::failure;
1031     }
1032     const CMICmnLLDBDebugSessionInfoVarObj::varFormat_e eFormat = CMICmnLLDBDebugSessionInfoVarObj::GetVarFormatForChar(rStrFormat[0]);
1033     if (eFormat == CMICmnLLDBDebugSessionInfoVarObj::eVarFormat_Invalid)
1034     {
1035         SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_FORMAT_TYPE), m_cmdData.strMiCmd.c_str(), rStrFormat.c_str()));
1036         return MIstatus::failure;
1037     }
1038
1039     CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
1040     lldb::SBProcess sbProcess = rSessionInfo.GetProcess();
1041     if (!sbProcess.IsValid())
1042     {
1043         SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_PROCESS), m_cmdData.strMiCmd.c_str()));
1044         return MIstatus::failure;
1045     }
1046
1047     const CMICmdArgValListBase::VecArgObjPtr_t &rVecRegNo(pArgRegNo->GetExpectedOptions());
1048     if (!rVecRegNo.empty())
1049     {
1050         // List of required registers
1051         CMICmdArgValListBase::VecArgObjPtr_t::const_iterator it = rVecRegNo.begin();
1052         while (it != rVecRegNo.end())
1053         {
1054             const CMICmdArgValNumber *pRegNo = static_cast<CMICmdArgValNumber *>(*it);
1055             const MIuint nRegIndex = pRegNo->GetValue();
1056             lldb::SBValue regValue = GetRegister(nRegIndex);
1057             if (regValue.IsValid())
1058             {
1059                 AddToOutput(nRegIndex, regValue, eFormat);
1060             }
1061
1062             // Next
1063             ++it;
1064         }
1065     }
1066     else
1067     {
1068         // No register numbers are provided. Output all registers.
1069         lldb::SBThread thread = sbProcess.GetSelectedThread();
1070         lldb::SBFrame frame = thread.GetSelectedFrame();
1071         lldb::SBValueList registers = frame.GetRegisters();
1072         const MIuint nRegisters = registers.GetSize();
1073         MIuint nRegIndex = 0;
1074         for (MIuint i = 0; i < nRegisters; i++)
1075         {
1076             lldb::SBValue value = registers.GetValueAtIndex(i);
1077             const MIuint nRegChildren = value.GetNumChildren();
1078             for (MIuint j = 0; j < nRegChildren; j++)
1079             {
1080                 lldb::SBValue regValue = value.GetChildAtIndex(j);
1081                 if (regValue.IsValid())
1082                 {
1083                     AddToOutput(nRegIndex, regValue, eFormat);
1084                 }
1085
1086                 // Next
1087                 ++nRegIndex;
1088             }
1089         }
1090     }
1091
1092     return MIstatus::success;
1093 }
1094
1095 //++ ------------------------------------------------------------------------------------
1096 // Details: The invoker requires this function. The command prepares a MI Record Result
1097 //          for the work carried out in the Execute().
1098 // Type:    Overridden.
1099 // Args:    None.
1100 // Return:  MIstatus::success - Functional succeeded.
1101 //          MIstatus::failure - Functional failed.
1102 // Throws:  None.
1103 //--
1104 bool
1105 CMICmdCmdDataListRegisterValues::Acknowledge()
1106 {
1107     const CMICmnMIValueResult miValueResult("register-values", m_miValueList);
1108     const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult);
1109     m_miResultRecord = miRecordResult;
1110
1111     return MIstatus::success;
1112 }
1113
1114 //++ ------------------------------------------------------------------------------------
1115 // Details: Required by the CMICmdFactory when registering *this command. The factory
1116 //          calls this function to create an instance of *this command.
1117 // Type:    Static method.
1118 // Args:    None.
1119 // Return:  CMICmdBase * - Pointer to a new command.
1120 // Throws:  None.
1121 //--
1122 CMICmdBase *
1123 CMICmdCmdDataListRegisterValues::CreateSelf()
1124 {
1125     return new CMICmdCmdDataListRegisterValues();
1126 }
1127
1128 //++ ------------------------------------------------------------------------------------
1129 // Details: Required by the CMICmdFactory when registering *this command. The factory
1130 //          calls this function to create an instance of *this command.
1131 // Type:    Method.
1132 // Args:    None.
1133 // Return:  lldb::SBValue - LLDB SBValue object.
1134 // Throws:  None.
1135 //--
1136 lldb::SBValue
1137 CMICmdCmdDataListRegisterValues::GetRegister(const MIuint vRegisterIndex) const
1138 {
1139     lldb::SBThread thread = CMICmnLLDBDebugSessionInfo::Instance().GetProcess().GetSelectedThread();
1140     lldb::SBFrame frame = thread.GetSelectedFrame();
1141     lldb::SBValueList registers = frame.GetRegisters();
1142     const MIuint nRegisters = registers.GetSize();
1143     MIuint nRegisterIndex(vRegisterIndex);
1144     for (MIuint i = 0; i < nRegisters; i++)
1145     {
1146         lldb::SBValue value = registers.GetValueAtIndex(i);
1147         const MIuint nRegChildren = value.GetNumChildren();
1148         if (nRegisterIndex >= nRegChildren)
1149         {
1150             nRegisterIndex -= nRegChildren;
1151             continue;
1152         }
1153
1154         lldb::SBValue value2 = value.GetChildAtIndex(nRegisterIndex);
1155         if (value2.IsValid())
1156         {
1157             return value2;
1158         }
1159     }
1160
1161     return lldb::SBValue();
1162 }
1163
1164 //++ ------------------------------------------------------------------------------------
1165 // Details: Adds the register value to the output list.
1166 // Type:    Method.
1167 // Args:    Value of the register, its index and output format.
1168 // Return:  None
1169 // Throws:  None.
1170 //--
1171 void
1172 CMICmdCmdDataListRegisterValues::AddToOutput(const MIuint vnIndex, const lldb::SBValue &vrValue,
1173             CMICmnLLDBDebugSessionInfoVarObj::varFormat_e veVarFormat)
1174 {
1175     const CMICmnMIValueConst miValueConst(CMIUtilString::Format("%u", vnIndex));
1176     const CMICmnMIValueResult miValueResult("number", miValueConst);
1177     CMICmnMIValueTuple miValueTuple(miValueResult);
1178     const CMIUtilString strRegValue(CMICmnLLDBDebugSessionInfoVarObj::GetValueStringFormatted(vrValue, veVarFormat));
1179     const CMICmnMIValueConst miValueConst2(strRegValue);
1180     const CMICmnMIValueResult miValueResult2("value", miValueConst2);
1181     miValueTuple.Add(miValueResult2);
1182     m_miValueList.Add(miValueTuple);
1183 }
1184
1185 //---------------------------------------------------------------------------------------
1186 //---------------------------------------------------------------------------------------
1187 //---------------------------------------------------------------------------------------
1188
1189 //++ ------------------------------------------------------------------------------------
1190 // Details: CMICmdCmdDataListRegisterChanged constructor.
1191 // Type:    Method.
1192 // Args:    None.
1193 // Return:  None.
1194 // Throws:  None.
1195 //--
1196 CMICmdCmdDataListRegisterChanged::CMICmdCmdDataListRegisterChanged()
1197 {
1198     // Command factory matches this name with that received from the stdin stream
1199     m_strMiCmd = "data-list-changed-registers";
1200
1201     // Required by the CMICmdFactory when registering *this command
1202     m_pSelfCreatorFn = &CMICmdCmdDataListRegisterChanged::CreateSelf;
1203 }
1204
1205 //++ ------------------------------------------------------------------------------------
1206 // Details: CMICmdCmdDataListRegisterChanged destructor.
1207 // Type:    Overrideable.
1208 // Args:    None.
1209 // Return:  None.
1210 // Throws:  None.
1211 //--
1212 CMICmdCmdDataListRegisterChanged::~CMICmdCmdDataListRegisterChanged()
1213 {
1214 }
1215
1216 //++ ------------------------------------------------------------------------------------
1217 // Details: The invoker requires this function. The command does work in this function.
1218 //          The command is likely to communicate with the LLDB SBDebugger in here.
1219 // Type:    Overridden.
1220 // Args:    None.
1221 // Return:  MIstatus::success - Functional succeeded.
1222 //          MIstatus::failure - Functional failed.
1223 // Throws:  None.
1224 //--
1225 bool
1226 CMICmdCmdDataListRegisterChanged::Execute()
1227 {
1228     // Do nothing
1229
1230     return MIstatus::success;
1231 }
1232
1233 //++ ------------------------------------------------------------------------------------
1234 // Details: The invoker requires this function. The command prepares a MI Record Result
1235 //          for the work carried out in the Execute().
1236 // Type:    Overridden.
1237 // Args:    None.
1238 // Return:  MIstatus::success - Functional succeeded.
1239 //          MIstatus::failure - Functional failed.
1240 // Throws:  None.
1241 //--
1242 bool
1243 CMICmdCmdDataListRegisterChanged::Acknowledge()
1244 {
1245     const CMICmnMIValueConst miValueConst(MIRSRC(IDS_WORD_NOT_IMPLEMENTED));
1246     const CMICmnMIValueResult miValueResult("msg", miValueConst);
1247     const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult);
1248     m_miResultRecord = miRecordResult;
1249
1250     return MIstatus::success;
1251 }
1252
1253 //++ ------------------------------------------------------------------------------------
1254 // Details: Required by the CMICmdFactory when registering *this command. The factory
1255 //          calls this function to create an instance of *this command.
1256 // Type:    Static method.
1257 // Args:    None.
1258 // Return:  CMICmdBase * - Pointer to a new command.
1259 // Throws:  None.
1260 //--
1261 CMICmdBase *
1262 CMICmdCmdDataListRegisterChanged::CreateSelf()
1263 {
1264     return new CMICmdCmdDataListRegisterChanged();
1265 }
1266
1267 //---------------------------------------------------------------------------------------
1268 //---------------------------------------------------------------------------------------
1269 //---------------------------------------------------------------------------------------
1270
1271 //++ ------------------------------------------------------------------------------------
1272 // Details: CMICmdCmdDataWriteMemoryBytes constructor.
1273 // Type:    Method.
1274 // Args:    None.
1275 // Return:  None.
1276 // Throws:  None.
1277 //--
1278 CMICmdCmdDataWriteMemoryBytes::CMICmdCmdDataWriteMemoryBytes()
1279     : m_constStrArgAddr("address")
1280     , m_constStrArgContents("contents")
1281     , m_constStrArgCount("count")
1282 {
1283     // Command factory matches this name with that received from the stdin stream
1284     m_strMiCmd = "data-write-memory-bytes";
1285
1286     // Required by the CMICmdFactory when registering *this command
1287     m_pSelfCreatorFn = &CMICmdCmdDataWriteMemoryBytes::CreateSelf;
1288 }
1289
1290 //++ ------------------------------------------------------------------------------------
1291 // Details: CMICmdCmdDataWriteMemoryBytes destructor.
1292 // Type:    Overrideable.
1293 // Args:    None.
1294 // Return:  None.
1295 // Throws:  None.
1296 //--
1297 CMICmdCmdDataWriteMemoryBytes::~CMICmdCmdDataWriteMemoryBytes()
1298 {
1299 }
1300
1301 //++ ------------------------------------------------------------------------------------
1302 // Details: The invoker requires this function. The parses the command line options
1303 //          arguments to extract values for each of those arguments.
1304 // Type:    Overridden.
1305 // Args:    None.
1306 // Return:  MIstatus::success - Functional succeeded.
1307 //          MIstatus::failure - Functional failed.
1308 // Throws:  None.
1309 //--
1310 bool
1311 CMICmdCmdDataWriteMemoryBytes::ParseArgs()
1312 {
1313     m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgAddr, true, true, false, true));
1314     m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgContents, true, true, true, true));
1315     m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgCount, false, true, false, true));
1316     return ParseValidateCmdOptions();
1317 }
1318
1319 //++ ------------------------------------------------------------------------------------
1320 // Details: The invoker requires this function. The command does work in this function.
1321 //          The command is likely to communicate with the LLDB SBDebugger in here.
1322 // Type:    Overridden.
1323 // Args:    None.
1324 // Return:  MIstatus::success - Functional succeeded.
1325 //          MIstatus::failure - Functional failed.
1326 // Throws:  None.
1327 //--
1328 bool
1329 CMICmdCmdDataWriteMemoryBytes::Execute()
1330 {
1331     // Do nothing - not reproduceable (yet) in Eclipse
1332     // CMICMDBASE_GETOPTION( pArgOffset, OptionShort, m_constStrArgOffset );
1333     // CMICMDBASE_GETOPTION( pArgAddr, String, m_constStrArgAddr );
1334     // CMICMDBASE_GETOPTION( pArgNumber, String, m_constStrArgNumber );
1335     // CMICMDBASE_GETOPTION( pArgContents, String, m_constStrArgContents );
1336     //
1337     // Numbers extracts as string types as they could be hex numbers
1338     // '&' is not recognised and so has to be removed
1339
1340     return MIstatus::success;
1341 }
1342
1343 //++ ------------------------------------------------------------------------------------
1344 // Details: The invoker requires this function. The command prepares a MI Record Result
1345 //          for the work carried out in the Execute().
1346 // Type:    Overridden.
1347 // Args:    None.
1348 // Return:  MIstatus::success - Functional succeeded.
1349 //          MIstatus::failure - Functional failed.
1350 // Throws:  None.
1351 //--
1352 bool
1353 CMICmdCmdDataWriteMemoryBytes::Acknowledge()
1354 {
1355     const CMICmnMIValueConst miValueConst(MIRSRC(IDS_WORD_NOT_IMPLEMENTED));
1356     const CMICmnMIValueResult miValueResult("msg", miValueConst);
1357     const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult);
1358     m_miResultRecord = miRecordResult;
1359
1360     return MIstatus::success;
1361 }
1362
1363 //++ ------------------------------------------------------------------------------------
1364 // Details: Required by the CMICmdFactory when registering *this command. The factory
1365 //          calls this function to create an instance of *this command.
1366 // Type:    Static method.
1367 // Args:    None.
1368 // Return:  CMICmdBase * - Pointer to a new command.
1369 // Throws:  None.
1370 //--
1371 CMICmdBase *
1372 CMICmdCmdDataWriteMemoryBytes::CreateSelf()
1373 {
1374     return new CMICmdCmdDataWriteMemoryBytes();
1375 }
1376
1377 //---------------------------------------------------------------------------------------
1378 //---------------------------------------------------------------------------------------
1379 //---------------------------------------------------------------------------------------
1380
1381 //++ ------------------------------------------------------------------------------------
1382 // Details: CMICmdCmdDataWriteMemory constructor.
1383 // Type:    Method.
1384 // Args:    None.
1385 // Return:  None.
1386 // Throws:  None.
1387 //--
1388 CMICmdCmdDataWriteMemory::CMICmdCmdDataWriteMemory()
1389     : m_constStrArgOffset("o")
1390     , m_constStrArgAddr("address")
1391     , m_constStrArgD("d")
1392     , m_constStrArgNumber("a number")
1393     , m_constStrArgContents("contents")
1394     , m_nAddr(0)
1395     , m_nCount(0)
1396     , m_pBufferMemory(nullptr)
1397 {
1398     // Command factory matches this name with that received from the stdin stream
1399     m_strMiCmd = "data-write-memory";
1400
1401     // Required by the CMICmdFactory when registering *this command
1402     m_pSelfCreatorFn = &CMICmdCmdDataWriteMemory::CreateSelf;
1403 }
1404
1405 //++ ------------------------------------------------------------------------------------
1406 // Details: CMICmdCmdDataWriteMemory destructor.
1407 // Type:    Overrideable.
1408 // Args:    None.
1409 // Return:  None.
1410 // Throws:  None.
1411 //--
1412 CMICmdCmdDataWriteMemory::~CMICmdCmdDataWriteMemory()
1413 {
1414     if (m_pBufferMemory != nullptr)
1415     {
1416         delete[] m_pBufferMemory;
1417         m_pBufferMemory = nullptr;
1418     }
1419 }
1420
1421 //++ ------------------------------------------------------------------------------------
1422 // Details: The invoker requires this function. The parses the command line options
1423 //          arguments to extract values for each of those arguments.
1424 // Type:    Overridden.
1425 // Args:    None.
1426 // Return:  MIstatus::success - Functional succeeded.
1427 //          MIstatus::failure - Functional failed.
1428 // Throws:  None.
1429 //--
1430 bool
1431 CMICmdCmdDataWriteMemory::ParseArgs()
1432 {
1433     m_setCmdArgs.Add(new CMICmdArgValOptionShort(m_constStrArgOffset, false, true, CMICmdArgValListBase::eArgValType_Number, 1));
1434     m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgAddr, true, true));
1435     m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgD, true, true));
1436     m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgNumber, true, true));
1437     m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgContents, true, true));
1438     return ParseValidateCmdOptions();
1439 }
1440
1441 //++ ------------------------------------------------------------------------------------
1442 // Details: The invoker requires this function. The command does work in this function.
1443 //          The command is likely to communicate with the LLDB SBDebugger in here.
1444 // Type:    Overridden.
1445 // Args:    None.
1446 // Return:  MIstatus::success - Functional succeeded.
1447 //          MIstatus::failure - Functional failed.
1448 // Throws:  None.
1449 //--
1450 bool
1451 CMICmdCmdDataWriteMemory::Execute()
1452 {
1453     CMICMDBASE_GETOPTION(pArgOffset, OptionShort, m_constStrArgOffset);
1454     CMICMDBASE_GETOPTION(pArgAddr, Number, m_constStrArgAddr);
1455     CMICMDBASE_GETOPTION(pArgNumber, Number, m_constStrArgNumber);
1456     CMICMDBASE_GETOPTION(pArgContents, Number, m_constStrArgContents);
1457
1458     MIuint nAddrOffset = 0;
1459     if (pArgOffset->GetFound() && !pArgOffset->GetExpectedOption<CMICmdArgValNumber, MIuint>(nAddrOffset))
1460     {
1461         SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ARGS_ERR_VALIDATION_INVALID), m_cmdData.strMiCmd.c_str(), m_constStrArgAddr.c_str()));
1462         return MIstatus::failure;
1463     }
1464     m_nAddr = pArgAddr->GetValue();
1465     m_nCount = pArgNumber->GetValue();
1466     const MIuint64 nValue = pArgContents->GetValue();
1467
1468     m_pBufferMemory = new unsigned char[m_nCount];
1469     if (m_pBufferMemory == nullptr)
1470     {
1471         SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_MEMORY_ALLOC_FAILURE), m_cmdData.strMiCmd.c_str(), m_nCount));
1472         return MIstatus::failure;
1473     }
1474     *m_pBufferMemory = static_cast<char>(nValue);
1475
1476     CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
1477     lldb::SBProcess sbProcess = rSessionInfo.GetProcess();
1478     lldb::SBError error;
1479     lldb::addr_t addr = static_cast<lldb::addr_t>(m_nAddr + nAddrOffset);
1480     const size_t nBytesWritten = sbProcess.WriteMemory(addr, (const void *)m_pBufferMemory, (size_t)m_nCount, error);
1481     if (nBytesWritten != static_cast<size_t>(m_nCount))
1482     {
1483         SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_LLDB_ERR_NOT_WRITE_WHOLEBLK), m_cmdData.strMiCmd.c_str(), m_nCount, addr));
1484         return MIstatus::failure;
1485     }
1486     if (error.Fail())
1487     {
1488         lldb::SBStream err;
1489         const bool bOk = error.GetDescription(err);
1490         MIunused(bOk);
1491         SetError(
1492             CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_LLDB_ERR_WRITE_MEM_BYTES), m_cmdData.strMiCmd.c_str(), m_nCount, addr, err.GetData()));
1493         return MIstatus::failure;
1494     }
1495
1496     return MIstatus::success;
1497 }
1498
1499 //++ ------------------------------------------------------------------------------------
1500 // Details: The invoker requires this function. The command prepares a MI Record Result
1501 //          for the work carried out in the Execute().
1502 // Type:    Overridden.
1503 // Args:    None.
1504 // Return:  MIstatus::success - Functional succeeded.
1505 //          MIstatus::failure - Functional failed.
1506 // Throws:  None.
1507 //--
1508 bool
1509 CMICmdCmdDataWriteMemory::Acknowledge()
1510 {
1511     const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done);
1512     m_miResultRecord = miRecordResult;
1513
1514     return MIstatus::success;
1515 }
1516
1517 //++ ------------------------------------------------------------------------------------
1518 // Details: Required by the CMICmdFactory when registering *this command. The factory
1519 //          calls this function to create an instance of *this command.
1520 // Type:    Static method.
1521 // Args:    None.
1522 // Return:  CMICmdBase * - Pointer to a new command.
1523 // Throws:  None.
1524 //--
1525 CMICmdBase *
1526 CMICmdCmdDataWriteMemory::CreateSelf()
1527 {
1528     return new CMICmdCmdDataWriteMemory();
1529 }
1530
1531 //---------------------------------------------------------------------------------------
1532 //---------------------------------------------------------------------------------------
1533 //---------------------------------------------------------------------------------------
1534
1535 //++ ------------------------------------------------------------------------------------
1536 // Details: CMICmdCmdDataInfoLine constructor.
1537 // Type:    Method.
1538 // Args:    None.
1539 // Return:  None.
1540 // Throws:  None.
1541 //--
1542 CMICmdCmdDataInfoLine::CMICmdCmdDataInfoLine()
1543     : m_constStrArgLocation("location")
1544 {
1545     // Command factory matches this name with that received from the stdin stream
1546     m_strMiCmd = "data-info-line";
1547
1548     // Required by the CMICmdFactory when registering *this command
1549     m_pSelfCreatorFn = &CMICmdCmdDataInfoLine::CreateSelf;
1550 }
1551
1552 //++ ------------------------------------------------------------------------------------
1553 // Details: CMICmdCmdDataInfoLine destructor.
1554 // Type:    Overrideable.
1555 // Args:    None.
1556 // Return:  None.
1557 // Throws:  None.
1558 //--
1559 CMICmdCmdDataInfoLine::~CMICmdCmdDataInfoLine()
1560 {
1561 }
1562
1563 //++ ------------------------------------------------------------------------------------
1564 // Details: The invoker requires this function. The parses the command line options
1565 //          arguments to extract values for each of those arguments.
1566 // Type:    Overridden.
1567 // Args:    None.
1568 // Return:  MIstatus::success - Functional succeeded.
1569 //          MIstatus::failure - Functional failed.
1570 // Throws:  None.
1571 //--
1572 bool
1573 CMICmdCmdDataInfoLine::ParseArgs()
1574 {
1575     m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgLocation, true, true));
1576     return ParseValidateCmdOptions();
1577 }
1578
1579 //++ ------------------------------------------------------------------------------------
1580 // Details: The invoker requires this function. The command does work in this function.
1581 //          The command is likely to communicate with the LLDB SBDebugger in here.
1582 // Type:    Overridden.
1583 // Args:    None.
1584 // Return:  MIstatus::success - Functional succeeded.
1585 //          MIstatus::failure - Functional failed.
1586 // Throws:  None.
1587 //--
1588 bool
1589 CMICmdCmdDataInfoLine::Execute()
1590 {
1591     CMICMDBASE_GETOPTION(pArgLocation, String, m_constStrArgLocation);
1592
1593     const CMIUtilString &strLocation(pArgLocation->GetValue());
1594     CMIUtilString strCmdOptionsLocation;
1595     if (strLocation.at(0) == '*')
1596     {
1597         // Parse argument:
1598         // *0x12345
1599         //  ^^^^^^^ -- address
1600         const CMIUtilString strAddress(strLocation.substr(1));
1601         strCmdOptionsLocation = CMIUtilString::Format("--address %s", strAddress.c_str());
1602     }
1603     else
1604     {
1605         const size_t nLineStartPos = strLocation.rfind(':');
1606         if ((nLineStartPos == std::string::npos) || (nLineStartPos == 0) || (nLineStartPos == strLocation.length() - 1))
1607         {
1608             SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_LOCATION_FORMAT), m_cmdData.strMiCmd.c_str(), strLocation.c_str())
1609                          .c_str());
1610             return MIstatus::failure;
1611         }
1612         // Parse argument:
1613         // hello.cpp:5
1614         // ^^^^^^^^^ -- file
1615         //           ^ -- line
1616         const CMIUtilString strFile(strLocation.substr(0, nLineStartPos));
1617         const CMIUtilString strLine(strLocation.substr(nLineStartPos + 1));
1618         strCmdOptionsLocation = CMIUtilString::Format("--file \"%s\" --line %s", strFile.AddSlashes().c_str(), strLine.c_str());
1619     }
1620     const CMIUtilString strCmd(CMIUtilString::Format("target modules lookup -v %s", strCmdOptionsLocation.c_str()));
1621
1622     CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
1623     const lldb::ReturnStatus rtn = rSessionInfo.GetDebugger().GetCommandInterpreter().HandleCommand(strCmd.c_str(), m_lldbResult);
1624     MIunused(rtn);
1625
1626     return MIstatus::success;
1627 }
1628
1629 //++ ------------------------------------------------------------------------------------
1630 // Details: Helper function for parsing a line entry returned from lldb for the command:
1631 //              target modules lookup -v <location>
1632 //          where the line entry is of the format:
1633 //              LineEntry: \[0x0000000100000f37-0x0000000100000f45\): /path/file:3[:1]
1634 //                           start              end                   file       line column(opt)
1635 // Args:    input - (R) Input string to parse.
1636 //          start - (W) String representing the start address.
1637 //          end   - (W) String representing the end address.
1638 //          file  - (W) String representing the file.
1639 //          line  - (W) String representing the line.
1640 // Return:  bool - True = input was parsed successfully, false = input could not be parsed.
1641 // Throws:  None.
1642 //--
1643 static bool
1644 ParseLLDBLineEntry(const char *input, CMIUtilString &start, CMIUtilString &end,
1645                    CMIUtilString &file, CMIUtilString &line)
1646 {
1647     // Note: Ambiguities arise because the column is optional, and
1648     // because : can appear in filenames or as a byte in a multibyte
1649     // UTF8 character.  We keep those cases to a minimum by using regex
1650     // to work on the string from both the left and right, so that what
1651     // is remains is assumed to be the filename.
1652
1653     // Match LineEntry using regex.
1654     static MIUtilParse::CRegexParser g_lineentry_nocol_regex( 
1655         "^ *LineEntry: \\[(0x[0-9a-fA-F]+)-(0x[0-9a-fA-F]+)\\): (.+):([0-9]+)$");
1656     static MIUtilParse::CRegexParser g_lineentry_col_regex( 
1657         "^ *LineEntry: \\[(0x[0-9a-fA-F]+)-(0x[0-9a-fA-F]+)\\): (.+):([0-9]+):[0-9]+$");
1658         //                ^1=start         ^2=end               ^3=f ^4=line ^5=:col(opt)
1659
1660     MIUtilParse::CRegexParser::Match match(6);
1661
1662     // First try matching the LineEntry with the column,
1663     // then try without the column.
1664     const bool ok = g_lineentry_col_regex.Execute(input, match) ||
1665                     g_lineentry_nocol_regex.Execute(input, match);
1666     if (ok)
1667     {
1668         start = match.GetMatchAtIndex(1);
1669         end   = match.GetMatchAtIndex(2);
1670         file  = match.GetMatchAtIndex(3);
1671         line  = match.GetMatchAtIndex(4);
1672     }
1673     return ok;
1674 }
1675
1676 //++ ------------------------------------------------------------------------------------
1677 // Details: The invoker requires this function. The command prepares a MI Record Result
1678 //          for the work carried out in the Execute().
1679 // Type:    Overridden.
1680 // Args:    None.
1681 // Return:  MIstatus::success - Functional succeeded.
1682 //          MIstatus::failure - Functional failed.
1683 // Throws:  None.
1684 //--
1685 bool
1686 CMICmdCmdDataInfoLine::Acknowledge()
1687 {
1688     if (m_lldbResult.GetErrorSize() > 0)
1689     {
1690         const CMICmnMIValueConst miValueConst(m_lldbResult.GetError());
1691         const CMICmnMIValueResult miValueResult("msg", miValueConst);
1692         const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult);
1693         m_miResultRecord = miRecordResult;
1694         return MIstatus::success;
1695     }
1696     else if (m_lldbResult.GetOutputSize() > 0)
1697     {
1698         CMIUtilString::VecString_t vecLines;
1699         const CMIUtilString strLldbMsg(m_lldbResult.GetOutput());
1700         const MIuint nLines(strLldbMsg.SplitLines(vecLines));
1701
1702         for (MIuint i = 0; i < nLines; ++i)
1703         {
1704             // String looks like:
1705             // LineEntry: \[0x0000000100000f37-0x0000000100000f45\): /path/to/file:3[:1]
1706             const CMIUtilString &rLine(vecLines[i]);
1707             CMIUtilString strStart;
1708             CMIUtilString strEnd;
1709             CMIUtilString strFile;
1710             CMIUtilString strLine;
1711
1712             if (!ParseLLDBLineEntry(rLine.c_str(), strStart, strEnd, strFile, strLine))
1713                 continue;
1714
1715             const CMICmnMIValueConst miValueConst(strStart);
1716             const CMICmnMIValueResult miValueResult("start", miValueConst);
1717             CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken,
1718                                                 CMICmnMIResultRecord::eResultClass_Done,
1719                                                 miValueResult);
1720             const CMICmnMIValueConst miValueConst2(strEnd);
1721             const CMICmnMIValueResult miValueResult2("end", miValueConst2);
1722             miRecordResult.Add(miValueResult2);
1723             const CMICmnMIValueConst miValueConst3(strFile);
1724             const CMICmnMIValueResult miValueResult3("file", miValueConst3);
1725             miRecordResult.Add(miValueResult3);
1726             const CMICmnMIValueConst miValueConst4(strLine);
1727             const CMICmnMIValueResult miValueResult4("line", miValueConst4);
1728             miRecordResult.Add(miValueResult4);
1729
1730             // MI print "%s^done,start=\"%d\",end=\"%d\"",file=\"%s\",line=\"%d\"
1731             m_miResultRecord = miRecordResult;
1732
1733             return MIstatus::success;
1734         }
1735     }
1736
1737     // MI print "%s^error,msg=\"Command '-data-info-line'. Error: The LineEntry is absent or has an unknown format.\""
1738     const CMICmnMIValueConst miValueConst(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_SOME_ERROR), m_cmdData.strMiCmd.c_str(), "The LineEntry is absent or has an unknown format."));
1739     const CMICmnMIValueResult miValueResult("msg", miValueConst);
1740     const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult);
1741     m_miResultRecord = miRecordResult;
1742
1743     return MIstatus::success;
1744 }
1745
1746 //++ ------------------------------------------------------------------------------------
1747 // Details: Required by the CMICmdFactory when registering *this command. The factory
1748 //          calls this function to create an instance of *this command.
1749 // Type:    Static method.
1750 // Args:    None.
1751 // Return:  CMICmdBase * - Pointer to a new command.
1752 // Throws:  None.
1753 //--
1754 CMICmdBase *
1755 CMICmdCmdDataInfoLine::CreateSelf()
1756 {
1757     return new CMICmdCmdDataInfoLine();
1758 }