processor_t LPH = { … ana, // analyze an instruction and fill the 'cmd' structure emu, // emulate an instruction out, // generate a text representation of an instruction outop, // generate a text representation of an operand … }
int idaapi ana(void); //analyze one instruction and return the // instruction length
int idaapi emu(void); //emulate one instruction
void idaapi out(void); //output a single disassembled instruction
bool idaapi outop(op_t &x); //output an operand of disassembled // instruction
class insn_t { public: ea_t cs; // Current segment base paragraph. Set by kernel ea_t ip; // Virtual address of instruction (within segment). // Set by kernel ea_t ea; // Linear address of the instruction. Set by kernel uint16 itype; // instruction enum value (not opcode!). // Proc sets this in ana uint16 size; // Size of instruction in bytes. Proc sets this in ana union { // processor dependent field. Proc may set this uint16 auxpref; struct { uchar low; uchar high; } auxpref_chars; }; char segpref; // processor dependent field. Proc may set this char insnpref; // processor dependent field. Proc may set this op_t Operands[6]; // instruction operand info. Proc sets this in ana char flags; // instruction flags. Proc may set this };
#// 0x00 0000 0000 BRK M16C_BRK = 0x00 @ { cmd.itype = M16C_xx_BRK; cmd.Op1.type = o_void; cmd.Op1.dtyp = dt_void; };
#// 0x01..0x03 0000 00DS MOV.B:S R0L, DEST M16C_MOV_B_S_R0L_DEST = (0x01..0x03) @ { cmd.itype = M16C_xx_MOV_B_S_R0L_DEST; MakeSrcDest8(SRC_DEST_R0L, cmd.Op1); switch(*p & 0x03) { case 0x01: MakeSrcDest8(SRC_DEST_DSP_8_SB_, cmd.Op2); break; case 0x02: MakeSrcDest8(SRC_DEST_DSP_8_FB_, cmd.Op2); break; default: MakeSrcDest8(SRC_DEST_ABS16, cmd.Op2); break; } };
instruc_t instructions[ ] = { ... { "ADC.B", CF_USE1|CF_CHG2 }, { "ADC.W", CF_USE1|CF_CHG2 }, { "ADC.B", CF_USE1|CF_CHG2 }, { "ADC.W", CF_USE1|CF_CHG2 }, { "ADCF.B", CF_CHG1 }, { "ADCF.W", CF_CHG1 }, { "ADD.B:G", CF_USE1|CF_CHG2 }, { "ADD.W:G", CF_USE1|CF_CHG2 }, { "ADD.B:Q", CF_USE1|CF_CHG2 }, ... };
[ Syntax ] ADC.size src,dest ^--- B, W [ Operation ] dest <- src + dest + C
int emu( ) { unsigned long feature = cmd.get_canon_feature( ); if( feature & CF_USE1 ) TouchArg( cmd.Op1, 1 ); if( feature & CF_USE2 ) TouchArg( cmd.Op2, 1 ); if( feature & CF_CHG1 ) TouchArg( cmd.Op1, 0 ); if( feature & CF_CHG2 ) TouchArg( cmd.Op2, 0 ); if( !( feature & CF_STOP ) ) ua_add_cref( 0, cmd.ea + cmd.size, fl_F); return 1; }
void TouchArg( op_t &x, int isload ) { switch ( x.type ) { 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_imm: if ( !isload ) break; op_num(cmd.ea, xn); if ( isOff(uFlag, xn) ) ua_add_off_drefs2(x, dr_O, OOF_SIGNED); break; case o_displ: if(x.dtyp == dt_byte) op_dec(cmd.ea, xn); break; case o_mem: { ea_t ea = toEA( dataSeg( ),x.addr ); ua_dodata2( x.offb, ea, x.dtyp ); if ( !isload ) doVar( ea ); ua_add_dref( x.offb, ea, isload ? dr_R : dr_W ); } break; default: break; } }
void out() { char str[MAXSTR]; //MAXSTR is an IDA define from pro.h init_output_buffer(str, sizeof(str)); OutMnem(12); //first we output the mnemonic if( cmd.Op1.type != o_void ) //then there is an argument to print out_one_operand( 0 ); if( cmd.Op2.type != o_void ) { //then there is an argument to print out_symbol(','); out_symbol(' '); out_one_operand( 1 ); } if( cmd.Op3.type != o_void ) { //then there is an argument to print out_symbol(','); out_symbol(' '); out_one_operand( 2 ); } term_output_buffer(); gl_comm = 1; //we want comments! MakeLine(str); //output the line with default indentation }
bool idaapi outop(op_t &x) { ea_t ea; switch (x.type) { case o_void: return 0; case o_imm: OutValue(x, OOF_NUMBER | OOF_SIGNED | OOFW_IMM); break; case o_displ: { //then there is an argument to print OutValue(x, OOF_NUMBER | OOF_SIGNED | OOFW_IMM); switch (x.dtyp) { case dt_byte: break; case dt_word: out_symbol(':'); out_symbol('8'); break; case dt_dword: out_symbol(':'); out_symbol('1'); out_symbol('6'); break; default: ea = toEA(cmd.cs, x.addr); if (!out_name_expr(x, ea, x.addr)) out_bad_address(x.addr); break; } out_symbol('['); out_register(M16C_xx_RegNames[x.reg]); out_symbol(']'); } break; case o_phrase: out_symbol('['); out_register(M16C_xx_RegNames[x.reg]); out_symbol(']'); break; case o_near: ea = toEA(cmd.cs, x.addr); if (!out_name_expr(x, ea, x.addr)) out_bad_address(x.addr); break; case o_mem: ea = toEA(dataSeg(), x.addr); if (!out_name_expr(x, ea, x.addr)) out_bad_address(x.addr); break; case o_reg: out_register(M16C_xx_RegNames[x.reg]); break; default: warning("out: %a: bad optype %d", cmd.ea, x.type); break; } return true; }
Source: https://habr.com/ru/post/268339/
All Articles