mirror of
https://github.com/capstone-engine/capstone.git
synced 2026-10-12 02:11:43 +00:00
x86: fix JO/JNO operand size in 64-bit mode by adding Intel/AMD mode flags (#3067)
* x86: fix JO/JNO operand size in 64-bit mode * x86: add explicit Intel/AMD near-Jcc decoding modes --------- Co-authored-by: Rot127 <[email protected]>
This commit is contained in:
@@ -75,7 +75,7 @@ static void set_mem_access(MCInst *MI, bool status)
|
||||
|
||||
static void printopaquemem(MCInst *MI, unsigned OpNo, SStream *O)
|
||||
{
|
||||
switch (MI->csh->mode) {
|
||||
switch (x86_get_bit_mode(MI->csh->mode)) {
|
||||
case CS_MODE_16:
|
||||
switch (MI->flat_insn->id) {
|
||||
default:
|
||||
@@ -185,7 +185,7 @@ static void printf32mem(MCInst *MI, unsigned OpNo, SStream *O)
|
||||
case X86_FSTENVm:
|
||||
case X86_FLDENVm:
|
||||
// TODO: fix this in tablegen instead
|
||||
switch (MI->csh->mode) {
|
||||
switch (x86_get_bit_mode(MI->csh->mode)) {
|
||||
default: // never reach
|
||||
break;
|
||||
case CS_MODE_16:
|
||||
@@ -438,7 +438,7 @@ static void printDstIdx(MCInst *MI, unsigned Op, SStream *O)
|
||||
}
|
||||
|
||||
// DI accesses are always ES-based on non-64bit mode
|
||||
if (MI->csh->mode != CS_MODE_64) {
|
||||
if (!(x86_has_feature(MI->csh->mode, CS_MODE_64))) {
|
||||
SStream_concat0(O, "%es:(");
|
||||
if (MI->csh->detail_opt) {
|
||||
MI->flat_insn->detail->x86
|
||||
@@ -562,8 +562,10 @@ static void printMemOffset(MCInst *MI, unsigned Op, SStream *O)
|
||||
.operands[MI->flat_insn->detail->x86.op_count]
|
||||
.mem.disp = imm;
|
||||
if (imm < 0) {
|
||||
SStream_concat(O, "0x%" PRIx64,
|
||||
arch_masks[MI->csh->mode] & imm);
|
||||
SStream_concat(
|
||||
O, "0x%" PRIx64,
|
||||
arch_masks[x86_get_bit_mode(MI->csh->mode)] &
|
||||
imm);
|
||||
} else {
|
||||
if (imm > HEX_THRESHOLD)
|
||||
SStream_concat(O, "0x%" PRIx64, imm);
|
||||
@@ -635,8 +637,11 @@ static void printPCRelImm(MCInst *MI, unsigned OpNo, SStream *O)
|
||||
MI->address;
|
||||
|
||||
// truncate imm for non-64bit
|
||||
if (MI->csh->mode != CS_MODE_64) {
|
||||
if (!(x86_has_feature(MI->csh->mode, CS_MODE_64))) {
|
||||
imm = imm & 0xffffffff;
|
||||
} else if ((x86_has_feature(MI->csh->mode, CS_MODE_X86_AMD)) &&
|
||||
MI->imm_size == 2) {
|
||||
imm &= 0xffff;
|
||||
}
|
||||
|
||||
if (imm < 0) {
|
||||
@@ -937,7 +942,8 @@ static void printMemReference(MCInst *MI, unsigned Op, SStream *O)
|
||||
if (DispVal < 0) {
|
||||
SStream_concat(
|
||||
O, "0x%" PRIx64,
|
||||
arch_masks[MI->csh->mode] &
|
||||
arch_masks[x86_get_bit_mode(
|
||||
MI->csh->mode)] &
|
||||
DispVal);
|
||||
} else {
|
||||
if (DispVal > HEX_THRESHOLD)
|
||||
@@ -1049,7 +1055,7 @@ void X86_ATT_printInst(MCInst *MI, SStream *OS, void *info)
|
||||
// TODO: Probably this hack should be redesigned via InstAlias in
|
||||
// InstrInfo.td as soon as Requires clause is supported properly
|
||||
// for InstAlias.
|
||||
if (MI->csh->mode == CS_MODE_64 &&
|
||||
if ((x86_has_feature(MI->csh->mode, CS_MODE_64)) &&
|
||||
MCInst_getOpcode(MI) == X86_CALLpcrel32) {
|
||||
SStream_concat0(OS, "callq\t");
|
||||
MCInst_setOpcodePub(MI, X86_INS_CALL);
|
||||
|
||||
@@ -1347,15 +1347,7 @@ bool X86_getInstruction(csh ud, const uint8_t *code, size_t code_len,
|
||||
//memset(instr->flat_insn->detail, 0, offsetof(cs_detail, x86)+offsetof(cs_x86, operands));
|
||||
}
|
||||
|
||||
if (handle->mode & CS_MODE_16)
|
||||
ret = decodeInstruction(&insn, reader, &info, address,
|
||||
MODE_16BIT);
|
||||
else if (handle->mode & CS_MODE_32)
|
||||
ret = decodeInstruction(&insn, reader, &info, address,
|
||||
MODE_32BIT);
|
||||
else
|
||||
ret = decodeInstruction(&insn, reader, &info, address,
|
||||
MODE_64BIT);
|
||||
ret = decodeInstruction(&insn, reader, &info, address, handle->mode);
|
||||
|
||||
if (ret) {
|
||||
// *size = (uint16_t)(insn.readerCursor - address);
|
||||
|
||||
@@ -1139,7 +1139,7 @@ static uint16_t resolveMandatoryPrefixConflict(struct InternalInstruction *insn,
|
||||
* @return - 0 if the ModR/M could be read when needed or was not needed;
|
||||
* nonzero otherwise.
|
||||
*/
|
||||
static int getID(struct InternalInstruction *insn)
|
||||
static int getID(struct InternalInstruction *insn, cs_mode mode)
|
||||
{
|
||||
uint16_t attrMask;
|
||||
uint16_t instructionID;
|
||||
@@ -1273,8 +1273,8 @@ static int getID(struct InternalInstruction *insn)
|
||||
attrMask ^= ATTR_ADSIZE;
|
||||
|
||||
/*
|
||||
* In 64-bit mode all f64 superscripted opcodes ignore opcode size prefix
|
||||
* CALL/JMP/JCC instructions need to ignore 0x66 and consume 4 bytes
|
||||
* CALL/JMP ignore 66 in 64-bit mode. Near Jcc preserve their previous
|
||||
* behavior unless an Intel or AMD mode is selected.
|
||||
*/
|
||||
if ((insn->mode == MODE_64BIT) && insn->hasOpSize) {
|
||||
switch (insn->opcode) {
|
||||
@@ -1287,6 +1287,8 @@ static int getID(struct InternalInstruction *insn)
|
||||
insn->displacementSize = 4;
|
||||
}
|
||||
break;
|
||||
case 0x80:
|
||||
case 0x81:
|
||||
case 0x82:
|
||||
case 0x83:
|
||||
case 0x84:
|
||||
@@ -1302,7 +1304,25 @@ static int getID(struct InternalInstruction *insn)
|
||||
case 0x8E:
|
||||
case 0x8F:
|
||||
// Take care of lea and three byte ops.
|
||||
if (insn->opcodeType == TWOBYTE) {
|
||||
if (insn->opcodeType != TWOBYTE)
|
||||
break;
|
||||
|
||||
if ((x86_has_feature(mode, CS_MODE_X86_INTEL) ||
|
||||
x86_has_feature(mode, CS_MODE_X86_AMD)) &&
|
||||
insn->vectorExtensionType == TYPE_NO_VEX_XOP) {
|
||||
if ((x86_has_feature(mode, CS_MODE_X86_AMD)) &&
|
||||
!wFromREX(insn->rexPrefix)) {
|
||||
attrMask |= ATTR_OPSIZE;
|
||||
insn->immediateSize = 2;
|
||||
insn->displacementSize = 2;
|
||||
insn->immSize = 2;
|
||||
} else {
|
||||
attrMask &= ~ATTR_OPSIZE;
|
||||
insn->immediateSize = 4;
|
||||
insn->displacementSize = 4;
|
||||
insn->immSize = 8;
|
||||
}
|
||||
} else if (insn->opcode >= 0x82) {
|
||||
attrMask ^= ATTR_OPSIZE;
|
||||
insn->immediateSize = 4;
|
||||
insn->displacementSize = 4;
|
||||
@@ -2507,22 +2527,25 @@ static bool checkPrefix(struct InternalInstruction *insn)
|
||||
* any internal state.
|
||||
* @param startLoc - The address (in the reader's address space) of the first
|
||||
* byte in the instruction.
|
||||
* @param mode - The mode (real mode, IA-32e, or IA-32e in 64-bit mode) to
|
||||
* decode the instruction in.
|
||||
* @param mode - Capstone mode flags.
|
||||
* @return - 0 if instruction is valid; nonzero if not.
|
||||
*/
|
||||
int decodeInstruction(struct InternalInstruction *insn, byteReader_t reader,
|
||||
const void *readerArg, uint64_t startLoc,
|
||||
DisassemblerMode mode)
|
||||
const void *readerArg, uint64_t startLoc, cs_mode mode)
|
||||
{
|
||||
insn->reader = reader;
|
||||
insn->readerArg = readerArg;
|
||||
insn->startLocation = startLoc;
|
||||
insn->readerCursor = startLoc;
|
||||
insn->mode = mode;
|
||||
if (x86_has_feature(mode, CS_MODE_16))
|
||||
insn->mode = MODE_16BIT;
|
||||
else if (x86_has_feature(mode, CS_MODE_32))
|
||||
insn->mode = MODE_32BIT;
|
||||
else
|
||||
insn->mode = MODE_64BIT;
|
||||
insn->numImmediatesConsumed = 0;
|
||||
|
||||
if (readPrefixes(insn) || readOpcode(insn) || getID(insn) ||
|
||||
if (readPrefixes(insn) || readOpcode(insn) || getID(insn, mode) ||
|
||||
insn->instructionID == 0 || checkPrefix(insn) || readOperands(insn))
|
||||
return -1;
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#include "../../include/capstone/capstone.h"
|
||||
#include "X86DisassemblerDecoderCommon.h"
|
||||
|
||||
/*
|
||||
@@ -700,12 +701,11 @@ typedef struct InternalInstruction {
|
||||
* specific to the logger. May be NULL.
|
||||
* @param startLoc - The address (in the reader's address space) of the first
|
||||
* byte in the instruction.
|
||||
* @param mode - The mode (16-bit, 32-bit, 64-bit) to decode in.
|
||||
* @param mode - Capstone mode flags.
|
||||
* @return - Nonzero if there was an error during decode, 0 otherwise.
|
||||
*/
|
||||
int decodeInstruction(struct InternalInstruction *insn, byteReader_t reader,
|
||||
const void *readerArg, uint64_t startLoc,
|
||||
DisassemblerMode mode);
|
||||
const void *readerArg, uint64_t startLoc, cs_mode mode);
|
||||
|
||||
//const char *x86DisassemblerGetInstrName(unsigned Opcode, const void *mii);
|
||||
|
||||
|
||||
@@ -93,7 +93,7 @@ static void printopaquemem(MCInst *MI, unsigned OpNo, SStream *O)
|
||||
break;
|
||||
}
|
||||
|
||||
switch (MI->csh->mode) {
|
||||
switch (x86_get_bit_mode(MI->csh->mode)) {
|
||||
case CS_MODE_16:
|
||||
switch (MI->flat_insn->id) {
|
||||
default:
|
||||
@@ -209,7 +209,7 @@ static void printf32mem(MCInst *MI, unsigned OpNo, SStream *O)
|
||||
case X86_FSTENVm:
|
||||
case X86_FLDENVm:
|
||||
// TODO: fix this in tablegen instead
|
||||
switch (MI->csh->mode) {
|
||||
switch (x86_get_bit_mode(MI->csh->mode)) {
|
||||
default: // never reach
|
||||
break;
|
||||
case CS_MODE_16:
|
||||
@@ -564,7 +564,7 @@ static void printDstIdx(MCInst *MI, unsigned Op, SStream *O)
|
||||
}
|
||||
|
||||
// DI accesses are always ES-based on non-64bit mode
|
||||
if (MI->csh->mode != CS_MODE_64) {
|
||||
if (!(x86_has_feature(MI->csh->mode, CS_MODE_64))) {
|
||||
SStream_concat0(O, "es:[");
|
||||
if (MI->csh->detail_opt) {
|
||||
MI->flat_insn->detail->x86
|
||||
@@ -700,7 +700,10 @@ static void printMemOffset(MCInst *MI, unsigned Op, SStream *O)
|
||||
.mem.disp = imm;
|
||||
|
||||
if (imm < 0)
|
||||
printImm(MI, O, arch_masks[MI->csh->mode] & imm, true);
|
||||
printImm(MI, O,
|
||||
arch_masks[x86_get_bit_mode(MI->csh->mode)] &
|
||||
imm,
|
||||
true);
|
||||
else
|
||||
printImm(MI, O, imm, true);
|
||||
}
|
||||
@@ -865,8 +868,11 @@ static void printPCRelImm(MCInst *MI, unsigned OpNo, SStream *O)
|
||||
uint8_t opsize = X86_immediate_size(MI->Opcode, NULL);
|
||||
|
||||
// truncate imm for non-64bit
|
||||
if (MI->csh->mode != CS_MODE_64) {
|
||||
if (!(x86_has_feature(MI->csh->mode, CS_MODE_64))) {
|
||||
imm = imm & 0xffffffff;
|
||||
} else if ((x86_has_feature(MI->csh->mode, CS_MODE_X86_AMD)) &&
|
||||
MI->imm_size == 2) {
|
||||
imm &= 0xffff;
|
||||
}
|
||||
|
||||
printImm(MI, O, imm, true);
|
||||
@@ -1205,11 +1211,12 @@ static void printMemReference(MCInst *MI, unsigned Op, SStream *O)
|
||||
}
|
||||
} else {
|
||||
// memory reference to an immediate address
|
||||
if (MI->csh->mode == CS_MODE_64)
|
||||
if (x86_has_feature(MI->csh->mode, CS_MODE_64))
|
||||
MI->op1_size = 8;
|
||||
if (DispVal < 0) {
|
||||
printImm(MI, O,
|
||||
arch_masks[MI->csh->mode] &
|
||||
arch_masks[x86_get_bit_mode(
|
||||
MI->csh->mode)] &
|
||||
DispVal,
|
||||
true);
|
||||
} else {
|
||||
|
||||
+19
-18
@@ -715,9 +715,9 @@ const char *X86_reg_name(csh handle, unsigned int reg)
|
||||
return NULL;
|
||||
|
||||
if (reg == X86_REG_EFLAGS) {
|
||||
if (ud->mode & CS_MODE_32)
|
||||
if (x86_has_feature(ud->mode, CS_MODE_32))
|
||||
return "eflags";
|
||||
if (ud->mode & CS_MODE_64)
|
||||
if (x86_has_feature(ud->mode, CS_MODE_64))
|
||||
return "rflags";
|
||||
}
|
||||
|
||||
@@ -900,6 +900,7 @@ void X86_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id)
|
||||
|
||||
if (h->detail_opt) {
|
||||
#ifndef CAPSTONE_DIET
|
||||
cs_mode mode = x86_get_bit_mode(h->mode);
|
||||
memcpy(insn->detail->regs_read, insns[i].regs_use,
|
||||
sizeof(insns[i].regs_use));
|
||||
insn->detail->regs_read_count =
|
||||
@@ -916,7 +917,7 @@ void X86_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id)
|
||||
insns[i].regs_mod);
|
||||
break;
|
||||
case X86_RDTSC:
|
||||
if (h->mode == CS_MODE_64) {
|
||||
if (mode == CS_MODE_64) {
|
||||
memcpy(insn->detail->regs_write,
|
||||
insns[i].regs_mod,
|
||||
sizeof(insns[i].regs_mod));
|
||||
@@ -932,7 +933,7 @@ void X86_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id)
|
||||
}
|
||||
break;
|
||||
case X86_RDTSCP:
|
||||
if (h->mode == CS_MODE_64) {
|
||||
if (mode == CS_MODE_64) {
|
||||
memcpy(insn->detail->regs_write,
|
||||
insns[i].regs_mod,
|
||||
sizeof(insns[i].regs_mod));
|
||||
@@ -958,7 +959,7 @@ void X86_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id)
|
||||
case X86_INS_LOOPE:
|
||||
case X86_INS_LOOPNE:
|
||||
// The instruction pointer register follows the mode.
|
||||
switch (h->mode) {
|
||||
switch (mode) {
|
||||
default:
|
||||
break;
|
||||
case CS_MODE_16:
|
||||
@@ -1012,7 +1013,7 @@ void X86_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id)
|
||||
case X86_INS_LODSD:
|
||||
case X86_INS_LODSQ:
|
||||
case X86_INS_LODSW:
|
||||
switch (h->mode) {
|
||||
switch (mode) {
|
||||
default:
|
||||
break;
|
||||
case CS_MODE_16:
|
||||
@@ -1046,7 +1047,7 @@ void X86_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id)
|
||||
case X86_INS_STOSD:
|
||||
case X86_INS_STOSQ:
|
||||
case X86_INS_STOSW:
|
||||
switch (h->mode) {
|
||||
switch (mode) {
|
||||
default:
|
||||
break;
|
||||
case CS_MODE_16:
|
||||
@@ -1080,7 +1081,7 @@ void X86_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id)
|
||||
case X86_INS_MOVSW:
|
||||
case X86_INS_MOVSD:
|
||||
case X86_INS_MOVSQ:
|
||||
switch (h->mode) {
|
||||
switch (mode) {
|
||||
default:
|
||||
break;
|
||||
case CS_MODE_16:
|
||||
@@ -1124,7 +1125,7 @@ void X86_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id)
|
||||
|
||||
case X86_INS_ENTER:
|
||||
case X86_INS_LEAVE:
|
||||
switch (h->mode) {
|
||||
switch (mode) {
|
||||
default:
|
||||
break;
|
||||
case CS_MODE_16:
|
||||
@@ -1168,7 +1169,7 @@ void X86_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id)
|
||||
case X86_INS_INSB:
|
||||
case X86_INS_INSW:
|
||||
case X86_INS_INSD:
|
||||
switch (h->mode) {
|
||||
switch (mode) {
|
||||
default:
|
||||
break;
|
||||
case CS_MODE_16:
|
||||
@@ -1197,7 +1198,7 @@ void X86_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id)
|
||||
case X86_INS_OUTSB:
|
||||
case X86_INS_OUTSW:
|
||||
case X86_INS_OUTSD:
|
||||
switch (h->mode) {
|
||||
switch (mode) {
|
||||
default:
|
||||
break;
|
||||
case CS_MODE_64:
|
||||
@@ -1239,7 +1240,7 @@ void X86_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id)
|
||||
case X86_INS_OUTSB:
|
||||
case X86_INS_OUTSW:
|
||||
case X86_INS_OUTSD:
|
||||
switch (h->mode) {
|
||||
switch (mode) {
|
||||
default:
|
||||
break;
|
||||
case CS_MODE_16:
|
||||
@@ -1254,7 +1255,7 @@ void X86_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id)
|
||||
|
||||
case X86_INS_JMP:
|
||||
case X86_INS_LJMP:
|
||||
switch (h->mode) {
|
||||
switch (mode) {
|
||||
default:
|
||||
break;
|
||||
case CS_MODE_16:
|
||||
@@ -1281,7 +1282,7 @@ void X86_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id)
|
||||
break;
|
||||
|
||||
case X86_INS_SYSENTER: {
|
||||
switch (h->mode) {
|
||||
switch (mode) {
|
||||
default:
|
||||
break;
|
||||
case CS_MODE_16:
|
||||
@@ -1308,7 +1309,7 @@ void X86_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id)
|
||||
break;
|
||||
} break;
|
||||
case X86_INS_SYSEXIT: {
|
||||
switch (h->mode) {
|
||||
switch (mode) {
|
||||
default:
|
||||
break;
|
||||
case CS_MODE_16:
|
||||
@@ -1364,7 +1365,7 @@ void X86_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id)
|
||||
X86_GRP_JUMP;
|
||||
insn->detail->groups_count++;
|
||||
|
||||
switch (h->mode) {
|
||||
switch (mode) {
|
||||
default:
|
||||
break;
|
||||
case CS_MODE_16:
|
||||
@@ -2222,9 +2223,9 @@ static void add_cx(MCInst *MI)
|
||||
if (MI->csh->detail_opt) {
|
||||
x86_reg cx;
|
||||
|
||||
if (MI->csh->mode & CS_MODE_16)
|
||||
if (x86_has_feature(MI->csh->mode, CS_MODE_16))
|
||||
cx = X86_REG_CX;
|
||||
else if (MI->csh->mode & CS_MODE_32)
|
||||
else if (x86_has_feature(MI->csh->mode, CS_MODE_32))
|
||||
cx = X86_REG_ECX;
|
||||
else // 64-bit
|
||||
cx = X86_REG_RCX;
|
||||
|
||||
@@ -104,4 +104,14 @@ void X86_build_lookup_tables(cs_struct *h);
|
||||
|
||||
void X86_postprinter(csh handle, cs_insn *insn, SStream *mnem, MCInst *mci);
|
||||
|
||||
static inline bool x86_has_feature(cs_mode mode, int flag)
|
||||
{
|
||||
return (mode & flag) == flag;
|
||||
}
|
||||
|
||||
static inline int x86_get_bit_mode(cs_mode mode)
|
||||
{
|
||||
return mode & (CS_MODE_64 | CS_MODE_32 | CS_MODE_16);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
+13
-3
@@ -13,6 +13,10 @@
|
||||
cs_err X86_global_init(cs_struct *ud)
|
||||
{
|
||||
MCRegisterInfo *mri;
|
||||
if (x86_has_feature(ud->mode, CS_MODE_X86_AMD) &&
|
||||
x86_has_feature(ud->mode, CS_MODE_X86_INTEL))
|
||||
return CS_ERR_MODE;
|
||||
|
||||
mri = cs_mem_calloc(1, sizeof(*mri));
|
||||
if (!mri)
|
||||
return CS_ERR_MEM;
|
||||
@@ -33,7 +37,7 @@ cs_err X86_global_init(cs_struct *ud)
|
||||
ud->reg_access = X86_reg_access;
|
||||
#endif
|
||||
|
||||
if (ud->mode == CS_MODE_64)
|
||||
if (x86_has_feature(ud->mode, CS_MODE_64))
|
||||
ud->regsize_map = regsize_map_64;
|
||||
else
|
||||
ud->regsize_map = regsize_map_32;
|
||||
@@ -49,12 +53,18 @@ cs_err X86_option(cs_struct *handle, cs_opt_type type, size_t value)
|
||||
default:
|
||||
break;
|
||||
case CS_OPT_MODE:
|
||||
if (value == CS_MODE_64)
|
||||
if ((x86_has_feature(value, CS_MODE_X86_INTEL) &&
|
||||
x86_has_feature(value, CS_MODE_X86_AMD)))
|
||||
return CS_ERR_OPTION;
|
||||
|
||||
if (x86_has_feature(value, CS_MODE_64))
|
||||
handle->regsize_map = regsize_map_64;
|
||||
else
|
||||
handle->regsize_map = regsize_map_32;
|
||||
|
||||
handle->mode = (cs_mode)value;
|
||||
handle->mode = (cs_mode)(value &
|
||||
(CS_MODE_16 | CS_MODE_32 | CS_MODE_64 |
|
||||
CS_MODE_X86_INTEL | CS_MODE_X86_AMD));
|
||||
break;
|
||||
case CS_OPT_SYNTAX:
|
||||
switch (value) {
|
||||
|
||||
@@ -45,6 +45,8 @@ __all__ = [
|
||||
"CS_MODE_16",
|
||||
"CS_MODE_32",
|
||||
"CS_MODE_64",
|
||||
"CS_MODE_X86_INTEL",
|
||||
"CS_MODE_X86_AMD",
|
||||
"CS_MODE_ARM",
|
||||
"CS_MODE_THUMB",
|
||||
"CS_MODE_MCLASS",
|
||||
@@ -353,6 +355,8 @@ CS_MODE_ARM = 0 # ARM mode
|
||||
CS_MODE_16 = 1 << 1 # 16-bit mode (for X86)
|
||||
CS_MODE_32 = 1 << 2 # 32-bit mode (for X86)
|
||||
CS_MODE_64 = 1 << 3 # 64-bit mode (for X86, PPC)
|
||||
CS_MODE_X86_INTEL = 1 << 4
|
||||
CS_MODE_X86_AMD = 1 << 5
|
||||
CS_MODE_THUMB = 1 << 4 # ARM's Thumb mode, including Thumb-2
|
||||
CS_MODE_MCLASS = 1 << 5 # ARM's Cortex-M series
|
||||
CS_MODE_V8 = 1 << 6 # ARMv8 A32 encodings for ARM
|
||||
|
||||
@@ -123,7 +123,7 @@ typedef struct cs_arch_config {
|
||||
X86_global_init, \
|
||||
X86_option, \
|
||||
~(CS_MODE_LITTLE_ENDIAN | CS_MODE_32 | CS_MODE_64 | \
|
||||
CS_MODE_16), \
|
||||
CS_MODE_16 | CS_MODE_X86_INTEL | CS_MODE_X86_AMD), \
|
||||
}
|
||||
#define CS_ARCH_CONFIG_PPC \
|
||||
{ \
|
||||
|
||||
@@ -285,6 +285,10 @@ Nonetheless, we hope this additional information is useful to you.
|
||||
- Decoding of conflicting segment overrides was changed to match CPU behavior:
|
||||
For instructions with both an FS/GS and a ES/CS/SS/DS overrides the FS/GS override now takes priority, regardless of prefix ordering.
|
||||
- Decoding of instructions with multiple mandatory prefixes was fixed. (e.g., `shld` with a data size override and a redundant `F3` prefix, or `addss` with an additional `66` prefix)
|
||||
- Added `CS_MODE_X86_INTEL` and `CS_MODE_X86_AMD` to select ISA specific quirks.
|
||||
Currently this is only:
|
||||
- How `66`-prefixed near conditional jumps are decoded in 64-bit mode (see flag documentation).
|
||||
Without either flag, the previous LLVM behavior is preserved.
|
||||
|
||||
**BPF**
|
||||
|
||||
|
||||
@@ -148,6 +148,13 @@ typedef enum cs_mode {
|
||||
CS_MODE_16 = 1 << 1, ///< 16-bit mode (X86)
|
||||
CS_MODE_32 = 1 << 2, ///< 32-bit mode (X86)
|
||||
CS_MODE_64 = 1 << 3, ///< 64-bit mode (X86, PPC)
|
||||
// X86
|
||||
/// x86 Intel specific quirks:
|
||||
/// - Ignore 66-prefix near Jcc in 64-bit mode.
|
||||
CS_MODE_X86_INTEL = 1 << 4,
|
||||
/// x86 AMD specific quirks:
|
||||
/// - Honor 66-prefix near Jcc in 64-bit mode, unless REX.W overrides it.
|
||||
CS_MODE_X86_AMD = 1 << 5,
|
||||
// ARM
|
||||
CS_MODE_THUMB = 1 << 4, ///< ARM's Thumb mode, including Thumb-2
|
||||
CS_MODE_MCLASS = 1 << 5, ///< ARM's Cortex-M series
|
||||
|
||||
@@ -253,6 +253,8 @@ static const cs_enum_id_map test_mode_map[] = {
|
||||
{ .str = "CS_MODE_TRICORE_180", .val = CS_MODE_TRICORE_180 },
|
||||
{ .str = "CS_MODE_V8", .val = CS_MODE_V8 },
|
||||
{ .str = "CS_MODE_V9", .val = CS_MODE_V9 },
|
||||
{ .str = "CS_MODE_X86_AMD", .val = CS_MODE_X86_AMD },
|
||||
{ .str = "CS_MODE_X86_INTEL", .val = CS_MODE_X86_INTEL },
|
||||
{ .str = "CS_MODE_XTENSA_ESP32", .val = CS_MODE_XTENSA_ESP32 },
|
||||
{ .str = "CS_MODE_XTENSA_ESP32S2", .val = CS_MODE_XTENSA_ESP32S2 },
|
||||
{ .str = "CS_MODE_XTENSA_ESP32S3", .val = CS_MODE_XTENSA_ESP32S3 },
|
||||
|
||||
@@ -0,0 +1,236 @@
|
||||
test_cases:
|
||||
- input:
|
||||
name: "Jcc DEFAULT: JO rel16"
|
||||
bytes: [0x66, 0x0f, 0x80, 0xce, 0xfa, 0xa5, 0xd8]
|
||||
arch: CS_ARCH_X86
|
||||
options: [CS_MODE_64, CS_OPT_DETAIL]
|
||||
address: 0
|
||||
expected:
|
||||
insns:
|
||||
- asm_text: "jo 0xfffffffffffffad3"
|
||||
size: 5
|
||||
details:
|
||||
x86:
|
||||
enc_imm_offset: 3
|
||||
enc_imm_size: 2
|
||||
operands:
|
||||
- type: X86_OP_IMM
|
||||
imm: -1325
|
||||
size: 4
|
||||
- asm_text: "movsd dword ptr [rdi], dword ptr [rsi]"
|
||||
size: 1
|
||||
- input:
|
||||
name: "Jcc DEFAULT: JB rel32"
|
||||
bytes: [0x66, 0x0f, 0x82, 0xce, 0xfa, 0xa5, 0xd8]
|
||||
arch: CS_ARCH_X86
|
||||
options: [CS_MODE_64, CS_OPT_DETAIL]
|
||||
address: 0
|
||||
expected:
|
||||
insns:
|
||||
- asm_text: "jb 0xffffffffd8a5fad5"
|
||||
size: 7
|
||||
details:
|
||||
x86:
|
||||
enc_imm_size: 4
|
||||
operands:
|
||||
- type: X86_OP_IMM
|
||||
imm: -660210987
|
||||
size: 4
|
||||
- input:
|
||||
name: "Jcc AMD: JO rel16 and following MOVSD"
|
||||
bytes: [0x66, 0x0f, 0x80, 0xce, 0xfa, 0xa5, 0xd8]
|
||||
arch: CS_ARCH_X86
|
||||
options: [CS_MODE_64, CS_OPT_DETAIL, CS_MODE_X86_AMD]
|
||||
address: 0x123450000
|
||||
expected:
|
||||
insns:
|
||||
- asm_text: "jo 0xfad3"
|
||||
size: 5
|
||||
details:
|
||||
x86:
|
||||
enc_imm_offset: 3
|
||||
enc_imm_size: 2
|
||||
operands:
|
||||
- type: X86_OP_IMM
|
||||
imm: 0xfad3
|
||||
size: 2
|
||||
- asm_text: "movsd dword ptr [rdi], dword ptr [rsi]"
|
||||
size: 1
|
||||
- input:
|
||||
name: "Jcc AMD: JNO in AT&T syntax"
|
||||
bytes: [0x66, 0x0f, 0x81, 0xce, 0xfa, 0xa5, 0xd8]
|
||||
arch: CS_ARCH_X86
|
||||
options: [CS_MODE_64, CS_OPT_DETAIL, CS_MODE_X86_AMD, CS_OPT_SYNTAX_ATT]
|
||||
address: 0
|
||||
expected:
|
||||
insns:
|
||||
- asm_text: "jno 0xfad3"
|
||||
size: 5
|
||||
details:
|
||||
x86:
|
||||
enc_imm_size: 2
|
||||
operands:
|
||||
- type: X86_OP_IMM
|
||||
imm: 0xfad3
|
||||
size: 2
|
||||
- asm_text: "movsl (%rsi), (%rdi)"
|
||||
size: 1
|
||||
- input:
|
||||
name: "Jcc AMD: JB target wraparound"
|
||||
bytes: [0x66, 0x0f, 0x82, 0x01, 0x00]
|
||||
arch: CS_ARCH_X86
|
||||
options: [CS_MODE_64, CS_OPT_DETAIL, CS_MODE_X86_AMD]
|
||||
address: 0xfffe
|
||||
expected:
|
||||
insns:
|
||||
- asm_text: "jb 4"
|
||||
size: 5
|
||||
details:
|
||||
x86:
|
||||
enc_imm_size: 2
|
||||
operands:
|
||||
- type: X86_OP_IMM
|
||||
imm: 4
|
||||
size: 2
|
||||
- input:
|
||||
name: "Jcc AMD: REX.W overrides 66"
|
||||
bytes: [0x66, 0x48, 0x0f, 0x80, 0xce, 0xfa, 0xa5, 0xd8]
|
||||
arch: CS_ARCH_X86
|
||||
options: [CS_MODE_64, CS_OPT_DETAIL, CS_MODE_X86_AMD]
|
||||
address: 0
|
||||
expected:
|
||||
insns:
|
||||
- asm_text: "jo 0xffffffffd8a5fad6"
|
||||
size: 8
|
||||
details:
|
||||
x86:
|
||||
enc_imm_offset: 4
|
||||
enc_imm_size: 4
|
||||
operands:
|
||||
- type: X86_OP_IMM
|
||||
imm: -660210986
|
||||
size: 8
|
||||
- input:
|
||||
name: "Jcc AMD: 66 after REX.W"
|
||||
bytes: [0x48, 0x66, 0x0f, 0x80, 0xce, 0xfa, 0xa5, 0xd8]
|
||||
arch: CS_ARCH_X86
|
||||
options: [CS_MODE_64, CS_OPT_DETAIL, CS_MODE_X86_AMD]
|
||||
address: 0
|
||||
expected:
|
||||
insns:
|
||||
- asm_text: "jo 0xfad4"
|
||||
size: 6
|
||||
details:
|
||||
x86:
|
||||
enc_imm_offset: 4
|
||||
enc_imm_size: 2
|
||||
operands:
|
||||
- type: X86_OP_IMM
|
||||
imm: 0xfad4
|
||||
size: 2
|
||||
- asm_text: "movsd dword ptr [rdi], dword ptr [rsi]"
|
||||
size: 1
|
||||
- input:
|
||||
name: "Jcc Intel: JG rel32"
|
||||
bytes: [0x66, 0x0f, 0x8f, 0xce, 0xfa, 0xa5, 0xd8]
|
||||
arch: CS_ARCH_X86
|
||||
options: [CS_MODE_64, CS_OPT_DETAIL, CS_MODE_X86_INTEL]
|
||||
address: 0
|
||||
expected:
|
||||
insns:
|
||||
- asm_text: "jg 0xffffffffd8a5fad5"
|
||||
size: 7
|
||||
details:
|
||||
x86:
|
||||
enc_imm_size: 4
|
||||
operands:
|
||||
- type: X86_OP_IMM
|
||||
imm: -660210987
|
||||
size: 8
|
||||
- input:
|
||||
name: "Jcc AMD: JG rel16"
|
||||
bytes: [0x66, 0x0f, 0x8f, 0xce, 0xfa]
|
||||
arch: CS_ARCH_X86
|
||||
options: [CS_MODE_64, CS_OPT_DETAIL, CS_MODE_X86_AMD]
|
||||
address: 0
|
||||
expected:
|
||||
insns:
|
||||
- asm_text: "jg 0xfad3"
|
||||
size: 5
|
||||
details:
|
||||
x86:
|
||||
enc_imm_size: 2
|
||||
operands:
|
||||
- type: X86_OP_IMM
|
||||
imm: 0xfad3
|
||||
size: 2
|
||||
- input:
|
||||
name: "Jcc Intel flag preserves 64-bit operands and registers"
|
||||
bytes: [0x48, 0xc7, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x48, 0xa1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x31, 0xd9, 0x20, 0xa5, 0xe8, 0x00, 0x00, 0x00, 0x00, 0xc3]
|
||||
arch: CS_ARCH_X86
|
||||
options: [CS_MODE_64, CS_MODE_X86_INTEL, CS_OPT_DETAIL]
|
||||
address: 0x100000000
|
||||
expected:
|
||||
insns:
|
||||
- asm_text: "mov rax, 0xffffffffffffffff"
|
||||
details:
|
||||
x86:
|
||||
operands:
|
||||
- type: X86_OP_REG
|
||||
reg: rax
|
||||
size: 8
|
||||
- type: X86_OP_IMM
|
||||
imm: -1
|
||||
size: 8
|
||||
- asm_text: "movabs rax, qword ptr [0xffffffffffffffff]"
|
||||
- asm_text: "rdtsc"
|
||||
details:
|
||||
regs_write: [rax, rdx]
|
||||
- asm_text: "fldenv [rax]"
|
||||
details:
|
||||
x86:
|
||||
operands:
|
||||
- type: X86_OP_MEM
|
||||
mem_base: rax
|
||||
size: 28
|
||||
- asm_text: "movsd dword ptr [rdi], dword ptr [rsi]"
|
||||
details:
|
||||
regs_read: [rdi, rsi, rflags]
|
||||
regs_write: [rdi, rsi]
|
||||
- asm_text: "call 0x10000001b"
|
||||
- asm_text: "ret"
|
||||
- input:
|
||||
name: "Jcc AMD flag preserves 64-bit operands and registers in AT&T syntax"
|
||||
bytes: [0x48, 0xc7, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x48, 0xa1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x31, 0xd9, 0x20, 0xa5, 0xe8, 0x00, 0x00, 0x00, 0x00, 0xc3]
|
||||
arch: CS_ARCH_X86
|
||||
options: [CS_MODE_64, CS_MODE_X86_AMD, CS_OPT_DETAIL, CS_OPT_SYNTAX_ATT]
|
||||
address: 0x100000000
|
||||
expected:
|
||||
insns:
|
||||
- asm_text: "movq $0xffffffffffffffff, %rax"
|
||||
details:
|
||||
x86:
|
||||
operands:
|
||||
- type: X86_OP_IMM
|
||||
imm: -1
|
||||
size: 8
|
||||
- type: X86_OP_REG
|
||||
reg: rax
|
||||
size: 8
|
||||
- asm_text: "movabsq 0xffffffffffffffff, %rax"
|
||||
- asm_text: "rdtsc"
|
||||
details:
|
||||
regs_write: [rax, rdx]
|
||||
- asm_text: "fldenv (%rax)"
|
||||
details:
|
||||
x86:
|
||||
operands:
|
||||
- type: X86_OP_MEM
|
||||
mem_base: rax
|
||||
size: 28
|
||||
- asm_text: "movsl (%rsi), (%rdi)"
|
||||
details:
|
||||
regs_read: [rdi, rsi, rflags]
|
||||
regs_write: [rdi, rsi]
|
||||
- asm_text: "callq 0x10000001b"
|
||||
- asm_text: "retq"
|
||||
@@ -7207,3 +7207,25 @@ test_cases:
|
||||
regs_read: [ rsp, ss ]
|
||||
regs_write: [ rsp, rip ]
|
||||
groups: [ ret, mode64 ]
|
||||
-
|
||||
input:
|
||||
name: "issue 3037 x86-64 Intel JO ignores operand-size override"
|
||||
bytes: [ 0x66,0x0f,0x80,0xce,0xfa,0xa5,0xd8 ]
|
||||
arch: "CS_ARCH_X86"
|
||||
options: [ CS_MODE_64, CS_OPT_DETAIL, CS_MODE_X86_INTEL ]
|
||||
address: 0x0
|
||||
expected:
|
||||
insns:
|
||||
-
|
||||
asm_text: "jo 0xffffffffd8a5fad5"
|
||||
-
|
||||
input:
|
||||
name: "issue 3037 x86-64 Intel JNO ignores operand-size override"
|
||||
bytes: [ 0x66,0x0f,0x81,0xce,0xfa,0xa5,0xd8 ]
|
||||
arch: "CS_ARCH_X86"
|
||||
options: [ CS_MODE_64, CS_OPT_DETAIL, CS_MODE_X86_INTEL ]
|
||||
address: 0x0
|
||||
expected:
|
||||
insns:
|
||||
-
|
||||
asm_text: "jno 0xffffffffd8a5fad5"
|
||||
|
||||
Reference in New Issue
Block a user