# GDB Sol extensions import gdb.printing import sys import traceback class _CatchExceptions(object): def __init__(self): self.excs = [] def print_eidx(self, idx): traceback.print_exception(*self.excs[idx]) def __enter__(self): pass def __exit__(self, t, v, tb): if t is not None: self.excs.append((t, v, tb)) guard = _CatchExceptions() class DslArray(gdb.Function): '''Returns the (DSL_DATATYPE[]) array base of a dsl_array or dsl_seq (if it wraps an array), else NULL''' def __init__(self): super(DslArray, self).__init__('dsl_array') def invoke(self, val): with guard: stype = str(val.type) tp = gdb.lookup_type('sol_object_t').pointer() if str(val.type).startswith('dsl_seq'): if str(val['type']) != 'DSL_SEQ_ARRAY': return gdb.Value(0).cast(tp.pointer()) val = val['array'] if str(val.type).startswith('dsl_array'): return val['data'].dereference().cast(tp.array(val['len'])) return gdb.Value(0).cast(tp.pointer()) DslArray.instance = DslArray() class DslLen(gdb.Function): '''Returns the length of a DSL sequence''' def __init__(self): super(DslLen, self).__init__('dsl_array') def invoke(self, val): with guard: stype = str(val.type) if stype.startswith('dsl_seq'): return int(gdb.lookup_symbol('dsl_seq_len')[0].value()(val)) if stype.startswith('dsl_array'): return int(gdb.lookup_symbol('dsl_array_len')[0].value()(val)) if stype.startswith('dsl_list'): return int(gdb.lookup_symbol('dsl_list_len')[0].value()(val)) return -1 DslLen.instance = DslLen() class SolObj(gdb.Function): '''Casts the argument to a sol_object_t *''' def __init__(self): super(SolObj, self).__init__('sol_obj') def invoke(self, val): with guard: return val.cast(gdb.lookup_type('sol_object_t').pointer()) SolObj.instance = SolObj() class SolObjectPrettyPrinter(object): STYPE_TO_DISPHINT = { 'SOL_SINGLET': 'string', 'SOL_INTEGER': 'number', 'SOL_FLOAT': 'number', 'SOL_STRING': 'string', 'SOL_LIST': 'array', 'SOL_MAP': 'map', 'SOL_MCELL': 'map', 'SOL_FUNCTION': 'function', 'SOL_CFUNCTION': 'function', 'SOL_STMT': 'syntax', 'SOL_EXPR': 'syntax', } def __init__(self, obj): self.obj = obj def display_hint(self): return self.STYPE_TO_DISPHINT.get(str(self.obj['type']), 'string') def to_string(self): with guard: return getattr(self, 'str_'+str(self.obj['type']), self.str_default)(self.obj) def str_default(self, obj): return ''%(obj, str(obj['type'])) def str_SOL_SINGLET(self, obj): return obj['str'] def str_SOL_INTEGER(self, obj): return str(obj['ival']) def str_SOL_FLOAT(self, obj): return str(obj['fval']) def str_SOL_STRING(self, obj): return obj['str'] def str_SOL_LIST(self, obj): return '[List len=%d]'%(DslLen.instance.invoke(obj['seq']),) def str_SOL_MAP(self, obj): return '{Map len=%d}'%(DslLen.instance.invoke(obj['seq']),) def str_SOL_MCELL(self, obj): return '<{[%s] = %s}>'%(SolObjectPrettyPrinter(obj['key']).to_string(), SolObjectPrettyPrinter(obj['val']).to_string()) def str_SOL_FUNCTION(self, obj): return ''%(obj['fname'],) def str_SOL_CFUNCTION(self, obj): return ''%(obj['cfunc'],) def str_SOL_STMT(self, obj): return str(obj['node'].cast(gdb.lookup_type('stmt_node').pointer())['type']) def str_SOL_EXPR(self, obj): return str(obj['node'].cast(gdb.lookup_type('expr_node').pointer())['type']) def children(self): with guard: stype = str(self.obj['type']) if stype in ('SOL_LIST', 'SOL_MAP'): if str(self.obj['seq']['type']) == 'DSL_SEQ_ARRAY': tp = gdb.lookup_type('sol_object_t').pointer() lseq = DslLen.instance.invoke(self.obj['seq']) arr = self.obj['seq']['array']['data'].dereference().cast(tp.array(lseq)) if stype == 'SOL_LIST': return [(str(i), arr[i]) for i in range(lseq)] else: return sum([[(str(i)+'k', arr[i]['key']), (str(i)+'v', arr[i]['val'])] for i in range(lseq)], []) if stype == 'SOL_FUNCTION': return [('stmt', self.obj['func'].cast(gdb.lookup_type('stmt_node').pointer))] return [] @classmethod def check_printable(cls, obj): with guard: stype = str(obj.type) if stype.startswith('sol_object_t') or stype.startswith('struct sol_tag_object_t'): return cls(obj) return None # pp = gdb.printing.RegexpCollectionPrettyPrinter('Sol') # pp.add_printer('sol_object_t', '^sol_object_t.*$', SolObjectPrettyPrinter) # pp.add_printer('sol_tag_object_t', '^struct sol_tag_object_t.*$', SolObjectPrettyPrinter) # gdb.printing.register_pretty_printer(gdb.current_objfile(), pp) gdb.pretty_printers.append(SolObjectPrettyPrinter.check_printable) print('Sol extensions loaded!')