Module pandare.extras.dwarfdump

Expand source code
#!/usr/bin/env python3

import sys
import json

# dwarfdump -dil $PROG

def parse_die(ent):
    result = {}
    for e in ent.split('> ')[1:]:
        while e.endswith('>'):
            e = e[:-1]
        assert (e.startswith('DW_AT_'))
        dat = e.split('<')
        attr = dat[0].strip()
        for v in dat[1:]:
            v = v.strip()
            if v:
                result[attr] = v
    return result

def parse_section(indat):
    result = {'.debug_line': [], '.debug_info': []}
    data = indat.decode().strip().split('\n')
    for l in data:
        l = l.strip()
        if l.startswith("0x"):
            result['.debug_line'].append(l)
            # Signal End of Text
            if 'ET' in l.split():
                result['.debug_line'].append(None)
        elif l.startswith("<") and not l.startswith("<pc>"):
            result['.debug_info'].append(l)
    return result

def reprocess_ops(ops):
    out = []
    for op in ops:
        if op.startswith('DW_'):
            out.append(op)
        elif type(op) == str:
            if op.lstrip('-+').startswith("0x"):
                out.append(int(op, 16))
            else:
                out.append(int(op))
        else:
            out.append(op)
    return out


class TypeDB(object):
    def __init__(self):
        self.data = {}

    def insert(self, cu, off, ty):
        if cu not in self.data:
            self.data[cu] = {}
        if off not in self.data[cu]:
            self.data[cu][off] = ty

    def jsondump(self):
        jout = {}
        for cu in self.data:
            jout[cu] = {}
            for off in self.data[cu]:
                jout[cu][off] = self.data[cu][off].jsondump()
        #return json.dumps(jout)
        return jout

class LineDB(object):
    def __init__(self):
        self.data = {}

    def _find_best_fit(self, srcfn, lno, addr):
        r = [-1, -1]
        for i in range(len(self.data[srcfn])):
            if self.data[srcfn][i].lno == lno:
                if r[1] < self.data[srcfn][i].highpc and addr > self.data[srcfn][i].highpc:
                    r = [i, self.data[srcfn][i].highpc]
        return r[0]

    def insert(self, srcfn, lno, col, addr, func=None):
        if srcfn not in self.data:
            self.data[srcfn] = []

        if self.data[srcfn] and lno < self.data[srcfn][-1].lno:
            i = -1
        else:
            i = self._find_best_fit(srcfn, lno, addr)
        if i == -1:
            self.data[srcfn].append(LineRange(lno, col, addr, addr, func))
            self.data[srcfn].sort(key = lambda x: x.lno)

        prevlno = lno-1
        i = self._find_best_fit(srcfn, prevlno, addr)
        while prevlno > 0 and i == -1:
            prevlno -= 1
            i = self._find_best_fit(srcfn, prevlno, addr)
        if i != -1:
            self.data[srcfn][i].highpc = addr

    def update_function(self, base_addr, end_addr, finfo):
        srcinfo = None
        for srcfn in self.data:
            for i in range(len(self.data[srcfn])):
                if self.data[srcfn][i].lowpc == base_addr:
                    srcinfo = (srcfn, self.data[srcfn][i].lno)
                if self.data[srcfn][i].lowpc >= base_addr \
                        and self.data[srcfn][i].highpc < end_addr:
                    self.data[srcfn][i].func = finfo.scope.lowpc
        return srcinfo

    def jsondump(self):
        jout = {}
        for srcfn in self.data:
            key = srcfn
            while srcfn[0] in ['"', "'"]:
                srcfn = srcfn[1:]
            while srcfn[-1] in ['"', "'"]:
                srcfn = srcfn[:-1]
            jout[srcfn] = []
            for lr in self.data[key]:
                jout[srcfn].append(lr.jsondump())
        #return json.dumps(jout)
        return jout

class GlobVarDB(object):
    def __init__(self):
        self.data = {}

    def insert(self, cu, var):
        if cu not in self.data:
            self.data[cu] = set()
        self.data[cu].add(var)

    def jsondump(self):
        jout = {}
        for cu in self.data:
            jout[cu] = [f.jsondump() for f in self.data[cu]]
        #return json.dumps(jout)
        return jout

class FunctionDB(object):
    def __init__(self):
        self.data = {}

    def insert(self, cu, f):
        if cu not in self.data:
            self.data[cu] = set()
        self.data[cu].add(f)

    def jsondump(self):
        jout = {}
        for cu in self.data:
            jout[cu] = [f.jsondump() for f in self.data[cu]]
        #return json.dumps(jout)
        return jout


class VarInfo(object):
    def __init__(self, name, cu_off):
        self.name = name
        self.cu_offset = cu_off
        self.scope = None
        self.decl_lno = None
        self.decl_fn = None
        self.loc_op = []
        self.type = None

    def jsondump(self):
        return {'name': self.name, \
                'cu_offset': self.cu_offset, \
                'scope': self.scope.jsondump(), \
                'decl_lno': self.decl_lno, \
                'decl_fn': self.decl_fn, \
                'loc_op': self.loc_op, \
                'type': self.type}

class FuncInfo(object):
    def __init__(self, cu_off, name, scope, fb_op):
        self.cu_offset = cu_off
        self.name = name
        self.scope = scope
        self.framebase = fb_op
        self.fn = None
        self.lno = None
        self.varlist = []

    def jsondump(self):
        return {'name': self.name, \
                'cu_offset': self.cu_offset, \
                'scope': self.scope.jsondump(), \
                'framebase': self.framebase, \
                'fn': self.fn, \
                'lno': self.lno, \
                'varlist': [v.jsondump() for v in self.varlist]}

class TypeInfo(object):
    def __init__(self, name):
        self.name = name

    def jsondump(self):
        return {'name': self.name}

class StructType(TypeInfo):
    def __init__(self, name, cu_off, size):
        TypeInfo.__init__(self, name)
        self.size = size
        self.cu_off = cu_off
        self.children = {}  # <member_offset: (name, type_offset)>

    def jsondump(self):
        d = TypeInfo.jsondump(self)
        d.update({
                'tag': 'StructType',
                'size': self.size,
                'cu_off': self.cu_off,
                'children': self.children,
                })
        return d

class BaseType(TypeInfo):
    def __init__(self, name, size):
        TypeInfo.__init__(self, name)
        self.size = size

    def jsondump(self):
        d = TypeInfo.jsondump(self)
        d.update({
                'tag': 'BaseType',
                'size': self.size,
                })
        return d

class SugarType(TypeInfo):
    def __init__(self, name, cu_off):
        TypeInfo.__init__(self, name)
        self.cu_off = cu_off
        self.ref = None

    def jsondump(self):
        d = TypeInfo.jsondump(self)
        d.update({
                'tag': 'SugarType',
                'cu_off': self.cu_off,
                'ref': self.ref,
                })
        return d

class PointerType(SugarType):
    def __init__(self, name, cu_off, target):
        SugarType.__init__(self, name, cu_off)
        self.ref = target

    def jsondump(self):
        d = SugarType.jsondump(self)
        d.update({
                'tag': 'PointerType',
                })
        return d

class ArrayType(SugarType):
    def __init__(self, name, cu_off, elemty):
        SugarType.__init__(self, name, cu_off)
        self.ref = elemty
        self.range = []

    def jsondump(self):
        d = SugarType.jsondump(self)
        d.update({
                'tag': 'ArrayType',
                'range': self.range,
                })
        return d

class ArrayRangeType(SugarType):
    def __init__(self, name, cu_off, rtype, cnt):
        SugarType.__init__(self, name, cu_off)
        self.ref = rtype
        self.size = cnt

    def jsondump(self):
        d = SugarType.jsondump(self)
        d.update({
                'tag': 'ArrayRangeType',
                'size': self.size,
                })
        return d

class EnumType(TypeInfo):
    def __init__(self, name, size):
        TypeInfo.__init__(self, name)
        self.size = size

    def jsondump(self):
        d = TypeInfo.jsondump(self)
        d.update({
                'tag': 'EnumType',
                'size': self.size,
                })
        return d

class SubroutineType(TypeInfo):
    def __init__(self, name):
        TypeInfo.__init__(self, name)

    def jsondump(self):
        d = TypeInfo.jsondump(self)
        d.update({
                'tag': 'SubroutineType',
                })
        return d

class UnionType(TypeInfo):
    def __init__(self, name, cu_off, size):
        TypeInfo.__init__(self, name)
        self.size = size
        self.cu_off = cu_off
        self.children = {}  # <member_offset: (name, type_offset)>

    def jsondump(self):
        d = TypeInfo.jsondump(self)
        d.update({
                'tag': 'UnionType',
                'size': self.size,
                'cu_off': self.cu_off,
                'children': self.children,
                })
        return d

class Scope(object):
    def __init__(self, lopc, hipc):
        self.lowpc = lopc
        self.highpc = hipc

    def jsondump(self):
        return {'lowpc': self.lowpc, 'highpc': self.highpc}

class LineRange(object):
    def __init__(self, lno, col, lopc, hipc, func):
        self.lno = lno
        self.col = col
        self.lowpc = lopc
        self.highpc = hipc
        self.func = func

    def jsondump(self):
        return {
                'lno': self.lno,
                'col': self.col,
                'lowpc': self.lowpc,
                'highpc': self.highpc,
                'func': self.func,
                }

def parse_dwarfdump(indat, prefix=""):
    reloc_base = 0
    line_info = LineDB()
    globvar_info = GlobVarDB()
    func_info = FunctionDB()
    type_info = TypeDB()

    data = parse_section(indat)
    tag = ".debug_line"
    if tag in data:
        srcname = ""
        for line in data[tag]:
            if line == None:
                srcname = ""
                continue
            line = line.strip()
            if line.startswith("0x"):
                addrstr, rest = line.split('[')
                lnostr, info = rest.split(']')
                if "uri:" in info:
                    srcfn = info.split("uri:")[-1].strip()
                assert (srcfn)
                addr = int(addrstr.strip(), 16) + reloc_base
                lno = int(lnostr.strip().split(',')[0])
                col = int(lnostr.strip().split(',')[1])
                line_info.insert(srcfn, lno, col, addr)

    type_overlay = None
    cu_off = None
    lvl_stack = []
    scope_stack = []
    func_stack = []
    type_stack = []
    tag = ".debug_info"
    if tag in data:
        for line in data[tag]:
            line = line.strip()
            print(line)
            if not line:
                continue
            if not line.startswith('<'):
                continue

            die = line.split(' ')[0].strip()
            assert (die.startswith('<') and die.endswith('>'))
            lvl, idx, tname = die[1:-1].split('><')
            lvl = int(lvl)

            res = parse_die(line)
            if "DW_TAG_compile_unit" in line:
                assert ('DW_AT_low_pc' in res)
                assert ('DW_AT_high_pc' in res)
                base_addr = int(res['DW_AT_low_pc'], 16) + reloc_base
                end_addr = int(res['DW_AT_high_pc'], 16) + reloc_base
                scope_stack = [Scope(base_addr, end_addr)]
                lvl_stack = [(lvl, 'DW_TAG_compile_unit')]
                func_stack = []
                type_stack = []
                cu_off = int(idx.split('+')[0], 16)
                continue

            idx = int(idx, 16)

            #print(lvl, idx, tname)

            while lvl < lvl_stack[-1][0]:
                lvl_stack.pop()
                if lvl_stack[-1][1] == 'DW_TAG_lexical_block':
                    scope_stack.pop()
                if lvl_stack[-1][1] == 'DW_TAG_subprogram':
                    func_stack.pop()
                if lvl_stack[-1][1] == 'DW_TAG_structure_type':
                    type_stack.pop()
                if lvl_stack[-1][1] == 'DW_TAG_union_type':
                    type_stack.pop()
                if lvl_stack[-1][1] == 'DW_TAG_array_type':
                    type_stack.pop()

            if lvl != lvl_stack[-1][0] and lvl != (lvl_stack[-1][0]+1):
                continue

            if lvl_stack[-1][1] in ['SugarType', 'DW_TAG_pointer_type']:
                assert (lvl == lvl_stack[-1][0])
                lvl_stack.pop()
                assert (type_overlay)
                type_overlay[2].ref = idx
                type_info.insert(type_overlay[0], type_overlay[1], type_overlay[2])
                type_overlay = None

            if tname == "DW_TAG_lexical_block":
                assert ('DW_AT_low_pc' in res)
                assert ('DW_AT_high_pc' in res)
                base_addr = int(res['DW_AT_low_pc'], 16) + reloc_base
                end_addr = int(res['DW_AT_high_pc'], 16) + reloc_base
                scope_stack.append(Scope(base_addr, end_addr))
                lvl_stack.append((lvl, 'DW_TAG_lexical_block'))

            elif tname == "DW_TAG_variable":
                assert ('DW_AT_name' in res)
                name = res['DW_AT_name']
                v = VarInfo(name, cu_off)

                v.scope = scope_stack[-1]
                assert ('DW_AT_decl_line' in res)
                v.decl_lno = int(res['DW_AT_decl_line'], 16)
                assert ('DW_AT_decl_file' in res)
                v.decl_fn = res['DW_AT_decl_file']
                v.decl_fn = v.decl_fn[v.decl_fn.find(' ')+1:]
                if 'DW_AT_location' not in res:
                    continue
                for x in res['DW_AT_location'].split(':')[-1].strip().split('DW_OP_'):
                    x = x.strip()
                    if not x:
                        continue
                    v.loc_op.extend('DW_OP_{}'.format(x).split())
                v.loc_op = reprocess_ops(v.loc_op)
                assert ('DW_AT_type' in res)
                v.type = int(res['DW_AT_type'], 16)

                if len(func_stack) == 0:
                    globvar_info.insert(cu_off, v)
                else:
                    func_stack[-1].varlist.append(v)

            elif tname == "DW_TAG_formal_parameter":
                if 'DW_AT_name' not in res:
                    continue
                name = res['DW_AT_name']
                v = VarInfo(name, cu_off)

                v.scope = scope_stack[-1]
                assert ('DW_AT_decl_line' in res)
                v.decl_lno = int(res['DW_AT_decl_line'], 16)
                assert ('DW_AT_decl_file' in res)
                v.decl_fn = res['DW_AT_decl_file']
                v.decl_fn = v.decl_fn[v.decl_fn.find(' ')+1:]
                if 'DW_AT_location' not in res:
                    continue
                for x in res['DW_AT_location'].split(':')[-1].strip().split('DW_OP_'):
                    x = x.strip()
                    if not x:
                        continue
                    v.loc_op.extend('DW_OP_{}'.format(x).split())
                v.loc_op = reprocess_ops(v.loc_op)
                assert ('DW_AT_type' in res)
                v.type = int(res['DW_AT_type'], 16)

                assert (len(func_stack) > 0)
                func_stack[-1].varlist.append(v)

            elif tname == "DW_TAG_subprogram":
                assert ('DW_AT_name' in res)
                name = res['DW_AT_name']

                assert ('DW_AT_low_pc' in res)
                assert ('DW_AT_high_pc' in res)
                base_addr = int(res['DW_AT_low_pc'], 16) + reloc_base
                end_addr = int(res['DW_AT_high_pc'], 16) + reloc_base
                scope = Scope(base_addr, end_addr)
                scope_stack.append(scope)
                lvl_stack.append((lvl, 'DW_TAG_subprogram'))

                assert ('DW_AT_decl_file' in res)
                decl_fn = res['DW_AT_decl_file']
                decl_fn = decl_fn[v.decl_fn.find(' ')+1:]

                if 'DW_AT_frame_base' in res:
                    fb_op = [res['DW_AT_frame_base'].split(':')[-1].strip()]
                else:
                    fb_op = []
                fb_op = reprocess_ops(fb_op)

                f = FuncInfo(cu_off, name, scope, fb_op)

                f.fn, f.lno = line_info.update_function(base_addr, end_addr, f)

                func_stack.append(f)
                func_info.insert(cu_off, f)

            elif tname == "DW_TAG_structure_type":
                if 'DW_AT_byte_size' not in res:
                    continue
                sz = int(res['DW_AT_byte_size'], 16)
                name = res['DW_AT_name'] if 'DW_AT_name' in res else "void"
                t = StructType(name, cu_off, sz)

                type_info.insert(cu_off, idx, t)

                type_stack.append(t)
                lvl_stack.append((lvl, 'DW_TAG_structure_type'))

            elif tname == "DW_TAG_member":
                assert (lvl_stack[-1][1] in ['DW_TAG_structure_type', 'DW_TAG_union_type'])

                name = res['DW_AT_name'] if 'DW_AT_name' in res else "void"

                # Skip bit fields
                if 'DW_AT_bit_size' in res or 'DW_AT_bit_offset' in res:
                    continue

                assert ('DW_AT_type' in res)
                toff = int(res['DW_AT_type'], 16)

                assert ('DW_AT_data_member_location' in res)
                loc_op = ['DW_OP_{}'.format(x.strip()) for x in \
                        res['DW_AT_data_member_location'].split(':')[-1].strip().split('DW_OP_')[1:]]
                # Signal attribute form DW_FORM_data1/2/4/8
                assert (len(loc_op) == 1)
                assert (loc_op[0].split()[0] == 'DW_OP_plus_uconst')
                off = int(loc_op[0].split()[1])

                type_stack[-1].children[off] = (name, toff)

            elif tname == "DW_TAG_array_type":
                name = res['DW_AT_name'] if 'DW_AT_name' in res else "void"
                assert ('DW_AT_type' in res)
                elemoff = int(res['DW_AT_type'], 16)

                t = ArrayType(name, cu_off, elemoff)

                type_info.insert(cu_off, idx, t)

                lvl_stack.append((lvl, 'DW_TAG_array_type'))
                type_stack.append(t)

            elif tname == "DW_TAG_subrange_type":
                name = res['DW_AT_name'] if 'DW_AT_name' in res else "void"
                assert ('DW_AT_type' in res)
                toff = int(res['DW_AT_type'], 16)
                assert ('DW_AT_count' in res)
                cnt = int(res['DW_AT_count'], 16)
                # cnt = int(res['DW_AT_upper_bound'], 16)

                t = ArrayRangeType(name, cu_off, toff, cnt)

                type_info.insert(cu_off, idx, t)

                assert (lvl_stack[-1][1] == 'DW_TAG_array_type')
                assert ((lvl_stack[-1][0]+1) == lvl)

                type_stack[-1].range.append(idx)

            elif tname == "DW_TAG_subroutine_type":
                name = res['DW_AT_name'] if 'DW_AT_name' in res else "void"
                t = SubroutineType(name)

                type_info.insert(cu_off, idx, t)

            elif tname == "DW_TAG_base_type":
                name = res['DW_AT_name'] if 'DW_AT_name' in res else "void"
                assert ('DW_AT_byte_size' in res)
                sz = int(res['DW_AT_byte_size'], 16)
                t = BaseType(name, sz)

                type_info.insert(cu_off, idx, t)

            elif tname == "DW_TAG_pointer_type":
                name = res['DW_AT_name'] if 'DW_AT_name' in res else "void"

                if 'DW_AT_type' not in res:
                    lvl_stack.append((lvl, 'DW_TAG_pointer_type'))
                    type_overlay = (cu_off, idx, PointerType(name, cu_off, None))
                    continue
                target = int(res['DW_AT_type'], 16)

                t = PointerType(name, cu_off, target)

                type_info.insert(cu_off, idx, t)

            elif tname == "DW_TAG_enumeration_type":
                name = res['DW_AT_name'] if 'DW_AT_name' in res else "void"

                assert ('DW_AT_byte_size' in res)
                sz = int(res['DW_AT_byte_size'], 16)

                t = EnumType(name, sz)

                type_info.insert(cu_off, idx, t)

            elif tname in [
                    "DW_TAG_restrict_type",
                    "DW_TAG_const_type",
                    "DW_TAG_volatile_type",
                    "DW_TAG_typedef"
                    ]:
                name = res['DW_AT_name'] if 'DW_AT_name' in res else "void"
                t = SugarType(name, cu_off)

                if 'DW_AT_type' not in res:
                    lvl_stack.append((lvl, 'SugarType'))
                    type_overlay = (cu_off, idx, t)
                    continue
                t.ref = int(res['DW_AT_type'], 16)

                type_info.insert(cu_off, idx, t)

            elif tname == "DW_TAG_union_type":
                name = res['DW_AT_name'] if 'DW_AT_name' in res else "void"
                assert ('DW_AT_byte_size' in res)
                sz = int(res['DW_AT_byte_size'], 16)
                t = UnionType(name, cu_off, sz)

                type_info.insert(cu_off, idx, t)

                type_stack.append(t)
                lvl_stack.append((lvl, 'DW_TAG_union_type'))

            elif tname == "DW_TAG_ptr_to_member_type":
                name = res['DW_AT_name'] if 'DW_AT_name' in res else "void"
                t = PointerType(name, cu_off, None)

                type_info.insert(cu_off, idx, t)

            elif tname == "DW_TAG_imported_declaration":
                pass
            elif tname == "DW_TAG_unspecified_parameters":
                pass
            elif tname == "DW_TAG_constant":
                pass

    with open(prefix+'_lineinfo.json', 'w') as fd:
        dump_json(fd, line_info)
    with open(prefix+'_globvar.json', 'w') as fd:
        dump_json(fd, globvar_info)
    with open(prefix+'_funcinfo.json', 'w') as fd:
        dump_json(fd, func_info)
    with open(prefix+'_typeinfo.json', 'w') as fd:
        dump_json(fd, type_info)

