diff --git a/tools/elf_mem_map b/tools/elf_mem_map index 3bd0f23e5..26694c807 100755 --- a/tools/elf_mem_map +++ b/tools/elf_mem_map @@ -70,6 +70,82 @@ def get_FORM_block1(attr): return v return None + +def get_array_dims(DIE): + array_DIE = get_type_def(DIE, 'DW_TAG_array_type') + if array_DIE is None: + return [] + + array_dim = [] + for range_DIE in array_DIE.iter_children(): + if range_DIE.tag == 'DW_TAG_subrange_type' and \ + 'DW_AT_upper_bound' in range_DIE.attributes: + array_dim.append(range_DIE.attributes['DW_AT_upper_bound'].value + 1) + return array_dim + + +def get_struct_members(DIE, size, expand_structs, struct_gaps): + if not expand_structs or size[0].tag == 'DW_TAG_pointer_type': + return [] + struct_DIE = get_type_def(DIE, 'DW_TAG_structure_type') + if struct_DIE is None: + return [] + + members = [] + for member_DIE in struct_DIE.iter_children(): + if member_DIE.tag == 'DW_TAG_member' and 'DW_AT_name' in member_DIE.attributes: + m_name = member_DIE.attributes['DW_AT_name'].value.decode('ascii') + m_off = get_FORM_block1(member_DIE.attributes['DW_AT_data_member_location']) + m_byte_size = get_type_size(member_DIE)[1] + + # still expand member arrays + m_array_dim = get_array_dims(member_DIE) + + if m_byte_size == 1 and len(m_array_dim) > 1: + # likely string, remove one dimension + m_byte_size *= m_array_dim.pop() + if len(m_array_dim) == 0 or (len(m_array_dim) == 1 and m_array_dim[0] == 1): + # plain entry + members.append(Member(m_name, m_off, m_byte_size)) + elif len(m_array_dim) == 1 and m_byte_size == 1: + # likely string, avoid expansion + members.append(Member(m_name + '[]', m_off, m_array_dim[0])) + else: + # expand array entries + m_array_pos = m_off + m_array_loc = [0] * len(m_array_dim) + while True: + # location index + sfx = '' + for d in range(len(m_array_dim)): + sfx += '[{}]'.format(str(m_array_loc[d]).rjust(len(str(m_array_dim[d]-1)), '0')) + members.append(Member(m_name + sfx, m_array_pos, m_byte_size)) + # advance + if array_inc(m_array_loc, m_array_dim): + break + m_array_pos += m_byte_size + + if struct_gaps and len(members): + # fill gaps in the middle + members = list(sorted(members, key=lambda x: x.off)) + last_end = 0 + for n in range(len(members)): + member = members[n] + if member.off > last_end: + members.append(Member('*UNKNOWN*', last_end, member.off - last_end)) + last_end = member.off + member.size + + if struct_gaps and len(members): + # fill gap at the end + members = list(sorted(members, key=lambda x: x.off)) + last = members[-1] + last_end = last.off + last.size + if size[1] > last_end: + members.append(Member('*UNKNOWN*', last_end, byte_size - last_end)) + + return members + + def get_elf_globals(path, expand_structs, struct_gaps=True): fd = open(path, "rb") if fd is None: @@ -121,78 +197,10 @@ def get_elf_globals(path, expand_structs, struct_gaps=True): byte_size = size[1] # fetch array dimensions (if known) - array_dim = [] - array_DIE = get_type_def(DIE, 'DW_TAG_array_type') - if array_DIE is not None: - for range_DIE in array_DIE.iter_children(): - if range_DIE.tag == 'DW_TAG_subrange_type' and \ - 'DW_AT_upper_bound' in range_DIE.attributes: - array_dim.append(range_DIE.attributes['DW_AT_upper_bound'].value + 1) + array_dim = get_array_dims(DIE) # fetch structure members (one level only) - members = [] - if expand_structs and size[0].tag != 'DW_TAG_pointer_type': - struct_DIE = get_type_def(DIE, 'DW_TAG_structure_type') - if struct_DIE is not None: - for member_DIE in struct_DIE.iter_children(): - if member_DIE.tag == 'DW_TAG_member' and 'DW_AT_name' in member_DIE.attributes: - m_name = member_DIE.attributes['DW_AT_name'].value.decode('ascii') - m_off = get_FORM_block1(member_DIE.attributes['DW_AT_data_member_location']) - m_byte_size = get_type_size(member_DIE)[1] - - # still expand member arrays - m_array_dim = [] - m_array_DIE = get_type_def(member_DIE, 'DW_TAG_array_type') - if m_array_DIE is not None: - for range_DIE in m_array_DIE.iter_children(): - if range_DIE.tag == 'DW_TAG_subrange_type' and \ - 'DW_AT_upper_bound' in range_DIE.attributes: - m_array_dim.append(range_DIE.attributes['DW_AT_upper_bound'].value + 1) - - if m_byte_size == 1 and len(m_array_dim) > 1: - # likely string, remove one dimension - m_byte_size *= m_array_dim.pop() - if len(m_array_dim) == 0 or (len(m_array_dim) == 1 and m_array_dim[0] == 1): - # plain entry - members.append(Member(m_name, m_off, m_byte_size)) - elif len(m_array_dim) == 1 and m_byte_size == 1: - # likely string, avoid expansion - members.append(Member(m_name + '[]', m_off, m_array_dim[0])) - else: - # expand array entries - m_array_pos = m_off - m_array_loc = [0] * len(m_array_dim) - while True: - # location index - sfx = '' - for d in range(len(m_array_dim)): - sfx += '[{}]'.format(str(m_array_loc[d]).rjust(len(str(m_array_dim[d]-1)), '0')) - - members.append(Member(m_name + sfx, m_array_pos, m_byte_size)) - - # advance - if array_inc(m_array_loc, m_array_dim): - break - m_array_pos += m_byte_size - - if struct_gaps and len(members): - # fill gaps in the middle - members = list(sorted(members, key=lambda x: x.off)) - last_end = 0 - for n in range(len(members)): - member = members[n] - if member.off > last_end: - members.append(Member('*UNKNOWN*', last_end, member.off - last_end)) - last_end = member.off + member.size - - if struct_gaps and len(members): - # fill gap at the end - members = list(sorted(members, key=lambda x: x.off)) - last = members[-1] - last_end = last.off + last.size - if byte_size > last_end: - members.append(Member('*UNKNOWN*', last_end, byte_size - last_end)) - + members = get_struct_members(DIE, size, expand_structs, struct_gaps) def expand_members(entry, members): if len(members) == 0: