| //===-- MICmdCmdData.cpp ----------------------------------------*- C++ -*-===// | 
 | // | 
 | //                     The LLVM Compiler Infrastructure | 
 | // | 
 | // This file is distributed under the University of Illinois Open Source | 
 | // License. See LICENSE.TXT for details. | 
 | // | 
 | //===----------------------------------------------------------------------===// | 
 |  | 
 | // Overview:    CMICmdCmdDataEvaluateExpression     implementation. | 
 | //              CMICmdCmdDataDisassemble            implementation. | 
 | //              CMICmdCmdDataReadMemoryBytes        implementation. | 
 | //              CMICmdCmdDataReadMemory             implementation. | 
 | //              CMICmdCmdDataListRegisterNames      implementation. | 
 | //              CMICmdCmdDataListRegisterValues     implementation. | 
 | //              CMICmdCmdDataListRegisterChanged    implementation. | 
 | //              CMICmdCmdDataWriteMemoryBytes       implementation. | 
 | //              CMICmdCmdDataWriteMemory            implementation. | 
 | //              CMICmdCmdDataInfoLine               implementation. | 
 |  | 
 | // Third Party Headers: | 
 | #include "lldb/API/SBInstruction.h" | 
 | #include "lldb/API/SBInstructionList.h" | 
 | #include "lldb/API/SBStream.h" | 
 | #include "lldb/API/SBThread.h" | 
 | #include "llvm/ADT/Twine.h" | 
 | #include "llvm/ADT/StringRef.h" | 
 | #include <inttypes.h> // For PRIx64 | 
 | #include <string> | 
 |  | 
 | // In-house headers: | 
 | #include "MICmdArgValConsume.h" | 
 | #include "MICmdArgValListOfN.h" | 
 | #include "MICmdArgValNumber.h" | 
 | #include "MICmdArgValOptionLong.h" | 
 | #include "MICmdArgValOptionShort.h" | 
 | #include "MICmdArgValString.h" | 
 | #include "MICmdArgValThreadGrp.h" | 
 | #include "MICmdCmdData.h" | 
 | #include "MICmnLLDBDebugSessionInfo.h" | 
 | #include "MICmnLLDBDebugSessionInfoVarObj.h" | 
 | #include "MICmnLLDBDebugger.h" | 
 | #include "MICmnLLDBProxySBValue.h" | 
 | #include "MICmnLLDBUtilSBValue.h" | 
 | #include "MICmnMIResultRecord.h" | 
 | #include "MICmnMIValueConst.h" | 
 | #include "Platform.h" | 
 |  | 
 | namespace { | 
 | CMIUtilString IntToHexAddrStr(uint32_t number) { | 
 |   return CMIUtilString("0x" + llvm::Twine::utohexstr(number).str()); | 
 | } | 
 | } // namespace | 
 |  | 
 | //++ | 
 | //------------------------------------------------------------------------------------ | 
 | // Details: CMICmdCmdDataEvaluateExpression constructor. | 
 | // Type:    Method. | 
 | // Args:    None. | 
 | // Return:  None. | 
 | // Throws:  None. | 
 | //-- | 
 | CMICmdCmdDataEvaluateExpression::CMICmdCmdDataEvaluateExpression() | 
 |     : m_bExpressionValid(true), m_bEvaluatedExpression(true), m_strValue("??"), | 
 |       m_bFoundInvalidChar(false), m_cExpressionInvalidChar(0x00), | 
 |       m_constStrArgExpr("expr") { | 
 |   // Command factory matches this name with that received from the stdin stream | 
 |   m_strMiCmd = "data-evaluate-expression"; | 
 |  | 
 |   // Required by the CMICmdFactory when registering *this command | 
 |   m_pSelfCreatorFn = &CMICmdCmdDataEvaluateExpression::CreateSelf; | 
 | } | 
 |  | 
 | //++ | 
 | //------------------------------------------------------------------------------------ | 
 | // Details: CMICmdCmdDataEvaluateExpression destructor. | 
 | // Type:    Overrideable. | 
 | // Args:    None. | 
 | // Return:  None. | 
 | // Throws:  None. | 
 | //-- | 
 | CMICmdCmdDataEvaluateExpression::~CMICmdCmdDataEvaluateExpression() {} | 
 |  | 
 | //++ | 
 | //------------------------------------------------------------------------------------ | 
 | // Details: The invoker requires this function. The parses the command line | 
 | // options | 
 | //          arguments to extract values for each of those arguments. | 
 | // Type:    Overridden. | 
 | // Args:    None. | 
 | // Return:  MIstatus::success - Functional succeeded. | 
 | //          MIstatus::failure - Functional failed. | 
 | // Throws:  None. | 
 | //-- | 
 | bool CMICmdCmdDataEvaluateExpression::ParseArgs() { | 
 |   m_setCmdArgs.Add( | 
 |       new CMICmdArgValString(m_constStrArgExpr, true, true, true, true)); | 
 |   return ParseValidateCmdOptions(); | 
 | } | 
 |  | 
 | //++ | 
 | //------------------------------------------------------------------------------------ | 
 | // Details: The invoker requires this function. The command does work in this | 
 | // function. | 
 | //          The command is likely to communicate with the LLDB SBDebugger in | 
 | //          here. | 
 | // Type:    Overridden. | 
 | // Args:    None. | 
 | // Return:  MIstatus::success - Functional succeeded. | 
 | //          MIstatus::failure - Functional failed. | 
 | // Throws:  None. | 
 | //-- | 
 | bool CMICmdCmdDataEvaluateExpression::Execute() { | 
 |   CMICMDBASE_GETOPTION(pArgExpr, String, m_constStrArgExpr); | 
 |  | 
 |   const CMIUtilString &rExpression(pArgExpr->GetValue()); | 
 |   CMICmnLLDBDebugSessionInfo &rSessionInfo( | 
 |       CMICmnLLDBDebugSessionInfo::Instance()); | 
 |   lldb::SBProcess sbProcess = rSessionInfo.GetProcess(); | 
 |   lldb::SBThread thread = sbProcess.GetSelectedThread(); | 
 |   m_bExpressionValid = (thread.GetNumFrames() > 0); | 
 |   if (!m_bExpressionValid) | 
 |     return MIstatus::success; | 
 |  | 
 |   lldb::SBFrame frame = thread.GetSelectedFrame(); | 
 |   lldb::SBValue value = frame.EvaluateExpression(rExpression.c_str()); | 
 |   m_Error = value.GetError(); | 
 |   if (!value.IsValid() || m_Error.Fail()) | 
 |     value = frame.FindVariable(rExpression.c_str()); | 
 |   const CMICmnLLDBUtilSBValue utilValue(value, true); | 
 |   if (!utilValue.IsValid() || utilValue.IsValueUnknown()) { | 
 |     m_bEvaluatedExpression = false; | 
 |     return MIstatus::success; | 
 |   } | 
 |   if (!utilValue.HasName()) { | 
 |     if (HaveInvalidCharacterInExpression(rExpression, | 
 |                                          m_cExpressionInvalidChar)) { | 
 |       m_bFoundInvalidChar = true; | 
 |       return MIstatus::success; | 
 |     } | 
 |  | 
 |     m_strValue = rExpression; | 
 |     return MIstatus::success; | 
 |   } | 
 |   if (rExpression.IsQuoted()) { | 
 |     m_strValue = rExpression.Trim('\"'); | 
 |     return MIstatus::success; | 
 |   } | 
 |   m_strValue = utilValue.GetValue(true).Escape().AddSlashes(); | 
 |   return MIstatus::success; | 
 | } | 
 |  | 
 | //++ | 
 | //------------------------------------------------------------------------------------ | 
 | // Details: The invoker requires this function. The command prepares a MI Record | 
 | // Result | 
 | //          for the work carried out in the Execute(). | 
 | // Type:    Overridden. | 
 | // Args:    None. | 
 | // Return:  MIstatus::success - Functional succeeded. | 
 | //          MIstatus::failure - Functional failed. | 
 | // Throws:  None. | 
 | //-- | 
 | bool CMICmdCmdDataEvaluateExpression::Acknowledge() { | 
 |   if (m_bExpressionValid) { | 
 |     if (m_bEvaluatedExpression) { | 
 |       if (m_bFoundInvalidChar) { | 
 |         const CMICmnMIValueConst miValueConst(CMIUtilString::Format( | 
 |             "Invalid character '%c' in expression", m_cExpressionInvalidChar)); | 
 |         const CMICmnMIValueResult miValueResult("msg", miValueConst); | 
 |         const CMICmnMIResultRecord miRecordResult( | 
 |             m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, | 
 |             miValueResult); | 
 |         m_miResultRecord = miRecordResult; | 
 |         return MIstatus::success; | 
 |       } | 
 |  | 
 |       const CMICmnMIValueConst miValueConst(m_strValue); | 
 |       const CMICmnMIValueResult miValueResult("value", miValueConst); | 
 |       const CMICmnMIResultRecord miRecordResult( | 
 |           m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, | 
 |           miValueResult); | 
 |       m_miResultRecord = miRecordResult; | 
 |       return MIstatus::success; | 
 |     } | 
 |     CMIUtilString mi_error_msg = "Could not evaluate expression"; | 
 |     if (const char *err_msg = m_Error.GetCString()) | 
 |       mi_error_msg = err_msg; | 
 |     const CMICmnMIValueConst miValueConst(mi_error_msg.Escape(true)); | 
 |     const CMICmnMIValueResult miValueResult("msg", miValueConst); | 
 |     const CMICmnMIResultRecord miRecordResult( | 
 |         m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, | 
 |         miValueResult); | 
 |     m_miResultRecord = miRecordResult; | 
 |     return MIstatus::success; | 
 |   } | 
 |  | 
 |   const CMICmnMIValueConst miValueConst("Invalid expression"); | 
 |   const CMICmnMIValueResult miValueResult("msg", miValueConst); | 
 |   const CMICmnMIResultRecord miRecordResult( | 
 |       m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, | 
 |       miValueResult); | 
 |   m_miResultRecord = miRecordResult; | 
 |  | 
 |   return MIstatus::success; | 
 | } | 
 |  | 
 | //++ | 
 | //------------------------------------------------------------------------------------ | 
 | // Details: Required by the CMICmdFactory when registering *this command. The | 
 | // factory | 
 | //          calls this function to create an instance of *this command. | 
 | // Type:    Static method. | 
 | // Args:    None. | 
 | // Return:  CMICmdBase * - Pointer to a new command. | 
 | // Throws:  None. | 
 | //-- | 
 | CMICmdBase *CMICmdCmdDataEvaluateExpression::CreateSelf() { | 
 |   return new CMICmdCmdDataEvaluateExpression(); | 
 | } | 
 |  | 
 | //++ | 
 | //------------------------------------------------------------------------------------ | 
 | // Details: Examine the expression string to see if it contains invalid | 
 | // characters. | 
 | // Type:    Method. | 
 | // Args:    vrExpr          - (R) Expression string given to *this command. | 
 | //          vrwInvalidChar  - (W) True = Invalid character found, false = | 
 | //          nothing found. | 
 | // Return:  bool - True = Invalid character found, false = nothing found. | 
 | // Throws:  None. | 
 | //-- | 
 | bool CMICmdCmdDataEvaluateExpression::HaveInvalidCharacterInExpression( | 
 |     const CMIUtilString &vrExpr, char &vrwInvalidChar) { | 
 |   static const std::string strInvalidCharacters(";#\\"); | 
 |   const size_t nInvalidCharacterOffset = | 
 |       vrExpr.find_first_of(strInvalidCharacters); | 
 |   const bool bFoundInvalidCharInExpression = | 
 |       (nInvalidCharacterOffset != CMIUtilString::npos); | 
 |   vrwInvalidChar = | 
 |       bFoundInvalidCharInExpression ? vrExpr[nInvalidCharacterOffset] : 0x00; | 
 |   return bFoundInvalidCharInExpression; | 
 | } | 
 |  | 
 | //--------------------------------------------------------------------------------------- | 
 | //--------------------------------------------------------------------------------------- | 
 | //--------------------------------------------------------------------------------------- | 
 |  | 
 | //++ | 
 | //------------------------------------------------------------------------------------ | 
 | // Details: CMICmdCmdDataDisassemble constructor. | 
 | // Type:    Method. | 
 | // Args:    None. | 
 | // Return:  None. | 
 | // Throws:  None. | 
 | //-- | 
 | CMICmdCmdDataDisassemble::CMICmdCmdDataDisassemble() | 
 |     : m_constStrArgAddrStart("s"), m_constStrArgAddrEnd("e"), | 
 |       m_constStrArgMode("mode"), m_miValueList(true) { | 
 |   // Command factory matches this name with that received from the stdin stream | 
 |   m_strMiCmd = "data-disassemble"; | 
 |  | 
 |   // Required by the CMICmdFactory when registering *this command | 
 |   m_pSelfCreatorFn = &CMICmdCmdDataDisassemble::CreateSelf; | 
 | } | 
 |  | 
 | //++ | 
 | //------------------------------------------------------------------------------------ | 
 | // Details: CMICmdCmdDataDisassemble destructor. | 
 | // Type:    Overrideable. | 
 | // Args:    None. | 
 | // Return:  None. | 
 | // Throws:  None. | 
 | //-- | 
 | CMICmdCmdDataDisassemble::~CMICmdCmdDataDisassemble() {} | 
 |  | 
 | //++ | 
 | //------------------------------------------------------------------------------------ | 
 | // Details: The invoker requires this function. The parses the command line | 
 | // options | 
 | //          arguments to extract values for each of those arguments. | 
 | // Type:    Overridden. | 
 | // Args:    None. | 
 | // Return:  MIstatus::success - Functional succeeded. | 
 | //          MIstatus::failure - Functional failed. | 
 | // Throws:  None. | 
 | //-- | 
 | bool CMICmdCmdDataDisassemble::ParseArgs() { | 
 |   m_setCmdArgs.Add(new CMICmdArgValOptionShort( | 
 |       m_constStrArgAddrStart, true, true, | 
 |       CMICmdArgValListBase::eArgValType_StringQuotedNumber, 1)); | 
 |   m_setCmdArgs.Add(new CMICmdArgValOptionShort( | 
 |       m_constStrArgAddrEnd, true, true, | 
 |       CMICmdArgValListBase::eArgValType_StringQuotedNumber, 1)); | 
 |   m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgMode, true, true)); | 
 |   return ParseValidateCmdOptions(); | 
 | } | 
 |  | 
 | //++ | 
 | //------------------------------------------------------------------------------------ | 
 | // Details: The invoker requires this function. The command does work in this | 
 | // function. | 
 | //          The command is likely to communicate with the LLDB SBDebugger in | 
 | //          here. | 
 | // Type:    Overridden. | 
 | // Args:    None. | 
 | // Return:  MIstatus::success - Functional succeeded. | 
 | //          MIstatus::failure - Functional failed. | 
 | // Throws:  None. | 
 | //-- | 
 | bool CMICmdCmdDataDisassemble::Execute() { | 
 |   CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread); | 
 |   CMICMDBASE_GETOPTION(pArgAddrStart, OptionShort, m_constStrArgAddrStart); | 
 |   CMICMDBASE_GETOPTION(pArgAddrEnd, OptionShort, m_constStrArgAddrEnd); | 
 |   CMICMDBASE_GETOPTION(pArgMode, Number, m_constStrArgMode); | 
 |  | 
 |   // Retrieve the --thread option's thread ID (only 1) | 
 |   MIuint64 nThreadId = UINT64_MAX; | 
 |   if (pArgThread->GetFound() && | 
 |       !pArgThread->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nThreadId)) { | 
 |     SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_THREAD_INVALID), | 
 |                                    m_cmdData.strMiCmd.c_str(), | 
 |                                    m_constStrArgThread.c_str())); | 
 |     return MIstatus::failure; | 
 |   } | 
 |   CMIUtilString strAddrStart; | 
 |   if (!pArgAddrStart->GetExpectedOption<CMICmdArgValString, CMIUtilString>( | 
 |           strAddrStart)) { | 
 |     SetError(CMIUtilString::Format( | 
 |         MIRSRC(IDS_CMD_ERR_DISASM_ADDR_START_INVALID), | 
 |         m_cmdData.strMiCmd.c_str(), m_constStrArgAddrStart.c_str())); | 
 |     return MIstatus::failure; | 
 |   } | 
 |   MIint64 nAddrStart = 0; | 
 |   if (!strAddrStart.ExtractNumber(nAddrStart)) { | 
 |     SetError(CMIUtilString::Format( | 
 |         MIRSRC(IDS_CMD_ERR_DISASM_ADDR_START_INVALID), | 
 |         m_cmdData.strMiCmd.c_str(), m_constStrArgAddrStart.c_str())); | 
 |     return MIstatus::failure; | 
 |   } | 
 |  | 
 |   CMIUtilString strAddrEnd; | 
 |   if (!pArgAddrEnd->GetExpectedOption<CMICmdArgValString, CMIUtilString>( | 
 |           strAddrEnd)) { | 
 |     SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_DISASM_ADDR_END_INVALID), | 
 |                                    m_cmdData.strMiCmd.c_str(), | 
 |                                    m_constStrArgAddrEnd.c_str())); | 
 |     return MIstatus::failure; | 
 |   } | 
 |   MIint64 nAddrEnd = 0; | 
 |   if (!strAddrEnd.ExtractNumber(nAddrEnd)) { | 
 |     SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_DISASM_ADDR_END_INVALID), | 
 |                                    m_cmdData.strMiCmd.c_str(), | 
 |                                    m_constStrArgAddrEnd.c_str())); | 
 |     return MIstatus::failure; | 
 |   } | 
 |   const MIuint nDisasmMode = pArgMode->GetValue(); | 
 |  | 
 |   CMICmnLLDBDebugSessionInfo &rSessionInfo( | 
 |       CMICmnLLDBDebugSessionInfo::Instance()); | 
 |   lldb::SBTarget sbTarget = rSessionInfo.GetTarget(); | 
 |   lldb::addr_t lldbStartAddr = static_cast<lldb::addr_t>(nAddrStart); | 
 |   lldb::SBInstructionList instructions = sbTarget.ReadInstructions( | 
 |       lldb::SBAddress(lldbStartAddr, sbTarget), nAddrEnd - nAddrStart); | 
 |   const MIuint nInstructions = instructions.GetSize(); | 
 |   // Calculate the offset of first instruction so that we can generate offset | 
 |   // starting at 0 | 
 |   lldb::addr_t start_offset = 0; | 
 |   if (nInstructions > 0) | 
 |     start_offset = | 
 |         instructions.GetInstructionAtIndex(0).GetAddress().GetOffset(); | 
 |  | 
 |   for (size_t i = 0; i < nInstructions; i++) { | 
 |     const char *pUnknown = "??"; | 
 |     lldb::SBInstruction instrt = instructions.GetInstructionAtIndex(i); | 
 |     const char *pStrMnemonic = instrt.GetMnemonic(sbTarget); | 
 |     pStrMnemonic = (pStrMnemonic != nullptr) ? pStrMnemonic : pUnknown; | 
 |     const char *pStrComment = instrt.GetComment(sbTarget); | 
 |     CMIUtilString strComment; | 
 |     if (pStrComment != nullptr && *pStrComment != '\0') | 
 |       strComment = CMIUtilString::Format("; %s", pStrComment); | 
 |     lldb::SBAddress address = instrt.GetAddress(); | 
 |     lldb::addr_t addr = address.GetLoadAddress(sbTarget); | 
 |     const char *pFnName = address.GetFunction().GetName(); | 
 |     pFnName = (pFnName != nullptr) ? pFnName : pUnknown; | 
 |     lldb::addr_t addrOffSet = address.GetOffset() - start_offset; | 
 |     const char *pStrOperands = instrt.GetOperands(sbTarget); | 
 |     pStrOperands = (pStrOperands != nullptr) ? pStrOperands : pUnknown; | 
 |     const size_t instrtSize = instrt.GetByteSize(); | 
 |  | 
 |     // MI "{address=\"0x%016" PRIx64 | 
 |     // "\",func-name=\"%s\",offset=\"%lld\",inst=\"%s %s\"}" | 
 |     const CMICmnMIValueConst miValueConst( | 
 |         CMIUtilString::Format("0x%016" PRIx64, addr)); | 
 |     const CMICmnMIValueResult miValueResult("address", miValueConst); | 
 |     CMICmnMIValueTuple miValueTuple(miValueResult); | 
 |     const CMICmnMIValueConst miValueConst2(pFnName); | 
 |     const CMICmnMIValueResult miValueResult2("func-name", miValueConst2); | 
 |     miValueTuple.Add(miValueResult2); | 
 |     const CMICmnMIValueConst miValueConst3( | 
 |         CMIUtilString::Format("%lld", addrOffSet)); | 
 |     const CMICmnMIValueResult miValueResult3("offset", miValueConst3); | 
 |     miValueTuple.Add(miValueResult3); | 
 |     const CMICmnMIValueConst miValueConst4( | 
 |         CMIUtilString::Format("%d", instrtSize)); | 
 |     const CMICmnMIValueResult miValueResult4("size", miValueConst4); | 
 |     miValueTuple.Add(miValueResult4); | 
 |     const CMICmnMIValueConst miValueConst5( | 
 |         CMIUtilString::Format("%s %s%s", pStrMnemonic, pStrOperands, | 
 |                               strComment.Escape(true).c_str())); | 
 |     const CMICmnMIValueResult miValueResult5("inst", miValueConst5); | 
 |     miValueTuple.Add(miValueResult5); | 
 |  | 
 |     if (nDisasmMode == 1) { | 
 |       lldb::SBLineEntry lineEntry = address.GetLineEntry(); | 
 |       const MIuint nLine = lineEntry.GetLine(); | 
 |       const char *pFileName = lineEntry.GetFileSpec().GetFilename(); | 
 |       pFileName = (pFileName != nullptr) ? pFileName : pUnknown; | 
 |  | 
 |       // MI "src_and_asm_line={line=\"%u\",file=\"%s\",line_asm_insn=[ ]}" | 
 |       const CMICmnMIValueConst miValueConst( | 
 |           CMIUtilString::Format("0x%u", nLine)); | 
 |       const CMICmnMIValueResult miValueResult("line", miValueConst); | 
 |       CMICmnMIValueTuple miValueTuple2(miValueResult); | 
 |       const CMICmnMIValueConst miValueConst2(pFileName); | 
 |       const CMICmnMIValueResult miValueResult2("file", miValueConst2); | 
 |       miValueTuple2.Add(miValueResult2); | 
 |       const CMICmnMIValueList miValueList(miValueTuple); | 
 |       const CMICmnMIValueResult miValueResult3("line_asm_insn", miValueList); | 
 |       miValueTuple2.Add(miValueResult3); | 
 |       const CMICmnMIValueResult miValueResult4("src_and_asm_line", | 
 |                                                miValueTuple2); | 
 |       m_miValueList.Add(miValueResult4); | 
 |     } else { | 
 |       m_miValueList.Add(miValueTuple); | 
 |     } | 
 |   } | 
 |  | 
 |   return MIstatus::success; | 
 | } | 
 |  | 
 | //++ | 
 | //------------------------------------------------------------------------------------ | 
 | // Details: The invoker requires this function. The command prepares a MI Record | 
 | // Result | 
 | //          for the work carried out in the Execute(). | 
 | // Type:    Overridden. | 
 | // Args:    None. | 
 | // Return:  MIstatus::success - Functional succeeded. | 
 | //          MIstatus::failure - Functional failed. | 
 | // Throws:  None. | 
 | //-- | 
 | bool CMICmdCmdDataDisassemble::Acknowledge() { | 
 |   const CMICmnMIValueResult miValueResult("asm_insns", m_miValueList); | 
 |   const CMICmnMIResultRecord miRecordResult( | 
 |       m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, | 
 |       miValueResult); | 
 |   m_miResultRecord = miRecordResult; | 
 |  | 
 |   return MIstatus::success; | 
 | } | 
 |  | 
 | //++ | 
 | //------------------------------------------------------------------------------------ | 
 | // Details: Required by the CMICmdFactory when registering *this command. The | 
 | // factory | 
 | //          calls this function to create an instance of *this command. | 
 | // Type:    Static method. | 
 | // Args:    None. | 
 | // Return:  CMICmdBase * - Pointer to a new command. | 
 | // Throws:  None. | 
 | //-- | 
 | CMICmdBase *CMICmdCmdDataDisassemble::CreateSelf() { | 
 |   return new CMICmdCmdDataDisassemble(); | 
 | } | 
 |  | 
 | //--------------------------------------------------------------------------------------- | 
 | //--------------------------------------------------------------------------------------- | 
 | //--------------------------------------------------------------------------------------- | 
 |  | 
 | //++ | 
 | //------------------------------------------------------------------------------------ | 
 | // Details: CMICmdCmdDataReadMemoryBytes constructor. | 
 | // Type:    Method. | 
 | // Args:    None. | 
 | // Return:  None. | 
 | // Throws:  None. | 
 | //-- | 
 | CMICmdCmdDataReadMemoryBytes::CMICmdCmdDataReadMemoryBytes() | 
 |     : m_constStrArgByteOffset("o"), m_constStrArgAddrExpr("address"), | 
 |       m_constStrArgNumBytes("count"), m_pBufferMemory(nullptr), m_nAddrStart(0), | 
 |       m_nAddrNumBytesToRead(0) { | 
 |   // Command factory matches this name with that received from the stdin stream | 
 |   m_strMiCmd = "data-read-memory-bytes"; | 
 |  | 
 |   // Required by the CMICmdFactory when registering *this command | 
 |   m_pSelfCreatorFn = &CMICmdCmdDataReadMemoryBytes::CreateSelf; | 
 | } | 
 |  | 
 | //++ | 
 | //------------------------------------------------------------------------------------ | 
 | // Details: CMICmdCmdDataReadMemoryBytes destructor. | 
 | // Type:    Overrideable. | 
 | // Args:    None. | 
 | // Return:  None. | 
 | // Throws:  None. | 
 | //-- | 
 | CMICmdCmdDataReadMemoryBytes::~CMICmdCmdDataReadMemoryBytes() { | 
 |   if (m_pBufferMemory != nullptr) { | 
 |     delete[] m_pBufferMemory; | 
 |     m_pBufferMemory = nullptr; | 
 |   } | 
 | } | 
 |  | 
 | //++ | 
 | //------------------------------------------------------------------------------------ | 
 | // Details: The invoker requires this function. The parses the command line | 
 | // options | 
 | //          arguments to extract values for each of those arguments. | 
 | // Type:    Overridden. | 
 | // Args:    None. | 
 | // Return:  MIstatus::success - Functional succeeded. | 
 | //          MIstatus::failure - Functional failed. | 
 | // Throws:  None. | 
 | //-- | 
 | bool CMICmdCmdDataReadMemoryBytes::ParseArgs() { | 
 |   m_setCmdArgs.Add( | 
 |       new CMICmdArgValOptionShort(m_constStrArgByteOffset, false, true, | 
 |                                   CMICmdArgValListBase::eArgValType_Number, 1)); | 
 |   m_setCmdArgs.Add( | 
 |       new CMICmdArgValString(m_constStrArgAddrExpr, true, true, true, true)); | 
 |   m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgNumBytes, true, true)); | 
 |   return ParseValidateCmdOptions(); | 
 | } | 
 |  | 
 | //++ | 
 | //------------------------------------------------------------------------------------ | 
 | // Details: The invoker requires this function. The command does work in this | 
 | // function. | 
 | //          The command is likely to communicate with the LLDB SBDebugger in | 
 | //          here. | 
 | // Type:    Overridden. | 
 | // Args:    None. | 
 | // Return:  MIstatus::success - Function succeeded. | 
 | //          MIstatus::failure - Function failed. | 
 | // Throws:  None. | 
 | //-- | 
 | bool CMICmdCmdDataReadMemoryBytes::Execute() { | 
 |   CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread); | 
 |   CMICMDBASE_GETOPTION(pArgFrame, OptionLong, m_constStrArgFrame); | 
 |   CMICMDBASE_GETOPTION(pArgAddrOffset, OptionShort, m_constStrArgByteOffset); | 
 |   CMICMDBASE_GETOPTION(pArgAddrExpr, String, m_constStrArgAddrExpr); | 
 |   CMICMDBASE_GETOPTION(pArgNumBytes, Number, m_constStrArgNumBytes); | 
 |  | 
 |   // get the --thread option value | 
 |   MIuint64 nThreadId = UINT64_MAX; | 
 |   if (pArgThread->GetFound() && | 
 |       !pArgThread->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nThreadId)) { | 
 |     SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND), | 
 |                                    m_cmdData.strMiCmd.c_str(), | 
 |                                    m_constStrArgThread.c_str())); | 
 |     return MIstatus::failure; | 
 |   } | 
 |  | 
 |   // get the --frame option value | 
 |   MIuint64 nFrame = UINT64_MAX; | 
 |   if (pArgFrame->GetFound() && | 
 |       !pArgFrame->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nFrame)) { | 
 |     SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND), | 
 |                                    m_cmdData.strMiCmd.c_str(), | 
 |                                    m_constStrArgFrame.c_str())); | 
 |     return MIstatus::failure; | 
 |   } | 
 |  | 
 |   // get the -o option value | 
 |   MIuint64 nAddrOffset = 0; | 
 |   if (pArgAddrOffset->GetFound() && | 
 |       !pArgAddrOffset->GetExpectedOption<CMICmdArgValNumber, MIuint64>( | 
 |           nAddrOffset)) { | 
 |     SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND), | 
 |                                    m_cmdData.strMiCmd.c_str(), | 
 |                                    m_constStrArgByteOffset.c_str())); | 
 |     return MIstatus::failure; | 
 |   } | 
 |  | 
 |   CMICmnLLDBDebugSessionInfo &rSessionInfo( | 
 |       CMICmnLLDBDebugSessionInfo::Instance()); | 
 |   lldb::SBProcess sbProcess = rSessionInfo.GetProcess(); | 
 |   if (!sbProcess.IsValid()) { | 
 |     SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_PROCESS), | 
 |                                    m_cmdData.strMiCmd.c_str())); | 
 |     return MIstatus::failure; | 
 |   } | 
 |  | 
 |   lldb::SBThread thread = (nThreadId != UINT64_MAX) | 
 |                               ? sbProcess.GetThreadByIndexID(nThreadId) | 
 |                               : sbProcess.GetSelectedThread(); | 
 |   if (!thread.IsValid()) { | 
 |     SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_THREAD_INVALID), | 
 |                                    m_cmdData.strMiCmd.c_str())); | 
 |     return MIstatus::failure; | 
 |   } | 
 |  | 
 |   lldb::SBFrame frame = (nFrame != UINT64_MAX) ? thread.GetFrameAtIndex(nFrame) | 
 |                                                : thread.GetSelectedFrame(); | 
 |   if (!frame.IsValid()) { | 
 |     SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_FRAME_INVALID), | 
 |                                    m_cmdData.strMiCmd.c_str())); | 
 |     return MIstatus::failure; | 
 |   } | 
 |  | 
 |   const CMIUtilString &rAddrExpr = pArgAddrExpr->GetValue(); | 
 |   lldb::SBValue addrExprValue = frame.EvaluateExpression(rAddrExpr.c_str()); | 
 |   lldb::SBError error = addrExprValue.GetError(); | 
 |   if (error.Fail()) { | 
 |     SetError(error.GetCString()); | 
 |     return MIstatus::failure; | 
 |   } else if (!addrExprValue.IsValid()) { | 
 |     SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_EXPR_INVALID), | 
 |                                    rAddrExpr.c_str())); | 
 |     return MIstatus::failure; | 
 |   } | 
 |  | 
 |   MIuint64 nAddrStart = 0; | 
 |   if (!CMICmnLLDBProxySBValue::GetValueAsUnsigned(addrExprValue, nAddrStart)) { | 
 |     SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_EXPR_INVALID), | 
 |                                    rAddrExpr.c_str())); | 
 |     return MIstatus::failure; | 
 |   } | 
 |  | 
 |   nAddrStart += nAddrOffset; | 
 |   const MIuint64 nAddrNumBytes = pArgNumBytes->GetValue(); | 
 |  | 
 |   m_pBufferMemory = new unsigned char[nAddrNumBytes]; | 
 |   if (m_pBufferMemory == nullptr) { | 
 |     SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_MEMORY_ALLOC_FAILURE), | 
 |                                    m_cmdData.strMiCmd.c_str(), nAddrNumBytes)); | 
 |     return MIstatus::failure; | 
 |   } | 
 |  | 
 |   const MIuint64 nReadBytes = | 
 |       sbProcess.ReadMemory(static_cast<lldb::addr_t>(nAddrStart), | 
 |                            (void *)m_pBufferMemory, nAddrNumBytes, error); | 
 |   if (nReadBytes != nAddrNumBytes) { | 
 |     SetError(CMIUtilString::Format( | 
 |         MIRSRC(IDS_CMD_ERR_LLDB_ERR_NOT_READ_WHOLE_BLK), | 
 |         m_cmdData.strMiCmd.c_str(), nAddrNumBytes, nAddrStart)); | 
 |     return MIstatus::failure; | 
 |   } | 
 |   if (error.Fail()) { | 
 |     lldb::SBStream err; | 
 |     const bool bOk = error.GetDescription(err); | 
 |     MIunused(bOk); | 
 |     SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_LLDB_ERR_READ_MEM_BYTES), | 
 |                                    m_cmdData.strMiCmd.c_str(), nAddrNumBytes, | 
 |                                    nAddrStart, err.GetData())); | 
 |     return MIstatus::failure; | 
 |   } | 
 |  | 
 |   m_nAddrStart = nAddrStart; | 
 |   m_nAddrNumBytesToRead = nAddrNumBytes; | 
 |  | 
 |   return MIstatus::success; | 
 | } | 
 |  | 
 | //++ | 
 | //------------------------------------------------------------------------------------ | 
 | // Details: The invoker requires this function. The command prepares a MI Record | 
 | // Result | 
 | //          for the work carried out in the Execute(). | 
 | // Type:    Overridden. | 
 | // Args:    None. | 
 | // Return:  MIstatus::success - Functional succeeded. | 
 | //          MIstatus::failure - Functional failed. | 
 | // Throws:  None. | 
 | //-- | 
 | bool CMICmdCmdDataReadMemoryBytes::Acknowledge() { | 
 |   // MI: memory=[{begin=\"0x%016" PRIx64 "\",offset=\"0x%016" PRIx64" | 
 |   // \",end=\"0x%016" PRIx64 "\",contents=\" \" }]" | 
 |   const CMICmnMIValueConst miValueConst( | 
 |       CMIUtilString::Format("0x%016" PRIx64, m_nAddrStart)); | 
 |   const CMICmnMIValueResult miValueResult("begin", miValueConst); | 
 |   CMICmnMIValueTuple miValueTuple(miValueResult); | 
 |   const MIuint64 nAddrOffset = 0; | 
 |   const CMICmnMIValueConst miValueConst2( | 
 |       CMIUtilString::Format("0x%016" PRIx64, nAddrOffset)); | 
 |   const CMICmnMIValueResult miValueResult2("offset", miValueConst2); | 
 |   miValueTuple.Add(miValueResult2); | 
 |   const CMICmnMIValueConst miValueConst3(CMIUtilString::Format( | 
 |       "0x%016" PRIx64, m_nAddrStart + m_nAddrNumBytesToRead)); | 
 |   const CMICmnMIValueResult miValueResult3("end", miValueConst3); | 
 |   miValueTuple.Add(miValueResult3); | 
 |  | 
 |   // MI: contents=\" \" | 
 |   CMIUtilString strContent; | 
 |   strContent.reserve((m_nAddrNumBytesToRead << 1) + 1); | 
 |   for (MIuint64 i = 0; i < m_nAddrNumBytesToRead; i++) { | 
 |     strContent += CMIUtilString::Format("%02hhx", m_pBufferMemory[i]); | 
 |   } | 
 |   const CMICmnMIValueConst miValueConst4(strContent); | 
 |   const CMICmnMIValueResult miValueResult4("contents", miValueConst4); | 
 |   miValueTuple.Add(miValueResult4); | 
 |   const CMICmnMIValueList miValueList(miValueTuple); | 
 |   const CMICmnMIValueResult miValueResult5("memory", miValueList); | 
 |  | 
 |   const CMICmnMIResultRecord miRecordResult( | 
 |       m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, | 
 |       miValueResult5); | 
 |   m_miResultRecord = miRecordResult; | 
 |  | 
 |   return MIstatus::success; | 
 | } | 
 |  | 
 | //++ | 
 | //------------------------------------------------------------------------------------ | 
 | // Details: Required by the CMICmdFactory when registering *this command. The | 
 | // factory | 
 | //          calls this function to create an instance of *this command. | 
 | // Type:    Static method. | 
 | // Args:    None. | 
 | // Return:  CMICmdBase * - Pointer to a new command. | 
 | // Throws:  None. | 
 | //-- | 
 | CMICmdBase *CMICmdCmdDataReadMemoryBytes::CreateSelf() { | 
 |   return new CMICmdCmdDataReadMemoryBytes(); | 
 | } | 
 |  | 
 | //--------------------------------------------------------------------------------------- | 
 | //--------------------------------------------------------------------------------------- | 
 | //--------------------------------------------------------------------------------------- | 
 |  | 
 | //++ | 
 | //------------------------------------------------------------------------------------ | 
 | // Details: CMICmdCmdDataReadMemory constructor. | 
 | // Type:    Method. | 
 | // Args:    None. | 
 | // Return:  None. | 
 | // Throws:  None. | 
 | //-- | 
 | CMICmdCmdDataReadMemory::CMICmdCmdDataReadMemory() { | 
 |   // Command factory matches this name with that received from the stdin stream | 
 |   m_strMiCmd = "data-read-memory"; | 
 |  | 
 |   // Required by the CMICmdFactory when registering *this command | 
 |   m_pSelfCreatorFn = &CMICmdCmdDataReadMemory::CreateSelf; | 
 | } | 
 |  | 
 | //++ | 
 | //------------------------------------------------------------------------------------ | 
 | // Details: CMICmdCmdDataReadMemory destructor. | 
 | // Type:    Overrideable. | 
 | // Args:    None. | 
 | // Return:  None. | 
 | // Throws:  None. | 
 | //-- | 
 | CMICmdCmdDataReadMemory::~CMICmdCmdDataReadMemory() {} | 
 |  | 
 | //++ | 
 | //------------------------------------------------------------------------------------ | 
 | // Details: The invoker requires this function. The command does work in this | 
 | // function. | 
 | //          The command is likely to communicate with the LLDB SBDebugger in | 
 | //          here. | 
 | // Type:    Overridden. | 
 | // Args:    None. | 
 | // Return:  MIstatus::success - Functional succeeded. | 
 | //          MIstatus::failure - Functional failed. | 
 | // Throws:  None. | 
 | //-- | 
 | bool CMICmdCmdDataReadMemory::Execute() { | 
 |   // Do nothing - command deprecated use "data-read-memory-bytes" command | 
 |   return MIstatus::success; | 
 | } | 
 |  | 
 | //++ | 
 | //------------------------------------------------------------------------------------ | 
 | // Details: The invoker requires this function. The command prepares a MI Record | 
 | // Result | 
 | //          for the work carried out in the Execute(). | 
 | // Type:    Overridden. | 
 | // Args:    None. | 
 | // Return:  MIstatus::success - Functional succeeded. | 
 | //          MIstatus::failure - Functional failed. | 
 | // Throws:  None. | 
 | //-- | 
 | bool CMICmdCmdDataReadMemory::Acknowledge() { | 
 |   // Command CMICmdCmdSupportListFeatures sends "data-read-memory-bytes" which | 
 |   // causes this command not to be called | 
 |   const CMICmnMIValueConst miValueConst( | 
 |       MIRSRC(IDS_CMD_ERR_NOT_IMPLEMENTED_DEPRECATED)); | 
 |   const CMICmnMIValueResult miValueResult("msg", miValueConst); | 
 |   const CMICmnMIResultRecord miRecordResult( | 
 |       m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, | 
 |       miValueResult); | 
 |   m_miResultRecord = miRecordResult; | 
 |  | 
 |   return MIstatus::success; | 
 | } | 
 |  | 
 | //++ | 
 | //------------------------------------------------------------------------------------ | 
 | // Details: Required by the CMICmdFactory when registering *this command. The | 
 | // factory | 
 | //          calls this function to create an instance of *this command. | 
 | // Type:    Static method. | 
 | // Args:    None. | 
 | // Return:  CMICmdBase * - Pointer to a new command. | 
 | // Throws:  None. | 
 | //-- | 
 | CMICmdBase *CMICmdCmdDataReadMemory::CreateSelf() { | 
 |   return new CMICmdCmdDataReadMemory(); | 
 | } | 
 |  | 
 | //--------------------------------------------------------------------------------------- | 
 | //--------------------------------------------------------------------------------------- | 
 | //--------------------------------------------------------------------------------------- | 
 |  | 
 | //++ | 
 | //------------------------------------------------------------------------------------ | 
 | // Details: CMICmdCmdDataListRegisterNames constructor. | 
 | // Type:    Method. | 
 | // Args:    None. | 
 | // Return:  None. | 
 | // Throws:  None. | 
 | //-- | 
 | CMICmdCmdDataListRegisterNames::CMICmdCmdDataListRegisterNames() | 
 |     : m_constStrArgRegNo("regno"), m_miValueList(true) { | 
 |   // Command factory matches this name with that received from the stdin stream | 
 |   m_strMiCmd = "data-list-register-names"; | 
 |  | 
 |   // Required by the CMICmdFactory when registering *this command | 
 |   m_pSelfCreatorFn = &CMICmdCmdDataListRegisterNames::CreateSelf; | 
 | } | 
 |  | 
 | //++ | 
 | //------------------------------------------------------------------------------------ | 
 | // Details: CMICmdCmdDataReadMemoryBytes destructor. | 
 | // Type:    Overrideable. | 
 | // Args:    None. | 
 | // Return:  None. | 
 | // Throws:  None. | 
 | //-- | 
 | CMICmdCmdDataListRegisterNames::~CMICmdCmdDataListRegisterNames() {} | 
 |  | 
 | //++ | 
 | //------------------------------------------------------------------------------------ | 
 | // Details: The invoker requires this function. The parses the command line | 
 | // options | 
 | //          arguments to extract values for each of those arguments. | 
 | // Type:    Overridden. | 
 | // Args:    None. | 
 | // Return:  MIstatus::success - Functional succeeded. | 
 | //          MIstatus::failure - Functional failed. | 
 | // Throws:  None. | 
 | //-- | 
 | bool CMICmdCmdDataListRegisterNames::ParseArgs() { | 
 |   m_setCmdArgs.Add( | 
 |       new CMICmdArgValListOfN(m_constStrArgRegNo, false, false, | 
 |                               CMICmdArgValListBase::eArgValType_Number)); | 
 |   return ParseValidateCmdOptions(); | 
 | } | 
 |  | 
 | //++ | 
 | //------------------------------------------------------------------------------------ | 
 | // Details: The invoker requires this function. The command does work in this | 
 | // function. | 
 | //          The command is likely to communicate with the LLDB SBDebugger in | 
 | //          here. | 
 | // Type:    Overridden. | 
 | // Args:    None. | 
 | // Return:  MIstatus::success - Functional succeeded. | 
 | //          MIstatus::failure - Functional failed. | 
 | // Throws:  None. | 
 | //-- | 
 | bool CMICmdCmdDataListRegisterNames::Execute() { | 
 |   CMICMDBASE_GETOPTION(pArgRegNo, ListOfN, m_constStrArgRegNo); | 
 |  | 
 |   CMICmnLLDBDebugSessionInfo &rSessionInfo( | 
 |       CMICmnLLDBDebugSessionInfo::Instance()); | 
 |   lldb::SBProcess sbProcess = rSessionInfo.GetProcess(); | 
 |   if (!sbProcess.IsValid()) { | 
 |     SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_PROCESS), | 
 |                                    m_cmdData.strMiCmd.c_str())); | 
 |     return MIstatus::failure; | 
 |   } | 
 |  | 
 |   const CMICmdArgValListBase::VecArgObjPtr_t &rVecRegNo( | 
 |       pArgRegNo->GetExpectedOptions()); | 
 |   if (!rVecRegNo.empty()) { | 
 |     // List of required registers | 
 |     CMICmdArgValListBase::VecArgObjPtr_t::const_iterator it = rVecRegNo.begin(); | 
 |     while (it != rVecRegNo.end()) { | 
 |       const CMICmdArgValNumber *pRegNo = static_cast<CMICmdArgValNumber *>(*it); | 
 |       const MIuint nRegIndex = pRegNo->GetValue(); | 
 |       lldb::SBValue regValue = GetRegister(nRegIndex); | 
 |       if (regValue.IsValid()) { | 
 |         const CMICmnMIValueConst miValueConst( | 
 |             CMICmnLLDBUtilSBValue(regValue).GetName()); | 
 |         m_miValueList.Add(miValueConst); | 
 |       } | 
 |  | 
 |       // Next | 
 |       ++it; | 
 |     } | 
 |   } else { | 
 |     // List of all registers | 
 |     lldb::SBThread thread = sbProcess.GetSelectedThread(); | 
 |     lldb::SBFrame frame = thread.GetSelectedFrame(); | 
 |     lldb::SBValueList registers = frame.GetRegisters(); | 
 |     const MIuint nRegisters = registers.GetSize(); | 
 |     for (MIuint i = 0; i < nRegisters; i++) { | 
 |       lldb::SBValue value = registers.GetValueAtIndex(i); | 
 |       const MIuint nRegChildren = value.GetNumChildren(); | 
 |       for (MIuint j = 0; j < nRegChildren; j++) { | 
 |         lldb::SBValue regValue = value.GetChildAtIndex(j); | 
 |         if (regValue.IsValid()) { | 
 |           const CMICmnMIValueConst miValueConst( | 
 |               CMICmnLLDBUtilSBValue(regValue).GetName()); | 
 |           m_miValueList.Add(miValueConst); | 
 |         } | 
 |       } | 
 |     } | 
 |   } | 
 |  | 
 |   return MIstatus::success; | 
 | } | 
 |  | 
 | //++ | 
 | //------------------------------------------------------------------------------------ | 
 | // Details: The invoker requires this function. The command prepares a MI Record | 
 | // Result | 
 | //          for the work carried out in the Execute(). | 
 | // Type:    Overridden. | 
 | // Args:    None. | 
 | // Return:  MIstatus::success - Functional succeeded. | 
 | //          MIstatus::failure - Functional failed. | 
 | // Throws:  None. | 
 | //-- | 
 | bool CMICmdCmdDataListRegisterNames::Acknowledge() { | 
 |   const CMICmnMIValueResult miValueResult("register-names", m_miValueList); | 
 |   const CMICmnMIResultRecord miRecordResult( | 
 |       m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, | 
 |       miValueResult); | 
 |   m_miResultRecord = miRecordResult; | 
 |  | 
 |   return MIstatus::success; | 
 | } | 
 |  | 
 | //++ | 
 | //------------------------------------------------------------------------------------ | 
 | // Details: Required by the CMICmdFactory when registering *this command. The | 
 | // factory | 
 | //          calls this function to create an instance of *this command. | 
 | // Type:    Static method. | 
 | // Args:    None. | 
 | // Return:  CMICmdBase * - Pointer to a new command. | 
 | // Throws:  None. | 
 | //-- | 
 | CMICmdBase *CMICmdCmdDataListRegisterNames::CreateSelf() { | 
 |   return new CMICmdCmdDataListRegisterNames(); | 
 | } | 
 |  | 
 | //++ | 
 | //------------------------------------------------------------------------------------ | 
 | // Details: Required by the CMICmdFactory when registering *this command. The | 
 | // factory | 
 | //          calls this function to create an instance of *this command. | 
 | // Type:    Method. | 
 | // Args:    None. | 
 | // Return:  lldb::SBValue - LLDB SBValue object. | 
 | // Throws:  None. | 
 | //-- | 
 | lldb::SBValue | 
 | CMICmdCmdDataListRegisterNames::GetRegister(const MIuint vRegisterIndex) const { | 
 |   lldb::SBThread thread = | 
 |       CMICmnLLDBDebugSessionInfo::Instance().GetProcess().GetSelectedThread(); | 
 |   lldb::SBFrame frame = thread.GetSelectedFrame(); | 
 |   lldb::SBValueList registers = frame.GetRegisters(); | 
 |   const MIuint nRegisters = registers.GetSize(); | 
 |   MIuint nRegisterIndex(vRegisterIndex); | 
 |   for (MIuint i = 0; i < nRegisters; i++) { | 
 |     lldb::SBValue value = registers.GetValueAtIndex(i); | 
 |     const MIuint nRegChildren = value.GetNumChildren(); | 
 |     if (nRegisterIndex >= nRegChildren) { | 
 |       nRegisterIndex -= nRegChildren; | 
 |       continue; | 
 |     } | 
 |  | 
 |     lldb::SBValue value2 = value.GetChildAtIndex(nRegisterIndex); | 
 |     if (value2.IsValid()) { | 
 |       return value2; | 
 |     } | 
 |   } | 
 |  | 
 |   return lldb::SBValue(); | 
 | } | 
 |  | 
 | //--------------------------------------------------------------------------------------- | 
 | //--------------------------------------------------------------------------------------- | 
 | //--------------------------------------------------------------------------------------- | 
 |  | 
 | //++ | 
 | //------------------------------------------------------------------------------------ | 
 | // Details: CMICmdCmdDataListRegisterValues constructor. | 
 | // Type:    Method. | 
 | // Args:    None. | 
 | // Return:  None. | 
 | // Throws:  None. | 
 | //-- | 
 | CMICmdCmdDataListRegisterValues::CMICmdCmdDataListRegisterValues() | 
 |     : m_constStrArgSkip("skip-unavailable"), m_constStrArgFormat("fmt"), | 
 |       m_constStrArgRegNo("regno"), m_miValueList(true) { | 
 |   // Command factory matches this name with that received from the stdin stream | 
 |   m_strMiCmd = "data-list-register-values"; | 
 |  | 
 |   // Required by the CMICmdFactory when registering *this command | 
 |   m_pSelfCreatorFn = &CMICmdCmdDataListRegisterValues::CreateSelf; | 
 | } | 
 |  | 
 | //++ | 
 | //------------------------------------------------------------------------------------ | 
 | // Details: CMICmdCmdDataListRegisterValues destructor. | 
 | // Type:    Overrideable. | 
 | // Args:    None. | 
 | // Return:  None. | 
 | // Throws:  None. | 
 | //-- | 
 | CMICmdCmdDataListRegisterValues::~CMICmdCmdDataListRegisterValues() {} | 
 |  | 
 | //++ | 
 | //------------------------------------------------------------------------------------ | 
 | // Details: The invoker requires this function. The parses the command line | 
 | // options | 
 | //          arguments to extract values for each of those arguments. | 
 | // Type:    Overridden. | 
 | // Args:    None. | 
 | // Return:  MIstatus::success - Functional succeeded. | 
 | //          MIstatus::failure - Functional failed. | 
 | // Throws:  None. | 
 | //-- | 
 | bool CMICmdCmdDataListRegisterValues::ParseArgs() { | 
 |   m_setCmdArgs.Add( | 
 |       new CMICmdArgValOptionLong(m_constStrArgThread, false, false, | 
 |                                  CMICmdArgValListBase::eArgValType_Number, 1)); | 
 |   m_setCmdArgs.Add(new CMICmdArgValOptionLong(m_constStrArgSkip, false, false)); | 
 |   m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgFormat, true, true)); | 
 |   m_setCmdArgs.Add( | 
 |       new CMICmdArgValListOfN(m_constStrArgRegNo, false, true, | 
 |                               CMICmdArgValListBase::eArgValType_Number)); | 
 |   return ParseValidateCmdOptions(); | 
 | } | 
 |  | 
 | //++ | 
 | //------------------------------------------------------------------------------------ | 
 | // Details: The invoker requires this function. The command does work in this | 
 | // function. | 
 | //          The command is likely to communicate with the LLDB SBDebugger in | 
 | //          here. | 
 | // Type:    Overridden. | 
 | // Args:    None. | 
 | // Return:  MIstatus::success - Functional succeeded. | 
 | //          MIstatus::failure - Functional failed. | 
 | // Throws:  None. | 
 | //-- | 
 | bool CMICmdCmdDataListRegisterValues::Execute() { | 
 |   CMICMDBASE_GETOPTION(pArgFormat, String, m_constStrArgFormat); | 
 |   CMICMDBASE_GETOPTION(pArgRegNo, ListOfN, m_constStrArgRegNo); | 
 |  | 
 |   const CMIUtilString &rStrFormat(pArgFormat->GetValue()); | 
 |   if (rStrFormat.length() != 1) { | 
 |     SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_FORMAT_TYPE), | 
 |                                    m_cmdData.strMiCmd.c_str(), | 
 |                                    rStrFormat.c_str())); | 
 |     return MIstatus::failure; | 
 |   } | 
 |   const CMICmnLLDBDebugSessionInfoVarObj::varFormat_e eFormat = | 
 |       CMICmnLLDBDebugSessionInfoVarObj::GetVarFormatForChar(rStrFormat[0]); | 
 |   if (eFormat == CMICmnLLDBDebugSessionInfoVarObj::eVarFormat_Invalid) { | 
 |     SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_FORMAT_TYPE), | 
 |                                    m_cmdData.strMiCmd.c_str(), | 
 |                                    rStrFormat.c_str())); | 
 |     return MIstatus::failure; | 
 |   } | 
 |  | 
 |   CMICmnLLDBDebugSessionInfo &rSessionInfo( | 
 |       CMICmnLLDBDebugSessionInfo::Instance()); | 
 |   lldb::SBProcess sbProcess = rSessionInfo.GetProcess(); | 
 |   if (!sbProcess.IsValid()) { | 
 |     SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_PROCESS), | 
 |                                    m_cmdData.strMiCmd.c_str())); | 
 |     return MIstatus::failure; | 
 |   } | 
 |  | 
 |   const CMICmdArgValListBase::VecArgObjPtr_t &rVecRegNo( | 
 |       pArgRegNo->GetExpectedOptions()); | 
 |   if (!rVecRegNo.empty()) { | 
 |     // List of required registers | 
 |     CMICmdArgValListBase::VecArgObjPtr_t::const_iterator it = rVecRegNo.begin(); | 
 |     while (it != rVecRegNo.end()) { | 
 |       const CMICmdArgValNumber *pRegNo = static_cast<CMICmdArgValNumber *>(*it); | 
 |       const MIuint nRegIndex = pRegNo->GetValue(); | 
 |       lldb::SBValue regValue = GetRegister(nRegIndex); | 
 |       if (regValue.IsValid()) { | 
 |         AddToOutput(nRegIndex, regValue, eFormat); | 
 |       } | 
 |  | 
 |       // Next | 
 |       ++it; | 
 |     } | 
 |   } else { | 
 |     // No register numbers are provided. Output all registers. | 
 |     lldb::SBThread thread = sbProcess.GetSelectedThread(); | 
 |     lldb::SBFrame frame = thread.GetSelectedFrame(); | 
 |     lldb::SBValueList registers = frame.GetRegisters(); | 
 |     const MIuint nRegisters = registers.GetSize(); | 
 |     MIuint nRegIndex = 0; | 
 |     for (MIuint i = 0; i < nRegisters; i++) { | 
 |       lldb::SBValue value = registers.GetValueAtIndex(i); | 
 |       const MIuint nRegChildren = value.GetNumChildren(); | 
 |       for (MIuint j = 0; j < nRegChildren; j++) { | 
 |         lldb::SBValue regValue = value.GetChildAtIndex(j); | 
 |         if (regValue.IsValid()) { | 
 |           AddToOutput(nRegIndex, regValue, eFormat); | 
 |         } | 
 |  | 
 |         // Next | 
 |         ++nRegIndex; | 
 |       } | 
 |     } | 
 |   } | 
 |  | 
 |   return MIstatus::success; | 
 | } | 
 |  | 
 | //++ | 
 | //------------------------------------------------------------------------------------ | 
 | // Details: The invoker requires this function. The command prepares a MI Record | 
 | // Result | 
 | //          for the work carried out in the Execute(). | 
 | // Type:    Overridden. | 
 | // Args:    None. | 
 | // Return:  MIstatus::success - Functional succeeded. | 
 | //          MIstatus::failure - Functional failed. | 
 | // Throws:  None. | 
 | //-- | 
 | bool CMICmdCmdDataListRegisterValues::Acknowledge() { | 
 |   const CMICmnMIValueResult miValueResult("register-values", m_miValueList); | 
 |   const CMICmnMIResultRecord miRecordResult( | 
 |       m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, | 
 |       miValueResult); | 
 |   m_miResultRecord = miRecordResult; | 
 |  | 
 |   return MIstatus::success; | 
 | } | 
 |  | 
 | //++ | 
 | //------------------------------------------------------------------------------------ | 
 | // Details: Required by the CMICmdFactory when registering *this command. The | 
 | // factory | 
 | //          calls this function to create an instance of *this command. | 
 | // Type:    Static method. | 
 | // Args:    None. | 
 | // Return:  CMICmdBase * - Pointer to a new command. | 
 | // Throws:  None. | 
 | //-- | 
 | CMICmdBase *CMICmdCmdDataListRegisterValues::CreateSelf() { | 
 |   return new CMICmdCmdDataListRegisterValues(); | 
 | } | 
 |  | 
 | //++ | 
 | //------------------------------------------------------------------------------------ | 
 | // Details: Required by the CMICmdFactory when registering *this command. The | 
 | // factory | 
 | //          calls this function to create an instance of *this command. | 
 | // Type:    Method. | 
 | // Args:    None. | 
 | // Return:  lldb::SBValue - LLDB SBValue object. | 
 | // Throws:  None. | 
 | //-- | 
 | lldb::SBValue CMICmdCmdDataListRegisterValues::GetRegister( | 
 |     const MIuint vRegisterIndex) const { | 
 |   lldb::SBThread thread = | 
 |       CMICmnLLDBDebugSessionInfo::Instance().GetProcess().GetSelectedThread(); | 
 |   lldb::SBFrame frame = thread.GetSelectedFrame(); | 
 |   lldb::SBValueList registers = frame.GetRegisters(); | 
 |   const MIuint nRegisters = registers.GetSize(); | 
 |   MIuint nRegisterIndex(vRegisterIndex); | 
 |   for (MIuint i = 0; i < nRegisters; i++) { | 
 |     lldb::SBValue value = registers.GetValueAtIndex(i); | 
 |     const MIuint nRegChildren = value.GetNumChildren(); | 
 |     if (nRegisterIndex >= nRegChildren) { | 
 |       nRegisterIndex -= nRegChildren; | 
 |       continue; | 
 |     } | 
 |  | 
 |     lldb::SBValue value2 = value.GetChildAtIndex(nRegisterIndex); | 
 |     if (value2.IsValid()) { | 
 |       return value2; | 
 |     } | 
 |   } | 
 |  | 
 |   return lldb::SBValue(); | 
 | } | 
 |  | 
 | //++ | 
 | //------------------------------------------------------------------------------------ | 
 | // Details: Adds the register value to the output list. | 
 | // Type:    Method. | 
 | // Args:    Value of the register, its index and output format. | 
 | // Return:  None | 
 | // Throws:  None. | 
 | //-- | 
 | void CMICmdCmdDataListRegisterValues::AddToOutput( | 
 |     const MIuint vnIndex, const lldb::SBValue &vrValue, | 
 |     CMICmnLLDBDebugSessionInfoVarObj::varFormat_e veVarFormat) { | 
 |   const CMICmnMIValueConst miValueConst(CMIUtilString::Format("%u", vnIndex)); | 
 |   const CMICmnMIValueResult miValueResult("number", miValueConst); | 
 |   CMICmnMIValueTuple miValueTuple(miValueResult); | 
 |   const CMIUtilString strRegValue( | 
 |       CMICmnLLDBDebugSessionInfoVarObj::GetValueStringFormatted(vrValue, | 
 |                                                                 veVarFormat)); | 
 |   const CMICmnMIValueConst miValueConst2(strRegValue); | 
 |   const CMICmnMIValueResult miValueResult2("value", miValueConst2); | 
 |   miValueTuple.Add(miValueResult2); | 
 |   m_miValueList.Add(miValueTuple); | 
 | } | 
 |  | 
 | //--------------------------------------------------------------------------------------- | 
 | //--------------------------------------------------------------------------------------- | 
 | //--------------------------------------------------------------------------------------- | 
 |  | 
 | //++ | 
 | //------------------------------------------------------------------------------------ | 
 | // Details: CMICmdCmdDataListRegisterChanged constructor. | 
 | // Type:    Method. | 
 | // Args:    None. | 
 | // Return:  None. | 
 | // Throws:  None. | 
 | //-- | 
 | CMICmdCmdDataListRegisterChanged::CMICmdCmdDataListRegisterChanged() { | 
 |   // Command factory matches this name with that received from the stdin stream | 
 |   m_strMiCmd = "data-list-changed-registers"; | 
 |  | 
 |   // Required by the CMICmdFactory when registering *this command | 
 |   m_pSelfCreatorFn = &CMICmdCmdDataListRegisterChanged::CreateSelf; | 
 | } | 
 |  | 
 | //++ | 
 | //------------------------------------------------------------------------------------ | 
 | // Details: CMICmdCmdDataListRegisterChanged destructor. | 
 | // Type:    Overrideable. | 
 | // Args:    None. | 
 | // Return:  None. | 
 | // Throws:  None. | 
 | //-- | 
 | CMICmdCmdDataListRegisterChanged::~CMICmdCmdDataListRegisterChanged() {} | 
 |  | 
 | //++ | 
 | //------------------------------------------------------------------------------------ | 
 | // Details: The invoker requires this function. The command does work in this | 
 | // function. | 
 | //          The command is likely to communicate with the LLDB SBDebugger in | 
 | //          here. | 
 | // Type:    Overridden. | 
 | // Args:    None. | 
 | // Return:  MIstatus::success - Functional succeeded. | 
 | //          MIstatus::failure - Functional failed. | 
 | // Throws:  None. | 
 | //-- | 
 | bool CMICmdCmdDataListRegisterChanged::Execute() { | 
 |   // Do nothing | 
 |  | 
 |   return MIstatus::success; | 
 | } | 
 |  | 
 | //++ | 
 | //------------------------------------------------------------------------------------ | 
 | // Details: The invoker requires this function. The command prepares a MI Record | 
 | // Result | 
 | //          for the work carried out in the Execute(). | 
 | // Type:    Overridden. | 
 | // Args:    None. | 
 | // Return:  MIstatus::success - Functional succeeded. | 
 | //          MIstatus::failure - Functional failed. | 
 | // Throws:  None. | 
 | //-- | 
 | bool CMICmdCmdDataListRegisterChanged::Acknowledge() { | 
 |   const CMICmnMIValueConst miValueConst(MIRSRC(IDS_WORD_NOT_IMPLEMENTED)); | 
 |   const CMICmnMIValueResult miValueResult("msg", miValueConst); | 
 |   const CMICmnMIResultRecord miRecordResult( | 
 |       m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, | 
 |       miValueResult); | 
 |   m_miResultRecord = miRecordResult; | 
 |  | 
 |   return MIstatus::success; | 
 | } | 
 |  | 
 | //++ | 
 | //------------------------------------------------------------------------------------ | 
 | // Details: Required by the CMICmdFactory when registering *this command. The | 
 | // factory | 
 | //          calls this function to create an instance of *this command. | 
 | // Type:    Static method. | 
 | // Args:    None. | 
 | // Return:  CMICmdBase * - Pointer to a new command. | 
 | // Throws:  None. | 
 | //-- | 
 | CMICmdBase *CMICmdCmdDataListRegisterChanged::CreateSelf() { | 
 |   return new CMICmdCmdDataListRegisterChanged(); | 
 | } | 
 |  | 
 | //--------------------------------------------------------------------------------------- | 
 | //--------------------------------------------------------------------------------------- | 
 | //--------------------------------------------------------------------------------------- | 
 |  | 
 | //++ | 
 | //------------------------------------------------------------------------------------ | 
 | // Details: CMICmdCmdDataWriteMemoryBytes constructor. | 
 | // Type:    Method. | 
 | // Args:    None. | 
 | // Return:  None. | 
 | // Throws:  None. | 
 | //-- | 
 | CMICmdCmdDataWriteMemoryBytes::CMICmdCmdDataWriteMemoryBytes() | 
 |     : m_constStrArgAddr("address"), m_constStrArgContents("contents"), | 
 |       m_constStrArgCount("count") { | 
 |   // Command factory matches this name with that received from the stdin stream | 
 |   m_strMiCmd = "data-write-memory-bytes"; | 
 |  | 
 |   // Required by the CMICmdFactory when registering *this command | 
 |   m_pSelfCreatorFn = &CMICmdCmdDataWriteMemoryBytes::CreateSelf; | 
 | } | 
 |  | 
 | //++ | 
 | //------------------------------------------------------------------------------------ | 
 | // Details: CMICmdCmdDataWriteMemoryBytes destructor. | 
 | // Type:    Overrideable. | 
 | // Args:    None. | 
 | // Return:  None. | 
 | // Throws:  None. | 
 | //-- | 
 | CMICmdCmdDataWriteMemoryBytes::~CMICmdCmdDataWriteMemoryBytes() {} | 
 |  | 
 | //++ | 
 | //------------------------------------------------------------------------------------ | 
 | // Details: The invoker requires this function. The parses the command line | 
 | // options | 
 | //          arguments to extract values for each of those arguments. | 
 | // Type:    Overridden. | 
 | // Args:    None. | 
 | // Return:  MIstatus::success - Functional succeeded. | 
 | //          MIstatus::failure - Functional failed. | 
 | // Throws:  None. | 
 | //-- | 
 | bool CMICmdCmdDataWriteMemoryBytes::ParseArgs() { | 
 |   m_setCmdArgs.Add( | 
 |       new CMICmdArgValString(m_constStrArgAddr, true, true, false, true)); | 
 |   m_setCmdArgs.Add( | 
 |       new CMICmdArgValString(m_constStrArgContents, true, true, true, true)); | 
 |   m_setCmdArgs.Add( | 
 |       new CMICmdArgValString(m_constStrArgCount, false, true, false, true)); | 
 |   return ParseValidateCmdOptions(); | 
 | } | 
 |  | 
 | //++ | 
 | //------------------------------------------------------------------------------------ | 
 | // Details: The invoker requires this function. The command does work in this | 
 | // function. | 
 | //          The command is likely to communicate with the LLDB SBDebugger in | 
 | //          here. | 
 | // Type:    Overridden. | 
 | // Args:    None. | 
 | // Return:  MIstatus::success - Functional succeeded. | 
 | //          MIstatus::failure - Functional failed. | 
 | // Throws:  None. | 
 | //-- | 
 | bool CMICmdCmdDataWriteMemoryBytes::Execute() { | 
 |   // Do nothing - not reproduceable (yet) in Eclipse | 
 |   // CMICMDBASE_GETOPTION( pArgOffset, OptionShort, m_constStrArgOffset ); | 
 |   // CMICMDBASE_GETOPTION( pArgAddr, String, m_constStrArgAddr ); | 
 |   // CMICMDBASE_GETOPTION( pArgNumber, String, m_constStrArgNumber ); | 
 |   // CMICMDBASE_GETOPTION( pArgContents, String, m_constStrArgContents ); | 
 |   // | 
 |   // Numbers extracts as string types as they could be hex numbers | 
 |   // '&' is not recognised and so has to be removed | 
 |  | 
 |   return MIstatus::success; | 
 | } | 
 |  | 
 | //++ | 
 | //------------------------------------------------------------------------------------ | 
 | // Details: The invoker requires this function. The command prepares a MI Record | 
 | // Result | 
 | //          for the work carried out in the Execute(). | 
 | // Type:    Overridden. | 
 | // Args:    None. | 
 | // Return:  MIstatus::success - Functional succeeded. | 
 | //          MIstatus::failure - Functional failed. | 
 | // Throws:  None. | 
 | //-- | 
 | bool CMICmdCmdDataWriteMemoryBytes::Acknowledge() { | 
 |   const CMICmnMIValueConst miValueConst(MIRSRC(IDS_WORD_NOT_IMPLEMENTED)); | 
 |   const CMICmnMIValueResult miValueResult("msg", miValueConst); | 
 |   const CMICmnMIResultRecord miRecordResult( | 
 |       m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, | 
 |       miValueResult); | 
 |   m_miResultRecord = miRecordResult; | 
 |  | 
 |   return MIstatus::success; | 
 | } | 
 |  | 
 | //++ | 
 | //------------------------------------------------------------------------------------ | 
 | // Details: Required by the CMICmdFactory when registering *this command. The | 
 | // factory | 
 | //          calls this function to create an instance of *this command. | 
 | // Type:    Static method. | 
 | // Args:    None. | 
 | // Return:  CMICmdBase * - Pointer to a new command. | 
 | // Throws:  None. | 
 | //-- | 
 | CMICmdBase *CMICmdCmdDataWriteMemoryBytes::CreateSelf() { | 
 |   return new CMICmdCmdDataWriteMemoryBytes(); | 
 | } | 
 |  | 
 | //--------------------------------------------------------------------------------------- | 
 | //--------------------------------------------------------------------------------------- | 
 | //--------------------------------------------------------------------------------------- | 
 |  | 
 | //++ | 
 | //------------------------------------------------------------------------------------ | 
 | // Details: CMICmdCmdDataWriteMemory constructor. | 
 | // Type:    Method. | 
 | // Args:    None. | 
 | // Return:  None. | 
 | // Throws:  None. | 
 | //-- | 
 | CMICmdCmdDataWriteMemory::CMICmdCmdDataWriteMemory() | 
 |     : m_constStrArgOffset("o"), m_constStrArgAddr("address"), | 
 |       m_constStrArgD("d"), m_constStrArgNumber("a number"), | 
 |       m_constStrArgContents("contents"), m_nAddr(0), m_nCount(0), | 
 |       m_pBufferMemory(nullptr) { | 
 |   // Command factory matches this name with that received from the stdin stream | 
 |   m_strMiCmd = "data-write-memory"; | 
 |  | 
 |   // Required by the CMICmdFactory when registering *this command | 
 |   m_pSelfCreatorFn = &CMICmdCmdDataWriteMemory::CreateSelf; | 
 | } | 
 |  | 
 | //++ | 
 | //------------------------------------------------------------------------------------ | 
 | // Details: CMICmdCmdDataWriteMemory destructor. | 
 | // Type:    Overrideable. | 
 | // Args:    None. | 
 | // Return:  None. | 
 | // Throws:  None. | 
 | //-- | 
 | CMICmdCmdDataWriteMemory::~CMICmdCmdDataWriteMemory() { | 
 |   if (m_pBufferMemory != nullptr) { | 
 |     delete[] m_pBufferMemory; | 
 |     m_pBufferMemory = nullptr; | 
 |   } | 
 | } | 
 |  | 
 | //++ | 
 | //------------------------------------------------------------------------------------ | 
 | // Details: The invoker requires this function. The parses the command line | 
 | // options | 
 | //          arguments to extract values for each of those arguments. | 
 | // Type:    Overridden. | 
 | // Args:    None. | 
 | // Return:  MIstatus::success - Functional succeeded. | 
 | //          MIstatus::failure - Functional failed. | 
 | // Throws:  None. | 
 | //-- | 
 | bool CMICmdCmdDataWriteMemory::ParseArgs() { | 
 |   m_setCmdArgs.Add( | 
 |       new CMICmdArgValOptionShort(m_constStrArgOffset, false, true, | 
 |                                   CMICmdArgValListBase::eArgValType_Number, 1)); | 
 |   m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgAddr, true, true)); | 
 |   m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgD, true, true)); | 
 |   m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgNumber, true, true)); | 
 |   m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgContents, true, true)); | 
 |   return ParseValidateCmdOptions(); | 
 | } | 
 |  | 
 | //++ | 
 | //------------------------------------------------------------------------------------ | 
 | // Details: The invoker requires this function. The command does work in this | 
 | // function. | 
 | //          The command is likely to communicate with the LLDB SBDebugger in | 
 | //          here. | 
 | // Type:    Overridden. | 
 | // Args:    None. | 
 | // Return:  MIstatus::success - Functional succeeded. | 
 | //          MIstatus::failure - Functional failed. | 
 | // Throws:  None. | 
 | //-- | 
 | bool CMICmdCmdDataWriteMemory::Execute() { | 
 |   CMICMDBASE_GETOPTION(pArgOffset, OptionShort, m_constStrArgOffset); | 
 |   CMICMDBASE_GETOPTION(pArgAddr, Number, m_constStrArgAddr); | 
 |   CMICMDBASE_GETOPTION(pArgNumber, Number, m_constStrArgNumber); | 
 |   CMICMDBASE_GETOPTION(pArgContents, Number, m_constStrArgContents); | 
 |  | 
 |   MIuint nAddrOffset = 0; | 
 |   if (pArgOffset->GetFound() && | 
 |       !pArgOffset->GetExpectedOption<CMICmdArgValNumber, MIuint>(nAddrOffset)) { | 
 |     SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ARGS_ERR_VALIDATION_INVALID), | 
 |                                    m_cmdData.strMiCmd.c_str(), | 
 |                                    m_constStrArgAddr.c_str())); | 
 |     return MIstatus::failure; | 
 |   } | 
 |   m_nAddr = pArgAddr->GetValue(); | 
 |   m_nCount = pArgNumber->GetValue(); | 
 |   const MIuint64 nValue = pArgContents->GetValue(); | 
 |  | 
 |   m_pBufferMemory = new unsigned char[m_nCount]; | 
 |   if (m_pBufferMemory == nullptr) { | 
 |     SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_MEMORY_ALLOC_FAILURE), | 
 |                                    m_cmdData.strMiCmd.c_str(), m_nCount)); | 
 |     return MIstatus::failure; | 
 |   } | 
 |   *m_pBufferMemory = static_cast<char>(nValue); | 
 |  | 
 |   CMICmnLLDBDebugSessionInfo &rSessionInfo( | 
 |       CMICmnLLDBDebugSessionInfo::Instance()); | 
 |   lldb::SBProcess sbProcess = rSessionInfo.GetProcess(); | 
 |   lldb::SBError error; | 
 |   lldb::addr_t addr = static_cast<lldb::addr_t>(m_nAddr + nAddrOffset); | 
 |   const size_t nBytesWritten = sbProcess.WriteMemory( | 
 |       addr, (const void *)m_pBufferMemory, (size_t)m_nCount, error); | 
 |   if (nBytesWritten != static_cast<size_t>(m_nCount)) { | 
 |     SetError( | 
 |         CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_LLDB_ERR_NOT_WRITE_WHOLEBLK), | 
 |                               m_cmdData.strMiCmd.c_str(), m_nCount, addr)); | 
 |     return MIstatus::failure; | 
 |   } | 
 |   if (error.Fail()) { | 
 |     lldb::SBStream err; | 
 |     const bool bOk = error.GetDescription(err); | 
 |     MIunused(bOk); | 
 |     SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_LLDB_ERR_WRITE_MEM_BYTES), | 
 |                                    m_cmdData.strMiCmd.c_str(), m_nCount, addr, | 
 |                                    err.GetData())); | 
 |     return MIstatus::failure; | 
 |   } | 
 |  | 
 |   return MIstatus::success; | 
 | } | 
 |  | 
 | //++ | 
 | //------------------------------------------------------------------------------------ | 
 | // Details: The invoker requires this function. The command prepares a MI Record | 
 | // Result | 
 | //          for the work carried out in the Execute(). | 
 | // Type:    Overridden. | 
 | // Args:    None. | 
 | // Return:  MIstatus::success - Functional succeeded. | 
 | //          MIstatus::failure - Functional failed. | 
 | // Throws:  None. | 
 | //-- | 
 | bool CMICmdCmdDataWriteMemory::Acknowledge() { | 
 |   const CMICmnMIResultRecord miRecordResult( | 
 |       m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done); | 
 |   m_miResultRecord = miRecordResult; | 
 |  | 
 |   return MIstatus::success; | 
 | } | 
 |  | 
 | //++ | 
 | //------------------------------------------------------------------------------------ | 
 | // Details: Required by the CMICmdFactory when registering *this command. The | 
 | // factory | 
 | //          calls this function to create an instance of *this command. | 
 | // Type:    Static method. | 
 | // Args:    None. | 
 | // Return:  CMICmdBase * - Pointer to a new command. | 
 | // Throws:  None. | 
 | //-- | 
 | CMICmdBase *CMICmdCmdDataWriteMemory::CreateSelf() { | 
 |   return new CMICmdCmdDataWriteMemory(); | 
 | } | 
 |  | 
 | //--------------------------------------------------------------------------------------- | 
 | //--------------------------------------------------------------------------------------- | 
 | //--------------------------------------------------------------------------------------- | 
 |  | 
 | //++ | 
 | //------------------------------------------------------------------------------------ | 
 | // Details: CMICmdCmdDataInfoLine constructor. | 
 | // Type:    Method. | 
 | // Args:    None. | 
 | // Return:  None. | 
 | // Throws:  None. | 
 | //-- | 
 | CMICmdCmdDataInfoLine::CMICmdCmdDataInfoLine() | 
 |     : m_constStrArgLocation("location"), | 
 |       m_resultRecord(m_cmdData.strMiCmdToken, | 
 |                      CMICmnMIResultRecord::eResultClass_Done) { | 
 |   // Command factory matches this name with that received from the stdin stream | 
 |   m_strMiCmd = "data-info-line"; | 
 |  | 
 |   // Required by the CMICmdFactory when registering *this command | 
 |   m_pSelfCreatorFn = &CMICmdCmdDataInfoLine::CreateSelf; | 
 | } | 
 |  | 
 | //++ | 
 | //------------------------------------------------------------------------------------ | 
 | // Details: CMICmdCmdDataInfoLine destructor. | 
 | // Type:    Overrideable. | 
 | // Args:    None. | 
 | // Return:  None. | 
 | // Throws:  None. | 
 | //-- | 
 | CMICmdCmdDataInfoLine::~CMICmdCmdDataInfoLine() = default; | 
 |  | 
 | //++ | 
 | //------------------------------------------------------------------------------------ | 
 | // Details: The invoker requires this function. The parses the command line | 
 | // options | 
 | //          arguments to extract values for each of those arguments. | 
 | // Type:    Overridden. | 
 | // Args:    None. | 
 | // Return:  MIstatus::success - Functional succeeded. | 
 | //          MIstatus::failure - Functional failed. | 
 | // Throws:  None. | 
 | //-- | 
 | bool CMICmdCmdDataInfoLine::ParseArgs() { | 
 |   m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgLocation, true, true)); | 
 |   return ParseValidateCmdOptions(); | 
 | } | 
 |  | 
 | //++ | 
 | //------------------------------------------------------------------------------------ | 
 | // Details: The invoker requires this function. The command does work in this | 
 | // function. | 
 | //          The command is likely to communicate with the LLDB SBDebugger in | 
 | //          here. | 
 | // Type:    Overridden. | 
 | // Args:    None. | 
 | // Return:  MIstatus::success - Functional succeeded. | 
 | //          MIstatus::failure - Functional failed. | 
 | // Throws:  None. | 
 | //-- | 
 | bool CMICmdCmdDataInfoLine::Execute() { | 
 |   CMICMDBASE_GETOPTION(pArgLocation, String, m_constStrArgLocation); | 
 |  | 
 |   lldb::SBLineEntry line; | 
 |   bool found_line = false; | 
 |   const CMIUtilString &strLocation(pArgLocation->GetValue()); | 
 |   lldb::SBTarget target = CMICmnLLDBDebugSessionInfo::Instance().GetTarget(); | 
 |  | 
 |   if (strLocation.at(0) == '*') { | 
 |     // Parse argument: | 
 |     // *0x12345 | 
 |     // ^^^^^^^^^ -- address | 
 |     lldb::addr_t address = 0x0; | 
 |     if (llvm::StringRef(strLocation.substr(1)).getAsInteger(0, address)) { | 
 |       SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_SOME_ERROR), | 
 |                                      m_cmdData.strMiCmd.c_str(), | 
 |                                      "Failed to parse address.")); | 
 |       return MIstatus::failure; | 
 |     } | 
 |     line = target.ResolveFileAddress(address).GetLineEntry(); | 
 |     // Check that found line is valid. | 
 |     if (line.GetLine()) | 
 |       found_line = true; | 
 |   } else { | 
 |     const size_t nLineStartPos = strLocation.rfind(':'); | 
 |     if ((nLineStartPos == std::string::npos) || (nLineStartPos == 0) || | 
 |         (nLineStartPos == strLocation.length() - 1)) { | 
 |       SetError(CMIUtilString::Format( | 
 |           MIRSRC(IDS_CMD_ERR_INVALID_LOCATION_FORMAT), | 
 |           m_cmdData.strMiCmd.c_str(), strLocation.c_str())); | 
 |       return MIstatus::failure; | 
 |     } | 
 |     // Parse argument: | 
 |     // hello.cpp:5 | 
 |     // ^^^^^^^^^ -- file | 
 |     //           ^ -- line | 
 |     const CMIUtilString &strFile(strLocation.substr(0, nLineStartPos)); | 
 |     uint32_t numLine = 0; | 
 |     llvm::StringRef(strLocation.substr(nLineStartPos + 1)) | 
 |         .getAsInteger(0, numLine); | 
 |     lldb::SBSymbolContextList sc_cu_list = | 
 |         target.FindCompileUnits(lldb::SBFileSpec(strFile.c_str(), false)); | 
 |     for (uint32_t i = 0, e = sc_cu_list.GetSize(); i < e; ++i) { | 
 |       const lldb::SBCompileUnit &cu = | 
 |         sc_cu_list.GetContextAtIndex(i).GetCompileUnit(); | 
 |       // Break if we have already found requested line. | 
 |       if (found_line) | 
 |         break; | 
 |       for (uint32_t j = 0, e = cu.GetNumLineEntries(); j < e; ++j) { | 
 |         const lldb::SBLineEntry &curLine = cu.GetLineEntryAtIndex(j); | 
 |         if (curLine.GetLine() == numLine) { | 
 |           line = curLine; | 
 |           found_line = true; | 
 |           break; | 
 |         } | 
 |       } | 
 |     } | 
 |   } | 
 |   if (!found_line) { | 
 |     SetError(CMIUtilString::Format( | 
 |         MIRSRC(IDS_CMD_ERR_SOME_ERROR), m_cmdData.strMiCmd.c_str(), | 
 |         "The LineEntry is absent or has an unknown format.")); | 
 |     return MIstatus::failure; | 
 |   } | 
 |   // Start address. | 
 |   m_resultRecord.Add(CMICmnMIValueResult( | 
 |       "start", CMICmnMIValueConst(IntToHexAddrStr( | 
 |                line.GetStartAddress().GetFileAddress())))); | 
 |   // End address. | 
 |   m_resultRecord.Add(CMICmnMIValueResult( | 
 |       "end", CMICmnMIValueConst(IntToHexAddrStr( | 
 |              line.GetEndAddress().GetFileAddress())))); | 
 |   // File. | 
 |   std::unique_ptr<char[]> upPath(new char[PATH_MAX]); | 
 |   line.GetFileSpec().GetPath(upPath.get(), PATH_MAX); | 
 |   m_resultRecord.Add(CMICmnMIValueResult( | 
 |       "file", CMICmnMIValueConst(CMIUtilString(upPath.get())))); | 
 |   // Line. | 
 |   m_resultRecord.Add(CMICmnMIValueResult( | 
 |       "line", CMICmnMIValueConst(std::to_string(line.GetLine())))); | 
 |   return MIstatus::success; | 
 | } | 
 |  | 
 | //++ | 
 | //------------------------------------------------------------------------------------ | 
 | // Details: The invoker requires this function. The command prepares a MI Record | 
 | // Result | 
 | //          for the work carried out in the Execute(). | 
 | // Type:    Overridden. | 
 | // Args:    None. | 
 | // Return:  MIstatus::success - Functional succeeded. | 
 | //          MIstatus::failure - Functional failed. | 
 | // Throws:  None. | 
 | //-- | 
 | bool CMICmdCmdDataInfoLine::Acknowledge() { | 
 |   m_miResultRecord = m_resultRecord; | 
 |   return MIstatus::success; | 
 | } | 
 |  | 
 | //++ | 
 | //------------------------------------------------------------------------------------ | 
 | // Details: Required by the CMICmdFactory when registering *this command. The | 
 | // factory | 
 | //          calls this function to create an instance of *this command. | 
 | // Type:    Static method. | 
 | // Args:    None. | 
 | // Return:  CMICmdBase * - Pointer to a new command. | 
 | // Throws:  None. | 
 | //-- | 
 | CMICmdBase *CMICmdCmdDataInfoLine::CreateSelf() { | 
 |   return new CMICmdCmdDataInfoLine(); | 
 | } |