forked from OSchip/llvm-project
Fix -data-read-memory-bytes command (MI)
Summary: * Add IsHexadecimalNumber method to CMIUtilString (MI) * Add number format (dec,hex,auto) to CMICmdArgValNumber (MI) * Fix -data-read-memory-bytes to pass address in hex format (MI) * Fix output begin/end/offset fields format in -data-read-memory-bytes * Fix CMICmdArgValNumber::ExtractNumber to extract 64bit value * + tests All tests passed on OS X Reviewers: abidh, zturner, clayborg Reviewed By: clayborg Subscribers: lldb-commits, zturner, clayborg, abidh Differential Revision: http://reviews.llvm.org/D7610 llvm-svn: 229132
This commit is contained in:
parent
a4897fe79c
commit
b4a110f051
|
@ -35,6 +35,34 @@ class MiDataTestCase(lldbmi_testcase.MiTestCaseBase):
|
|||
self.runCmd("-data-disassemble -s %#x -e %#x -- 0" % (addr, addr + 0x10))
|
||||
self.expect("\^done,asm_insns=\[{address=\"0x%08x\",func-name=\"main\",offset=\"0\",size=\"[1-9]+\",inst=\".+\"}," % addr)
|
||||
|
||||
@lldbmi_test
|
||||
@expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows")
|
||||
def test_lldbmi_data_read_memory_bytes(self):
|
||||
"""Test that 'lldb-mi --interpreter' works for -data-read-memory-bytes."""
|
||||
|
||||
self.spawnLldbMi(args = None)
|
||||
|
||||
# Load executable
|
||||
self.runCmd("-file-exec-and-symbols %s" % self.myexe)
|
||||
self.expect("\^done")
|
||||
|
||||
# Run to main
|
||||
self.runCmd("-break-insert -f main")
|
||||
self.expect("\^done,bkpt={number=\"1\"")
|
||||
self.runCmd("-exec-run")
|
||||
self.expect("\^running")
|
||||
self.expect("\*stopped,reason=\"breakpoint-hit\"")
|
||||
|
||||
# Get address of s_RawData
|
||||
self.runCmd("-data-evaluate-expression &s_RawData")
|
||||
self.expect("\^done,value=\"0x[0-9a-f]+\"",timeout=1)
|
||||
addr = int(self.child.after.split("\"")[1], 16)
|
||||
size = 5
|
||||
|
||||
# Test -data-read-memory-bytes: try to read data of s_RawData
|
||||
self.runCmd("-data-read-memory-bytes %#x %d" % (addr, size))
|
||||
self.expect("\^done,memory=\[{begin=\"0x0*%x\",offset=\"0x0+\",end=\"0x0*%x\",contents=\"1234567800\"}\]" % (addr, addr + size))
|
||||
|
||||
@lldbmi_test
|
||||
@expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows")
|
||||
def test_lldbmi_data_list_register_names(self):
|
||||
|
|
|
@ -152,22 +152,22 @@ class MiExecTestCase(lldbmi_testcase.MiTestCaseBase):
|
|||
# Test -exec-next
|
||||
self.runCmd("-exec-next --thread 1 --frame 0")
|
||||
self.expect("\^running")
|
||||
self.expect("\*stopped,reason=\"end-stepping-range\".*main.c\",line=\"24\"")
|
||||
self.expect("\*stopped,reason=\"end-stepping-range\".*main.c\",line=\"26\"")
|
||||
|
||||
# Test that --thread is optional
|
||||
self.runCmd("-exec-next --frame 0")
|
||||
self.expect("\^running")
|
||||
self.expect("\*stopped,reason=\"end-stepping-range\".*main.c\",line=\"25\"")
|
||||
self.expect("\*stopped,reason=\"end-stepping-range\".*main.c\",line=\"27\"")
|
||||
|
||||
# Test that --frame is optional
|
||||
self.runCmd("-exec-next --thread 1")
|
||||
self.expect("\^running")
|
||||
self.expect("\*stopped,reason=\"end-stepping-range\".*main.c\",line=\"27\"")
|
||||
self.expect("\*stopped,reason=\"end-stepping-range\".*main.c\",line=\"29\"")
|
||||
|
||||
# Test that both --thread and --frame are optional
|
||||
self.runCmd("-exec-next --thread 1")
|
||||
self.expect("\^running")
|
||||
self.expect("\*stopped,reason=\"end-stepping-range\".*main.c\",line=\"29\"")
|
||||
self.expect("\*stopped,reason=\"end-stepping-range\".*main.c\",line=\"31\"")
|
||||
|
||||
# Test that an invalid --thread is handled
|
||||
self.runCmd("-exec-next --thread 0")
|
||||
|
@ -204,23 +204,23 @@ class MiExecTestCase(lldbmi_testcase.MiTestCaseBase):
|
|||
# Test -exec-next-instruction
|
||||
self.runCmd("-exec-next-instruction --thread 1 --frame 0")
|
||||
self.expect("\^running")
|
||||
self.expect("\*stopped,reason=\"end-stepping-range\".*main.c\",line=\"22\"")
|
||||
self.expect("\*stopped,reason=\"end-stepping-range\".*main.c\",line=\"24\"")
|
||||
|
||||
# Test that --thread is optional
|
||||
self.runCmd("-exec-next-instruction --frame 0")
|
||||
self.expect("\^running")
|
||||
self.expect("\*stopped,reason=\"end-stepping-range\".*main.c\",line=\"22\"")
|
||||
self.expect("\*stopped,reason=\"end-stepping-range\".*main.c\",line=\"24\"")
|
||||
|
||||
# Test that --frame is optional
|
||||
self.runCmd("-exec-next-instruction --thread 1")
|
||||
self.expect("\^running")
|
||||
self.expect("\*stopped,reason=\"end-stepping-range\".*main.c\",line=\"22\"")
|
||||
self.expect("\*stopped,reason=\"end-stepping-range\".*main.c\",line=\"24\"")
|
||||
|
||||
# Test that both --thread and --frame are optional
|
||||
self.runCmd("-exec-next-instruction --thread 1")
|
||||
self.expect("\^running")
|
||||
# Depending on compiler, it can stop at different line.
|
||||
self.expect("\*stopped,reason=\"end-stepping-range\".*main.c\",line=\"2[2-4]\"")
|
||||
self.expect("\*stopped,reason=\"end-stepping-range\".*main.c\",line=\"2[4-6]\"")
|
||||
|
||||
# Test that an invalid --thread is handled
|
||||
self.runCmd("-exec-next-instruction --thread 0")
|
||||
|
@ -259,7 +259,7 @@ class MiExecTestCase(lldbmi_testcase.MiTestCaseBase):
|
|||
#FIXME: is this supposed to step into printf?
|
||||
self.runCmd("-exec-step --thread 1 --frame 0")
|
||||
self.expect("\^running")
|
||||
self.expect("\*stopped,reason=\"end-stepping-range\".*main.c\",line=\"24\"")
|
||||
self.expect("\*stopped,reason=\"end-stepping-range\".*main.c\",line=\"26\"")
|
||||
|
||||
# Test that -exec-step steps into a_MyFunction and back out
|
||||
# (and that --thread is optional)
|
||||
|
@ -274,10 +274,10 @@ class MiExecTestCase(lldbmi_testcase.MiTestCaseBase):
|
|||
# -exec-step can keep us in the a_MyFunction for gcc
|
||||
self.runCmd("-exec-finish --frame 0")
|
||||
self.expect("\^running")
|
||||
self.expect("\*stopped,reason=\"end-stepping-range\".*main.c\",line=\"24\"")
|
||||
self.expect("\*stopped,reason=\"end-stepping-range\".*main.c\",line=\"26\"")
|
||||
self.runCmd("-exec-step --frame 0")
|
||||
self.expect("\^running")
|
||||
self.expect("\*stopped,reason=\"end-stepping-range\".*main.c\",line=\"25\"")
|
||||
self.expect("\*stopped,reason=\"end-stepping-range\".*main.c\",line=\"27\"")
|
||||
|
||||
# Test that -exec-step steps into b_MyFunction
|
||||
# (and that --frame is optional)
|
||||
|
@ -329,13 +329,13 @@ class MiExecTestCase(lldbmi_testcase.MiTestCaseBase):
|
|||
# instruction
|
||||
self.runCmd("-exec-step-instruction --thread 1 --frame 0")
|
||||
self.expect("\^running")
|
||||
self.expect("\*stopped,reason=\"end-stepping-range\".*main.c\",line=\"2[2-4]\"")
|
||||
self.expect("\*stopped,reason=\"end-stepping-range\".*main.c\",line=\"2[4-6]\"")
|
||||
|
||||
# Test that -exec-step-instruction steps over non branching
|
||||
# instruction (and that --thread is optional)
|
||||
self.runCmd("-exec-step-instruction --frame 0")
|
||||
self.expect("\^running")
|
||||
self.expect("\*stopped,reason=\"end-stepping-range\".*main.c\",line=\"2[2-4]\"")
|
||||
self.expect("\*stopped,reason=\"end-stepping-range\".*main.c\",line=\"2[4-6]\"")
|
||||
|
||||
# Test that -exec-step-instruction steps into a_MyFunction
|
||||
# (and that --frame is optional)
|
||||
|
|
|
@ -15,6 +15,8 @@ extern int local_test();
|
|||
int doloop, dosegfault;
|
||||
int g_MyVar = 3;
|
||||
static int s_MyVar = 4;
|
||||
//FIXME -data-evaluate-expression/print can't evaluate value of type "static char[]"
|
||||
const char s_RawData[] = "\x12\x34\x56\x78"; //FIXME static const char s_RawData[] = "\x12\x34\x56\x78";
|
||||
|
||||
int main (int argc, char const *argv[])
|
||||
{
|
||||
|
|
|
@ -31,21 +31,25 @@
|
|||
// Throws: None.
|
||||
//--
|
||||
CMICmdArgValNumber::CMICmdArgValNumber(void)
|
||||
: m_nNumber(0)
|
||||
: m_nNumberFormatMask(CMICmdArgValNumber::eArgValNumberFormat_Decimal)
|
||||
, m_nNumber(0)
|
||||
{
|
||||
}
|
||||
|
||||
//++ ------------------------------------------------------------------------------------
|
||||
// Details: CMICmdArgValNumber constructor.
|
||||
// Type: Method.
|
||||
// Args: vrArgName - (R) Argument's name to search by.
|
||||
// vbMandatory - (R) True = Yes must be present, false = optional argument.
|
||||
// vbHandleByCmd - (R) True = Command processes *this option, false = not handled.
|
||||
// Args: vrArgName - (R) Argument's name to search by.
|
||||
// vbMandatory - (R) True = Yes must be present, false = optional argument.
|
||||
// vbHandleByCmd - (R) True = Command processes *this option, false = not handled.
|
||||
// vnNumberFormatMask - (R) Mask of the number formats. (Dflt = CMICmdArgValNumber::eArgValNumberFormat_Decimal)
|
||||
// Return: None.
|
||||
// Throws: None.
|
||||
//--
|
||||
CMICmdArgValNumber::CMICmdArgValNumber(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd)
|
||||
CMICmdArgValNumber::CMICmdArgValNumber(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd,
|
||||
const MIuint vnNumberFormatMask /* = CMICmdArgValNumber::eArgValNumberFormat_Decimal*/)
|
||||
: CMICmdArgValBaseTemplate(vrArgName, vbMandatory, vbHandleByCmd)
|
||||
, m_nNumberFormatMask(vnNumberFormatMask)
|
||||
, m_nNumber(0)
|
||||
{
|
||||
}
|
||||
|
@ -128,11 +132,20 @@ CMICmdArgValNumber::Validate(CMICmdArgContext &vwArgContext)
|
|||
bool
|
||||
CMICmdArgValNumber::IsArgNumber(const CMIUtilString &vrTxt) const
|
||||
{
|
||||
const bool bFormatDecimal(m_nNumberFormatMask & CMICmdArgValNumber::eArgValNumberFormat_Decimal);
|
||||
const bool bFormatHexadecimal(m_nNumberFormatMask & CMICmdArgValNumber::eArgValNumberFormat_Hexadecimal);
|
||||
|
||||
// Look for --someLongOption
|
||||
if (std::string::npos != vrTxt.find("--"))
|
||||
return false;
|
||||
|
||||
return vrTxt.IsNumber();
|
||||
if (bFormatDecimal && vrTxt.IsNumber())
|
||||
return true;
|
||||
|
||||
if (bFormatHexadecimal && vrTxt.IsHexadecimalNumber())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//++ ------------------------------------------------------------------------------------
|
||||
|
@ -150,7 +163,7 @@ CMICmdArgValNumber::ExtractNumber(const CMIUtilString &vrTxt)
|
|||
bool bOk = vrTxt.ExtractNumber(nNumber);
|
||||
if (bOk)
|
||||
{
|
||||
m_nNumber = static_cast<MIint>(nNumber);
|
||||
m_nNumber = static_cast<MIint64>(nNumber);
|
||||
}
|
||||
|
||||
return bOk;
|
||||
|
|
|
@ -40,10 +40,24 @@ class CMICmdArgContext;
|
|||
//--
|
||||
class CMICmdArgValNumber : public CMICmdArgValBaseTemplate<MIint64>
|
||||
{
|
||||
// Enums:
|
||||
public:
|
||||
//++ ---------------------------------------------------------------------------------
|
||||
// Details: CMICmdArgValNumber needs to know what format of argument to look for in
|
||||
// the command options text.
|
||||
//--
|
||||
enum ArgValNumberFormat_e
|
||||
{
|
||||
eArgValNumberFormat_Decimal = (1u << 0),
|
||||
eArgValNumberFormat_Hexadecimal = (1u << 1),
|
||||
eArgValNumberFormat_Auto = ((eArgValNumberFormat_Hexadecimal << 1) - 1u) ///< Indicates to try and lookup everything up during a query.
|
||||
};
|
||||
|
||||
// Methods:
|
||||
public:
|
||||
/* ctor */ CMICmdArgValNumber(void);
|
||||
/* ctor */ CMICmdArgValNumber(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd);
|
||||
/* ctor */ CMICmdArgValNumber(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd,
|
||||
const MIuint vnNumberFormatMask = eArgValNumberFormat_Decimal);
|
||||
//
|
||||
bool IsArgNumber(const CMIUtilString &vrTxt) const;
|
||||
|
||||
|
@ -61,5 +75,6 @@ class CMICmdArgValNumber : public CMICmdArgValBaseTemplate<MIint64>
|
|||
|
||||
// Attributes:
|
||||
private:
|
||||
MIuint m_nNumberFormatMask;
|
||||
MIint64 m_nNumber;
|
||||
};
|
||||
|
|
|
@ -568,7 +568,7 @@ CMICmdCmdDataReadMemoryBytes::ParseArgs(void)
|
|||
bOk =
|
||||
bOk &&
|
||||
m_setCmdArgs.Add(*(new CMICmdArgValOptionShort(m_constStrArgByteOffset, false, true, CMICmdArgValListBase::eArgValType_Number, 1)));
|
||||
bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValNumber(m_constStrArgAddrStart, true, true)));
|
||||
bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValNumber(m_constStrArgAddrStart, true, true, CMICmdArgValNumber::eArgValNumberFormat_Auto)));
|
||||
bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValNumber(m_constStrArgNumBytes, true, true)));
|
||||
return (bOk && ParseValidateCmdOptions());
|
||||
}
|
||||
|
@ -640,13 +640,13 @@ bool
|
|||
CMICmdCmdDataReadMemoryBytes::Acknowledge(void)
|
||||
{
|
||||
// MI: memory=[{begin=\"0x%08x\",offset=\"0x%08x\",end=\"0x%08x\",contents=\" \" }]"
|
||||
const CMICmnMIValueConst miValueConst(CMIUtilString::Format("0x%08x", m_nAddrStart));
|
||||
const CMICmnMIValueConst miValueConst(CMIUtilString::Format("0x%08llx", m_nAddrStart));
|
||||
const CMICmnMIValueResult miValueResult("begin", miValueConst);
|
||||
CMICmnMIValueTuple miValueTuple(miValueResult);
|
||||
const CMICmnMIValueConst miValueConst2(CMIUtilString::Format("0x%08x", m_nAddrOffset));
|
||||
const CMICmnMIValueConst miValueConst2(CMIUtilString::Format("0x%08llx", m_nAddrOffset));
|
||||
const CMICmnMIValueResult miValueResult2("offset", miValueConst2);
|
||||
miValueTuple.Add(miValueResult2);
|
||||
const CMICmnMIValueConst miValueConst3(CMIUtilString::Format("0x%08x", m_nAddrStart + m_nAddrNumBytesToRead));
|
||||
const CMICmnMIValueConst miValueConst3(CMIUtilString::Format("0x%08llx", m_nAddrStart + m_nAddrNumBytesToRead));
|
||||
const CMICmnMIValueResult miValueResult3("end", miValueConst3);
|
||||
miValueTuple.Add(miValueResult3);
|
||||
|
||||
|
@ -655,7 +655,7 @@ CMICmdCmdDataReadMemoryBytes::Acknowledge(void)
|
|||
strContent.reserve((m_nAddrNumBytesToRead << 1) + 1);
|
||||
for (MIuint64 i = 0; i < m_nAddrNumBytesToRead; i++)
|
||||
{
|
||||
strContent += CMIUtilString::Format("%02x", m_pBufferMemory[i]);
|
||||
strContent += CMIUtilString::Format("%02hhx", m_pBufferMemory[i]);
|
||||
}
|
||||
const CMICmnMIValueConst miValueConst4(strContent);
|
||||
const CMICmnMIValueResult miValueResult4("contents", miValueConst4);
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
#include <memory> // std::unique_ptr
|
||||
#include <stdarg.h> // va_list, va_start, var_end
|
||||
#include <sstream> // std::stringstream
|
||||
#include <string.h> // for strcpy
|
||||
#include <string.h> // for strncmp
|
||||
#include <limits.h> // for ULONG_MAX
|
||||
|
||||
// In-house headers:
|
||||
|
@ -394,6 +394,28 @@ CMIUtilString::IsNumber(void) const
|
|||
return true;
|
||||
}
|
||||
|
||||
//++ ------------------------------------------------------------------------------------
|
||||
// Details: Check if *this string is a hexadecimal number.
|
||||
// Type: Method.
|
||||
// Args: None.
|
||||
// Return: bool - True = yes number, false not a number.
|
||||
// Throws: None.
|
||||
//--
|
||||
bool
|
||||
CMIUtilString::IsHexadecimalNumber(void) const
|
||||
{
|
||||
// Compare '0x..' prefix
|
||||
if ((strncmp(c_str(), "0x", 2) != 0) && (strncmp(c_str(), "0X", 2) != 0))
|
||||
return false;
|
||||
|
||||
// Skip '0x..' prefix
|
||||
const MIint nPos = find_first_not_of("01234567890ABCDEFabcedf", 2);
|
||||
if (nPos != (MIint)std::string::npos)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//++ ------------------------------------------------------------------------------------
|
||||
// Details: Extract the number from the string. The number can be either a hexadecimal or
|
||||
// natural number. It cannot contain other non-numeric characters.
|
||||
|
@ -433,16 +455,16 @@ CMIUtilString::ExtractNumberFromHexadecimal(MIint64 &vwrNumber) const
|
|||
{
|
||||
vwrNumber = 0;
|
||||
|
||||
const MIint nPos = find_first_not_of("x01234567890ABCDEFabcedf");
|
||||
const MIint nPos = find_first_not_of("xX01234567890ABCDEFabcedf");
|
||||
if (nPos != (MIint)std::string::npos)
|
||||
return false;
|
||||
|
||||
const MIint64 nNum = ::strtoul(this->c_str(), nullptr, 16);
|
||||
if (nNum != LONG_MAX)
|
||||
{
|
||||
vwrNumber = nNum;
|
||||
return true;
|
||||
}
|
||||
errno = 0;
|
||||
const MIuint64 nNum = ::strtoull(this->c_str(), nullptr, 16);
|
||||
if (errno == ERANGE)
|
||||
return false;
|
||||
|
||||
vwrNumber = static_cast<MIint64>(nNum);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -58,6 +58,7 @@ class CMIUtilString : public std::string
|
|||
bool ExtractNumber(MIint64 &vwrNumber) const;
|
||||
CMIUtilString FindAndReplace(const CMIUtilString &vFind, const CMIUtilString &vReplaceWith) const;
|
||||
bool IsNumber(void) const;
|
||||
bool IsHexadecimalNumber(void) const;
|
||||
bool IsQuoted(void) const;
|
||||
CMIUtilString RemoveRepeatedCharacters(const MIchar vChar);
|
||||
MIuint Split(const CMIUtilString &vDelimiter, VecString_t &vwVecSplits) const;
|
||||
|
|
Loading…
Reference in New Issue