Files
clang-p2996/lldb/tools/lldb-mi/MICmdCmdData.cpp
Kate Stone b9c1b51e45 *** This commit represents a complete reformatting of the LLDB source code
*** to conform to clang-format’s LLVM style.  This kind of mass change has
*** two obvious implications:

Firstly, merging this particular commit into a downstream fork may be a huge
effort.  Alternatively, it may be worth merging all changes up to this commit,
performing the same reformatting operation locally, and then discarding the
merge for this particular commit.  The commands used to accomplish this
reformatting were as follows (with current working directory as the root of
the repository):

    find . \( -iname "*.c" -or -iname "*.cpp" -or -iname "*.h" -or -iname "*.mm" \) -exec clang-format -i {} +
    find . -iname "*.py" -exec autopep8 --in-place --aggressive --aggressive {} + ;

The version of clang-format used was 3.9.0, and autopep8 was 1.2.4.

Secondly, “blame” style tools will generally point to this commit instead of
a meaningful prior commit.  There are alternatives available that will attempt
to look through this change and find the appropriate prior commit.  YMMV.

llvm-svn: 280751
2016-09-06 20:57:50 +00:00

1822 lines
69 KiB
C++

//===-- 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/SBCommandInterpreter.h"
#include "lldb/API/SBInstruction.h"
#include "lldb/API/SBInstructionList.h"
#include "lldb/API/SBStream.h"
#include "lldb/API/SBThread.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Regex.h"
#include <inttypes.h> // For PRIx64
// 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"
//++
//------------------------------------------------------------------------------------
// 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") {
// 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() {}
//++
//------------------------------------------------------------------------------------
// 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);
const CMIUtilString &strLocation(pArgLocation->GetValue());
CMIUtilString strCmdOptionsLocation;
if (strLocation.at(0) == '*') {
// Parse argument:
// *0x12345
// ^^^^^^^ -- address
const CMIUtilString strAddress(strLocation.substr(1));
strCmdOptionsLocation =
CMIUtilString::Format("--address %s", strAddress.c_str());
} 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())
.c_str());
return MIstatus::failure;
}
// Parse argument:
// hello.cpp:5
// ^^^^^^^^^ -- file
// ^ -- line
const CMIUtilString strFile(strLocation.substr(0, nLineStartPos));
const CMIUtilString strLine(strLocation.substr(nLineStartPos + 1));
strCmdOptionsLocation =
CMIUtilString::Format("--file \"%s\" --line %s",
strFile.AddSlashes().c_str(), strLine.c_str());
}
const CMIUtilString strCmd(CMIUtilString::Format(
"target modules lookup -v %s", strCmdOptionsLocation.c_str()));
CMICmnLLDBDebugSessionInfo &rSessionInfo(
CMICmnLLDBDebugSessionInfo::Instance());
const lldb::ReturnStatus rtn =
rSessionInfo.GetDebugger().GetCommandInterpreter().HandleCommand(
strCmd.c_str(), m_lldbResult);
MIunused(rtn);
return MIstatus::success;
}
//++
//------------------------------------------------------------------------------------
// Details: Helper function for parsing a line entry returned from lldb for the
// command:
// target modules lookup -v <location>
// where the line entry is of the format:
// LineEntry: \[0x0000000100000f37-0x0000000100000f45\):
// /path/file:3[:1]
// start end file
// line column(opt)
// Args: input - (R) Input string to parse.
// start - (W) String representing the start address.
// end - (W) String representing the end address.
// file - (W) String representing the file.
// line - (W) String representing the line.
// Return: bool - True = input was parsed successfully, false = input could not
// be parsed.
// Throws: None.
//--
static bool ParseLLDBLineEntry(const char *input, CMIUtilString &start,
CMIUtilString &end, CMIUtilString &file,
CMIUtilString &line) {
// Note: Ambiguities arise because the column is optional, and
// because : can appear in filenames or as a byte in a multibyte
// UTF8 character. We keep those cases to a minimum by using regex
// to work on the string from both the left and right, so that what
// is remains is assumed to be the filename.
// Match LineEntry using regex.
static llvm::Regex g_lineentry_nocol_regex(llvm::StringRef(
"^ *LineEntry: \\[(0x[0-9a-fA-F]+)-(0x[0-9a-fA-F]+)\\): (.+):([0-9]+)$"));
static llvm::Regex g_lineentry_col_regex(
llvm::StringRef("^ *LineEntry: \\[(0x[0-9a-fA-F]+)-(0x[0-9a-fA-F]+)\\): "
"(.+):([0-9]+):[0-9]+$"));
// ^1=start ^2=end ^3=f
// ^4=line ^5=:col(opt)
llvm::SmallVector<llvm::StringRef, 6> match;
// First try matching the LineEntry with the column,
// then try without the column.
const bool ok = g_lineentry_col_regex.match(input, &match) ||
g_lineentry_nocol_regex.match(input, &match);
if (ok) {
start = match[1];
end = match[2];
file = match[3];
line = match[4];
}
return ok;
}
//++
//------------------------------------------------------------------------------------
// 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() {
if (m_lldbResult.GetErrorSize() > 0) {
const CMICmnMIValueConst miValueConst(m_lldbResult.GetError());
const CMICmnMIValueResult miValueResult("msg", miValueConst);
const CMICmnMIResultRecord miRecordResult(
m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error,
miValueResult);
m_miResultRecord = miRecordResult;
return MIstatus::success;
} else if (m_lldbResult.GetOutputSize() > 0) {
CMIUtilString::VecString_t vecLines;
const CMIUtilString strLldbMsg(m_lldbResult.GetOutput());
const MIuint nLines(strLldbMsg.SplitLines(vecLines));
for (MIuint i = 0; i < nLines; ++i) {
// String looks like:
// LineEntry: \[0x0000000100000f37-0x0000000100000f45\):
// /path/to/file:3[:1]
const CMIUtilString &rLine(vecLines[i]);
CMIUtilString strStart;
CMIUtilString strEnd;
CMIUtilString strFile;
CMIUtilString strLine;
if (!ParseLLDBLineEntry(rLine.c_str(), strStart, strEnd, strFile,
strLine))
continue;
const CMICmnMIValueConst miValueConst(strStart);
const CMICmnMIValueResult miValueResult("start", miValueConst);
CMICmnMIResultRecord miRecordResult(
m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done,
miValueResult);
const CMICmnMIValueConst miValueConst2(strEnd);
const CMICmnMIValueResult miValueResult2("end", miValueConst2);
miRecordResult.Add(miValueResult2);
const CMICmnMIValueConst miValueConst3(strFile);
const CMICmnMIValueResult miValueResult3("file", miValueConst3);
miRecordResult.Add(miValueResult3);
const CMICmnMIValueConst miValueConst4(strLine);
const CMICmnMIValueResult miValueResult4("line", miValueConst4);
miRecordResult.Add(miValueResult4);
// MI print "%s^done,start=\"%d\",end=\"%d\"",file=\"%s\",line=\"%d\"
m_miResultRecord = miRecordResult;
return MIstatus::success;
}
}
// MI print "%s^error,msg=\"Command '-data-info-line'. Error: The LineEntry is
// absent or has an unknown format.\""
const CMICmnMIValueConst miValueConst(CMIUtilString::Format(
MIRSRC(IDS_CMD_ERR_SOME_ERROR), m_cmdData.strMiCmd.c_str(),
"The LineEntry is absent or has an unknown format."));
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 *CMICmdCmdDataInfoLine::CreateSelf() {
return new CMICmdCmdDataInfoLine();
}