diff options
| -rw-r--r-- | lldb/test/tools/lldb-mi/TestMiData.py | 28 | ||||
| -rw-r--r-- | lldb/test/tools/lldb-mi/TestMiExec.py | 26 | ||||
| -rw-r--r-- | lldb/test/tools/lldb-mi/main.c | 2 | ||||
| -rw-r--r-- | lldb/tools/lldb-mi/MICmdArgValNumber.cpp | 27 | ||||
| -rw-r--r-- | lldb/tools/lldb-mi/MICmdArgValNumber.h | 17 | ||||
| -rw-r--r-- | lldb/tools/lldb-mi/MICmdCmdData.cpp | 10 | ||||
| -rw-r--r-- | lldb/tools/lldb-mi/MIUtilString.cpp | 38 | ||||
| -rw-r--r-- | lldb/tools/lldb-mi/MIUtilString.h | 1 |
8 files changed, 115 insertions, 34 deletions
diff --git a/lldb/test/tools/lldb-mi/TestMiData.py b/lldb/test/tools/lldb-mi/TestMiData.py index 8d59197eca8..d01b1c4dd32 100644 --- a/lldb/test/tools/lldb-mi/TestMiData.py +++ b/lldb/test/tools/lldb-mi/TestMiData.py @@ -37,6 +37,34 @@ class MiDataTestCase(lldbmi_testcase.MiTestCaseBase): @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): """Test that 'lldb-mi --interpreter' works for -data-list-register-names.""" diff --git a/lldb/test/tools/lldb-mi/TestMiExec.py b/lldb/test/tools/lldb-mi/TestMiExec.py index 0936f40c321..79c32ebee3b 100644 --- a/lldb/test/tools/lldb-mi/TestMiExec.py +++ b/lldb/test/tools/lldb-mi/TestMiExec.py @@ -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) diff --git a/lldb/test/tools/lldb-mi/main.c b/lldb/test/tools/lldb-mi/main.c index 3398e35a8a8..d8083e01371 100644 --- a/lldb/test/tools/lldb-mi/main.c +++ b/lldb/test/tools/lldb-mi/main.c @@ -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[]) { diff --git a/lldb/tools/lldb-mi/MICmdArgValNumber.cpp b/lldb/tools/lldb-mi/MICmdArgValNumber.cpp index 8b1878df028..bfe4d6d564a 100644 --- a/lldb/tools/lldb-mi/MICmdArgValNumber.cpp +++ b/lldb/tools/lldb-mi/MICmdArgValNumber.cpp @@ -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; diff --git a/lldb/tools/lldb-mi/MICmdArgValNumber.h b/lldb/tools/lldb-mi/MICmdArgValNumber.h index 1a782e1af38..ac1be7b47a0 100644 --- a/lldb/tools/lldb-mi/MICmdArgValNumber.h +++ b/lldb/tools/lldb-mi/MICmdArgValNumber.h @@ -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; }; diff --git a/lldb/tools/lldb-mi/MICmdCmdData.cpp b/lldb/tools/lldb-mi/MICmdCmdData.cpp index 5ef97a4915c..9e25e546e30 100644 --- a/lldb/tools/lldb-mi/MICmdCmdData.cpp +++ b/lldb/tools/lldb-mi/MICmdCmdData.cpp @@ -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); diff --git a/lldb/tools/lldb-mi/MIUtilString.cpp b/lldb/tools/lldb-mi/MIUtilString.cpp index 08540926901..70294285d9f 100644 --- a/lldb/tools/lldb-mi/MIUtilString.cpp +++ b/lldb/tools/lldb-mi/MIUtilString.cpp @@ -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: @@ -395,6 +395,28 @@ CMIUtilString::IsNumber(void) const } //++ ------------------------------------------------------------------------------------ +// 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. // Type: Method. @@ -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; } diff --git a/lldb/tools/lldb-mi/MIUtilString.h b/lldb/tools/lldb-mi/MIUtilString.h index cf5528c1070..c30dca3d7b4 100644 --- a/lldb/tools/lldb-mi/MIUtilString.h +++ b/lldb/tools/lldb-mi/MIUtilString.h @@ -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; |

