Exemple #1
0
 def analyze_die_TAG_type_qualifier(self, die: DIE, tag: type_info.TAG):
     # type_info取得
     type_inf = self.new_type_info(die.offset, tag)
     # 情報取得
     for at in die.attributes.keys():
         attr: AttributeValue = die.attributes[at]
         if at == "DW_AT_name":
             type_inf.name = attr.value.decode(self._encoding)
         elif at == "DW_AT_type":
             type_inf.child_type = self.analyze_die_AT_FORM(
                 attr.form, attr.value)
         elif at == "DW_AT_address_class":
             type_inf.address_class = self.analyze_die_AT_FORM(
                 attr.form, attr.value)
             self.register_address_class(type_inf)
         elif at == "DW_AT_count":
             pass
         else:
             if self._debug_warning:
                 print("unknown attr: " + at)
     # child check
     if die.has_children:
         child: DIE
         for child in die.iter_children():
             if self._debug_warning:
                 print("unproc child.")
Exemple #2
0
 def analyze_die_TAG_typedef(self, die: DIE):
     # type_info取得
     type_inf = self.new_type_info(die.offset,
                                   utilDwarf.type_info.TAG.typedef)
     # 情報取得
     for at in die.attributes.keys():
         attr: AttributeValue = die.attributes[at]
         if at == "DW_AT_name":
             type_inf.name = attr.value.decode(self._encoding)
         elif at == "DW_AT_type":
             type_inf.child_type = self.analyze_die_AT_FORM(
                 attr.form, attr.value)
         elif at == "DW_AT_decl_file":
             file_no = self.analyze_die_AT_FORM(attr.form, attr.value)
             type_inf.decl_file = self._cu_info.file_list[file_no]
         elif at == "DW_AT_decl_line":
             type_inf.decl_line = self.analyze_die_AT_FORM(
                 attr.form, attr.value)
         else:
             if self._debug_warning:
                 print("typedef:?:" + at)
     # child check
     if die.has_children:
         child: DIE
         for child in die.iter_children():
             if self._debug_warning:
                 print("unproc child.")
Exemple #3
0
 def analyze_die_TAG_array_type(self, die: DIE):
     # type_info取得
     type_inf = self.new_type_info(die.offset,
                                   utilDwarf.type_info.TAG.array)
     # Attr check
     for at in die.attributes.keys():
         attr: AttributeValue = die.attributes[at]
         if at == "DW_AT_type":
             type_inf.child_type = self.analyze_die_AT_FORM(
                 attr.form, attr.value)
         elif at == "DW_AT_allocated":
             pass
         elif at == "DW_AT_associated":
             pass
         elif at == "DW_AT_data_location":
             pass
         else:
             if self._debug_warning:
                 print("array:?:" + at)
     # child check
     if die.has_children:
         for child in die.iter_children():
             if child.tag == "DW_TAG_subrange_type":
                 # Attr check
                 for at in child.attributes.keys():
                     attr: AttributeValue = child.attributes[at]
                     if at == "DW_AT_count":
                         type_inf.range = self.analyze_die_AT_FORM(
                             attr.form, attr.value)
             elif child.tag == "DW_TAG_enumeration_type":
                 pass
 def process_imported_units(self, unit_die: DIE):
   """Include nested partial units.
   """
   # self._logger.debug(f'Importing unit at {unit_die.cu.cu_offset}')
   for child in unit_die.iter_children():
     if child.tag == 'DW_TAG_imported_unit':
       imported_unit_die = self.get_attr_as_die(child, 'DW_AT_import')
       if imported_unit_die is not None:
         self.process_imported_units(imported_unit_die)
Exemple #5
0
    def __init__(self, die: DIE):
        super().__init__(die)
        self.die = die

        self.parameters = []
        for child in die.iter_children():
            if die.tag != 'DW_TAG_formal_parameter':
                continue
            self.parameters.append(die.attributes['DW_AT_type'].value)
