From 6965fc30b18bfd77b15f633807f8abeba46d75ba Mon Sep 17 00:00:00 2001
From: hjk <hjk@theqtcompany.com>
Date: Wed, 15 Apr 2015 12:38:11 +0200
Subject: [PATCH] Debugger: Disable parts of QDate* dumper for GDB on 32 bit

Older versions of GDB (~GDB 7.4 on 32 bit) will cause segmentation
faults in inferior calls due to misaligned %ebx values in an SSE
call in qstring.cpp:findChar.

Change-Id: I44492106080f12e645f9d57828438ec70fd66ca6
Reviewed-by: Christian Stenger <christian.stenger@theqtcompany.com>
---
 share/qtcreator/debugger/dumper.py    |  5 +++
 share/qtcreator/debugger/gdbbridge.py | 28 +++++++--------
 share/qtcreator/debugger/qttypes.py   | 51 ++++++++++++++-------------
 tests/auto/debugger/tst_dumpers.cpp   | 48 +++++++++++++++----------
 4 files changed, 73 insertions(+), 59 deletions(-)

diff --git a/share/qtcreator/debugger/dumper.py b/share/qtcreator/debugger/dumper.py
index 0bf0bd28353..6a3e2b5afcf 100644
--- a/share/qtcreator/debugger/dumper.py
+++ b/share/qtcreator/debugger/dumper.py
@@ -1792,6 +1792,11 @@ class DumperBase:
             return True
         return functionName.startswith(self.qtNamespace() + "QV4::")
 
+    # Hack to avoid QDate* dumper timeouts with GDB 7.4 on 32 bit
+    # due to misaligned %ebx in SSE calls (qstring.cpp:findChar)
+    def canCallLocale(self):
+        return True
+
     def isReportableQmlFrame(self, functionName):
         return functionName and functionName.find("QV4::Moth::VME::exec") >= 0
 
diff --git a/share/qtcreator/debugger/gdbbridge.py b/share/qtcreator/debugger/gdbbridge.py
index 890a39c158e..2c840cce039 100644
--- a/share/qtcreator/debugger/gdbbridge.py
+++ b/share/qtcreator/debugger/gdbbridge.py
@@ -346,6 +346,11 @@ class Dumper(DumperBase):
 
         return items
 
+    # Hack to avoid QDate* dumper timeouts with GDB 7.4 on 32 bit
+    # due to misaligned %ebx in SSE calls (qstring.cpp:findChar)
+    # This seems to be fixed in 7.9 (or earlier)
+    def canCallLocale(self):
+        return False if self.is32bit() else True
 
     def showData(self, args):
         self.prepare(args)
@@ -1653,8 +1658,8 @@ class CliDumper(Dumper):
         self.indent = 0
         self.isCli = True
 
-    def reportDumpers(self):
-        return ""
+    def reportDumpers(self, msg):
+        return msg
 
     def enterSubItem(self, item):
         if not item.iname:
@@ -1734,20 +1739,11 @@ class CliDumper(Dumper):
         return True
 
     def showData(self, args):
-        arglist = args.split(' ')
-        name = ''
-        if len(arglist) >= 1:
-            name = arglist[0]
-        allexpanded = [name]
-        if len(arglist) >= 2:
-            for sub in arglist[1].split(','):
-                allexpanded.append(name + '.' + sub)
-        pars = {}
-        pars['fancy': 1]
-        pars['passException': 1]
-        pars['autoderef': 1]
-        pars['expanded': allexpanded]
-        self.prepare(pars)
+        args['fancy'] = 1
+        args['passException'] = 1
+        args['autoderef'] = 1
+        name = args['varlist']
+        self.prepare(args)
         self.output = name + ' = '
         frame = gdb.selected_frame()
         value = frame.read_var(name)
diff --git a/share/qtcreator/debugger/qttypes.py b/share/qtcreator/debugger/qttypes.py
index 031c72bf48f..9078b3b7542 100644
--- a/share/qtcreator/debugger/qttypes.py
+++ b/share/qtcreator/debugger/qttypes.py
@@ -198,14 +198,15 @@ def qdump__QDate(d, value):
         if d.isExpanded():
             # FIXME: This improperly uses complex return values.
             with Children(d):
-                d.putCallItem("toString", value, "toString",
-                    d.enumExpression("DateFormat", "TextDate"))
-                d.putCallItem("(ISO)", value, "toString",
-                    d.enumExpression("DateFormat", "ISODate"))
-                d.putCallItem("(SystemLocale)", value, "toString",
-                    d.enumExpression("DateFormat", "SystemLocaleDate"))
-                d.putCallItem("(Locale)", value, "toString",
-                    d.enumExpression("DateFormat", "LocaleDate"))
+                if d.canCallLocale():
+                    d.putCallItem("toString", value, "toString",
+                        d.enumExpression("DateFormat", "TextDate"))
+                    d.putCallItem("(ISO)", value, "toString",
+                        d.enumExpression("DateFormat", "ISODate"))
+                    d.putCallItem("(SystemLocale)", value, "toString",
+                        d.enumExpression("DateFormat", "SystemLocaleDate"))
+                    d.putCallItem("(Locale)", value, "toString",
+                        d.enumExpression("DateFormat", "LocaleDate"))
                 d.putFields(value)
     else:
         d.putValue("(invalid)")
