summaryrefslogtreecommitdiff
path: root/contrib/llvm-project/lldb/tools/lldb-mi/MICmdCmdData.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/lldb/tools/lldb-mi/MICmdCmdData.cpp')
-rw-r--r--contrib/llvm-project/lldb/tools/lldb-mi/MICmdCmdData.cpp1673
1 files changed, 1673 insertions, 0 deletions
diff --git a/contrib/llvm-project/lldb/tools/lldb-mi/MICmdCmdData.cpp b/contrib/llvm-project/lldb/tools/lldb-mi/MICmdCmdData.cpp
new file mode 100644
index 000000000000..e0a165765199
--- /dev/null
+++ b/contrib/llvm-project/lldb/tools/lldb-mi/MICmdCmdData.cpp
@@ -0,0 +1,1673 @@
+//===-- MICmdCmdData.cpp ----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// 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/StringRef.h"
+#include "llvm/ADT/Twine.h"
+#include <inttypes.h>
+#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;
+ // Get a full path to the file.
+ char pathBuffer[PATH_MAX];
+ lineEntry.GetFileSpec().GetPath(pathBuffer, PATH_MAX);
+
+ // MI "src_and_asm_line={line=\"%u\",file=\"%s\",line_asm_insn=[ ],
+ // fullname=\"%s\"}"
+ const CMICmnMIValueConst miValueConst(
+ CMIUtilString::Format("%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 CMICmnMIValueConst miValueConst5(pathBuffer);
+ const CMICmnMIValueResult miValueResult5("fullname", miValueConst5);
+ miValueTuple2.Add(miValueResult5);
+ 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();
+}