//---------------------------------------------------------------------- static void process_imm(op_t &x) { doImmd(cmd.ea); if ( isDefArg(uFlag,x.n) ) return; // if already defined by user switch (cmd.itype) { case TMS320C54_cmpm: case TMS320C54_bitf: case TMS320C54_andm: case TMS320C54_orm: case TMS320C54_xorm: case TMS320C54_addm: case TMS320C54_st: case TMS320C54_stm: case TMS320C54_rpt: case TMS320C54_ld3: case TMS320C54_mpy2: case TMS320C54_rptz: case TMS320C54_add3: case TMS320C54_sub3: case TMS320C54_and3: case TMS320C54_or3: case TMS320C54_xor3: case TMS320C54_mac2: op_num(cmd.ea, x.n); } }
//---------------------------------------------------------------------- int idaapi emu(void) { uint32 Feature = cmd.get_canon_feature(); flow = ((Feature & CF_STOP) == 0); if ( Feature & CF_USE1 ) process_operand(cmd.Op1, true); if ( Feature & CF_USE2 ) process_operand(cmd.Op2, true); if ( Feature & CF_USE3 ) process_operand(cmd.Op3, true); if ( Feature & CF_CHG1 ) process_operand(cmd.Op1, false); if ( Feature & CF_CHG2 ) process_operand(cmd.Op2, false); if ( Feature & CF_CHG3 ) process_operand(cmd.Op3, false); // // Determine if the next instruction should be executed // if ( segtype(cmd.ea) == SEG_XTRN ) flow = 0; if ( flow ) ua_add_cref(0,cmd.ea+cmd.size,fl_F); // // convert "lda imm, reg" to "lda mem, reg" // if ( cmd.itype == I960_lda && cmd.Op1.type == o_imm && !isDefArg(uFlag, 0) && isEnabled(cmd.Op1.value) ) set_offset(cmd.ea, 0, 0); return 1; }
//------------------------------------------------------------------------ static void process_immediate_number(int n) { doImmd(cmd.ea); if ( isDefArg(uFlag,n) ) return; /* switch ( cmd.itype ) { op_dec(cmd.ea, n); break; }*/ }
//------------------------------------------------------------------------ static void doImmdValue(int n) { doImmd(cmd.ea); if ( isDefArg(uFlag,n) ) return; switch ( cmd.itype ) { case AVR_andi: case AVR_ori: op_num(cmd.ea, n); } }
//------------------------------------------------------------------------ static void process_immediate_number(int n) { doImmd(cmd.ea); if ( isDefArg(uFlag,n) ) return; switch ( cmd.itype ) { // case DSP56_asl: // case DSP56_asr: case DSP56_bchg: case DSP56_bclr: case DSP56_brclr: case DSP56_brset: case DSP56_bsclr: case DSP56_bset: case DSP56_bsset: case DSP56_btst: case DSP56_jclr: case DSP56_jset: case DSP56_jsclr: case DSP56_jsset: // case DSP56_lsl: // case DSP56_lsr: op_dec(cmd.ea, n); break; case DSP56_add: case DSP56_and: case DSP56_andi: case DSP56_cmp: case DSP56_eor: case DSP56_extract: case DSP56_extractu: case DSP56_insert: case DSP56_mac: case DSP56_maci: case DSP56_macr: case DSP56_macri: case DSP56_mpy: case DSP56_mpyi: case DSP56_mpyr: case DSP56_mpyri: case DSP56_or: case DSP56_ori: case DSP56_sub: case DSP56_do: case DSP56_dor: case DSP56_rep: op_num(cmd.ea, n); break; } }
//---------------------------------------------------------------------- static void TouchArg( op_t &x, int isload ) { switch( x.type ) { case o_imm: doImmd(cmd.ea); if ( isOff(uFlag, x.n) ) ua_add_off_drefs2(x, dr_O, OOF_SIGNED); break; case o_indexed: // addr[value] doImmd(cmd.ea); if ( x.value == 0 && !isDefArg(uFlag, x.n) ) set_offset(cmd.ea, x.n, toEA(cmd.cs, 0)); if ( isOff(uFlag, x.n) ) // xref to addr { uval_t saved = x.value; x.value = x.addr; ua_add_off_drefs2(x, saved ? dr_O : isload ? dr_R : dr_W, OOF_SIGNED|OOF_ADDR); x.value = saved; } if ( x.value != 0 ) // xref to value { // no references to ZERO_REG ea_t ea = toEA(cmd.cs, x.value); ua_add_dref(x.offb, ea, isload ? dr_R : dr_W ); ua_dodata2(x.offb, ea, x.dtyp); } break; case o_indirect: case o_indirect_inc: case o_mem: { ea_t dea = toEA( cmd.cs, x.addr ); ua_dodata2(x.offb, dea, x.dtyp); if( !isload ) doVar(dea); ua_add_dref( x.offb, dea, isload ? dr_R : dr_W ); if ( !isload && (x.addr == 0x14 || x.addr == 0x15) ) { sel_t wsrval = BADSEL; if ( cmd.Op2.type == o_imm ) wsrval = sel_t(cmd.Op2.value); splitSRarea1(cmd.ea, x.addr == 0x14 ? WSR : WSR1, wsrval, SR_auto); } } break; case o_near: ea_t ea = toEA( cmd.cs, x.addr ); int iscall = InstrIsSet( cmd.itype, CF_CALL ); ua_add_cref( x.offb, ea, iscall ? fl_CN : fl_JN ); if ( flow && iscall ) flow = func_does_return(ea); } }
//------------------------------------------------------------------------ static void doImmdValue(int n) { doImmd(cmd.ea); if ( isDefArg(uFlag,n) ) return; switch ( cmd.itype ) { case TMS6_and: // Rd = Op1 & Op2 case TMS6_xor: // Rd = Op1 ^ Op2 case TMS6_or: // Rd = Op2 | Op1 case TMS6_set: // Rd = Op1 & ~Op2 case TMS6_clr: // Rd = Op1 & ~Op2 case TMS6_ext: // Rd = Op1 & ~Op2 case TMS6_extu: // Rd = Op1 & ~Op2 op_num(cmd.ea,n); } }
//------------------------------------------------------------------------ static void process_immediate_number(int n) { doImmd(cmd.ea); if ( isDefArg(uFlag,n) ) return; switch ( cmd.itype ) { case PIC_iorlw: case PIC_andlw: case PIC_xorlw: op_num(cmd.ea, n); break; case PIC_lfsr2: // FSRs are used to address the data memory if ( dataseg != BADADDR ) op_offset(cmd.ea, n, REF_OFF16, BADADDR, dataseg); break; } }
int emu(void) { uint32 Feature = cmd.get_canon_feature(); flow = ((Feature & CF_STOP) == 0); // you may emulate selected instructions with a greater care: switch ( cmd.itype ) { case I51_mov: if ( cmd.Op1.type == o_mem && cmd.Op1.addr == 0x81 ) // mov SP, #num { if ( cmd.Op2.type == o_imm && !isDefArg(uFlag,1) ) set_offset(cmd.ea,1,intmem); // convert it to an offset } break; case I51_trap: ua_add_cref(0, 0x7B, fl_CN); break; case I51_pop: add_stkpnt(1); break; case I51_push: add_stkpnt(-1); break; } if ( Feature & CF_USE1 ) handle_operand(cmd.Op1, 1); if ( Feature & CF_USE2 ) handle_operand(cmd.Op2, 1); if ( Feature & CF_USE3 ) handle_operand(cmd.Op3, 1); if ( Feature & CF_JUMP ) QueueMark(Q_jumps,cmd.ea); if ( Feature & CF_CHG1 ) handle_operand(cmd.Op1, 0); if ( Feature & CF_CHG2 ) handle_operand(cmd.Op2, 0); if ( Feature & CF_CHG3 ) handle_operand(cmd.Op3, 0); // if the execution flow is not stopped here, then create // a xref to the next instruction. // Thus we plan to analyze the next instruction. if ( flow ) ua_add_cref(0,cmd.ea+cmd.size,fl_F); return 1; // actually the return value is unimportant, but let's it be so }
//------------------------------------------------------------------------ static void doImmdValue(int n) { doImmd(cmd.ea); if ( !isDefArg(uFlag, n) ) { switch ( cmd.itype ) { case I5_ani: case I5_xri: case I5_ori: case I5_in: case I5_out: case I5_rst: case HD_in0: case HD_out0: case HD_tstio: op_num(cmd.ea,-1); break; } } }
//------------------------------------------------------------------------ static void process_immediate_number(int n) { doImmd(cmd.ea); if ( isDefArg(uFlag,n) ) return; switch ( cmd.itype ) { case H8500_add_q: case H8500_bclr: case H8500_bnot: case H8500_bset: case H8500_btst: op_dec(cmd.ea, n); break; case H8500_and: case H8500_or: case H8500_xor: case H8500_andc: case H8500_orc: case H8500_xorc: op_num(cmd.ea, n); break; } }
//------------------------------------------------------------------------ static void process_immediate_number(int n) { doImmd(cmd.ea); if ( isDefArg(uFlag,n) ) return; switch ( cmd.itype ) { case H8_shal: case H8_shar: case H8_shll: case H8_shlr: case H8_rotl: case H8_rotr: case H8_rotxl: case H8_rotxr: op_dec(cmd.ea, n); break; case H8_and: case H8_or: case H8_xor: op_num(cmd.ea, n); break; } }
static void op_imm(int n) { doImmd(cmd.ea); if (isDefArg(uFlag, n)) return; switch (cmd.itype) { case M8B_ADD: case M8B_ADC: case M8B_SUB: case M8B_SBB: op_dec(cmd.ea, n); break; case M8B_CMP: case M8B_MOV: case M8B_AND: case M8B_OR: case M8B_XOR: op_num(cmd.ea, n); break; } }
//---------------------------------------------------------------------- static void TouchArg(op_t &x,int isAlt,int isload) { switch ( x.type ) { case o_phrase: //Добавляем в список ошибок(выводим сообщение) //ошибку и адресс где это случилось //QueueMark(Q_jumps, cmd.ea); case o_void: case o_reg: break; case o_sr: case o_displ: //Установить для данного байта признак immedia doImmd(cmd.ea); //Получить флаг для указанного линейного адресса if ( !isAlt ) { uint32 offb; ushort addr = ushort(x.addr); if ( x.type == o_displ ) { addr += (ushort)cmd.ip; addr += cmd.size; //Получить линейный адресс offb = (uint32)toEA(codeSeg(addr,x.n), 0); DataSet(x, offb+addr, isload); } else if ( isOff(uFlag, x.n) ) { reref: ua_add_off_drefs2(x, dr_O, x.type == o_displ ? OOF_ADDR : 0); if ( x.type == o_displ ) //Преобразовать данные по указанному линейному адрессу в указанный тип ua_dodata2(x.offb, calc_target(cmd.ea+x.offb, cmd.ea, x.n, x.addr), x.dtyp); } else if ( x.type == o_displ && !x.reg && !isDefArg(uFlag, x.n ) && set_offset(cmd.ea, x.n, toEA(cmd.cs,0))) goto reref; } break; case o_stk: case o_imm: { //Установить для данного байта признак immedia doImmd(cmd.ea); if ( isOff(get_flags_novalue(cmd.ea), x.n) ) ua_add_off_drefs2(x, dr_O, 0); } break; case o_ab: { if ( x.TypeOper == TAB_INDIRECTED_ABS_X ) { ea_t ea = toEA(cmd.cs, x.addr); ua_dodata2(x.offb, ea, dt_word); //добавить крос референсы для текущей инструкции ua_add_dref(x.offb, ea, isload ? dr_R : dr_W); //получить данные uint32 Addr; Addr = get_word(ea); Addr = uint32( Addr | (getPG<<16)); //добавить крос референсы для текущей инструкции ua_add_cref(2, Addr, fl_JF); } else DataSet(x, toEA(codeSeg(x.addr,x.n), x.addr), isload); } break; case o_mem: { // Конвертирование в данные(указан адресс) по указанному типу, //добавить крос референсы для текущей инструкции switch ( x.TypeOper ) { case TDIR_DIR_Y: case TDIR_DIR_X: case TDIR_DIR: case TDIR_INDIRECT_DIR: case TDIR_INDIRECT_DIR_X: case TDIR_INDIRECT_DIR_Y: case TDIR_L_INDIRECT_DIR: case TDIR_L_INDIRECT_DIR_Y: { if ( getDPReg == 1 ) { uint32 d = x.addr & 0xC; x.addr &= 0xFF3F; DataSet(x, toEA(codeSeg(x.addr,x.n), x.addr), isload); x.addr |=d; } else DataSet(x, toEA(codeSeg(x.addr,x.n), x.addr), isload); } break; default: DataSet(x, toEA(codeSeg(x.addr,x.n), x.addr), isload); }//end switch } break; case o_near: { //Получить линейный адресс ea_t ea = toEA(cmd.cs, x.addr); switch ( cmd.itype ) { case m7900_jsr: { //добавить крос референсы для текущей инструкции ua_add_cref(x.offb, ea, fl_CN ); if ( !func_does_return(ea) ) flow = false; } break; case m7900_jsrl: //добавить крос референсы для текущей инструкции ua_add_cref(x.offb, ea, fl_CF); if ( !func_does_return(ea) ) flow = false; break; case m7900_jmpl: //добавить крос референсы для текущей инструкции ua_add_cref(x.offb, ea, fl_JF); break; default: ua_add_cref(x.offb, ea, fl_JN); break; } } break; default: // warning("%a: %s,%d: bad optype %d", cmd.ea, cmd.get_canon_mnem(), x.n, x.type); break; } }
// Emulate an operand. static void handle_operand(op_t &op, bool write) { switch ( op.type ) { // Code address case o_near: { cref_t mode; ea_t ea = toEA(cmd.cs, op.addr); // call or jump ? if ( cmd.itype == st9_call || cmd.itype == st9_calls ) { if ( !func_does_return(ea) ) flow = false; mode = fl_CN; } else { mode = fl_JN; } ua_add_cref(op.offb, ea, mode); } break; // Memory address case o_mem: { enum dref_t mode; mode = write ? dr_W: dr_R; ua_add_dref(op.offb, toEA(cmd.cs, op.addr), mode); ua_dodata2(op.offb, op.addr, op.dtyp); } break; // Immediate value case o_imm: doImmd(cmd.ea); // create a comment if this immediate is represented in the .cfg file { const ioport_t * port = find_sym(op.value); if ( port != NULL && !has_cmt(uFlag) ) { set_cmt(cmd.ea, port->cmt, false); } } // if the value was converted to an offset, then create a data xref: if ( isOff(uFlag, op.n) ) ua_add_off_drefs2(op, dr_O, 0); break; // Displacement case o_displ: doImmd(cmd.ea); if ( isOff(uFlag, op.n) ) { ua_add_off_drefs2(op, dr_O, OOF_ADDR); ua_dodata2(op.offb, op.addr, op.dtyp); } // create stack variables if required if ( may_create_stkvars() && !isDefArg(uFlag, op.n) ) { func_t *pfn = get_func(cmd.ea); if ( pfn != NULL && pfn->flags & FUNC_FRAME ) { if ( ua_stkvar2(op, op.addr, STKVAR_VALID_SIZE) ) { op_stkvar(cmd.ea, op.n); if ( cmd.Op2.type == o_reg ) { regvar_t *r = find_regvar(pfn, cmd.ea, ph.regNames[cmd.Op2.reg]); if ( r != NULL ) { struc_t *s = get_frame(pfn); member_t *m = get_stkvar(op, op.addr, NULL); char b[20]; qsnprintf(b, sizeof b, "%scopy", r->user); set_member_name(s, m->soff, b); } } } } } break; // Register - Phrase - Void: do nothing case o_reg: case o_phrase: case o_void: break; default: IDA_ERROR("Invalid op.type in handle_operand()"); } }
//---------------------------------------------------------------------- static void process_operand(op_t &x,int isAlt,int isload) { switch ( x.type ) { case o_reg: case o_reglist: return; case o_imm: QASSERT(10090, isload); process_immediate_number(x.n); if ( op_adds_xrefs(uFlag, x.n) ) ua_add_off_drefs2(x, dr_O, calc_opimm_flags()); break; case o_phrase: case o_displ: process_immediate_number(x.n); if ( isAlt ) break; if ( op_adds_xrefs(uFlag, x.n) ) { ea_t ea = ua_add_off_drefs2(x, isload ? dr_R : dr_W, calc_opdispl_flags()); if ( ea != BADADDR ) { ua_dodata2(x.offb, ea, x.dtyp); if ( !isload ) doVar(ea); } } // create stack variables if required if ( x.type == o_displ && may_create_stkvars() && !isDefArg(uFlag, x.n) ) { func_t *pfn = get_func(cmd.ea); if ( pfn != NULL && (issp(x.phrase) || isbp(x.phrase) && (pfn->flags & FUNC_FRAME) != 0) ) { if ( ua_stkvar2(x, x.addr, STKVAR_VALID_SIZE) ) op_stkvar(cmd.ea, x.n); } } break; case o_near: case o_far: { cref_t ftype = x.type == o_near ? fl_JN : fl_JF; ea_t ea = calc_mem(x); if ( InstrIsSet(cmd.itype, CF_CALL) ) { if ( !func_does_return(ea) ) flow = false; ftype = x.type == o_near ? fl_CN : fl_CF; } ua_add_cref(x.offb, ea, ftype); } break; case o_mem: { ea_t ea = calc_mem(x); ua_add_dref(x.offb, ea, isload ? dr_R : dr_W); ua_dodata2(x.offb, ea, x.dtyp); if ( !isload ) doVar(ea); } break; default: INTERR(10091); } }
//------------------------------------------------------------------------ static void process_immediate_number(int n) { doImmd(cmd.ea); if ( isDefArg(uFlag,n) ) return; switch ( cmd.itype ) { case OAK_Dsp_shfi: case OAK_Dsp_movsi: op_dec(cmd.ea, n); uFlag = getFlags(cmd.ea); break; case OAK_Dsp_lpg: case OAK_Dsp_mpyi: case OAK_Dsp_mov: case OAK_Dsp_rets: case OAK_Dsp_rep: case OAK_Dsp_load: case OAK_Dsp_push: case OAK_Dsp_bkrep: case OAK_Dsp_msu: case OAK_Dsp_tstb: case OAK_Dsp_or: case OAK_Dsp_and: case OAK_Dsp_xor: case OAK_Dsp_add: case OAK_Dsp_alm_tst0: case OAK_Dsp_alm_tst1: case OAK_Dsp_cmp: case OAK_Dsp_sub: case OAK_Dsp_alm_msu: case OAK_Dsp_addh: case OAK_Dsp_addl: case OAK_Dsp_subh: case OAK_Dsp_subl: case OAK_Dsp_sqr: case OAK_Dsp_sqra: case OAK_Dsp_cmpu: case OAK_Dsp_set: case OAK_Dsp_rst: case OAK_Dsp_chng: case OAK_Dsp_addv: case OAK_Dsp_alb_tst0: case OAK_Dsp_alb_tst1: case OAK_Dsp_cmpv: case OAK_Dsp_subv: case OAK_Dsp_mpy: case OAK_Dsp_mpysu: case OAK_Dsp_mac: case OAK_Dsp_macus: case OAK_Dsp_maa: case OAK_Dsp_macuu: case OAK_Dsp_macsu: case OAK_Dsp_maasu: op_num(cmd.ea, n); uFlag = getFlags(cmd.ea); break; } }
//---------------------------------------------------------------------- static void process_operand(op_t &x,int isAlt,int isload) { switch ( x.type ) { case o_reg: case o_phrase: case o_reglist: return; case o_imm: QASSERT(10094, isload); process_immediate_number(x.n); if ( op_adds_xrefs(uFlag, x.n) ) ua_add_off_drefs2(x, dr_O, OOFS_IFSIGN|OOFW_IMM); break; case o_displ: process_immediate_number(x.n); if ( isAlt ) break; if ( op_adds_xrefs(uFlag, x.n) ) { ea_t ea = ua_add_off_drefs2(x, isload ? dr_R : dr_W, get_displ_outf(x)); if ( ea != BADADDR ) { ua_dodata2(x.offb, ea, x.dtyp); if ( !isload ) doVar(ea); } } // create stack variables if required if ( may_create_stkvars() && !isDefArg(uFlag, x.n) ) { func_t *pfn = get_func(cmd.ea); if ( pfn != NULL && (issp(x.phrase) || isbp(x.phrase) && (pfn->flags & FUNC_FRAME) != 0) ) { if ( ua_stkvar2(x, x.addr, STKVAR_VALID_SIZE) ) op_stkvar(cmd.ea, x.n); } } break; case o_near: add_code_xref(x, calc_mem(x.addr)); break; case o_mem: case o_memind: { ea_t ea = calc_mem(x.addr); if ( !isEnabled(ea) && find_sym(ea) ) break; // address not here ua_add_dref(x.offb, ea, isload ? dr_R : dr_W); ua_dodata2(x.offb, ea, x.dtyp); if ( x.type == o_memind ) { ssize_t size = get_dtyp_size(x.dtyp); flags_t F = getFlags(ea); if ( (isWord(F) || isDwrd(F)) && (!isDefArg0(F) || isOff0(F)) ) { ea_t target = calc_mem(size == 2 ? get_word(ea) : (get_long(ea) & 0xFFFFFFL)); if ( isEnabled(target) ) add_code_xref(x, target); if ( !isOff0(F) ) set_offset(ea, 0, calc_mem(0)); } break; } if ( !isload ) doVar(ea); } break; default: INTERR(10095); } }
// output an operand bool idaapi outop(op_t &x) { switch ( x.type ) { // register case o_reg: outreg(x.reg); break; // immediate case o_imm: { const ioport_t *port = find_sym(x.value); // this immediate is represented in the .cfg file if ( port != NULL ) { // output the port name instead of the numeric value out_line(port->name, COLOR_IMPNAME); } // otherwise, simply print the value else { out_symbol('#'); OutValue(x, OOFW_IMM|OOF_SIGNED); } } break; // displ @(imm, reg) case o_displ: out_symbol('@'); out_symbol('('); OutValue(x, OOF_SIGNED | OOF_ADDR | OOFW_32); out_symbol(','); OutChar(' '); outreg(x.reg); out_symbol(')'); break; // address case o_near: if ( !out_name_expr(x, toEA(cmd.cs, x.addr), x.addr) ) OutValue(x, OOF_ADDR | OOF_NUMBER | OOFS_NOSIGN | OOFW_32); break; // phrase case o_phrase: switch ( x.specflag1 ) { // @R case fRI: out_symbol('@'); if ( isDefArg(uFlag, x.n) ) { out_symbol('('); OutValue(x, 0); // will print 0 out_symbol(','); OutChar(' '); outreg(x.reg); out_symbol(')'); } else { outreg(x.reg); } break; // @R+ case fRIBA: out_symbol('@'); outreg(x.reg); out_symbol('+'); break; // @+R case fRIAA: out_symbol('@'); out_symbol('+'); outreg(x.reg); break; // @-R case fRIAS: out_symbol('@'); out_symbol('-'); outreg(x.reg); break; } break; } return 1; }
//---------------------------------------------------------------------- static void process_imm(op_t &x) { doImmd(cmd.ea); if ( isDefArg(uFlag,x.n) ) return; // if already defined by user op_num(cmd.ea, x.n); }
// emulate operand static void handle_operand(op_t &op, bool loading) { switch ( op.type ) { // Address case o_near: // branch label - create code reference (call or jump // according to the instruction) { ea_t ea = toEA(cmd.cs, op.addr); cref_t ftype = fl_JN; if ( cmd.itype == m32r_bl ) { if ( !func_does_return(ea) ) flow = false; ftype = fl_CN; } ua_add_cref(op.offb, ea, ftype); } break; // Immediate case o_imm: if ( !loading ) { interr1("handle_operand(): o_imm with CF_CHG"); } handle_imm(); // if the value was converted to an offset, then create a data xref: if ( op_adds_xrefs(uFlag, op.n) ) ua_add_off_drefs2(op, dr_O, OOFW_IMM|OOF_SIGNED); // create a comment if this immediate is represented in the .cfg file { const ioport_t * port = find_sym(op.value); if ( port != NULL && !has_cmt(uFlag) ) set_cmt(cmd.ea, port->cmt, false); } break; // Displ case o_displ: handle_imm(); // if the value was converted to an offset, then create a data xref: if ( op_adds_xrefs(uFlag, op.n) ) ua_add_off_drefs2(op, loading ? dr_R : dr_W, OOF_SIGNED|OOF_ADDR|OOFW_32); // create stack variables if required if ( may_create_stkvars() && !isDefArg(uFlag, op.n) ) { func_t *pfn = get_func(cmd.ea); if ( pfn != NULL && (op.reg == rFP || op.reg == rSP) && pfn->flags & FUNC_FRAME ) { if ( ua_stkvar2(op, op.addr, STKVAR_VALID_SIZE) ) { op_stkvar(cmd.ea, op.n); } } } break; case o_phrase: /* create stack variables if required */ if ( op.specflag1 == fRI && may_create_stkvars() && !isDefArg(uFlag, op.n) ) { func_t *pfn = get_func(cmd.ea); if ( pfn != NULL && (op.reg == rFP || op.reg == rSP) && pfn->flags & FUNC_FRAME ) { if ( ua_stkvar2(op, 0, STKVAR_VALID_SIZE) ) { op_stkvar(cmd.ea, op.n); } } } break; // Phrase - register - void : do nothing case o_reg: case o_void: break; // Others types should never be called default: interr2("handle_operand(): unknown type %d", op.type); break; } }
// Emulate an operand. static void handle_operand(op_t &op) { bool offset = false; switch ( op.type ) { case o_near: ua_add_cref(op.offb, toEA(cmd.cs, op.addr), (cmd.itype == fr_call) ? fl_CN : fl_JN); break; case o_mem: { enum dref_t mode = dr_U; if ( op.specflag1 & OP_ADDR_R ) mode = dr_R; else if ( op.specflag1 & OP_ADDR_W ) mode = dr_W; ea_t ea = toEA(cmd.cs, op.addr); ua_add_dref(op.offb, ea, mode); ua_dodata2(op.offb, ea, op.dtyp); } break; case o_imm: // if current insn is ldi:32 #imm, r1 // and next insn is call @r1, // replace the immediate value with an offset. if (cmd.itype == fr_ldi_32 && cmd.Op1.type == o_imm && cmd.Op2.type == o_reg) { const int callreg = cmd.Op2.reg; insn_t cmd_backup = cmd; if ( next_insn(cmd.ea + cmd.size ) > 0 && cmd.itype == fr_call && cmd.Op1.type == o_phrase && cmd.Op1.specflag2 == fIGR && cmd.Op1.reg == callreg) { offset = true; } const ea_t from = cmd.ea; cmd = cmd_backup; if ( !isDefArg(uFlag, 0) && offset && set_offset(cmd.ea, 0, 0) ) add_cref(from, toEA(cmd.cs, cmd.Op1.value), fl_CN); } doImmd(cmd.ea); if ( !offset ) // if the value was converted to an offset, then create a data xref: if ( isOff(uFlag, op.n) ) ua_add_off_drefs2(op, dr_O, 0); // create stack variables if necessary { bool ok = false; // ldi8 #our_value, R1 // extsb R1 // addn R14, R1 if (cmd.itype == fr_ldi_8 && cmd.Op2.type == o_reg && cmd.Op2.reg == rR1) { insn_t current_insn = cmd; next_insn(cmd.ea + cmd.size); if (cmd.itype == fr_extsb && cmd.Op1.type == o_reg && cmd.Op1.reg == rR1) { ok = true; } if ( ok ) { ok = false; next_insn(cmd.ea + cmd.size); if (cmd.itype == fr_addn && cmd.Op1.type == o_reg && cmd.Op1.reg == rR14 && cmd.Op2.type == o_reg && cmd.Op2.reg == rR1) { ok = true; } } cmd = current_insn; } // ldi32 #our_value, Ri // addn R14, Ri // // (where Ri is either R1 or R2) else if (cmd.itype == fr_ldi_32 && cmd.Op2.type == o_reg && (cmd.Op2.reg == rR1 || cmd.Op2.reg == rR2)) { ushort the_reg = cmd.Op2.reg; insn_t current_insn = cmd; next_insn(cmd.ea + cmd.size); if (cmd.itype == fr_addn && cmd.Op1.type == o_reg && cmd.Op1.reg == rR14 && cmd.Op2.type == o_reg && cmd.Op2.reg == the_reg) { ok = true; } cmd = current_insn; } if ( ok && may_create_stkvars() && !isDefArg(uFlag, op.n) ) { func_t *pfn = get_func(cmd.ea); if ( pfn != NULL && pfn->flags & FUNC_FRAME ) { if ( ua_stkvar2(op, op.value, 0) ) { op_stkvar(cmd.ea, op.n); } } } } break; case o_displ: case o_phrase: // XXX case o_reglist: case o_void: case o_reg: break; default: INTERR(10017); } }
//---------------------------------------------------------------------- static void TouchArg(op_t &x,int isAlt,int isload) { switch (x.type) { case o_phrase: //Добавляем в список ошибок(выводим сообщение) //ошибку и адресс где это случилось //QueueMark(Q_jumps, cmd.ea); case o_void: case o_reg: break; case o_imm: { //Установить для данного байта признак immedia doImmd(cmd.ea); //Получить флаг для указанного линейного адресса if(!isAlt) { uint32 offb; ushort addr = ushort(x.addr); if(x.type == o_displ ) { addr += (ushort)cmd.ip; addr += cmd.size; //Получить линейный адресс offb = (uint32)toEA(codeSeg(addr,x.n), 0); DataSet(x, offb+addr, isload); } else if ( isOff(uFlag, x.n) ) { reref: ua_add_off_drefs(x, dr_O); if ( x.type == o_displ ) //Преобразовать данные по указанному линейному адрессу в указанный тип ua_dodata2(x.offb, calc_target(cmd.ea+x.offb, cmd.ea, x.n, x.addr), x.dtyp); } else if(x.type == o_displ && !x.reg && !isDefArg(uFlag, x.n) && set_offset(cmd.ea, x.n, toEA(cmd.cs,0))) goto reref; } } break; case o_bit: case o_mem: // Конвертирование в данные(указан адресс) по указанному типу, //добавить крос референсы для текущей инструкции DataSet(x, toEA(codeSeg(x.addr,x.n), x.addr), isload); break; case o_near: { //Получить линейный адресс ea_t ea = toEA(cmd.cs, x.addr); //Проверить является ли значение по указанному линейному адрессу - инструкцией int iscall = InstrIsSet(cmd.itype, CF_CALL); //добавить крос референсы для текущей инструкции ua_add_cref(x.offb, ea, iscall ? fl_CN : fl_JN); if ( iscall ) flow = func_does_return(ea); } break; default: warning("%a: %s,%d: bad optype %d", cmd.ea, cmd.get_canon_mnem(), x.n, x.type); break; } }