The Sol Programming Language!
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

158 lines
5.4 KiB

# 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 '<Unknown object %r type %s>'%(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 '<Function %s>'%(obj['fname'],)
def str_SOL_CFUNCTION(self, obj):
return '<CFunction %r>'%(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!')