@@ -224,10 +225,11 @@ def qdump__QTime(d, value):
                     d.enumExpression("DateFormat", "TextDate"))
                 d.putCallItem("(ISO)", value, "toString",
                     d.enumExpression("DateFormat", "ISODate"))
-                d.putCallItem("(SystemLocale)", value, "toString",
-                    d.enumExpression("DateFormat", "SystemLocaleDate"))
-                d.putCallItem("(Locale)", value, "toString",
-                    d.enumExpression("DateFormat", "LocaleDate"))
+                if d.canCallLocale():
+                    d.putCallItem("(SystemLocale)", value, "toString",
+                        d.enumExpression("DateFormat", "SystemLocaleDate"))
+                    d.putCallItem("(Locale)", value, "toString",
+                        d.enumExpression("DateFormat", "LocaleDate"))
                 d.putFields(value)
     else:
         d.putValue("(invalid)")
@@ -305,18 +307,19 @@ def qdump__QDateTime(d, value):
             # FIXME: This improperly uses complex return values.
             with Children(d):
                 d.putCallItem("toTime_t", value, "toTime_t")
-                d.putCallItem("toString", value, "toString",
-                    d.enumExpression("DateFormat", "TextDate"))
-                d.putCallItem("(ISO)", value, "toString",
-                    d.enumExpression("DateFormat", "ISODate"))
-                d.putCallItem("(SystemLocale)", value, "toString",
-                    d.enumExpression("DateFormat", "SystemLocaleDate"))
-                d.putCallItem("(Locale)", value, "toString",
-                    d.enumExpression("DateFormat", "LocaleDate"))
-                d.putCallItem("toUTC", value, "toTimeSpec",
-                    d.enumExpression("TimeSpec", "UTC"))
-                d.putCallItem("toLocalTime", value, "toTimeSpec",
-                    d.enumExpression("TimeSpec", "LocalTime"))
+                if d.canCallLocale():
+                    d.putCallItem("toString", value, "toString",
+                        d.enumExpression("DateFormat", "TextDate"))
+                    d.putCallItem("(ISO)", value, "toString",
+                        d.enumExpression("DateFormat", "ISODate"))
+                    d.putCallItem("toUTC", value, "toTimeSpec",
+                        d.enumExpression("TimeSpec", "UTC"))
+                    d.putCallItem("(SystemLocale)", value, "toString",
+                        d.enumExpression("DateFormat", "SystemLocaleDate"))
+                    d.putCallItem("(Locale)", value, "toString",
+                        d.enumExpression("DateFormat", "LocaleDate"))
+                    d.putCallItem("toLocalTime", value, "toTimeSpec",
+                        d.enumExpression("TimeSpec", "LocalTime"))
                 d.putFields(value)
     else:
         d.putValue("(invalid)")
diff --git a/tests/auto/debugger/tst_dumpers.cpp b/tests/auto/debugger/tst_dumpers.cpp
index d775086051d..d2a87df83b3 100644
--- a/tests/auto/debugger/tst_dumpers.cpp
+++ b/tests/auto/debugger/tst_dumpers.cpp
@@ -383,6 +383,8 @@ struct UnsubstitutedValue : Value
     UnsubstitutedValue(const QByteArray &value) : Value(value) { substituteNamespace = false; }
 };
 
+struct Optional {};
+
 struct Type
 {
     Type() : qtVersion(0), isPattern(false) {}
@@ -454,12 +456,13 @@ enum DebuggerEngine
 
 struct CheckBase
 {
-    CheckBase() : enginesForCheck(AllEngines) {}
+    CheckBase() : enginesForCheck(AllEngines), optionallyPresent(false) {}
     mutable int enginesForCheck;
     mutable VersionBase debuggerVersionForCheck;
     mutable VersionBase gccVersionForCheck;
     mutable VersionBase clangVersionForCheck;
     mutable QtVersion qtVersionForCheck;
+    mutable bool optionallyPresent;
 };
 
 struct Check : CheckBase
@@ -486,6 +489,12 @@ struct Check : CheckBase
             && qtVersionForCheck.covers(context.qtVersion);
     }
 
+    const Check &operator%(Optional) const
+    {
+        optionallyPresent = true;
+        return *this;
+    }
+
     const Check &operator%(DebuggerEngine engine)
     {
         enginesForCheck = engine;
@@ -1429,16 +1438,17 @@ void tst_Dumpers::dumper()
     }
 
     if (!data.checks.isEmpty()) {
-        bool fail = false;
         qDebug() << "SOME TESTS NOT EXECUTED: ";
         foreach (const Check &check, data.checks) {
-            qDebug() << "  TEST NOT FOUND FOR INAME: " << check.iname;
-            if (!fail && check.expectedValue.qtVersion != 0)
-                fail = true;
+            if (check.optionallyPresent) {
+                qDebug() << "  OPTIONAL TEST NOT FOUND FOR INAME: " << check.iname << " IGNORED.";
+            } else {
+                qDebug() << "  COMPULSORY TEST NOT FOUND FOR INAME: " << check.iname;
+                ok = false;
+            }
         }
         qDebug() << "SEEN INAMES " << seenINames;
         qDebug() << "EXPANDED     : " << expanded;
-        ok = false;
     }
     if (ok) {
         m_keepTemp = false;
@@ -1592,33 +1602,33 @@ void tst_Dumpers::dumper_data()
 
                + Check("d0", "(invalid)", "@QDate")
                + Check("d1", "Tue Jan 1 1980", "@QDate")
-               + Check("d1.(ISO)", "\"1980-01-01\"", "@QString") % NoCdbEngine
-               + CheckType("d1.(Locale)", "@QString") % NoCdbEngine
-               + CheckType("d1.(SystemLocale)", "@QString") % NoCdbEngine
-               + Check("d1.toString", "\"Tue Jan 1 1980\"", "@QString") % NoCdbEngine
+               + Check("d1.(ISO)", "\"1980-01-01\"", "@QString") % NoCdbEngine % Optional()
+               + Check("d1.toString", "\"Tue Jan 1 1980\"", "@QString") % NoCdbEngine % Optional()
+               + CheckType("d1.(Locale)", "@QString") % NoCdbEngine % Optional()
+               + CheckType("d1.(SystemLocale)", "@QString") % NoCdbEngine % Optional()
 
                + Check("t0", "(invalid)", "@QTime")
                + Check("t1", "13:15:32", "@QTime")
                + Check("t1.(ISO)", "\"13:15:32\"", "@QString") % NoCdbEngine
-               + CheckType("t1.(Locale)", "@QString") % NoCdbEngine
-               + CheckType("t1.(SystemLocale)", "@QString") % NoCdbEngine
                + Check("t1.toString", "\"13:15:32\"", "@QString") % NoCdbEngine
+               + CheckType("t1.(Locale)", "@QString") % NoCdbEngine % Optional()
+               + CheckType("t1.(SystemLocale)", "@QString") % NoCdbEngine % Optional()
 
                + Check("dt0", "(invalid)", "@QDateTime")
                + Check("dt1", Value4("Tue Jan 1 13:15:32 1980"), "@QDateTime")
                + Check("dt1", Value5("Tue Jan 1 13:15:32 1980 GMT"), "@QDateTime")
                + Check("dt1.(ISO)",
-                    "\"1980-01-01T13:15:32Z\"", "@QString") % NoCdbEngine
-               + CheckType("dt1.(Locale)", "@QString") % NoCdbEngine
-               + CheckType("dt1.(SystemLocale)", "@QString") % NoCdbEngine
+                    "\"1980-01-01T13:15:32Z\"", "@QString") % NoCdbEngine % Optional()
+               + CheckType("dt1.(Locale)", "@QString") % NoCdbEngine % Optional()
+               + CheckType("dt1.(SystemLocale)", "@QString") % NoCdbEngine % Optional()
                + Check("dt1.toString",
-                    Value4("\"Tue Jan 1 13:15:32 1980\""), "@QString") % NoCdbEngine
+                    Value4("\"Tue Jan 1 13:15:32 1980\""), "@QString") % NoCdbEngine % Optional()
                + Check("dt1.toString",
-                    Value5("\"Tue Jan 1 13:15:32 1980 GMT\""), "@QString") % NoCdbEngine
+                    Value5("\"Tue Jan 1 13:15:32 1980 GMT\""), "@QString") % NoCdbEngine % Optional()
                + Check("dt1.toUTC",
-                    Value4("Tue Jan 1 13:15:32 1980"), "@QDateTime") % NoCdbEngine
+                    Value4("Tue Jan 1 13:15:32 1980"), "@QDateTime") % NoCdbEngine % Optional()
                + Check("dt1.toUTC",
-                    Value5("Tue Jan 1 13:15:32 1980 GMT"), "@QDateTime") % NoCdbEngine;
+                    Value5("Tue Jan 1 13:15:32 1980 GMT"), "@QDateTime") % NoCdbEngine % Optional();
 
 #ifdef Q_OS_WIN
     QByteArray tempDir = "\"C:/Program Files\"";
-- 
GitLab