Exemple #6
0
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 import_from_compile_unit(self, die: DIE, component: Component):
   for child in die.iter_children():
     if child.tag == 'DW_TAG_subprogram':
       if self._include_subprograms:
         self.import_subprogram(child, component)
     elif child.tag == 'DW_TAG_variable':
       if self._include_variables:
         self.import_global_variable(child, component)
     elif child.tag == 'DW_TAG_imported_declaration':
       if self._include_imports:
         self.import_imported_declaration(child)
     elif child.tag in [
         'DW_TAG_namespace',
         'DW_TAG_class_type',
         'DW_TAG_interface_type',
         'DW_TAG_structure_type',
         'DW_TAG_union_type'
     ]:
       self.import_from_compile_unit(child, component)
     elif child.tag == 'DW_TAG_module' and 'DW_AT_declaration' in child.attributes:
       pass
     elif child.tag in [
         'DW_TAG_imported_unit',
         'DW_TAG_typedef',
         'DW_TAG_unspecified_type',
         'DW_TAG_base_type',
         'DW_TAG_const_type',
         'DW_TAG_volatile_type',
         'DW_TAG_restrict_type',
         'DW_TAG_array_type',
         'DW_TAG_enumeration_type',
         'DW_TAG_pointer_type',
         'DW_TAG_reference_type',
         'DW_TAG_ptr_to_member_type',
         'DW_TAG_subroutine_type',
         'DW_TAG_rvalue_reference_type',
         'DW_TAG_subrange_type',
         'DW_TAG_string_type',
         'DW_TAG_member',
         'DW_TAG_inheritance',
         'DW_TAG_template_type_param',
         'DW_TAG_template_value_param',
         'DW_TAG_GNU_template_template_param',
         'DW_TAG_GNU_template_parameter_pack',
         'DW_TAG_imported_module',
         'DW_TAG_imported_declaration',
         'DW_TAG_dwarf_procedure',
         'DW_TAG_constant'
     ]:
       pass
     else:
       print(child.tag, '(child tag)')
Exemple #8
0
 def analyze_die_TAG_subprogram(self, die: DIE):
     f_inf: utilDwarf.func_info = None
     if "DW_AT_external" in die.attributes.keys():
         # 関数
         self._func_tbl.append(utilDwarf.func_info())
         f_inf = self._func_tbl[len(self._func_tbl) - 1]
     else:
         # ?
         return
     # AT取得
     call_convention = 1  # デフォルトがDW_CC_normal
     for at in die.attributes.keys():
         attr: AttributeValue = die.attributes[at]
         if at == "DW_AT_external":
             pass
         elif at == "DW_AT_name":
             f_inf.name = die.attributes[at].value.decode(self._encoding)
         elif at == "DW_AT_type":
             f_inf.return_type = self.analyze_die_AT_FORM(
                 attr.form, attr.value)
         elif at == "DW_AT_calling_convention":
             call_convention = die.attributes[at].value
         elif at == "DW_AT_decl_file":
             file_no = self.analyze_die_AT_FORM(attr.form, attr.value)
             f_inf.decl_file = self._cu_info.file_list[file_no]
         elif at == "DW_AT_decl_line":
             f_inf.decl_line = self.analyze_die_AT_FORM(
                 attr.form, attr.value)
         elif at == "DW_AT_low_pc":
             pass
         elif at == "DW_AT_high_pc":
             pass
         elif at == "DW_AT_frame_base":
             pass
         elif at == "DW_AT_return_addr":
             pass
         else:
             if self._debug_warning:
                 print("subprogram:?:" + at)
     # child check
     if die.has_children:
         child: DIE
         for child in die.iter_children():
             if child.tag == "DW_TAG_formal_parameter":
                 param_inf = self.analyze_parameter(child)
                 f_inf.params.append(param_inf)
             elif child.tag == "DW_TAG_unspecified_parameters":
                 param_inf = self.analyze_parameter(child)
                 f_inf.params.append(param_inf)
             elif child.tag == "DW_TAG_variable":
                 pass
Exemple #9
0
 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
