enlight created this revision.
enlight added reviewers: ki.stfu, abidh.
enlight added a subscriber: LLDB.
enlight set the repository for this revision to rL LLVM.

While attempting to run lldb-mi on Windows it became apparent that it doesn't 
consistently escape output, for instance error messages contained paths with 
unescaped backslashes, and unescaped double-quotes. To address this issue 
without spending a ridiculous amount of time trying to track down every case 
where output isn't properly escaped I've opted to move all escaping into 
`CMICmnMIValueConst`. `CMICmnMIValueConst` is the basic building block of all 
output emitted by lldb-mi, so handling escaping in a consistent manner here 
will help to ensure all output is properly escaped. This change required 
removing any existing escaping of output to prevent double-escaping.

I've also removed the spacing code from `CMICmnMIValueTuple` and 
`CMICmnMIValueResult`, it was only misused to format composite values in 
`CMICmnLLDBUtilSBValue::GetCompositeValue()`. The format of composite values 
isn't specified by the GDB-MI spec, and as such these values shouldn't be built 
using `CMICmnMIValueTuple`, `CMICmnMIValueResult`, and `CMICmnMIValueConst`.


Repository:
  rL LLVM

https://reviews.llvm.org/D26124

Files:
  packages/Python/lldbsuite/test/tools/lldb-mi/syntax/TestMiSyntax.py
  packages/Python/lldbsuite/test/tools/lldb-mi/variable/TestMiGdbSetShowPrint.py
  tools/lldb-mi/MICmdCmdData.cpp
  tools/lldb-mi/MICmdCmdVar.cpp
  tools/lldb-mi/MICmnLLDBDebugSessionInfo.cpp
  tools/lldb-mi/MICmnLLDBDebugSessionInfo.h
  tools/lldb-mi/MICmnLLDBDebugSessionInfoVarObj.cpp
  tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.cpp
  tools/lldb-mi/MICmnLLDBUtilSBValue.cpp
  tools/lldb-mi/MICmnLLDBUtilSBValue.h
  tools/lldb-mi/MICmnMIValueConst.cpp
  tools/lldb-mi/MICmnMIValueConst.h
  tools/lldb-mi/MICmnMIValueResult.cpp
  tools/lldb-mi/MICmnMIValueResult.h
  tools/lldb-mi/MICmnMIValueTuple.cpp
  tools/lldb-mi/MICmnMIValueTuple.h

Index: tools/lldb-mi/MICmnMIValueTuple.h
===================================================================
--- tools/lldb-mi/MICmnMIValueTuple.h
+++ tools/lldb-mi/MICmnMIValueTuple.h
@@ -38,12 +38,9 @@
 public:
   /* ctor */ CMICmnMIValueTuple();
   /* ctor */ CMICmnMIValueTuple(const CMICmnMIValueResult &vResult);
-  /* ctor */ CMICmnMIValueTuple(const CMICmnMIValueResult &vResult,
-                                const bool vbUseSpacing);
   //
   void Add(const CMICmnMIValueResult &vResult);
-  void Add(const CMICmnMIValueResult &vResult, const bool vbUseSpacing);
-  void Add(const CMICmnMIValueConst &vValue, const bool vbUseSpacing);
+  void Add(const CMICmnMIValueConst &vValue);
   CMIUtilString ExtractContentNoBrackets() const;
 
   // Overridden:
@@ -56,9 +53,4 @@
   void BuildTuple();
   void BuildTuple(const CMICmnMIValueResult &vResult);
   void BuildTuple(const CMIUtilString &vValue);
-
-  // Attributes:
-private:
-  bool m_bSpaceAfterComma; // True = put space separators into the string, false
-                           // = no spaces used
 };
Index: tools/lldb-mi/MICmnMIValueTuple.cpp
===================================================================
--- tools/lldb-mi/MICmnMIValueTuple.cpp
+++ tools/lldb-mi/MICmnMIValueTuple.cpp
@@ -18,7 +18,7 @@
 // Return:  None.
 // Throws:  None.
 //--
