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