diff --git a/share/qtcreator/dumper/dumper.py b/share/qtcreator/dumper/dumper.py index 61770db911a..32a1e5f6f5f 100644 --- a/share/qtcreator/dumper/dumper.py +++ b/share/qtcreator/dumper/dumper.py @@ -89,12 +89,39 @@ def hasInferiorThreadList(): except: return False +def dynamicTypeName(value): + #vtbl = str(parseAndEvaluate("{int(*)(int)}%s" % long(value.address))) + vtbl = gdb.execute("info symbol {int*}%s" % long(value.address), + to_string = True) + pos1 = vtbl.find("vtable ") + if pos1 != -1: + pos1 += 11 + pos2 = vtbl.find(" +", pos1) + if pos2 != -1: + return vtbl[pos1 : pos2] + return str(value.type) + def upcast(value): try: - type = value.dynamic_type - return value.cast(type) + return value.cast(value.dynamic_type) except: - return value + pass + #try: + # return value.cast(lookupType(dynamicTypeName(value))) + #except: + # pass + return value + +def expensiveUpcast(value): + try: + return value.cast(value.dynamic_type) + except: + pass + try: + return value.cast(lookupType(dynamicTypeName(value))) + except: + pass + return value typeCache = {} @@ -956,6 +983,7 @@ class Dumper: elif arg.startswith("watchers:"): watchers = base64.b16decode(arg[pos:], True) + self.useDynamicType = "dyntype" in options self.useFancy = "fancy" in options self.passExceptions = "pe" in options self.autoDerefPointers = "autoderef" in options @@ -1542,30 +1570,26 @@ class Dumper: warn("WRONG ASSUMPTION HERE: %s " % type.code) check(False) - #vtbl = str(parseAndEvaluate("{int(*)(int)}%s" % long(value.address))) - vtbl = gdb.execute("info symbol {int*}%s" % long(value.address), - to_string = True) - pos1 = vtbl.find("vtable ") - if pos1 != -1: - pos1 += 11 - pos2 = vtbl.find(" +", pos1) - if pos2 != -1: - self.putType(vtbl[pos1 : pos2], 1) + + if self.useDynamicType: + dtypeName = dynamicTypeName(value) + else: + dtypeName = typeName if self.useFancy and (format is None or format >= 1): self.putAddress(value.address) - self.putType(typeName) + self.putType(dtypeName) - if typeName in qqDumpers: - qqDumpers[typeName](self, value) + if dtypeName in qqDumpers: + qqDumpers[dtypeName](self, expensiveUpcast(value)) return - nsStrippedType = self.stripNamespaceFromType(typeName)\ + nsStrippedType = self.stripNamespaceFromType(dtypeName)\ .replace("::", "__") #warn(" STRIPPED: %s" % nsStrippedType) #warn(" DUMPERS: %s" % (nsStrippedType in qqDumpers)) if nsStrippedType in qqDumpers: - qqDumpers[nsStrippedType](self, value) + qqDumpers[nsStrippedType](self, expensiveUpcast(value)) return # Is this derived from QObject? @@ -1580,7 +1604,7 @@ class Dumper: fields = extractFields(type) #fields = type.fields() - self.putType(typeName) + self.putType(dtypeName) self.putAddress(value.address) self.putValue("{...}") diff --git a/src/plugins/debugger/debuggeractions.cpp b/src/plugins/debugger/debuggeractions.cpp index 86fac6ecf08..b50a72b9c9d 100644 --- a/src/plugins/debugger/debuggeractions.cpp +++ b/src/plugins/debugger/debuggeractions.cpp @@ -357,6 +357,14 @@ DebuggerSettings::DebuggerSettings(QSettings *settings) item->setValue(false); insertItem(AutoEnrichParameters, item); + item = new SavedAction(this); + item->setSettingsKey(debugModeGroup, QLatin1String("UseDynamicType")); + item->setText(tr("Use dynamic object type for display")); + item->setCheckable(true); + item->setDefaultValue(true); + item->setValue(true); + insertItem(UseDynamicType, item); + item = new SavedAction(this); item->setSettingsKey(debugModeGroup, QLatin1String("TargetAsync")); item->setCheckable(true); diff --git a/src/plugins/debugger/debuggeractions.h b/src/plugins/debugger/debuggeractions.h index 3f0c4bb86f8..fadfce9b245 100644 --- a/src/plugins/debugger/debuggeractions.h +++ b/src/plugins/debugger/debuggeractions.h @@ -120,6 +120,7 @@ enum DebuggerActionCode GdbStartupCommands, GdbWatchdogTimeout, AutoEnrichParameters, + UseDynamicType, TargetAsync, // Stack diff --git a/src/plugins/debugger/gdb/gdboptionspage.cpp b/src/plugins/debugger/gdb/gdboptionspage.cpp index 2828ee0ec63..01a60a9a294 100644 --- a/src/plugins/debugger/gdb/gdboptionspage.cpp +++ b/src/plugins/debugger/gdb/gdboptionspage.cpp @@ -88,6 +88,8 @@ QWidget *GdbOptionsPage::createPage(QWidget *parent) m_ui->checkBoxLoadGdbInit); m_group.insert(debuggerCore()->action(AutoEnrichParameters), m_ui->checkBoxAutoEnrichParameters); + m_group.insert(debuggerCore()->action(UseDynamicType), + m_ui->checkBoxUseDynamicType); m_group.insert(debuggerCore()->action(TargetAsync), m_ui->checkBoxTargetAsync); m_group.insert(debuggerCore()->action(AdjustBreakpointLocations), @@ -120,6 +122,7 @@ QWidget *GdbOptionsPage::createPage(QWidget *parent) << sep << m_ui->groupBoxLocations->title() << sep << m_ui->checkBoxLoadGdbInit->text() << sep << m_ui->checkBoxTargetAsync->text() + << sep << m_ui->checkBoxUseDynamicType->text() << sep << m_ui->labelGdbWatchdogTimeout->text() << sep << m_ui->checkBoxEnableReverseDebugging->text() << sep << m_ui->checkBoxSkipKnownFrames->text() diff --git a/src/plugins/debugger/gdb/gdboptionspage.ui b/src/plugins/debugger/gdb/gdboptionspage.ui index a53133d4aac..a63038e07ab 100644 --- a/src/plugins/debugger/gdb/gdboptionspage.ui +++ b/src/plugins/debugger/gdb/gdboptionspage.ui @@ -92,6 +92,16 @@ on slow machines. In this case, the value should be increased. + + + This specifies whether the dynamic or the static type of objects will be displayed. Choosing the dynamic type might be slower. + + + Use dynamic object type for display + + + + This allows or inhibits reading the user's default .gdbinit file on debugger startup. @@ -101,14 +111,14 @@ on slow machines. In this case, the value should be increased. - + Use asynchronous mode to control the inferior - + This adds common paths to locations of debug information at debugger startup. @@ -118,21 +128,21 @@ on slow machines. In this case, the value should be increased. - + Stop when a qWarning is issued - + Stop when a qFatal is issued - + <html><head/><body><p>Selecting this enables reverse debugging.</p><.p><b>Note:</b> This feature is very slow and unstable on the GDB side. It exhibits unpredictable behavior when going backwards over system calls and is very likely to destroy your debugging session.</p><body></html> diff --git a/src/plugins/debugger/gdb/pythongdbengine.cpp b/src/plugins/debugger/gdb/pythongdbengine.cpp index 17f54be00d9..81baea0fe9c 100644 --- a/src/plugins/debugger/gdb/pythongdbengine.cpp +++ b/src/plugins/debugger/gdb/pythongdbengine.cpp @@ -93,12 +93,14 @@ void GdbEngine::updateLocalsPython(const UpdateParameters ¶ms) const static bool alwaysVerbose = !qgetenv("QTC_DEBUGGER_PYTHON_VERBOSE").isEmpty(); QByteArray options; + if (alwaysVerbose) + options += "pe,"; if (debuggerCore()->boolSetting(UseDebuggingHelpers)) options += "fancy,"; if (debuggerCore()->boolSetting(AutoDerefPointers)) options += "autoderef,"; - if (alwaysVerbose) - options += "pe,"; + if (debuggerCore()->boolSetting(UseDynamicType)) + options += "dyntype,"; if (options.isEmpty()) options += "defaults,"; if (params.tryPartial) diff --git a/src/plugins/debugger/watchwindow.cpp b/src/plugins/debugger/watchwindow.cpp index 28bef18d5c4..7149becdbe3 100644 --- a/src/plugins/debugger/watchwindow.cpp +++ b/src/plugins/debugger/watchwindow.cpp @@ -864,6 +864,7 @@ void WatchWindow::contextMenuEvent(QContextMenuEvent *ev) menu.addAction(debuggerCore()->action(ShowStdNamespace)); menu.addAction(debuggerCore()->action(ShowQtNamespace)); menu.addAction(debuggerCore()->action(SortStructMembers)); + menu.addAction(debuggerCore()->action(UseDynamicType)); QAction *actClearCodeModelSnapshot = new QAction(tr("Refresh Code Model Snapshot"), &menu); diff --git a/tests/manual/debugger/simple/simple_test_app.cpp b/tests/manual/debugger/simple/simple_test_app.cpp index 17a528aae92..1e544180c93 100644 --- a/tests/manual/debugger/simple/simple_test_app.cpp +++ b/tests/manual/debugger/simple/simple_test_app.cpp @@ -4148,7 +4148,7 @@ namespace gdb13393 { S s(d); Base *ptr = &d; const Base *ptrConst = &d; - Base& ref = d; + Base &ref = d; const Base &refConst = d; Base **ptrToPtr = &ptr; #if USE_BOOST