-CMICmnMIValueTuple::CMICmnMIValueTuple() : m_bSpaceAfterComma(false) {
+CMICmnMIValueTuple::CMICmnMIValueTuple() {
   m_strValue = "{}";
 }
 
@@ -30,26 +30,7 @@
 // Return:  None.
 // Throws:  None.
 //--
-CMICmnMIValueTuple::CMICmnMIValueTuple(const CMICmnMIValueResult &vResult)
-    : m_bSpaceAfterComma(false) {
-  m_strValue = vResult.GetString();
-  BuildTuple();
-  m_bJustConstructed = false;
-}
-
-//++
-//------------------------------------------------------------------------------------
-// Details: CMICmnMIValueTuple constructor.
-// Type:    Method.
-// Args:    vResult         - (R) MI result object.
-//          vbUseSpacing    - (R) True = put space separators into the string,
-//          false = no spaces used.
-// Return:  None.
-// Throws:  None.
-//--
-CMICmnMIValueTuple::CMICmnMIValueTuple(const CMICmnMIValueResult &vResult,
-                                       const bool vbUseSpacing)
-    : m_bSpaceAfterComma(vbUseSpacing) {
+CMICmnMIValueTuple::CMICmnMIValueTuple(const CMICmnMIValueResult &vResult) {
   m_strValue = vResult.GetString();
   BuildTuple();
   m_bJustConstructed = false;
@@ -74,8 +55,7 @@
 // Throws:  None.
 //--
 void CMICmnMIValueTuple::BuildTuple() {
-  const char *pFormat = "{%s}";
-  m_strValue = CMIUtilString::Format(pFormat, m_strValue.c_str());
+  m_strValue = CMIUtilString::Format("{%s}", m_strValue.c_str());
 }
 
 //++
@@ -102,8 +82,7 @@
     m_strValue = m_strValue.substr(0, m_strValue.size() - 1);
   }
 
-  const char *pFormat = m_bSpaceAfterComma ? "{%s, %s}" : "{%s,%s}";
-  m_strValue = CMIUtilString::Format(pFormat, m_strValue.c_str(),
+  m_strValue = CMIUtilString::Format("{%s,%s}", m_strValue.c_str(),
                                      vResult.GetString().c_str());
 }
 
@@ -125,8 +104,7 @@
   }
 
   const CMIUtilString data(ExtractContentNoBrackets());
-  const char *pFormat = m_bSpaceAfterComma ? "{%s, %s}" : "{%s,%s}";
-  m_strValue = CMIUtilString::Format(pFormat, data.c_str(), vValue.c_str());
+  m_strValue = CMIUtilString::Format("{%s,%s}", data.c_str(), vValue.c_str());
 }
 
 //++
@@ -152,33 +130,11 @@
 //          will return MIstatus::failure.
 // Type:    Method.
 // Args:    vValue          - (R) The MI value object.
-//          vbUseSpacing    - (R) True = put space separators into the string,
-//          false = no spaces used.
-// Return:  None.
-// Throws:  None.
-//--
-void CMICmnMIValueTuple::Add(const CMICmnMIValueResult &vResult,
-                             const bool vbUseSpacing) {
-  m_bSpaceAfterComma = vbUseSpacing;
-  BuildTuple(vResult);
-}
-
-//++
-//------------------------------------------------------------------------------------
-// Details: Add another MI value object to  the value list's of list is values.
-//          Only values objects can be added to a list of values otherwise this
-//          function
-//          will return MIstatus::failure.
-// Type:    Method.
-// Args:    vValue          - (R) The MI value object.
-//          vbUseSpacing    - (R) True = put space separators into the string,
 //          false = no spaces used.
 // Return:  None.
 // Throws:  None.
 //--
-void CMICmnMIValueTuple::Add(const CMICmnMIValueConst &vValue,
-                             const bool vbUseSpacing) {
-  m_bSpaceAfterComma = vbUseSpacing;
+void CMICmnMIValueTuple::Add(const CMICmnMIValueConst &vValue) {
   BuildTuple(vValue.GetString());
 }
 
Index: tools/lldb-mi/MICmnMIValueResult.h
===================================================================
--- tools/lldb-mi/MICmnMIValueResult.h
+++ tools/lldb-mi/MICmnMIValueResult.h
@@ -38,9 +38,6 @@
   /* ctor */ CMICmnMIValueResult();
   /* ctor */ CMICmnMIValueResult(const CMIUtilString &vVariable,
                                  const CMICmnMIValue &vValue);
-  /* ctor */ CMICmnMIValueResult(const CMIUtilString &vVariable,
-                                 const CMICmnMIValue &vValue,
-                                 const bool vbUseSpacing);
   //
   void Add(const CMIUtilString &vVariable, const CMICmnMIValue &vValue);
 
@@ -56,12 +53,9 @@
 
   // Attributes:
 private:
-  static const CMIUtilString ms_constStrEqual;
   //
   CMIUtilString m_strPartVariable;
   CMICmnMIValue m_partMIValue;
   bool m_bEmptyConstruction; // True = *this object used constructor with no
                              // parameters, false = constructor with parameters
-  bool m_bUseSpacing; // True = put space separators into the string, false = no
-                      // spaces used
 };
