def _collect_xrefs_from_func(pfn, ea, out_ref_eas): """Collect cross-references at `ea` in `pfn` that target code/data outside of `pfn`. Save them into `out_ref_eas`.""" for ref_ea in _xref_generator(ea, ida_xref.get_first_cref_from, \ ida_xref.get_next_cref_from): if not ida_funcs.func_contains(pfn, ref_ea): out_ref_eas.add(ref_ea) for ref_ea in _xref_generator(ea, ida_xref.get_first_dref_from, \ ida_xref.get_next_dref_from): if not ida_funcs.func_contains(pfn, ref_ea): out_ref_eas.add(ref_ea)
def data(self, index, role=Qt.DisplayRole): # Check if disabled by the user cursors = self._plugin.config["cursors"] if role == Qt.BackgroundRole and cursors["funcs"]: func_ea = int(index.sibling(index.row(), 2).data(), 16) func = ida_funcs.get_func(func_ea) for user in self._plugin.core.get_users().values(): if ida_funcs.func_contains(func, user["ea"]): r, g, b = StatusWidget.ida_to_python(user["color"]) return QColor(StatusWidget.python_to_qt(r, g, b)) index = self._model.index(index.row(), index.column()) return self._model.data(index, role)
def refresh_pseudocode_view(ea): """Refreshes the pseudocode view in IDA.""" names = ["Pseudocode-%c" % chr(ord("A") + i) for i in range(5)] for name in names: widget = ida_kernwin.find_widget(name) if widget: vu = ida_hexrays.get_widget_vdui(widget) # Check if the address is in the same function func_ea = vu.cfunc.entry_ea func = ida_funcs.get_func(func_ea) if ida_funcs.func_contains(func, ea): vu.refresh_view(True)
def _collect_xrefs_from_func(pfn, ea, out_ref_eas, seg_ref): """Collect cross-references at `ea` in `pfn` that target code/data outside of `pfn`. Save them into `out_ref_eas`.""" global _OPERANDS_NUMS # TODO(pag): Decode instruction at `ea`, iterate over operands, and try # to build up operand-specific refs, using a mechanism similar # to McSema's `get_instruction_references`. Might want to pass # in a boolean argument to tell us if IDA thinks this is an # instruction head. for ref_ea in _xref_generator(ea, seg_ref): if not ida_funcs.func_contains(pfn, ref_ea): out_ref_eas.add(ref_ea) _add_real_xref(ea, ref_ea, out_ref_eas)
def _set_tooltip(self, obj, ev): cursors = self._plugin.config["cursors"] if not cursors["funcs"]: return obj.setToolTip("") index = obj.parent().indexAt(ev.pos()) func_ea = int(index.sibling(index.row(), 2).data(), 16) func = ida_funcs.get_func(func_ea) # Find the corresponding username for name, user in self._plugin.core.get_users().items(): if ida_funcs.func_contains(func, user["ea"]): # Set the tooltip obj.setToolTip(name) break
def node_contained(node): return (ida_funcs.func_contains(func, node.startEA) and ida_funcs.func_contains(func, node.endEA - 1))
def get_function_impl(self, address): """Given an address, return a `Function` instance or raise an `InvalidFunctionException` exception.""" arch = self._arch os = self._os pfn = ida_funcs.get_func(address) if not pfn: pfn = ida_funcs.get_prev_func(address) seg_ref = [None] seg = find_segment_containing_ea(address, seg_ref) # Check this function. if not pfn or not seg: raise InvalidFunctionException( "No function defined at or containing address {:x}".format(address) ) elif ( not ida_funcs.func_contains(pfn, address) and not _is_extern_seg(seg) and not is_imported_table_seg(seg) ): raise InvalidFunctionException( "No function defined at or containing address {:x}".format(address) ) # Reset to the start of the function, and get the type of the function. address = pfn.start_ea tif = ida_typeinf.tinfo_t() if not ida_nalt.get_tinfo(tif, address): if ida_typeinf.GUESS_FUNC_OK != ida_typeinf.guess_tinfo(tif, address): raise InvalidFunctionException( "Can't guess type information for function at address {:x}".format( address ) ) if not tif.is_func(): raise InvalidFunctionException( "Type information at address {:x} is not a function: {}".format( address, tif.dstr() ) ) ftd = ida_typeinf.func_type_data_t() if not tif.get_func_details(ftd): raise InvalidFunctionException( "Could not get function details for function at address {:x}".format( address ) ) # Make sure we can handle the basic signature of the function. This might # not be the final signature that we go with, but it's a good way to make # sure we can handle the relevant types. try: func_type = _get_type(tif, TYPE_CONTEXT_FUNCTION) except UnhandledTypeException as e: raise InvalidFunctionException( "Could not assign type to function at address {:x}: {}".format( address, str(e) ) ) # Get the calling convention. The CC might override `is_variadic`, e.g. how # old style C functions declared as `foo()` actually imply `foo(...)`. cc, is_variadic = _get_calling_convention(arch, os, ftd) if is_variadic: func_type.set_is_variadic() # Go look into each of the parameters and their types. Each parameter may # refer to multiple locations, so we want to split each of those locations # into unique i = 0 max_i = ftd.size() param_list = [] while i < max_i: funcarg = ftd[i] i += 1 arg_type = _get_type(funcarg.type, TYPE_CONTEXT_PARAMETER) arg_type_str = arg_type.serialize(arch, {}) j = len(param_list) _expand_locations(arch, pfn, arg_type, funcarg.argloc, param_list) # If we have a parameter name, then give a name to each of the expanded # locations associated with this parameter. if funcarg.name: if (j + 1) == len(param_list): param_list[-1].set_name(funcarg.name) else: k = j while k < len(param_list): param_list[-1].set_name("{}_{}".format(funcarg.name, k - j)) k += 1 # Build up the list of return values. ret_list = [] ret_type = _get_type(ftd.rettype, TYPE_CONTEXT_RETURN) if not isinstance(ret_type, VoidType): _expand_locations(arch, pfn, ret_type, ftd.retloc, ret_list) func = IDAFunction( arch, address, param_list, ret_list, pfn, ftd.is_noret(), func_type, cc ) self.add_symbol(address, _function_name(address)) return func
def get_function(self, address): """Given an address, return a `Function` instance or raise an `InvalidFunctionException` exception.""" arch = self._arch pfn = ida_funcs.get_func(address) if not pfn: pfn = ida_funcs.get_prev_func(address) # Check this function. if not pfn or not ida_funcs.func_contains(pfn, address): raise InvalidFunctionException( "No function defined at or containing address {:x}".format( address)) # Reset to the start of the function, and get the type of the function. address = pfn.start_ea if address in self._functions: return self._functions[address] tif = ida_typeinf.tinfo_t() if not ida_nalt.get_tinfo(tif, address): ida_typeinf.guess_tinfo(tif, address) if not tif.is_func(): raise InvalidFunctionException( "Type information at address {:x} is not a function: {}". format(address, tif.dstr())) ftd = ida_typeinf.func_type_data_t() if not tif.get_func_details(ftd): raise InvalidFunctionException( "Could not get function details for function at address {:x}". format(address)) # Make sure we can handle the basic signature of the function. This might # not be the final signature that we go with, but it's a good way to make # sure we can handle the relevant types. try: func_type = get_type(tif) except UnhandledTypeException as e: raise InvalidFunctionException( "Could not assign type to function at address {:x}: {}".format( address, str(e))) # Go look into each of the parameters and their types. Each parameter may # refer to multiple locations, so we want to split each of those locations # into unique i = 0 max_i = ftd.size() param_list = [] while i < max_i: funcarg = ftd[i] i += 1 arg_type = get_type(funcarg.type) arg_type_str = arg_type.serialize(arch, {}) j = len(param_list) _expand_locations(arch, pfn, arg_type, funcarg.argloc, param_list) # If we have a parameter name, then give a name to each of the expanded # locations associated with this parameter. if funcarg.name: if (j + 1) == len(param_list): param_list[-1].set_name(funcarg.name) else: k = j while k < len(param_list): param_list[-1].set_name("{}_{}".format( funcarg.name, k - j)) k += 1 # Build up the list of return values. ret_list = [] ret_type = get_type(ftd.rettype) if not isinstance(ret_type, VoidType): _expand_locations(arch, pfn, ret_type, ftd.retloc, ret_list) func = IDAFunction(arch, address, param_list, ret_list, pfn) self._functions[address] = func return func