[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