Index: tools/lldb-mi/MICmnMIValueResult.cpp
===================================================================
--- tools/lldb-mi/MICmnMIValueResult.cpp
+++ tools/lldb-mi/MICmnMIValueResult.cpp
@@ -11,9 +11,6 @@
 #include "MICmnMIValueResult.h"
 #include "MICmnResources.h"
 
-// Instantiations:
-const CMIUtilString CMICmnMIValueResult::ms_constStrEqual("=");
-
 //++
 //------------------------------------------------------------------------------------
 // Details: CMICmnMIValueResult constructor.
@@ -36,26 +33,7 @@
 CMICmnMIValueResult::CMICmnMIValueResult(const CMIUtilString &vrVariable,
                                          const CMICmnMIValue &vrValue)
     : m_strPartVariable(vrVariable), m_partMIValue(vrValue),
-      m_bEmptyConstruction(false), m_bUseSpacing(false) {
-  BuildResult();
-}
-
-//++
-//------------------------------------------------------------------------------------
-// Details: CMICmnMIValueResult constructor.
-// Type:    Method.
-// Args:    vrVariable      - (R) MI value's name.
-//          vrValue         - (R) The MI value.
-//          vbUseSpacing    - (R) True = put space separators into the string,
-//          false = no spaces used.
-// Return:  None.
-// Throws:  None.
-//--
-CMICmnMIValueResult::CMICmnMIValueResult(const CMIUtilString &vrVariable,
-                                         const CMICmnMIValue &vrValue,
-                                         const bool vbUseSpacing)
-    : m_strPartVariable(vrVariable), m_partMIValue(vrValue),
-      m_bEmptyConstruction(false), m_bUseSpacing(vbUseSpacing) {
+      m_bEmptyConstruction(false) {
   BuildResult();
 }
 
@@ -78,9 +56,7 @@
 // Throws:  None.
 //--
 void CMICmnMIValueResult::BuildResult() {
-  const char *pFormat = m_bUseSpacing ? "%s %s %s" : "%s%s%s";
-  m_strValue = CMIUtilString::Format(pFormat, m_strPartVariable.c_str(),
-                                     ms_constStrEqual.c_str(),
+  m_strValue = CMIUtilString::Format("%s=%s", m_strPartVariable.c_str(),
                                      m_partMIValue.GetString().c_str());
 }
 
@@ -95,9 +71,8 @@
 //--
 void CMICmnMIValueResult::BuildResult(const CMIUtilString &vVariable,
                                       const CMICmnMIValue &vValue) {
-  const char *pFormat = m_bUseSpacing ? "%s, %s %s %s" : "%s,%s%s%s";
   m_strValue = CMIUtilString::Format(
-      pFormat, m_strValue.c_str(), vVariable.c_str(), ms_constStrEqual.c_str(),
+      "%s,%s=%s", m_strValue.c_str(), vVariable.c_str(),
       vValue.GetString().c_str());
 }
 
Index: tools/lldb-mi/MICmnMIValueConst.h
===================================================================
--- tools/lldb-mi/MICmnMIValueConst.h
+++ tools/lldb-mi/MICmnMIValueConst.h
@@ -38,8 +38,6 @@
   // Methods:
 public:
   /* ctor */ CMICmnMIValueConst(const CMIUtilString &vString);
-  /* ctor */ CMICmnMIValueConst(const CMIUtilString &vString,
-                                const bool vbNoQuotes);
 
   // Overridden:
 public:
@@ -52,9 +50,6 @@
 
   // Attributes:
 private:
-  static const CMIUtilString ms_constStrDblQuote;
   //
   CMIUtilString m_strPartConst;
-  bool m_bNoQuotes; // True = return string not surrounded with quotes, false =
-                    // use quotes
 };
Index: tools/lldb-mi/MICmnMIValueConst.cpp
===================================================================
--- tools/lldb-mi/MICmnMIValueConst.cpp
+++ tools/lldb-mi/MICmnMIValueConst.cpp
@@ -10,9 +10,6 @@
 // In-house headers:
 #include "MICmnMIValueConst.h"
 
-// Instantiations:
-const CMIUtilString CMICmnMIValueConst::ms_constStrDblQuote("\"");
-
 //++
 //------------------------------------------------------------------------------------
 // Details: CMICmnMIValueConst constructor.
@@ -22,23 +19,7 @@
 // Throws:  None.
 //--
 CMICmnMIValueConst::CMICmnMIValueConst(const CMIUtilString &vString)
-    : m_strPartConst(vString), m_bNoQuotes(false) {
-  BuildConst();
-}
-
-//++
-//------------------------------------------------------------------------------------
-// Details: CMICmnMIValueConst constructor.
-// Type:    Method.
-// Args:    vString     - (R) MI Const c-string value.
-//          vbNoQuotes  - (R) True = return string not surrounded with quotes,
-//          false = use quotes.
-// Return:  None.
-// Throws:  None.
-//--
-CMICmnMIValueConst::CMICmnMIValueConst(const CMIUtilString &vString,
-                                       const bool vbNoQuotes)
-    : m_strPartConst(vString), m_bNoQuotes(vbNoQuotes) {
+    : m_strPartConst(vString) {
   BuildConst();
 }
 
@@ -63,19 +44,10 @@
 //--
 bool CMICmnMIValueConst::BuildConst() {
   if (m_strPartConst.length() != 0) {
-    const CMIUtilString strValue(m_strPartConst.StripCREndOfLine());
-    if (m_bNoQuotes) {
-      m_strValue = strValue;
-    } else {
-      const char *pFormat = "%s%s%s";
-      m_strValue =
-          CMIUtilString::Format(pFormat, ms_constStrDblQuote.c_str(),
-                                strValue.c_str(), ms_constStrDblQuote.c_str());
-    }
+    m_strValue = CMIUtilString::Format("\"%s\"",
+                                       m_strPartConst.Escape(true).c_str());
   } else {
-    const char *pFormat = "%s%s";
-    m_strValue = CMIUtilString::Format(pFormat, ms_constStrDblQuote.c_str(),
-                                       ms_constStrDblQuote.c_str());
+    m_strValue = "\"\"";
   }
 
   return MIstatus::success;
Index: tools/lldb-mi/MICmnLLDBUtilSBValue.h
===================================================================
--- tools/lldb-mi/MICmnLLDBUtilSBValue.h
+++ tools/lldb-mi/MICmnLLDBUtilSBValue.h
@@ -57,7 +57,7 @@
   bool GetSimpleValue(const bool vbHandleArrayType,
                       CMIUtilString &vrValue) const;
   bool GetCompositeValue(const bool vbPrintFieldNames,
-                         CMICmnMIValueTuple &vwrMiValueTuple,
+                         CMIUtilString &vwrCompositeValue,
                          const MIuint vnDepth = 1) const;
   CMIUtilString
   GetValueSummary(bool valueOnly,
Index: tools/lldb-mi/MICmnLLDBUtilSBValue.cpp
===================================================================
--- tools/lldb-mi/MICmnLLDBUtilSBValue.cpp
+++ tools/lldb-mi/MICmnLLDBUtilSBValue.cpp
@@ -110,12 +110,10 @@
           bPrintAggregateFieldNames) ||
       bPrintAggregateFieldNames;
 
-  CMICmnMIValueTuple miValueTuple;
-  const bool bOk = GetCompositeValue(bPrintAggregateFieldNames, miValueTuple);
+  const bool bOk = GetCompositeValue(bPrintAggregateFieldNames, value);
   if (!bOk)
     return kUnknownValue;
 
-  value = miValueTuple.GetString();
   return value;
 }
 
@@ -169,10 +167,11 @@
 }
 
 bool CMICmnLLDBUtilSBValue::GetCompositeValue(
-    const bool vbPrintFieldNames, CMICmnMIValueTuple &vwrMiValueTuple,
+    const bool vbPrintFieldNames, CMIUtilString &vwrCompositeValue,
     const MIuint vnDepth /* = 1 */) const {
   const MIuint nMaxDepth = 10;
   const MIuint nChildren = m_rValue.GetNumChildren();
+  vwrCompositeValue = "{";
   for (MIuint i = 0; i < nChildren; ++i) {
     const lldb::SBValue member = m_rValue.GetChildAtIndex(i);
     const CMICmnLLDBUtilSBValue utilMember(member, m_bHandleCharType,
@@ -185,31 +184,28 @@
       // OK. Value is simple (not composite) and was successfully got
     } else if (vnDepth < nMaxDepth) {
       // Need to get value from composite type
-      CMICmnMIValueTuple miValueTuple;
       const bool bOk = utilMember.GetCompositeValue(vbPrintFieldNames,
-                                                    miValueTuple, vnDepth + 1);
+                                                    value, vnDepth + 1);
       if (!bOk)
         // Can't obtain composite type
         value = kUnknownValue;
-      else
-        // OK. Value is composite and was successfully got
-        value = miValueTuple.GetString();
     } else {
       // Need to get value from composite type, but vnMaxDepth is reached
       value = kUnresolvedCompositeValue;
     }
-    const bool bNoQuotes = true;
-    const CMICmnMIValueConst miValueConst(value, bNoQuotes);
     if (vbPrintFieldNames) {
-      const bool bUseSpacing = true;
-      const CMICmnMIValueResult miValueResult(utilMember.GetName(),
-                                              miValueConst, bUseSpacing);
-      vwrMiValueTuple.Add(miValueResult, bUseSpacing);
+      if (vwrCompositeValue.back() != '{')
+        vwrCompositeValue += ", ";
+      vwrCompositeValue += CMIUtilString::Format("%s = %s",
+                                                 utilMember.GetName().c_str(),
+                                                 value.c_str());
     } else {
-      const bool bUseSpacing = false;
-      vwrMiValueTuple.Add(miValueConst, bUseSpacing);
+      if (vwrCompositeValue.back() != '{')
+        vwrCompositeValue += ",";
+      vwrCompositeValue += value;
     }
   }
+  vwrCompositeValue += "}";
 
   return MIstatus::success;
 }
Index: tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.cpp
===================================================================
--- tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.cpp
+++ tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.cpp
@@ -719,19 +719,16 @@
   std::unique_ptr<char[]> apPath(new char[PATH_MAX]);
   vModule.GetFileSpec().GetPath(apPath.get(), PATH_MAX);
   const CMIUtilString strTargetPath(apPath.get());
-  const CMICmnMIValueConst miValueConst(strTargetPath.AddSlashes());
-  const CMICmnMIValueResult miValueResult("id", miValueConst);
-  vwrMiOutOfBandRecord.Add(miValueResult);
+  vwrMiOutOfBandRecord.Add(
+      CMICmnMIValueResult("id", CMICmnMIValueConst(strTargetPath)));
   // Build "target-name" field
-  const CMICmnMIValueConst miValueConst2(strTargetPath.AddSlashes());
-  const CMICmnMIValueResult miValueResult2("target-name", miValueConst2);
-  vwrMiOutOfBandRecord.Add(miValueResult2);
+  vwrMiOutOfBandRecord.Add(
+      CMICmnMIValueResult("target-name", CMICmnMIValueConst(strTargetPath)));
   // Build "host-name" field
   vModule.GetPlatformFileSpec().GetPath(apPath.get(), PATH_MAX);
   const CMIUtilString strHostPath(apPath.get());
