Skip to content

Instantly share code, notes, and snippets.

@parsa
Forked from ytomino/drake-gdb.py
Created March 4, 2018 21:26
Show Gist options
  • Save parsa/48cfd7352b01a6da99f15db78d81cef2 to your computer and use it in GitHub Desktop.
Save parsa/48cfd7352b01a6da99f15db78d81cef2 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
length_limit = 1024
class UnboundedStringPrinter:
"Print a Unbounded_String"
def __init__(self, val):
global length_limit
self.val = val
# Character_Type
typename = get_typename(self.val)
char_typename = typename[0 : len(typename) - 16] + "character_type"
char_t = gdb.lookup_type(char_typename)
# make (byte)array or unicode
length = int(self.val["length"])
items = self.val["data"].dereference()["items"] # fat pointer
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
if char_t.sizeof == 1:
bin = bytearray(read_length)
for i in range(read_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:
in_python_string = True
contents = []
for i in range(read_length):
code = int(p.dereference())
contents.append(code)
p += 1
# image
double_quote = ord("\"")
s = "+\""
for c in contents:
if type(contents) == bytearray:
code = c
valid = code < 0x80
else:
code = ord(c) if type(contents) == unicode else c
valid = code <= 0xFFFF
if valid and is_graphic(code) and code != double_quote:
s += unichr(code)
else:
s += gnat_substitute(code, char_t)
s += "\""
if read_length < length: s += " & ..."
self.image = s
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 and t.endswith("__unbounded_string"):
return UnboundedStringPrinter(val)
super(Printer, self).__call__(val)
pp = Printer("drake")
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