Commit c4648e97 authored by Martin Bohacek's avatar Martin Bohacek Committed by hjk

Debugger: Python dumper support for QNX targets on arm/x86.

gdbbridge.py + dumper.py:
    added detection on QNX target and ARM arch
    added detection of Qt 3 support
    fixed detection of Qt version

qttypes.py:
    fixes of different memory alignment

stdtypes.py:
    support of different libstdc++ internal structures on QNX

Change-Id: I808ee048c66c73c38bf5a8403e9cf881e767442e
Reviewed-by: default avatarhjk <hjk121@nokiamail.com>
parent 6c615593
......@@ -260,10 +260,19 @@ class DumperBase:
self.cachedFormats[typeName] = stripped
return stripped
def isArmArchitecture(self):
return False
def isQnxTarget(self):
return False
def is32bit(self):
return self.ptrSize() == 4
def isQt3Support(self):
# assume no Qt 3 support by default
return False
def computeLimit(self, size, limit):
if limit is None:
return size
......
......@@ -990,6 +990,12 @@ class Dumper(DumperBase):
return xrange(0, toInteger(self.currentNumChild))
return xrange(min(toInteger(self.currentMaxNumChild), toInteger(self.currentNumChild)))
def isArmArchitecture(self):
return 'arm' in gdb.TARGET_CONFIG.lower()
def isQnxTarget(self):
return 'qnx' in gdb.TARGET_CONFIG.lower()
def qtVersion(self):
try:
version = str(gdb.parse_and_eval("qVersion()"))
......@@ -998,7 +1004,7 @@ class Dumper(DumperBase):
except:
try:
# This will fail on Qt 5
gdb.execute("ptype QString::shared_empty", to_string=True)
gdb.execute("ptype QString::shared_null", to_string=True)
self.cachedQtVersion = 0x040800
except:
#self.cachedQtVersion = 0x050000
......@@ -1009,6 +1015,21 @@ class Dumper(DumperBase):
self.qtVersion = lambda: self.cachedQtVersion
return self.cachedQtVersion
def isQt3Support(self):
if self.qtVersion() >= 0x050000:
return False
else:
try:
# This will fail on Qt 4 without Qt 3 support
gdb.execute("ptype QChar::null", to_string=True)
self.cachedIsQt3Suport = True
except:
self.cachedIsQt3Suport = False
# Memoize good results.
self.isQt3Support = lambda: self.cachedIsQt3Suport
return self.cachedIsQt3Suport
def putType(self, type, priority = 0):
# Higher priority values override lower ones.
if priority >= self.currentTypePriority:
......
......@@ -291,6 +291,7 @@ def qdump__QDir(d, value):
privAddress = d.dereferenceValue(value)
bit32 = d.is32bit()
qt5 = d.qtVersion() >= 0x050000
qt3support = d.isQt3Support()
# QDirPrivate:
# QAtomicInt ref
# QStringList nameFilters;
......@@ -306,7 +307,7 @@ def qdump__QDir(d, value):
# QFileInfoList fileInfos;
# QFileSystemEntry dirEntry;
# QFileSystemEntry absoluteDirEntry;
qt3SupportAddition = 0 if qt5 else d.ptrSize() # qt5 doesn't have qt3support
qt3SupportAddition = d.ptrSize() if qt3support else 0
filesOffset = (24 if bit32 else 40) + qt3SupportAddition
fileInfosOffset = filesOffset + d.ptrSize()
dirEntryOffset = fileInfosOffset + d.ptrSize()
......@@ -733,6 +734,7 @@ def qdump__QImage(d, value):
ptrSize = d.ptrSize()
isQt5 = d.qtVersion() >= 0x050000
qt3Support = d.isQt3Support()
offset = (3 if isQt5 else 2) * ptrSize
base = d.dereference(d.addressOf(value) + offset)
width = d.extractInt(base + 4)
......@@ -740,7 +742,7 @@ def qdump__QImage(d, value):
nbytes = d.extractInt(base + 16)
padding = d.ptrSize() - d.intSize()
pixelRatioSize = 8 if isQt5 else 0
jumpTableSize = ptrSize if not isQt5 else 0 # FIXME: Assumes Qt3 Support
jumpTableSize = ptrSize if qt3Support else 0
bits = d.dereference(base + 20 + padding + pixelRatioSize + ptrSize)
iformat = d.extractInt(base + 20 + padding + pixelRatioSize + jumpTableSize + 2 * ptrSize)
d.putValue("(%dx%d)" % (width, height))
......@@ -870,6 +872,9 @@ def qdumpHelper__Qt4_QMap(d, value, forceLong):
# Or possibly 2 * sizeof(void *)
nodeType = d.lookupType(d.qtNamespace() + "QMapNode<%s,%s>" % (keyType, valueType))
nodePointerType = nodeType.pointer()
if d.isArmArchitecture() and d.isQnxTarget() and str(valueType) == 'QVariant': # symbols reports payload size at wrong size 24
payloadSize = 28
else:
payloadSize = nodeType.sizeof - 2 * nodePointerType.sizeof
if isCompact:
......
......@@ -90,6 +90,10 @@ def qdump__std__complex(d, value):
def qdump__std__deque(d, value):
if d.isQnxTarget():
qdump__std__deque__QNX(d, value)
return
innerType = d.templateArgument(value.type, 0)
innerSize = innerType.sizeof
bufsize = 1
......@@ -122,11 +126,47 @@ def qdump__std__deque(d, value):
plast = pfirst + bufsize
pcur = pfirst
def qdump__std__deque__QNX(d, value):
innerType = d.templateArgument(value.type, 0)
innerSize = innerType.sizeof
if innerSize <= 1:
bufsize = 16
elif innerSize <= 2:
bufsize = 8
elif innerSize <= 4:
bufsize = 4
elif innerSize <= 8:
bufsize = 2
else:
bufsize = 1
myoff = value['_Myoff']
mysize = value['_Mysize']
mapsize = value['_Mapsize']
d.check(0 <= mapsize and mapsize <= 1000 * 1000 * 1000)
d.putItemCount(mysize)
d.putNumChild(mysize)
if d.isExpanded():
with Children(d, mysize, maxNumChild=2000, childType=innerType):
map = value['_Map']
for i in d.childRange():
block = myoff / bufsize
offset = myoff - (block * bufsize)
if mapsize <= block:
block -= mapsize
d.putSubItem(i, map[block][offset])
myoff += 1;
def qdump__std____debug__deque(d, value):
qdump__std__deque(d, value)
def qdump__std__list(d, value):
if d.isQnxTarget():
qdump__std__list__QNX(d, value)
return
head = d.dereferenceValue(value)
impl = value["_M_impl"]
node = impl["_M_node"]
......@@ -148,6 +188,21 @@ def qdump__std__list(d, value):
d.putSubItem(i, (p + 1).cast(innerPointer).dereference())
p = p["_M_next"]
def qdump__std__list__QNX(d, value):
node = value["_Myhead"]
size = value["_Mysize"]
d.putItemCount(size, 1000)
d.putNumChild(size)
if d.isExpanded():
p = node["_Next"]
innerType = d.templateArgument(value.type, 0)
with Children(d, size, maxNumChild=1000, childType=innerType):
for i in d.childRange():
d.putSubItem(i, p['_Myval'])
p = p["_Next"]
def qdump__std____debug__list(d, value):
qdump__std__list(d, value)
......@@ -155,6 +210,10 @@ def qform__std__map():
return mapForms()
def qdump__std__map(d, value):
if d.isQnxTarget():
qdump__std__map__QNX(d, value)
return
impl = value["_M_t"]["_M_impl"]
size = int(impl["_M_node_count"])
d.check(0 <= size and size <= 100*1000*1000)
......@@ -210,6 +269,63 @@ def qdump__std__map(d, value):
while not d.isNull(node["_M_left"]):
node = node["_M_left"]
def qdump__std__map__QNX(d, value):
size = value['_Mysize']
d.check(0 <= size and size <= 100*1000*1000)
d.putItemCount(size)
d.putNumChild(size)
if d.isExpanded():
keyType = d.templateArgument(value.type, 0)
valueType = d.templateArgument(value.type, 1)
try:
# Does not work on gcc 4.4, the allocator type (fourth template
# argument) seems not to be available.
pairType = d.templateArgument(d.templateArgument(value.type, 3), 0)
pairPointer = pairType.pointer()
except:
# So use this as workaround:
pairType = d.templateArgument(impl.type, 1)
pairPointer = pairType.pointer()
isCompact = d.isMapCompact(keyType, valueType)
innerType = pairType
if isCompact:
innerType = valueType
head = value['_Myhead']
node = head['_Left']
nodeType = head.type
childType = innerType
if size == 0:
childType = pairType
childNumChild = 2
if isCompact:
childNumChild = None
with Children(d, size, maxNumChild=1000,
childType=childType, childNumChild=childNumChild):
for i in d.childRange():
with SubItem(d, i):
pair = node.cast(nodeType).dereference()['_Myval']
if isCompact:
d.putMapName(pair["first"])
d.putItem(pair["second"])
else:
d.putEmptyValue()
if d.isExpanded():
with Children(d, 2):
d.putSubItem("first", pair["first"])
d.putSubItem("second", pair["second"])
if not node['_Right']['_Isnil']:
node = node['_Right']
while not node['_Left']['_Isnil']:
node = node['_Left']
else:
parent = node['_Parent']
while node == parent['_Right']['_Isnil']:
node = parent
parent = parent['_Parent']
if node['_Right'] != parent:
node = parent
def qdump__std____debug__map(d, value):
qdump__std__map(d, value)
......@@ -271,6 +387,10 @@ def qdump__std____cxx1998__set(d, value):
qdump__std__set(d, value)
def qdump__std__set(d, value):
if d.isQnxTarget():
qdump__std__set__QNX(d, value)
return
impl = value["_M_t"]["_M_impl"]
size = int(impl["_M_node_count"])
d.check(0 <= size and size <= 100*1000*1000)
......@@ -294,6 +414,30 @@ def qdump__std__set(d, value):
while not d.isNull(node["_M_left"]):
node = node["_M_left"]
def qdump__std__set__QNX(d, value):
size = value['_Mysize']
d.check(0 <= size and size <= 100*1000*1000)
d.putItemCount(size)
d.putNumChild(size)
if d.isExpanded():
valueType = d.templateArgument(value.type, 0)
head = value['_Myhead']
node = head['_Left']
nodeType = head.type
with Children(d, size, maxNumChild=1000, childType=valueType):
for i in d.childRange():
d.putSubItem(i, node.cast(nodeType).dereference()['_Myval'])
if not node['_Right']['_Isnil']:
node = node['_Right']
while not node['_Left']['_Isnil']:
node = node['_Left']
else:
parent = node['_Parent']
while node == parent['_Right']['_Isnil']:
node = parent
parent = parent['_Parent']
if node['_Right'] != parent:
node = parent
def qdump__std__stack(d, value):
qdump__std__deque(d, value["c"])
......@@ -308,6 +452,10 @@ def qdump__std__string(d, value):
qdump__std__stringHelper1(d, value, 1)
def qdump__std__stringHelper1(d, value, charSize):
if d.isQnxTarget():
qdump__std__stringHelper1__QNX(d, value, charSize)
return
data = value["_M_dataplus"]["_M_p"]
# We can't lookup the std::string::_Rep type without crashing LLDB,
# so hard-code assumption on member position
......@@ -320,6 +468,20 @@ def qdump__std__stringHelper1(d, value, charSize):
d.check(0 <= size and size <= alloc and alloc <= 100*1000*1000)
qdump_stringHelper(d, sizePtr, size * charSize, charSize)
def qdump__std__stringHelper1__QNX(d, value, charSize):
size = value['_Mysize']
alloc = value['_Myres']
_BUF_SIZE = 16 / charSize
if _BUF_SIZE <= alloc: #(_BUF_SIZE <= _Myres ? _Bx._Ptr : _Bx._Buf);
data = value['_Bx']['_Ptr']
else:
data = value['_Bx']['_Buf']
sizePtr = data.cast(d.charType().pointer())
refcount = int(sizePtr[-1])
d.check(refcount >= -1) # Can be -1 accoring to docs.
d.check(0 <= size and size <= alloc and alloc <= 100*1000*1000)
qdump_stringHelper(d, sizePtr, size * charSize, charSize)
def qdump_stringHelper(d, data, size, charSize):
cutoff = min(size, d.stringCutOff)
mem = d.readMemory(data, cutoff)
......@@ -545,6 +707,10 @@ def qedit__std__vector(expr, value):
gdb.execute(cmd)
def qdump__std__vector(d, value):
if d.isQnxTarget():
qdump__std__vector__QNX(d, value)
return
impl = value["_M_impl"]
type = d.templateArgument(value.type, 0)
alloc = impl["_M_end_of_storage"]
......@@ -580,6 +746,40 @@ def qdump__std__vector(d, value):
else:
d.putArrayData(type, start, size)
def qdump__std__vector__QNX(d, value):
type = d.templateArgument(value.type, 0)
isBool = str(type) == 'bool'
if isBool:
impl = value['_Myvec']
start = impl['_Myfirst']
last = impl['_Mylast']
end = impl['_Myend']
size = value['_Mysize']
storagesize = start.dereference().type.sizeof * 8
else:
start = value['_Myfirst']
last = value['_Mylast']
end = value['_Myend']
size = int (last - start)
alloc = int (end - start)
d.check(0 <= size and size <= 1000 * 1000 * 1000)
d.check(last <= end)
d.checkPointer(start)
d.checkPointer(last)
d.checkPointer(end)
d.putItemCount(size)
d.putNumChild(size)
if d.isExpanded():
if isBool:
with Children(d, size, maxNumChild=10000, childType=type):
for i in d.childRange():
q = start + int(i / storagesize)
d.putBoolItem(str(i), (q.dereference() >> (i % storagesize)) & 1)
else:
d.putArrayData(type, start, size)
def qdump__std____1__vector(d, value):
innerType = d.templateArgument(value.type, 0)
if d.isLldb and d.childAt(value, 0).type == innerType:
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment