//---------------------------------------------------------------------- bool create_func_frame(func_t *pfn) // create frame of newly created function { bool std_vars_func = true; if ( pfn != NULL ) { if ( pfn->frame == BADNODE ) { ea_t ea = pfn->startEA; int regsize = 0; while (ea < pfn->endEA) // check for register pushs { decode_insn(ea); ea += cmd.size; // считаем кол-во push if ( (cmd.itype == OAK_Dsp_push) && (cmd.Op1.type == o_reg) ) regsize++; else break; } ea = pfn->startEA; int16 localsize = 0; while (ea < pfn->endEA) // check for frame creation { decode_insn(ea); ea += cmd.size; // Попытка определить команду типа ADDV #,SP if ( (cmd.itype == OAK_Dsp_addv) && (cmd.Op1.type == o_imm) && (cmd.Op2.type == o_reg) && (cmd.Op2.reg == SP) ) { localsize = (uint16)cmd.Op1.value; break; } // Если встретили команду mov #, rb --> не надо создавать фрейм такой ф-ции, и объявлять локальные переменные if ( (cmd.itype == OAK_Dsp_mov) && (cmd.Op1.type == o_imm) && (cmd.Op2.type == o_reg) && (cmd.Op2.reg == RB) ) { std_vars_func = false; break; } } if (std_vars_func) { pfn->flags |= FUNC_FRAME; update_func(pfn); } add_frame(pfn, -localsize, (ushort)regsize, 0); } } return 0; }
int get_disasm(ea_t addr, char *buf, int bufsz) { char mnem[32]; char *ptr = buf; decode_insn(addr); ua_mnem(addr, mnem, sizeof(mnem) - 1); qsnprintf(buf, bufsz - 1, "%08x: %-5s ", addr, mnem); ptr += strlen(buf); for(int opnum = 0; cmd.Operands[opnum].type != o_void; opnum++) { char op_str[128]; if(opnum != 0) qsnprintf(op_str, sizeof(op_str), ", "); ua_outop2(addr, op_str, sizeof(op_str) - 3, opnum); tag_remove(op_str, op_str, 0); qsnprintf(ptr, bufsz - 1 - (ptr - buf), "%s", op_str); ptr += strlen(op_str); } return 0; }
//---------------------------------------------------------------------- bool idaapi create_func_frame(func_t *pfn) { if ( pfn != NULL ) { if ( pfn->frame == BADNODE ) { ea_t ea = pfn->startEA; if ( ea + 12 < pfn->endEA) // minimum 4 + 4 + 2 + 2 bytes needed { insn_t insn[4]; for (int i=0; i<4; i++) { decode_insn(ea); insn[i] = cmd; ea += cmd.size; } if ( insn[0].itype == PIC_movff2 // movff FSR2L,POSTINC1 && insn[0].Op1.addr == PIC16_FSR2L && insn[0].Op2.addr == PIC16_POSTINC1 && insn[1].itype == PIC_movff2 // movff FSR1L,FSR2L && insn[1].Op1.addr == PIC16_FSR1L && insn[1].Op2.addr == PIC16_FSR2L && insn[2].itype == PIC_movlw // movlw <size> && insn[3].itype == PIC_addwf3 // addwf FSR1L,f && insn[3].Op1.addr == PIC16_FSR1L && insn[3].Op2.reg == F) { setflag((uint32 &)pfn->flags,FUNC_FRAME,1); return add_frame(pfn, insn[2].Op1.value, 0, 0); } } } } return 0; }
// The plugin can be passed an integer argument from the plugins.cfg // file. This can be useful when you want the one plug-in to do // something different depending on the hot-key pressed or menu // item selected. void IDAP_run(int arg) { msg("%s run()\n", IDAP_name); // Disassemble the instruction at the cursor position, store it in // the global accessible "cmd" structure. // ua_out(get_screen_ea(), false); decode_insn( get_screen_ea() ); // Display information about the first operand msg("itype = %u size = %zu\n", cmd.itype, cmd.size ); for( unsigned int n = 0; n < UA_MAXOP ; ++n ) { if( cmd.Operands[n].type == o_void ) break; msg("Operand %u n = %d type = %d reg = %d value = %a addr = %a\n", n, cmd.Operands[n].n, cmd.Operands[n].type, cmd.Operands[n].reg, cmd.Operands[n].value, cmd.Operands[n].addr); } char calleeName[MAXSTR]; get_func_name(cmd.Op1.addr, calleeName, sizeof(calleeName)); msg("Callee Name: \"%s\"", calleeName); return; }
//---------------------------------------------------------------------- static uval_t find_ret_purged(const func_t *pfn) { uval_t argsize = 0; ea_t ea = pfn->startEA; while ( ea < pfn->endEA ) { decode_insn(ea); if ( cmd.itype == H8500_rtd || cmd.itype == H8500_prtd ) { argsize = cmd.Op1.value; break; } ea = nextthat(ea, pfn->endEA, f_isCode, NULL); } // could not find any ret instructions // but the function ends with a jump if ( ea >= pfn->endEA && (cmd.itype == H8500_jmp || cmd.itype == H8500_pjmp) ) { ea_t target = calc_mem(cmd.Op1); pfn = get_func(target); if ( pfn != NULL ) argsize = pfn->argsize; } return argsize; }
bool idaapi create_func_frame(func_t *pfn) { if ( pfn == NULL ) return 0; ea_t ea = pfn->startEA; insn_t insn[4]; int i; for (i = 0; i < 4; i++) { decode_insn(ea); insn[i] = cmd; ea += cmd.size; } i = 0; ushort regsize = 0; // number of saved registers // first insn is not either push fp OR st fp, @-sp if ( (insn[i].itype != m32r_push || insn[i].Op1.reg != rFP ) && (insn[i].itype != m32r_st || insn[i].Op1.reg != rFP || insn[i].Op2.reg != rSP || insn[i].Op2.specflag1 != fRIAS)) { return 0; } regsize += 4; i++; // next insn is push lr OR st lr, @-sp if ( (insn[i].itype == m32r_push && insn[i].Op1.reg == rLR ) || (insn[i].itype == m32r_st && insn[i].Op1.reg == rFP && insn[i].Op2.reg == rLR && insn[i].Op2.specflag1 != fRIAS)) { regsize += 4; i++; } // next insn is not addi sp, #imm if ( insn[i].itype != m32r_addi || insn[i].Op1.reg != rSP ) return 0; sval_t offset = - (sval_t) insn[i].Op2.value; // toggle to the negative sign of the immediate operand of the addi insn if ( !is_invsign(insn[i].ea, get_flags_novalue(insn[i].ea), 2) ) toggle_sign(insn[i].ea, 2); i++; // next insn is not mv fp, sp if ( insn[i].itype != m32r_mv || insn[i].Op1.reg != rFP || insn[i].Op2.reg != rSP ) return 0; #if DEBUG msg("=> %d bytes\n", - (signed) insn[1].Op2.value); #endif pfn->flags |= (FUNC_FRAME | FUNC_BOTTOMBP); //setflag((uint32 &) pfn->flags, FUNC_FRAME | FUNC_BOTTOMBP, 1); return add_frame(pfn, offset, regsize, 0); }
/* * decode_ext() * * Decode opcode extensions (if any) */ static int decode_ext(struct ud *u, uint16_t ptr) { uint8_t idx = 0; if ((ptr & 0x8000) == 0) { return decode_insn(u, ptr); } u->le = &ud_lookup_table_list[(~0x8000 & ptr)]; if (u->le->type == UD_TAB__OPC_3DNOW) { return decode_3dnow(u); } switch (u->le->type) { case UD_TAB__OPC_MOD: /* !11 = 0, 11 = 1 */ idx = (MODRM_MOD(modrm(u)) + 1) / 4; break; /* disassembly mode/operand size/address size based tables. * 16 = 0,, 32 = 1, 64 = 2 */ case UD_TAB__OPC_MODE: idx = u->dis_mode / 32; break; case UD_TAB__OPC_OSIZE: idx = eff_opr_mode(u->dis_mode, REX_W(u->pfx_rex), u->pfx_opr) / 32; break; case UD_TAB__OPC_ASIZE: idx = eff_adr_mode(u->dis_mode, u->pfx_adr) / 32; break; case UD_TAB__OPC_X87: idx = modrm(u) - 0xC0; break; case UD_TAB__OPC_VENDOR: if (u->vendor == UD_VENDOR_ANY) { /* choose a valid entry */ idx = (u->le->table[idx] != 0) ? 0 : 1; } else if (u->vendor == UD_VENDOR_AMD) { idx = 0; } else { idx = 1; } break; case UD_TAB__OPC_RM: idx = MODRM_RM(modrm(u)); break; case UD_TAB__OPC_REG: idx = MODRM_REG(modrm(u)); break; case UD_TAB__OPC_SSE: return decode_ssepfx(u); default: assert(!"not reached"); break; } return decode_ext(u, u->le->table[idx]); }
//---------------------------------------------------------------------- int is_align_insn(ea_t ea) { if ( !decode_insn(ea) ) return 0; switch ( cmd.itype ) { case OAK_Dsp_nop: break; default: return 0; } return cmd.size; }
//---------------------------------------------------------------------- int idaapi is_align_insn(ea_t ea) { if ( !decode_insn(ea) ) return 0; switch ( cmd.itype ) { case DSP56_nop: break; default: return 0; } return cmd.size; }
//---------------------------------------------------------------------- int is_align_insn(ea_t ea) { decode_insn(ea); switch ( cmd.itype ) { case AVR_mov: if ( cmd.Op1.reg == cmd.Op2.reg ) break; default: return 0; case AVR_nop: break; } return cmd.size; }
int idaapi is_align_insn(ea_t ea) { if (!decode_insn(ea)) return 0; switch (cmd.itype) { case M8B_NOP: case M8B_XPAGE: return cmd.size; default: return 0; } }
// check and create a flat 32 bit jump table -- the most common case static void check_and_create_flat32( jump_table_type_t /*jtt*/, switch_info_ex_t &si) { // check the table contents ea_t table = si.jumps; segment_t *s = getseg(table); if ( s == NULL ) return; size_t maxsize = size_t(s->endEA - table); int size = si.ncases; if ( size > maxsize ) size = (int)maxsize; int i; insn_t saved = cmd; for ( i=0; i < size; i++ ) { ea_t ea = table + 4*i; flags_t F = getFlags(ea); if ( !hasValue(F) ) break; if ( i && (has_any_name(F) || hasRef(F)) ) break; ea_t target = segm_adjust_ea(getseg(table), si.elbase + get_long(ea)); if ( !isLoaded(target) ) break; flags_t F2 = get_flags_novalue(target); if ( isTail(F2) || isData(F2) ) break; if ( !isCode(F2) && !decode_insn(target) ) break; } cmd = saved; size = i; // create the table for ( i=0; i < size; i++ ) { ea_t ea = table + 4*i; doDwrd(ea, 4); op_offset(ea, 0, REF_OFF32, BADADDR, si.elbase); ea_t target = si.elbase + segm_adjust_diff(getseg(table), get_long(ea)); ua_add_cref(0, target, fl_JN); } si.flags |= SWI_J32; if ( si.defjump != BADADDR ) si.flags |= SWI_DEFAULT; si.ncases = (uint16)size; si.startea = cmd.ea; set_switch_info_ex(cmd.ea, &si); }
//---------------------------------------------------------------------- bool create_func_frame(func_t *pfn) // create frame of newly created function { if ( pfn != NULL ) { if ( pfn->frame == BADNODE ) { ea_t ea = pfn->startEA; ushort regsize = 0; while (ea < pfn->endEA) // check for register pushs { decode_insn(ea); ea += cmd.size; // считаем кол-во push if ( ((cmd.itype == TMS320C3X_PUSH) || (cmd.itype == TMS320C3X_PUSHF)) && (cmd.Op1.type == o_reg) ) regsize++; else // варианты манипуляции с sp типа: LDI SP,AR3 ADDI #0001,SP игнорируем if ( ((cmd.Op1.type == o_reg) && (cmd.Op1.reg == sp)) || ((cmd.Op2.type == o_reg) && (cmd.Op2.reg == sp)) ) continue; else break; } ea = pfn->startEA; int localsize = 0; while (ea < pfn->endEA) // check for frame creation { decode_insn(ea); ea += cmd.size; // Попытка определить команду типа ADDI #0001,SP if ( (cmd.itype == TMS320C3X_ADDI) && (cmd.Op1.type == o_imm) && (cmd.Op2.type == o_reg) && (cmd.Op2.reg == sp) ) { localsize = (int)cmd.Op1.value; break; } } add_frame(pfn, localsize, regsize, 0); } } return 0; }
//---------------------------------------------------------------------- bool create_func_frame(func_t *pfn) { if ( pfn != NULL ) { if ( pfn->frame == BADNODE ) { ea_t ea = pfn->startEA; int regsize = 0; while (ea < pfn->endEA) // check for register pushs { if ( !decode_insn(ea) ) break; if (cmd.itype != TMS320C54_pshm ) break; if ( cmd.Op1.type != o_mem && cmd.Op1.type != o_mmr ) break; if ( get_mapped_register(cmd.Op1.addr) == rnone ) break; regsize++; ea += cmd.size; } int localsize = 0; while (ea < pfn->endEA) // check for frame creation { if (cmd.itype == TMS320C54_frame && cmd.Op1.type == o_imm) { localsize = -(int)cmd.Op1.value; break; } ea += cmd.size; if ( !decode_insn(ea) ) break; } add_frame(pfn, localsize+regsize, 0, 0); } } return 0; }
//---------------------------------------------------------------------- // Is the instruction created only for alignment purposes? // returns: number of bytes in the instruction int is_align_insn(ea_t ea) { if ( !decode_insn(ea) ) return 0; switch ( cmd.itype ) { case TMS320C3X_NOP: break; default: return 0; } return cmd.size; }
//---------------------------------------------------------------------- int idaapi is_align_insn(ea_t ea) { if ( !decode_insn(ea) ) return 0; switch ( cmd.itype ) { case H8_nop: break; case H8_mov: case H8_or: if ( cmd.Op1.type == cmd.Op2.type && cmd.Op1.reg == cmd.Op2.reg ) break; default: return 0; } return cmd.size; }
/* * decode_3dnow() * * Decoding 3dnow is a little tricky because of its strange opcode * structure. The final opcode disambiguation depends on the last * byte that comes after the operands have been decoded. Fortunately, * all 3dnow instructions have the same set of operand types. So we * go ahead and decode the instruction by picking an arbitrarily chosen * valid entry in the table, decode the operands, and read the final * byte to resolve the menmonic. */ static __inline int decode_3dnow(struct ud* u) { uint16_t ptr; assert(u->le->type == UD_TAB__OPC_3DNOW); assert(u->le->table[0xc] != 0); decode_insn(u, u->le->table[0xc]); inp_next(u); if (u->error) { return -1; } ptr = u->le->table[inp_curr(u)]; assert((ptr & 0x8000) == 0); u->mnemonic = ud_itab[ptr].mnemonic; return 0; }
char get_byte_with_optimization(ea_t ea) { switch (patchdiff_cpu) { case CPU_X8632: case CPU_X8664: return x86_get_byte(ea); case CPU_PPC: return ppc_get_byte(ea); default: { decode_insn(ea); return (char)cmd.itype; } } }
//---------------------------------------------------------------------- bool idaapi create_func_frame(func_t *pfn) { int code = 0; if ( pfn->frame == BADNODE ) { size_t regs = 0; ea_t ea = pfn->startEA; bool bpused = false; while ( ea < pfn->endEA ) // skip all pushregs { // (must test that ea is lower // than pfn->endEA) decode_insn(ea); ea += cmd.size; switch ( cmd.itype ) { case H8_nop: continue; case H8_push: regs += get_dtyp_size(cmd.Op1.dtyp); continue; case H8_stm: if ( !issp(cmd.Op2.reg) ) break; regs += cmd.Op1.nregs * get_dtyp_size(cmd.Op1.dtyp); continue; case H8_mov: // mov.l er6, sp if ( cmd.Op1.type == o_reg && issp(cmd.Op1.reg) && cmd.Op2.type == o_reg && isbp(cmd.Op2.reg) ) bpused = true; break; default: break; } break; } uint32 frsize = 0; uint32 argsize = 0; if ( frsize != 0 || argsize != 0 || regs != 0 || bpused ) { setflag((uint32 &)pfn->flags,FUNC_FRAME,bpused); return add_frame(pfn, frsize, (ushort)regs, argsize); } } return code; }
static void decode(struct ptxed_decoder *decoder, struct pt_image_section_cache *iscache, const struct ptxed_options *options, struct ptxed_stats *stats) { if (!decoder) { printf("[internal error]\n"); return; } switch (decoder->type) { case pdt_insn_decoder: decode_insn(decoder->variant.insn, options, stats); break; case pdt_block_decoder: decode_block(decoder->variant.block, iscache, options, stats); break; } }
//---------------------------------------------------------------------- int idaapi is_align_insn(ea_t ea) { if ( !decode_insn(ea) ) return 0; switch ( cmd.itype ) { case H8500_nop: break; case H8500_mov_g: // B/W Move data case H8500_mov_e: // B Move data case H8500_mov_i: // W Move data case H8500_mov_f: // B/W Move data case H8500_mov_l: // B/W Move data case H8500_mov_s: // B/W Move data case H8500_or: case H8500_and: if ( cmd.Op1.type == cmd.Op2.type && cmd.Op1.reg == cmd.Op2.reg ) break; default: return 0; } return cmd.size; }
//---------------------------------------------------------------------- static void setup_far_func(func_t *pfn) { if ( (pfn->flags & FUNC_FAR) == 0 ) { ea_t ea1 = pfn->startEA; ea_t ea2 = pfn->endEA; while ( ea1 < ea2 ) { if ( isCode(get_flags_novalue(ea1)) ) { decode_insn(ea1); if ( is_far_ending() ) { pfn->flags |= FUNC_FAR; update_func(pfn); break; } } ea1 = next_head(ea1, ea2); } } }
static bool check_for_table_jump(void) { ea_t base = BADADDR, table = BADADDR, defea = BADADDR; int size = 0, elsize = 0; int i; bool ok = false; insn_t saved = cmd; for ( i=0; !ok && i < qnumber(patterns); i++ ) { ok = patterns[i](&base, &table, &defea, &size, &elsize); cmd = saved; } if ( !ok ) return false; if ( table != BADADDR ) table = toEA(cmd.cs, table); if ( base != BADADDR ) base = toEA(cmd.cs, base); if ( defea != BADADDR ) defea = toEA(cmd.cs, defea); // check the table contents int oldsize = size; segment_t *s = getseg(table); if ( s == NULL ) return false; int maxsize = int(s->endEA - table); if ( size > maxsize ) size = maxsize; for ( i=0; i < size; i++ ) { ea_t ea = table+i*elsize; flags_t F = getFlags(ea); if ( !hasValue(F) || (i && (has_any_name(F) || hasRef(F))) ) break; int el = elsize == 1 ? get_byte(ea) : get_word(ea); flags_t F2 = get_flags_novalue(base+el); if ( isTail(F2) || isData(F2) || (!isCode(F2) && !decode_insn(base+el)) ) break; } cmd = saved; size = i; if ( size != oldsize ) msg("Warning: jpt_%04a calculated size of %d forced to %d!\n", cmd.ip, oldsize, size); // create the table if ( size == 0 ) return false; for ( i=0; i < size; i++ ) { ea_t ea = table + i*elsize; (elsize == 1 ? doByte : doWord)(ea, elsize); op_offset(ea, 0, elsize == 1 ? REF_OFF8 : REF_OFF16, BADADDR, base); ua_add_cref(0, base + (elsize==1?get_byte(ea):get_word(ea)), fl_JN); } char buf[MAXSTR]; qsnprintf(buf, sizeof(buf), "def_%a", cmd.ip); // set_name(defea, buf, SN_NOWARN|SN_LOCAL); // temporary kernel bug workaround set_name(defea, buf, SN_NOWARN); qsnprintf(buf, sizeof(buf), "jpt_%a", cmd.ip); set_name(table, buf, SN_NOWARN); return true; }
void struct_trace(ea_t addr) { strace_t *trace; decode_insn(addr); for(int opnum = 0; cmd.Operands[opnum].type != o_void; opnum++) { op_t *op = &cmd.Operands[opnum]; char *opname = NULL; unsigned int val = 0; switch(opnum) { case 0: opname = "dst"; break; case 1: opname = "src"; break; case 2: opname = "aux"; break; } switch(op->type) { case o_displ: // if operand if is a register deref'd // get absolute value // check if it points to beginning of structures val = general[op->reg] + op->addr; break; case o_phrase: val = general[op->phrase]; break; } for(trace = strace; trace; trace = trace->next) { if(val >= trace->base && val <= trace->base + trace->size) { char name[256]; // char cmt[512]; struc_t *sptr = trace->sptr; member_t *mptr = get_member(sptr, val - trace->base); if(!mptr) { char *mtype; switch(get_dtyp_size(op->dtyp)) { case 1: mtype = "_byte"; break; case 2: mtype = "_word"; break; case 4: mtype = "_dword"; break; case 8: mtype = "_qword"; break; default: mtype = "_offset"; break; } qsnprintf(name, 256, "%s_%d", mtype, val - trace->base); //msg("%s\n", name); //qsnprintf(name, 256, "offset_%d", val - trace->base); if(struct_member_add(sptr, name, val - trace->base, 0, NULL, get_dtyp_size(op->dtyp)) < 0) { trace = trace->next; continue; } mptr = get_member(sptr, val - trace->base); } //get_member_fullname(mptr->id, name, sizeof(name) -1); //append_cmt(addr, name, true); tid_t path[2]; path[0] = sptr->id; path[1] = mptr->id; op_stroff(addr, opnum, path, 2, 0); } } } return; }
//--------------------------------------------------------------------------- // The main function - called when the user selects the menu item static bool idaapi callback(void *) { // Calculate the default values to display in the form ea_t screen_ea = get_screen_ea(); segment_t *s = getseg(screen_ea); if ( s == NULL || !isCode(get_flags_novalue(screen_ea)) ) { warning("AUTOHIDE NONE\nThe cursor must be on the table jump instruction"); return false; } ea_t startea = screen_ea; while ( true ) { ea_t prev = prev_not_tail(startea); if ( !is_switch_insn(prev) ) break; startea = prev; } ea_t jumps = get_first_dref_from(screen_ea); uval_t jelsize = s->abytes(); uval_t jtsize = 0; if ( jumps != BADADDR ) { decode_insn(screen_ea); jtsize = guess_table_size(jumps); } uval_t shift = 0; uval_t elbase = 0; char input[MAXSTR]; input[0] = '\0'; ea_t defea = BADADDR; uval_t lowcase = 0; ushort jflags = 0; ushort vflags = 0; ea_t vtable = BADADDR; ea_t vtsize = 0; ea_t velsize = s->abytes(); reg_info_t ri; ri.size = 0; // If switch information is present in the database, use it for defaults switch_info_ex_t si; if ( get_switch_info_ex(screen_ea, &si, sizeof(si)) > 0 ) { jumps = si.jumps; jtsize = si.ncases; startea = si.startea; elbase = si.elbase; jelsize = si.get_jtable_element_size(); shift = si.get_shift(); defea = (si.flags & SWI_DEFAULT) ? si.defjump : BADADDR; if ( si.regnum != -1 ) get_reg_name(si.regnum, get_dtyp_size(si.regdtyp), input, sizeof(input)); if ( si.flags & SWI_SIGNED ) jflags |= 2; if ( si.flags2 & SWI2_SUBTRACT ) jflags |= 4; if ( si.flags & SWI_SPARSE ) { jflags |= 1; vtable = si.values; vtsize = jtsize; velsize = si.get_vtable_element_size(); if ( si.flags2 & SWI2_INDIRECT ) { vflags |= 1; jtsize = si.jcases; } if ( si.flags & SWI_JMP_INV ) vflags |= 2; } else { lowcase = si.lowcase; } } // Now display the form and let the user edit the attributes while ( AskUsingForm_c(main_form, &jumps, &jtsize, &jelsize, &shift, &elbase, &startea, input, &lowcase, &defea, &jflags) ) { if ( !check_table(jumps, jelsize, jtsize) ) continue; if ( shift > 3 ) { warning("AUTOHIDE NONE\nInvalid shift value (allowed values are 0..3)"); continue; } if ( !isCode(get_flags_novalue(startea)) ) { warning("AUTOHIDE NONE\nInvalid switch idiom start %a (must be an instruction", startea); continue; } ri.reg = -1; if ( input[0] != '\0' && !parse_reg_name(input, &ri) ) { warning("AUTOHIDE NONE\nUnknown input register: %s", input); continue; } if ( defea != BADADDR && !isCode(get_flags_novalue(defea)) ) { warning("AUTOHIDE NONE\nInvalid default jump %a (must be an instruction", defea); continue; } if ( jflags & 1 ) // value table is present { bool vok = false; while ( AskUsingForm_c(value_form, &vflags, &vtable, &vtsize, &velsize) ) { if ( (vflags & 1) == 0 ) vtsize = jtsize; if ( check_table(vtable, velsize, vtsize) ) { vok = true; break; } } if ( !vok ) break; } // ok, got and validated all params -- fill the structure si.flags = SWI_EXTENDED; si.flags2 = 0; if ( jflags & 2 ) si.flags |= SWI_SIGNED; if ( jflags & 4 ) si.flags2 |= SWI2_SUBTRACT; si.jumps = jumps; si.ncases = ushort(jtsize); si.startea = startea; si.elbase = elbase; if ( elbase != 0 ) si.flags |= SWI_ELBASE; si.set_jtable_element_size((int)jelsize); si.set_shift((int)shift); if ( defea != BADADDR ) { si.flags |= SWI_DEFAULT; si.defjump = defea; } if ( ri.reg != -1 ) si.set_expr(ri.reg, get_dtyp_by_size(ri.size)); if ( jflags & 1 ) // value table is present { si.flags |= SWI_SPARSE; si.values = vtable; si.set_vtable_element_size((int)velsize); if ( (vflags & 1) != 0 ) { si.flags2 |= SWI2_INDIRECT; si.jcases = (int)jtsize; si.ncases = (ushort)vtsize; } if ( (vflags & 2) != 0 ) si.flags |= SWI_JMP_INV; } else { si.lowcase = lowcase; } // ready, store it set_switch_info_ex(screen_ea, &si); create_switch_table(screen_ea, &si); setFlbits(screen_ea, FF_JUMP); create_insn(screen_ea); info("AUTOHIDE REGISTRY\nSwitch information has been stored"); break; } return true; }
int idaapi emu() { char szLabel[MAXSTR]; insn_t saved; segment_t* pSegment; ea_t ea, length, offset; flags_t flags; uint32 dwFeature, i; dwFeature = cmd.get_canon_feature(); fFlow = !(dwFeature & CF_STOP); if (dwFeature & CF_USE1) op_emu(cmd.Op1, 1); if (dwFeature & CF_USE2) op_emu(cmd.Op2, 1); if (dwFeature & CF_CHG1) op_emu(cmd.Op1, 0); if (dwFeature & CF_CHG2) op_emu(cmd.Op2, 0); saved = cmd; switch (cmd.itype) { case M8B_MOV: if (!cmd.Op1.is_reg(rPSP)) break; case M8B_SWAP: if (cmd.itype == M8B_SWAP && !cmd.Op2.is_reg(rDSP)) break; for (i = 0; i < 5; ++i) { ea = decode_prev_insn(cmd.ea); if (ea == BADADDR) break; if (cmd.itype == M8B_MOV && cmd.Op1.is_reg(rA) && cmd.Op2.type == o_imm) { ea = toRAM(cmd.Op2.value); if (ea != BADADDR) { qsnprintf(szLabel, sizeof(szLabel), "%s_%0.2X", cmd.itype == M8B_MOV ? "psp" : "dsp", cmd.Op2.value); ua_add_dref(cmd.Op2.offb, ea, dr_O); set_name(ea, szLabel, SN_NOWARN); } break; } } break; case M8B_JACC: pSegment = getseg(cmd.ea); if (!pSegment) break; length = pSegment->endEA - cmd.ea; if (length > 256) length = 256; for (offset = 2; offset < length; offset += 2) { ea = toROM(saved.Op1.addr + offset); if (ea == BADADDR) break; flags = getFlags(ea); if (!hasValue(flags) || (has_any_name(flags) || hasRef(flags)) || !create_insn(ea)) break; switch (cmd.itype) { case M8B_JMP: case M8B_RET: case M8B_RETI: case M8B_IPRET: add_cref(saved.ea, ea, fl_JN); break; default: offset = length; } } break; case M8B_IORD: case M8B_IOWR: case M8B_IOWX: for (i = 0; i < 5; ++i) { ea = (saved.itype == M8B_IORD) ? decode_insn(cmd.ea + cmd.size) : decode_prev_insn(cmd.ea); if (ea == BADADDR) break; if (cmd.Op1.is_reg(rA) && cmd.Op2.type == o_imm) { qsnprintf(szLabel, sizeof(szLabel), "[A=%0.2Xh] ", cmd.Op2.value); if (get_portbits_sym(szLabel + qstrlen(szLabel), saved.Op1.addr, cmd.Op2.value)) set_cmt(saved.ea, szLabel, false); break; } } } cmd = saved; if ((cmd.ea & 0xFF) == 0xFF) { switch (cmd.itype) { case M8B_RET: case M8B_RETI: case M8B_XPAGE: break; default: QueueMark(Q_noValid, cmd.ea); } } if (fFlow) ua_add_cref(0, cmd.ea + cmd.size, fl_F); return 1; }
// Analyze an instruction static ea_t next_insn(ea_t ea) { if ( decode_insn(ea) == 0 ) return 0; ea += cmd.size; return ea; }
static int idaapi hook_ui(void *user_data, int notification_code, va_list va) { switch (notification_code) { case ui_notification_t::ui_get_custom_viewer_hint: { TCustomControl *viewer = va_arg(va, TCustomControl *); place_t *place = va_arg(va, place_t *); int *important_lines = va_arg(va, int *); qstring &hint = *va_arg(va, qstring *); if (place == NULL) return 0; int x, y; if (get_custom_viewer_place(viewer, true, &x, &y) == NULL) return 0; char buf[MAXSTR]; const char *line = get_custom_viewer_curline(viewer, true); tag_remove(line, buf, sizeof(buf)); if (x >= (int)strlen(buf)) return 0; idaplace_t &pl = *(idaplace_t *)place; if (decode_insn(pl.ea) && dbg_started) { insn_t _cmd = cmd; int flags = calc_default_idaplace_flags(); linearray_t ln(&flags); for (int i = 0; i < qnumber(_cmd.Operands); i++) { op_t op = _cmd.Operands[i]; if (op.type != o_void) { switch (op.type) { case o_mem: case o_near: { idaplace_t here; here.ea = op.addr; here.lnnum = 0; ln.set_place(&here); hint.cat_sprnt((COLSTR(SCOLOR_INV"OPERAND#%d (ADDRESS: $%a)\n", SCOLOR_DREF)), op.n, op.addr); (*important_lines)++; int n = qmin(ln.get_linecnt(), 10); // how many lines for this address? (*important_lines) += n; for (int j = 0; j < n; ++j) { hint.cat_sprnt("%s\n", ln.down()); } } break; case o_phrase: case o_reg: { regval_t reg; int reg_idx = idp_to_dbg_reg(op.reg); const char *reg_name = dbg->registers(reg_idx).name; if (get_reg_val(reg_name, ®)) { idaplace_t here; here.ea = (uint32)reg.ival; here.lnnum = 0; ln.set_place(&here); hint.cat_sprnt((COLSTR(SCOLOR_INV"OPERAND#%d (REGISTER: %s)\n", SCOLOR_DREF)), op.n, reg_name); (*important_lines)++; int n = qmin(ln.get_linecnt(), 10); // how many lines for this address? (*important_lines) += n; for (int j = 0; j < n; ++j) { hint.cat_sprnt("%s\n", ln.down()); } } } break; case o_displ: { regval_t main_reg, add_reg; int main_reg_idx = idp_to_dbg_reg(op.reg); int add_reg_idx = idp_to_dbg_reg(op.specflag1 & 0xF); main_reg.ival = 0; add_reg.ival = 0; if (op.specflag2 & 0x10) { get_reg_val(dbg->registers(add_reg_idx).name, &add_reg); if (op.specflag1 & 0x10) add_reg.ival &= 0xFFFF; } if (main_reg_idx != R_PC) get_reg_val(dbg->registers(main_reg_idx).name, &main_reg); idaplace_t here; ea_t addr = (uint32)main_reg.ival + op.addr + (uint32)add_reg.ival; // TODO: displacements with PC and other regs unk_123(pc, d0.l); unk_111(d0, d2.w) here.ea = addr; here.lnnum = 0; ln.set_place(&here); hint.cat_sprnt((COLSTR(SCOLOR_INV"OPERAND#%d (DISPLACEMENT: [$%s%X($%X", SCOLOR_DREF)), op.n, ((int)op.addr < 0) ? "-" : "", ((int)op.addr < 0) ? -(int)op.addr : op.addr, (uint32)main_reg.ival ); if (op.specflag2 & 0x10) hint.cat_sprnt((COLSTR(",$%X", SCOLOR_DREF)), (uint32)add_reg.ival); hint.cat_sprnt((COLSTR(")])\n", SCOLOR_DREF))); (*important_lines)++; int n = qmin(ln.get_linecnt(), 10); // how many lines for this address? (*important_lines) += n; for (int j = 0; j < n; ++j) { hint.cat_sprnt("%s\n", ln.down()); } } break; } } } return 1; } } default: return 0; } }
int pt_insn_next(struct pt_insn_decoder *decoder, struct pt_insn *uinsn, size_t size) { struct pt_insn insn, *pinsn; int errcode, status; if (!uinsn || !decoder) return -pte_invalid; pinsn = size == sizeof(insn) ? uinsn : &insn; /* Zero-initialize the instruction in case of error returns. */ memset(pinsn, 0, sizeof(*pinsn)); /* We process events three times: * - once based on the current IP. * - once based on the instruction at that IP. * - once based on the next IP. * * Between the first and second round of event processing, we decode * the instruction and fill in @insn. * * This is necessary to attribute events to the correct instruction. */ errcode = process_events_before(decoder, pinsn); if (errcode < 0) goto err; /* If tracing is disabled at this point, we should be at the end * of the trace - otherwise there should have been a re-enable * event. */ if (!decoder->enabled) { struct pt_event event; /* Any query should give us an end of stream, error. */ errcode = pt_qry_event(&decoder->query, &event, sizeof(event)); if (errcode != -pte_eos) errcode = -pte_no_enable; goto err; } errcode = decode_insn(pinsn, decoder); if (errcode < 0) goto err; /* After decoding the instruction, we must not change the IP in this * iteration - postpone processing of events that would to the next * iteration. */ decoder->event_may_change_ip = 0; errcode = process_events_after(decoder, pinsn); if (errcode < 0) goto err; /* We return the decoder status for this instruction. */ status = pt_insn_status(decoder); /* If event processing disabled tracing, we're done for this * iteration - we will process the re-enable event on the next. * * Otherwise, we determine the next instruction and peek ahead. * * This may indicate an event already in this instruction. */ if (decoder->enabled) { /* Proceed errors are signaled one instruction too early. */ errcode = proceed(decoder); if (errcode < 0) goto err; /* Peek errors are ignored. We will run into them again * in the next iteration. */ (void) process_events_peek(decoder, pinsn); } errcode = insn_to_user(uinsn, size, pinsn); if (errcode < 0) return errcode; /* We're done with this instruction. Now we may change the IP again. */ decoder->event_may_change_ip = 1; return status; err: /* We provide the (incomplete) instruction also in case of errors. * * For decode or post-decode event-processing errors, the IP or * other fields are already valid and may help diagnose the error. */ (void) insn_to_user(uinsn, size, pinsn); return errcode; }
int dline_add(dline_t * dl, ea_t ea, char options) { char buf[256]; char tmp[256]; char dis[256]; char addr[30]; char * dll; int len; flags_t f; buf[0] = '\0'; f = getFlags(ea); generate_disasm_line(ea, dis, sizeof(dis)); decode_insn(ea); init_output_buffer(buf, sizeof(buf)); // Adds block label if (has_dummy_name(f)) { get_nice_colored_name(ea,tmp,sizeof(tmp),GNCN_NOSEG|GNCN_NOFUNC); out_snprintf("%s", tmp); out_line(":\n", COLOR_DATNAME); } if (options) { qsnprintf(addr, sizeof(addr), "%a", ea); out_snprintf("%s ", addr); } out_insert(get_output_ptr(), dis); term_output_buffer(); len = strlen(buf); if (dl->available < (len+3)) { dll = (char *)qrealloc(dl->lines, sizeof(char*) * (dl->num+len+256)); if (!dll) return -1; dl->available = len+256; dl->lines = dll; } if (dl->num) { dl->lines[dl->num] = '\n'; dl->num++; } memcpy(&dl->lines[dl->num], buf, len); dl->available -= len+1; dl->num += len; dl->lines[dl->num] = '\0'; return 0; }