Exemple #10
0
    def __init__(self, die: DIE):
        super().__init__(die)

        self.name = '<unnamed-union>'
        if 'DW_AT_name' in die.attributes:
            self.name = die.attributes['DW_AT_name'].value.decode('utf-8')

        self.byte_size = die.attributes['DW_AT_byte_size'].value

        self.variants = OrderedDict()
        for variant in die.iter_children():
            assert variant.tag == 'DW_TAG_member'
            name = variant.attributes['DW_AT_name'].value.decode('utf-8')
            value = variant.attributes['DW_AT_type'].value
            self.variants[name] = value
Exemple #11
0
 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
Exemple #12
0
 def analyze_die_TAG_structure_union_type_impl_child(
         self, die: DIE, type_inf: type_info):
     for child in die.iter_children():
         if child.tag == "DW_TAG_member":
             #type_inf.member.append(utilDwarf.type_info())
             #mem_inf = type_inf.member[len(type_inf.member)-1]
             #self.analyze_die_TAG_member(child, mem_inf)
             mem_inf = self.analyze_die_TAG_member(child)
             type_inf.member.append(mem_inf)
         elif child.tag == "DW_TAG_array_type":
             # struct/union/class内で使う型の定義
             # よって, member要素ではない
             self.analyze_die_TAG_array_type(child)
         else:
             # ありえないパス
             if self._debug_warning:
                 print("?: " + child.tag)
Exemple #13
0
 def analyze_die_TAG_variable(self, die: DIE):
     var = utilDwarf.var_info()
     # AT解析
     for at in die.attributes.keys():
         attr = die.attributes[at]
         if at == "DW_AT_external":
             var.extern = self.analyze_die_AT_FORM(attr.form, attr.value)
         elif at == "DW_AT_name":
             var.name = die.attributes[at].value.decode(self._encoding)
         elif at == "DW_AT_decl_file":
             file_no = self.analyze_die_AT_FORM(attr.form, attr.value)
             # ファイル情報取得
             var.decl_file = self._cu_info.file_list[file_no]
             # ファイルが現在解析中のものでない
             if file_no != 1:
                 var.external_file = True
         elif at == "DW_AT_decl_line":
             var.decl_line = self.analyze_die_AT_FORM(attr.form, attr.value)
         elif at == "DW_AT_type":
             var.type = die.attributes[at].value
         elif at == "DW_AT_location":
             self.analyze_die_AT_location(var, die.attributes[at])
         elif at == "DW_AT_declaration":
             var.not_declaration = self.analyze_die_AT_FORM(
                 attr.form, attr.value)
         elif at == "DW_AT_const_value":
             pass
         else:
             if self._debug_warning:
                 print("variable:?:" + at)
     # child check
     if die.has_children:
         child: DIE
         for child in die.iter_children():
             if self._debug_warning:
                 print("unproc child.")
     # 変数登録
     if var.addr is not None:
         # アドレスを持っているとき
         # グローバル変数
         self._global_var_tbl.append(var)
     else:
         # アドレスを持たない
         # ローカル変数, 定数, etc
         pass
Exemple #14
0
 def get_array_count(self, die: DIE) -> Optional[int]:
   for d in die.iter_children():
     if d.tag == 'DW_TAG_subrange_type':
       if 'DW_AT_count' in d.attributes:
         return d.attributes['DW_AT_count'].value
       if 'DW_AT_upper_bound' in d.attributes:
         upper_bound = d.attributes['DW_AT_upper_bound']
         if upper_bound.form == 'DW_FORM_exprloc':
           return None
         if upper_bound.form in DWARFDB.REFERENCE_FORMS:
           return None
         ub = upper_bound.value
         if 'DW_AT_lower_bound' in d.attributes:
           lb = d.attributes['DW_AT_lower_bound'].value
           return ub - lb
         assert(isinstance(ub, int))
         return ub + 1  # TODO: assuming zero-based, but need to know for sure
   return None
