From 58fa319a30c63205bae57cd17664d3e56e26f694 Mon Sep 17 00:00:00 2001 From: Denis Drakhnia Date: Tue, 28 May 2024 10:52:05 +0300 Subject: [PATCH] Add cs_insn_flags. Breaking API change. Replace dedicated cs_insn members for boolean flags with bitflags. --- MCInst.c | 2 +- Mapping.c | 2 +- arch/AArch64/AArch64Mapping.c | 4 ++-- arch/ARM/ARMMapping.c | 4 ++-- arch/PowerPC/PPCMapping.c | 2 +- bindings/python/capstone/__init__.py | 8 +++++-- bindings/python/pyx/ccapstone.pxd | 8 +++++-- cstool/cstool.c | 4 ++-- include/capstone/capstone.h | 35 +++++++++++++++++++++------- 9 files changed, 47 insertions(+), 22 deletions(-) diff --git a/MCInst.c b/MCInst.c index 933327a468..e7bf3384b9 100644 --- a/MCInst.c +++ b/MCInst.c @@ -288,7 +288,7 @@ uint64_t MCInst_getOpVal(MCInst *MI, unsigned OpNum) void MCInst_setIsAlias(MCInst *MI, bool Flag) { assert(MI); MI->isAliasInstr = Flag; - MI->flat_insn->is_alias = Flag; + CS_INSN_FLAGS_SET(MI->flat_insn, Flag, CS_INSN_FLAG_ALIAS); } /// @brief Copies the relevant members of a temporary MCInst to diff --git a/Mapping.c b/Mapping.c index 5483bee6ad..90de9f28c6 100644 --- a/Mapping.c +++ b/Mapping.c @@ -361,7 +361,7 @@ void map_set_fill_detail_ops(MCInst *MI, bool Val) { void map_set_is_alias_insn(MCInst *MI, bool Val, uint64_t Alias) { assert(MI); MI->isAliasInstr = Val; - MI->flat_insn->is_alias = Val; + CS_INSN_FLAGS_SET(MI->flat_insn, Val, CS_INSN_FLAG_ALIAS); MI->flat_insn->alias_id = Alias; } diff --git a/arch/AArch64/AArch64Mapping.c b/arch/AArch64/AArch64Mapping.c index 6db42a21f5..824ce8283f 100644 --- a/arch/AArch64/AArch64Mapping.c +++ b/arch/AArch64/AArch64Mapping.c @@ -423,7 +423,7 @@ static void AArch64_add_not_defined_ops(MCInst *MI, const SStream *OS) if (!detail_is_set(MI)) return; - if (!MI->flat_insn->is_alias || !MI->flat_insn->usesAliasDetails) { + if (!CS_INSN_FLAGS_ALL(MI->flat_insn, CS_INSN_FLAG_ALIAS | CS_INSN_FLAG_ALIAS_DETAILS)) { add_non_alias_details(MI); return; } @@ -539,7 +539,7 @@ void AArch64_printer(MCInst *MI, SStream *O, void * /* MCRegisterInfo* */ info) MCRegisterInfo *MRI = (MCRegisterInfo *)info; MI->MRI = MRI; MI->fillDetailOps = detail_is_set(MI); - MI->flat_insn->usesAliasDetails = map_use_alias_details(MI); + CS_INSN_FLAGS_SET(MI->flat_insn, map_use_alias_details(MI), CS_INSN_FLAG_ALIAS_DETAILS); AArch64_LLVM_printInstruction(MI, O, info); if (detail_is_set(MI)) AArch64_get_detail(MI)->post_index = AArch64_check_post_index_am(MI, O); diff --git a/arch/ARM/ARMMapping.c b/arch/ARM/ARMMapping.c index beb0214a02..d71aac4ae0 100644 --- a/arch/ARM/ARMMapping.c +++ b/arch/ARM/ARMMapping.c @@ -257,7 +257,7 @@ static void ARM_add_not_defined_ops(MCInst *MI) if (!detail_is_set(MI)) return; - if (MI->flat_insn->is_alias && MI->flat_insn->usesAliasDetails) { + if (CS_INSN_FLAGS_ALL(MI->flat_insn, CS_INSN_FLAG_ALIAS | CS_INSN_FLAG_ALIAS_DETAILS)) { add_alias_details(MI); return; } @@ -596,7 +596,7 @@ void ARM_printer(MCInst *MI, SStream *O, void * /* MCRegisterInfo* */ info) MCRegisterInfo *MRI = (MCRegisterInfo *)info; MI->MRI = MRI; MI->fillDetailOps = detail_is_set(MI); - MI->flat_insn->usesAliasDetails = map_use_alias_details(MI); + CS_INSN_FLAGS_SET(MI->flat_insn, map_use_alias_details(MI), CS_INSN_FLAG_ALIAS_DETAILS); ARM_LLVM_printInstruction(MI, O, info); map_set_alias_id(MI, O, insn_alias_mnem_map, ARR_SIZE(insn_alias_mnem_map) - 1); ARM_add_not_defined_ops(MI); diff --git a/arch/PowerPC/PPCMapping.c b/arch/PowerPC/PPCMapping.c index 2d11674389..58f9aad098 100644 --- a/arch/PowerPC/PPCMapping.c +++ b/arch/PowerPC/PPCMapping.c @@ -223,7 +223,7 @@ void PPC_printer(MCInst *MI, SStream *O, void * /* MCRegisterInfo* */ info) { MI->MRI = (MCRegisterInfo *)info; MI->fillDetailOps = detail_is_set(MI); - MI->flat_insn->usesAliasDetails = map_use_alias_details(MI); + CS_INSN_FLAGS_SET(MI->flat_insn, map_use_alias_details(MI), CS_INSN_FLAG_ALIAS_DETAILS); PPC_LLVM_printInst(MI, MI->address, "", O); map_set_alias_id(MI, O, insn_alias_mnem_map, ARR_SIZE(insn_alias_mnem_map)); diff --git a/bindings/python/capstone/__init__.py b/bindings/python/capstone/__init__.py index 154e6f1105..83bb554a26 100755 --- a/bindings/python/capstone/__init__.py +++ b/bindings/python/capstone/__init__.py @@ -355,6 +355,11 @@ CS_OPT_SYNTAX_MOTOROLA = 1 << 6 # MOS65XX use $ as hex prefix CS_OPT_SYNTAX_CS_REG_ALIAS = 1 << 7 # Prints common register alias which are not defined in LLVM (ARM: r9 = sb etc.) +# Instruction flags +CS_INSN_FLAG_ALIAS = 1 << 0 +CS_INSN_FLAG_ALIAS_DETAIL = 1 << 1 +CS_INSN_FLAG_ARCH_MASK = 0xfff00000 + # Capstone error type CS_ERR_OK = 0 # No error: everything was fine CS_ERR_MEM = 1 # Out-Of-Memory error: cs_open(), cs_disasm() @@ -492,14 +497,13 @@ class _cs_detail(ctypes.Structure): class _cs_insn(ctypes.Structure): _fields_ = ( ('id', ctypes.c_uint), + ('flags', ctypes.c_uint), ('alias_id', ctypes.c_uint64), ('address', ctypes.c_uint64), ('size', ctypes.c_uint16), ('bytes', ctypes.c_ubyte * 24), ('mnemonic', ctypes.c_char * 32), ('op_str', ctypes.c_char * 160), - ('is_alias', ctypes.c_bool), - ('usesAliasDetails', ctypes.c_bool), ('detail', ctypes.POINTER(_cs_detail)), ) diff --git a/bindings/python/pyx/ccapstone.pxd b/bindings/python/pyx/ccapstone.pxd index 176dd43b20..6d091966c5 100644 --- a/bindings/python/pyx/ccapstone.pxd +++ b/bindings/python/pyx/ccapstone.pxd @@ -13,19 +13,23 @@ cdef extern from "": ctypedef enum cs_arch: pass + ctypedef enum cs_insn_flags: + is_alias "CS_INSN_FLAG_ALIAS" = 1 << 0 + usesAliasDetails "CS_INSN_FLAG_ALIAS_DETAILS" = 1 << 1 + archMask "CS_INSN_FLAG_ARCH_MASK" = 0xfff00000 + ctypedef struct cs_detail: pass ctypedef struct cs_insn: unsigned int id + cs_insn_flags flags uint64_t alias_id; uint64_t address uint16_t size uint8_t bytes[24] char mnemonic[32] char op_str[160] - bool is_alias; - bool usesAliasDetails; cs_detail *detail ctypedef enum cs_err: diff --git a/cstool/cstool.c b/cstool/cstool.c index 795850840f..15278df485 100644 --- a/cstool/cstool.c +++ b/cstool/cstool.c @@ -354,9 +354,9 @@ static void usage(char *prog) static void print_details(csh handle, cs_arch arch, cs_mode md, cs_insn *ins) { printf("\tID: %u (%s)\n", ins->id, cs_insn_name(handle, ins->id)); - if (ins->is_alias) { + if (ins->flags & CS_INSN_FLAG_ALIAS) { printf("\tIs alias: %" PRIu64 " (%s) ", ins->alias_id, cs_insn_name(handle, ins->alias_id)); - printf("with %s operand set\n", ins->usesAliasDetails ? "ALIAS" : "REAL"); + printf("with %s operand set\n", ins->flags & CS_INSN_FLAG_ALIAS_DETAILS ? "ALIAS" : "REAL"); } switch(arch) { diff --git a/include/capstone/capstone.h b/include/capstone/capstone.h index 4fed66ef08..055e931c2e 100644 --- a/include/capstone/capstone.h +++ b/include/capstone/capstone.h @@ -426,6 +426,21 @@ typedef struct cs_detail { }; } cs_detail; +/// Instruction flags. +typedef enum cs_insn_flags { + /// True: This instruction is an alias. + /// False: Otherwise. + /// -- Only supported by auto-sync archs -- + CS_INSN_FLAG_ALIAS = 1 << 0, + + /// True: The operands are the ones of the alias instructions. + /// False: The detail operands are from the real instruction. + CS_INSN_FLAG_ALIAS_DETAILS = 1 << 1, + + /// Mask for architecture specific flags. + CS_INSN_FLAG_ARCH_MASK = 0xfff00000, +} cs_insn_flags; + /// Detail information of disassembled instruction typedef struct cs_insn { /// Instruction ID (basically a numeric ID for the instruction mnemonic) @@ -436,6 +451,9 @@ typedef struct cs_insn { /// NOTE: in Skipdata mode, "data" instruction has 0 for this id field. unsigned int id; + /// Instruction flags. + cs_insn_flags flags; + /// If this instruction is an alias instruction, this member is set with /// the alias ID. /// Otherwise to _INS_INVALID. @@ -462,15 +480,6 @@ typedef struct cs_insn { /// This information is available even when CS_OPT_DETAIL = CS_OPT_OFF char op_str[160]; - /// True: This instruction is an alias. - /// False: Otherwise. - /// -- Only supported by auto-sync archs -- - bool is_alias; - - /// True: The operands are the ones of the alias instructions. - /// False: The detail operands are from the real instruction. - bool usesAliasDetails; - /// Pointer to cs_detail. /// NOTE: detail pointer is only valid when both requirements below are met: /// (1) CS_OP_DETAIL = CS_OPT_ON @@ -481,6 +490,14 @@ typedef struct cs_insn { cs_detail *detail; } cs_insn; +#define CS_INSN_FLAGS_ALL(INSN, FLAGS) (((INSN)->flags & (FLAGS)) == (FLAGS)) +#define CS_INSN_FLAGS_ANY(INSN, FLAGS) (((INSN)->flags & (FLAGS)) != 0) +#define CS_INSN_FLAGS_SET(INSN, COND, FLAGS) \ + if (COND) { \ + (INSN)->flags |= FLAGS; \ + } else { \ + (INSN)->flags &= ~(FLAGS); \ + } /// Calculate the offset of a disassembled instruction in its buffer, given its position /// in its array of disassembled insn