forked from qt-creator/qt-creator
debugger: make use of dynamic type for dumpers configurable
It's too expensive to have it unconditionally on in some settings. Giving the user the possibility to switch it off seems ok. Change-Id: I7bdcb0ce919f0dca83a4563ac83958efdeb251e7 Reviewed-by: hjk <qthjk@ovi.com>
This commit is contained in:
@@ -89,12 +89,39 @@ def hasInferiorThreadList():
|
|||||||
except:
|
except:
|
||||||
return False
|
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):
|
def upcast(value):
|
||||||
try:
|
try:
|
||||||
type = value.dynamic_type
|
return value.cast(value.dynamic_type)
|
||||||
return value.cast(type)
|
|
||||||
except:
|
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 = {}
|
typeCache = {}
|
||||||
|
|
||||||
@@ -956,6 +983,7 @@ class Dumper:
|
|||||||
elif arg.startswith("watchers:"):
|
elif arg.startswith("watchers:"):
|
||||||
watchers = base64.b16decode(arg[pos:], True)
|
watchers = base64.b16decode(arg[pos:], True)
|
||||||
|
|
||||||
|
self.useDynamicType = "dyntype" in options
|
||||||
self.useFancy = "fancy" in options
|
self.useFancy = "fancy" in options
|
||||||
self.passExceptions = "pe" in options
|
self.passExceptions = "pe" in options
|
||||||
self.autoDerefPointers = "autoderef" in options
|
self.autoDerefPointers = "autoderef" in options
|
||||||
@@ -1542,30 +1570,26 @@ class Dumper:
|
|||||||
warn("WRONG ASSUMPTION HERE: %s " % type.code)
|
warn("WRONG ASSUMPTION HERE: %s " % type.code)
|
||||||
check(False)
|
check(False)
|
||||||
|
|
||||||
#vtbl = str(parseAndEvaluate("{int(*)(int)}%s" % long(value.address)))
|
|
||||||
vtbl = gdb.execute("info symbol {int*}%s" % long(value.address),
|
if self.useDynamicType:
|
||||||
to_string = True)
|
dtypeName = dynamicTypeName(value)
|
||||||
pos1 = vtbl.find("vtable ")
|
else:
|
||||||
if pos1 != -1:
|
dtypeName = typeName
|
||||||
pos1 += 11
|
|
||||||
pos2 = vtbl.find(" +", pos1)
|
|
||||||
if pos2 != -1:
|
|
||||||
self.putType(vtbl[pos1 : pos2], 1)
|
|
||||||
|
|
||||||
if self.useFancy and (format is None or format >= 1):
|
if self.useFancy and (format is None or format >= 1):
|
||||||
self.putAddress(value.address)
|
self.putAddress(value.address)
|
||||||
self.putType(typeName)
|
self.putType(dtypeName)
|
||||||
|
|
||||||
if typeName in qqDumpers:
|
if dtypeName in qqDumpers:
|
||||||
qqDumpers[typeName](self, value)
|
qqDumpers[dtypeName](self, expensiveUpcast(value))
|
||||||
return
|
return
|
||||||
|
|
||||||
nsStrippedType = self.stripNamespaceFromType(typeName)\
|
nsStrippedType = self.stripNamespaceFromType(dtypeName)\
|
||||||
.replace("::", "__")
|
.replace("::", "__")
|
||||||
#warn(" STRIPPED: %s" % nsStrippedType)
|
#warn(" STRIPPED: %s" % nsStrippedType)
|
||||||
#warn(" DUMPERS: %s" % (nsStrippedType in qqDumpers))
|
#warn(" DUMPERS: %s" % (nsStrippedType in qqDumpers))
|
||||||
if nsStrippedType in qqDumpers:
|
if nsStrippedType in qqDumpers:
|
||||||
qqDumpers[nsStrippedType](self, value)
|
qqDumpers[nsStrippedType](self, expensiveUpcast(value))
|
||||||
return
|
return
|
||||||
|
|
||||||
# Is this derived from QObject?
|
# Is this derived from QObject?
|
||||||
@@ -1580,7 +1604,7 @@ class Dumper:
|
|||||||
fields = extractFields(type)
|
fields = extractFields(type)
|
||||||
#fields = type.fields()
|
#fields = type.fields()
|
||||||
|
|
||||||
self.putType(typeName)
|
self.putType(dtypeName)
|
||||||
self.putAddress(value.address)
|
self.putAddress(value.address)
|
||||||
self.putValue("{...}")
|
self.putValue("{...}")
|
||||||
|
|
||||||
|
|||||||
@@ -357,6 +357,14 @@ DebuggerSettings::DebuggerSettings(QSettings *settings)
|
|||||||
item->setValue(false);
|
item->setValue(false);
|
||||||
insertItem(AutoEnrichParameters, item);
|
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 = new SavedAction(this);
|
||||||
item->setSettingsKey(debugModeGroup, QLatin1String("TargetAsync"));
|
item->setSettingsKey(debugModeGroup, QLatin1String("TargetAsync"));
|
||||||
item->setCheckable(true);
|
item->setCheckable(true);
|
||||||
|
|||||||
@@ -120,6 +120,7 @@ enum DebuggerActionCode
|
|||||||
GdbStartupCommands,
|
GdbStartupCommands,
|
||||||
GdbWatchdogTimeout,
|
GdbWatchdogTimeout,
|
||||||
AutoEnrichParameters,
|
AutoEnrichParameters,
|
||||||
|
UseDynamicType,
|
||||||
TargetAsync,
|
TargetAsync,
|
||||||
|
|
||||||
// Stack
|
// Stack
|
||||||
|
|||||||
@@ -88,6 +88,8 @@ QWidget *GdbOptionsPage::createPage(QWidget *parent)
|
|||||||
m_ui->checkBoxLoadGdbInit);
|
m_ui->checkBoxLoadGdbInit);
|
||||||
m_group.insert(debuggerCore()->action(AutoEnrichParameters),
|
m_group.insert(debuggerCore()->action(AutoEnrichParameters),
|
||||||
m_ui->checkBoxAutoEnrichParameters);
|
m_ui->checkBoxAutoEnrichParameters);
|
||||||
|
m_group.insert(debuggerCore()->action(UseDynamicType),
|
||||||
|
m_ui->checkBoxUseDynamicType);
|
||||||
m_group.insert(debuggerCore()->action(TargetAsync),
|
m_group.insert(debuggerCore()->action(TargetAsync),
|
||||||
m_ui->checkBoxTargetAsync);
|
m_ui->checkBoxTargetAsync);
|
||||||
m_group.insert(debuggerCore()->action(AdjustBreakpointLocations),
|
m_group.insert(debuggerCore()->action(AdjustBreakpointLocations),
|
||||||
@@ -120,6 +122,7 @@ QWidget *GdbOptionsPage::createPage(QWidget *parent)
|
|||||||
<< sep << m_ui->groupBoxLocations->title()
|
<< sep << m_ui->groupBoxLocations->title()
|
||||||
<< sep << m_ui->checkBoxLoadGdbInit->text()
|
<< sep << m_ui->checkBoxLoadGdbInit->text()
|
||||||
<< sep << m_ui->checkBoxTargetAsync->text()
|
<< sep << m_ui->checkBoxTargetAsync->text()
|
||||||
|
<< sep << m_ui->checkBoxUseDynamicType->text()
|
||||||
<< sep << m_ui->labelGdbWatchdogTimeout->text()
|
<< sep << m_ui->labelGdbWatchdogTimeout->text()
|
||||||
<< sep << m_ui->checkBoxEnableReverseDebugging->text()
|
<< sep << m_ui->checkBoxEnableReverseDebugging->text()
|
||||||
<< sep << m_ui->checkBoxSkipKnownFrames->text()
|
<< sep << m_ui->checkBoxSkipKnownFrames->text()
|
||||||
|
|||||||
@@ -92,6 +92,16 @@ on slow machines. In this case, the value should be increased.</string>
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="4" column="0" colspan="2">
|
<item row="4" column="0" colspan="2">
|
||||||
|
<widget class="QCheckBox" name="checkBoxUseDynamicType">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>This specifies whether the dynamic or the static type of objects will be displayed. Choosing the dynamic type might be slower.</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Use dynamic object type for display</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="0" colspan="2">
|
||||||
<widget class="QCheckBox" name="checkBoxLoadGdbInit">
|
<widget class="QCheckBox" name="checkBoxLoadGdbInit">
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>This allows or inhibits reading the user's default .gdbinit file on debugger startup.</string>
|
<string>This allows or inhibits reading the user's default .gdbinit file on debugger startup.</string>
|
||||||
@@ -101,14 +111,14 @@ on slow machines. In this case, the value should be increased.</string>
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="5" column="0" colspan="2">
|
<item row="6" column="0" colspan="2">
|
||||||
<widget class="QCheckBox" name="checkBoxTargetAsync">
|
<widget class="QCheckBox" name="checkBoxTargetAsync">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Use asynchronous mode to control the inferior</string>
|
<string>Use asynchronous mode to control the inferior</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="6" column="0" colspan="2">
|
<item row="7" column="0" colspan="2">
|
||||||
<widget class="QCheckBox" name="checkBoxAutoEnrichParameters">
|
<widget class="QCheckBox" name="checkBoxAutoEnrichParameters">
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>This adds common paths to locations of debug information at debugger startup.</string>
|
<string>This adds common paths to locations of debug information at debugger startup.</string>
|
||||||
@@ -118,21 +128,21 @@ on slow machines. In this case, the value should be increased.</string>
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="7" column="0" colspan="2">
|
<item row="8" column="0" colspan="2">
|
||||||
<widget class="QCheckBox" name="checkBoxBreakOnWarning">
|
<widget class="QCheckBox" name="checkBoxBreakOnWarning">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Stop when a qWarning is issued</string>
|
<string>Stop when a qWarning is issued</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="8" column="0" colspan="2">
|
<item row="9" column="0" colspan="2">
|
||||||
<widget class="QCheckBox" name="checkBoxBreakOnFatal">
|
<widget class="QCheckBox" name="checkBoxBreakOnFatal">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Stop when a qFatal is issued</string>
|
<string>Stop when a qFatal is issued</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="9" column="0" colspan="2">
|
<item row="10" column="0" colspan="2">
|
||||||
<widget class="QCheckBox" name="checkBoxEnableReverseDebugging">
|
<widget class="QCheckBox" name="checkBoxEnableReverseDebugging">
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string><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></string>
|
<string><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></string>
|
||||||
|
|||||||
@@ -93,12 +93,14 @@ void GdbEngine::updateLocalsPython(const UpdateParameters ¶ms)
|
|||||||
|
|
||||||
const static bool alwaysVerbose = !qgetenv("QTC_DEBUGGER_PYTHON_VERBOSE").isEmpty();
|
const static bool alwaysVerbose = !qgetenv("QTC_DEBUGGER_PYTHON_VERBOSE").isEmpty();
|
||||||
QByteArray options;
|
QByteArray options;
|
||||||
|
if (alwaysVerbose)
|
||||||
|
options += "pe,";
|
||||||
if (debuggerCore()->boolSetting(UseDebuggingHelpers))
|
if (debuggerCore()->boolSetting(UseDebuggingHelpers))
|
||||||
options += "fancy,";
|
options += "fancy,";
|
||||||
if (debuggerCore()->boolSetting(AutoDerefPointers))
|
if (debuggerCore()->boolSetting(AutoDerefPointers))
|
||||||
options += "autoderef,";
|
options += "autoderef,";
|
||||||
if (alwaysVerbose)
|
if (debuggerCore()->boolSetting(UseDynamicType))
|
||||||
options += "pe,";
|
options += "dyntype,";
|
||||||
if (options.isEmpty())
|
if (options.isEmpty())
|
||||||
options += "defaults,";
|
options += "defaults,";
|
||||||
if (params.tryPartial)
|
if (params.tryPartial)
|
||||||
|
|||||||
@@ -864,6 +864,7 @@ void WatchWindow::contextMenuEvent(QContextMenuEvent *ev)
|
|||||||
menu.addAction(debuggerCore()->action(ShowStdNamespace));
|
menu.addAction(debuggerCore()->action(ShowStdNamespace));
|
||||||
menu.addAction(debuggerCore()->action(ShowQtNamespace));
|
menu.addAction(debuggerCore()->action(ShowQtNamespace));
|
||||||
menu.addAction(debuggerCore()->action(SortStructMembers));
|
menu.addAction(debuggerCore()->action(SortStructMembers));
|
||||||
|
menu.addAction(debuggerCore()->action(UseDynamicType));
|
||||||
|
|
||||||
QAction *actClearCodeModelSnapshot
|
QAction *actClearCodeModelSnapshot
|
||||||
= new QAction(tr("Refresh Code Model Snapshot"), &menu);
|
= new QAction(tr("Refresh Code Model Snapshot"), &menu);
|
||||||
|
|||||||
@@ -4148,7 +4148,7 @@ namespace gdb13393 {
|
|||||||
S s(d);
|
S s(d);
|
||||||
Base *ptr = &d;
|
Base *ptr = &d;
|
||||||
const Base *ptrConst = &d;
|
const Base *ptrConst = &d;
|
||||||
Base& ref = d;
|
Base &ref = d;
|
||||||
const Base &refConst = d;
|
const Base &refConst = d;
|
||||||
Base **ptrToPtr = &ptr;
|
Base **ptrToPtr = &ptr;
|
||||||
#if USE_BOOST
|
#if USE_BOOST
|
||||||
|
|||||||
Reference in New Issue
Block a user