* Added build files [Capstone to Zydis] * x86 Analysis [Capstone to Zydis] * Changed x86 RzIL [Capstone to Zydis] * Changed asm and arch files [Capstone to Zydis] * Compilation, build error and test fixes [Capstone to Zydis] * Test changes [Capstone to Zydis] * Remaining changes [Capstone to Zydis] * Added BE support [Capstone to Zydis] --------- Co-authored-by: tushar3q34 <tushar3q34@gmail.com>
390 lines
11 KiB
C
390 lines
11 KiB
C
// SPDX-FileCopyrightText: 2023 Dhruv Maroo <dhruvmaru007@gmail.com>
|
|
// SPDX-FileCopyrightText: 2024-2025 tushar3q34 <tushar3q34@gmail.com>
|
|
// SPDX-License-Identifier: LGPL-3.0-only
|
|
|
|
#include "x86_il.h"
|
|
#include "il_ops.inc"
|
|
#include "il_fp_ops.inc"
|
|
|
|
#define COMMON_REGS \
|
|
"cs", /* X86_REG_CS */ \
|
|
"ss", /* X86_REG_SS */ \
|
|
"ds", /* X86_REG_DS */ \
|
|
"es", /* X86_REG_ES */ \
|
|
"cf", /* X86_EFLAGS_CF */ \
|
|
"pf", /* X86_EFLAGS_PF */ \
|
|
"af", /* X86_EFLAGS_AF */ \
|
|
"zf", /* X86_EFLAGS_ZF */ \
|
|
"sf", /* X86_EFLAGS_SF */ \
|
|
"tf", /* X86_EFLAGS_TF */ \
|
|
"if", /* X86_EFLAGS_IF */ \
|
|
"df", /* X86_EFLAGS_DF */ \
|
|
"of", /* X86_EFLAGS_OF */ \
|
|
"nt" /* X86_EFLAGS_NT */
|
|
|
|
#define FPU_REGS \
|
|
"cwd", /* X86_REG_FPU_CW */ \
|
|
"swd", /* X86_REG_FPSW */ \
|
|
"ftw", /* X86_REG_FPU_TW */ \
|
|
"fop", /* X86_REG_FPU_OP */ \
|
|
"frip", /* X86_REG_FPU_IP */ \
|
|
"frdp", /* X86_REG_FPU_DP */ \
|
|
"st0", /* X86_REG_ST0 */ \
|
|
"st1", /* X86_REG_ST1 */ \
|
|
"st2", /* X86_REG_ST2 */ \
|
|
"st3", /* X86_REG_ST3 */ \
|
|
"st4", /* X86_REG_ST4 */ \
|
|
"st5", /* X86_REG_ST5 */ \
|
|
"st6", /* X86_REG_ST6 */ \
|
|
"st7" /* X86_REG_ST6 */
|
|
|
|
/**
|
|
* \brief All registers bound to IL variables for x86 16-bit
|
|
*/
|
|
const char *x86_bound_regs_16[] = {
|
|
COMMON_REGS,
|
|
"ax", /* X86_REG_AX */
|
|
"bx", /* X86_REG_BX */
|
|
"cx", /* X86_REG_CX */
|
|
"dx", /* X86_REG_DX */
|
|
"sp", /* X86_REG_SP */
|
|
"bp", /* X86_REG_BP */
|
|
"si", /* X86_REG_SI */
|
|
"di", /* X86_REG_DI */
|
|
NULL
|
|
};
|
|
|
|
/**
|
|
* \brief All registers bound to IL variables for x86 32-bit
|
|
*/
|
|
const char *x86_bound_regs_32[] = {
|
|
COMMON_REGS,
|
|
"eax", /* X86_REG_EAX */
|
|
"ebx", /* X86_REG_EBX */
|
|
"ecx", /* X86_REG_ECX */
|
|
"edx", /* X86_REG_EDX */
|
|
"esp", /* X86_REG_ESP */
|
|
"ebp", /* X86_REG_EBP */
|
|
"esi", /* X86_REG_ESI */
|
|
"edi", /* X86_REG_EDI */
|
|
"rf", /* X86_EFLAGS_RF */
|
|
"vm", /* X86_EFLAGS_VM */
|
|
"ac", /* X86_EFLAGS_AC */
|
|
"fs", /* X86_REG_FS */
|
|
"gs", /* X86_REG_GS */
|
|
"cr0", /* X86_REG_CR0 */
|
|
"dr0", /* X86_REG_DR0 */
|
|
NULL
|
|
};
|
|
|
|
/**
|
|
* \brief All registers bound to IL variables for x86 64-bit
|
|
*/
|
|
const char *x86_bound_regs_64[] = {
|
|
COMMON_REGS,
|
|
"rax", /* X86_REG_RAX */
|
|
"rbx", /* X86_REG_RBX */
|
|
"rcx", /* X86_REG_RCX */
|
|
"rdx", /* X86_REG_RDX */
|
|
"rsp", /* X86_REG_RSP */
|
|
"rbp", /* X86_REG_RBP */
|
|
"rsi", /* X86_REG_RSI */
|
|
"rdi", /* X86_REG_RDI */
|
|
"r8", /* X86_REG_R8 */
|
|
"r9", /* X86_REG_R9 */
|
|
"r10", /* X86_REG_R10 */
|
|
"r11", /* X86_REG_R11 */
|
|
"r12", /* X86_REG_R12 */
|
|
"r13", /* X86_REG_R13 */
|
|
"r14", /* X86_REG_R14 */
|
|
"r15", /* X86_REG_R15 */
|
|
"rf", /* X86_EFLAGS_RF */
|
|
"vm", /* X86_EFLAGS_VM */
|
|
"ac", /* X86_EFLAGS_AC */
|
|
"fs", /* X86_REG_FS */
|
|
"gs", /* X86_REG_GS */
|
|
"cr0", /* X86_REG_CR0 */
|
|
"dr0", /* X86_REG_DR0 */
|
|
FPU_REGS,
|
|
NULL
|
|
};
|
|
|
|
typedef RzILOpEffect *(*x86_il_ins)(const X86ILIns *, ut64, RzAnalysis *, X86ILContext *);
|
|
|
|
/**
|
|
* \brief RzIL handlers for x86 instructions
|
|
*/
|
|
x86_il_ins x86_ins[X86_INS_MAX_VALUE] = {
|
|
[X86_INS_INVALID] = x86_il_invalid,
|
|
[X86_INS_AAA] = x86_il_aaa,
|
|
[X86_INS_AAD] = x86_il_aad,
|
|
[X86_INS_AAM] = x86_il_aam,
|
|
[X86_INS_AAS] = x86_il_aas,
|
|
[X86_INS_ADC] = x86_il_adc,
|
|
[X86_INS_ADD] = x86_il_add,
|
|
[X86_INS_AND] = x86_il_and,
|
|
[X86_INS_BSF] = x86_il_bsf,
|
|
[X86_INS_CALL] = x86_il_call,
|
|
[X86_INS_CBW] = x86_il_cbw,
|
|
[X86_INS_CLC] = x86_il_clc,
|
|
[X86_INS_CLD] = x86_il_cld,
|
|
[X86_INS_CLI] = x86_il_cli,
|
|
[X86_INS_CMC] = x86_il_cmc,
|
|
[X86_INS_CMP] = x86_il_cmp,
|
|
[X86_INS_CMOVNBE] = x86_il_cmov,
|
|
[X86_INS_CMOVNB] = x86_il_cmov,
|
|
[X86_INS_CMOVB] = x86_il_cmov,
|
|
[X86_INS_CMOVBE] = x86_il_cmov,
|
|
[X86_INS_CMOVZ] = x86_il_cmov,
|
|
[X86_INS_CMOVNLE] = x86_il_cmov,
|
|
[X86_INS_CMOVNL] = x86_il_cmov,
|
|
[X86_INS_CMOVL] = x86_il_cmov,
|
|
[X86_INS_CMOVLE] = x86_il_cmov,
|
|
[X86_INS_CMOVNZ] = x86_il_cmov,
|
|
[X86_INS_CMOVNO] = x86_il_cmov,
|
|
[X86_INS_CMOVNP] = x86_il_cmov,
|
|
[X86_INS_CMOVNS] = x86_il_cmov,
|
|
[X86_INS_CMOVO] = x86_il_cmov,
|
|
[X86_INS_CMOVP] = x86_il_cmov,
|
|
[X86_INS_CMOVS] = x86_il_cmov,
|
|
[X86_INS_CMPSB] = x86_il_cmpsb,
|
|
[X86_INS_CMPSW] = x86_il_cmpsw,
|
|
[X86_INS_CMPSD] = x86_il_cmpsd,
|
|
[X86_INS_CMPSQ] = x86_il_cmpsq,
|
|
[X86_INS_DAA] = x86_il_daa,
|
|
[X86_INS_DAS] = x86_il_das,
|
|
[X86_INS_DEC] = x86_il_dec,
|
|
[X86_INS_DIV] = x86_il_div,
|
|
[X86_INS_HLT] = x86_il_hlt,
|
|
[X86_INS_IDIV] = x86_il_idiv,
|
|
[X86_INS_IMUL] = x86_il_imul,
|
|
[X86_INS_IN] = x86_il_in,
|
|
[X86_INS_INC] = x86_il_inc,
|
|
[X86_INS_INT] = x86_il_int,
|
|
[X86_INS_INTO] = x86_il_into,
|
|
[X86_INS_JA] = x86_il_ja,
|
|
[X86_INS_JAE] = x86_il_jae,
|
|
[X86_INS_JB] = x86_il_jb,
|
|
[X86_INS_JBE] = x86_il_jbe,
|
|
[X86_INS_JCXZ] = x86_il_jcxz,
|
|
[X86_INS_JECXZ] = x86_il_jecxz,
|
|
[X86_INS_JRCXZ] = x86_il_jrcxz,
|
|
[X86_INS_JE] = x86_il_je,
|
|
[X86_INS_JG] = x86_il_jg,
|
|
[X86_INS_JGE] = x86_il_jge,
|
|
[X86_INS_JL] = x86_il_jl,
|
|
[X86_INS_JLE] = x86_il_jle,
|
|
[X86_INS_JNE] = x86_il_jne,
|
|
[X86_INS_JNO] = x86_il_jno,
|
|
[X86_INS_JNP] = x86_il_jnp,
|
|
[X86_INS_JNS] = x86_il_jns,
|
|
[X86_INS_JO] = x86_il_jo,
|
|
[X86_INS_JP] = x86_il_jp,
|
|
[X86_INS_JS] = x86_il_js,
|
|
[X86_INS_JMP] = x86_il_jmp,
|
|
[X86_INS_LAHF] = x86_il_lahf,
|
|
[X86_INS_LDS] = x86_il_lds,
|
|
[X86_INS_LEA] = x86_il_lea,
|
|
[X86_INS_LES] = x86_il_les,
|
|
[X86_INS_LODSB] = x86_il_lodsb,
|
|
[X86_INS_LODSW] = x86_il_lodsw,
|
|
[X86_INS_LODSD] = x86_il_lodsd,
|
|
[X86_INS_LODSQ] = x86_il_lodsq,
|
|
[X86_INS_LOOP] = x86_il_loop,
|
|
[X86_INS_LOOPE] = x86_il_loope,
|
|
[X86_INS_LOOPNE] = x86_il_loopne,
|
|
[X86_INS_MOV] = x86_il_mov,
|
|
[X86_INS_MOVSB] = x86_il_movsb,
|
|
[X86_INS_MOVSW] = x86_il_movsw,
|
|
[X86_INS_MOVSD] = x86_il_movsd,
|
|
[X86_INS_MOVSQ] = x86_il_movsq,
|
|
[X86_INS_MOVSX] = x86_il_movsx,
|
|
[X86_INS_MOVSXD] = x86_il_movsx,
|
|
[X86_INS_MOVZX] = x86_il_movzx,
|
|
[X86_INS_MUL] = x86_il_mul,
|
|
[X86_INS_NEG] = x86_il_neg,
|
|
[X86_INS_NOP] = x86_il_nop,
|
|
[X86_INS_NOT] = x86_il_not,
|
|
[X86_INS_OR] = x86_il_or,
|
|
[X86_INS_OUT] = x86_il_out,
|
|
[X86_INS_POP] = x86_il_pop,
|
|
[X86_INS_POPF] = x86_il_popf,
|
|
[X86_INS_POPFD] = x86_il_popfd,
|
|
[X86_INS_POPFQ] = x86_il_popfq,
|
|
[X86_INS_PUSH] = x86_il_push,
|
|
[X86_INS_PUSHF] = x86_il_pushf,
|
|
[X86_INS_PUSHFD] = x86_il_pushfd,
|
|
[X86_INS_PUSHFQ] = x86_il_pushfq,
|
|
[X86_INS_PUSHAD] = x86_il_pushaw,
|
|
[X86_INS_RCL] = x86_il_rcl,
|
|
[X86_INS_RCR] = x86_il_rcr,
|
|
[X86_INS_ROL] = x86_il_rol,
|
|
[X86_INS_ROR] = x86_il_ror,
|
|
[X86_INS_RET] = x86_il_ret,
|
|
[X86_INS_SAHF] = x86_il_sahf,
|
|
[X86_INS_SAR] = x86_il_sar,
|
|
[X86_INS_SHL] = x86_il_shl,
|
|
[X86_INS_SHR] = x86_il_shr,
|
|
[X86_INS_SBB] = x86_il_sbb,
|
|
[X86_INS_SCASB] = x86_il_scasb,
|
|
[X86_INS_SCASW] = x86_il_scasw,
|
|
[X86_INS_SCASD] = x86_il_scasd,
|
|
[X86_INS_SCASQ] = x86_il_scasq,
|
|
[X86_INS_STAC] = x86_il_stac,
|
|
[X86_INS_STC] = x86_il_stc,
|
|
[X86_INS_STD] = x86_il_std,
|
|
[X86_INS_STI] = x86_il_sti,
|
|
[X86_INS_STOSB] = x86_il_stosb,
|
|
[X86_INS_STOSD] = x86_il_stosd,
|
|
[X86_INS_STOSQ] = x86_il_stosq,
|
|
[X86_INS_STOSW] = x86_il_stosw,
|
|
[X86_INS_SUB] = x86_il_sub,
|
|
[X86_INS_TEST] = x86_il_test,
|
|
[X86_INS_FWAIT] = x86_il_fwait,
|
|
[X86_INS_XCHG] = x86_il_xchg,
|
|
[X86_INS_XLAT] = x86_il_xlat,
|
|
[X86_INS_XOR] = x86_il_xor,
|
|
[X86_INS_BOUND] = x86_il_bound,
|
|
[X86_INS_ENTER] = x86_il_enter,
|
|
[X86_INS_LEAVE] = x86_il_leave,
|
|
|
|
/* floating-point instructions */
|
|
[X86_INS_FNINIT] = x86_il_fninit,
|
|
[X86_INS_FLDCW] = x86_il_fldcw,
|
|
[X86_INS_FNSTCW] = x86_il_fnstcw,
|
|
[X86_INS_FNSTSW] = x86_il_fnstsw,
|
|
[X86_INS_FNCLEX] = x86_il_fnclex,
|
|
[X86_INS_FLD] = x86_il_fld,
|
|
[X86_INS_FST] = x86_il_fst,
|
|
[X86_INS_FSTP] = x86_il_fstp,
|
|
[X86_INS_FLD1] = x86_il_fld1,
|
|
[X86_INS_FLDZ] = x86_il_fldz,
|
|
[X86_INS_FLDL2T] = x86_il_fldl2t,
|
|
[X86_INS_FLDL2E] = x86_il_fldl2e,
|
|
[X86_INS_FLDPI] = x86_il_fldpi,
|
|
[X86_INS_FLDLG2] = x86_il_fldlg2,
|
|
[X86_INS_FLDLN2] = x86_il_fldln2,
|
|
[X86_INS_FXCH] = x86_il_fxch,
|
|
[X86_INS_FILD] = x86_il_fild,
|
|
[X86_INS_FIST] = x86_il_fist,
|
|
[X86_INS_FISTP] = x86_il_fistp,
|
|
[X86_INS_FBLD] = x86_il_fbld,
|
|
[X86_INS_FBSTP] = x86_il_fbstp,
|
|
[X86_INS_FABS] = x86_il_fabs,
|
|
[X86_INS_FADD] = x86_il_fadd,
|
|
#if CS_API_MAJOR <= 4
|
|
[X86_INS_FADDP] = x86_il_fadd,
|
|
#endif
|
|
[X86_INS_FIADD] = x86_il_fiadd,
|
|
[X86_INS_FMUL] = x86_il_fmul,
|
|
[X86_INS_FMULP] = x86_il_fmulp,
|
|
[X86_INS_FIMUL] = x86_il_fimul,
|
|
[X86_INS_FSUB] = x86_il_fsub,
|
|
[X86_INS_FSUBP] = x86_il_fsubp,
|
|
[X86_INS_FISUB] = x86_il_fisub,
|
|
[X86_INS_FSUBR] = x86_il_fsubr,
|
|
[X86_INS_FSUBRP] = x86_il_fsubrp,
|
|
[X86_INS_FISUBR] = x86_il_fisubr,
|
|
[X86_INS_FDIV] = x86_il_fdiv,
|
|
[X86_INS_FDIVP] = x86_il_fdivp,
|
|
[X86_INS_FIDIV] = x86_il_fidiv,
|
|
[X86_INS_FDIVR] = x86_il_fdivr,
|
|
[X86_INS_FDIVRP] = x86_il_fdivrp,
|
|
[X86_INS_FIDIVR] = x86_il_fidivr,
|
|
[X86_INS_FCOM] = x86_il_fcom,
|
|
[X86_INS_FCOMP] = x86_il_fcomp,
|
|
[X86_INS_FICOM] = x86_il_ficom,
|
|
[X86_INS_FCOMPP] = x86_il_fcompp,
|
|
[X86_INS_FICOMP] = x86_il_ficomp,
|
|
[X86_INS_FCOMI] = x86_il_fcomi,
|
|
|
|
/* Using the same FCOM & FCOMI family IL lifters for FUCOM & FUCOMI family instructions
|
|
* since we don't support invalid arithmetic operand exceptions (#IA) anyways. */
|
|
[X86_INS_FUCOM] = x86_il_fcom,
|
|
[X86_INS_FUCOMP] = x86_il_fcomp,
|
|
[X86_INS_FUCOMPP] = x86_il_fcompp,
|
|
[X86_INS_FUCOMI] = x86_il_fcomi,
|
|
[X86_INS_FCHS] = x86_il_fchs,
|
|
[X86_INS_FTST] = x86_il_ftst,
|
|
[X86_INS_FRNDINT] = x86_il_frndint,
|
|
[X86_INS_FSQRT] = x86_il_fsqrt,
|
|
[X86_INS_FNOP] = x86_il_fnop,
|
|
[X86_INS_FISTTP] = x86_il_fisttp,
|
|
|
|
/* unimplemented instructions */
|
|
[X86_INS_IRET] = x86_il_unimpl,
|
|
[X86_INS_INSB] = x86_il_unimpl,
|
|
[X86_INS_INSW] = x86_il_unimpl,
|
|
[X86_INS_OUTSB] = x86_il_unimpl,
|
|
[X86_INS_OUTSW] = x86_il_unimpl,
|
|
[X86_INS_FLDENV] = x86_il_unimpl,
|
|
[X86_INS_FNSTENV] = x86_il_unimpl,
|
|
[X86_INS_FNSAVE] = x86_il_unimpl,
|
|
[X86_INS_FRSTOR] = x86_il_unimpl
|
|
};
|
|
|
|
void label_int(RzILVM *vm, RzILOpEffect *op);
|
|
void label_halt(RzILVM *vm, RzILOpEffect *op);
|
|
void label_port(RzILVM *vm, RzILOpEffect *op);
|
|
|
|
RZ_IPI bool rz_x86_il_opcode(RZ_NONNULL RzAnalysis *analysis, RZ_NONNULL RzAnalysisOp *aop, ut64 pc, RZ_BORROW RZ_NONNULL const X86ILIns *ins) {
|
|
rz_return_val_if_fail(analysis && aop && ins && ins->ins_size > 0, false);
|
|
if (ins->mnem >= X86_INS_MAX_VALUE) {
|
|
RZ_LOG_ERROR("RzIL: x86: Invalid instruction type %d\n", ins->mnem);
|
|
return false;
|
|
}
|
|
|
|
x86_il_ins lifter = x86_ins[ins->mnem];
|
|
|
|
RzILOpEffect *lifted;
|
|
if (!lifter) {
|
|
/* For unimplemented instructions */
|
|
lifter = x86_il_unimpl;
|
|
}
|
|
|
|
X86ILContext ctx = {
|
|
.use_rmode = false
|
|
};
|
|
|
|
lifted = lifter(ins, pc, analysis, &ctx);
|
|
if (ctx.use_rmode) {
|
|
lifted = rz_il_op_new_seq(init_rmode(), lifted);
|
|
}
|
|
|
|
aop->il_op = lifted;
|
|
return true;
|
|
}
|
|
|
|
RZ_IPI RzAnalysisILConfig *rz_x86_il_config(RZ_NONNULL RzAnalysis *analysis) {
|
|
rz_return_val_if_fail(analysis, NULL);
|
|
|
|
RzAnalysisILConfig *r = rz_analysis_il_config_new(analysis->bits, analysis->big_endian, analysis->bits);
|
|
|
|
switch (analysis->bits) {
|
|
case 16:
|
|
r->reg_bindings = x86_bound_regs_16;
|
|
break;
|
|
case 32:
|
|
r->reg_bindings = x86_bound_regs_32;
|
|
break;
|
|
case 64:
|
|
r->reg_bindings = x86_bound_regs_64;
|
|
break;
|
|
default:
|
|
rz_warn_if_reached();
|
|
}
|
|
|
|
RzILEffectLabel *int_label = rz_il_effect_label_new("int", EFFECT_LABEL_SYSCALL);
|
|
int_label->hook = label_int;
|
|
rz_analysis_il_config_add_label(r, int_label);
|
|
|
|
RzILEffectLabel *halt_label = rz_il_effect_label_new("halt", EFFECT_LABEL_SYSCALL);
|
|
halt_label->hook = label_halt;
|
|
rz_analysis_il_config_add_label(r, halt_label);
|
|
|
|
RzILEffectLabel *port_label = rz_il_effect_label_new("port", EFFECT_LABEL_SYSCALL);
|
|
port_label->hook = label_port;
|
|
rz_analysis_il_config_add_label(r, port_label);
|
|
|
|
return r;
|
|
}
|