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