def get_microcode(func, maturity): """ Return the mba_t of the given function at the specified maturity. """ mbr = ida_hexrays.mba_ranges_t(func) hf = ida_hexrays.hexrays_failure_t() ml = ida_hexrays.mlist_t() ida_hexrays.mark_cfunc_dirty(func.start_ea) mba = ida_hexrays.gen_microcode(mbr, hf, ml, ida_hexrays.DECOMP_NO_WAIT, maturity) if not mba: print("0x%08X: %s" % (hf.errea, hf.desc())) return None return mba
def show_microcode(): """Generates and displays microcode for an address range. An address range can be a selection of code or that of the current function.""" sel, sea, eea = kw.read_range_selection(None) pfn = ida_funcs.get_func(kw.get_screen_ea()) if not sel and not pfn: return (False, "Position cursor within a function or select range") if not sel and pfn: sea = pfn.start_ea eea = pfn.end_ea addr_fmt = "%016x" if ida_ida.inf_is_64bit() else "%08x" fn_name = (ida_funcs.get_func_name(pfn.start_ea) if pfn else "0x%s-0x%s" % (addr_fmt % sea, addr_fmt % eea)) F = ida_bytes.get_flags(sea) if not ida_bytes.is_code(F): return (False, "The selected range must start with an instruction") text, mmat, mba_flags = ask_desired_maturity() if text is None and mmat is None: return (True, "Cancelled") if not sel and pfn: mbr = hr.mba_ranges_t(pfn) else: mbr = hr.mba_ranges_t() mbr.ranges.push_back(ida_range.range_t(sea, eea)) hf = hr.hexrays_failure_t() ml = hr.mlist_t() mba = hr.gen_microcode(mbr, hf, ml, hr.DECOMP_WARNINGS, mmat) if not mba: return (False, "0x%s: %s" % (addr_fmt % hf.errea, hf.desc())) vp = printer_t() mba.set_mba_flags(mba_flags) mba._print(vp) mcv = microcode_viewer_t() if not mcv.Create( mba, "0x%s-0x%s (%s)" % (addr_fmt % sea, addr_fmt % eea, text), text, fn_name, vp.get_mc()): return (False, "Error creating viewer") mcv.Show() return (True, "Successfully generated microcode for 0x%s..0x%s" % (addr_fmt % sea, addr_fmt % eea))
def collect_xrefs(out, ctx, mop, mlist, du, find_uses): # first collect the references in the current block start = ctx.topins.next if find_uses else ctx.topins.prev; collect_block_xrefs(out, mlist, ctx.blk, start, find_uses) # then find references in other blocks serial = ctx.blk.serial; # block number of the operand bc = du[serial] # chains of that block voff = ida_hexrays.voff_t(mop) ch = bc.get_chain(voff) # chain of the operand if not ch: return # odd for bn in ch: b = ctx.mba.get_mblock(bn) ins = b.head if find_uses else b.tail tmp = ida_hexrays.mlist_t() tmp.add(mlist) collect_block_xrefs(out, tmp, b, ins, find_uses)
if ida_hexrays.get_current_operand(gco): # generate microcode hf = ida_hexrays.hexrays_failure_t() mbr = ida_hexrays.mba_ranges_t(pfn) mba = ida_hexrays.gen_microcode(mbr, hf, None, ida_hexrays.DECOMP_WARNINGS, ida_hexrays.MMAT_PREOPTIMIZED) if mba: merr = mba.build_graph() if merr == ida_hexrays.MERR_OK: ncalls = mba.analyze_calls(ida_hexrays.ACFL_GUESS) if ncalls < 0: print( "%08x: failed to determine some calling conventions", pfn.start_ea) mlist = ida_hexrays.mlist_t() if gco.append_to_list(mlist, mba): ctx = ida_hexrays.op_parent_info_t() mop = mba.find_mop(ctx, ea, gco.is_def(), mlist) if mop: xrefs = ida_pro.eavec_t() ndefs = 0 graph = mba.get_graph() ud = graph.get_ud( ida_hexrays.GC_REGS_AND_STKVARS) du = graph.get_du( ida_hexrays.GC_REGS_AND_STKVARS) if gco.is_use(): collect_xrefs(xrefs, ctx, mop, mlist, ud, False) ndefs = xrefs.size()