[Lldb-commits] [lldb] r230652 - Fix process's output to stdout/stderr (MI)

Ilia K ki.stfu at gmail.com
Thu Feb 26 10:14:30 PST 2015


Author: ki.stfu
Date: Thu Feb 26 12:14:30 2015
New Revision: 230652

URL: http://llvm.org/viewvc/llvm-project?rev=230652&view=rev
Log:
Fix process's output to stdout/stderr (MI)

Summary:
* Add CMIUtilString::Escape/Unescape methods (MI)
* Fix process's output to stdout/stderr (MI):
lldb-mi escapes process's output to show it in the following format:
```
~"..."
```

But previously not all characters were escaped by CMICmnLLDBDebuggerHandleEvents::ConvertPrintfCtrlCodeToString and output of
```
printf("'\n` - it's \\n\x12\"\\\"")
```
looked like:
```
~"'\r\n` - it's \n"\""
```

This patch fixes it by using CMIUtilString::Escape method and now it looks like:
```
~"'\r\n` - it's \\n\x12\"\\\""
```

Reviewers: abidh, emaste, clayborg

Reviewed By: clayborg

Subscribers: zturner, lldb-commits, emaste, clayborg, abidh

Differential Revision: http://reviews.llvm.org/D7858

Added:
    lldb/trunk/test/tools/lldb-mi/syntax/
    lldb/trunk/test/tools/lldb-mi/syntax/Makefile
    lldb/trunk/test/tools/lldb-mi/syntax/TestMiSyntax.py
      - copied, changed from r230627, lldb/trunk/test/tools/lldb-mi/TestMiSyntax.py
    lldb/trunk/test/tools/lldb-mi/syntax/main.cpp
Removed:
    lldb/trunk/test/tools/lldb-mi/TestMiSyntax.py
Modified:
    lldb/trunk/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.cpp
    lldb/trunk/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.h
    lldb/trunk/tools/lldb-mi/MIUtilString.cpp
    lldb/trunk/tools/lldb-mi/MIUtilString.h

Removed: lldb/trunk/test/tools/lldb-mi/TestMiSyntax.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/tools/lldb-mi/TestMiSyntax.py?rev=230651&view=auto
==============================================================================
--- lldb/trunk/test/tools/lldb-mi/TestMiSyntax.py (original)
+++ lldb/trunk/test/tools/lldb-mi/TestMiSyntax.py (removed)
@@ -1,67 +0,0 @@
-"""
-Test that the lldb-mi driver understands MI command syntax.
-"""
-
-import lldbmi_testcase
-from lldbtest import *
-import unittest2
-
-class MiSyntaxTestCase(lldbmi_testcase.MiTestCaseBase):
-
-    mydir = TestBase.compute_mydir(__file__)
-
-    @lldbmi_test
-    @expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows")
-    @skipIfFreeBSD # llvm.org/pr22411: Failure presumably due to known thread races
-    def test_lldbmi_tokens(self):
-        """Test that 'lldb-mi --interpreter' prints command tokens."""
-
-        self.spawnLldbMi(args = None)
-
-        # Load executable
-        self.runCmd("000-file-exec-and-symbols %s" % self.myexe)
-        self.expect("000\^done")
-
-        # Run to main
-        self.runCmd("100000001-break-insert -f main")
-        self.expect("100000001\^done,bkpt={number=\"1\"")
-        self.runCmd("2-exec-run")
-        self.expect("2\^running")
-        self.expect("\*stopped,reason=\"breakpoint-hit\"")
-
-        # Exit
-        self.runCmd("0000000000000000000003-exec-continue")
-        self.expect("0000000000000000000003\^running")
-        self.expect("\*stopped,reason=\"exited-normally\"")
-
-    @lldbmi_test
-    @expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows")
-    def test_lldbmi_specialchars(self):
-        """Test that 'lldb-mi --interpreter' handles complicated strings."""
-
-        self.spawnLldbMi(args = None)
-
-        # Create alias for myexe
-        complicated_myexe = "C--mpl-x file's`s @#$%^&*()_+-={}[]| name"
-        if os.path.exists(complicated_myexe):
-            os.unlink(complicated_myexe)
-        os.symlink(self.myexe, complicated_myexe)
-
-        try:
-            # Try to load executable with complicated filename
-            self.runCmd("-file-exec-and-symbols \"%s\"" % complicated_myexe)
-            self.expect("\^done")
-
-            # Check that it was loaded correctly
-            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\"")
-
-        finally:
-            # Clean up
-            os.unlink(complicated_myexe)
-
-if __name__ == '__main__':
-    unittest2.main()

