Skip to content

Commit

Permalink
Add cs_insn_flags. Breaking API change.
Browse files Browse the repository at this point in the history
Replace dedicated cs_insn members for boolean flags with bitflags.
  • Loading branch information
numas13 committed May 31, 2024
1 parent 1a6921f commit 1b5577b
Show file tree
Hide file tree
Showing 10 changed files with 51 additions and 22 deletions.
2 changes: 1 addition & 1 deletion MCInst.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion Mapping.c
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,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;
}

Expand Down
4 changes: 2 additions & 2 deletions arch/AArch64/AArch64Mapping.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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);
Expand Down
4 changes: 2 additions & 2 deletions arch/ARM/ARMMapping.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion arch/PowerPC/PPCMapping.c
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down
8 changes: 6 additions & 2 deletions bindings/python/capstone/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -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)),
)

Expand Down
8 changes: 6 additions & 2 deletions bindings/python/pyx/ccapstone.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,23 @@ cdef extern from "<capstone/capstone.h>":
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:
Expand Down
8 changes: 8 additions & 0 deletions cs_priv.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,4 +109,12 @@ extern cs_vsnprintf_t cs_vsnprintf;
#define CS_ASSERT(expr)
#endif

/// Set flags if condition is true or clear flags.
#define CS_INSN_FLAGS_SET(INSN, COND, FLAGS) \
if (COND) { \
(INSN)->flags |= FLAGS; \
} else { \
(INSN)->flags &= ~(FLAGS); \
}

#endif
4 changes: 2 additions & 2 deletions cstool/cstool.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
31 changes: 22 additions & 9 deletions include/capstone/capstone.h
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,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)
Expand All @@ -450,6 +465,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 <ARCH>_INS_INVALID.
Expand All @@ -476,15 +494,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
Expand All @@ -495,6 +504,10 @@ typedef struct cs_insn {
cs_detail *detail;
} cs_insn;

/// Check if all flags is set.
#define CS_INSN_FLAGS_ALL(INSN, FLAGS) (((INSN)->flags & (FLAGS)) == (FLAGS))
/// Check if any flag is set.
#define CS_INSN_FLAGS_ANY(INSN, FLAGS) (((INSN)->flags & (FLAGS)) != 0)

/// Calculate the offset of a disassembled instruction in its buffer, given its position
/// in its array of disassembled insn
Expand Down

0 comments on commit 1b5577b

Please sign in to comment.