def _die_to_function(self, die): while "DW_AT_name" not in die.attributes: if "DW_AT_abstract_origin" in die.attributes: ref_attr = "DW_AT_abstract_origin" elif "DW_AT_specification" in die.attributes: ref_attr = "DW_AT_specification" else: break new_offset = (int(die.attributes[ref_attr].value) + die.cu.cu_offset) die = DIE(cu=die.cu, stream=die.stream, offset=new_offset) if "DW_AT_name" in die.attributes: return die.attributes["DW_AT_name"].value else: return None
def _get_entries(self, dwarfinfo): entries = [] for cu in dwarfinfo.iter_CUs(): first_DIE = DIE(cu=cu, stream=dwarfinfo.debug_info_sec.stream, offset=cu.cu_die_offset) addr_ranges = self._get_DIE_addrs(dwarfinfo, first_DIE) if not addr_ranges: continue for range_entry in addr_ranges: entries.append( ARangeEntry(begin_addr=range_entry.begin_offset, length=range_entry.end_offset - range_entry.begin_offset, info_offset=cu.cu_offset)) return entries
def _iter_DIEs(cu): cu_boundary = cu.cu_offset + cu[ 'unit_length'] + cu.structs.initial_length_field_size() die_offset = cu.cu_die_offset # See CompileUnit._unflatten_tree() parent_stack = [-1] while die_offset < cu_boundary: die = DIE(cu=cu, stream=cu.dwarfinfo.debug_info_sec.stream, offset=die_offset) if not die.is_null(): yield die, parent_stack[-1] if die.has_children: parent_stack.append(die.offset) elif parent_stack: parent_stack.pop() die_offset += die.size
def get_dio_by_pos(self, pos): assert pos >= 0 # Consider sorted array A having no duplicate elements # [..., X, Y, ...], where X < Y, and some element P # If X < P < Y then bisect_left(P) == bisect_right(P) == index(Y) # as described at https://docs.python.org/2/library/bisect.html # IOW, bisection selects right end of the range. Finally, when # P is same as Y, these functions return different results: # bisect_left(P) == index(Y) # bisect_right(P) == index(Y) + 1 # So we use A[bisect_right(pos) - 1] to lookup DIEs. # When looking up CUs, situation is a bit different, since we store # 2-tuples in the array. To make comparisons possible, we should use 1-tuple as a key. # When position to look up matches CU offset, key tuple will be less than element tuple. # So subtracting one will give wrong result. To overcome this, we use negated offsets. # In such case, we want to select the right end, so to lookup CUs we use # A[bisect_right(key)] # bisect_right() is the same as bisect() cu_key = (-pos, ) cu_idx = bisect.bisect(self._cu_pos, cu_key) _, cu = self._cu_pos[cu_idx] if not cu: return die_pos, die_parent_pos = _read_CU(cu) die_idx = bisect.bisect(die_pos, pos) assert die_idx > 0 die_idx -= 1 die_offset = die_pos[die_idx] if die_offset < 0: return # See CompileUnit._parse_DIEs() die = DIE(cu=cu, stream=cu.dwarfinfo.debug_info_sec.stream, offset=die_offset) within_die = die.offset <= pos < die.offset + die.size if not within_die: raise Exception("Position is outside DIE") return DebugInfoObject(self, die, die_parent_pos[die_idx])
def _parse_DIE_at_offset(self, cu, die_offset): die = DIE(cu=cu, stream=cu.dwarfinfo.debug_info_sec.stream, offset=die_offset + cu.cu_offset) return die