Exemple #15
0
    def analyze_die_TAG_member(self, die: DIE) -> type_info:
        # type_info取得
        type_inf = self.new_type_info(die.offset, None)
        # type要素追加
        idx = die.offset
        for at in die.attributes.keys():
            attr: AttributeValue = die.attributes[at]
            if at == "DW_AT_name":
                type_inf.name = attr.value.decode(self._encoding)
            elif at == "DW_AT_type":
                type_inf.child_type = self.analyze_die_AT_FORM(
                    attr.form, attr.value)
            elif at == "DW_AT_data_member_location":
                type_inf.member_location = self.analyze_die_AT_FORM(
                    attr.form, attr.value)
            elif at == "DW_AT_byte_size":
                type_inf.byte_size = self.analyze_die_AT_FORM(
                    attr.form, attr.value)
            elif at == "DW_AT_bit_offset":
                type_inf.bit_offset = self.analyze_die_AT_FORM(
                    attr.form, attr.value)
            elif at == "DW_AT_bit_size":
                type_inf.bit_size = self.analyze_die_AT_FORM(
                    attr.form, attr.value)
            elif at == "DW_AT_decl_file":
                file_no = self.analyze_die_AT_FORM(attr.form, attr.value)
                type_inf.decl_file = self._cu_info.file_list[file_no]
            elif at == "DW_AT_decl_line":
                type_inf.decl_line = self.analyze_die_AT_FORM(
                    attr.form, attr.value)
            else:
                if self._debug_warning:
                    print("unknown attribute detected: " + at)
        # child check
        if die.has_children:
            for child in die.iter_children():
                pass
        # debug comment
#		print("    DIE tag   : " + die.tag)
#		print("        offset: " + str(die.offset))
#		print("        name  : " + type_inf.name)
#		print("        type  : " + str(type_inf.typedef))
#		print("        memloc: " + str(type_inf.member_location))
        return type_inf
Exemple #16
0
    def __init__(self, die: DIE):
        super().__init__(die)

        self.name = '<unnamed-enum>'
        if 'DW_AT_name' in die.attributes:
            self.name = die.attributes['DW_AT_name'].value.decode('utf-8')

        self.literals = OrderedDict()
        for lit in die.iter_children():
            assert lit.tag == 'DW_TAG_enumerator'
            name = lit.attributes['DW_AT_name'].value.decode('utf-8')
            value = lit.attributes['DW_AT_const_value'].value
            self.literals[name] = value

        if 'DW_AT_type' in die.attributes:
            self.item_type = die.attributes['DW_AT_type'].value
        else:
            # Probably `void`
            assert False, 'TODO'
Exemple #17
0
    def __init__(self, die: DIE):
        global no_matrices
        super().__init__(die)

        self.item_type = die.attributes['DW_AT_type'].value

        self.dimensions = []
        self.is_vla = False
        for c in die.iter_children():
            # This attribute is usually missing in VLAs (TODO: Not supported currently)
            if 'DW_AT_upper_bound' in c.attributes:
                dimension = c.attributes['DW_AT_upper_bound'].value + 1

                if no_matrices and len(self.dimensions) > 0:
                    self.dimensions[0] = self.dimensions[0] * dimension
                else:
                    self.dimensions.append(dimension)
            else:
                assert self.is_vla is False
                self.is_vla = True
Exemple #18
0
 def analyze_die_TAG_subroutine_type(self, die: DIE):
     # type_info取得
     type_inf = self.new_type_info(die.offset, utilDwarf.type_info.TAG.func)
     for at in die.attributes.keys():
         if at == "DW_AT_name":
             type_inf.name = die.attributes[at].value.decode(self._encoding)
         elif at == "DW_AT_type":
             # 返り値型
             type_inf.result_type = die.attributes[at].value
         elif at == "DW_AT_prototyped":
             type_inf.prototyped = die.attributes[at].value
         else:
             if self._debug_warning:
                 print("subroutine_type:?:" + at)
     # child check
     if die.has_children:
         child: DIE
         for child in die.iter_children():
             param_inf = self.analyze_parameter(child)
             type_inf.params.append(param_inf)
Exemple #19
0
    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])
Exemple #20
0
 def analyze_die_TAG_base_type(self, die: DIE):
     # type_info取得
     type_inf = self.new_type_info(die.offset, utilDwarf.type_info.TAG.base)
     for at in die.attributes.keys():
         attr: AttributeValue = die.attributes[at]
         if at == "DW_AT_name":
             type_inf.name = self.analyze_die_AT_FORM(attr.form, attr.value)
         elif at == "DW_AT_encoding":
             type_inf.encoding = self.analyze_die_AT_FORM(
                 attr.form, attr.value)
         elif at == "DW_AT_byte_size":
             type_inf.byte_size = self.analyze_die_AT_FORM(
                 attr.form, attr.value)
         else:
             if self._debug_warning:
                 print("base_type:?:" + at)
     # child check
     if die.has_children:
         child: DIE
         for child in die.iter_children():
             if self._debug_warning:
                 print("unproc child.")
Exemple #21
0
    def __init__(self, die: DIE):
        super().__init__(die)

        self.name = None
        if 'DW_AT_name' in die.attributes:
            self.name = die.attributes['DW_AT_name'].value.decode('utf-8')

        self.byte_size = 0
        if 'DW_AT_byte_size' in die.attributes:
            self.byte_size = die.attributes['DW_AT_byte_size'].value

        self.members = []
        for c in die.iter_children():
            if c.tag not in ['DW_TAG_member', 'DW_TAG_inheritance']:
                continue

            member_offset = c.attributes['DW_AT_data_member_location'].value
            type_num = c.attributes['DW_AT_type'].value
            if 'DW_AT_name' in c.attributes:
                member_name = c.attributes['DW_AT_name'].value.decode(
                    'utf-8') if c.tag == 'DW_TAG_member' else '<base>'
            else:
                member_name = '<unnamed>'
            self.members.append((member_offset, type_num, member_name))
Exemple #22
0
 def read_die_rec(self, die: DIE) -> None:
     self.all_dies[die.offset] = die
     for child in die.iter_children():
         self.read_die_rec(child)
Exemple #23
0
  def _make_user_type_helper(self, type_die: DIE, alias: Optional[str] = None, visited = None) -> Type:
    """Create a type object to represent the DWARF type.
    """
    if type_die in self._defined_types:
      return self._defined_types[type_die]

    if type_die is None:
      return self._defined_types.setdefault(None, Type.void())

    # Detect cycles in the DIE structures.
    if type_die in visited:
      return Type.void()
    visited.append(type_die)

    if type_die.tag == 'DW_TAG_base_type':
      base_type = Type(scalar_type=ScalarType.BASE_TYPE, name=self.name_of(type_die), size=size_of(type_die))
      self._base_types[base_type.name] = base_type
      return self._defined_types.setdefault(type_die, base_type)

    elif type_die.tag == 'DW_TAG_unspecified_type':
      unspecified_type = Type(scalar_type=ScalarType.BASE_TYPE, name=self.name_of(type_die))
      return self._defined_types.setdefault(type_die, unspecified_type)

    elif type_die.tag == 'DW_TAG_typedef':
      qualified_alias = self._dwarf_db.get_qualified_name(type_die)
      aliased_type_die = self._dwarf_db.get_type_attr_as_die(type_die)
      if type_die:
        element_type = self._make_user_type_helper(aliased_type_die, alias=qualified_alias, visited=visited)
      else:
        element_type = Type.void()
      if element_type.name == qualified_alias:
        return element_type
      else:
        alias = Type(name=qualified_alias, element=element_type)
        return self._defined_types.setdefault(type_die, alias)

    elif type_die.tag in ['DW_TAG_const_type', 'DW_TAG_volatile_type']:
      if has_type(type_die):
        try:
          element_type = self._make_user_type_helper(self.type_of(type_die), visited=visited)
        except Exception as e:
          self._logger.error(str(e))
          raise e
      else:
        element_type = Type.void()
      qualified_type = Type(element=element_type)
      if type_die.tag == 'DW_TAG_const_type':
        qualified_type.is_constant = True
      elif type_die.tag == 'DW_TAG_volatile_type':
        qualified_type.is_volatile = True
      return self._defined_types.setdefault(type_die, qualified_type)

    elif type_die.tag in ['DW_TAG_pointer_type', 'DW_TAG_reference_type', 'DW_TAG_rvalue_reference_type']:
      if has_type(type_die):
        element_type = self._make_user_type_helper(self.type_of(type_die), visited=visited)
      else:
        element_type = Type.void()
      pointer_size = size_of(type_die) if has_size(type_die) else None
      pointer_type = Type(element=element_type, size=pointer_size)
      if type_die.tag == 'DW_TAG_pointer_type':
        pointer_type.scalar_type = ScalarType.POINTER_TYPE
      elif type_die.tag == 'DW_TAG_reference_type':
        pointer_type.scalar_type = ScalarType.REFERENCE_TYPE
      elif type_die.tag == 'DW_TAG_class_type':
        pointer_type.scalar_type = ScalarType.RVALUE_REFERENCE_TYPE
      elif type_die.tag == 'DW_TAG_interface_type':
        pointer_type.scalar_type = ScalarType.RVALUE_REFERENCE_TYPE
      if has_name(type_die):
        # Create a type alias and return that.
        alias_type = Type(name=self.name_of(type_die), element=pointer_type)
        return self._defined_types.setdefault(type_die, alias_type)
      else:
        return self._defined_types.setdefault(type_die, pointer_type)

    elif type_die.tag in ['DW_TAG_structure_type', 'DW_TAG_class_type', 'DW_TAG_union_type', 'DW_TAG_interface_type']:
      composite_name = self.get_type_name(type_die, alias)
      composite_size = size_of(type_die) if has_size(type_die) else None
      composite_type = Type(name=composite_name, size=composite_size)
      if type_die.tag == 'DW_TAG_structure_type':
        composite_type.composite_type = CompositeType.STRUCT_TYPE
      elif type_die.tag == 'DW_TAG_union_type':
        composite_type.composite_type = CompositeType.UNION_TYPE
      elif type_die.tag == 'DW_TAG_class_type':
        composite_type.composite_type = CompositeType.CLASS_TYPE
      elif type_die.tag == 'DW_TAG_interface_type':
        composite_type.composite_type = CompositeType.CLASS_TYPE
      forward_type = Type(name=composite_name, size=composite_size)
      forward_type.composite_type = composite_type.composite_type
      self._defined_types[type_die] = forward_type
      for member_die in type_die.iter_children():
        if member_die.tag == 'DW_TAG_member':
          if not has_type(member_die):
            print(member_die)
          member_type = self._make_user_type_helper(self.type_of(member_die), visited=visited)
          if member_type.name is None:
            member_type = member_type.clone()
          member_offset = member_offset_of(member_die) if has_member_offset(member_die) else 0
          if member_offset is not None:
            if has_name(member_die):
              composite_type.add_member(Type(name=self.name_of(member_die), offset=member_offset, element=member_type))
            else:
              composite_type.add_member(Type(offset=member_offset, element=member_type))
          else:
            if 'DW_AT_const_value' in member_die.attributes:
              # TODO: add constant
              pass
            else:
              # TODO: must be static
              pass
        elif member_die.tag == 'DW_TAG_inheritance':
          member_type_die = self.type_of(member_die)
          member_type = self._make_user_type_helper(member_type_die, visited=visited)
          member_offset = member_offset_of(member_die) if has_member_offset(member_die) else 0
          base_name = 'inherited$'
          if has_name(member_type_die):
            base_name = f'inherited${self.name_of(member_type_die)}'
          composite_type.add_member(Type(name=base_name, offset=member_offset, element=member_type))
        elif member_die.tag == 'DW_TAG_variant_part':
          # TODO: implement
          pass
      self._defined_types[type_die] = composite_type
      return composite_type

    elif type_die.tag in ['DW_TAG_enumeration_type']:
      enum_name = self.get_type_name(type_die, alias)
      enum_size = size_of(type_die) if has_size(type_die) else None
      enum_type = Type(composite_type=CompositeType.ENUM_TYPE, name=enum_name, size=enum_size)
      for member_die in type_die.iter_children():
        if member_die.tag == 'DW_TAG_enumerator':
          offset = member_die.attributes['DW_AT_const_value'].value
          enum_type.add_member(Type(scalar_type=ScalarType.ENUMERATOR_TYPE, name=self.name_of(member_die), offset=offset))
      return self._defined_types.setdefault(type_die, enum_type)

    elif type_die.tag == 'DW_TAG_subroutine_type':
      function_name = self.get_type_name(type_die, alias)
      if has_type(type_die):
        return_type = self._make_user_type_helper(self.type_of(type_die), visited=visited)
      else:
        return_type = Type.void()
      function_type = Type(composite_type=CompositeType.FUNCTION_TYPE, name=function_name, element=return_type)
      ordinal = 0
      for param_die in type_die.iter_children():
        if param_die.tag == 'DW_TAG_formal_parameter':
          param_type = self._make_user_type_helper(self.type_of(param_die), visited=visited)
          function_type.add_member(Type(offset=ordinal, element=param_type))
          ordinal += 1
        elif param_die.tag == 'DW_TAG_unspecified_parameters':
          function_type.add_member(Type(offset=ordinal, element=Type.variadic()))
          ordinal += 1
        else:
          self._logger.warning(f'While defining subroutine type "{function_name}", encountered an unhandled tag "{param_die.tag}"')
      return self._defined_types.setdefault(type_die, function_type)

    elif type_die.tag == 'DW_TAG_array_type':
      array_name = self.get_type_name(type_die, alias)
      element_type = self._make_user_type_helper(self._dwarf_db.get_type_attr_as_die(type_die), visited=visited)
      array_count = self._dwarf_db.get_array_count(type_die)
      array_type = Type(scalar_type=ScalarType.ARRAY_TYPE, name=array_name, element=element_type, array_count=array_count)
      return self._defined_types.setdefault(type_die, array_type)

    elif type_die.tag in ['DW_TAG_restrict_type']:
      return self._make_user_type_helper(self._dwarf_db.get_type_attr_as_die(type_die), visited=visited)

    elif type_die.tag in ['DW_TAG_ptr_to_member_type']:
      p2m_name = self.get_type_name(type_die, alias)
      if has_type(type_die):
        member_type = self._make_user_type_helper(self._dwarf_db.get_type_attr_as_die(type_die), visited=visited)
      else:
        member_type = Type.void()
      if 'DW_AT_containing_type' in type_die.attributes:
        containing_die = self._dwarf_db.get_attr_as_die(type_die, 'DW_AT_containing_type')
        containing_type = self._make_user_type_helper(containing_die, visited=visited)
      else:
        containing_type = Type.void()
      p2m_type = Type(composite_type=CompositeType.PTR_TO_MEMBER_TYPE, name=p2m_name)
      p2m_type.add_member(containing_type)
      p2m_type.add_member(member_type)
      return p2m_type

    elif type_die.tag == 'DW_TAG_string_type':
      assert('DW_AT_type' not in type_die.attributes)
      if 'char' not in self._base_types:
        char_type = Type(scalar_type=ScalarType.BASE_TYPE, name='char', size=1)
        self._base_types[char_type.name] = char_type
      else:
        char_type = self._base_types['char']

      if 'DW_AT_byte_size' in type_die.attributes:
        # Treat it as a char array of fixed length.
        size = type_die.attributes['DW_AT_byte_size'].value
        array_type = Type(scalar_type=ScalarType.ARRAY_TYPE, element=char_type, array_count=size)
        return self._defined_types.setdefault(type_die, array_type)
      else:
        # Treat it a char *.
        cptr_type = Type(scalar_type=ScalarType.POINTER_TYPE, element=char_type)
        return self._defined_types.setdefault(type_die, cptr_type)

    elif type_die.tag == 'DW_TAG_subrange_type':
      assert('DW_AT_type' in type_die.attributes)
      return self._make_user_type_helper(self._dwarf_db.get_type_attr_as_die(type_die), visited=visited)

    elif type_die.tag == 'DW_TAG_variant_part':
      return None

    else:
      print(type_die)
      assert(type_die and False)
