1 //===-- MICmdCmdData.cpp ----------------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // Overview: 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.
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"
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"
46 //++ ------------------------------------------------------------------------------------
47 // Details: CMICmdCmdDataEvaluateExpression constructor.
53 CMICmdCmdDataEvaluateExpression::CMICmdCmdDataEvaluateExpression(void)
54 : m_bExpressionValid(true)
55 , m_bEvaluatedExpression(true)
57 , m_bCompositeVarType(false)
58 , m_bFoundInvalidChar(false)
59 , m_cExpressionInvalidChar(0x00)
60 , m_constStrArgThread("thread")
61 , m_constStrArgFrame("frame")
62 , m_constStrArgExpr("expr")
64 // Command factory matches this name with that received from the stdin stream
65 m_strMiCmd = "data-evaluate-expression";
67 // Required by the CMICmdFactory when registering *this command
68 m_pSelfCreatorFn = &CMICmdCmdDataEvaluateExpression::CreateSelf;
71 //++ ------------------------------------------------------------------------------------
72 // Details: CMICmdCmdDataEvaluateExpression destructor.
73 // Type: Overrideable.
78 CMICmdCmdDataEvaluateExpression::~CMICmdCmdDataEvaluateExpression(void)
82 //++ ------------------------------------------------------------------------------------
83 // Details: The invoker requires this function. The parses the command line options
84 // arguments to extract values for each of those arguments.
87 // Return: MIstatus::success - Functional succeeded.
88 // MIstatus::failure - Functional failed.
92 CMICmdCmdDataEvaluateExpression::ParseArgs(void)
95 m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgThread, false, false, CMICmdArgValListBase::eArgValType_Number, 1)));
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());
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.
107 // Return: MIstatus::success - Functional succeeded.
108 // MIstatus::failure - Functional failed.
112 CMICmdCmdDataEvaluateExpression::Execute(void)
114 CMICMDBASE_GETOPTION(pArgExpr, String, m_constStrArgExpr);
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;
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())
131 m_bEvaluatedExpression = false;
132 return MIstatus::success;
134 if (!utilValue.HasName())
136 if (HaveInvalidCharacterInExpression(rExpression, m_cExpressionInvalidChar))
138 m_bFoundInvalidChar = true;
139 return MIstatus::success;
142 m_strValue = rExpression;
143 return MIstatus::success;
145 if (rExpression.IsQuoted())
147 m_strValue = rExpression.Trim('\"');
148 return MIstatus::success;
151 MIuint64 nNumber = 0;
152 if (CMICmnLLDBProxySBValue::GetValueAsUnsigned(value, nNumber) == MIstatus::success)
154 const lldb::ValueType eValueType = value.GetValueType();
155 MIunused(eValueType);
156 m_strValue = utilValue.GetValue().Escape().AddSlashes();
157 return MIstatus::success;
160 // Composite type i.e. struct
161 m_bCompositeVarType = true;
162 const MIuint nChild = value.GetNumChildren();
163 for (MIuint i = 0; i < nChild; i++)
165 lldb::SBValue member = value.GetChildAtIndex(i);
166 const bool bValid = member.IsValid();
167 CMIUtilString strType(MIRSRC(IDS_WORD_UNKNOWNTYPE_BRKTS));
170 const CMIUtilString strValue(
171 CMICmnLLDBDebugSessionInfoVarObj::GetValueStringFormatted(member, CMICmnLLDBDebugSessionInfoVarObj::eVarFormat_Natural));
172 const char *pTypeName = member.GetName();
173 if (pTypeName != nullptr)
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);
185 return MIstatus::success;
188 //++ ------------------------------------------------------------------------------------
189 // Details: The invoker requires this function. The command prepares a MI Record Result
190 // for the work carried out in the Execute().
193 // Return: MIstatus::success - Functional succeeded.
194 // MIstatus::failure - Functional failed.
198 CMICmdCmdDataEvaluateExpression::Acknowledge(void)
200 if (m_bExpressionValid)
202 if (m_bEvaluatedExpression)
204 if (m_bCompositeVarType)
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;
213 if (m_bFoundInvalidChar)
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;
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;
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;
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;
242 return MIstatus::success;
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.
250 // Return: CMICmdBase * - Pointer to a new command.
254 CMICmdCmdDataEvaluateExpression::CreateSelf(void)
256 return new CMICmdCmdDataEvaluateExpression();
259 //++ ------------------------------------------------------------------------------------
260 // Details: Examine the expression string to see if it contains invalid characters.
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.
268 CMICmdCmdDataEvaluateExpression::HaveInvalidCharacterInExpression(const CMIUtilString &vrExpr, char &vrwInvalidChar)
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;
277 //---------------------------------------------------------------------------------------
278 //---------------------------------------------------------------------------------------
279 //---------------------------------------------------------------------------------------
281 //++ ------------------------------------------------------------------------------------
282 // Details: CMICmdCmdDataDisassemble constructor.
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)
296 // Command factory matches this name with that received from the stdin stream
297 m_strMiCmd = "data-disassemble";
299 // Required by the CMICmdFactory when registering *this command
300 m_pSelfCreatorFn = &CMICmdCmdDataDisassemble::CreateSelf;
303 //++ ------------------------------------------------------------------------------------
304 // Details: CMICmdCmdDataDisassemble destructor.
305 // Type: Overrideable.
310 CMICmdCmdDataDisassemble::~CMICmdCmdDataDisassemble(void)
314 //++ ------------------------------------------------------------------------------------
315 // Details: The invoker requires this function. The parses the command line options
316 // arguments to extract values for each of those arguments.
319 // Return: MIstatus::success - Functional succeeded.
320 // MIstatus::failure - Functional failed.
324 CMICmdCmdDataDisassemble::ParseArgs(void)
327 m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgThread, false, true, CMICmdArgValListBase::eArgValType_Number, 1)));
330 *(new CMICmdArgValOptionShort(m_constStrArgAddrStart, true, true, CMICmdArgValListBase::eArgValType_StringQuotedNumber, 1)));
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());
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.
344 // Return: MIstatus::success - Functional succeeded.
345 // MIstatus::failure - Functional failed.
349 CMICmdCmdDataDisassemble::Execute(void)
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);
356 // Retrieve the --thread option's thread ID (only 1)
357 MIuint64 nThreadId = UINT64_MAX;
358 if (pArgThread->GetFound() && !pArgThread->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nThreadId))
360 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_THREAD_INVALID), m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str()));
361 return MIstatus::failure;
363 CMIUtilString strAddrStart;
364 if (!pArgAddrStart->GetExpectedOption<CMICmdArgValString, CMIUtilString>(strAddrStart))
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;
370 MIint64 nAddrStart = 0;
371 if (!strAddrStart.ExtractNumber(nAddrStart))
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;
378 CMIUtilString strAddrEnd;
379 if (!pArgAddrEnd->GetExpectedOption<CMICmdArgValString, CMIUtilString>(strAddrEnd))
382 CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_DISASM_ADDR_END_INVALID), m_cmdData.strMiCmd.c_str(), m_constStrArgAddrEnd.c_str()));
383 return MIstatus::failure;
385 MIint64 nAddrEnd = 0;
386 if (!strAddrEnd.ExtractNumber(nAddrEnd))
389 CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_DISASM_ADDR_END_INVALID), m_cmdData.strMiCmd.c_str(), m_constStrArgAddrEnd.c_str()));
390 return MIstatus::failure;
392 const MIuint nDisasmMode = pArgMode->GetValue();
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();
404 for (size_t i = 0; i < nInstructions; i++)
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();
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);
440 if (nDisasmMode == 1)
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;
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);
462 m_miValueList.Add(miValueTuple);
466 return MIstatus::success;
469 //++ ------------------------------------------------------------------------------------
470 // Details: The invoker requires this function. The command prepares a MI Record Result
471 // for the work carried out in the Execute().
474 // Return: MIstatus::success - Functional succeeded.
475 // MIstatus::failure - Functional failed.
479 CMICmdCmdDataDisassemble::Acknowledge(void)
481 const CMICmnMIValueResult miValueResult("asm_insns", m_miValueList);
482 const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult);
483 m_miResultRecord = miRecordResult;
485 return MIstatus::success;
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.
493 // Return: CMICmdBase * - Pointer to a new command.
497 CMICmdCmdDataDisassemble::CreateSelf(void)
499 return new CMICmdCmdDataDisassemble();
502 //---------------------------------------------------------------------------------------
503 //---------------------------------------------------------------------------------------
504 //---------------------------------------------------------------------------------------
506 //++ ------------------------------------------------------------------------------------
507 // Details: CMICmdCmdDataReadMemoryBytes constructor.
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)
521 , m_nAddrNumBytesToRead(0)
523 // Command factory matches this name with that received from the stdin stream
524 m_strMiCmd = "data-read-memory-bytes";
526 // Required by the CMICmdFactory when registering *this command
527 m_pSelfCreatorFn = &CMICmdCmdDataReadMemoryBytes::CreateSelf;
530 //++ ------------------------------------------------------------------------------------
531 // Details: CMICmdCmdDataReadMemoryBytes destructor.
532 // Type: Overrideable.
537 CMICmdCmdDataReadMemoryBytes::~CMICmdCmdDataReadMemoryBytes(void)
539 if (m_pBufferMemory != nullptr)
541 delete[] m_pBufferMemory;
542 m_pBufferMemory = nullptr;
546 //++ ------------------------------------------------------------------------------------
547 // Details: The invoker requires this function. The parses the command line options
548 // arguments to extract values for each of those arguments.
551 // Return: MIstatus::success - Functional succeeded.
552 // MIstatus::failure - Functional failed.
556 CMICmdCmdDataReadMemoryBytes::ParseArgs(void)
559 m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgThread, false, true, CMICmdArgValListBase::eArgValType_Number, 1)));
561 m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgFrame, false, true, CMICmdArgValListBase::eArgValType_Number, 1)));
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());
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.
575 // Return: MIstatus::success - Function succeeded.
576 // MIstatus::failure - Function failed.
580 CMICmdCmdDataReadMemoryBytes::Execute(void)
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);
588 // get the --thread option value
589 MIuint64 nThreadId = UINT64_MAX;
590 if (pArgThread->GetFound() && !pArgThread->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nThreadId))
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;
597 // get the --frame option value
598 MIuint64 nFrame = UINT64_MAX;
599 if (pArgFrame->GetFound() && !pArgFrame->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nFrame))
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;
606 // get the -o option value
607 MIuint64 nAddrOffset = 0;
608 if (pArgAddrOffset->GetFound() && !pArgAddrOffset->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nAddrOffset))
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;
615 CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
616 lldb::SBProcess sbProcess = rSessionInfo.GetProcess();
617 if (!sbProcess.IsValid())
619 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_PROCESS), m_cmdData.strMiCmd.c_str()));
620 return MIstatus::failure;
623 lldb::SBThread thread = (nThreadId != UINT64_MAX) ?
624 sbProcess.GetThreadByIndexID(nThreadId) : sbProcess.GetSelectedThread();
625 if (!thread.IsValid())
627 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_THREAD_INVALID), m_cmdData.strMiCmd.c_str()));
628 return MIstatus::failure;
631 lldb::SBFrame frame = (nFrame != UINT64_MAX) ?
632 thread.GetFrameAtIndex(nFrame) : thread.GetSelectedFrame();
633 if (!frame.IsValid())
635 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_FRAME_INVALID), m_cmdData.strMiCmd.c_str()));
636 return MIstatus::failure;
639 const CMIUtilString &rAddrExpr = pArgAddrExpr->GetValue();
640 lldb::SBValue addrExprValue = frame.EvaluateExpression(rAddrExpr.c_str());
641 lldb::SBError error = addrExprValue.GetError();
644 SetError(error.GetCString());
645 return MIstatus::failure;
647 else if (!addrExprValue.IsValid())
649 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_EXPR_INVALID), rAddrExpr.c_str()));
650 return MIstatus::failure;
653 MIuint64 nAddrStart = 0;
654 if (!CMICmnLLDBProxySBValue::GetValueAsUnsigned(addrExprValue, nAddrStart))
656 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_EXPR_INVALID), rAddrExpr.c_str()));
657 return MIstatus::failure;
660 nAddrStart += nAddrOffset;
661 const MIuint64 nAddrNumBytes = pArgNumBytes->GetValue();
663 m_pBufferMemory = new unsigned char[nAddrNumBytes];
664 if (m_pBufferMemory == nullptr)
666 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_MEMORY_ALLOC_FAILURE), m_cmdData.strMiCmd.c_str(), nAddrNumBytes));
667 return MIstatus::failure;
670 const MIuint64 nReadBytes = sbProcess.ReadMemory(static_cast<lldb::addr_t>(nAddrStart), (void *)m_pBufferMemory, nAddrNumBytes, error);
671 if (nReadBytes != nAddrNumBytes)
674 CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_LLDB_ERR_NOT_READ_WHOLE_BLK), m_cmdData.strMiCmd.c_str(), nAddrNumBytes, nAddrStart));
675 return MIstatus::failure;
680 const bool bOk = error.GetDescription(err);
682 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_LLDB_ERR_READ_MEM_BYTES), m_cmdData.strMiCmd.c_str(), nAddrNumBytes, nAddrStart,
684 return MIstatus::failure;
687 m_nAddrStart = nAddrStart;
688 m_nAddrNumBytesToRead = nAddrNumBytes;
690 return MIstatus::success;
693 //++ ------------------------------------------------------------------------------------
694 // Details: The invoker requires this function. The command prepares a MI Record Result
695 // for the work carried out in the Execute().
698 // Return: MIstatus::success - Functional succeeded.
699 // MIstatus::failure - Functional failed.
703 CMICmdCmdDataReadMemoryBytes::Acknowledge(void)
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);
717 // MI: contents=\" \"
718 CMIUtilString strContent;
719 strContent.reserve((m_nAddrNumBytesToRead << 1) + 1);
720 for (MIuint64 i = 0; i < m_nAddrNumBytesToRead; i++)
722 strContent += CMIUtilString::Format("%02hhx", m_pBufferMemory[i]);
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);
730 const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult5);
731 m_miResultRecord = miRecordResult;
733 return MIstatus::success;
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.
741 // Return: CMICmdBase * - Pointer to a new command.
745 CMICmdCmdDataReadMemoryBytes::CreateSelf(void)
747 return new CMICmdCmdDataReadMemoryBytes();
750 //---------------------------------------------------------------------------------------
751 //---------------------------------------------------------------------------------------
752 //---------------------------------------------------------------------------------------
754 //++ ------------------------------------------------------------------------------------
755 // Details: CMICmdCmdDataReadMemory constructor.
761 CMICmdCmdDataReadMemory::CMICmdCmdDataReadMemory(void)
763 // Command factory matches this name with that received from the stdin stream
764 m_strMiCmd = "data-read-memory";
766 // Required by the CMICmdFactory when registering *this command
767 m_pSelfCreatorFn = &CMICmdCmdDataReadMemory::CreateSelf;
770 //++ ------------------------------------------------------------------------------------
771 // Details: CMICmdCmdDataReadMemory destructor.
772 // Type: Overrideable.
777 CMICmdCmdDataReadMemory::~CMICmdCmdDataReadMemory(void)
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.
786 // Return: MIstatus::success - Functional succeeded.
787 // MIstatus::failure - Functional failed.
791 CMICmdCmdDataReadMemory::Execute(void)
793 // Do nothing - command deprecated use "data-read-memory-bytes" command
794 return MIstatus::success;
797 //++ ------------------------------------------------------------------------------------
798 // Details: The invoker requires this function. The command prepares a MI Record Result
799 // for the work carried out in the Execute().
802 // Return: MIstatus::success - Functional succeeded.
803 // MIstatus::failure - Functional failed.
807 CMICmdCmdDataReadMemory::Acknowledge(void)
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;
815 return MIstatus::success;
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.
823 // Return: CMICmdBase * - Pointer to a new command.
827 CMICmdCmdDataReadMemory::CreateSelf(void)
829 return new CMICmdCmdDataReadMemory();
832 //---------------------------------------------------------------------------------------
833 //---------------------------------------------------------------------------------------
834 //---------------------------------------------------------------------------------------
836 //++ ------------------------------------------------------------------------------------
837 // Details: CMICmdCmdDataListRegisterNames constructor.
843 CMICmdCmdDataListRegisterNames::CMICmdCmdDataListRegisterNames(void)
844 : m_constStrArgThreadGroup("thread-group")
845 , m_constStrArgRegNo("regno")
846 , m_miValueList(true)
848 // Command factory matches this name with that received from the stdin stream
849 m_strMiCmd = "data-list-register-names";
851 // Required by the CMICmdFactory when registering *this command
852 m_pSelfCreatorFn = &CMICmdCmdDataListRegisterNames::CreateSelf;
855 //++ ------------------------------------------------------------------------------------
856 // Details: CMICmdCmdDataReadMemoryBytes destructor.
857 // Type: Overrideable.
862 CMICmdCmdDataListRegisterNames::~CMICmdCmdDataListRegisterNames(void)
866 //++ ------------------------------------------------------------------------------------
867 // Details: The invoker requires this function. The parses the command line options
868 // arguments to extract values for each of those arguments.
871 // Return: MIstatus::success - Functional succeeded.
872 // MIstatus::failure - Functional failed.
876 CMICmdCmdDataListRegisterNames::ParseArgs(void)
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());
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.
889 // Return: MIstatus::success - Functional succeeded.
890 // MIstatus::failure - Functional failed.
894 CMICmdCmdDataListRegisterNames::Execute(void)
896 CMICMDBASE_GETOPTION(pArgRegNo, ListOfN, m_constStrArgRegNo);
898 CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
899 lldb::SBProcess sbProcess = rSessionInfo.GetProcess();
900 if (!sbProcess.IsValid())
902 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_PROCESS), m_cmdData.strMiCmd.c_str()));
903 return MIstatus::failure;
906 const CMICmdArgValListBase::VecArgObjPtr_t &rVecRegNo(pArgRegNo->GetExpectedOptions());
907 if (!rVecRegNo.empty())
909 // List of required registers
910 CMICmdArgValListBase::VecArgObjPtr_t::const_iterator it = rVecRegNo.begin();
911 while (it != rVecRegNo.end())
913 const CMICmdArgValNumber *pRegNo = static_cast<CMICmdArgValNumber *>(*it);
914 const MIuint nRegIndex = pRegNo->GetValue();
915 lldb::SBValue regValue = GetRegister(nRegIndex);
916 if (regValue.IsValid())
918 const CMICmnMIValueConst miValueConst(CMICmnLLDBUtilSBValue(regValue).GetName());
919 m_miValueList.Add(miValueConst);
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++)
935 lldb::SBValue value = registers.GetValueAtIndex(i);
936 const MIuint nRegChildren = value.GetNumChildren();
937 for (MIuint j = 0; j < nRegChildren; j++)
939 lldb::SBValue regValue = value.GetChildAtIndex(j);
940 if (regValue.IsValid())
942 const CMICmnMIValueConst miValueConst(CMICmnLLDBUtilSBValue(regValue).GetName());
943 const bool bOk = m_miValueList.Add(miValueConst);
945 return MIstatus::failure;
951 return MIstatus::success;
954 //++ ------------------------------------------------------------------------------------
955 // Details: The invoker requires this function. The command prepares a MI Record Result
956 // for the work carried out in the Execute().
959 // Return: MIstatus::success - Functional succeeded.
960 // MIstatus::failure - Functional failed.
964 CMICmdCmdDataListRegisterNames::Acknowledge(void)
966 const CMICmnMIValueResult miValueResult("register-names", m_miValueList);
967 const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult);
968 m_miResultRecord = miRecordResult;
970 return MIstatus::success;
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.
978 // Return: CMICmdBase * - Pointer to a new command.
982 CMICmdCmdDataListRegisterNames::CreateSelf(void)
984 return new CMICmdCmdDataListRegisterNames();
987 //++ ------------------------------------------------------------------------------------
988 // Details: Required by the CMICmdFactory when registering *this command. The factory
989 // calls this function to create an instance of *this command.
992 // Return: lldb::SBValue - LLDB SBValue object.
996 CMICmdCmdDataListRegisterNames::GetRegister(const MIuint vRegisterIndex) const
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++)
1005 lldb::SBValue value = registers.GetValueAtIndex(i);
1006 const MIuint nRegChildren = value.GetNumChildren();
1007 if (nRegisterIndex >= nRegChildren)
1009 nRegisterIndex -= nRegChildren;
1013 lldb::SBValue value2 = value.GetChildAtIndex(nRegisterIndex);
1014 if (value2.IsValid())
1020 return lldb::SBValue();
1023 //---------------------------------------------------------------------------------------
1024 //---------------------------------------------------------------------------------------
1025 //---------------------------------------------------------------------------------------
1027 //++ ------------------------------------------------------------------------------------
1028 // Details: CMICmdCmdDataListRegisterValues constructor.
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)
1041 // Command factory matches this name with that received from the stdin stream
1042 m_strMiCmd = "data-list-register-values";
1044 // Required by the CMICmdFactory when registering *this command
1045 m_pSelfCreatorFn = &CMICmdCmdDataListRegisterValues::CreateSelf;
1048 //++ ------------------------------------------------------------------------------------
1049 // Details: CMICmdCmdDataListRegisterValues destructor.
1050 // Type: Overrideable.
1055 CMICmdCmdDataListRegisterValues::~CMICmdCmdDataListRegisterValues(void)
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.
1064 // Return: MIstatus::success - Functional succeeded.
1065 // MIstatus::failure - Functional failed.
1069 CMICmdCmdDataListRegisterValues::ParseArgs(void)
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());
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.
1084 // Return: MIstatus::success - Functional succeeded.
1085 // MIstatus::failure - Functional failed.
1089 CMICmdCmdDataListRegisterValues::Execute(void)
1091 CMICMDBASE_GETOPTION(pArgFormat, String, m_constStrArgFormat);
1092 CMICMDBASE_GETOPTION(pArgRegNo, ListOfN, m_constStrArgRegNo);
1094 const CMIUtilString &rStrFormat(pArgFormat->GetValue());
1095 if (rStrFormat.length() != 1)
1097 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_FORMAT_TYPE), m_cmdData.strMiCmd.c_str(), rStrFormat.c_str()));
1098 return MIstatus::failure;
1100 const CMICmnLLDBDebugSessionInfoVarObj::varFormat_e eFormat = CMICmnLLDBDebugSessionInfoVarObj::GetVarFormatForChar(rStrFormat[0]);
1101 if (eFormat == CMICmnLLDBDebugSessionInfoVarObj::eVarFormat_Invalid)
1103 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_FORMAT_TYPE), m_cmdData.strMiCmd.c_str(), rStrFormat.c_str()));
1104 return MIstatus::failure;
1107 CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
1108 lldb::SBProcess sbProcess = rSessionInfo.GetProcess();
1109 if (!sbProcess.IsValid())
1111 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_PROCESS), m_cmdData.strMiCmd.c_str()));
1112 return MIstatus::failure;
1115 const CMICmdArgValListBase::VecArgObjPtr_t &rVecRegNo(pArgRegNo->GetExpectedOptions());
1116 if (!rVecRegNo.empty())
1118 // List of required registers
1119 CMICmdArgValListBase::VecArgObjPtr_t::const_iterator it = rVecRegNo.begin();
1120 while (it != rVecRegNo.end())
1122 const CMICmdArgValNumber *pRegNo = static_cast<CMICmdArgValNumber *>(*it);
1123 const MIuint nRegIndex = pRegNo->GetValue();
1124 lldb::SBValue regValue = GetRegister(nRegIndex);
1125 if (regValue.IsValid())
1127 const bool bOk = AddToOutput(nRegIndex, regValue, eFormat);
1129 return MIstatus::failure;
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++)
1146 lldb::SBValue value = registers.GetValueAtIndex(i);
1147 const MIuint nRegChildren = value.GetNumChildren();
1148 for (MIuint j = 0; j < nRegChildren; j++)
1150 lldb::SBValue regValue = value.GetChildAtIndex(j);
1151 if (regValue.IsValid())
1153 const bool bOk = AddToOutput(nRegIndex, regValue, eFormat);
1155 return MIstatus::failure;
1164 return MIstatus::success;
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.
1172 // Return: MIstatus::success - Functional succeeded.
1173 // MIstatus::failure - Functional failed.
1177 CMICmdCmdDataListRegisterValues::Acknowledge(void)
1179 const CMICmnMIValueResult miValueResult("register-values", m_miValueList);
1180 const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult);
1181 m_miResultRecord = miRecordResult;
1183 return MIstatus::success;
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.
1191 // Return: CMICmdBase * - Pointer to a new command.
1195 CMICmdCmdDataListRegisterValues::CreateSelf(void)
1197 return new CMICmdCmdDataListRegisterValues();
1200 //++ ------------------------------------------------------------------------------------
1201 // Details: Required by the CMICmdFactory when registering *this command. The factory
1202 // calls this function to create an instance of *this command.
1205 // Return: lldb::SBValue - LLDB SBValue object.
1209 CMICmdCmdDataListRegisterValues::GetRegister(const MIuint vRegisterIndex) const
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++)
1218 lldb::SBValue value = registers.GetValueAtIndex(i);
1219 const MIuint nRegChildren = value.GetNumChildren();
1220 if (nRegisterIndex >= nRegChildren)
1222 nRegisterIndex -= nRegChildren;
1226 lldb::SBValue value2 = value.GetChildAtIndex(nRegisterIndex);
1227 if (value2.IsValid())
1233 return lldb::SBValue();
1236 //++ ------------------------------------------------------------------------------------
1237 // Details: Adds the register value to the output list.
1239 // Args: Value of the register, its index and output format.
1244 CMICmdCmdDataListRegisterValues::AddToOutput(const MIuint vnIndex, const lldb::SBValue &vrValue,
1245 CMICmnLLDBDebugSessionInfoVarObj::varFormat_e veVarFormat)
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);
1257 //---------------------------------------------------------------------------------------
1258 //---------------------------------------------------------------------------------------
1259 //---------------------------------------------------------------------------------------
1261 //++ ------------------------------------------------------------------------------------
1262 // Details: CMICmdCmdDataListRegisterChanged constructor.
1268 CMICmdCmdDataListRegisterChanged::CMICmdCmdDataListRegisterChanged(void)
1270 // Command factory matches this name with that received from the stdin stream
1271 m_strMiCmd = "data-list-changed-registers";
1273 // Required by the CMICmdFactory when registering *this command
1274 m_pSelfCreatorFn = &CMICmdCmdDataListRegisterChanged::CreateSelf;
1277 //++ ------------------------------------------------------------------------------------
1278 // Details: CMICmdCmdDataListRegisterChanged destructor.
1279 // Type: Overrideable.
1284 CMICmdCmdDataListRegisterChanged::~CMICmdCmdDataListRegisterChanged(void)
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.
1293 // Return: MIstatus::success - Functional succeeded.
1294 // MIstatus::failure - Functional failed.
1298 CMICmdCmdDataListRegisterChanged::Execute(void)
1302 return MIstatus::success;
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.
1310 // Return: MIstatus::success - Functional succeeded.
1311 // MIstatus::failure - Functional failed.
1315 CMICmdCmdDataListRegisterChanged::Acknowledge(void)
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;
1322 return MIstatus::success;
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.
1330 // Return: CMICmdBase * - Pointer to a new command.
1334 CMICmdCmdDataListRegisterChanged::CreateSelf(void)
1336 return new CMICmdCmdDataListRegisterChanged();
1339 //---------------------------------------------------------------------------------------
1340 //---------------------------------------------------------------------------------------
1341 //---------------------------------------------------------------------------------------
1343 //++ ------------------------------------------------------------------------------------
1344 // Details: CMICmdCmdDataWriteMemoryBytes constructor.
1350 CMICmdCmdDataWriteMemoryBytes::CMICmdCmdDataWriteMemoryBytes(void)
1351 : m_constStrArgThread("thread")
1352 , m_constStrArgAddr("address")
1353 , m_constStrArgContents("contents")
1354 , m_constStrArgCount("count")
1356 // Command factory matches this name with that received from the stdin stream
1357 m_strMiCmd = "data-write-memory-bytes";
1359 // Required by the CMICmdFactory when registering *this command
1360 m_pSelfCreatorFn = &CMICmdCmdDataWriteMemoryBytes::CreateSelf;
1363 //++ ------------------------------------------------------------------------------------
1364 // Details: CMICmdCmdDataWriteMemoryBytes destructor.
1365 // Type: Overrideable.
1370 CMICmdCmdDataWriteMemoryBytes::~CMICmdCmdDataWriteMemoryBytes(void)
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.
1379 // Return: MIstatus::success - Functional succeeded.
1380 // MIstatus::failure - Functional failed.
1384 CMICmdCmdDataWriteMemoryBytes::ParseArgs(void)
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());
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.
1399 // Return: MIstatus::success - Functional succeeded.
1400 // MIstatus::failure - Functional failed.
1404 CMICmdCmdDataWriteMemoryBytes::Execute(void)
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 );
1412 // Numbers extracts as string types as they could be hex numbers
1413 // '&' is not recognised and so has to be removed
1415 return MIstatus::success;
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.
1423 // Return: MIstatus::success - Functional succeeded.
1424 // MIstatus::failure - Functional failed.
1428 CMICmdCmdDataWriteMemoryBytes::Acknowledge(void)
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;
1435 return MIstatus::success;
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.
1443 // Return: CMICmdBase * - Pointer to a new command.
1447 CMICmdCmdDataWriteMemoryBytes::CreateSelf(void)
1449 return new CMICmdCmdDataWriteMemoryBytes();
1452 //---------------------------------------------------------------------------------------
1453 //---------------------------------------------------------------------------------------
1454 //---------------------------------------------------------------------------------------
1456 //++ ------------------------------------------------------------------------------------
1457 // Details: CMICmdCmdDataWriteMemory constructor.
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")
1472 , m_pBufferMemory(nullptr)
1474 // Command factory matches this name with that received from the stdin stream
1475 m_strMiCmd = "data-write-memory";
1477 // Required by the CMICmdFactory when registering *this command
1478 m_pSelfCreatorFn = &CMICmdCmdDataWriteMemory::CreateSelf;
1481 //++ ------------------------------------------------------------------------------------
1482 // Details: CMICmdCmdDataWriteMemory destructor.
1483 // Type: Overrideable.
1488 CMICmdCmdDataWriteMemory::~CMICmdCmdDataWriteMemory(void)
1490 if (m_pBufferMemory != nullptr)
1492 delete[] m_pBufferMemory;
1493 m_pBufferMemory = nullptr;
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.
1502 // Return: MIstatus::success - Functional succeeded.
1503 // MIstatus::failure - Functional failed.
1507 CMICmdCmdDataWriteMemory::ParseArgs(void)
1510 m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgThread, false, false, CMICmdArgValListBase::eArgValType_Number, 1)));
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());
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.
1525 // Return: MIstatus::success - Functional succeeded.
1526 // MIstatus::failure - Functional failed.
1530 CMICmdCmdDataWriteMemory::Execute(void)
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);
1537 MIuint nAddrOffset = 0;
1538 if (pArgOffset->GetFound() && !pArgOffset->GetExpectedOption<CMICmdArgValNumber, MIuint>(nAddrOffset))
1540 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ARGS_ERR_VALIDATION_INVALID), m_cmdData.strMiCmd.c_str(), m_constStrArgAddr.c_str()));
1541 return MIstatus::failure;
1543 m_nAddr = pArgAddr->GetValue();
1544 m_nCount = pArgNumber->GetValue();
1545 const MIuint64 nValue = pArgContents->GetValue();
1547 m_pBufferMemory = new unsigned char[m_nCount];
1548 if (m_pBufferMemory == nullptr)
1550 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_MEMORY_ALLOC_FAILURE), m_cmdData.strMiCmd.c_str(), m_nCount));
1551 return MIstatus::failure;
1553 *m_pBufferMemory = static_cast<char>(nValue);
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))
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;
1568 const bool bOk = error.GetDescription(err);
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;
1575 return MIstatus::success;
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.
1583 // Return: MIstatus::success - Functional succeeded.
1584 // MIstatus::failure - Functional failed.
1588 CMICmdCmdDataWriteMemory::Acknowledge(void)
1590 const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done);
1591 m_miResultRecord = miRecordResult;
1593 return MIstatus::success;
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.
1601 // Return: CMICmdBase * - Pointer to a new command.
1605 CMICmdCmdDataWriteMemory::CreateSelf(void)
1607 return new CMICmdCmdDataWriteMemory();
1610 //---------------------------------------------------------------------------------------
1611 //---------------------------------------------------------------------------------------
1612 //---------------------------------------------------------------------------------------
1614 //++ ------------------------------------------------------------------------------------
1615 // Details: CMICmdCmdDataInfoLine constructor.
1621 CMICmdCmdDataInfoLine::CMICmdCmdDataInfoLine(void)
1622 : m_constStrArgLocation("location")
1624 // Command factory matches this name with that received from the stdin stream
1625 m_strMiCmd = "data-info-line";
1627 // Required by the CMICmdFactory when registering *this command
1628 m_pSelfCreatorFn = &CMICmdCmdDataInfoLine::CreateSelf;
1631 //++ ------------------------------------------------------------------------------------
1632 // Details: CMICmdCmdDataInfoLine destructor.
1633 // Type: Overrideable.
1638 CMICmdCmdDataInfoLine::~CMICmdCmdDataInfoLine(void)
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.
1647 // Return: MIstatus::success - Functional succeeded.
1648 // MIstatus::failure - Functional failed.
1652 CMICmdCmdDataInfoLine::ParseArgs(void)
1654 bool bOk = m_setCmdArgs.Add(*(new CMICmdArgValString(m_constStrArgLocation, true, true)));
1655 return (bOk && ParseValidateCmdOptions());
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.
1663 // Return: MIstatus::success - Functional succeeded.
1664 // MIstatus::failure - Functional failed.
1668 CMICmdCmdDataInfoLine::Execute(void)
1670 CMICMDBASE_GETOPTION(pArgLocation, String, m_constStrArgLocation);
1672 const CMIUtilString &strLocation(pArgLocation->GetValue());
1673 CMIUtilString strCmdOptionsLocation;
1674 if (strLocation.at(0) == '*')
1678 // ^^^^^^^ -- address
1679 const CMIUtilString strAddress(strLocation.c_str() + 1);
1680 strCmdOptionsLocation = CMIUtilString::Format("--address %s", strAddress.c_str());
1684 const size_t nLineStartPos = strLocation.rfind(':');
1685 if ((nLineStartPos == std::string::npos) || (nLineStartPos == 0) || (nLineStartPos == strLocation.length() - 1))
1687 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_LOCATION_FORMAT), m_cmdData.strMiCmd.c_str(), strLocation.c_str())
1689 return MIstatus::failure;
1693 // ^^^^^^^^^ -- file
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());
1699 const CMIUtilString strCmd(CMIUtilString::Format("target modules lookup -v %s", strCmdOptionsLocation.c_str()));
1701 CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
1702 const lldb::ReturnStatus rtn = rSessionInfo.GetDebugger().GetCommandInterpreter().HandleCommand(strCmd.c_str(), m_lldbResult);
1705 return MIstatus::success;
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.
1713 // Return: MIstatus::success - Functional succeeded.
1714 // MIstatus::failure - Functional failed.
1718 CMICmdCmdDataInfoLine::Acknowledge(void)
1720 if (m_lldbResult.GetErrorSize() > 0)
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;
1728 else if (m_lldbResult.GetOutputSize() > 0)
1730 CMIUtilString::VecString_t vecLines;
1731 const CMIUtilString strLldbMsg(m_lldbResult.GetOutput());
1732 const MIuint nLines(strLldbMsg.SplitLines(vecLines));
1734 for (MIuint i = 0; i < nLines; ++i)
1736 // String looks like:
1737 // LineEntry: \[0x0000000100000f37-0x0000000100000f45\): /path/to/file:3[:1]
1738 const CMIUtilString &rLine(vecLines[i]);
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());
1747 // Skip all except LineEntry
1748 if (!CMIUtilString::Compare(strProperty, "LineEntry"))
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);
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);
1770 return MIstatus::failure;
1772 // LineEntry: \[0x0000000100000f37-0x0000000100000f45\): /path/to/file:3[:1]
1773 // ^^^^^^^^^^^^^ -- file
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);
1786 return MIstatus::failure;
1788 // LineEntry: \[0x0000000100000f37-0x0000000100000f45\): /path/to/file:3[:1]
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);
1799 return MIstatus::failure;
1801 // MI print "%s^done,start=\"%d\",end=\"%d\"",file=\"%s\",line=\"%d\"
1802 m_miResultRecord = miRecordResult;
1804 return MIstatus::success;
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;
1814 return MIstatus::success;
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.
1822 // Return: CMICmdBase * - Pointer to a new command.
1826 CMICmdCmdDataInfoLine::CreateSelf(void)
1828 return new CMICmdCmdDataInfoLine();