2018-03-28 14:55:54 +11:00
|
|
|
import re
|
|
|
|
import gdb
|
2019-01-18 19:45:55 +11:00
|
|
|
import sys
|
|
|
|
import struct
|
|
|
|
|
2018-03-28 14:55:54 +11:00
|
|
|
|
|
|
|
class CoordPrinter(object):
|
2019-01-18 19:45:31 +11:00
|
|
|
def __init__(self, val):
|
2018-03-28 14:55:54 +11:00
|
|
|
self.val = val
|
|
|
|
|
|
|
|
def to_string(self):
|
2019-01-18 19:45:31 +11:00
|
|
|
return self.val
|
2018-03-28 14:55:54 +11:00
|
|
|
|
|
|
|
def display_hint(self):
|
|
|
|
return 'array'
|
|
|
|
|
|
|
|
class _iterator(object):
|
|
|
|
def __init__(self, data):
|
|
|
|
self.data = data
|
|
|
|
|
|
|
|
def __iter__(self):
|
|
|
|
indices = self.data.type.range()
|
|
|
|
for i in range(indices[0], indices[1] + 1):
|
|
|
|
res = (str(i), self.data[i])
|
|
|
|
yield res
|
|
|
|
raise StopIteration()
|
|
|
|
|
|
|
|
|
|
|
|
def children(self):
|
|
|
|
return self._iterator(self.val['data'])
|
|
|
|
|
|
|
|
|
2018-08-03 16:49:47 +10:00
|
|
|
class ViewPrinter(object):
|
2019-01-18 19:45:31 +11:00
|
|
|
def __init__(self, val):
|
2018-08-03 16:49:47 +10:00
|
|
|
self.val = val
|
|
|
|
|
|
|
|
def to_string(self):
|
2019-01-18 19:45:31 +11:00
|
|
|
return self.val
|
2018-08-03 16:49:47 +10:00
|
|
|
|
|
|
|
def display_hint(self):
|
|
|
|
return 'array'
|
|
|
|
|
|
|
|
class _iterator(object):
|
|
|
|
def __init__(self, first, last):
|
|
|
|
self.cursor = first
|
|
|
|
self.last = last
|
|
|
|
self.index = 0
|
|
|
|
|
|
|
|
def __iter__(self):
|
|
|
|
return self
|
|
|
|
|
|
|
|
def __next__(self):
|
|
|
|
if self.cursor == self.last:
|
|
|
|
raise StopIteration
|
|
|
|
|
|
|
|
val = self.cursor.dereference()
|
2018-12-19 17:11:46 +11:00
|
|
|
res = ("[%d]" % self.index, val)
|
|
|
|
|
2018-08-03 16:49:47 +10:00
|
|
|
self.cursor = self.cursor + 1
|
|
|
|
self.index = self.index + 1
|
|
|
|
|
2018-12-19 17:11:46 +11:00
|
|
|
return res
|
2018-08-03 16:49:47 +10:00
|
|
|
|
|
|
|
def children(self):
|
|
|
|
return self._iterator(
|
|
|
|
self.val["m_begin"],
|
|
|
|
self.val["m_end"]
|
|
|
|
)
|
2018-03-28 14:55:54 +11:00
|
|
|
|
2019-01-18 19:45:55 +11:00
|
|
|
class EndianValuePrinter(object):
|
|
|
|
val: gdb.Type
|
|
|
|
|
|
|
|
def __init__(self, val: gdb.Value):
|
|
|
|
self.val = val
|
|
|
|
# The type should be something like:
|
|
|
|
# "cruft::endian::value<cruft::endian::BIG,u64>"
|
|
|
|
order_name = str(val.type.template_argument(0))
|
|
|
|
|
|
|
|
# Fuck knows how to use the GDB API. It's easier to just search for a
|
|
|
|
# differentiator that's unlikely to be present in anything else.
|
|
|
|
if '::BIG' in order_name:
|
|
|
|
self.order = '>'
|
|
|
|
elif '::LITTLE' in order_name:
|
|
|
|
self.order = '<'
|
|
|
|
else:
|
|
|
|
raise RuntimeError("Unknown endianness")
|
|
|
|
|
|
|
|
# Find a format specifier for the size of the underlying value
|
|
|
|
self.size = {
|
|
|
|
1: 'B',
|
|
|
|
2: 'H',
|
|
|
|
4: 'I',
|
|
|
|
8: 'Q',
|
|
|
|
}[self.val.type.sizeof]
|
|
|
|
|
|
|
|
def to_string (self):
|
|
|
|
# Construct format specifiers for converting to bytes, then from
|
|
|
|
# bytes, so that we can perform the byte reversal.
|
|
|
|
to_bytes = f"{self.order}{self.size}"
|
|
|
|
from_bytes = f"={self.size}"
|
|
|
|
|
|
|
|
raw = int(self.val["raw"])
|
|
|
|
native = struct.unpack(from_bytes, struct.pack(to_bytes, raw))[0]
|
|
|
|
|
|
|
|
# Print the value and some annotations so that the user isn't misled
|
|
|
|
# about what value they're looking at.
|
|
|
|
return f"{native} (0x{native:x}, from 0x{raw:x})"
|
|
|
|
|
|
|
|
|
2018-03-28 14:55:54 +11:00
|
|
|
def build_cruft_dict():
|
2019-01-18 19:45:31 +11:00
|
|
|
pretty_printers_dict[re.compile('^cruft::point.*$') ] = lambda val: CoordPrinter(val)
|
|
|
|
pretty_printers_dict[re.compile('^cruft::vector.*$')] = lambda val: CoordPrinter(val)
|
|
|
|
pretty_printers_dict[re.compile('^cruft::extent.*$')] = lambda val: CoordPrinter(val)
|
|
|
|
pretty_printers_dict[re.compile('^cruft::colour.*$')] = lambda val: CoordPrinter(val)
|
2018-03-28 14:55:54 +11:00
|
|
|
|
2019-01-18 19:45:55 +11:00
|
|
|
pretty_printers_dict[re.compile('^cruft::view')] = lambda val: ViewPrinter(val)
|
|
|
|
|
|
|
|
pretty_printers_dict[re.compile('^cruft::endian::value')] = lambda val: EndianValuePrinter(val)
|
2018-08-03 16:49:47 +10:00
|
|
|
|
2018-03-28 14:55:54 +11:00
|
|
|
|
|
|
|
def lookup(val):
|
|
|
|
type = val.type
|
|
|
|
|
|
|
|
if type.code == gdb.TYPE_CODE_REF:
|
|
|
|
type = type.target()
|
|
|
|
|
|
|
|
type = type.unqualified().strip_typedefs()
|
|
|
|
|
|
|
|
typename = type.tag
|
|
|
|
if typename == None:
|
|
|
|
return None
|
|
|
|
|
|
|
|
for function in pretty_printers_dict:
|
|
|
|
if function.search(typename):
|
2019-01-18 19:45:31 +11:00
|
|
|
return pretty_printers_dict[function](val)
|
2018-03-28 14:55:54 +11:00
|
|
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
|
|
def register_cruft_printers():
|
|
|
|
gdb.pretty_printers.append(lookup)
|
|
|
|
|
|
|
|
|
|
|
|
pretty_printers_dict = {}
|
2019-01-18 19:45:31 +11:00
|
|
|
build_cruft_dict()
|