5af28808 Update Auto-Sync to Python 3.13 and tree-sitter-py 24.0 (#2705) 99f018ac Python binding: (#2742) a07baf83 Auto-Sync update Sparc LLVM-18 (#2704) 81c5c93d Enable to generate legacy MC tests for the fuzzer. (#2733) a25d4980 Add warning about naive search and replace to patch reg names. (#2728) 7ac87d17 Print immediate only memory operands for AArch64. (#2732) c34034c8 Add x30 implicit read to the RET alias. (#2739) 95a4ca3e Update source list before installing valgrind. (#2730) 6909724e Make assertion hit warnings optional in release builds. (#2729) fe6bdc6e Make SStream respect the CS_OPT_UNSIGNED flag. (#2723) 21ce3624 Use cs_ac_type for operand access mode in all arches and use cs_xtensa_op_type for Xtensa operand type (#2721) df26583f clang-format: change license to BSD-3-Clause (#2724) 280b749e Remove unused files. (#2709) 87908ece Add flag for the SoftFail case of the LLVM disassembler. (#2707) efc0ba44 Fix missing operand for smstart, due to space replaced by tab (#2720) 2ae64133 Fix missing sp register read in ret instruction (#2719) 8df252a6 Fix arm pop reg access (#2718) 14612272 ARM: fix typo, cspr -> cpsr (#2716) f2f0a3c3 Fix LoongArch ld/st instructions register info (#2701) 829be2bf LoongArch: Compute absolute address for address operand (#2699) 42fbce6c Add jump group for generic jirl (#2698) fc525c73 Apple AArch64 proprietary (#2692) 895f2f2e Build PDB for debugging on Windows (#2685) 5c3aef03 Version: Update to v6.0.0-alpha4 (#2682) 106f7d3b Update read/written registers for x87 comparison instructions (#2680) ebe3ef2a Add workflow for building on Windows (#2675) 72f7d305 Revert "Add a script to compare the inc file content with the latest generate…" (#2678) 5b5c5ed8 Fix nanomips decoding of jalrc (#2672) ae03cca4 Mips32r6_64r632 is for both mips32r6 and mips64r6 (#2673) 21178aea Add a script to compare the inc file content with the latest generated ones. (#2667) 81a6ba03 MIPS: Fix MIPS16 decoding, wrong flags and ghost registers (#2665) 98a393e3 Stringify BH fields when printing ppc details (#2663) 2607d0f3 Remove undefined constants in riscv_const.py (#2660) (#2661) 5058c634 Decode BH field in print_insn_detail_ppc (#2662) 6461ed08 Add Call group to svc, smc and hvc. (#2651) e2f1dc8d Tms32c64x Little Endian (#2648) 5464c91d Fix build for compilers requiring explicit static for inline functions.. (#2645) bb2f6579 Enhance shift value and types of shift instructions. (#2638) cd282ef5 Update operand type enums of all arch modules to the one in `capstone.h` (#2633) dc0c0909 cmake: Fix building capstone as sub-project (#2629) cd8dd20c - Added missing files for sdist archive (#2624) 9affd99b Give the user some guidance where to add missing enumeration values. (#2639) 1bea3fab Add checks for MIPS details on cstest_py (#2640) ace8056c Add aliases mapping for MIPS & test for id, alias_id (#2635) 1abe1868 Build Tarball before DEB/RPM package. (#2627) 0a012190 Switch to ubuntu-24.04-arm runner image (#2625) 4e0b8c48 Fix wrong version requirement of tricore instructions: (#2620) 8ac2843b chore(version): Update Version to 6.0.0-Alpha3 (#2616) d7ef910b Rebased #2570 (#2614) c831cd5e Fix SystemZ macro in Makefile (#2603) 30601176 Apply new EVM opcode updates (#2602) 3c4d7fc8 Add tricore tc1.8 instructions (#2595) 5f290cad Create debian and rpm package on releases (#2590) 0f09210a delete travis (#2600) 5c5f756f Downgrade labeler to v4 due to https://github.com/actions/labeler/issues/710. (#2598) git-subtree-dir: external/capstone git-subtree-split: 5af288083e9f03e32723f9708c305692f866b666
306 lines
9.4 KiB
C
306 lines
9.4 KiB
C
/* Capstone Disassembly Engine */
|
|
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
|
|
/* Rot127 <unisono@quyllur.org>, 2022-2023 */
|
|
|
|
#ifndef CS_MAPPING_H
|
|
#define CS_MAPPING_H
|
|
|
|
#if defined(CAPSTONE_HAS_OSXKERNEL)
|
|
#include <libkern/libkern.h>
|
|
#else
|
|
#include "include/capstone/capstone.h"
|
|
#include <stddef.h>
|
|
#endif
|
|
#include "cs_priv.h"
|
|
#include <assert.h>
|
|
#include <string.h>
|
|
|
|
// map instruction to its characteristics
|
|
typedef struct insn_map {
|
|
unsigned short id; // The LLVM instruction id
|
|
unsigned short mapid; // The Capstone instruction id
|
|
#ifndef CAPSTONE_DIET
|
|
uint16_t regs_use[MAX_IMPL_R_REGS]; ///< list of implicit registers used by
|
|
///< this instruction
|
|
uint16_t regs_mod[MAX_IMPL_W_REGS]; ///< list of implicit registers modified
|
|
///< by this instruction
|
|
unsigned char groups
|
|
[MAX_NUM_GROUPS]; ///< list of group this instruction belong to
|
|
bool branch; // branch instruction?
|
|
bool indirect_branch; // indirect branch instruction?
|
|
union {
|
|
ppc_suppl_info ppc;
|
|
loongarch_suppl_info loongarch;
|
|
aarch64_suppl_info aarch64;
|
|
systemz_suppl_info systemz;
|
|
arm_suppl_info arm;
|
|
xtensa_suppl_info xtensa;
|
|
sparc_suppl_info sparc;
|
|
} suppl_info; // Supplementary information for each instruction.
|
|
#endif
|
|
} insn_map;
|
|
|
|
// look for @id in @m, given its size in @max. first time call will update
|
|
// @cache. return 0 if not found
|
|
unsigned short insn_find(const insn_map *m, unsigned int max, unsigned int id,
|
|
unsigned short **cache);
|
|
|
|
unsigned int find_cs_id(unsigned MC_Opcode, const insn_map *imap,
|
|
unsigned imap_size);
|
|
|
|
#define MAX_NO_DATA_TYPES 16
|
|
|
|
///< A LLVM<->CS Mapping entry of an MCOperand.
|
|
typedef struct {
|
|
uint8_t /* cs_op_type */ type; ///< Operand type (e.g.: reg, imm, mem)
|
|
uint8_t /* cs_ac_type */ access; ///< The access type (read, write)
|
|
uint8_t /* cs_data_type */
|
|
dtypes[MAX_NO_DATA_TYPES]; ///< List of op types. Terminated by
|
|
///< CS_DATA_TYPE_LAST
|
|
} mapping_op;
|
|
|
|
#define MAX_NO_INSN_MAP_OPS 16
|
|
|
|
///< MCOperands of an instruction.
|
|
typedef struct {
|
|
mapping_op
|
|
ops[MAX_NO_INSN_MAP_OPS]; ///< NULL terminated array of insn_op.
|
|
} map_insn_ops;
|
|
|
|
/// Only usable by `auto-sync` archs!
|
|
const cs_op_type mapping_get_op_type(MCInst *MI, unsigned OpNum,
|
|
const map_insn_ops *insn_ops_map,
|
|
size_t map_size);
|
|
|
|
/// Only usable by `auto-sync` archs!
|
|
const cs_ac_type mapping_get_op_access(MCInst *MI, unsigned OpNum,
|
|
const map_insn_ops *insn_ops_map,
|
|
size_t map_size);
|
|
|
|
/// Macro for easier access of operand types from the map.
|
|
/// Assumes the istruction operands map is called "insn_operands"
|
|
/// Only usable by `auto-sync` archs!
|
|
#ifndef CAPSTONE_DIET
|
|
#define map_get_op_type(MI, OpNum) \
|
|
mapping_get_op_type(MI, OpNum, (const map_insn_ops *)insn_operands, \
|
|
sizeof(insn_operands) / sizeof(insn_operands[0]))
|
|
#else
|
|
#define map_get_op_type(MI, OpNum) \
|
|
CS_OP_INVALID
|
|
#endif
|
|
|
|
/// Macro for easier access of operand access flags from the map.
|
|
/// Assumes the istruction operands map is called "insn_operands"
|
|
/// Only usable by `auto-sync` archs!
|
|
#ifndef CAPSTONE_DIET
|
|
#define map_get_op_access(MI, OpNum) \
|
|
mapping_get_op_access(MI, OpNum, (const map_insn_ops *)insn_operands, \
|
|
sizeof(insn_operands) / \
|
|
sizeof(insn_operands[0]))
|
|
#else
|
|
#define map_get_op_access(MI, OpNum) \
|
|
CS_AC_INVALID
|
|
#endif
|
|
|
|
///< Map for ids to their string
|
|
typedef struct name_map {
|
|
unsigned int id;
|
|
const char *name;
|
|
} name_map;
|
|
|
|
// map a name to its ID
|
|
// return 0 if not found
|
|
int name2id(const name_map *map, int max, const char *name);
|
|
|
|
// map ID to a name
|
|
// return NULL if not found
|
|
const char *id2name(const name_map *map, int max, const unsigned int id);
|
|
|
|
void map_add_implicit_write(MCInst *MI, uint32_t Reg);
|
|
void map_add_implicit_read(MCInst *MI, uint32_t Reg);
|
|
void map_remove_implicit_write(MCInst *MI, uint32_t Reg);
|
|
|
|
void map_implicit_reads(MCInst *MI, const insn_map *imap);
|
|
|
|
void map_implicit_writes(MCInst *MI, const insn_map *imap);
|
|
|
|
void add_group(MCInst *MI, unsigned /* arch_group */ group);
|
|
|
|
void map_groups(MCInst *MI, const insn_map *imap);
|
|
|
|
void map_cs_id(MCInst *MI, const insn_map *imap, unsigned int imap_size);
|
|
|
|
const void *map_get_suppl_info(MCInst *MI, const insn_map *imap);
|
|
|
|
#define DECL_get_detail_op(arch, ARCH) \
|
|
cs_##arch##_op *ARCH##_get_detail_op(MCInst *MI, int offset);
|
|
|
|
DECL_get_detail_op(arm, ARM);
|
|
DECL_get_detail_op(ppc, PPC);
|
|
DECL_get_detail_op(tricore, TriCore);
|
|
DECL_get_detail_op(aarch64, AArch64);
|
|
DECL_get_detail_op(alpha, Alpha);
|
|
DECL_get_detail_op(hppa, HPPA);
|
|
DECL_get_detail_op(loongarch, LoongArch);
|
|
DECL_get_detail_op(mips, Mips);
|
|
DECL_get_detail_op(riscv, RISCV);
|
|
DECL_get_detail_op(systemz, SystemZ);
|
|
DECL_get_detail_op(xtensa, Xtensa);
|
|
DECL_get_detail_op(bpf, BPF);
|
|
DECL_get_detail_op(arc, ARC);
|
|
DECL_get_detail_op(sparc, Sparc);
|
|
|
|
/// Increments the detail->arch.op_count by one.
|
|
#define DEFINE_inc_detail_op_count(arch, ARCH) \
|
|
static inline void ARCH##_inc_op_count(MCInst *MI) \
|
|
{ \
|
|
MI->flat_insn->detail->arch.op_count++; \
|
|
}
|
|
|
|
/// Decrements the detail->arch.op_count by one.
|
|
#define DEFINE_dec_detail_op_count(arch, ARCH) \
|
|
static inline void ARCH##_dec_op_count(MCInst *MI) \
|
|
{ \
|
|
MI->flat_insn->detail->arch.op_count--; \
|
|
}
|
|
|
|
DEFINE_inc_detail_op_count(arm, ARM);
|
|
DEFINE_dec_detail_op_count(arm, ARM);
|
|
DEFINE_inc_detail_op_count(ppc, PPC);
|
|
DEFINE_dec_detail_op_count(ppc, PPC);
|
|
DEFINE_inc_detail_op_count(tricore, TriCore);
|
|
DEFINE_dec_detail_op_count(tricore, TriCore);
|
|
DEFINE_inc_detail_op_count(aarch64, AArch64);
|
|
DEFINE_dec_detail_op_count(aarch64, AArch64);
|
|
DEFINE_inc_detail_op_count(alpha, Alpha);
|
|
DEFINE_dec_detail_op_count(alpha, Alpha);
|
|
DEFINE_inc_detail_op_count(hppa, HPPA);
|
|
DEFINE_dec_detail_op_count(hppa, HPPA);
|
|
DEFINE_inc_detail_op_count(loongarch, LoongArch);
|
|
DEFINE_dec_detail_op_count(loongarch, LoongArch);
|
|
DEFINE_inc_detail_op_count(mips, Mips);
|
|
DEFINE_dec_detail_op_count(mips, Mips);
|
|
DEFINE_inc_detail_op_count(riscv, RISCV);
|
|
DEFINE_dec_detail_op_count(riscv, RISCV);
|
|
DEFINE_inc_detail_op_count(systemz, SystemZ);
|
|
DEFINE_dec_detail_op_count(systemz, SystemZ);
|
|
DEFINE_inc_detail_op_count(xtensa, Xtensa);
|
|
DEFINE_dec_detail_op_count(xtensa, Xtensa);
|
|
DEFINE_inc_detail_op_count(bpf, BPF);
|
|
DEFINE_dec_detail_op_count(bpf, BPF);
|
|
DEFINE_inc_detail_op_count(arc, ARC);
|
|
DEFINE_dec_detail_op_count(arc, ARC);
|
|
DEFINE_inc_detail_op_count(sparc, Sparc);
|
|
DEFINE_dec_detail_op_count(sparc, Sparc);
|
|
|
|
/// Returns true if a memory operand is currently edited.
|
|
static inline bool doing_mem(const MCInst *MI)
|
|
{
|
|
return MI->csh->doing_mem;
|
|
}
|
|
|
|
/// Sets the doing_mem flag to @status.
|
|
static inline void set_doing_mem(const MCInst *MI, bool status)
|
|
{
|
|
MI->csh->doing_mem = status;
|
|
}
|
|
|
|
/// Returns detail->arch
|
|
#define DEFINE_get_arch_detail(arch, ARCH) \
|
|
static inline cs_##arch *ARCH##_get_detail(const MCInst *MI) \
|
|
{ \
|
|
assert(MI && MI->flat_insn && MI->flat_insn->detail); \
|
|
return &MI->flat_insn->detail->arch; \
|
|
}
|
|
|
|
DEFINE_get_arch_detail(arm, ARM);
|
|
DEFINE_get_arch_detail(ppc, PPC);
|
|
DEFINE_get_arch_detail(tricore, TriCore);
|
|
DEFINE_get_arch_detail(aarch64, AArch64);
|
|
DEFINE_get_arch_detail(alpha, Alpha);
|
|
DEFINE_get_arch_detail(hppa, HPPA);
|
|
DEFINE_get_arch_detail(loongarch, LoongArch);
|
|
DEFINE_get_arch_detail(mips, Mips);
|
|
DEFINE_get_arch_detail(riscv, RISCV);
|
|
DEFINE_get_arch_detail(arc, ARC);
|
|
DEFINE_get_arch_detail(systemz, SystemZ);
|
|
DEFINE_get_arch_detail(xtensa, Xtensa);
|
|
DEFINE_get_arch_detail(bpf, BPF);
|
|
DEFINE_get_arch_detail(sparc, Sparc);
|
|
|
|
#define DEFINE_check_safe_inc(Arch, ARCH) \
|
|
static inline void Arch##_check_safe_inc(const MCInst *MI) { \
|
|
assert(Arch##_get_detail(MI)->op_count + 1 < NUM_##ARCH##_OPS); \
|
|
}
|
|
|
|
DEFINE_check_safe_inc(ARM, ARM);
|
|
DEFINE_check_safe_inc(PPC, PPC);
|
|
DEFINE_check_safe_inc(TriCore, TRICORE);
|
|
DEFINE_check_safe_inc(AArch64, AARCH64);
|
|
DEFINE_check_safe_inc(Alpha, ALPHA);
|
|
DEFINE_check_safe_inc(HPPA, HPPA);
|
|
DEFINE_check_safe_inc(LoongArch, LOONGARCH);
|
|
DEFINE_check_safe_inc(RISCV, RISCV);
|
|
DEFINE_check_safe_inc(SystemZ, SYSTEMZ);
|
|
DEFINE_check_safe_inc(Mips, MIPS);
|
|
DEFINE_check_safe_inc(BPF, BPF);
|
|
DEFINE_check_safe_inc(ARC, ARC);
|
|
DEFINE_check_safe_inc(Sparc, SPARC);
|
|
|
|
static inline bool detail_is_set(const MCInst *MI)
|
|
{
|
|
assert(MI && MI->flat_insn);
|
|
return MI->flat_insn->detail != NULL && MI->csh->detail_opt & CS_OPT_ON;
|
|
}
|
|
|
|
static inline cs_detail *get_detail(const MCInst *MI)
|
|
{
|
|
assert(MI && MI->flat_insn);
|
|
return MI->flat_insn->detail;
|
|
}
|
|
|
|
/// Returns if the given instruction is an alias instruction.
|
|
#define RETURN_IF_INSN_IS_ALIAS(MI) \
|
|
do { \
|
|
if (MI->isAliasInstr) \
|
|
return; \
|
|
} while(0)
|
|
|
|
void map_set_fill_detail_ops(MCInst *MI, bool Val);
|
|
|
|
static inline bool map_fill_detail_ops(MCInst *MI) {
|
|
assert(MI);
|
|
return MI->fillDetailOps;
|
|
}
|
|
|
|
void map_set_is_alias_insn(MCInst *MI, bool Val, uint64_t Alias);
|
|
|
|
bool map_use_alias_details(const MCInst *MI);
|
|
|
|
void map_set_alias_id(MCInst *MI, const SStream *O, const name_map *alias_mnem_id_map, int map_size);
|
|
|
|
/// Mapping from Capstone enumeration identifiers and their values.
|
|
///
|
|
/// This map MUST BE sorted to allow binary searches.
|
|
/// Please always ensure the map is sorted after you added a value.
|
|
///
|
|
/// You can sort the map with Python.
|
|
/// Copy the map into a file and run:
|
|
///
|
|
/// ```python
|
|
/// with open("/tmp/file_with_map_entries") as f:
|
|
/// text = f.readlines()
|
|
///
|
|
/// text.sort()
|
|
/// print(''.join(text))
|
|
/// ```
|
|
typedef struct {
|
|
const char *str; ///< The name of the enumeration identifier
|
|
uint64_t val; ///< The value of the identifier
|
|
} cs_enum_id_map;
|
|
|
|
uint64_t enum_map_bin_search(const cs_enum_id_map *map, size_t map_len,
|
|
const char *id, bool *found);
|
|
|
|
#endif // CS_MAPPING_H
|