radare2/libr/anal/p/anal_x86_x86im.c

203 lines
5.4 KiB
C

/* radare - LGPL - Copyright 2009 */
/* nibble<.ds@gmail.com> */
#include <string.h>
#include <r_types.h>
#include <r_anal.h>
#include <r_util.h>
#include "x86/x86im/x86im.h"
static int aop(RAnal *anal, RAnalOp *aop, ut64 addr, const ut8 *data, int len) {
x86im_instr_object io;
st64 imm, disp;
char mnem[256];
if (data == NULL)
return 0;
memset (aop, '\0', sizeof (RAnalOp));
aop->type = R_ANAL_OP_TYPE_UNK;
aop->addr = addr;
aop->jump = aop->fail = -1;
if ((x86im_dec (&io,
anal->bits == 32 ? X86IM_IO_MODE_32BIT : X86IM_IO_MODE_64BIT,
(unsigned char*)data)) == X86IM_STATUS_SUCCESS) {
if (io.len > len)
return 0;
x86im_fmt_format_name (&io, mnem);
aop->mnemonic = strdup (mnem);
imm = r_hex_bin_truncate (io.imm, io.imm_size);
disp = r_hex_bin_truncate (io.disp, io.disp_size);
if (X86IM_IO_IS_GPI_JMP (&io)) { /* jump */
if (io.id == X86IM_IO_ID_JMP_N_AI_RG) {
aop->type = R_ANAL_OP_TYPE_UJMP;
aop->eob = R_TRUE;
} else {
aop->type = R_ANAL_OP_TYPE_JMP;
aop->jump = aop->addr + io.len + imm;
aop->eob = R_TRUE;
}
} else
if (X86IM_IO_IS_GPI_JCC (&io)) { /* conditional jump*/
aop->type = R_ANAL_OP_TYPE_CJMP;
aop->fail = aop->addr + io.len;
aop->jump = aop->addr + io.len + imm;
aop->eob = R_TRUE;
} else
if (X86IM_IO_IS_GPI_CALL (&io)) { /* call */
if (io.id == X86IM_IO_ID_CALL_N_AI_RG) {
aop->type = R_ANAL_OP_TYPE_RCALL;
} else {
aop->type = R_ANAL_OP_TYPE_CALL;
aop->jump = aop->addr + io.len + imm;
}
aop->fail = aop->addr + io.len;
} else
if (X86IM_IO_IS_GPI_RET (&io)) { /* ret */
aop->type = R_ANAL_OP_TYPE_RET;
aop->eob = R_TRUE;
} else
if (io.id == X86IM_IO_ID_HLT) { /* htl */
aop->type = R_ANAL_OP_TYPE_RET;
aop->eob = R_TRUE;
} else
if (X86IM_IO_IS_GPI_MOV (&io)) { /* mov */
aop->type = R_ANAL_OP_TYPE_MOV;
if (io.id == X86IM_IO_ID_MOV_RG_MM &&
(io.mem_base & X86IM_IO_ROP_ID_EBP)) {
aop->stackop = R_ANAL_STACK_GET;
aop->ref = disp;
} else
if ((io.id == X86IM_IO_ID_MOV_MM_RG ||
io.id == X86IM_IO_ID_MOV_MM_IM) &&
(io.mem_base & X86IM_IO_ROP_ID_EBP)) {
aop->stackop = R_ANAL_STACK_SET;
aop->ref = disp;
}
} else
if (X86IM_IO_IS_GPI_CMP (&io)) { /* cmp */
aop->type = R_ANAL_OP_TYPE_CMP;
if (io.id == X86IM_IO_ID_CMP_MM_IM &&
(io.mem_base & X86IM_IO_ROP_ID_EBP)) {
aop->stackop = R_ANAL_STACK_GET;
aop->ref = disp;
}
} else
if (X86IM_IO_IS_GPI_PUSH (&io)) { /* push */
if ((io.rop[0] & X86IM_IO_ROP_SGR_GPR_16)) {
aop->type = R_ANAL_OP_TYPE_UPUSH;
aop->stackptr = 2;
} else
if ((io.rop[0] & X86IM_IO_ROP_SGR_GPR_32)) {
aop->type = R_ANAL_OP_TYPE_UPUSH;
aop->stackptr = 4;
} else
if ((io.rop[0] & X86IM_IO_ROP_SGR_GPR_64)) {
aop->type = R_ANAL_OP_TYPE_UPUSH;
aop->stackptr = 8;
} else {
aop->type = R_ANAL_OP_TYPE_PUSH;
aop->ref = imm;
aop->stackptr = io.imm_size;
}
if (io.id == X86IM_IO_ID_PUSH_MM &&
(io.mem_base & X86IM_IO_ROP_ID_EBP)) {
aop->stackop = R_ANAL_STACK_GET;
}
} else
if (X86IM_IO_IS_GPI_POP (&io)) { /* pop */
aop->type = R_ANAL_OP_TYPE_POP;
if ((io.rop[0] & X86IM_IO_ROP_SGR_GPR_16))
aop->stackptr = -2;
else
if ((io.rop[0] & X86IM_IO_ROP_SGR_GPR_32))
aop->stackptr = -4;
else
if ((io.rop[0] & X86IM_IO_ROP_SGR_GPR_64))
aop->stackptr = -8;
} else
if (X86IM_IO_IS_GPI_ADD (&io)) { /* add */
aop->type = R_ANAL_OP_TYPE_ADD;
if (io.id == X86IM_IO_ID_ADD_RG_MM &&
(io.mem_base & X86IM_IO_ROP_ID_EBP)) {
aop->stackop = R_ANAL_STACK_GET;
aop->ref = disp;
} else
if (io.id == X86IM_IO_ID_ADD_MM_RG &&
(io.mem_base & X86IM_IO_ROP_ID_EBP)) {
aop->stackop = R_ANAL_STACK_SET;
aop->ref = disp;
} else
if (io.id == X86IM_IO_ID_ADD_RG_IM &&
(io.rop[0] & X86IM_IO_ROP_ID_ESP)) {
aop->stackop = R_ANAL_STACK_INCSTACK;
aop->value = imm;
aop->stackptr = -imm;
}
} else
if (X86IM_IO_IS_GPI_SUB (&io)) { /* sub */
if (io.id == X86IM_IO_ID_SUB_RG_IM &&
(io.rop[0] & X86IM_IO_ROP_ID_ESP)) {
aop->stackop = R_ANAL_STACK_INCSTACK;
aop->value = imm;
aop->stackptr = imm;
}
aop->type = R_ANAL_OP_TYPE_SUB;
} else
if (X86IM_IO_IS_GPI_MUL (&io)) { /* mul */
aop->type = R_ANAL_OP_TYPE_MUL;
aop->value = imm;
} else
if (X86IM_IO_IS_GPI_DIV (&io)) { /* div */
aop->type = R_ANAL_OP_TYPE_DIV;
aop->value = imm;
} else
if (X86IM_IO_IS_GPI_SHR (&io)) { /* shr */
aop->type = R_ANAL_OP_TYPE_SHR;
aop->value = imm;
} else
if (X86IM_IO_IS_GPI_SHL (&io)) { /* shl */
aop->type = R_ANAL_OP_TYPE_SHL;
aop->value = imm;
} else
if (X86IM_IO_IS_GPI_OR (&io)) { /* or */
aop->type = R_ANAL_OP_TYPE_OR;
aop->value = imm;
} else
if (X86IM_IO_IS_GPI_AND (&io)) { /* and */
aop->type = R_ANAL_OP_TYPE_AND;
aop->value = imm;
} else
if (X86IM_IO_IS_GPI_XOR (&io)) { /* xor */
aop->type = R_ANAL_OP_TYPE_XOR;
aop->value = imm;
} else
if (X86IM_IO_IS_GPI_NOT (&io)) { /* not */
aop->type = R_ANAL_OP_TYPE_NOT;
aop->value = imm;
}
aop->length = io.len;
aop->nopcode = io.opcode_count;
}
return aop->length;
}
struct r_anal_plugin_t r_anal_plugin_x86_x86im = {
.name = "x86_x86im",
.desc = "X86 x86im analysis plugin",
.init = NULL,
.fini = NULL,
.aop = &aop
};
#ifndef CORELIB
struct r_lib_struct_t radare_plugin = {
.type = R_LIB_TYPE_ANAL,
.data = &r_anal_plugin_x86_x86im
};
#endif