def dump_json(j, info):
    class DwarfJsonEncoder(json.JSONEncoder):
        def default(self, obj):
            if hasattr(obj, "jsondump"):
                return obj.jsondump()
            else:
                return json.JSONEncoder.default(self, obj)
    json.dump(info.jsondump(), j, cls=DwarfJsonEncoder)

if __name__ == '__main__':
    with open(sys.argv[1], 'r') as fd:
        parse_dwarfdump(fd.read())

Functions

def dump_json(j, info)
Expand source code
def dump_json(j, info):
    class DwarfJsonEncoder(json.JSONEncoder):
        def default(self, obj):
            if hasattr(obj, "jsondump"):
                return obj.jsondump()
            else:
                return json.JSONEncoder.default(self, obj)
    json.dump(info.jsondump(), j, cls=DwarfJsonEncoder)
def parse_die(ent)
Expand source code
def parse_die(ent):
    result = {}
    for e in ent.split('> ')[1:]:
        while e.endswith('>'):
            e = e[:-1]
        assert (e.startswith('DW_AT_'))
        dat = e.split('<')
        attr = dat[0].strip()
        for v in dat[1:]:
            v = v.strip()
            if v:
                result[attr] = v
    return result
def parse_dwarfdump(indat, prefix='')
Expand source code
def parse_dwarfdump(indat, prefix=""):
    reloc_base = 0
    line_info = LineDB()
    globvar_info = GlobVarDB()
    func_info = FunctionDB()
    type_info = TypeDB()

    data = parse_section(indat)
    tag = ".debug_line"
    if tag in data:
        srcname = ""
        for line in data[tag]:
            if line == None:
                srcname = ""
                continue
            line = line.strip()
            if line.startswith("0x"):
                addrstr, rest = line.split('[')
                lnostr, info = rest.split(']')
                if "uri:" in info:
                    srcfn = info.split("uri:")[-1].strip()
                assert (srcfn)
                addr = int(addrstr.strip(), 16) + reloc_base
                lno = int(lnostr.strip().split(',')[0])
                col = int(lnostr.strip().split(',')[1])
                line_info.insert(srcfn, lno, col, addr)

    type_overlay = None
    cu_off = None
    lvl_stack = []
    scope_stack = []
    func_stack = []
    type_stack = []
    tag = ".debug_info"
    if tag in data:
        for line in data[tag]:
            line = line.strip()
            print(line)
            if not line:
                continue
            if not line.startswith('<'):
                continue

            die = line.split(' ')[0].strip()
            assert (die.startswith('<') and die.endswith('>'))
            lvl, idx, tname = die[1:-1].split('><')
            lvl = int(lvl)

            res = parse_die(line)
            if "DW_TAG_compile_unit" in line:
                assert ('DW_AT_low_pc' in res)
                assert ('DW_AT_high_pc' in res)
                base_addr = int(res['DW_AT_low_pc'], 16) + reloc_base
                end_addr = int(res['DW_AT_high_pc'], 16) + reloc_base
                scope_stack = [Scope(base_addr, end_addr)]
                lvl_stack = [(lvl, 'DW_TAG_compile_unit')]
                func_stack = []
                type_stack = []
                cu_off = int(idx.split('+')[0], 16)
                continue

            idx = int(idx, 16)

            #print(lvl, idx, tname)

            while lvl < lvl_stack[-1][0]:
                lvl_stack.pop()
                if lvl_stack[-1][1] == 'DW_TAG_lexical_block':
                    scope_stack.pop()
                if lvl_stack[-1][1] == 'DW_TAG_subprogram':
                    func_stack.pop()
                if lvl_stack[-1][1] == 'DW_TAG_structure_type':
                    type_stack.pop()
                if lvl_stack[-1][1] == 'DW_TAG_union_type':
                    type_stack.pop()
                if lvl_stack[-1][1] == 'DW_TAG_array_type':
                    type_stack.pop()

            if lvl != lvl_stack[-1][0] and lvl != (lvl_stack[-1][0]+1):
                continue

            if lvl_stack[-1][1] in ['SugarType', 'DW_TAG_pointer_type']:
                assert (lvl == lvl_stack[-1][0])
                lvl_stack.pop()
                assert (type_overlay)
                type_overlay[2].ref = idx
                type_info.insert(type_overlay[0], type_overlay[1], type_overlay[2])
                type_overlay = None

            if tname == "DW_TAG_lexical_block":
                assert ('DW_AT_low_pc' in res)
                assert ('DW_AT_high_pc' in res)
                base_addr = int(res['DW_AT_low_pc'], 16) + reloc_base
                end_addr = int(res['DW_AT_high_pc'], 16) + reloc_base
                scope_stack.append(Scope(base_addr, end_addr))
                lvl_stack.append((lvl, 'DW_TAG_lexical_block'))

            elif tname == "DW_TAG_variable":
                assert ('DW_AT_name' in res)
                name = res['DW_AT_name']
                v = VarInfo(name, cu_off)

                v.scope = scope_stack[-1]
                assert ('DW_AT_decl_line' in res)
                v.decl_lno = int(res['DW_AT_decl_line'], 16)
                assert ('DW_AT_decl_file' in res)
                v.decl_fn = res['DW_AT_decl_file']
                v.decl_fn = v.decl_fn[v.decl_fn.find(' ')+1:]
                if 'DW_AT_location' not in res:
                    continue
                for x in res['DW_AT_location'].split(':')[-1].strip().split('DW_OP_'):
                    x = x.strip()
                    if not x:
                        continue
                    v.loc_op.extend('DW_OP_{}'.format(x).split())
                v.loc_op = reprocess_ops(v.loc_op)
                assert ('DW_AT_type' in res)
                v.type = int(res['DW_AT_type'], 16)

                if len(func_stack) == 0:
                    globvar_info.insert(cu_off, v)
                else:
                    func_stack[-1].varlist.append(v)

            elif tname == "DW_TAG_formal_parameter":
                if 'DW_AT_name' not in res:
                    continue
                name = res['DW_AT_name']
                v = VarInfo(name, cu_off)

                v.scope = scope_stack[-1]
                assert ('DW_AT_decl_line' in res)
                v.decl_lno = int(res['DW_AT_decl_line'], 16)
                assert ('DW_AT_decl_file' in res)
                v.decl_fn = res['DW_AT_decl_file']
                v.decl_fn = v.decl_fn[v.decl_fn.find(' ')+1:]
                if 'DW_AT_location' not in res:
                    continue
                for x in res['DW_AT_location'].split(':')[-1].strip().split('DW_OP_'):
                    x = x.strip()
                    if not x:
                        continue
                    v.loc_op.extend('DW_OP_{}'.format(x).split())
                v.loc_op = reprocess_ops(v.loc_op)
                assert ('DW_AT_type' in res)
                v.type = int(res['DW_AT_type'], 16)

                assert (len(func_stack) > 0)
                func_stack[-1].varlist.append(v)

            elif tname == "DW_TAG_subprogram":
                assert ('DW_AT_name' in res)
                name = res['DW_AT_name']

                assert ('DW_AT_low_pc' in res)
                assert ('DW_AT_high_pc' in res)
                base_addr = int(res['DW_AT_low_pc'], 16) + reloc_base
                end_addr = int(res['DW_AT_high_pc'], 16) + reloc_base
                scope = Scope(base_addr, end_addr)
                scope_stack.append(scope)
                lvl_stack.append((lvl, 'DW_TAG_subprogram'))

                assert ('DW_AT_decl_file' in res)
                decl_fn = res['DW_AT_decl_file']
                decl_fn = decl_fn[v.decl_fn.find(' ')+1:]

                if 'DW_AT_frame_base' in res:
                    fb_op = [res['DW_AT_frame_base'].split(':')[-1].strip()]
                else:
                    fb_op = []
                fb_op = reprocess_ops(fb_op)

                f = FuncInfo(cu_off, name, scope, fb_op)

                f.fn, f.lno = line_info.update_function(base_addr, end_addr, f)

                func_stack.append(f)
                func_info.insert(cu_off, f)

            elif tname == "DW_TAG_structure_type":
                if 'DW_AT_byte_size' not in res:
                    continue
                sz = int(res['DW_AT_byte_size'], 16)
                name = res['DW_AT_name'] if 'DW_AT_name' in res else "void"
                t = StructType(name, cu_off, sz)

                type_info.insert(cu_off, idx, t)

                type_stack.append(t)
                lvl_stack.append((lvl, 'DW_TAG_structure_type'))

            elif tname == "DW_TAG_member":
                assert (lvl_stack[-1][1] in ['DW_TAG_structure_type', 'DW_TAG_union_type'])

                name = res['DW_AT_name'] if 'DW_AT_name' in res else "void"

                # Skip bit fields
                if 'DW_AT_bit_size' in res or 'DW_AT_bit_offset' in res:
                    continue

                assert ('DW_AT_type' in res)
                toff = int(res['DW_AT_type'], 16)

                assert ('DW_AT_data_member_location' in res)
                loc_op = ['DW_OP_{}'.format(x.strip()) for x in \
                        res['DW_AT_data_member_location'].split(':')[-1].strip().split('DW_OP_')[1:]]
                # Signal attribute form DW_FORM_data1/2/4/8
                assert (len(loc_op) == 1)
                assert (loc_op[0].split()[0] == 'DW_OP_plus_uconst')
                off = int(loc_op[0].split()[1])

                type_stack[-1].children[off] = (name, toff)

            elif tname == "DW_TAG_array_type":
                name = res['DW_AT_name'] if 'DW_AT_name' in res else "void"
                assert ('DW_AT_type' in res)
                elemoff = int(res['DW_AT_type'], 16)

                t = ArrayType(name, cu_off, elemoff)

                type_info.insert(cu_off, idx, t)

                lvl_stack.append((lvl, 'DW_TAG_array_type'))
                type_stack.append(t)

            elif tname == "DW_TAG_subrange_type":
                name = res['DW_AT_name'] if 'DW_AT_name' in res else "void"
                assert ('DW_AT_type' in res)
                toff = int(res['DW_AT_type'], 16)
                assert ('DW_AT_count' in res)
                cnt = int(res['DW_AT_count'], 16)
                # cnt = int(res['DW_AT_upper_bound'], 16)

                t = ArrayRangeType(name, cu_off, toff, cnt)

                type_info.insert(cu_off, idx, t)

                assert (lvl_stack[-1][1] == 'DW_TAG_array_type')
                assert ((lvl_stack[-1][0]+1) == lvl)

                type_stack[-1].range.append(idx)

            elif tname == "DW_TAG_subroutine_type":
                name = res['DW_AT_name'] if 'DW_AT_name' in res else "void"
                t = SubroutineType(name)

                type_info.insert(cu_off, idx, t)

            elif tname == "DW_TAG_base_type":
                name = res['DW_AT_name'] if 'DW_AT_name' in res else "void"
                assert ('DW_AT_byte_size' in res)
                sz = int(res['DW_AT_byte_size'], 16)
                t = BaseType(name, sz)

                type_info.insert(cu_off, idx, t)

            elif tname == "DW_TAG_pointer_type":
                name = res['DW_AT_name'] if 'DW_AT_name' in res else "void"

                if 'DW_AT_type' not in res:
                    lvl_stack.append((lvl, 'DW_TAG_pointer_type'))
                    type_overlay = (cu_off, idx, PointerType(name, cu_off, None))
                    continue
                target = int(res['DW_AT_type'], 16)

                t = PointerType(name, cu_off, target)

                type_info.insert(cu_off, idx, t)

            elif tname == "DW_TAG_enumeration_type":
                name = res['DW_AT_name'] if 'DW_AT_name' in res else "void"

                assert ('DW_AT_byte_size' in res)
                sz = int(res['DW_AT_byte_size'], 16)

                t = EnumType(name, sz)

                type_info.insert(cu_off, idx, t)

            elif tname in [
                    "DW_TAG_restrict_type",
                    "DW_TAG_const_type",
                    "DW_TAG_volatile_type",
                    "DW_TAG_typedef"
                    ]:
                name = res['DW_AT_name'] if 'DW_AT_name' in res else "void"
                t = SugarType(name, cu_off)

                if 'DW_AT_type' not in res:
                    lvl_stack.append((lvl, 'SugarType'))
                    type_overlay = (cu_off, idx, t)
                    continue
                t.ref = int(res['DW_AT_type'], 16)

                type_info.insert(cu_off, idx, t)

            elif tname == "DW_TAG_union_type":
                name = res['DW_AT_name'] if 'DW_AT_name' in res else "void"
                assert ('DW_AT_byte_size' in res)
                sz = int(res['DW_AT_byte_size'], 16)
                t = UnionType(name, cu_off, sz)

                type_info.insert(cu_off, idx, t)

                type_stack.append(t)
                lvl_stack.append((lvl, 'DW_TAG_union_type'))

            elif tname == "DW_TAG_ptr_to_member_type":
                name = res['DW_AT_name'] if 'DW_AT_name' in res else "void"
                t = PointerType(name, cu_off, None)

                type_info.insert(cu_off, idx, t)

            elif tname == "DW_TAG_imported_declaration":
                pass
            elif tname == "DW_TAG_unspecified_parameters":
                pass
            elif tname == "DW_TAG_constant":
                pass

    with open(prefix+'_lineinfo.json', 'w') as fd:
        dump_json(fd, line_info)
    with open(prefix+'_globvar.json', 'w') as fd:
        dump_json(fd, globvar_info)
    with open(prefix+'_funcinfo.json', 'w') as fd:
        dump_json(fd, func_info)
    with open(prefix+'_typeinfo.json', 'w') as fd:
        dump_json(fd, type_info)