-  const CMICmnMIValueConst miValueConst3(strHostPath.AddSlashes());
-  const CMICmnMIValueResult miValueResult3("host-name", miValueConst3);
-  vwrMiOutOfBandRecord.Add(miValueResult3);
+  vwrMiOutOfBandRecord.Add(
+      CMICmnMIValueResult("host-name", CMICmnMIValueConst(strHostPath)));
 
   // Then build extra fields if needed:
   if (vbWithExtraFields) {
@@ -746,9 +743,9 @@
     vwrMiOutOfBandRecord.Add(miValueResult4);
     // Build "symbols-path" field
     if (bSymbolsLoaded) {
-      const CMICmnMIValueConst miValueConst5(strSymbolsPath.AddSlashes());
-      const CMICmnMIValueResult miValueResult5("symbols-path", miValueConst5);
-      vwrMiOutOfBandRecord.Add(miValueResult5);
+      vwrMiOutOfBandRecord.Add(
+          CMICmnMIValueResult("symbols-path",
+                              CMICmnMIValueConst(strSymbolsPath)));
     }
     // Build "loaded_addr" field
     lldb::SBAddress sbAddress(vModule.GetObjectFileHeaderAddress());
@@ -1649,22 +1646,19 @@
 
       const CMIUtilString line(text.substr(0, nNewLine + 1));
       text.erase(0, nNewLine + 1);
-      const bool bEscapeQuotes(true);
-      CMICmnMIValueConst miValueConst(line.Escape(bEscapeQuotes));
       CMICmnMIOutOfBandRecord miOutOfBandRecord(
-          CMICmnMIOutOfBandRecord::eOutOfBand_TargetStreamOutput, miValueConst);
+          CMICmnMIOutOfBandRecord::eOutOfBand_TargetStreamOutput,
+          CMICmnMIValueConst(line));
       const bool bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord);
       if (!bOk)
         return MIstatus::failure;
     }
 
     if (nBytes == 0) {
       if (!text.empty()) {
-        const bool bEscapeQuotes(true);
-        CMICmnMIValueConst miValueConst(text.Escape(bEscapeQuotes));
         CMICmnMIOutOfBandRecord miOutOfBandRecord(
             CMICmnMIOutOfBandRecord::eOutOfBand_TargetStreamOutput,
-            miValueConst);
+            CMICmnMIValueConst(text));
         return MiOutOfBandRecordToStdout(miOutOfBandRecord);
       }
       break;
