-
-
Save parsa/48cfd7352b01a6da99f15db78d81cef2 to your computer and use it in GitHub Desktop.
My first gdb pretty-printer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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