def parse_section(indat)
Expand source code
def parse_section(indat):
    result = {'.debug_line': [], '.debug_info': []}
    data = indat.decode().strip().split('\n')
    for l in data:
        l = l.strip()
        if l.startswith("0x"):
            result['.debug_line'].append(l)
            # Signal End of Text
            if 'ET' in l.split():
                result['.debug_line'].append(None)
        elif l.startswith("<") and not l.startswith("<pc>"):
            result['.debug_info'].append(l)
    return result
def reprocess_ops(ops)
Expand source code
def reprocess_ops(ops):
    out = []
    for op in ops:
        if op.startswith('DW_'):
            out.append(op)
        elif type(op) == str:
            if op.lstrip('-+').startswith("0x"):
                out.append(int(op, 16))
            else:
                out.append(int(op))
        else:
            out.append(op)
    return out

Classes

class ArrayRangeType (name, cu_off, rtype, cnt)
Expand source code
class ArrayRangeType(SugarType):
    def __init__(self, name, cu_off, rtype, cnt):
        SugarType.__init__(self, name, cu_off)
        self.ref = rtype
        self.size = cnt

    def jsondump(self):
        d = SugarType.jsondump(self)
        d.update({
                'tag': 'ArrayRangeType',
                'size': self.size,
                })
        return d

Ancestors

Methods

def jsondump(self)
Expand source code
def jsondump(self):
    d = SugarType.jsondump(self)
    d.update({
            'tag': 'ArrayRangeType',
            'size': self.size,
            })
    return d
class ArrayType (name, cu_off, elemty)
Expand source code
class ArrayType(SugarType):
    def __init__(self, name, cu_off, elemty):
        SugarType.__init__(self, name, cu_off)
        self.ref = elemty
        self.range = []

    def jsondump(self):
        d = SugarType.jsondump(self)
        d.update({
                'tag': 'ArrayType',
                'range': self.range,
                })
        return d

Ancestors

Methods

def jsondump(self)
Expand source code
def jsondump(self):
    d = SugarType.jsondump(self)
    d.update({
            'tag': 'ArrayType',
            'range': self.range,
            })
    return d
class BaseType (name, size)
Expand source code
class BaseType(TypeInfo):
    def __init__(self, name, size):
        TypeInfo.__init__(self, name)
        self.size = size

    def jsondump(self):
        d = TypeInfo.jsondump(self)
        d.update({
                'tag': 'BaseType',
                'size': self.size,
                })
        return d

Ancestors

Methods

def jsondump(self)
Expand source code
def jsondump(self):
    d = TypeInfo.jsondump(self)
    d.update({
            'tag': 'BaseType',
            'size': self.size,
            })
    return d
class EnumType (name, size)
Expand source code
class EnumType(TypeInfo):
    def __init__(self, name, size):
        TypeInfo.__init__(self, name)
        self.size = size

    def jsondump(self):
        d = TypeInfo.jsondump(self)
        d.update({
                'tag': 'EnumType',
                'size': self.size,
                })
        return d

Ancestors

Methods

def jsondump(self)
Expand source code
def jsondump(self):
    d = TypeInfo.jsondump(self)
    d.update({
            'tag': 'EnumType',
            'size': self.size,
            })
    return d
class FuncInfo (cu_off, name, scope, fb_op)
Expand source code
class FuncInfo(object):
    def __init__(self, cu_off, name, scope, fb_op):
        self.cu_offset = cu_off
        self.name = name
        self.scope = scope
        self.framebase = fb_op
        self.fn = None
        self.lno = None
        self.varlist = []

    def jsondump(self):
        return {'name': self.name, \
                'cu_offset': self.cu_offset, \
                'scope': self.scope.jsondump(), \
                'framebase': self.framebase, \
                'fn': self.fn, \
                'lno': self.lno, \
                'varlist': [v.jsondump() for v in self.varlist]}

Methods

def jsondump(self)
Expand source code
def jsondump(self):
    return {'name': self.name, \
            'cu_offset': self.cu_offset, \
            'scope': self.scope.jsondump(), \
            'framebase': self.framebase, \
            'fn': self.fn, \
            'lno': self.lno, \
            'varlist': [v.jsondump() for v in self.varlist]}
class FunctionDB
Expand source code
class FunctionDB(object):
    def __init__(self):
        self.data = {}

    def insert(self, cu, f):
        if cu not in self.data:
            self.data[cu] = set()
        self.data[cu].add(f)

    def jsondump(self):
        jout = {}
        for cu in self.data:
            jout[cu] = [f.jsondump() for f in self.data[cu]]
        #return json.dumps(jout)
        return jout

Methods

def insert(self, cu, f)
Expand source code
def insert(self, cu, f):
    if cu not in self.data:
        self.data[cu] = set()
    self.data[cu].add(f)
def jsondump(self)
Expand source code
def jsondump(self):
    jout = {}
    for cu in self.data:
        jout[cu] = [f.jsondump() for f in self.data[cu]]
    #return json.dumps(jout)
    return jout
class GlobVarDB
Expand source code
class GlobVarDB(object):
    def __init__(self):
        self.data = {}

    def insert(self, cu, var):
        if cu not in self.data:
            self.data[cu] = set()
        self.data[cu].add(var)

    def jsondump(self):
        jout = {}
        for cu in self.data:
            jout[cu] = [f.jsondump() for f in self.data[cu]]
        #return json.dumps(jout)
        return jout

Methods

def insert(self, cu, var)
Expand source code
def insert(self, cu, var):
    if cu not in self.data:
        self.data[cu] = set()
    self.data[cu].add(var)
def jsondump(self)
Expand source code
def jsondump(self):
    jout = {}
    for cu in self.data:
        jout[cu] = [f.jsondump() for f in self.data[cu]]
    #return json.dumps(jout)
    return jout
class LineDB
Expand source code
class LineDB(object):
    def __init__(self):
        self.data = {}

    def _find_best_fit(self, srcfn, lno, addr):
        r = [-1, -1]
        for i in range(len(self.data[srcfn])):
            if self.data[srcfn][i].lno == lno:
                if r[1] < self.data[srcfn][i].highpc and addr > self.data[srcfn][i].highpc:
                    r = [i, self.data[srcfn][i].highpc]
        return r[0]

    def insert(self, srcfn, lno, col, addr, func=None):
        if srcfn not in self.data:
            self.data[srcfn] = []

        if self.data[srcfn] and lno < self.data[srcfn][-1].lno:
            i = -1
        else:
            i = self._find_best_fit(srcfn, lno, addr)
        if i == -1:
            self.data[srcfn].append(LineRange(lno, col, addr, addr, func))
            self.data[srcfn].sort(key = lambda x: x.lno)

        prevlno = lno-1
        i = self._find_best_fit(srcfn, prevlno, addr)
        while prevlno > 0 and i == -1:
            prevlno -= 1
            i = self._find_best_fit(srcfn, prevlno, addr)
        if i != -1:
            self.data[srcfn][i].highpc = addr

    def update_function(self, base_addr, end_addr, finfo):
        srcinfo = None
        for srcfn in self.data:
            for i in range(len(self.data[srcfn])):
                if self.data[srcfn][i].lowpc == base_addr:
                    srcinfo = (srcfn, self.data[srcfn][i].lno)
                if self.data[srcfn][i].lowpc >= base_addr \
                        and self.data[srcfn][i].highpc < end_addr:
                    self.data[srcfn][i].func = finfo.scope.lowpc
        return srcinfo

    def jsondump(self):
        jout = {}
        for srcfn in self.data:
            key = srcfn
            while srcfn[0] in ['"', "'"]:
                srcfn = srcfn[1:]
            while srcfn[-1] in ['"', "'"]:
                srcfn = srcfn[:-1]
            jout[srcfn] = []
            for lr in self.data[key]:
                jout[srcfn].append(lr.jsondump())
        #return json.dumps(jout)
        return jout

Methods

def insert(self, srcfn, lno, col, addr, func=None)
Expand source code
def insert(self, srcfn, lno, col, addr, func=None):
    if srcfn not in self.data:
        self.data[srcfn] = []

    if self.data[srcfn] and lno < self.data[srcfn][-1].lno:
        i = -1
    else:
        i = self._find_best_fit(srcfn, lno, addr)
    if i == -1:
        self.data[srcfn].append(LineRange(lno, col, addr, addr, func))
        self.data[srcfn].sort(key = lambda x: x.lno)

    prevlno = lno-1
    i = self._find_best_fit(srcfn, prevlno, addr)
    while prevlno > 0 and i == -1:
        prevlno -= 1
        i = self._find_best_fit(srcfn, prevlno, addr)
    if i != -1:
        self.data[srcfn][i].highpc = addr
def jsondump(self)
Expand source code
def jsondump(self):
    jout = {}
    for srcfn in self.data:
        key = srcfn
        while srcfn[0] in ['"', "'"]:
            srcfn = srcfn[1:]
        while srcfn[-1] in ['"', "'"]:
            srcfn = srcfn[:-1]
        jout[srcfn] = []
        for lr in self.data[key]:
            jout[srcfn].append(lr.jsondump())
    #return json.dumps(jout)
    return jout
def update_function(self, base_addr, end_addr, finfo)
Expand source code
def update_function(self, base_addr, end_addr, finfo):
    srcinfo = None
    for srcfn in self.data:
        for i in range(len(self.data[srcfn])):
            if self.data[srcfn][i].lowpc == base_addr:
                srcinfo = (srcfn, self.data[srcfn][i].lno)
            if self.data[srcfn][i].lowpc >= base_addr \
                    and self.data[srcfn][i].highpc < end_addr:
                self.data[srcfn][i].func = finfo.scope.lowpc
    return srcinfo
class LineRange (lno, col, lopc, hipc, func)
Expand source code
class LineRange(object):
    def __init__(self, lno, col, lopc, hipc, func):
        self.lno = lno
        self.col = col
        self.lowpc = lopc
        self.highpc = hipc
        self.func = func

    def jsondump(self):
        return {
                'lno': self.lno,
                'col': self.col,
                'lowpc': self.lowpc,
                'highpc': self.highpc,
                'func': self.func,
                }

Methods

def jsondump(self)
Expand source code
def jsondump(self):
    return {
            'lno': self.lno,
            'col': self.col,
            'lowpc': self.lowpc,
            'highpc': self.highpc,
            'func': self.func,
            }
class PointerType (name, cu_off, target)
Expand source code
class PointerType(SugarType):
    def __init__(self, name, cu_off, target):
        SugarType.__init__(self, name, cu_off)
        self.ref = target

    def jsondump(self):
        d = SugarType.jsondump(self)
        d.update({
                'tag': 'PointerType',
                })
        return d

Ancestors

Methods

def jsondump(self)
Expand source code
def jsondump(self):
    d = SugarType.jsondump(self)
    d.update({
            'tag': 'PointerType',
            })
    return d
class Scope (lopc, hipc)
Expand source code
class Scope(object):
    def __init__(self, lopc, hipc):
        self.lowpc = lopc
        self.highpc = hipc

    def jsondump(self):
        return {'lowpc': self.lowpc, 'highpc': self.highpc}

Methods

def jsondump(self)
Expand source code
def jsondump(self):
    return {'lowpc': self.lowpc, 'highpc': self.highpc}
class StructType (name, cu_off, size)
Expand source code
class StructType(TypeInfo):
    def __init__(self, name, cu_off, size):
        TypeInfo.__init__(self, name)
        self.size = size
        self.cu_off = cu_off
        self.children = {}  # <member_offset: (name, type_offset)>

    def jsondump(self):
        d = TypeInfo.jsondump(self)
        d.update({
                'tag': 'StructType',
                'size': self.size,
                'cu_off': self.cu_off,
                'children': self.children,
                })
        return d

Ancestors

Methods

def jsondump(self)
Expand source code
def jsondump(self):
    d = TypeInfo.jsondump(self)
    d.update({
            'tag': 'StructType',
            'size': self.size,
            'cu_off': self.cu_off,
            'children': self.children,
            })
    return d
class SubroutineType (name)
Expand source code
class SubroutineType(TypeInfo):
    def __init__(self, name):
        TypeInfo.__init__(self, name)

    def jsondump(self):
        d = TypeInfo.jsondump(self)
        d.update({
                'tag': 'SubroutineType',
                })
        return d

Ancestors

Methods

def jsondump(self)
Expand source code
def jsondump(self):
    d = TypeInfo.jsondump(self)
    d.update({
            'tag': 'SubroutineType',
            })
    return d
class SugarType (name, cu_off)
Expand source code
class SugarType(TypeInfo):
    def __init__(self, name, cu_off):
        TypeInfo.__init__(self, name)
        self.cu_off = cu_off
        self.ref = None

    def jsondump(self):
        d = TypeInfo.jsondump(self)
        d.update({
                'tag': 'SugarType',
                'cu_off': self.cu_off,
                'ref': self.ref,
                })
        return d

Ancestors

Subclasses

Methods

def jsondump(self)
Expand source code
def jsondump(self):
    d = TypeInfo.jsondump(self)
    d.update({
            'tag': 'SugarType',
            'cu_off': self.cu_off,
            'ref': self.ref,
            })
    return d
class TypeDB
Expand source code
class TypeDB(object):
    def __init__(self):
        self.data = {}

    def insert(self, cu, off, ty):
        if cu not in self.data:
            self.data[cu] = {}
        if off not in self.data[cu]:
            self.data[cu][off] = ty

    def jsondump(self):
        jout = {}
        for cu in self.data:
            jout[cu] = {}
            for off in self.data[cu]:
                jout[cu][off] = self.data[cu][off].jsondump()
        #return json.dumps(jout)
        return jout

Methods

def insert(self, cu, off, ty)
Expand source code
def insert(self, cu, off, ty):
    if cu not in self.data:
        self.data[cu] = {}
    if off not in self.data[cu]:
        self.data[cu][off] = ty
def jsondump(self)
Expand source code
def jsondump(self):
    jout = {}
    for cu in self.data:
        jout[cu] = {}
        for off in self.data[cu]:
            jout[cu][off] = self.data[cu][off].jsondump()
    #return json.dumps(jout)
    return jout
class TypeInfo (name)
Expand source code
class TypeInfo(object):
    def __init__(self, name):
        self.name = name

    def jsondump(self):
        return {'name': self.name}

Subclasses

Methods

def jsondump(self)
Expand source code
def jsondump(self):
    return {'name': self.name}
class UnionType (name, cu_off, size)
Expand source code
class UnionType(TypeInfo):
    def __init__(self, name, cu_off, size):
        TypeInfo.__init__(self, name)
        self.size = size
        self.cu_off = cu_off
        self.children = {}  # <member_offset: (name, type_offset)>

    def jsondump(self):
        d = TypeInfo.jsondump(self)
        d.update({
                'tag': 'UnionType',
                'size': self.size,
                'cu_off': self.cu_off,
                'children': self.children,
                })
        return d

Ancestors

Methods

def jsondump(self)
Expand source code
def jsondump(self):
    d = TypeInfo.jsondump(self)
    d.update({
            'tag': 'UnionType',
            'size': self.size,
            'cu_off': self.cu_off,
            'children': self.children,
            })
    return d
class VarInfo (name, cu_off)
Expand source code
class VarInfo(object):
    def __init__(self, name, cu_off):
        self.name = name
        self.cu_offset = cu_off
        self.scope = None
        self.decl_lno = None
        self.decl_fn = None
        self.loc_op = []
        self.type = None

    def jsondump(self):
        return {'name': self.name, \
                'cu_offset': self.cu_offset, \
                'scope': self.scope.jsondump(), \
                'decl_lno': self.decl_lno, \
                'decl_fn': self.decl_fn, \
                'loc_op': self.loc_op, \
                'type': self.type}

Methods

def jsondump(self)
Expand source code
def jsondump(self):
    return {'name': self.name, \
            'cu_offset': self.cu_offset, \
            'scope': self.scope.jsondump(), \
            'decl_lno': self.decl_lno, \
            'decl_fn': self.decl_fn, \
            'loc_op': self.loc_op, \
            'type': self.type}