@@ -1704,22 +1698,19 @@
         break;
 
       const CMIUtilString line(text.substr(0, nNewLine + 1));
-      const bool bEscapeQuotes(true);
-      CMICmnMIValueConst miValueConst(line.Escape(bEscapeQuotes));
       CMICmnMIOutOfBandRecord miOutOfBandRecord(
-          CMICmnMIOutOfBandRecord::eOutOfBand_TargetStreamOutput, miValueConst);
+          CMICmnMIOutOfBandRecord::eOutOfBand_TargetStreamOutput,
+          CMICmnMIValueConst(line));
       const bool bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord);
       if (!bOk)
         return MIstatus::failure;
     }
 
     if (nBytes == 0) {
       if (!text.empty()) {
-        const bool bEscapeQuotes(true);
-        CMICmnMIValueConst miValueConst(text.Escape(bEscapeQuotes));
         CMICmnMIOutOfBandRecord miOutOfBandRecord(
             CMICmnMIOutOfBandRecord::eOutOfBand_TargetStreamOutput,
-            miValueConst);
+            CMICmnMIValueConst(text));
         return MiOutOfBandRecordToStdout(miOutOfBandRecord);
       }
       break;
Index: tools/lldb-mi/MICmnLLDBDebugSessionInfoVarObj.cpp
===================================================================
--- tools/lldb-mi/MICmnLLDBDebugSessionInfoVarObj.cpp
+++ tools/lldb-mi/MICmnLLDBDebugSessionInfoVarObj.cpp
@@ -265,10 +265,7 @@
 //++
 //------------------------------------------------------------------------------------
 // Details: Return the equivalent var value formatted string for the given value
-// type,
-//          which was prepared for printing (i.e. value was escaped and now it's
-//          ready
-//          for wrapping into quotes).
+// type.
 //          The SBValue vrValue parameter is checked by LLDB private code for
 //          valid
 //          scalar type via MI Driver proxy function as the valued returned can
@@ -294,7 +291,7 @@
     }
   }
 
-  return utilValue.GetValue().AddSlashes();
+  return utilValue.GetValue();
 }
 
 //++
Index: tools/lldb-mi/MICmnLLDBDebugSessionInfo.h
===================================================================
--- tools/lldb-mi/MICmnLLDBDebugSessionInfo.h
+++ tools/lldb-mi/MICmnLLDBDebugSessionInfo.h
@@ -219,7 +219,7 @@
                     CMIUtilString &vwPath, MIuint &vwnLine);
   bool GetThreadFrames(const SMICmdData &vCmdData, const MIuint vThreadIdx,
                        const FrameInfoFormat_e veFrameInfoFormat,
-                       CMIUtilString &vwrThreadFrames);
+                       CMICmnMIValueResult &vwrThreadFrames);
   bool
   MIResponseForVariableInfoInternal(const VariableInfoFormat_e veVarInfoFormat,
                                     CMICmnMIValueList &vwrMiValueList,
Index: tools/lldb-mi/MICmnLLDBDebugSessionInfo.cpp
===================================================================
--- tools/lldb-mi/MICmnLLDBDebugSessionInfo.cpp
+++ tools/lldb-mi/MICmnLLDBDebugSessionInfo.cpp
@@ -207,37 +207,32 @@
 //--
 bool CMICmnLLDBDebugSessionInfo::GetThreadFrames(
     const SMICmdData &vCmdData, const MIuint vThreadIdx,
-    const FrameInfoFormat_e veFrameInfoFormat, CMIUtilString &vwrThreadFrames) {
+    const FrameInfoFormat_e veFrameInfoFormat, CMICmnMIValueResult &vwrThreadFrames) {
   lldb::SBThread thread = GetProcess().GetThreadByIndexID(vThreadIdx);
   const uint32_t nFrames = thread.GetNumFrames();
   if (nFrames == 0) {
     // MI print "frame={}"
-    CMICmnMIValueTuple miValueTuple;
-    CMICmnMIValueResult miValueResult("frame", miValueTuple);
-    vwrThreadFrames = miValueResult.GetString();
+    vwrThreadFrames = CMICmnMIValueResult("frame", CMICmnMIValueTuple());
     return MIstatus::success;
   }
 
   // MI print
   // "frame={level=\"%d\",addr=\"0x%016" PRIx64
   // "\",func=\"%s\",args=[%s],file=\"%s\",fullname=\"%s\",line=\"%d\"},frame={level=\"%d\",addr=\"0x%016"
   // PRIx64 "\",func=\"%s\",args=[%s],file=\"%s\",fullname=\"%s\",line=\"%d\"},
   // ..."
-  CMIUtilString strListCommaSeparated;
   for (MIuint nLevel = 0; nLevel < nFrames; nLevel++) {
     CMICmnMIValueTuple miValueTuple;
     if (!MIResponseFormFrameInfo(thread, nLevel, veFrameInfoFormat,
                                  miValueTuple))
       return MIstatus::failure;
 
-    const CMICmnMIValueResult miValueResult2("frame", miValueTuple);
     if (nLevel != 0)
-      strListCommaSeparated += ",";
-    strListCommaSeparated += miValueResult2.GetString();
+      vwrThreadFrames.Add("frame", miValueTuple);
+    else
+      vwrThreadFrames = CMICmnMIValueResult("frame", miValueTuple);
   }
 
-  vwrThreadFrames = strListCommaSeparated;
-
   return MIstatus::success;
 }
 
@@ -393,13 +388,12 @@
 
   // Add "frame"
   if (veThreadInfoFormat != eThreadInfoFormat_NoFrames) {
-    CMIUtilString strFrames;
+    CMICmnMIValueResult frames;
     if (!GetThreadFrames(vCmdData, rThread.GetIndexID(),
-                         eFrameInfoFormat_AllArgumentsInSimpleForm, strFrames))
+                         eFrameInfoFormat_AllArgumentsInSimpleForm, frames))
       return MIstatus::failure;
 
-    const CMICmnMIValueConst miValueConst3(strFrames, true);
-    vwrMIValueTuple.Add(miValueConst3, false);
+    vwrMIValueTuple.Add(frames);
   }
 
   // Add "state"
@@ -489,12 +483,9 @@
           veVarInfoFormat == eVariableInfoFormat_AllValues) // show all values
       {
         CMIUtilString strValue;
-        if (GetVariableInfo(value, vnMaxDepth == 0, strValue)) {
-          const CMICmnMIValueConst miValueConst2(
-              strValue.Escape().AddSlashes());
-          const CMICmnMIValueResult miValueResult2("value", miValueConst2);
-          miValueTuple.Add(miValueResult2);
-        }
+        if (GetVariableInfo(value, vnMaxDepth == 0, strValue))
+          miValueTuple.Add(CMICmnMIValueResult("value",
+                                               CMICmnMIValueConst(strValue)));
       }
       vwrMiValueList.Add(miValueTuple);
       continue;
Index: tools/lldb-mi/MICmdCmdVar.cpp
===================================================================
--- tools/lldb-mi/MICmdCmdVar.cpp
+++ tools/lldb-mi/MICmdCmdVar.cpp
@@ -251,12 +251,9 @@
   if (m_strValue.empty())
     strErrMsg = CMIUtilString::Format(
         MIRSRC(IDS_CMD_ERR_VARIABLE_CREATION_FAILED), m_strExpression.c_str());
-  const CMICmnMIValueConst miValueConst(
-      strErrMsg.Escape(true /* vbEscapeQuotes */));
-  CMICmnMIValueResult miValueResult("msg", miValueConst);
   const CMICmnMIResultRecord miRecordResult(
       m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error,
-      miValueResult);
+      CMICmnMIValueResult("msg", CMICmnMIValueConst(strErrMsg)));
   m_miResultRecord = miRecordResult;
 
   return MIstatus::success;
Index: tools/lldb-mi/MICmdCmdData.cpp
===================================================================
--- tools/lldb-mi/MICmdCmdData.cpp
+++ tools/lldb-mi/MICmdCmdData.cpp
@@ -140,7 +140,7 @@
     m_strValue = rExpression.Trim('\"');
     return MIstatus::success;
   }
-  m_strValue = utilValue.GetValue(true).Escape().AddSlashes();
+  m_strValue = utilValue.GetValue(true);
   return MIstatus::success;
 }
 
@@ -180,11 +180,9 @@
     CMIUtilString mi_error_msg = "Could not evaluate expression";
     if (const char *err_msg = m_Error.GetCString())
       mi_error_msg = err_msg;
