Skip to content
Open
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
54 changes: 36 additions & 18 deletions Mapping.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,34 +7,52 @@
#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 < cache_elements; ++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)
insn_map const *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);

unsigned short highest_id =
handle->insn_map[handle->insn_map_size - 1].id;
if (id > highest_id)
return NULL;

if (*cache == NULL)
*cache = make_id2insn(insns, max);
unsigned short i = handle->insn_cache[id];

return (*cache)[id];
return &handle->insn_map[i];
}

// Gives the id for the given @name if it is saved in @map.
Expand Down
37 changes: 8 additions & 29 deletions Mapping.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,35 +15,14 @@
#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);
// 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);

// 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().
insn_map const *lookup_insn_map(cs_struct *handle, unsigned short id);

unsigned int find_cs_id(unsigned MC_Opcode, const insn_map *imap,
unsigned imap_size);
Expand Down
2 changes: 2 additions & 0 deletions arch/AArch64/AArch64Module.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
4 changes: 3 additions & 1 deletion arch/ARC/ARCModule.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -49,4 +51,4 @@ cs_err ARC_option(cs_struct *handle, cs_opt_type type, size_t value)
return CS_ERR_OK;
}

#endif
#endif
2 changes: 2 additions & 0 deletions arch/ARM/ARMModule.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
29 changes: 15 additions & 14 deletions arch/Alpha/AlphaMapping.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
};
Expand Down Expand Up @@ -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
}
}
Expand Down
3 changes: 3 additions & 0 deletions arch/Alpha/AlphaMapping.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
4 changes: 4 additions & 0 deletions arch/Alpha/AlphaModule.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
}
Expand Down
2 changes: 2 additions & 0 deletions arch/LoongArch/LoongArchModule.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
3 changes: 3 additions & 0 deletions arch/MOS65XX/MOS65XXModule.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 2 additions & 0 deletions arch/Mips/MipsModule.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
2 changes: 2 additions & 0 deletions arch/PowerPC/PPCModule.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
30 changes: 16 additions & 14 deletions arch/RISCV/RISCVMapping.c
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,9 @@ static const insn_map insns[] = {
#include "RISCVMappingInsn.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[] = {
Expand Down Expand Up @@ -132,30 +135,29 @@ void RISCV_add_cs_detail(MCInst *MI, unsigned OpNum)
// 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] =
Expand Down
3 changes: 3 additions & 0 deletions arch/RISCV/RISCVMapping.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@

#include "../../include/capstone/capstone.h"

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);

Expand Down
4 changes: 4 additions & 0 deletions arch/RISCV/RISCVModule.c
Original file line number Diff line number Diff line change
Expand Up @@ -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_printInst;
Expand All @@ -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;
}
Expand Down
2 changes: 2 additions & 0 deletions arch/Sparc/SparcModule.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 2 additions & 0 deletions arch/SystemZ/SystemZModule.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Loading
Loading