Make it work (somewhat)
Signed-off-by: Juraj Oravec <jurajoravec@mailo.com>
This commit is contained in:
parent
3c6b845948
commit
9a7f1d21fd
261
main.py
261
main.py
|
@ -1,13 +1,12 @@
|
|||
#!/bin/python
|
||||
|
||||
import sys
|
||||
import math
|
||||
from bear import formats
|
||||
from elftools.dwarf.locationlists import LocationParser, LocationExpr
|
||||
from elftools.dwarf.dwarf_expr import DWARFExprParser, DWARFExprOp, DW_OP_opcode2name
|
||||
from bear.dwarfone import DWARFExprParserV1
|
||||
|
||||
from pprint import pprint
|
||||
|
||||
|
||||
configuration = {
|
||||
"include_file_name": False,
|
||||
|
@ -31,6 +30,7 @@ def decorate_die(die, i):
|
|||
die._children = None
|
||||
return die
|
||||
|
||||
|
||||
def load_children(parent_die):
|
||||
# Load and cache child DIEs in the parent DIE, if necessary
|
||||
# Assumes the check if the DIE has children has been already performed
|
||||
|
@ -47,7 +47,6 @@ def load_children(parent_die):
|
|||
parent_die._children = []
|
||||
|
||||
|
||||
|
||||
def safe_DIE_name(die, default=''):
|
||||
return die.attributes['DW_AT_name'].value.decode('utf-8', errors='ignore') if 'DW_AT_name' in die.attributes else default
|
||||
|
||||
|
@ -64,6 +63,7 @@ class Bear():
|
|||
# Some cached top level stuff
|
||||
# Notably, iter_CUs doesn't cache
|
||||
di._ranges = None # Loaded on first use
|
||||
|
||||
def decorate_cu(cu, i):
|
||||
cu._i = i
|
||||
cu._lineprogram = None
|
||||
|
@ -91,6 +91,7 @@ class Bear():
|
|||
# address: absolute address of the variable
|
||||
# children: a dictionary of child elements
|
||||
self.myVariables = []
|
||||
self.flat_list = []
|
||||
self.top_dies = [decorate_die(CU.get_top_DIE(), i) for (i, CU) in enumerate(di._CUs)]
|
||||
|
||||
for top_die in self.top_dies:
|
||||
|
@ -99,11 +100,10 @@ class Bear():
|
|||
# Preload children
|
||||
load_children(top_die)
|
||||
|
||||
children_dies = []
|
||||
children_dies = list()
|
||||
|
||||
for child_die in top_die._children:
|
||||
if child_die.tag == 'DW_TAG_variable':
|
||||
# pprint(child_die)
|
||||
entry = {
|
||||
# Name should be on every element, if not set something so it can be printed
|
||||
'name': safe_DIE_name(child_die, '?')
|
||||
|
@ -112,8 +112,6 @@ class Bear():
|
|||
if 'DW_AT_location' in child_die.attributes:
|
||||
if LocationParser.attribute_has_location(child_die.attributes['DW_AT_location'], child_die.cu['version']):
|
||||
ll = self.parse_location(child_die, child_die.attributes['DW_AT_location'])
|
||||
# pprint(ll.loc_expr)
|
||||
# pprint(self.dump_expr(child_die, ll.loc_expr))
|
||||
lloc = self.dump_expr(child_die, ll.loc_expr)
|
||||
# print(hex(lloc[0].args[0]))
|
||||
entry['address'] = hex(lloc[0].args[0])
|
||||
|
@ -124,7 +122,7 @@ class Bear():
|
|||
|
||||
if 'DW_AT_type' in child_die.attributes:
|
||||
typ_die = child_die.get_DIE_from_attribute('DW_AT_type')
|
||||
entry['type'] = self.resolve_type(typ_die)
|
||||
self.truly_resolve_type(entry, typ_die)
|
||||
|
||||
children_dies.append(entry)
|
||||
|
||||
|
@ -133,19 +131,16 @@ class Bear():
|
|||
'children': children_dies
|
||||
})
|
||||
|
||||
pprint(self.myVariables)
|
||||
|
||||
def resolve_type(self, die_type):
|
||||
def truly_resolve_type(self, entry, die_type):
|
||||
if die_type.tag == 'DW_TAG_volatile_type':
|
||||
die_type = die_type.get_DIE_from_attribute('DW_AT_type')
|
||||
|
||||
entry = {
|
||||
# Name should be on every element, if not set something so it can be printed
|
||||
'name': safe_DIE_name(die_type, '?')
|
||||
}
|
||||
entry['type'] = safe_DIE_name(die_type, '?')
|
||||
|
||||
if 'DW_AT_data_member_location' in die_type.attributes:
|
||||
entry['offset'] = die_type.attributes['DW_AT_data_member_location'].value * 8
|
||||
if 'address' in entry:
|
||||
entry['address'] = hex(int(entry['address'], 16) + die_type.attributes['DW_AT_data_member_location'].value)
|
||||
|
||||
if 'DW_AT_type' in die_type.attributes and die_type.tag not in ['DW_TAG_base_type', 'DW_TAG_structure_type', 'DW_TAG_array_type']:
|
||||
# Check if the type is a redefinition of a base type
|
||||
|
@ -156,186 +151,114 @@ class Bear():
|
|||
die_type = die_type_test
|
||||
break
|
||||
|
||||
if 'DW_AT_byte_size' in die_type.attributes:
|
||||
entry['size_byte'] = die_type.attributes['DW_AT_byte_size'].value
|
||||
|
||||
if die_type.tag == 'DW_TAG_base_type':
|
||||
entry['type'] = safe_DIE_name(die_type, '?')
|
||||
real_type_name = safe_DIE_name(die_type, '?')
|
||||
if real_type_name != '?' and real_type_name != entry['type']:
|
||||
entry['type'] = '{name} ({real})'.format(name=entry['type'], real=safe_DIE_name(die_type, '?'))
|
||||
elif die_type.tag == "DW_TAG_structure_type":
|
||||
load_children(die_type)
|
||||
child_dies = []
|
||||
child_offset = 0
|
||||
child_offset_bit = 0
|
||||
for child_die in die_type._children:
|
||||
child_entry = self.resolve_type(child_die)
|
||||
if 'DW_AT_type' in child_die.attributes:
|
||||
typ_die = child_die.get_DIE_from_attribute('DW_AT_type')
|
||||
|
||||
child_entry = dict()
|
||||
child_entry['name'] = safe_DIE_name(child_die, '?')
|
||||
|
||||
if 'DW_AT_data_bit_offset' in child_die.attributes:
|
||||
child_offset_bit = child_die.attributes['DW_AT_data_bit_offset'].value
|
||||
if child_offset_bit >= 8:
|
||||
child_offset = child_offset + math.floor(child_offset_bit / 8)
|
||||
child_offset_bit = child_offset_bit - math.floor(child_offset_bit / 8) * 8
|
||||
|
||||
if 'address' in entry:
|
||||
child_entry['address'] = hex(int(entry['address'], 16) + child_offset)
|
||||
|
||||
self.truly_resolve_type(child_entry, typ_die)
|
||||
|
||||
if ('size_byte' in child_entry) and ('DW_AT_data_bit_offset' not in child_die.attributes):
|
||||
child_offset = child_offset + child_entry['size_byte']
|
||||
|
||||
child_dies.append(child_entry)
|
||||
entry['children'] = child_dies;
|
||||
entry['children'] = child_dies
|
||||
elif die_type.tag == "DW_TAG_array_type":
|
||||
array_type = self.resolve_type(die_type.get_DIE_from_attribute('DW_AT_type'))
|
||||
self.truly_resolve_type(entry, die_type.get_DIE_from_attribute('DW_AT_type'))
|
||||
load_children(die_type)
|
||||
children_num = die_type._children[0].attributes['DW_AT_upper_bound'].value
|
||||
child_entries = []
|
||||
for child in range(0, children_num + 1):
|
||||
child_entry = array_type.copy()
|
||||
child_entry['offset'] = array_type['size_bit'] * child
|
||||
child_entries.append(child_entry)
|
||||
entry['children'] = child_entries
|
||||
entry['number_of_elements'] = die_type._children[0].attributes['DW_AT_upper_bound'].value + 1
|
||||
elif die_type.tag == 'DW_TAG_union_type':
|
||||
load_children(die_type)
|
||||
child_entries = []
|
||||
for child_die in die_type._children:
|
||||
child_entry = self.resolve_type(child_die)
|
||||
if 'DW_AT_type' in child_die.attributes:
|
||||
typ_die = child_die.get_DIE_from_attribute('DW_AT_type')
|
||||
|
||||
child_entry = dict()
|
||||
child_entry['name'] = safe_DIE_name(child_die, '?')
|
||||
|
||||
if 'address' in entry:
|
||||
child_entry['address'] = entry['address']
|
||||
|
||||
self.truly_resolve_type(child_entry, typ_die)
|
||||
|
||||
child_entries.append(child_entry)
|
||||
entry['children'] = child_entries
|
||||
else:
|
||||
eprint("Unsupported type:", die_type.tag)
|
||||
|
||||
if 'DW_AT_byte_size' in die_type.attributes:
|
||||
entry['size_bit'] = die_type.attributes['DW_AT_byte_size'].value * 8
|
||||
|
||||
return entry
|
||||
|
||||
def flatten_type(self, parent=None):
|
||||
# Structure of resulting list of dictionaries
|
||||
# address - The address
|
||||
# name - The long name of a variable after out rolling the type
|
||||
vars = []
|
||||
# Iterate over CUs
|
||||
# - name - filename
|
||||
# - children - variables
|
||||
for CU in self.myVariables:
|
||||
vars.append(CU['name'])
|
||||
|
||||
for child in CU['children']:
|
||||
if configuration["include_file_name"]:
|
||||
vars.append(self.flatten_child(child, CU['name']))
|
||||
self.pettanko(child, CU['name'])
|
||||
else:
|
||||
vars.append(self.flatten_child(child))
|
||||
return vars
|
||||
self.pettanko(child)
|
||||
|
||||
def flatten_child(self, child, name='', address=0):
|
||||
var = {}
|
||||
kids = []
|
||||
|
||||
if name:
|
||||
var['name'] = '{parent}.{child}'.format(parent=name, child=child['name'])
|
||||
def pettanko(self, entry : dict, a_parent_name : str = ""):
|
||||
flat_entry = dict()
|
||||
if a_parent_name:
|
||||
flat_entry['name'] = '{0}.{1}'.format(a_parent_name, entry['name'])
|
||||
else:
|
||||
var['name'] = child['name']
|
||||
flat_entry['name'] = entry['name']
|
||||
|
||||
if address:
|
||||
var['address'] = address
|
||||
else:
|
||||
var['address'] = child['address']
|
||||
if 'address' in entry:
|
||||
flat_entry['address'] = entry['address']
|
||||
|
||||
if 'children' in child:
|
||||
for kid in child['children']:
|
||||
self.flatten_child(kid, var['name'], var['address'])
|
||||
if 'size_byte' in entry:
|
||||
flat_entry['size_byte'] = entry['size_byte']
|
||||
if 'number_of_elements' in entry:
|
||||
flat_entry['size_byte'] = flat_entry['size_byte'] * entry['number_of_elements']
|
||||
|
||||
if 'type' in child:
|
||||
self.flatten_child()
|
||||
if 'type' in entry:
|
||||
flat_entry['type'] = entry['type']
|
||||
|
||||
return kids
|
||||
self.flat_list.append(flat_entry)
|
||||
|
||||
if 'children' in entry:
|
||||
for kid in entry['children']:
|
||||
self.pettanko(kid, flat_entry['name'])
|
||||
|
||||
if 'number_of_elements' in entry:
|
||||
for index in range(0, entry['number_of_elements']):
|
||||
kid = flat_entry.copy()
|
||||
kid['name'] = '{0}[{1}]'.format(flat_entry['name'], index)
|
||||
kid['address'] = hex(int(flat_entry['address'], 16) + entry['size_byte'] * index)
|
||||
|
||||
self.pettanko(kid)
|
||||
|
||||
kid_parent = self.flat_list[-1]
|
||||
|
||||
if 'children' in entry:
|
||||
for kid_of_kid in entry['children']:
|
||||
self.pettanko(kid_of_kid, kid_parent['name'])
|
||||
|
||||
def pretty_print(self):
|
||||
vars = []
|
||||
# Iterate over CUs
|
||||
# - name - filename
|
||||
# - children - variables
|
||||
for CU in self.myVariables:
|
||||
vars.append(CU['name'])
|
||||
|
||||
for child in CU['children']:
|
||||
self.pretty_child(child)
|
||||
return vars
|
||||
|
||||
def pretty_child(self, child, prefix='', address=0):
|
||||
name = ''
|
||||
if 'children' in child:
|
||||
pass
|
||||
else:
|
||||
pass
|
||||
|
||||
def print_top_DIE(self, die):
|
||||
if die.tag == 'DW_TAG_variable':
|
||||
name = safe_DIE_name(die)
|
||||
if name:
|
||||
typ_name = ''
|
||||
if 'DW_AT_type' in die.attributes:
|
||||
typ = die.get_DIE_from_attribute('DW_AT_type')
|
||||
print(self.describe_type(typ))
|
||||
# typ_name = safe_DIE_name(typ)
|
||||
# if not typ_name:
|
||||
# print (typ)
|
||||
print('{name} {typ_name}'.format(name=name, typ_name=typ_name))
|
||||
|
||||
def print_DIE(self, die, prefix=''):
|
||||
name = ''
|
||||
# print(die)
|
||||
if die.tag == 'DW_TAG_variable':
|
||||
name = safe_DIE_name(die)
|
||||
if name and 'DW_AT_type' in die.attributes:
|
||||
typ = die.get_DIE_from_attribute('DW_AT_type')
|
||||
if 'DW_AT_location' in die.attributes:
|
||||
ll = self.parse_location(die, die.attributes['DW_AT_location'])
|
||||
# if isinstance(ll, LocationExpr):
|
||||
# print(self.dump_expr(die, ll.loc_expr))
|
||||
|
||||
self.print_DIE(typ, name)
|
||||
return
|
||||
# print(typ)
|
||||
elif die.tag == 'DW_TAG_compile_unit':
|
||||
name = safe_DIE_name(die, '.')
|
||||
elif prefix and die.tag == 'DW_TAG_base_type':
|
||||
name = safe_DIE_name(die)
|
||||
elif prefix and die.tag == 'DW_TAG_const_type':
|
||||
if 'DW_AT_type' in die.attributes:
|
||||
typ = die.get_DIE_from_attribute('DW_AT_type')
|
||||
self.print_DIE(typ, prefix)
|
||||
return
|
||||
elif prefix and die.tag == 'DW_TAG_array_type':
|
||||
if 'DW_AT_type' in die.attributes:
|
||||
typ = die.get_DIE_from_attribute('DW_AT_type')
|
||||
name = prefix + '[]'
|
||||
self.print_DIE(typ, name)
|
||||
load_children(die)
|
||||
|
||||
if die._children:
|
||||
for child in die._children:
|
||||
print(child)
|
||||
self.print_DIE(child, name)
|
||||
|
||||
return
|
||||
elif prefix and die.tag == 'DW_TAG_volatile_type':
|
||||
if 'DW_AT_type' in die.attributes:
|
||||
typ = die.get_DIE_from_attribute('DW_AT_type')
|
||||
self.print_DIE(typ, prefix)
|
||||
return
|
||||
elif prefix and die.tag == 'DW_TAG_typedef':
|
||||
print(die.attributes["DW_AT_name"].value)
|
||||
if 'DW_AT_type' in die.attributes:
|
||||
typ = die.get_DIE_from_attribute('DW_AT_type')
|
||||
name = prefix + '[]'
|
||||
self.print_DIE(typ, name)
|
||||
load_children(die)
|
||||
|
||||
if die._children:
|
||||
for child in die._children:
|
||||
print(child)
|
||||
self.print_DIE(child, name)
|
||||
elif prefix and die.tag == 'DW_TAG_enumeration_type':
|
||||
# print(die.attributes["DW_AT_name"].value)
|
||||
print ("mylittlepony")
|
||||
print(die)
|
||||
if 'DW_AT_type' in die.attributes:
|
||||
typ = die.get_DIE_from_attribute('DW_AT_type')
|
||||
name = prefix
|
||||
self.print_DIE(typ, name)
|
||||
load_children(die)
|
||||
print (typ)
|
||||
elif prefix:
|
||||
print (prefix)
|
||||
print(die)
|
||||
|
||||
if name:
|
||||
if prefix:
|
||||
print (prefix, name)
|
||||
else:
|
||||
print (name)
|
||||
for entry in self.flat_list:
|
||||
print('{address}\t{variable_name}'.format(address=entry['address'], variable_name=entry['name']))
|
||||
|
||||
def parse_location(self, die, attr):
|
||||
di = die.dwarfinfo
|
||||
|
@ -365,13 +288,9 @@ def main():
|
|||
monkeypatch()
|
||||
|
||||
bear = Bear("/home/juraj/projects/Playground_C/build/playground_c")
|
||||
vars = bear.flatten_type()
|
||||
pprint(vars)
|
||||
bear.flatten_type()
|
||||
bear.pretty_print()
|
||||
|
||||
#bear = Bear("main.elf")
|
||||
# bear = Bear("LED_Cube.elf")
|
||||
# bear = Bear("serialplay")
|
||||
pass
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
Loading…
Reference in New Issue
Block a user