-    const CMICmnMIValueConst miValueConst(mi_error_msg.Escape(true));
-    const CMICmnMIValueResult miValueResult("msg", miValueConst);
     const CMICmnMIResultRecord miRecordResult(
         m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error,
-        miValueResult);
+        CMICmnMIValueResult("msg", CMICmnMIValueConst(mi_error_msg)));
     m_miResultRecord = miRecordResult;
     return MIstatus::success;
   }
@@ -401,7 +399,7 @@
     miValueTuple.Add(miValueResult4);
     const CMICmnMIValueConst miValueConst5(
         CMIUtilString::Format("%s %s%s", pStrMnemonic, pStrOperands,
-                              strComment.Escape(true).c_str()));
+                              strComment.c_str()));
     const CMICmnMIValueResult miValueResult5("inst", miValueConst5);
     miValueTuple.Add(miValueResult5);
 
Index: packages/Python/lldbsuite/test/tools/lldb-mi/variable/TestMiGdbSetShowPrint.py
===================================================================
--- packages/Python/lldbsuite/test/tools/lldb-mi/variable/TestMiGdbSetShowPrint.py
+++ packages/Python/lldbsuite/test/tools/lldb-mi/variable/TestMiGdbSetShowPrint.py
@@ -236,13 +236,15 @@
         # specified
         self.runCmd("-gdb-set print expand-aggregates")
         self.expect(
-            "\^error,msg=\"The request ''print' expects option-name and \"on\" or \"off\"' failed.\"")
+            '''^error,msg="The request ''print' expects option-name and \\"on\\" or \\"off\\"' failed."''',
+            exactly=True)
 
         # Test that -gdb-set print expand-aggregates fails when option is
         # unknown
         self.runCmd("-gdb-set print expand-aggregates unknown")
         self.expect(
-            "\^error,msg=\"The request ''print' expects option-name and \"on\" or \"off\"' failed.\"")
+            '''^error,msg="The request ''print' expects option-name and \\"on\\" or \\"off\\"' failed."''',
+            exactly=True)
 
     @skipIfWindows  # llvm.org/pr24452: Get lldb-mi working on Windows
     @expectedFailureAll(compiler="gcc", bugnumber="llvm.org/pr23357")
@@ -310,10 +312,12 @@
         # isn't specified
         self.runCmd("-gdb-set print aggregate-field-names")
         self.expect(
-            "\^error,msg=\"The request ''print' expects option-name and \"on\" or \"off\"' failed.\"")
+            '''^error,msg="The request ''print' expects option-name and \\"on\\" or \\"off\\"' failed."''',
+            exactly=True)
 
         # Test that -gdb-set print aggregate-field-names fails when option is
         # unknown
         self.runCmd("-gdb-set print aggregate-field-names unknown")
         self.expect(
-            "\^error,msg=\"The request ''print' expects option-name and \"on\" or \"off\"' failed.\"")
+            '''^error,msg="The request ''print' expects option-name and \\"on\\" or \\"off\\"' failed."''',
+            exactly=True)
Index: packages/Python/lldbsuite/test/tools/lldb-mi/syntax/TestMiSyntax.py
===================================================================
--- packages/Python/lldbsuite/test/tools/lldb-mi/syntax/TestMiSyntax.py
+++ packages/Python/lldbsuite/test/tools/lldb-mi/syntax/TestMiSyntax.py
@@ -63,6 +63,21 @@
         self.runCmd("-exec-run")
         self.expect("\^running")
         self.expect("\*stopped,reason=\"breakpoint-hit\"")
+        
+    @skipIfWindows  # llvm.org/pr24452: Get lldb-mi tests working on Windows
+    @skipIfFreeBSD  # llvm.org/pr22411: Failure presumably due to known thread races
+    def test_lldbmi_backslashes(self):
+        """Test that 'lldb-mi --interpreter' escapes backslashes in output."""
+
+        self.spawnLldbMi()
+
+        # Test that backslashes are escaped in error output records
+        unescaped_path = r'X:\this\is\a\fake\path'
+        escaped_path = r'X:\\this\\is\\a\\fake\\path'
+        self.runCmd('-file-exec-and-symbols %s' % unescaped_path)
+        self.expect(
+            """^error,msg="Command 'file-exec-and-symbols'. Target binary '%s' is invalid. error: unable to find executable for '%s'""" %
+            (escaped_path, escaped_path), exactly=True)
 
     @skipIfWindows  # llvm.org/pr24452: Get lldb-mi tests working on Windows
     @skipIfFreeBSD  # llvm.org/pr22411: Failure presumably due to known thread races
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to