Skip to content

Instantly share code, notes, and snippets.

@ytomino
Last active March 4, 2018 21:26
Show Gist options
  • Save ytomino/17d58e254eec2de5f9419c05509f3960 to your computer and use it in GitHub Desktop.
Save ytomino/17d58e254eec2de5f9419c05509f3960 to your computer and use it in GitHub Desktop.
My first gdb pretty-printer
# from pprint import pprint
import codecs
import unicodedata
def get_typename(val):
t = gdb.types.get_basic_type(val.type).tag
if not t: t = val.type.name
return t
def is_graphic(c):
category = unicodedata.category(unichr(c))
# print "{{%s}}" % category
# excluding Cc, Cf, Co, Zl, Zp, not Cs(Surrogate)
return (category != "Cc" and category != "Cf" and category != "Co" and
category != "Zl" and category != "Zp")
def gnat_substitute(c, char_t):
if char_t.sizeof == 1:
return "[\"%.2x\"]" % c
elif char_t.sizeof == 2:
return "[\"%.4x\"]" % c
else:
return "[\"%.8x\"]" % c
def read_string(p, length, char_t):
if char_t.sizeof == 1:
bin = bytearray(length)
for i in range(length):
code = int(p.dereference())
if code < 0: code += 256 # signed?
bin[i] = code
p += 1
try:
contents = bin.decode("utf-8")
except:
contents = bin
else:
contents = []
for i in range(length):
code = int(p.dereference())
contents.append(code)
p += 1
return contents
def wrapped_string_image(contents, length_is_limited):
double_quote = ord("\"")
s = "+\""
for c in contents:
code = ord(c) if type(contents) == unicode else c
if type(contents) == bytearray:
valid = code < 0x80 # decoding is failed
else:
valid = code <= 0xFFFF
if valid and code != double_quote and is_graphic(code):
s += unichr(code)
else:
s += gnat_substitute(code, char_t)
s += "\""
if length_is_limited: s += " & ..."
return s
length_limit = 1024
class BoundedStringPrinter:
"Print a Bounded_String"
def __init__(self, val):
global length_limit
self.val = val
# components
length = int(self.val["length"])
element = self.val["element___XVL"]
# Character_Type
char_t = element.type.target()
# contents
char_t_ptr = char_t.pointer()
p = element.address.reinterpret_cast(char_t_ptr)
read_length = length if length <= length_limit else length_limit
contents = read_string(p, read_length, char_t)
self.image = wrapped_string_image(contents, read_length < length)
def to_string(self):
return self.image
class UnboundedStringPrinter:
"Print a Unbounded_String"
def __init__(self, val):
global length_limit
self.val = val
# components
length = int(self.val["length"])
items = self.val["data"].dereference()["items"]
# Character_Type
typename = get_typename(self.val)
char_typename = typename[0 : len(typename) - 16] + "character_type"
char_t = gdb.lookup_type(char_typename)
# contents
char_t_ptr_ptr = char_t.pointer().pointer()
p = items.address.reinterpret_cast(char_t_ptr_ptr).dereference()
read_length = length if length <= length_limit else length_limit
contents = read_string(p, read_length, char_t)
self.image = wrapped_string_image(contents, read_length < length)
def to_string(self):
return self.image
class Printer(gdb.printing.RegexpCollectionPrettyPrinter):
def __call__(self, val):
t = get_typename(val)
if t:
# print "{{" + t + "}}"
if t.find("__Tbounded_stringB__") >= 0:
return BoundedStringPrinter(val)
elif t.endswith("__unbounded_string"):
return UnboundedStringPrinter(val)
super(Printer, self).__call__(val)
pp = Printer("drake")
pp.add_printer("Bounded_String", '__Tbounded_stringB__', BoundedStringPrinter)
pp.add_printer("Unbounded_String", '__unbounded_string$',
UnboundedStringPrinter)
gdb.printing.register_pretty_printer(gdb.current_objfile(), pp)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment