Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add cs_insn_flags. Breaking API change. #2374

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think a function to check for flags is better for the flag field (something like cs_flag_set(insn->flags, CS_INSN_FLAG_ALIAS)). Bit operations in conditions get messy after a while.

Copy link
Author

@numas13 numas13 May 29, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added some macros to manage flags for more complex cases. See capstone.h.

CS_INSN_FLAGS_ALL -- test if all flags is set
CS_INSN_FLAGS_ANY -- test if any flag is set
CS_INSN_FLAGS_SET -- enable flags if condition is true, disable flags if false

But forgot to add some documentation. :)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ouh, sorry. Overlooked it. Just took a shallow look.

Copy link
Collaborator

@Rot127 Rot127 May 29, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wait. I meant for checking if a flag is set. Like cs_flag_is_set(insn->flags, CS_INSN_FLAG_ALIAS) => true/false.
But I'll review tomorrow again with a clear mind.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can check it with CS_INSN_FLAGS_ANY(insn, 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
Loading