Added: lldb/trunk/test/tools/lldb-mi/syntax/Makefile
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/tools/lldb-mi/syntax/Makefile?rev=230652&view=auto
==============================================================================
--- lldb/trunk/test/tools/lldb-mi/syntax/Makefile (added)
+++ lldb/trunk/test/tools/lldb-mi/syntax/Makefile Thu Feb 26 12:14:30 2015
@@ -0,0 +1,5 @@
+LEVEL = ../../../make
+
+CXX_SOURCES := main.cpp
+
+include $(LEVEL)/Makefile.rules

Copied: lldb/trunk/test/tools/lldb-mi/syntax/TestMiSyntax.py (from r230627, lldb/trunk/test/tools/lldb-mi/TestMiSyntax.py)
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/tools/lldb-mi/syntax/TestMiSyntax.py?p2=lldb/trunk/test/tools/lldb-mi/syntax/TestMiSyntax.py&p1=lldb/trunk/test/tools/lldb-mi/TestMiSyntax.py&r1=230627&r2=230652&rev=230652&view=diff
==============================================================================
--- lldb/trunk/test/tools/lldb-mi/TestMiSyntax.py (original)
+++ lldb/trunk/test/tools/lldb-mi/syntax/TestMiSyntax.py Thu Feb 26 12:14:30 2015
@@ -2,6 +2,10 @@
 Test that the lldb-mi driver understands MI command syntax.
 """
 
+# adjust path for lldbmi_testcase.py
+import sys, os.path
+sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
+
 import lldbmi_testcase
 from lldbtest import *
 import unittest2
@@ -63,5 +67,24 @@ class MiSyntaxTestCase(lldbmi_testcase.M
             # Clean up
             os.unlink(complicated_myexe)
 
+    @lldbmi_test
+    @expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows")
+    @skipIfFreeBSD # llvm.org/pr22411: Failure presumably due to known thread races
+    def test_lldbmi_process_output(self):
+        """Test that 'lldb-mi --interpreter' wraps process output correctly."""
+
+        self.spawnLldbMi(args = None)
+
+        # Load executable
+        self.runCmd("-file-exec-and-symbols %s" % self.myexe)
+        self.expect("\^done")
+
+        # Run
+        self.runCmd("-exec-run")
+        self.expect("\^running")
+
+        # Test that a process output is wrapped correctly
+        self.expect("\~\"'\\\\r\\\\n` - it's \\\\\\\\n\\\\x12\\\\\"\\\\\\\\\\\\\"")
+
 if __name__ == '__main__':
     unittest2.main()

Added: lldb/trunk/test/tools/lldb-mi/syntax/main.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/tools/lldb-mi/syntax/main.cpp?rev=230652&view=auto
==============================================================================
--- lldb/trunk/test/tools/lldb-mi/syntax/main.cpp (added)
+++ lldb/trunk/test/tools/lldb-mi/syntax/main.cpp Thu Feb 26 12:14:30 2015
@@ -0,0 +1,17 @@
+//===-- main.cpp ------------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <cstdio>
+
+int
+main(int argc, char const *argv[]) 
+{
+    printf("'\n` - it's \\n\x12\"\\\"");
+    return 0;
+}

Modified: lldb/trunk/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.cpp?rev=230652&r1=230651&r2=230652&view=diff
==============================================================================
--- lldb/trunk/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.cpp (original)
+++ lldb/trunk/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.cpp Thu Feb 26 12:14:30 2015
@@ -1379,26 +1379,24 @@ CMICmnLLDBDebuggerHandleEvents::HandlePr
 bool
 CMICmnLLDBDebuggerHandleEvents::GetProcessStdout(void)
 {
-    bool bOk = MIstatus::success;
-
-    char c;
-    size_t nBytes = 0;
     CMIUtilString text;
+    std::unique_ptr<char[]> apStdoutBuffer(new char[1024]);
     lldb::SBProcess process = CMICmnLLDBDebugSessionInfo::Instance().GetDebugger().GetSelectedTarget().GetProcess();
-    while (process.GetSTDOUT(&c, 1) > 0)
-    {
-        CMIUtilString str;
-        if (ConvertPrintfCtrlCodeToString(c, str))
-            text += str;
-        nBytes++;
-    }
-    if (nBytes > 0)
+    while (1)
     {
-        const CMIUtilString t(CMIUtilString::Format("~\"%s\"", text.c_str()));
-        bOk = TextToStdout(t);
+        const size_t nBytes = process.GetSTDOUT(apStdoutBuffer.get(), 1024);
+        if (nBytes == 0)
+            break;
+
+        text.append(apStdoutBuffer.get(), nBytes);
     }
 
-    return bOk;
+    if (text.empty())
+        return MIstatus::success;
+
+    const bool bEscapeQuotes(true);
+    const CMIUtilString t(CMIUtilString::Format("~\"%s\"", text.Escape(bEscapeQuotes).c_str()));
+    return TextToStdout(t);
 }
 
 //++ ------------------------------------------------------------------------------------
@@ -1414,72 +1412,24 @@ CMICmnLLDBDebuggerHandleEvents::GetProce
 bool
 CMICmnLLDBDebuggerHandleEvents::GetProcessStderr(void)
 {
-    bool bOk = MIstatus::success;
-
-    char c;
-    size_t nBytes = 0;
     CMIUtilString text;
+    std::unique_ptr<char[]> apStderrBuffer(new char[1024]);
     lldb::SBProcess process = CMICmnLLDBDebugSessionInfo::Instance().GetDebugger().GetSelectedTarget().GetProcess();
-    while (process.GetSTDERR(&c, 1) > 0)
-    {
-        CMIUtilString str;
-        if (ConvertPrintfCtrlCodeToString(c, str))
-            text += str;
-        nBytes++;
-    }
-    if (nBytes > 0)
-    {
-        const CMIUtilString t(CMIUtilString::Format("~\"%s\"", text.c_str()));
-        bOk = TextToStdout(t);
-    }
-
-    return bOk;
-}
-
-//++ ------------------------------------------------------------------------------------
-// Details: Convert text stream control codes to text equivalent.
-// Type:    Method.
-// Args:    vCtrl             - (R) The control code.
-//          vwrStrEquivalent  - (W) The text equivalent.
-// Return:  MIstatus::success - Functionality succeeded.
-//          MIstatus::failure - Functionality failed.
-// Throws:  None.
-//--
-bool
-CMICmnLLDBDebuggerHandleEvents::ConvertPrintfCtrlCodeToString(const MIchar vCtrl, CMIUtilString &vwrStrEquivalent)
-{
-    switch (vCtrl)
+    while (1)
     {
-        case '\033':
-            vwrStrEquivalent = "\\e";
-            break;
-        case '\a':
-            vwrStrEquivalent = "\\a";
-            break;
-        case '\b':
-            vwrStrEquivalent = "\\b";
-            break;
-        case '\f':
-            vwrStrEquivalent = "\\f";
-            break;
-        case '\n':
-            vwrStrEquivalent = "\\n";
-            break;
-        case '\r':
-            vwrStrEquivalent = "\\r";
-            break;
-        case '\t':
-            vwrStrEquivalent = "\\t";
-            break;
-        case '\v':
-            vwrStrEquivalent = "\\v";
-            break;
-        default:
-            vwrStrEquivalent = CMIUtilString::Format("%c", vCtrl);
+        const size_t nBytes = process.GetSTDERR(apStderrBuffer.get(), 1024);
+        if (nBytes == 0)
             break;
+
+        text.append(apStderrBuffer.get(), nBytes);
     }
 
-    return MIstatus::success;
+    if (text.empty())
+        return MIstatus::success;
+
+    const bool bEscapeQuotes(true);
+    const CMIUtilString t(CMIUtilString::Format("~\"%s\"", text.Escape(bEscapeQuotes).c_str()));
+    return TextToStdout(t);
 }
 
 //++ ------------------------------------------------------------------------------------

Modified: lldb/trunk/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.h?rev=230652&r1=230651&r2=230652&view=diff
==============================================================================
--- lldb/trunk/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.h (original)
+++ lldb/trunk/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.h Thu Feb 26 12:14:30 2015
@@ -86,7 +86,6 @@ class CMICmnLLDBDebuggerHandleEvents : p
     bool TextToStdout(const CMIUtilString &vrTxt);
     bool TextToStderr(const CMIUtilString &vrTxt);
     bool UpdateSelectedThread(void);
-    bool ConvertPrintfCtrlCodeToString(const MIchar vCtrl, CMIUtilString &vwrStrEquivalent);
 
     // Overridden:
   private:

Modified: lldb/trunk/tools/lldb-mi/MIUtilString.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/lldb-mi/MIUtilString.cpp?rev=230652&r1=230651&r2=230652&view=diff
==============================================================================
--- lldb/trunk/tools/lldb-mi/MIUtilString.cpp (original)
+++ lldb/trunk/tools/lldb-mi/MIUtilString.cpp Thu Feb 26 12:14:30 2015
@@ -20,11 +20,12 @@
 //--
 
 // Third party headers
-#include <memory>   // std::unique_ptr
-#include <stdarg.h> // va_list, va_start, var_end
-#include <sstream>  // std::stringstream
-#include <string.h> // for strncmp
-#include <limits.h> // for ULONG_MAX
+#include <inttypes.h> // for PRIx8
+#include <limits.h>   // for ULONG_MAX
+#include <memory>     // std::unique_ptr
+#include <sstream>    // std::stringstream
+#include <stdarg.h>   // va_list, va_start, var_end
+#include <string.h>   // for strncmp
 
 // In-house headers:
 #include "MIUtilString.h"
@@ -797,3 +798,70 @@ CMIUtilString::FindFirstQuote(const MIui
 
     return (MIuint)std::string::npos;
 }
+
+//++ ------------------------------------------------------------------------------------
+// Details: Get escaped string from *this string.
+// Type:    Method.
+// Args:    None.
+// Return:  CMIUtilString - The escaped version of the initial string.
+// Throws:  None.
+//--
+CMIUtilString
+CMIUtilString::Escape(const bool vbEscapeQuotes /* = false */) const
+{
+    const MIuint nLen(length());
+    CMIUtilString strNew;
+    strNew.reserve(nLen);
+    for (MIuint nIndex(0); nIndex < nLen; ++nIndex)
+    {
+        const MIchar cUnescapedChar((*this)[nIndex]);
+        switch (cUnescapedChar)
+        {
+            case '\a':
+                strNew.append("\\a");
+                break;
+            case '\b':
+                strNew.append("\\b");
+                break;
+            case '\t':
+                strNew.append("\\t");
+                break;
+            case '\n':
+                strNew.append("\\n");
+                break;
+            case '\v':
+                strNew.append("\\v");
+                break;
+            case '\f':
+                strNew.append("\\f");
+                break;
+            case '\r':
+                strNew.append("\\r");
+                break;
+            case '\033':
+                strNew.append("\\e");
+                break;
+            case '\\':
+                strNew.append("\\\\");
+                break;
+            case '\"':
+                if (vbEscapeQuotes)
+                {
+                    strNew.append("\\\"");
+                    break;
+                }
+                // FALLTHROUGH
+            default:
+                if (::isprint(cUnescapedChar))
+                    strNew.push_back(cUnescapedChar);
+                else
+                {
+                    char strEscapedChar[sizeof("\\xXX")];
+                    ::sprintf(strEscapedChar, "\\x%02" PRIx8, cUnescapedChar);
+                    strNew.append(strEscapedChar);
+                }
+                break;
+        }
+    }
+    return strNew;
+}

Modified: lldb/trunk/tools/lldb-mi/MIUtilString.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/lldb-mi/MIUtilString.h?rev=230652&r1=230651&r2=230652&view=diff
==============================================================================
--- lldb/trunk/tools/lldb-mi/MIUtilString.h (original)
+++ lldb/trunk/tools/lldb-mi/MIUtilString.h Thu Feb 26 12:14:30 2015
@@ -72,6 +72,7 @@ class CMIUtilString : public std::string
     MIuint FindFirst(const CMIUtilString &vrPattern, const bool vbSkipQuotedText, bool &vrwbNotFoundClosedQuote,
                      const MIuint vnPos = 0) const;
     MIuint FindFirstNot(const CMIUtilString &vrPattern, const MIuint vnPos = 0) const;
+    CMIUtilString Escape(const bool vbEscapeQuotes = false) const;
     //
     CMIUtilString &operator=(const MIchar *vpRhs);
     CMIUtilString &operator=(const std::string &vrRhs);





More information about the lldb-commits mailing list