Exemple #24
0
  def import_local_elements(self, die: DIE, component: Component, function: Function, parent_function: Function, inside_lexical_block: bool = False, location_map = None, abstract_map=None):
    """Imports function elements.

    Notes
    -----
    Local variables can share locations with the formal parameters. For
    example, opaque parameters that are simply type cast to a structure
    pointer occur quite often.  In these cases, we want the local variable
    to take priority over the parameter.  If a variable shares a Location
    with a parameter, that location will be removed from the parameter's
    location list.  In short, the variable hides the parameter at that
    location.

    Also, inlined functions may have parameters or local variables that
    share locations with the containing function's variables and/or
    parameters.  Thus, if the type stored at the location differs from
    the containing function, we use the most specific type - the local
    hides the pre-existing variable from that location.  But if the name
    of the variable or parameter is "artificial" then the artificial
    name is replaced/inherited from the variable that shares the location.
    """
    for child in die.iter_children():
      if child.tag == 'DW_TAG_variable':
        if self._include_local_variables:
          if self._dwarf_db.is_concrete_variable(child):
            local_var = self.import_local_variable(child, component, function, abstract_map)
            if local_var:
              # print(self._dwarf_db.is_concrete_variable(die), child)
              self.import_locations(local_var, child, location_map, [LocationType.STATIC_LOCAL, LocationType.STATIC_GLOBAL])
          # else:
          #     self._logger.warning(f'In {function.name} variable is not concrete\n{child}')
      elif child.tag == 'DW_TAG_formal_parameter':
        if self._include_parameters:
          param = self.import_parameter(child, function, parent_function, abstract_map)
          if param:
            self.import_locations(param, child, location_map, [LocationType.STATIC_LOCAL])
      elif child.tag == 'DW_TAG_unspecified_parameters':
        p = Parameter(name='...', type=None)
        function.add_parameter(p)
      elif child.tag == 'DW_TAG_lexical_block':
        self.import_local_elements(child, component, function, parent_function, inside_lexical_block=True, location_map=location_map, abstract_map=abstract_map)
      elif child.tag == 'DW_TAG_inlined_subroutine':
        if self._include_inlined_functions:
          f = self.import_inlined_subroutine(child, component, function if parent_function is None else parent_function, location_map, abstract_map)
          function.add_inlined_function(f)
      elif child.tag == 'DW_TAG_subprogram':
        if self._dwarf_db.is_concrete_subprogram(child):
          self._logger.warning(f'In {function.name} a concrete subprogram inside subprogram\n{child}')
        else:
          pass
      elif child.tag in [
          'DW_TAG_template_type_parameter',
          'DW_TAG_template_type_param',
          'DW_TAG_template_value_param',
          'DW_TAG_GNU_formal_parameter_pack',
          'DW_TAG_GNU_template_parameter_pack',
          'DW_TAG_GNU_call_site',
          'DW_TAG_label',
          'DW_TAG_imported_declaration',
          'DW_TAG_constant',
          # Types are picked up via the variables, as needed.
          'DW_TAG_typedef',
          'DW_TAG_structure_type',
          'DW_TAG_union_type',
          'DW_TAG_class_type',
          'DW_TAG_interface_type',
          'DW_TAG_const_type',
          'DW_TAG_pointer_type',
          'DW_TAG_enumeration_type'
      ]:
        # TODO: use DW_TAG_label to inform control-flow reconstruction
        pass
      else:
        self._logger.warning(f'unhandled tag {child.tag} inside {die.tag}\n\tParent DIE = {die}\n\tChild DIE  = {child}')
Exemple #25
0
 def read_die_rec(self, die: DIE) -> None:
     self.all_dies[die.offset] = die
     for child in die.iter_children():
         self.read_die_rec(child)
Exemple #26
0
 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