open62541/tools/gdb-prettyprint.py
Julius Pfrommer 7fc181348f
Merge pull request #5027 from open62541/1.3
Merge 1.3 to master
2022-03-20 13:19:34 +01:00

182 lines
6.0 KiB
Python

#!/usr/bin/env python3
# Load into gdb with 'source <path-to>/tools/gdb-prettyprint.py'
# Make sure to have 'set print pretty on' to get nice structure printouts
import base64
import gdb
def findType(name):
tt = None
try:
tt = gdb.lookup_type("UA_" + name)
except Exception:
try:
tt = gdb.lookup_type(name)
except Exception:
pass
return tt
class String:
def __init__(self, val):
self.val = val
def to_string(self):
data = self.val['data']
if int(data) == 0:
return "UA_STRING_NULL"
length = int(self.val['length'])
inferior = gdb.selected_inferior()
return "\"%s\"" % inferior.read_memory(data, length).tobytes().decode(errors='replace')
class ByteString:
def __init__(self, val):
self.val = val
@staticmethod
def print(s):
length = int(s['length'])
data = s['data']
if int(data) == 0:
return "UA_BYTESTRING_NULL"
inferior = gdb.selected_inferior()
encoded = base64.b64encode(inferior.read_memory(data, length).tobytes())
return "\"%s\"" % encoded.decode(errors='replace')
def to_string(self):
data = self.val['data']
if int(data) == 0:
return "UA_BYTESTRING_NULL"
return "UA_ByteString(%s)" % ByteString.print(self.val)
class LocalizedText:
def __init__(self, val):
self.val = val
def to_string(self):
return "UA_LocalizedText(%s, %s)" % (self.val['locale'], self.val['text'])
class QualifiedName:
def __init__(self, val):
self.val = val
def to_string(self):
return "UA_QualifiedName(%i, %s)" % (self.val['namespaceIndex'], self.val['name'])
class Guid:
def __init__(self, val):
self.val = val
@staticmethod
def print(g):
data = (g['data1'], g['data2'], g['data3'], g['data4'][0],
g['data4'][1], g['data4'][2], g['data4'][3], g['data4'][4],
g['data4'][5], g['data4'][6], g['data4'][7])
return "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x" % data
def to_string(self):
return "UA_Guid(%s)" % Guid.print(self.val)
class NodeId:
def __init__(self, val):
self.val = val
@staticmethod
def print(val):
s = ""
ns = int(val['namespaceIndex'])
idType = int(val['identifierType'])
if ns > 0:
s += "ns=%i;" % ns
if idType < 3:
s += "i=%i" % val['identifier']['numeric']
elif idType == 3:
s += "s=%s" % val['identifier']['string']
elif idType == 4:
s += "g=%s" % Guid.print(val['identifier']['guid'])
elif idType == 5:
s += "b=%s" % ByteString.print(val['identifier']['byteString'])
else:
raise gdb.GdbError("Invalid NodeId Identifier Type")
return s
def to_string(self):
return "UA_NodeId(%s)" % NodeId.print(self.val)
class ExpandedNodeId:
def __init__(self, val):
self.val = val
def to_string(self):
s = ""
if self.val['serverIndex'] > 0:
s += "svr=%i;" % self.val['serverIndex']
if self.val['namespaceUri']['data'] > 0:
s += "nsu=%s;" % self.val['namespaceUri']
s += NodeId.print(self.val['nodeId'])
return "UA_ExpandedNodeId(%s)" % s
class ExtensionObject:
def __init__(self, val):
self.val = val
def to_string(self):
encoding = self.val['encoding']
content = self.val['content']
if encoding == 0:
return "UA_ExtensionObject()"
elif encoding == 1 or encoding == 2:
encoded = content['encoded']
return "UA_ExtensionObject(%s, %s)" % (encoded['typeId'], encoded['body'])
decoded = content['decoded']
if int(decoded['type']) == 0:
return "UA_ExtensionObject()"
datatype = decoded['type'].dereference()
typeName = datatype['typeName'].string()
tt = findType(typeName)
if not tt:
return "UA_ExtensionObject<%s>((void*) %s)" % (typeName, decoded['data'])
value = decoded['data'].cast(tt.pointer()).dereference()
return "UA_ExtensionObject<%s>(%s)" % (tt, value)
class Variant:
def __init__(self, val):
self.val = val
def to_string(self):
if int(self.val['type']) == 0:
return "UA_Variant()"
datatype = self.val['type'].dereference()
tt = findType(datatype['typeName'].string())
if not tt:
return "UA_Variant()"
data_ptr = int(self.val['data'])
array_length = int(self.val['arrayLength'])
content = None
if array_length == 0 and data_ptr > 1:
content = self.val['data'].cast(tt.pointer()).dereference()
else:
content = self.val['data'].cast(tt.array(array_length - 1).pointer()).dereference()
dims_length = int(self.val['arrayDimensionsSize'])
if dims_length == 0:
return "UA_Variant<%s>(%s)" % (tt, content)
dims_type = findType("UInt32").array(dims_length - 1).pointer()
dims = self.val['arrayDimensions'].cast(dims_type).dereference()
return "UA_Variant<%s[%i]>(%s, arrayDimensions = %s)" % (tt, array_length, content, dims)
def build_open62541_printer():
pp = gdb.printing.RegexpCollectionPrettyPrinter("open62541")
pp.add_printer('UA_String', '^UA_String$', String)
pp.add_printer('UA_ByteString', '^UA_ByteString$', ByteString)
pp.add_printer('UA_LocalizedText', '^UA_LocalizedText$', LocalizedText)
pp.add_printer('UA_QualifiedName', '^UA_QualifiedName$', QualifiedName)
pp.add_printer('UA_Guid', '^UA_Guid$', Guid)
pp.add_printer('UA_NodeId', '^UA_NodeId$', NodeId)
pp.add_printer('UA_ExpandedNodeId', '^UA_ExpandedNodeId$', ExpandedNodeId)
pp.add_printer('UA_ExtensionObject', '^UA_ExtensionObject$', ExtensionObject)
pp.add_printer('UA_Variant', '^UA_Variant$', Variant)
return pp
gdb.printing.register_pretty_printer(gdb.current_objfile(),
build_open62541_printer())