static void handle_operand(op_t &op) { switch (op.type) { // code address case o_near: { ea_t ea = toEA(cmd.cs, op.addr); cref_t mode = fl_JN; if (cmd.itype == m740_jsr) { if ( !func_does_return(ea) ) flow = false; mode = fl_CN; } ua_add_cref(op.offb, ea, mode); } break; // data address case o_mem: { enum dref_t mode = dr_U; if (is_addr_ind(op)) mode = dr_R; /* NOT dr_O */ else if (is_addr_read(op)) mode = dr_R; else if (is_addr_write(op)) mode = dr_W; ua_add_dref(op.offb, toEA(cmd.cs, op.addr), mode); ua_dodata2(op.offb, op.addr, op.dtyp); } break; // immediate case o_imm: handle_imm(op); // 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; // displ case o_displ: if (isOff(uFlag, op.n)) { ua_add_off_drefs2(op, dr_O, OOF_ADDR); ua_dodata2(op.offb, op.addr, op.dtyp); } break; // reg - do nothing case o_reg: case o_void: break; default: IDA_ERROR("Invalid op.type in handle_operand()"); } }
//---------------------------------------------------------------------- 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 TouchArg(op_t &x,int isAlt,int isload) { switch ( x.type ) { case o_reg: case o_phrase: case o_port: break; case o_imm: if ( !isload ) goto badTouch; doImmdValue(x.n); if ( isOff(uFlag, x.n) ) ua_add_off_drefs2(x, dr_O, OOF_SIGNED); break; case o_displ: doImmdValue(x.n); if ( isAlt ) break; if ( isOff(uFlag, x.n) ) { ua_add_off_drefs2(x, isload ? dr_R : dr_W, OOF_ADDR); ea_t ea = calc_target(cmd.ea+x.offb, cmd.ea, x.n, x.addr); ua_dodata2(x.offb, ea, x.dtyp); if ( !isload ) doVar(ea); } break; case o_near: { cref_t ftype = fl_JN; ea_t ea = toEA(cmd.cs, x.addr); if ( InstrIsSet(cmd.itype, CF_CALL) ) { if ( !func_does_return(ea) ) flow = false; ftype = fl_CN; } ua_add_cref(x.offb, ea, ftype); } break; case o_mem: { ea_t ea = toEA(dataSeg(), x.addr); ua_add_dref(x.offb, ea, isload ? dr_R : dr_W); } break; default: badTouch: if ( cmd.itype != AVR_lpm && cmd.itype != AVR_elpm ) warning("%a: %s,%d: bad optype %d", cmd.ea, cmd.get_canon_mnem(), x.n, x.type); break; } }
ea_t calc_io_mem(op_t &op) { ea_t addr = op.addr; sel_t pdp = 0; if (op.tms_regP == PDP) { pdp = getSR(toEA(cmd.cs, cmd.ip), PDP); if ( pdp == BADSEL ) return BADSEL; addr &= 0x7F; } ea_t ea = ((pdp & 0x1FF) << 7) | addr; return toEA(cmd.cs, ea); }
static void TouchArg( op_t &x, int isload ) { switch( x.type ) { case o_imm: case o_displ: if ( isOff(uFlag, x.n) ) ua_add_off_drefs(x, dr_O); break; case o_mem: case o_ind_mem: { ulong dea = intmem + x.addr; ua_dodata( dea, x.dtyp ); if( !isload ) doVar( dea ); ua_add_dref( x.offb, dea, isload ? dr_R : dr_W ); } break; case o_near: ulong 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 ) { if ( !func_does_return(ea) ) flow = false; } } }
/* outputs an operand 'x' */ bool outop(op_t &x) { // const char *ptr; ea_t v; switch (x.type) { case o_reg: out_register(ph.regNames[x.reg]); break; case o_imm: OutValue(x, OOFS_IFSIGN | OOFW_IMM); break; case o_mem: case o_near: v=toEA(cmd.cs, x.addr); if ( !out_name_expr(x, v, x.addr) ) { OutValue(x, OOF_ADDR | OOF_NUMBER | OOFS_NOSIGN | OOFW_32); QueueMark(Q_noName, cmd.ea); break; } break; default: out_symbol('?'); break; } return 1; }
static void TouchArg( op_t &x, int isload ) { switch( x.type ) { case o_displ: case o_imm: if ( isOff(uFlag, x.n) ) { int outf = x.type != o_imm ? OOF_ADDR : 0; ua_add_off_drefs2(x, dr_O, outf|OOF_SIGNED); } break; case o_mem: case o_ind_mem: { ea_t dea = intmem + x.addr; ua_dodata2(x.offb, dea, x.dtyp); if( !isload ) doVar( dea ); ua_add_dref( x.offb, dea, isload ? dr_R : dr_W ); } 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 ) { if ( !func_does_return(ea) ) flow = false; } } }
//---------------------------------------------------------------------- int find_ar(ea_t *res) { ea_t ea = cmd.ea; for ( int i=0; i < lookback; i++ ) { ea = prevInstruction(ea); if ( !isCode(get_flags_novalue(ea)) ) break; ushort code = (ushort)get_full_byte(ea); if ( isC2() ) { switch ( code >> 11 ) { case 6: // LAR return 0; case 0x18: // LARK *res = toEA(dataSeg(),(code & 0xFF)); return 1; case 0x1A: // LRLK if ( (code & 0xF8FF) == 0xD000 ) { ushort b = (ushort)get_full_byte(ea+1); *res = toEA(dataSeg(), b); return 1; } } continue; } switch ( code >> 11 ) { case 0: // Load AR from addressed data return 0; // LAR found, unknown address case 0x16: // Load AR short immediate *res = toEA(dataSeg(), code & 0xFF); return 1; case 0x17: // Load AR long immediate if ( (code & ~7) == 0xBF08 ) { ushort b = (ushort)get_full_byte(ea+1); *res = toEA(dataSeg(),b); return 1; } } } return 0; }
//---------------------------------------------------------------------- // Calculate the target data address ea_t map_addr(asize_t off, int opnum, bool isdata) { if ( isdata ) { if ( isOff(uFlag, opnum) ) return get_offbase(cmd.ea, opnum) >> 4; return ((off >= 0x80 && off < 0x100) ? sfrmem : intmem) + off; } return toEA(codeSeg(off, opnum), off); }
//---------------------------------------------------------------------- bool outop( op_t &x ) { uval_t v, v1; // const char *ptr; switch( x.type ) { case o_imm: out_symbol( '#' ); OutValue( x, OOF_SIGNED | OOFW_IMM ); break; case o_indexed: OutValue( x, OOF_ADDR|OOF_SIGNED|(is_ext_insn() ? OOFW_32 : OOFW_16) ); //.addr v = x.value; out_symbol( '[' ); if ( v != 0 ) goto OUTPHRASE; out_symbol( ']' ); break; case o_indirect: case o_indirect_inc: out_symbol( '[' ); case o_mem: case o_near: v = x.addr; OUTPHRASE: v1 = toEA( getSR(cmd.ea, (x.type == o_near) ? rVcs : rVds), v); if( !out_name_expr( x, v1, v ) ) { OutValue( x, (x.type == o_indexed ? 0 : OOF_ADDR) | OOF_NUMBER|OOFS_NOSIGN| ((x.type == o_near) ? (is_ext_insn() ? OOFW_32 : OOFW_16) : OOFW_8) ); QueueMark( Q_noName, cmd.ea ); } if( x.type == o_indirect || x.type == o_indirect_inc || x.type == o_indexed ) { out_symbol( ']' ); if( x.type == o_indirect_inc ) out_symbol( '+' ); } break; case o_void: return 0; case o_bit: out_symbol( char('0' + x.reg) ); break; default: warning( "out: %a: bad optype %d", cmd.ea, x.type ); } return 1; }
//------------------------------------------------------------------------ ea_t calc_data_mem(op_t &op) { ea_t addr = op.addr; sel_t dph = 0; if (op.tms_regH == DPH) { dph = getSR(toEA(cmd.cs, cmd.ip), DPH); if ( dph == BADSEL ) return BADSEL; addr &= 0xFFFF; } sel_t dp = 0; if (op.tms_regP == DP) { dp = getSR(toEA(cmd.cs, cmd.ip), DP); if ( dp == BADSEL ) return BADSEL; addr &= 0xFFFF; } return (((dph & 0x7F) << 16) | (dp + addr)) << 1; }
//------------------------------------------------------------------------ ea_t calc_code_mem(ea_t ea, bool is_near) { if (is_near) { sel_t xpc = getSR(cmd.ea, XPC); if ( xpc == BADSEL ) xpc = 0; return ((xpc & 0x7F) << 16) | (ea & 0xFFFF); } return toEA(cmd.cs, ea); }
//---------------------------------------------------------------------- // Calculate the target data address ea_t map_addr(asize_t off, int opnum, bool isdata) { if ( isdata ) { if ( isOff(uFlag, opnum) ) return get_offbase(cmd.ea, opnum) >> 4; return intmem + off; } return toEA(codeSeg(off, opnum), off); }
// This function finds and creates a 32-bit jump table static bool check_for_table_jump2(is_pattern_t * const patterns[], size_t qty, void (*create_table)(jump_table_type_t jtt, switch_info_ex_t &si), switch_info_ex_t &si) { jump_table_type_t jtt = JT_NONE; insn_t saved = cmd; for ( int i=0; jtt == JT_NONE && i < qty; i++ ) { jmsg("%a: check pattern %d ----\n", cmd.ea, i); si.clear(); jtt = patterns[i](si); cmd = saved; } if ( jtt == JT_NONE ) return false; jmsg("jumps=%a lowcase=%d. ncases=%d. elbase=%a defjump=%a\n", si.jumps, si.lowcase, si.ncases, si.elbase, si.defjump); if ( si.jumps != BADADDR ) si.jumps = toEA(cmd.cs, si.jumps); if ( si.elbase != BADADDR ) { si.elbase = toEA(cmd.cs, si.elbase); si.flags |=SWI_ELBASE; } if ( si.defjump != BADADDR ) si.defjump = toEA(cmd.cs, si.defjump); if ( create_table == NULL ) create_table = check_and_create_flat32; create_table(jtt, si); char buf[MAXSTR]; qsnprintf(buf, sizeof(buf), "def_%a", cmd.ip); set_name(si.defjump, buf, SN_NOWARN|SN_LOCAL); qsnprintf(buf, sizeof(buf), "jpt_%a", cmd.ip); set_name(si.jumps, buf, SN_NOWARN); // msg("final size=%d.\n", size); return true; }
//-------------------------------------------------------------------------- static void declare_class(ea_t ea, const char *entryname) { static const char class_name[] = "ClassStruct"; struc_t *sptr = get_struc(get_struc_id(class_name)); if ( sptr == NULL ) { sptr = get_struc(add_struc(BADADDR, class_name)); if ( sptr == NULL ) return; opinfo_t mt; mt.ri.flags = REF_OFF32; mt.ri.target = BADADDR; mt.ri.base = 0; mt.ri.tdelta = 0; add_struc_member(sptr, "superClass", BADADDR, offflag()|dwrdflag(), &mt, 4); add_struc_member(sptr, "masterOffset", BADADDR, wordflag(), NULL, 2); add_struc_member(sptr, "methodCount", BADADDR, decflag()|wordflag(), NULL, 2); add_struc_member(sptr, "instanceSize", BADADDR, decflag()|wordflag(), NULL, 2); add_struc_member(sptr, "vdRelocTable", BADADDR, wordflag(), NULL, 2); add_struc_member(sptr, "relocTable", BADADDR, wordflag(), NULL, 2); mt.ec.tid = get_class_struct_flags_enum(); mt.ec.serial = 0; add_struc_member(sptr, "flags", BADADDR, enumflag()|byteflag(), &mt, 1); add_struc_member(sptr, "masterMethods",BADADDR, byteflag(), NULL, 1); } asize_t size = get_struc_size(sptr); doStruct(ea, size, sptr->id); int count = get_word(ea+6); // bool c_handlers = get_byte(ea+14) & (1<<6); ea += size; ea_t messages = ea; doWord(ea, count*2); op_dec(ea, 0); ea += 2*count; doDwrd(ea, count*4); set_offset(ea, 0, 0); for ( int i=0; i < count; i++ ) { ea_t idx = ea + 4*i; ea_t pea = toEA(get_word(idx+2), get_word(idx)); auto_make_proc(pea); char name[MAXSTR]; qsnprintf(name, sizeof(name), "%s_%u", entryname, get_word(messages+2*i)); add_entry(pea, pea, name, true); } // commented out because it doesn't work properly // see geoplan.geo, entry number 1 for example // if ( c_handlers ) // declare_parameter_types(ea+count*4, count); }
//---------------------------------------------------------------------- static int OutVarName(op_t &x, int iscode, int relative) { //char *ptr; ushort addr = ushort(x.addr); if(relative) { addr += (ushort)cmd.ip; addr += cmd.size; // ig: this is tested only for 6809 } //Получить линейный адресс ea_t toea = toEA((iscode || relative) ? codeSeg(addr,x.n) : dataSeg_op(x.n), addr); //Получть строку для данного лин. адресса return out_name_expr(x, toea, addr); }
static void OutVarNameVal(op_t &x) { ushort addr = x.value; ulong toea = toEA(codeSeg(addr,x.n), addr); #if IDP_INTERFACE_VERSION > 37 if(out_name_expr(x,toea,addr))return; #else const char *ptr; if((ptr=get_name_expr(cmd.ea+x.offb, toea, addr)) != NULL){ //вывод имен переменных и меток перехода OutLine(ptr); } #endif else OutValue(x, OOFW_16); }
// output an address static void outaddr(op_t &op, const bool replace_with_label = true) { bool ind = is_addr_ind(op); // is operand indirect ? bool sp = is_addr_sp(op); // is operand special page ? int size = 16; // operand is 16 bits long if ( ind) out_symbol('(' ); if ( sp) { out_symbol('\\' ); size = 8; /* just display the first 8 bits */ } if ( !out_name_expr(op, toEA(cmd.cs, op.addr), op.addr) || !replace_with_label) { if ( replace_with_label) out_tagon(COLOR_ERROR ); OutValue(op, OOF_ADDR | OOFS_NOSIGN | (size < 16 ? OOFW_8 : OOFW_16) ); if ( replace_with_label) out_tagoff(COLOR_ERROR ); } if ( ind) out_symbol(')' ); }
//---------------------------------------------------------------------- int emu(void) { uint32 feature = cmd.get_canon_feature(); flow = (feature & CF_STOP) == 0; if ((cmd.auxpref & DBrFlag) == 0) // У отложенных переходов не надо обрабатывать операнды, т.к. // регистры и так не обрабатываются, а адр. перехода будет обработан через 3 команды { if ( feature & CF_USE1 ) process_operand(cmd.Op1, 1); if ( feature & CF_USE2 ) process_operand(cmd.Op2, 1); if ( feature & CF_USE3 ) process_operand(cmd.Op3, 1); if ( feature & CF_CHG1 ) process_operand(cmd.Op1, 0); if ( feature & CF_CHG2 ) process_operand(cmd.Op2, 0); if ( feature & CF_CHG3 ) process_operand(cmd.Op3, 0); } if (GetDelayedBranchAdr() != BADADDR) // добавить ссылку по отложенному переходу ua_add_cref(0, toEA(cmd.cs, GetDelayedBranchAdr()), fl_JN); if (cmd.itype == TMS320C3X_RETScond) // добавить ссылку по условному выходу ua_add_cref(0, cmd.ea, fl_JN); // check for DP changes if ( ((cmd.itype == TMS320C3X_LDIcond) || (cmd.itype == TMS320C3X_LDI)) && (cmd.Op1.type == o_imm) && (cmd.Op2.type == o_reg) && (cmd.Op2.reg == dp)) splitSRarea1(get_item_end(cmd.ea), dp, cmd.Op1.value & 0xFF, SR_auto); // determine if the next instruction should be executed if ( segtype(cmd.ea) == SEG_XTRN ) flow = 0; if ( flow && delayed_stop() ) flow = 0; if ( flow ) ua_add_cref(0,cmd.ea+cmd.size,fl_F); if ( may_trace_sp() ) { if ( !flow ) recalc_spd(cmd.ea); // recalculate SP register for the next insn else trace_sp(); } return 1; }
//---------------------------------------------------------------------- static void SaveArg(op_t &x) { switch ( x.type ) { case o_reg: { // if ( x.reg == R_sp ) return; // AbstractRegister *out = &i5_getreg(x.reg); // if ( ! isDef(r) ) { // out->undef(); // } else { // out->doInt(r.value()); // } return; } case o_mem: { ea_t ea = toEA(dataSeg_op(x.n),x.addr); ua_dodata2(x.offb, ea, x.dtyp); doVar(ea); ua_add_dref(x.offb,ea,dr_W); } break; case o_displ: doImmdValue(x.n); if ( isOff(uFlag, x.n) ) ua_add_off_drefs2(x, dr_W, OOF_ADDR); case o_phrase: break; default: switch ( cmd.itype ) { case Z80_in0: case Z80_outaw: break; default: // warning("%a: %s,%d: bad save optype %d", cmd.ea, cmd.get_canon_mnem(), x.n, x.type); break; } break; } }
//---------------------------------------------------------------------- // This is jump table pattern #2 // (*1* may be omitted...IE, this logic is located above jump table sizing instructions) //0100 *1* sub.b r0h, r0h //0102 add.w r0, r0 //0104 mov.w @(jpt_108:16,r0), r0 //0108 jmp @r0 //---------------------------------------------------------------------- static bool is_jump_pattern2(ea_t *base, ea_t *table, ea_t *defea, int *size, int *elsize) { int reg = cmd.Op1.phrase; if ( decode_prev_insn(cmd.ea) == BADADDR || cmd.itype != H8_mov // mov.w @(table:16,r0), r0 || (cmd.auxpref & aux_word) == 0 || cmd.Op1.type != o_displ || cmd.Op2.reg != reg ) return false; *table = cmd.Op1.addr; int rx = cmd.Op1.reg; *base = 0; ea_t bea = toEA(cmd.cs, 0); set_offset(cmd.ea, 0, bea); if ( decode_prev_insn(cmd.ea) == BADADDR || cmd.itype != H8_add // add.w r0, r0 || (cmd.auxpref & aux_word) == 0 || cmd.Op1.type != o_reg || cmd.Op1.reg != rx || cmd.Op2.reg != rx ) return false; int rhx = rx + 16; int rlx = rhx + 8; ea_t oldea = cmd.ea; ea_t oldip = cmd.ip; if ( decode_prev_insn(cmd.ea) == BADADDR || (cmd.itype != H8_sub && cmd.itype != H8_xor) // sub.b rhx, rhx || (cmd.auxpref & aux_byte) == 0 || cmd.Op1.type != o_reg || cmd.Op2.type != o_reg || cmd.Op1.reg != rhx || cmd.Op2.reg != rhx ) // return false; { cmd.ea = oldea; // forgive this... cmd.ip = oldip; } // the jump table is found, try to determine its size *elsize = 2; return find_table_size(defea, size, rlx, cmd.ip); }
//---------------------------------------------------------------------- ea_t calc_mem(op_t &x) { uint xaddr; if ( x.amode & amode_x ) { if (x.amode & amode_short) { sel_t dpage = getSR(cmd.ea, PAGE); if ( dpage == BADSEL ) return BADSEL; xaddr = ((dpage & 0xFF) << 8) | uint(x.addr); } else xaddr = (uint)x.addr; return xmem == BADADDR ? BADADDR : xmem + xaddr; } return toEA(cmd.cs, x.addr); }
static void OutVarName(op_t &x) { ea_t addr = x.addr; ea_t toea = toEA(codeSeg(addr,x.n), addr); #if IDP_INTERFACE_VERSION > 37 // msg("AT:%a target=%lx, segm=%lx, Result=%lx\n", // cmd.ea,addr, codeSeg(addr,x.n),toea); if ( out_name_expr(x,toea,addr) )return; #else const char *ptr; if ( (ptr=get_name_expr(cmd.ea+x.offb, toea, addr)) != NULL ){ //вывод имен переменных и меток перехода OutLine(ptr); } #endif else{ OutValue(x, OOF_ADDR | OOF_NUMBER | OOFS_NOSIGN | OOFW_32); // пометим проблему - нет имени QueueMark(Q_noName,cmd.ea); } }
//---------------------------------------------------------------------- ea_t calc_mem(op_t &x) { if ( x.type == o_near ) return toEA(cmd.cs, x.addr); // Before this was simply toEA, now we do it like this: // (if someone complains, both methods should be retained) ea_t ea = x.addr; switch ( calc_sizer(x) ) { case 8: if ( cmd.auxpref & aux_page ) { ea &= 0xFF; sel_t br = getSR(cmd.ea, BR); if ( br != BADSEL ) ea |= br << 8; else ea = BADADDR; } break; case 16: ea &= 0xFFFF; if ( x.type == o_mem ) { sel_t dp = getSR(cmd.ea, DP); if ( dp != BADSEL ) ea |= dp << 16; else ea = BADADDR; } else { ea |= cmd.ea & ~0xFFFF; } break; } return ea; }
//---------------------------------------------------------------------- static void TouchArg(op_t &x,int isload) { switch ( x.type ) { case o_regpair: case o_reg: case o_phrase: case o_spmask: case o_stgcyc: break; case o_imm: if ( !isload ) goto badTouch; /* no break */ case o_displ: doImmdValue(x.n); if ( op_adds_xrefs(uFlag, x.n) ) { int outf = x.type != o_imm ? OOF_ADDR : 0; if ( x.dtyp == dt_word ) outf |= OOF_SIGNED; ua_add_off_drefs2(x, dr_O, outf); } break; case o_near: { ea_t ea = toEA(cmd.cs,x.addr); ea_t ref = find_first_insn_in_packet(ea); ua_add_cref(x.offb, ref, fl_JN); } break; default: badTouch: warning("%a: %s,%d: bad optype %d", cmd.ea, cmd.get_canon_mnem(), x.n, x.type); break; } }
//---------------------------------------------------------------------- static void TouchArg(op_t &x,int isload) { switch ( x.type ) { case o_regpair: case o_reg: case o_phrase: break; case o_imm: if ( !isload ) goto badTouch; /* no break */ case o_displ: doImmdValue(x.n); if ( isOff(uFlag, x.n) ) ua_add_off_drefs(x, dr_O); break; case o_near: ua_add_cref(x.offb,toEA(cmd.cs,x.addr),fl_JN); break; default: badTouch: warning("%a: %s,%d: bad optype %d", cmd.ea, cmd.get_canon_mnem(), x.n, x.type); break; } }
//---------------------------------------------------------------------- // поставим использование/изменение операндов static void near TouchArg(op_t &x,int isAlt,int isload) { ea_t ea = toEA(codeSeg(x.addr,x.n), x.addr); switch ( x.type ) { // эта часть не используется ! case o_void: break; // тут тоже нечего делать case o_reg: break; // непосредственный операнд case o_imm: // непосредственный не может меняться if ( ! isload ) goto badTouch; // поставим флажок непосредственного операнда doImmd(cmd.ea); // если не форсирован и помечен смещением if ( !isAlt && isOff(uFlag,x.n) ) // это смещение ! ua_add_dref(x.offb,ea,dr_O); break; // переход или вызов case o_near: // это вызов ? (или переход) if(InstrIsSet(cmd.itype,CF_CALL)){ // поставим ссылку на код ua_add_cref(x.offb,ea,fl_CN); // это функция без возврата ? #if IDP_INTERFACE_VERSION > 37 flow = func_does_return(ea); #else // получим описатель функции func_t *pfn = get_func(ea); // если функция описана и не имеет возврата - остановим if(pfn != NULL && (pfn->flags & FUNC_NORET) ) flow = false; #endif } else ua_add_cref(x.offb,ea,fl_JN); break; // ссылка на ячейку памяти case o_mem: // сделаем данные по указанному адресу ua_dodata2(x.offb, ea, x.dtyp); // если изменяется - поставим переменную if ( ! isload ) doVar(ea); // добавим ссылку на память ua_add_dref(x.offb,ea,isload ? dr_R : dr_W); break; // прочее - сообщим ошибку default: badTouch: #if IDP_INTERFACE_VERSION > 37 warning("%a %s,%d: bad optype %d", cmd.ea, cmd.get_canon_mnem(), #else warning("%08lX %s,%d: bad optype (%x)", cmd.ea,(char far *)Instructions[cmd.itype].name, #endif x.n, x.type); break; } }
static int notify(processor_t::idp_notify msgid, ...) // Various messages { va_list va; va_start(va, msgid); // A well behaving processor module should call invoke_callbacks() // in his notify() function. If this function returns 0, then // the processor module should process the notification itself // Otherwise the code should be returned to the caller: int code = invoke_callbacks(HT_IDP, msgid, va); if ( code ) return code; switch ( msgid ) { case processor_t::newfile: { // ig: вообще у меня теперь такая точка зрения: // не надо в коде задавать вид имен. // при желании это можно сделать в ida.cfg: // #ifdef __80196__ // DUMMY_NAMES_TYPE = NM_SHORT // #endif segment_t *sptr = get_first_seg(); if( sptr != NULL ) set_segm_class( sptr, "CODE" ); ea_t ea, ea1; for( int i = 0; i < qnumber(entries); i++ ) { ea = toEA( inf.baseaddr, entries[i].off ); if( isEnabled(ea) ) { switch( entries[i].type ) { case I196F_BTS: doByte( ea, entries[i+1].off-entries[i].off ); set_cmt( ea, entries[i].cmt, 0 ); break; case I196F_CMT: if( entries[i].cmt ) add_long_cmt( ea, 1, "%s", entries[i].cmt ); else describe( ea, 1, "" ); break; case I196F_OFF: doWord( ea, 2 ); set_offset( ea, 0, toEA( inf.baseaddr, 0 ) ); ea1 = toEA( inf.baseaddr, get_word( ea ) ); auto_make_proc( ea1 ); //dash: long_cmt здесь не смотрится, так как рисуется до заголовка // хорошо бы поставить func_cmt, но к этому моменту функций еще нет // как быть? //ig: воспользоваться простым комментарием // при создании функции комментарий перетащится set_cmt( ea1, entries[i].cmt, 1 ); } set_name( ea, entries[i].name ); } } ea = toEA( inf.baseaddr, 0x2080 ); if( isEnabled( ea ) ) { inf.beginEA = ea; inf.startIP = 0x2080; } segment_t s; s.startEA = toEA( inf.baseaddr, 0 ); s.endEA = toEA( inf.baseaddr, 0x400 ); s.sel = inf.baseaddr; s.type = SEG_IMEM; // internal memory // ig: лучше искать дырку не от нуля, а от базы загрузки // ea_t bottom = toEA( inf.baseaddr, 0 ); // intmem = s.startEA = freechunk( bottom, 1024, 0xF ); // s.endEA = s.startEA + 1024; // s.sel = ushort(s.startEA >> 4); // dash: дырку искать не пришлось, но я оставил это как пример на будущее add_segm_ex( &s, "INTMEM", NULL, ADDSEG_OR_DIE); predefined_t *ptr; for( ptr = iregs; ptr->name != NULL; ptr++ ) { ea_t ea = toEA( inf.baseaddr, ptr->addr ); ea_t oldea = get_name_ea( BADADDR, ptr->name ); if( oldea != ea ) { if( oldea != BADADDR ) set_name( oldea, NULL ); do_unknown( ea, DOUNK_EXPAND ); set_name( ea, ptr->name ); } if( ptr->cmt != NULL ) set_cmt( ea, ptr->cmt, 1 ); } } // do16bit( 0x18, 2 ); // SP always word break; case processor_t::oldfile: for ( segment_t *s=get_first_seg(); s != NULL; s=get_next_seg(s->startEA) ) { if ( getSRarea(s->startEA) == NULL ) { segreg_t sr; sr.startEA = s->startEA; sr.endEA = s->endEA; sr.reg(WSR) = 0; sr.reg(WSR1) = 0; sr.reg(rVds) = inf.baseaddr; sr.settags(SR_autostart); SRareas.create_area(&sr); } } break; case processor_t::newseg: // default DS is equal to Base Address (va_arg(va, segment_t *))->defsr[rVds-ph.regFirstSreg] = inf.baseaddr; break; case processor_t::newprc: extended = va_arg(va,int) != 0; if ( !extended ) ph.flag &= ~PR_SEGS; else ph.flag |= PR_SEGS; default: break; } va_end(va); return(1); }
// Output an operand as an address inline void out_addr(op_t &op, bool find_label = true) { if ( !find_label || !out_name_expr(op, toEA(cmd.cs, op.addr), op.addr) ) OutValue(op, OOF_ADDR | OOFS_NOSIGN); }
//---------------------------------------------------------------------- static int LoadArg(op_t &x) { dref_t xreftype; switch ( x.type ) { case o_reg: { if ( x.reg == R_sp ) goto Undefined; // AbstractRegister *in = &i5_getreg(x.reg); // if ( ! in->isDef() ) goto Undefined; // r.doInt(in->value()); return 1; } case o_imm: // r.doInt(unsigned(x.value)); xreftype = dr_O; MakeImm: doImmdValue(x.n); if ( isOff(uFlag, x.n) ) ua_add_off_drefs2(x, xreftype, 0); return 1; case o_displ: // r.undef(); xreftype = dr_R; goto MakeImm; case o_mem: { ea_t ea = toEA(dataSeg_op(x.n),x.addr); ua_add_dref(x.offb,ea,dr_R); ua_dodata2(x.offb, ea, x.dtyp); if ( !isVar(get_flags_novalue(ea)) && isLoaded(ea) ) { // r.doInt( x.dtyp != dt_byte ? get_word(ea) : char(get_byte(ea)) ); return 1; } } case o_phrase: Undefined: // r.undef(); break; case o_near: { ea_t segbase = codeSeg(x.addr,x.n); ea_t ea = toEA(segbase,x.addr); ea_t thisseg = cmd.cs; int iscall = InstrIsSet(cmd.itype,CF_CALL); ua_add_cref(x.offb, ea, iscall ? ((segbase == thisseg) ? fl_CN : fl_CF) : ((segbase == thisseg) ? fl_JN : fl_JF)); if ( iscall && !func_does_return(ea) ) flow = false; // r.doInt(unsigned(x.addr)); } return 1; default: // warning("%a: %s,%d: bad load optype %d", cmd.ea, cmd.get_canon_mnem(), x.n, x.type); break; } return 0; }