forked from qt-creator/qt-creator
debugger: implement selected of string encoding per pointer type/individual pointer
This commit is contained in:
@@ -432,12 +432,50 @@ def qtNamespace():
|
|||||||
# Happens for none-Qt applications
|
# Happens for none-Qt applications
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
def encodeCharArray(p, size):
|
def findFirstZero(p, max):
|
||||||
|
for i in xrange(max):
|
||||||
|
if p.dereference() == 0:
|
||||||
|
return i
|
||||||
|
p = p + 1
|
||||||
|
return -1
|
||||||
|
|
||||||
|
def encodeCharArray(p, maxsize):
|
||||||
|
t = gdb.lookup_type("unsigned char").pointer()
|
||||||
|
p = p.cast(t)
|
||||||
|
i = findFirstZero(p, maxsize)
|
||||||
|
limit = select(i < 0, maxsize, i)
|
||||||
s = ""
|
s = ""
|
||||||
p = p.cast(gdb.lookup_type("unsigned char").pointer())
|
for i in xrange(limit):
|
||||||
for i in xrange(size):
|
|
||||||
s += "%02x" % int(p.dereference())
|
s += "%02x" % int(p.dereference())
|
||||||
p += 1
|
p += 1
|
||||||
|
if i == maxsize:
|
||||||
|
s += "2e2e2e"
|
||||||
|
return s
|
||||||
|
|
||||||
|
def encodeChar2Array(p, maxsize):
|
||||||
|
t = gdb.lookup_type("unsigned short").pointer()
|
||||||
|
p = p.cast(t)
|
||||||
|
i = findFirstZero(p, maxsize)
|
||||||
|
limit = select(i < 0, maxsize, i)
|
||||||
|
s = ""
|
||||||
|
for i in xrange(limit):
|
||||||
|
s += "%04x" % int(p.dereference())
|
||||||
|
p += 1
|
||||||
|
if i == maxsize:
|
||||||
|
s += "2e002e002e00"
|
||||||
|
return s
|
||||||
|
|
||||||
|
def encodeChar4Array(p, maxsize):
|
||||||
|
t = gdb.lookup_type("unsigned int").pointer()
|
||||||
|
p = p.cast(t)
|
||||||
|
i = findFirstZero(p, maxsize)
|
||||||
|
limit = select(i < 0, maxsize, i)
|
||||||
|
s = ""
|
||||||
|
for i in xrange(limit):
|
||||||
|
s += "%08x" % int(p.dereference())
|
||||||
|
p += 1
|
||||||
|
if i == maxsize:
|
||||||
|
s += "2e0000002e0000002e000000"
|
||||||
return s
|
return s
|
||||||
|
|
||||||
def encodeByteArray(value):
|
def encodeByteArray(value):
|
||||||
@@ -450,10 +488,7 @@ def encodeByteArray(value):
|
|||||||
if size > 0:
|
if size > 0:
|
||||||
checkAccess(data, 4)
|
checkAccess(data, 4)
|
||||||
checkAccess(data + size) == 0
|
checkAccess(data + size) == 0
|
||||||
|
return encodeCharArray(data, size)
|
||||||
innerType = gdb.lookup_type("char")
|
|
||||||
p = gdb.Value(data.cast(innerType.pointer()))
|
|
||||||
return encodeCharArray(p, size)
|
|
||||||
|
|
||||||
def encodeString(value):
|
def encodeString(value):
|
||||||
d_ptr = value['d'].dereference()
|
d_ptr = value['d'].dereference()
|
||||||
@@ -502,22 +537,33 @@ class FrameCommand(gdb.Command):
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(FrameCommand, self).__init__("bb", gdb.COMMAND_OBSCURE)
|
super(FrameCommand, self).__init__("bb", gdb.COMMAND_OBSCURE)
|
||||||
|
|
||||||
def invoke(self, arg, from_tty):
|
def invoke(self, args, from_tty):
|
||||||
args = arg.split(' ')
|
options = []
|
||||||
|
varList = []
|
||||||
#warn("ARG: %s" % arg)
|
typeformats = {}
|
||||||
#warn("ARGS: %s" % args)
|
formats = {}
|
||||||
options = args[0].split(",")
|
|
||||||
varList = args[1][1:]
|
|
||||||
if len(varList) == 0:
|
|
||||||
varList = []
|
|
||||||
else:
|
|
||||||
varList = varList.split(",")
|
|
||||||
expandedINames = set(args[2].split(","))
|
|
||||||
watchers = ""
|
watchers = ""
|
||||||
if len(args) > 3:
|
for arg in args.split(' '):
|
||||||
watchers = base64.b16decode(args[3], True)
|
pos = arg.find(":") + 1
|
||||||
#warn("WATCHERS: %s" % watchers)
|
if arg.startswith("options:"):
|
||||||
|
options = arg[pos:].split(",")
|
||||||
|
elif arg.startswith("vars:"):
|
||||||
|
vars = arg[pos:].split(",")
|
||||||
|
elif arg.startswith("expanded:"):
|
||||||
|
expandedINames = set(arg[pos:].split(","))
|
||||||
|
elif arg.startswith("typeformats:"):
|
||||||
|
for f in arg[pos:].split(","):
|
||||||
|
pos = f.find("=")
|
||||||
|
if pos != -1:
|
||||||
|
type = base64.b16decode(f[0:pos], True)
|
||||||
|
typeformats[type] = int(f[pos+1:])
|
||||||
|
elif arg.startswith("formats:"):
|
||||||
|
for f in arg[pos:].split(","):
|
||||||
|
pos = f.find("=")
|
||||||
|
if pos != -1:
|
||||||
|
formats[f[0:pos]] = int(f[pos+1:])
|
||||||
|
elif arg.startswith("watchers:"):
|
||||||
|
watchers = base64.b16decode(arg[pos:], True)
|
||||||
|
|
||||||
useFancy = "fancy" in options
|
useFancy = "fancy" in options
|
||||||
|
|
||||||
@@ -552,6 +598,8 @@ class FrameCommand(gdb.Command):
|
|||||||
|
|
||||||
d = Dumper()
|
d = Dumper()
|
||||||
d.dumpers = self.dumpers
|
d.dumpers = self.dumpers
|
||||||
|
d.typeformats = typeformats
|
||||||
|
d.formats = formats
|
||||||
d.useFancy = useFancy
|
d.useFancy = useFancy
|
||||||
d.passExceptions = "passexceptions" in options
|
d.passExceptions = "passexceptions" in options
|
||||||
d.autoDerefPointers = "autoderef" in options
|
d.autoDerefPointers = "autoderef" in options
|
||||||
@@ -837,6 +885,9 @@ class Dumper:
|
|||||||
if len(type) > 0 and type != self.childTypes[-1]:
|
if len(type) > 0 and type != self.childTypes[-1]:
|
||||||
self.put('type="%s",' % type) # str(type.unqualified()) ?
|
self.put('type="%s",' % type) # str(type.unqualified()) ?
|
||||||
|
|
||||||
|
def putAddress(self, addr):
|
||||||
|
self.put('addr="%s",' % cleanAddress(addr))
|
||||||
|
|
||||||
def putNumChild(self, numchild):
|
def putNumChild(self, numchild):
|
||||||
#warn("NUM CHILD: '%s' '%s'" % (numchild, self.childNumChilds[-1]))
|
#warn("NUM CHILD: '%s' '%s'" % (numchild, self.childNumChilds[-1]))
|
||||||
if numchild != self.childNumChilds[-1]:
|
if numchild != self.childNumChilds[-1]:
|
||||||
@@ -1038,13 +1089,36 @@ class Dumper:
|
|||||||
|
|
||||||
|
|
||||||
elif type.code == gdb.TYPE_CODE_PTR:
|
elif type.code == gdb.TYPE_CODE_PTR:
|
||||||
#warn("A POINTER: %s" % value.type)
|
|
||||||
isHandled = False
|
isHandled = False
|
||||||
|
|
||||||
if str(type.strip_typedefs()).find("(") != -1:
|
format = self.formats.get(item.iname)
|
||||||
|
if format is None:
|
||||||
|
format = self.typeformats.get(str(value.type))
|
||||||
|
|
||||||
|
if not format is None:
|
||||||
|
self.putAddress(value.address)
|
||||||
|
self.putType(item.value.type)
|
||||||
|
self.putNumChild(0)
|
||||||
|
isHandled = True
|
||||||
|
|
||||||
|
if format == 0:
|
||||||
|
# Bald pointer.
|
||||||
|
self.putValue(str(cleanAddress(value.address)))
|
||||||
|
elif format == 1 or format == 2:
|
||||||
|
# Latin1 or UTF-8
|
||||||
|
f = select(format == 1, "6", "9")
|
||||||
|
self.putValue(encodeCharArray(value, 100), f)
|
||||||
|
elif format == 3:
|
||||||
|
# UTF-16.
|
||||||
|
self.putValue(encodeChar2Array(value, 100), "11")
|
||||||
|
elif format == 4:
|
||||||
|
# UCS-4:
|
||||||
|
self.putValue(encodeChar4Array(value, 100), "10")
|
||||||
|
|
||||||
|
if (not isHandled) and str(type.strip_typedefs()).find("(") != -1:
|
||||||
# A function pointer.
|
# A function pointer.
|
||||||
self.putValue(str(item.value))
|
self.putValue(str(item.value))
|
||||||
self.put('addr="%s",' % cleanAddress(value.address))
|
self.putAddress(value.address)
|
||||||
self.putType(item.value.type)
|
self.putType(item.value.type)
|
||||||
self.putNumChild(0)
|
self.putNumChild(0)
|
||||||
isHandled = True
|
isHandled = True
|
||||||
@@ -1069,21 +1143,8 @@ class Dumper:
|
|||||||
# Display values up to given length directly
|
# Display values up to given length directly
|
||||||
#warn("CHAR AUTODEREF: %s" % value.address)
|
#warn("CHAR AUTODEREF: %s" % value.address)
|
||||||
self.putType(item.value.type)
|
self.putType(item.value.type)
|
||||||
firstNul = -1
|
self.putValue(encodeCharArray(value, 100), "6")
|
||||||
p = value
|
self.putNumChild(0)
|
||||||
found = False
|
|
||||||
for i in xrange(100):
|
|
||||||
if p.dereference() == 0:
|
|
||||||
# Found terminating NUL
|
|
||||||
found = True
|
|
||||||
break
|
|
||||||
p += 1
|
|
||||||
if found:
|
|
||||||
self.putValue(encodeCharArray(value, i), "6")
|
|
||||||
self.putNumChild(0)
|
|
||||||
else:
|
|
||||||
self.putValue(encodeCharArray(value, 100) + "2e2e2e", "6")
|
|
||||||
self.putNumChild(0)
|
|
||||||
isHandled = True
|
isHandled = True
|
||||||
|
|
||||||
#warn("AUTODEREF: %s" % self.autoDerefPointers)
|
#warn("AUTODEREF: %s" % self.autoDerefPointers)
|
||||||
@@ -1105,8 +1166,9 @@ class Dumper:
|
|||||||
if not isHandled:
|
if not isHandled:
|
||||||
#warn("GENERIC PLAIN POINTER: %s" % value.type)
|
#warn("GENERIC PLAIN POINTER: %s" % value.type)
|
||||||
self.putType(item.value.type)
|
self.putType(item.value.type)
|
||||||
self.putValue(str(value))
|
#self.putValue(str(value))
|
||||||
self.put('addr="%s",' % cleanAddress(value.address))
|
self.putValue("")
|
||||||
|
self.putAddress(value.address)
|
||||||
self.putNumChild(1)
|
self.putNumChild(1)
|
||||||
if self.isExpanded(item):
|
if self.isExpanded(item):
|
||||||
self.beginChildren()
|
self.beginChildren()
|
||||||
@@ -1208,7 +1270,7 @@ class Dumper:
|
|||||||
value = item.value[field.name]
|
value = item.value[field.name]
|
||||||
child = Item(value, item.iname, field.name, field.name)
|
child = Item(value, item.iname, field.name, field.name)
|
||||||
self.beginHash()
|
self.beginHash()
|
||||||
self.put('addr="%s",' % cleanAddress(value.address))
|
self.putAddress(value.address)
|
||||||
self.putItemHelper(child)
|
self.putItemHelper(child)
|
||||||
self.endHash();
|
self.endHash();
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -252,10 +252,10 @@ void GdbEngine::updateSubItemClassic(const WatchData &data0)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// we should have a type now. this is relied upon further below
|
// We should have a type now. This is relied upon further below.
|
||||||
QTC_ASSERT(!data.type.isEmpty(), return);
|
QTC_ASSERT(!data.type.isEmpty(), return);
|
||||||
|
|
||||||
// a common case that can be easily solved
|
// A common case that can be easily solved.
|
||||||
if (data.isChildrenNeeded() && isPointerType(data.type)
|
if (data.isChildrenNeeded() && isPointerType(data.type)
|
||||||
&& !hasDebuggingHelperForType(data.type)) {
|
&& !hasDebuggingHelperForType(data.type)) {
|
||||||
// We sometimes know what kind of children pointers have
|
// We sometimes know what kind of children pointers have
|
||||||
@@ -431,8 +431,6 @@ void GdbEngine::handleDebuggingHelperValue3Classic(const GdbResponse &response)
|
|||||||
while (out.endsWith(' ') || out.endsWith('\n'))
|
while (out.endsWith(' ') || out.endsWith('\n'))
|
||||||
out.chop(1);
|
out.chop(1);
|
||||||
QList<QByteArray> list = out.split(' ');
|
QList<QByteArray> list = out.split(' ');
|
||||||
//qDebug() << "RECEIVED" << response.toString() << "FOR" << data0.toString()
|
|
||||||
// << " STREAM:" << out;
|
|
||||||
if (list.isEmpty()) {
|
if (list.isEmpty()) {
|
||||||
//: Value for variable
|
//: Value for variable
|
||||||
data.setError(WatchData::msgNotInScope());
|
data.setError(WatchData::msgNotInScope());
|
||||||
@@ -538,7 +536,7 @@ void GdbEngine::tryLoadDebuggingHelpersClassic()
|
|||||||
postCommand("call (void*)dlopen(\"" + GdbMi::escapeCString(dlopenLib)
|
postCommand("call (void*)dlopen(\"" + GdbMi::escapeCString(dlopenLib)
|
||||||
+ "\", " + flag + ")",
|
+ "\", " + flag + ")",
|
||||||
CB(handleDebuggingHelperSetup));
|
CB(handleDebuggingHelperSetup));
|
||||||
// some older systems like CentOS 4.6 prefer this:
|
// Some older systems like CentOS 4.6 prefer this:
|
||||||
postCommand("call (void*)__dlopen(\"" + GdbMi::escapeCString(dlopenLib)
|
postCommand("call (void*)__dlopen(\"" + GdbMi::escapeCString(dlopenLib)
|
||||||
+ "\", " + flag + ")",
|
+ "\", " + flag + ")",
|
||||||
CB(handleDebuggingHelperSetup));
|
CB(handleDebuggingHelperSetup));
|
||||||
@@ -550,7 +548,7 @@ void GdbEngine::tryLoadDebuggingHelpersClassic()
|
|||||||
void GdbEngine::tryQueryDebuggingHelpersClassic()
|
void GdbEngine::tryQueryDebuggingHelpersClassic()
|
||||||
{
|
{
|
||||||
PRECONDITION;
|
PRECONDITION;
|
||||||
// retrieve list of dumpable classes
|
// Retrieve list of dumpable classes.
|
||||||
postCommand("call (void*)qDumpObjectData440(1,0,0,0,0,0,0,0)");
|
postCommand("call (void*)qDumpObjectData440(1,0,0,0,0,0,0,0)");
|
||||||
postCommand("p (char*)&qDumpOutBuffer",
|
postCommand("p (char*)&qDumpOutBuffer",
|
||||||
CB(handleQueryDebuggingHelperClassic));
|
CB(handleQueryDebuggingHelperClassic));
|
||||||
@@ -560,7 +558,7 @@ void GdbEngine::recheckDebuggingHelperAvailabilityClassic()
|
|||||||
{
|
{
|
||||||
PRECONDITION;
|
PRECONDITION;
|
||||||
if (m_gdbAdapter->dumperHandling() != AbstractGdbAdapter::DumperNotAvailable) {
|
if (m_gdbAdapter->dumperHandling() != AbstractGdbAdapter::DumperNotAvailable) {
|
||||||
// retrieve list of dumpable classes
|
// Retrieve list of dumpable classes.
|
||||||
postCommand("call (void*)qDumpObjectData440(1,0,0,0,0,0,0,0)");
|
postCommand("call (void*)qDumpObjectData440(1,0,0,0,0,0,0,0)");
|
||||||
postCommand("p (char*)&qDumpOutBuffer",
|
postCommand("p (char*)&qDumpOutBuffer",
|
||||||
CB(handleQueryDebuggingHelperClassic));
|
CB(handleQueryDebuggingHelperClassic));
|
||||||
@@ -681,7 +679,6 @@ bool GdbEngine::checkDebuggingHelpersClassic()
|
|||||||
if (!manager()->qtDumperLibraryEnabled())
|
if (!manager()->qtDumperLibraryEnabled())
|
||||||
return false;
|
return false;
|
||||||
const QString lib = qtDumperLibraryName();
|
const QString lib = qtDumperLibraryName();
|
||||||
//qDebug() << "DUMPERLIB:" << lib;
|
|
||||||
const QFileInfo fi(lib);
|
const QFileInfo fi(lib);
|
||||||
if (!fi.exists()) {
|
if (!fi.exists()) {
|
||||||
const QStringList &locations = manager()->qtDumperLibraryLocations();
|
const QStringList &locations = manager()->qtDumperLibraryLocations();
|
||||||
|
|||||||
@@ -3321,7 +3321,7 @@ void GdbEngine::setWatchDataDisplayedType(WatchData &data, const GdbMi &item)
|
|||||||
void GdbEngine::handleVarCreate(const GdbResponse &response)
|
void GdbEngine::handleVarCreate(const GdbResponse &response)
|
||||||
{
|
{
|
||||||
WatchData data = response.cookie.value<WatchData>();
|
WatchData data = response.cookie.value<WatchData>();
|
||||||
// happens e.g. when we already issued a var-evaluate command
|
// Happens e.g. when we already issued a var-evaluate command.
|
||||||
if (!data.isValid())
|
if (!data.isValid())
|
||||||
return;
|
return;
|
||||||
//qDebug() << "HANDLE VARIABLE CREATION:" << data.toString();
|
//qDebug() << "HANDLE VARIABLE CREATION:" << data.toString();
|
||||||
@@ -3351,11 +3351,9 @@ void GdbEngine::handleVarCreate(const GdbResponse &response)
|
|||||||
|
|
||||||
void GdbEngine::handleDebuggingHelperSetup(const GdbResponse &response)
|
void GdbEngine::handleDebuggingHelperSetup(const GdbResponse &response)
|
||||||
{
|
{
|
||||||
//qDebug() << "CUSTOM SETUP RESULT:" << response.toString();
|
|
||||||
if (response.resultClass == GdbResultDone) {
|
if (response.resultClass == GdbResultDone) {
|
||||||
} else {
|
} else {
|
||||||
QString msg = QString::fromLocal8Bit(response.data.findChild("msg").data());
|
QString msg = QString::fromLocal8Bit(response.data.findChild("msg").data());
|
||||||
//qDebug() << "CUSTOM DUMPER SETUP ERROR MESSAGE:" << msg;
|
|
||||||
showStatusMessage(tr("Custom dumper setup: %1").arg(msg), 10000);
|
showStatusMessage(tr("Custom dumper setup: %1").arg(msg), 10000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3381,7 +3379,6 @@ void GdbEngine::handleChildren(const WatchData &data0, const GdbMi &item,
|
|||||||
}
|
}
|
||||||
setWatchDataType(data, item.findChild("type"));
|
setWatchDataType(data, item.findChild("type"));
|
||||||
setWatchDataEditValue(data, item.findChild("editvalue"));
|
setWatchDataEditValue(data, item.findChild("editvalue"));
|
||||||
setWatchDataChildCount(data, item.findChild("numchild"));
|
|
||||||
setWatchDataValue(data, item.findChild("value"),
|
setWatchDataValue(data, item.findChild("value"),
|
||||||
item.findChild("valueencoded").data().toInt());
|
item.findChild("valueencoded").data().toInt());
|
||||||
setWatchDataAddress(data, item.findChild("addr"));
|
setWatchDataAddress(data, item.findChild("addr"));
|
||||||
@@ -3391,6 +3388,7 @@ void GdbEngine::handleChildren(const WatchData &data0, const GdbMi &item,
|
|||||||
item.findChild("valuetooltipencoded").data().toInt());
|
item.findChild("valuetooltipencoded").data().toInt());
|
||||||
setWatchDataValueEnabled(data, item.findChild("valueenabled"));
|
setWatchDataValueEnabled(data, item.findChild("valueenabled"));
|
||||||
setWatchDataValueEditable(data, item.findChild("valueeditable"));
|
setWatchDataValueEditable(data, item.findChild("valueeditable"));
|
||||||
|
setWatchDataChildCount(data, item.findChild("numchild"));
|
||||||
//qDebug() << "\nAPPEND TO LIST: " << data.toString() << "\n";
|
//qDebug() << "\nAPPEND TO LIST: " << data.toString() << "\n";
|
||||||
list->append(data);
|
list->append(data);
|
||||||
|
|
||||||
@@ -3451,7 +3449,7 @@ void GdbEngine::updateLocals(const QVariant &cookie)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Parse a local variable from GdbMi
|
// Parse a local variable from GdbMi.
|
||||||
WatchData GdbEngine::localVariable(const GdbMi &item,
|
WatchData GdbEngine::localVariable(const GdbMi &item,
|
||||||
const QStringList &uninitializedVariables,
|
const QStringList &uninitializedVariables,
|
||||||
QMap<QByteArray, int> *seen)
|
QMap<QByteArray, int> *seen)
|
||||||
@@ -3479,7 +3477,7 @@ WatchData GdbEngine::localVariable(const GdbMi &item,
|
|||||||
WatchData data;
|
WatchData data;
|
||||||
QString nam = _(name);
|
QString nam = _(name);
|
||||||
data.iname = "local." + name + QByteArray::number(n + 1);
|
data.iname = "local." + name + QByteArray::number(n + 1);
|
||||||
//: Variable %1 is the variable name, %2 is a simple count
|
//: Variable %1 is the variable name, %2 is a simple count.
|
||||||
data.name = WatchData::shadowedName(nam, n);
|
data.name = WatchData::shadowedName(nam, n);
|
||||||
if (uninitializedVariables.contains(data.name)) {
|
if (uninitializedVariables.contains(data.name)) {
|
||||||
data.setError(WatchData::msgNotInScope());
|
data.setError(WatchData::msgNotInScope());
|
||||||
@@ -3511,8 +3509,8 @@ WatchData GdbEngine::localVariable(const GdbMi &item,
|
|||||||
// somewhere in the response.
|
// somewhere in the response.
|
||||||
data.setChildrenUnneeded();
|
data.setChildrenUnneeded();
|
||||||
} else {
|
} else {
|
||||||
// set value only directly if it is simple enough, otherwise
|
// Set value only directly if it is simple enough, otherwise
|
||||||
// pass through the insertData() machinery
|
// pass through the insertData() machinery.
|
||||||
if (isIntOrFloatType(data.type) || isPointerType(data.type))
|
if (isIntOrFloatType(data.type) || isPointerType(data.type))
|
||||||
setWatchDataValue(data, item.findChild("value"));
|
setWatchDataValue(data, item.findChild("value"));
|
||||||
if (isSymbianIntType(data.type)) {
|
if (isSymbianIntType(data.type)) {
|
||||||
@@ -3523,7 +3521,11 @@ WatchData GdbEngine::localVariable(const GdbMi &item,
|
|||||||
|
|
||||||
if (!m_manager->watchHandler()->isExpandedIName(data.iname))
|
if (!m_manager->watchHandler()->isExpandedIName(data.iname))
|
||||||
data.setChildrenUnneeded();
|
data.setChildrenUnneeded();
|
||||||
if (isPointerType(data.type) || data.name == __("this"))
|
|
||||||
|
GdbMi t = item.findChild("numchild");
|
||||||
|
if (t.isValid())
|
||||||
|
data.setHasChildren(t.data().toInt() > 0);
|
||||||
|
else if (isPointerType(data.type) || data.name == __("this"))
|
||||||
data.setHasChildren(true);
|
data.setHasChildren(true);
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,13 +55,7 @@ void GdbEngine::updateLocalsPython(const QByteArray &varList)
|
|||||||
//m_toolTipExpression.clear();
|
//m_toolTipExpression.clear();
|
||||||
WatchHandler *handler = m_manager->watchHandler();
|
WatchHandler *handler = m_manager->watchHandler();
|
||||||
|
|
||||||
QByteArray expanded;
|
QByteArray expanded = handler->formatRequests();
|
||||||
QSet<QByteArray> expandedINames = handler->expandedINames();
|
|
||||||
QSetIterator<QByteArray> jt(expandedINames);
|
|
||||||
while (jt.hasNext()) {
|
|
||||||
expanded.append(jt.next());
|
|
||||||
expanded.append(',');
|
|
||||||
}
|
|
||||||
if (expanded.isEmpty())
|
if (expanded.isEmpty())
|
||||||
expanded.append("defaults,");
|
expanded.append("defaults,");
|
||||||
expanded.chop(1);
|
expanded.chop(1);
|
||||||
@@ -92,8 +86,8 @@ void GdbEngine::updateLocalsPython(const QByteArray &varList)
|
|||||||
options += "defaults,";
|
options += "defaults,";
|
||||||
options.chop(1);
|
options.chop(1);
|
||||||
|
|
||||||
postCommand("bb " + options + " @" + varList + ' '
|
postCommand("bb options:" + options + " vars:" + varList + ' '
|
||||||
+ expanded + ' ' + watchers.toHex(),
|
+ expanded + " watchers:" + watchers.toHex(),
|
||||||
WatchUpdate, CB(handleStackFramePython));
|
WatchUpdate, CB(handleStackFramePython));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -639,27 +639,6 @@ static QString formattedValue(const WatchData &data, int format)
|
|||||||
return reformatInteger(data.value.toULongLong(), format);
|
return reformatInteger(data.value.toULongLong(), format);
|
||||||
return reformatInteger(data.value.toLongLong(), format);
|
return reformatInteger(data.value.toLongLong(), format);
|
||||||
}
|
}
|
||||||
if (0 && !data.addr.isEmpty()) {
|
|
||||||
if (format == BaldPointerFormat)
|
|
||||||
return data.value;
|
|
||||||
bool ok = false;
|
|
||||||
const void *addr =
|
|
||||||
reinterpret_cast<void *>(data.value.toULongLong(&ok, 0));
|
|
||||||
if (!ok || !addr)
|
|
||||||
return data.value;
|
|
||||||
// FIXME: add a round trip through the debugger to prevent crashs?
|
|
||||||
if (format == Latin1StringFormat)
|
|
||||||
return QString::fromLatin1(static_cast<const char *>(addr));
|
|
||||||
if (format == Local8BitStringFormat)
|
|
||||||
return QString::fromLocal8Bit(static_cast<const char *>(addr));
|
|
||||||
if (format == Utf8StringFormat)
|
|
||||||
return QString::fromUtf8(static_cast<const char *>(addr));
|
|
||||||
if (format == Utf16StringFormat)
|
|
||||||
return QString::fromUtf16(static_cast<const ushort *>(addr));
|
|
||||||
if (format == Ucs4StringFormat)
|
|
||||||
return QString::fromUcs4(static_cast<const uint *>(addr));
|
|
||||||
return data.value;
|
|
||||||
}
|
|
||||||
return data.value;
|
return data.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -802,7 +781,6 @@ QVariant WatchModel::data(const QModelIndex &idx, int role) const
|
|||||||
int format = m_handler->m_individualFormats.value(data.iname, -1);
|
int format = m_handler->m_individualFormats.value(data.iname, -1);
|
||||||
if (format == -1)
|
if (format == -1)
|
||||||
format = m_handler->m_typeFormats.value(data.type, -1);
|
format = m_handler->m_typeFormats.value(data.type, -1);
|
||||||
//qDebug() << "FORMATTED: " << format << formattedValue(data, format);
|
|
||||||
return truncateValue(formattedValue(data, format));
|
return truncateValue(formattedValue(data, format));
|
||||||
}
|
}
|
||||||
case 2: {
|
case 2: {
|
||||||
@@ -845,7 +823,7 @@ QVariant WatchModel::data(const QModelIndex &idx, int role) const
|
|||||||
if (isIntType(data.type))
|
if (isIntType(data.type))
|
||||||
return QStringList() << tr("decimal") << tr("hexadecimal")
|
return QStringList() << tr("decimal") << tr("hexadecimal")
|
||||||
<< tr("binary") << tr("octal");
|
<< tr("binary") << tr("octal");
|
||||||
if (!data.addr.isEmpty())
|
if (data.type.endsWith(QLatin1Char('*')))
|
||||||
return QStringList()
|
return QStringList()
|
||||||
<< tr("Bald pointer")
|
<< tr("Bald pointer")
|
||||||
<< tr("Latin1 string")
|
<< tr("Latin1 string")
|
||||||
@@ -889,6 +867,7 @@ bool WatchModel::setData(const QModelIndex &index, const QVariant &value, int ro
|
|||||||
}
|
}
|
||||||
} else if (role == TypeFormatRole) {
|
} else if (role == TypeFormatRole) {
|
||||||
m_handler->setFormat(data.type, value.toInt());
|
m_handler->setFormat(data.type, value.toInt());
|
||||||
|
m_handler->m_manager->updateWatchData(data);
|
||||||
} else if (role == IndividualFormatRole) {
|
} else if (role == IndividualFormatRole) {
|
||||||
const int format = value.toInt();
|
const int format = value.toInt();
|
||||||
if (format == -1) {
|
if (format == -1) {
|
||||||
@@ -896,6 +875,7 @@ bool WatchModel::setData(const QModelIndex &index, const QVariant &value, int ro
|
|||||||
} else {
|
} else {
|
||||||
m_handler->m_individualFormats[data.iname] = format;
|
m_handler->m_individualFormats[data.iname] = format;
|
||||||
}
|
}
|
||||||
|
m_handler->m_manager->updateWatchData(data);
|
||||||
}
|
}
|
||||||
emit dataChanged(index, index);
|
emit dataChanged(index, index);
|
||||||
return true;
|
return true;
|
||||||
@@ -1155,8 +1135,8 @@ WatchItem *WatchModel::findItem(const QByteArray &iname, WatchItem *root) const
|
|||||||
static void debugRecursion(QDebug &d, const WatchItem *item, int depth)
|
static void debugRecursion(QDebug &d, const WatchItem *item, int depth)
|
||||||
{
|
{
|
||||||
d << QString(2 * depth, QLatin1Char(' ')) << item->toString() << '\n';
|
d << QString(2 * depth, QLatin1Char(' ')) << item->toString() << '\n';
|
||||||
foreach(const WatchItem *i, item->children)
|
foreach (const WatchItem *child, item->children)
|
||||||
debugRecursion(d, i, depth + 1);
|
debugRecursion(d, child, depth + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
QDebug operator<<(QDebug d, const WatchModel &m)
|
QDebug operator<<(QDebug d, const WatchModel &m)
|
||||||
@@ -1167,6 +1147,16 @@ QDebug operator<<(QDebug d, const WatchModel &m)
|
|||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WatchModel::formatRequests(QByteArray *out, const WatchItem *item) const
|
||||||
|
{
|
||||||
|
int format = m_handler->m_individualFormats.value(item->iname, -1);
|
||||||
|
if (format == -1)
|
||||||
|
format = m_handler->m_typeFormats.value(item->type, -1);
|
||||||
|
if (format != -1)
|
||||||
|
*out += item->iname + ":format=" + QByteArray::number(format) + ',';
|
||||||
|
foreach (const WatchItem *child, item->children)
|
||||||
|
formatRequests(out, child);
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
@@ -1573,5 +1563,65 @@ void WatchHandler::setFormat(const QString &type, int format)
|
|||||||
m_tooltips->emitDataChanged(1);
|
m_tooltips->emitDataChanged(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int WatchHandler::format(const QByteArray &iname) const
|
||||||
|
{
|
||||||
|
int result = -1;
|
||||||
|
if (const WatchData *item = findItem(iname)) {
|
||||||
|
int result = m_individualFormats.value(iname, -1);
|
||||||
|
if (result == -1)
|
||||||
|
result = m_typeFormats.value(item->type, -1);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray WatchHandler::formatRequests() const
|
||||||
|
{
|
||||||
|
QByteArray ba;
|
||||||
|
//m_locals->formatRequests(&ba, m_locals->m_root);
|
||||||
|
//m_watchers->formatRequests(&ba, m_watchers->m_root);
|
||||||
|
|
||||||
|
ba.append("expanded:");
|
||||||
|
if (!m_expandedINames.isEmpty()) {
|
||||||
|
QSetIterator<QByteArray> jt(m_expandedINames);
|
||||||
|
while (jt.hasNext()) {
|
||||||
|
QByteArray iname = jt.next();
|
||||||
|
ba.append(iname);
|
||||||
|
ba.append(',');
|
||||||
|
}
|
||||||
|
ba.chop(1);
|
||||||
|
}
|
||||||
|
ba.append(' ');
|
||||||
|
|
||||||
|
ba.append("typeformats:");
|
||||||
|
if (!m_typeFormats.isEmpty()) {
|
||||||
|
QHashIterator<QString, int> it(m_typeFormats);
|
||||||
|
while (it.hasNext()) {
|
||||||
|
it.next();
|
||||||
|
ba.append(it.key().toLatin1().toHex());
|
||||||
|
ba.append('=');
|
||||||
|
ba.append(QByteArray::number(it.value()));
|
||||||
|
ba.append(',');
|
||||||
|
}
|
||||||
|
ba.chop(1);
|
||||||
|
}
|
||||||
|
ba.append(' ');
|
||||||
|
|
||||||
|
ba.append("formats:");
|
||||||
|
if (!m_individualFormats.isEmpty()) {
|
||||||
|
QHashIterator<QString, int> it(m_individualFormats);
|
||||||
|
while (it.hasNext()) {
|
||||||
|
it.next();
|
||||||
|
ba.append(it.key().toLatin1());
|
||||||
|
ba.append('=');
|
||||||
|
ba.append(QByteArray::number(it.value()));
|
||||||
|
ba.append(',');
|
||||||
|
}
|
||||||
|
ba.chop(1);
|
||||||
|
}
|
||||||
|
ba.append(' ');
|
||||||
|
|
||||||
|
return ba;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
} // namespace Debugger
|
} // namespace Debugger
|
||||||
|
|||||||
@@ -139,8 +139,6 @@ public:
|
|||||||
bool valueEditable; // value will be editable
|
bool valueEditable; // value will be editable
|
||||||
bool error;
|
bool error;
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
int source; // Used by some debuggers (CDB) to tell where it originates from (dumper or symbol evaluation)
|
int source; // Used by some debuggers (CDB) to tell where it originates from (dumper or symbol evaluation)
|
||||||
int state;
|
int state;
|
||||||
@@ -239,6 +237,7 @@ signals:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
QString niceType(const QString &typeIn) const;
|
QString niceType(const QString &typeIn) const;
|
||||||
|
void formatRequests(QByteArray *out, const WatchItem *item) const;
|
||||||
|
|
||||||
WatchHandler *m_handler;
|
WatchHandler *m_handler;
|
||||||
WatchType m_type;
|
WatchType m_type;
|
||||||
@@ -284,8 +283,10 @@ public:
|
|||||||
QStringList watchedExpressions() const;
|
QStringList watchedExpressions() const;
|
||||||
QHash<QByteArray, int> watcherNames() const
|
QHash<QByteArray, int> watcherNames() const
|
||||||
{ return m_watcherNames; }
|
{ return m_watcherNames; }
|
||||||
|
QByteArray formatRequests() const;
|
||||||
|
|
||||||
static QString watcherEditPlaceHolder();
|
static QString watcherEditPlaceHolder();
|
||||||
|
int format(const QByteArray &iname) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class WatchModel;
|
friend class WatchModel;
|
||||||
|
|||||||
@@ -640,7 +640,7 @@ QString decodeData(const QByteArray &ba, int encoding)
|
|||||||
case 5: { // base64 encoded 8 bit data, without quotes (see 1)
|
case 5: { // base64 encoded 8 bit data, without quotes (see 1)
|
||||||
return quoteUnprintableLatin1(QByteArray::fromBase64(ba));
|
return quoteUnprintableLatin1(QByteArray::fromBase64(ba));
|
||||||
}
|
}
|
||||||
case 6: { // %02x encoded 8 bit data
|
case 6: { // %02x encoded 8 bit Latin1 data
|
||||||
const QChar doubleQuote(QLatin1Char('"'));
|
const QChar doubleQuote(QLatin1Char('"'));
|
||||||
const QByteArray decodedBa = QByteArray::fromHex(ba);
|
const QByteArray decodedBa = QByteArray::fromHex(ba);
|
||||||
//qDebug() << quoteUnprintableLatin1(decodedBa) << "\n\n";
|
//qDebug() << quoteUnprintableLatin1(decodedBa) << "\n\n";
|
||||||
@@ -660,6 +660,39 @@ QString decodeData(const QByteArray &ba, int encoding)
|
|||||||
return doubleQuote + QString::fromUcs4(reinterpret_cast<const uint *>
|
return doubleQuote + QString::fromUcs4(reinterpret_cast<const uint *>
|
||||||
(decodedBa.data()), decodedBa.size() / 4) + doubleQuote;
|
(decodedBa.data()), decodedBa.size() / 4) + doubleQuote;
|
||||||
}
|
}
|
||||||
|
case 9: { // %02x encoded 8 bit Utf-8 data
|
||||||
|
const QChar doubleQuote(QLatin1Char('"'));
|
||||||
|
const QByteArray decodedBa = QByteArray::fromHex(ba);
|
||||||
|
//qDebug() << quoteUnprintableLatin1(decodedBa) << "\n\n";
|
||||||
|
return doubleQuote + QString::fromUtf8(decodedBa) + doubleQuote;
|
||||||
|
}
|
||||||
|
case 10: { // %08x encoded 32 bit data, Big Endian
|
||||||
|
const QChar doubleQuote(QLatin1Char('"'));
|
||||||
|
QByteArray decodedBa = QByteArray::fromHex(ba);
|
||||||
|
for (int i = 0; i < decodedBa.size(); i += 4) {
|
||||||
|
char c = decodedBa.at(i);
|
||||||
|
decodedBa[i] = decodedBa.at(i + 3);
|
||||||
|
decodedBa[i + 3] = c;
|
||||||
|
c = decodedBa.at(i + 1);
|
||||||
|
decodedBa[i + 1] = decodedBa.at(i + 2);
|
||||||
|
decodedBa[i + 2] = c;
|
||||||
|
}
|
||||||
|
//qDebug() << quoteUnprintableLatin1(decodedBa) << "\n\n";
|
||||||
|
return doubleQuote + QString::fromUcs4(reinterpret_cast<const uint *>
|
||||||
|
(decodedBa.data()), decodedBa.size() / 4) + doubleQuote;
|
||||||
|
}
|
||||||
|
case 11: { // %02x encoded 16 bit data, Big Endian
|
||||||
|
const QChar doubleQuote(QLatin1Char('"'));
|
||||||
|
QByteArray decodedBa = QByteArray::fromHex(ba);
|
||||||
|
for (int i = 0; i < decodedBa.size(); i += 2) {
|
||||||
|
char c = decodedBa.at(i);
|
||||||
|
decodedBa[i] = decodedBa.at(i + 1);
|
||||||
|
decodedBa[i + 1] = c;
|
||||||
|
}
|
||||||
|
//qDebug() << quoteUnprintableLatin1(decodedBa) << "\n\n";
|
||||||
|
return doubleQuote + QString::fromUcs4(reinterpret_cast<const uint *>
|
||||||
|
(decodedBa.data()), decodedBa.size() / 4) + doubleQuote;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
qDebug() << "ENCODING ERROR: " << encoding;
|
qDebug() << "ENCODING ERROR: " << encoding;
|
||||||
return QCoreApplication::translate("Debugger", "<Encoding error>");
|
return QCoreApplication::translate("Debugger", "<Encoding error>");
|
||||||
|
|||||||
@@ -269,7 +269,8 @@ void WatchWindow::contextMenuEvent(QContextMenuEvent *ev)
|
|||||||
actWatchUnknownMemory->setEnabled(actionsEnabled && canShowMemory);
|
actWatchUnknownMemory->setEnabled(actionsEnabled && canShowMemory);
|
||||||
|
|
||||||
if (canShowMemory && !address.isEmpty())
|
if (canShowMemory && !address.isEmpty())
|
||||||
actWatchKnownMemory = new QAction(tr("Open Memory Editor at %1").arg(address), &menu);
|
actWatchKnownMemory =
|
||||||
|
new QAction(tr("Open Memory Editor at %1").arg(address), &menu);
|
||||||
menu.addSeparator();
|
menu.addSeparator();
|
||||||
|
|
||||||
QAction *actWatchOrRemove;
|
QAction *actWatchOrRemove;
|
||||||
@@ -293,8 +294,10 @@ void WatchWindow::contextMenuEvent(QContextMenuEvent *ev)
|
|||||||
|
|
||||||
menu.addAction(theDebuggerAction(RecheckDebuggingHelpers));
|
menu.addAction(theDebuggerAction(RecheckDebuggingHelpers));
|
||||||
menu.addAction(theDebuggerAction(UseDebuggingHelpers));
|
menu.addAction(theDebuggerAction(UseDebuggingHelpers));
|
||||||
QAction *actClearCodeModelSnapshot = new QAction(tr("Refresh Code Model Snapshot"), &menu);
|
QAction *actClearCodeModelSnapshot
|
||||||
actClearCodeModelSnapshot->setEnabled(actionsEnabled && theDebuggerAction(UseCodeModel)->isChecked());
|
= new QAction(tr("Refresh Code Model Snapshot"), &menu);
|
||||||
|
actClearCodeModelSnapshot->setEnabled(actionsEnabled
|
||||||
|
&& theDebuggerAction(UseCodeModel)->isChecked());
|
||||||
menu.addAction(actClearCodeModelSnapshot);
|
menu.addAction(actClearCodeModelSnapshot);
|
||||||
menu.addSeparator();
|
menu.addSeparator();
|
||||||
menu.addAction(theDebuggerAction(UseToolTipsInLocalsView));
|
menu.addAction(theDebuggerAction(UseToolTipsInLocalsView));
|
||||||
|
|||||||
@@ -1486,6 +1486,8 @@ int main(int argc, char *argv[])
|
|||||||
testPlugin();
|
testPlugin();
|
||||||
testQList();
|
testQList();
|
||||||
testQLinkedList();
|
testQLinkedList();
|
||||||
|
char *s = "aöa";
|
||||||
|
wchar_t *w = L"aöa";
|
||||||
testNamespace();
|
testNamespace();
|
||||||
//return 0;
|
//return 0;
|
||||||
testQHash();
|
testQHash();
|
||||||
|
|||||||
Reference in New Issue
Block a user