[Lldb-commits] [lldb] r229132 - Fix -data-read-memory-bytes command (MI)

Ilia K ki.stfu at gmail.com
Fri Feb 13 10:42:25 PST 2015


Author: ki.stfu
Date: Fri Feb 13 12:42:25 2015
New Revision: 229132

URL: http://llvm.org/viewvc/llvm-project?rev=229132&view=rev
Log:
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

Modified:
    lldb/trunk/test/tools/lldb-mi/TestMiData.py
    lldb/trunk/test/tools/lldb-mi/TestMiExec.py
    lldb/trunk/test/tools/lldb-mi/main.c
    lldb/trunk/tools/lldb-mi/MICmdArgValNumber.cpp
    lldb/trunk/tools/lldb-mi/MICmdArgValNumber.h
    lldb/trunk/tools/lldb-mi/MICmdCmdData.cpp
    lldb/trunk/tools/lldb-mi/MIUtilString.cpp
    lldb/trunk/tools/lldb-mi/MIUtilString.h

Modified: lldb/trunk/test/tools/lldb-mi/TestMiData.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/tools/lldb-mi/TestMiData.py?rev=229132&r1=229131&r2=229132&view=diff
==============================================================================
--- lldb/trunk/test/tools/lldb-mi/TestMiData.py (original)
+++ lldb/trunk/test/tools/lldb-mi/TestMiData.py Fri Feb 13 12:42:25 2015
@@ -37,6 +37,34 @@ class MiDataTestCase(lldbmi_testcase.MiT
 
     @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."""
 

Modified: lldb/trunk/test/tools/lldb-mi/TestMiExec.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/tools/lldb-mi/TestMiExec.py?rev=229132&r1=229131&r2=229132&view=diff
==============================================================================
--- lldb/trunk/test/tools/lldb-mi/TestMiExec.py (original)
+++ lldb/trunk/test/tools/lldb-mi/TestMiExec.py Fri Feb 13 12:42:25 2015
@@ -152,22 +152,22 @@ class MiExecTestCase(lldbmi_testcase.MiT
         # 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.MiT
         # 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.MiT
         #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.MiT
         # -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.MiT
         # 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)

Modified: lldb/trunk/test/tools/lldb-mi/main.c
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/tools/lldb-mi/main.c?rev=229132&r1=229131&r2=229132&view=diff
==============================================================================
--- lldb/trunk/test/tools/lldb-mi/main.c (original)
+++ lldb/trunk/test/tools/lldb-mi/main.c Fri Feb 13 12:42:25 2015
@@ -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[])
 {

Modified: lldb/trunk/tools/lldb-mi/MICmdArgValNumber.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/lldb-mi/MICmdArgValNumber.cpp?rev=229132&r1=229131&r2=229132&view=diff
==============================================================================
--- lldb/trunk/tools/lldb-mi/MICmdArgValNumber.cpp (original)
+++ lldb/trunk/tools/lldb-mi/MICmdArgValNumber.cpp Fri Feb 13 12:42:25 2015
@@ -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(CMICmdArgCo
 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
     bool bOk = vrTxt.ExtractNumber(nNumber);
     if (bOk)
     {
-        m_nNumber = static_cast<MIint>(nNumber);
+        m_nNumber = static_cast<MIint64>(nNumber);
     }
 
     return bOk;

Modified: lldb/trunk/tools/lldb-mi/MICmdArgValNumber.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/lldb-mi/MICmdArgValNumber.h?rev=229132&r1=229131&r2=229132&view=diff
==============================================================================
--- lldb/trunk/tools/lldb-mi/MICmdArgValNumber.h (original)
+++ lldb/trunk/tools/lldb-mi/MICmdArgValNumber.h Fri Feb 13 12:42:25 2015
@@ -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 CMICmd
 
     // Attributes:
   private:
+    MIuint m_nNumberFormatMask;
     MIint64 m_nNumber;
 };

Modified: lldb/trunk/tools/lldb-mi/MICmdCmdData.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/lldb-mi/MICmdCmdData.cpp?rev=229132&r1=229131&r2=229132&view=diff
==============================================================================
--- lldb/trunk/tools/lldb-mi/MICmdCmdData.cpp (original)
+++ lldb/trunk/tools/lldb-mi/MICmdCmdData.cpp Fri Feb 13 12:42:25 2015
@@ -568,7 +568,7 @@ CMICmdCmdDataReadMemoryBytes::ParseArgs(
     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::Acknowledg
     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);

Modified: lldb/trunk/tools/lldb-mi/MIUtilString.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/lldb-mi/MIUtilString.cpp?rev=229132&r1=229131&r2=229132&view=diff
==============================================================================
--- lldb/trunk/tools/lldb-mi/MIUtilString.cpp (original)
+++ lldb/trunk/tools/lldb-mi/MIUtilString.cpp Fri Feb 13 12:42:25 2015
@@ -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::ExtractNumberFromHexadeci
 {
     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;
 }

Modified: lldb/trunk/tools/lldb-mi/MIUtilString.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/lldb-mi/MIUtilString.h?rev=229132&r1=229131&r2=229132&view=diff
==============================================================================
--- lldb/trunk/tools/lldb-mi/MIUtilString.h (original)
+++ lldb/trunk/tools/lldb-mi/MIUtilString.h Fri Feb 13 12:42:25 2015
@@ -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;





More information about the lldb-commits mailing list