mirror of
https://github.com/capstone-engine/capstone
synced 2026-08-11 16:26:07 -04:00
Fix unchecked allocations (#2844)
* Fix trivial unchecked allocations * Move instruction lookup caching allocation into the core * Apply formatting nitpicks Co-authored-by: Rot127 <45763064+Rot127@users.noreply.github.com> * Assert to avoid an integer overflow in lookup_insn_map() * Remove unused member from cs_struct * Document what happens when lookup_insn_map() fails --------- Co-authored-by: Samuel Arnold <samuel.arnold@crowdstrike.com> Co-authored-by: Rot127 <45763064+Rot127@users.noreply.github.com>
This commit is contained in:
parent
6705cb8120
commit
a7399233eb
28 changed files with 260 additions and 145 deletions
55
Mapping.c
55
Mapping.c
|
|
@ -7,34 +7,53 @@
|
|||
#include "cs_priv.h"
|
||||
#include "utils.h"
|
||||
|
||||
// create a cache for fast id lookup
|
||||
static unsigned short *make_id2insn(const insn_map *insns, unsigned int size)
|
||||
// Create a cache to map LLVM instruction IDs to capstone instruction IDs, if
|
||||
// the architecture needs this.
|
||||
cs_err populate_insn_map_cache(cs_struct *handle)
|
||||
{
|
||||
// NOTE: assume that the max id is always put at the end of insns array
|
||||
unsigned short max_id = insns[size - 1].id;
|
||||
unsigned int i;
|
||||
|
||||
unsigned short *cache =
|
||||
(unsigned short *)cs_mem_calloc(max_id + 1, sizeof(*cache));
|
||||
// If this architecture doesn't use instruction mapping, do nothing
|
||||
if (!handle->insn_map || handle->insn_map_size <= 0)
|
||||
return CS_ERR_OK;
|
||||
|
||||
for (i = 1; i < size; i++)
|
||||
cache[insns[i].id] = i;
|
||||
// Since the instruction map is assumed to be stored in ascending
|
||||
// order, we can get the maximum LLVM instruction id just by looking at
|
||||
// the last element.
|
||||
unsigned int cache_elements =
|
||||
handle->insn_map[handle->insn_map_size - 1].id + 1;
|
||||
|
||||
return cache;
|
||||
// This should not be initialized yet.
|
||||
CS_ASSERT(!handle->insn_cache);
|
||||
|
||||
unsigned short *cache = cs_mem_calloc(cache_elements, sizeof(*cache));
|
||||
if (!cache) {
|
||||
handle->errnum = CS_ERR_MEM;
|
||||
return CS_ERR_MEM;
|
||||
}
|
||||
handle->insn_cache = cache;
|
||||
|
||||
for (i = 1; i < handle->insn_map_size; ++i)
|
||||
handle->insn_cache[handle->insn_map[i].id] = i;
|
||||
|
||||
return CS_ERR_OK;
|
||||
}
|
||||
|
||||
// look for @id in @insns, given its size in @max. first time call will update
|
||||
// @cache. return 0 if not found
|
||||
unsigned short insn_find(const insn_map *insns, unsigned int max,
|
||||
unsigned int id, unsigned short **cache)
|
||||
const insn_map *lookup_insn_map(cs_struct *handle, unsigned short id)
|
||||
{
|
||||
if (id > insns[max - 1].id)
|
||||
return 0;
|
||||
// If this is getting called, we need the cache to already be populated
|
||||
// (this should be done when populate_insn_map_cache() gets called).
|
||||
CS_ASSERT(handle->insn_cache);
|
||||
CS_ASSERT(handle->insn_map_size);
|
||||
|
||||
if (*cache == NULL)
|
||||
*cache = make_id2insn(insns, max);
|
||||
unsigned short highest_id =
|
||||
handle->insn_map[handle->insn_map_size - 1].id;
|
||||
if (id > highest_id)
|
||||
return NULL;
|
||||
|
||||
return (*cache)[id];
|
||||
unsigned short i = handle->insn_cache[id];
|
||||
|
||||
return &handle->insn_map[i];
|
||||
}
|
||||
|
||||
// Gives the id for the given @name if it is saved in @map.
|
||||
|
|
|
|||
37
Mapping.h
37
Mapping.h
|
|
@ -15,35 +15,16 @@
|
|||
#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;
|
||||
// Create a cache to map LLVM instruction IDs to capstone instruction IDs, if
|
||||
// the architecture needs this.
|
||||
cs_err populate_insn_map_cache(cs_struct *handle);
|
||||
|
||||
// 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);
|
||||
// Lookup the insn_map instance for an LLVM instruction ID. This method assumes
|
||||
// that this architecture uses the instruction mapping functionality available
|
||||
// from populate_insn_map_cache().
|
||||
// Returns NULL in case id is larger than the maximum mapped LLVM instruction
|
||||
// ID.
|
||||
const insn_map *lookup_insn_map(cs_struct *handle, unsigned short id);
|
||||
|
||||
unsigned int find_cs_id(unsigned MC_Opcode, const insn_map *imap,
|
||||
unsigned imap_size);
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@ cs_err AArch64_global_init(cs_struct *ud)
|
|||
{
|
||||
MCRegisterInfo *mri;
|
||||
mri = cs_mem_malloc(sizeof(*mri));
|
||||
if (!mri)
|
||||
return CS_ERR_MEM;
|
||||
|
||||
AArch64_init_mri(mri);
|
||||
ud->printer = AArch64_printer;
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@ cs_err ARC_global_init(cs_struct *ud)
|
|||
{
|
||||
MCRegisterInfo *mri;
|
||||
mri = cs_mem_malloc(sizeof(*mri));
|
||||
if (!mri)
|
||||
return CS_ERR_MEM;
|
||||
|
||||
ARC_init_mri(mri);
|
||||
|
||||
|
|
@ -49,4 +51,4 @@ cs_err ARC_option(cs_struct *handle, cs_opt_type type, size_t value)
|
|||
return CS_ERR_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@ cs_err ARM_global_init(cs_struct *ud)
|
|||
{
|
||||
MCRegisterInfo *mri;
|
||||
mri = cs_mem_malloc(sizeof(*mri));
|
||||
if (!mri)
|
||||
return CS_ERR_MEM;
|
||||
|
||||
ARM_init_mri(mri);
|
||||
|
||||
|
|
|
|||
|
|
@ -23,6 +23,9 @@ static const insn_map insns[] = {
|
|||
#include "AlphaGenCSMappingInsn.inc"
|
||||
};
|
||||
|
||||
const insn_map *Alpha_insns = insns;
|
||||
const unsigned int Alpha_insn_count = ARR_SIZE(insns);
|
||||
|
||||
static const map_insn_ops insn_operands[] = {
|
||||
#include "AlphaGenCSMappingInsnOp.inc"
|
||||
};
|
||||
|
|
@ -81,30 +84,28 @@ void Alpha_set_detail_op_reg(MCInst *MI, unsigned OpNum, alpha_op_type Reg)
|
|||
// given internal insn id, return public instruction info
|
||||
void Alpha_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id)
|
||||
{
|
||||
unsigned short i;
|
||||
insn_map const *insn_map = NULL;
|
||||
|
||||
i = insn_find(insns, ARR_SIZE(insns), id, &h->insn_cache);
|
||||
if (i == 0) {
|
||||
if (!(insn_map = lookup_insn_map(h, id)))
|
||||
return;
|
||||
}
|
||||
insn->id = insns[i].mapid;
|
||||
insn->id = insn_map->mapid;
|
||||
|
||||
if (insn->detail) {
|
||||
#ifndef CAPSTONE_DIET
|
||||
memcpy(insn->detail->regs_read, insns[i].regs_use,
|
||||
sizeof(insns[i].regs_use));
|
||||
memcpy(insn->detail->regs_read, insn_map->regs_use,
|
||||
sizeof(insn_map->regs_use));
|
||||
insn->detail->regs_read_count =
|
||||
(uint8_t)count_positive(insns[i].regs_use);
|
||||
(uint8_t)count_positive(insn_map->regs_use);
|
||||
|
||||
memcpy(insn->detail->regs_write, insns[i].regs_mod,
|
||||
sizeof(insns[i].regs_mod));
|
||||
memcpy(insn->detail->regs_write, insn_map->regs_mod,
|
||||
sizeof(insn_map->regs_mod));
|
||||
insn->detail->regs_write_count =
|
||||
(uint8_t)count_positive(insns[i].regs_mod);
|
||||
(uint8_t)count_positive(insn_map->regs_mod);
|
||||
|
||||
memcpy(insn->detail->groups, insns[i].groups,
|
||||
sizeof(insns[i].groups));
|
||||
memcpy(insn->detail->groups, insn_map->groups,
|
||||
sizeof(insn_map->groups));
|
||||
insn->detail->groups_count =
|
||||
(uint8_t)count_positive8(insns[i].groups);
|
||||
(uint8_t)count_positive8(insn_map->groups);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,9 @@
|
|||
|
||||
// unsigned int Alpha_map_insn_id(cs_struct *h, unsigned int id);
|
||||
|
||||
extern const insn_map *Alpha_insns;
|
||||
extern const unsigned int Alpha_insn_count;
|
||||
|
||||
// given internal insn id, return public instruction info
|
||||
void Alpha_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id);
|
||||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@ cs_err ALPHA_global_init(cs_struct *ud)
|
|||
MCRegisterInfo *mri;
|
||||
|
||||
mri = cs_mem_malloc(sizeof(*mri));
|
||||
if (!mri)
|
||||
return CS_ERR_MEM;
|
||||
|
||||
Alpha_init(mri);
|
||||
ud->printer = Alpha_printInst;
|
||||
|
|
@ -29,6 +31,8 @@ cs_err ALPHA_global_init(cs_struct *ud)
|
|||
#ifndef CAPSTONE_DIET
|
||||
ud->reg_access = Alpha_reg_access;
|
||||
#endif
|
||||
ud->insn_map = Alpha_insns;
|
||||
ud->insn_map_size = Alpha_insn_count;
|
||||
|
||||
return CS_ERR_OK;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@ cs_err LoongArch_global_init(cs_struct *ud)
|
|||
{
|
||||
MCRegisterInfo *mri;
|
||||
mri = cs_mem_malloc(sizeof(*mri));
|
||||
if (!mri)
|
||||
return CS_ERR_MEM;
|
||||
|
||||
LoongArch_init_mri(mri);
|
||||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,9 @@ cs_err MOS65XX_global_init(cs_struct *ud)
|
|||
mos65xx_info *info;
|
||||
|
||||
info = cs_mem_malloc(sizeof(*info));
|
||||
if (!info)
|
||||
return CS_ERR_MEM;
|
||||
|
||||
info->hex_prefix = NULL;
|
||||
info->cpu_type = MOS65XX_CPU_TYPE_6502;
|
||||
info->long_m = 0;
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@ cs_err Mips_global_init(cs_struct *ud)
|
|||
{
|
||||
MCRegisterInfo *mri;
|
||||
mri = cs_mem_malloc(sizeof(*mri));
|
||||
if (!mri)
|
||||
return CS_ERR_MEM;
|
||||
|
||||
Mips_init_mri(mri);
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ cs_err PPC_global_init(cs_struct *ud)
|
|||
{
|
||||
MCRegisterInfo *mri;
|
||||
mri = (MCRegisterInfo *)cs_mem_malloc(sizeof(*mri));
|
||||
if (!mri)
|
||||
return CS_ERR_MEM;
|
||||
|
||||
PPC_init_mri(mri);
|
||||
ud->printer = PPC_printer;
|
||||
|
|
|
|||
|
|
@ -36,6 +36,9 @@ static const insn_map insns[] = {
|
|||
#include "RISCVGenCSMappingInsn.inc"
|
||||
};
|
||||
|
||||
const insn_map *RISCV_insns = insns;
|
||||
const unsigned int RISCV_insn_count = ARR_SIZE(insns);
|
||||
|
||||
#ifndef CAPSTONE_DIET
|
||||
|
||||
static const map_insn_ops insn_operands[] = {
|
||||
|
|
@ -310,30 +313,29 @@ void RISCV_add_missing_write_access(MCInst *MI)
|
|||
// given internal insn id, return public instruction info
|
||||
void RISCV_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id)
|
||||
{
|
||||
unsigned int i;
|
||||
insn_map const *insn_map = NULL;
|
||||
|
||||
i = insn_find(insns, ARR_SIZE(insns), id, &h->insn_cache);
|
||||
if (i != 0) {
|
||||
insn->id = insns[i].mapid;
|
||||
if ((insn_map = lookup_insn_map(h, id))) {
|
||||
insn->id = insn_map->mapid;
|
||||
|
||||
if (h->detail_opt) {
|
||||
#ifndef CAPSTONE_DIET
|
||||
memcpy(insn->detail->regs_read, insns[i].regs_use,
|
||||
sizeof(insns[i].regs_use));
|
||||
memcpy(insn->detail->regs_read, insn_map->regs_use,
|
||||
sizeof(insn_map->regs_use));
|
||||
insn->detail->regs_read_count =
|
||||
(uint8_t)count_positive(insns[i].regs_use);
|
||||
(uint8_t)count_positive(insn_map->regs_use);
|
||||
|
||||
memcpy(insn->detail->regs_write, insns[i].regs_mod,
|
||||
sizeof(insns[i].regs_mod));
|
||||
memcpy(insn->detail->regs_write, insn_map->regs_mod,
|
||||
sizeof(insn_map->regs_mod));
|
||||
insn->detail->regs_write_count =
|
||||
(uint8_t)count_positive(insns[i].regs_mod);
|
||||
(uint8_t)count_positive(insn_map->regs_mod);
|
||||
|
||||
memcpy(insn->detail->groups, insns[i].groups,
|
||||
sizeof(insns[i].groups));
|
||||
memcpy(insn->detail->groups, insn_map->groups,
|
||||
sizeof(insn_map->groups));
|
||||
insn->detail->groups_count =
|
||||
(uint8_t)count_positive8(insns[i].groups);
|
||||
(uint8_t)count_positive8(insn_map->groups);
|
||||
|
||||
if (insns[i].branch || insns[i].indirect_branch) {
|
||||
if (insn_map->branch || insn_map->indirect_branch) {
|
||||
// this insn also belongs to JUMP group. add JUMP group
|
||||
insn->detail
|
||||
->groups[insn->detail->groups_count] =
|
||||
|
|
|
|||
|
|
@ -9,6 +9,9 @@ typedef enum {
|
|||
#include "RISCVGenCSOpGroup.inc"
|
||||
} riscv_op_group;
|
||||
|
||||
extern const insn_map *RISCV_insns;
|
||||
extern const unsigned int RISCV_insn_count;
|
||||
|
||||
// given internal insn id, return public instruction info
|
||||
void RISCV_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id);
|
||||
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@ cs_err RISCV_global_init(cs_struct *ud)
|
|||
{
|
||||
MCRegisterInfo *mri;
|
||||
mri = cs_mem_malloc(sizeof(*mri));
|
||||
if (!mri)
|
||||
return CS_ERR_MEM;
|
||||
|
||||
RISCV_init(mri);
|
||||
ud->printer = RISCV_LLVM_printInstruction;
|
||||
|
|
@ -27,6 +29,8 @@ cs_err RISCV_global_init(cs_struct *ud)
|
|||
ud->insn_id = RISCV_get_insn_id;
|
||||
ud->insn_name = RISCV_insn_name;
|
||||
ud->group_name = RISCV_group_name;
|
||||
ud->insn_map = RISCV_insns;
|
||||
ud->insn_map_size = RISCV_insn_count;
|
||||
|
||||
return CS_ERR_OK;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ cs_err Sparc_global_init(cs_struct *ud)
|
|||
{
|
||||
MCRegisterInfo *mri;
|
||||
mri = cs_mem_malloc(sizeof(*mri));
|
||||
if (!mri)
|
||||
return CS_ERR_MEM;
|
||||
|
||||
Sparc_init_mri(mri);
|
||||
ud->printer = Sparc_printer;
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ cs_err SystemZ_global_init(cs_struct *ud)
|
|||
{
|
||||
MCRegisterInfo *mri;
|
||||
mri = cs_mem_malloc(sizeof(*mri));
|
||||
if (!mri)
|
||||
return CS_ERR_MEM;
|
||||
|
||||
SystemZ_init_mri(mri);
|
||||
ud->printer = SystemZ_printer;
|
||||
|
|
|
|||
|
|
@ -2682,32 +2682,34 @@ static const insn_map insns[] = {
|
|||
},
|
||||
};
|
||||
|
||||
const insn_map *TMS320C64x_insns = insns;
|
||||
const unsigned int TMS320C64x_insn_count = ARR_SIZE(insns);
|
||||
|
||||
void TMS320C64x_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id)
|
||||
{
|
||||
unsigned short i;
|
||||
insn_map const *insn_map = NULL;
|
||||
|
||||
i = insn_find(insns, ARR_SIZE(insns), id, &h->insn_cache);
|
||||
if (i != 0) {
|
||||
insn->id = insns[i].mapid;
|
||||
if ((insn_map = lookup_insn_map(h, id))) {
|
||||
insn->id = insn_map->mapid;
|
||||
|
||||
if (h->detail_opt) {
|
||||
#ifndef CAPSTONE_DIET
|
||||
memcpy(insn->detail->regs_read, insns[i].regs_use,
|
||||
sizeof(insns[i].regs_use));
|
||||
memcpy(insn->detail->regs_read, insn_map->regs_use,
|
||||
sizeof(insn_map->regs_use));
|
||||
insn->detail->regs_read_count =
|
||||
(uint8_t)count_positive(insns[i].regs_use);
|
||||
(uint8_t)count_positive(insn_map->regs_use);
|
||||
|
||||
memcpy(insn->detail->regs_write, insns[i].regs_mod,
|
||||
sizeof(insns[i].regs_mod));
|
||||
memcpy(insn->detail->regs_write, insn_map->regs_mod,
|
||||
sizeof(insn_map->regs_mod));
|
||||
insn->detail->regs_write_count =
|
||||
(uint8_t)count_positive(insns[i].regs_mod);
|
||||
(uint8_t)count_positive(insn_map->regs_mod);
|
||||
|
||||
memcpy(insn->detail->groups, insns[i].groups,
|
||||
sizeof(insns[i].groups));
|
||||
memcpy(insn->detail->groups, insn_map->groups,
|
||||
sizeof(insn_map->groups));
|
||||
insn->detail->groups_count =
|
||||
(uint8_t)count_positive8(insns[i].groups);
|
||||
(uint8_t)count_positive8(insn_map->groups);
|
||||
|
||||
if (insns[i].branch || insns[i].indirect_branch) {
|
||||
if (insn_map->branch || insn_map->indirect_branch) {
|
||||
insn->detail
|
||||
->groups[insn->detail->groups_count] =
|
||||
TMS320C64X_GRP_JUMP;
|
||||
|
|
|
|||
|
|
@ -6,6 +6,9 @@
|
|||
|
||||
#include "capstone/capstone.h"
|
||||
|
||||
extern const insn_map *TMS320C64x_insns;
|
||||
extern const unsigned int TMS320C64x_insn_count;
|
||||
|
||||
// return name of register in friendly string
|
||||
const char *TMS320C64x_reg_name(csh handle, unsigned int reg);
|
||||
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@ cs_err TMS320C64x_global_init(cs_struct *ud)
|
|||
MCRegisterInfo *mri;
|
||||
|
||||
mri = cs_mem_malloc(sizeof(*mri));
|
||||
if (!mri)
|
||||
return CS_ERR_MEM;
|
||||
|
||||
TMS320C64x_init(mri);
|
||||
ud->printer = TMS320C64x_printInst;
|
||||
|
|
@ -27,6 +29,8 @@ cs_err TMS320C64x_global_init(cs_struct *ud)
|
|||
ud->insn_id = TMS320C64x_get_insn_id;
|
||||
ud->insn_name = TMS320C64x_insn_name;
|
||||
ud->group_name = TMS320C64x_group_name;
|
||||
ud->insn_map = TMS320C64x_insns;
|
||||
ud->insn_map_size = TMS320C64x_insn_count;
|
||||
|
||||
return CS_ERR_OK;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,9 @@ cs_err TRICORE_global_init(cs_struct *ud)
|
|||
{
|
||||
MCRegisterInfo *mri;
|
||||
mri = cs_mem_calloc(sizeof(*mri), 1);
|
||||
if (!mri)
|
||||
return CS_ERR_MEM;
|
||||
|
||||
TriCore_init_mri(mri);
|
||||
ud->printer = TriCore_printInst;
|
||||
ud->printer_info = mri;
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@ cs_err X86_global_init(cs_struct *ud)
|
|||
{
|
||||
MCRegisterInfo *mri;
|
||||
mri = cs_mem_malloc(sizeof(*mri));
|
||||
if (!mri)
|
||||
return CS_ERR_MEM;
|
||||
|
||||
X86_init(mri);
|
||||
|
||||
|
|
|
|||
|
|
@ -88,33 +88,35 @@ static const insn_map insns[] = {
|
|||
#include "XCoreMappingInsn.inc"
|
||||
};
|
||||
|
||||
const insn_map *XCore_insns = insns;
|
||||
const unsigned int XCore_insn_count = ARR_SIZE(insns);
|
||||
|
||||
// given internal insn id, return public instruction info
|
||||
void XCore_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id)
|
||||
{
|
||||
unsigned short i;
|
||||
insn_map const *insn_map = NULL;
|
||||
|
||||
i = insn_find(insns, ARR_SIZE(insns), id, &h->insn_cache);
|
||||
if (i != 0) {
|
||||
insn->id = insns[i].mapid;
|
||||
if ((insn_map = lookup_insn_map(h, id))) {
|
||||
insn->id = insn_map->mapid;
|
||||
|
||||
if (h->detail_opt) {
|
||||
#ifndef CAPSTONE_DIET
|
||||
memcpy(insn->detail->regs_read, insns[i].regs_use,
|
||||
sizeof(insns[i].regs_use));
|
||||
memcpy(insn->detail->regs_read, insn_map->regs_use,
|
||||
sizeof(insn_map->regs_use));
|
||||
insn->detail->regs_read_count =
|
||||
(uint8_t)count_positive(insns[i].regs_use);
|
||||
(uint8_t)count_positive(insn_map->regs_use);
|
||||
|
||||
memcpy(insn->detail->regs_write, insns[i].regs_mod,
|
||||
sizeof(insns[i].regs_mod));
|
||||
memcpy(insn->detail->regs_write, insn_map->regs_mod,
|
||||
sizeof(insn_map->regs_mod));
|
||||
insn->detail->regs_write_count =
|
||||
(uint8_t)count_positive(insns[i].regs_mod);
|
||||
(uint8_t)count_positive(insn_map->regs_mod);
|
||||
|
||||
memcpy(insn->detail->groups, insns[i].groups,
|
||||
sizeof(insns[i].groups));
|
||||
memcpy(insn->detail->groups, insn_map->groups,
|
||||
sizeof(insn_map->groups));
|
||||
insn->detail->groups_count =
|
||||
(uint8_t)count_positive8(insns[i].groups);
|
||||
(uint8_t)count_positive8(insn_map->groups);
|
||||
|
||||
if (insns[i].branch || insns[i].indirect_branch) {
|
||||
if (insn_map->branch || insn_map->indirect_branch) {
|
||||
// this insn also belongs to JUMP group. add JUMP group
|
||||
insn->detail
|
||||
->groups[insn->detail->groups_count] =
|
||||
|
|
|
|||
|
|
@ -6,6 +6,9 @@
|
|||
|
||||
#include "capstone/capstone.h"
|
||||
|
||||
extern const insn_map *XCore_insns;
|
||||
extern const unsigned int XCore_insn_count;
|
||||
|
||||
// return name of register in friendly string
|
||||
const char *XCore_reg_name(csh handle, unsigned int reg);
|
||||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@ cs_err XCore_global_init(cs_struct *ud)
|
|||
{
|
||||
MCRegisterInfo *mri;
|
||||
mri = cs_mem_malloc(sizeof(*mri));
|
||||
if (!mri)
|
||||
return CS_ERR_MEM;
|
||||
|
||||
XCore_init(mri);
|
||||
ud->printer = XCore_printInst;
|
||||
|
|
@ -26,6 +28,8 @@ cs_err XCore_global_init(cs_struct *ud)
|
|||
ud->insn_id = XCore_get_insn_id;
|
||||
ud->insn_name = XCore_insn_name;
|
||||
ud->group_name = XCore_group_name;
|
||||
ud->insn_map = XCore_insns;
|
||||
ud->insn_map_size = XCore_insn_count;
|
||||
|
||||
return CS_ERR_OK;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@ cs_err Xtensa_global_init(cs_struct *ud)
|
|||
{
|
||||
MCRegisterInfo *mri;
|
||||
mri = cs_mem_calloc(1, sizeof(*mri));
|
||||
if (!mri)
|
||||
return CS_ERR_MEM;
|
||||
|
||||
Xtensa_init_mri(mri);
|
||||
ud->printer = Xtensa_printer;
|
||||
|
|
@ -44,4 +46,4 @@ cs_err Xtensa_option(cs_struct *handle, cs_opt_type type, size_t value)
|
|||
}
|
||||
|
||||
return CS_ERR_OK;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
105
cs.c
105
cs.c
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#include "utils.h"
|
||||
#include "MCRegisterInfo.h"
|
||||
#include "Mapping.h"
|
||||
|
||||
#if defined(_KERNEL_MODE)
|
||||
#include "windows\winkernel_mm.h"
|
||||
|
|
@ -779,52 +780,59 @@ const char *CAPSTONE_API cs_strerror(cs_err code)
|
|||
CAPSTONE_EXPORT
|
||||
cs_err CAPSTONE_API cs_open(cs_arch arch, cs_mode mode, csh *handle)
|
||||
{
|
||||
cs_err err;
|
||||
cs_err err = CS_ERR_ARCH;
|
||||
struct cs_struct *ud = NULL;
|
||||
|
||||
if (!cs_mem_malloc || !cs_mem_calloc || !cs_mem_realloc ||
|
||||
!cs_mem_free || !cs_vsnprintf)
|
||||
!cs_mem_free || !cs_vsnprintf) {
|
||||
// Error: before cs_open(), dynamic memory management must be initialized
|
||||
// with cs_option(CS_OPT_MEM)
|
||||
return CS_ERR_MEMSETUP;
|
||||
|
||||
if (arch < CS_ARCH_MAX && arch_configs[arch].arch_init) {
|
||||
// verify if requested mode is valid
|
||||
if (mode & arch_configs[arch].arch_disallowed_mode_mask) {
|
||||
*handle = 0;
|
||||
return CS_ERR_MODE;
|
||||
}
|
||||
|
||||
ud = cs_mem_calloc(1, sizeof(*ud));
|
||||
if (!ud) {
|
||||
// memory insufficient
|
||||
return CS_ERR_MEM;
|
||||
}
|
||||
|
||||
ud->errnum = CS_ERR_OK;
|
||||
ud->arch = arch;
|
||||
ud->mode = mode;
|
||||
// by default, do not break instruction into details
|
||||
ud->detail_opt = CS_OPT_OFF;
|
||||
ud->PrintBranchImmAsAddress = true;
|
||||
|
||||
// default skipdata setup
|
||||
ud->skipdata_setup.mnemonic = SKIPDATA_MNEM;
|
||||
|
||||
err = arch_configs[ud->arch].arch_init(ud);
|
||||
if (err) {
|
||||
cs_mem_free(ud);
|
||||
*handle = 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
*handle = (uintptr_t)ud;
|
||||
|
||||
return CS_ERR_OK;
|
||||
} else {
|
||||
cs_mem_free(ud);
|
||||
*handle = 0;
|
||||
return CS_ERR_ARCH;
|
||||
err = CS_ERR_MEMSETUP;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (arch >= CS_ARCH_MAX || !arch_configs[arch].arch_init) {
|
||||
err = CS_ERR_ARCH;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
// verify if requested mode is valid
|
||||
if (mode & arch_configs[arch].arch_disallowed_mode_mask) {
|
||||
err = CS_ERR_MODE;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ud = cs_mem_calloc(1, sizeof(*ud));
|
||||
if (!ud) {
|
||||
err = CS_ERR_MEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ud->errnum = CS_ERR_OK;
|
||||
ud->arch = arch;
|
||||
ud->mode = mode;
|
||||
// by default, do not break instruction into details
|
||||
ud->detail_opt = CS_OPT_OFF;
|
||||
ud->PrintBranchImmAsAddress = true;
|
||||
|
||||
// default skipdata setup
|
||||
ud->skipdata_setup.mnemonic = SKIPDATA_MNEM;
|
||||
|
||||
if ((err = arch_configs[ud->arch].arch_init(ud)))
|
||||
goto fail;
|
||||
|
||||
if ((err = populate_insn_map_cache(ud)))
|
||||
goto fail;
|
||||
|
||||
*handle = (uintptr_t)ud;
|
||||
return CS_ERR_OK;
|
||||
|
||||
fail:
|
||||
if (ud) {
|
||||
cs_mem_free(ud);
|
||||
}
|
||||
*handle = 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
CAPSTONE_EXPORT
|
||||
|
|
@ -1113,6 +1121,10 @@ cs_err CAPSTONE_API cs_option(csh ud, cs_opt_type type, uintptr_t value)
|
|||
// 2. add this instruction if we have not had it yet
|
||||
if (!tmp) {
|
||||
tmp = cs_mem_malloc(sizeof(*tmp));
|
||||
if (!tmp) {
|
||||
return CS_ERR_MEM;
|
||||
}
|
||||
|
||||
tmp->insn.id = opt->id;
|
||||
(void)strncpy(
|
||||
tmp->insn.mnemonic,
|
||||
|
|
@ -1268,6 +1280,17 @@ size_t CAPSTONE_API cs_disasm(csh ud, const uint8_t *buffer, size_t size,
|
|||
// allocate memory for @detail pointer
|
||||
insn_cache->detail =
|
||||
cs_mem_calloc(1, sizeof(cs_detail));
|
||||
if (!insn_cache->detail) {
|
||||
insn_cache = (cs_insn *)total;
|
||||
for (i = 0; i < c; i++, insn_cache++)
|
||||
cs_mem_free(insn_cache->detail);
|
||||
|
||||
cs_mem_free(total);
|
||||
*insn = NULL;
|
||||
|
||||
handle->errnum = CS_ERR_MEM;
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
insn_cache->detail = NULL;
|
||||
}
|
||||
|
|
|
|||
31
cs_priv.h
31
cs_priv.h
|
|
@ -57,6 +57,31 @@ struct insn_mnem {
|
|||
struct insn_mnem *next; // linked list of customized mnemonics
|
||||
};
|
||||
|
||||
// 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;
|
||||
|
||||
struct cs_struct {
|
||||
cs_arch arch;
|
||||
cs_mode mode;
|
||||
|
|
@ -79,6 +104,12 @@ struct cs_struct {
|
|||
bool doing_mem; // handling memory operand in InstPrinter code
|
||||
bool doing_SME_Index; // handling a SME instruction that has index
|
||||
unsigned short *insn_cache; // index caching for mapping.c
|
||||
// A mapping of LLVM instruction IDs to capstone instruction IDs, with
|
||||
// some supplementary information, sorted in ascending order by LLVM
|
||||
// instruction ID.
|
||||
const insn_map *insn_map;
|
||||
// The number of elements in the array pointed to by .insn_map
|
||||
unsigned short insn_map_size;
|
||||
bool skipdata; // set this to True if we skip data when disassembling
|
||||
uint8_t skipdata_size; // how many bytes to skip
|
||||
cs_opt_skipdata skipdata_setup; // user-defined skipdata setup
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue