Skip to content

Commit bc5f6b2

Browse files
author
Samuel Arnold
committed
Move instruction lookup caching allocation into the core
1 parent c7ac627 commit bc5f6b2

File tree

16 files changed

+206
-139
lines changed

16 files changed

+206
-139
lines changed

Mapping.c

Lines changed: 36 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,34 +7,52 @@
77
#include "cs_priv.h"
88
#include "utils.h"
99

10-
// create a cache for fast id lookup
11-
static unsigned short *make_id2insn(const insn_map *insns, unsigned int size)
10+
// Create a cache to map LLVM instruction IDs to capstone instruction IDs, if
11+
// the architecture needs this.
12+
cs_err populate_insn_map_cache(cs_struct *handle)
1213
{
13-
// NOTE: assume that the max id is always put at the end of insns array
14-
unsigned short max_id = insns[size - 1].id;
1514
unsigned int i;
1615

17-
unsigned short *cache =
18-
(unsigned short *)cs_mem_calloc(max_id + 1, sizeof(*cache));
16+
// If this architecture doesn't use instruction mapping, do nothing
17+
if (!handle->insn_map || handle->insn_map_size <= 0)
18+
return CS_ERR_OK;
1919

20-
for (i = 1; i < size; i++)
21-
cache[insns[i].id] = i;
20+
// Since the instruction map is assumed to be stored in ascending
21+
// order, we can get the maximum LLVM instruction id just by looking at
22+
// the last element.
23+
unsigned int cache_elements =
24+
handle->insn_map[handle->insn_map_size - 1].id + 1;
2225

23-
return cache;
26+
// This should not be initialized yet.
27+
CS_ASSERT(!handle->insn_cache);
28+
29+
unsigned short *cache = cs_mem_calloc(cache_elements, sizeof(*cache));
30+
if (!cache) {
31+
handle->errnum = CS_ERR_MEM;
32+
return CS_ERR_MEM;
33+
}
34+
handle->insn_cache = cache;
35+
36+
for (i = 1; i < cache_elements; ++i)
37+
handle->insn_cache[handle->insn_map[i].id] = i;
38+
39+
return CS_ERR_OK;
2440
}
2541

26-
// look for @id in @insns, given its size in @max. first time call will update
27-
// @cache. return 0 if not found
28-
unsigned short insn_find(const insn_map *insns, unsigned int max,
29-
unsigned int id, unsigned short **cache)
42+
insn_map const *lookup_insn_map(cs_struct *handle, unsigned short id)
3043
{
31-
if (id > insns[max - 1].id)
32-
return 0;
44+
// If this is getting called, we need the cache to already be populated
45+
// (this should be done when populate_insn_map_cache() gets called).
46+
CS_ASSERT(handle->insn_cache);
47+
48+
unsigned short highest_id =
49+
handle->insn_map[handle->insn_map_size - 1].id;
50+
if (id > highest_id)
51+
return NULL;
3352

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

37-
return (*cache)[id];
55+
return &handle->insn_map[i];
3856
}
3957

4058
// Gives the id for the given @name if it is saved in @map.

Mapping.h

Lines changed: 8 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -15,35 +15,14 @@
1515
#include <assert.h>
1616
#include <string.h>
1717

18-
// map instruction to its characteristics
19-
typedef struct insn_map {
20-
unsigned short id; // The LLVM instruction id
21-
unsigned short mapid; // The Capstone instruction id
22-
#ifndef CAPSTONE_DIET
23-
uint16_t regs_use[MAX_IMPL_R_REGS]; ///< list of implicit registers used by
24-
///< this instruction
25-
uint16_t regs_mod[MAX_IMPL_W_REGS]; ///< list of implicit registers modified
26-
///< by this instruction
27-
unsigned char groups
28-
[MAX_NUM_GROUPS]; ///< list of group this instruction belong to
29-
bool branch; // branch instruction?
30-
bool indirect_branch; // indirect branch instruction?
31-
union {
32-
ppc_suppl_info ppc;
33-
loongarch_suppl_info loongarch;
34-
aarch64_suppl_info aarch64;
35-
systemz_suppl_info systemz;
36-
arm_suppl_info arm;
37-
xtensa_suppl_info xtensa;
38-
sparc_suppl_info sparc;
39-
} suppl_info; // Supplementary information for each instruction.
40-
#endif
41-
} insn_map;
42-
43-
// look for @id in @m, given its size in @max. first time call will update
44-
// @cache. return 0 if not found
45-
unsigned short insn_find(const insn_map *m, unsigned int max, unsigned int id,
46-
unsigned short **cache);
18+
// Create a cache to map LLVM instruction IDs to capstone instruction IDs, if
19+
// the architecture needs this.
20+
cs_err populate_insn_map_cache(cs_struct *handle);
21+
22+
// Lookup the insn_map instance for an LLVM instruction ID. This method assumes
23+
// that this architecture uses the instruction mapping functionality available
24+
// from populate_insn_map_cache().
25+
insn_map const *lookup_insn_map(cs_struct *handle, unsigned short id);
4726

4827
unsigned int find_cs_id(unsigned MC_Opcode, const insn_map *imap,
4928
unsigned imap_size);

arch/Alpha/AlphaMapping.c

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ static const insn_map insns[] = {
2323
#include "AlphaGenCSMappingInsn.inc"
2424
};
2525

26+
const insn_map *Alpha_insns = insns;
27+
const unsigned int Alpha_insn_count = ARR_SIZE(insns);
28+
2629
static const map_insn_ops insn_operands[] = {
2730
#include "AlphaGenCSMappingInsnOp.inc"
2831
};
@@ -81,30 +84,28 @@ void Alpha_set_detail_op_reg(MCInst *MI, unsigned OpNum, alpha_op_type Reg)
8184
// given internal insn id, return public instruction info
8285
void Alpha_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id)
8386
{
84-
unsigned short i;
87+
insn_map const *insn_map = NULL;
8588

86-
i = insn_find(insns, ARR_SIZE(insns), id, &h->insn_cache);
87-
if (i == 0) {
89+
if (!(insn_map = lookup_insn_map(h, id)))
8890
return;
89-
}
90-
insn->id = insns[i].mapid;
91+
insn->id = insn_map->mapid;
9192

9293
if (insn->detail) {
9394
#ifndef CAPSTONE_DIET
94-
memcpy(insn->detail->regs_read, insns[i].regs_use,
95-
sizeof(insns[i].regs_use));
95+
memcpy(insn->detail->regs_read, insn_map->regs_use,
96+
sizeof(insn_map->regs_use));
9697
insn->detail->regs_read_count =
97-
(uint8_t)count_positive(insns[i].regs_use);
98+
(uint8_t)count_positive(insn_map->regs_use);
9899

99-
memcpy(insn->detail->regs_write, insns[i].regs_mod,
100-
sizeof(insns[i].regs_mod));
100+
memcpy(insn->detail->regs_write, insn_map->regs_mod,
101+
sizeof(insn_map->regs_mod));
101102
insn->detail->regs_write_count =
102-
(uint8_t)count_positive(insns[i].regs_mod);
103+
(uint8_t)count_positive(insn_map->regs_mod);
103104

104-
memcpy(insn->detail->groups, insns[i].groups,
105-
sizeof(insns[i].groups));
105+
memcpy(insn->detail->groups, insn_map->groups,
106+
sizeof(insn_map->groups));
106107
insn->detail->groups_count =
107-
(uint8_t)count_positive8(insns[i].groups);
108+
(uint8_t)count_positive8(insn_map->groups);
108109
#endif
109110
}
110111
}

arch/Alpha/AlphaMapping.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111

1212
// unsigned int Alpha_map_insn_id(cs_struct *h, unsigned int id);
1313

14+
extern const insn_map *Alpha_insns;
15+
extern const unsigned int Alpha_insn_count;
16+
1417
// given internal insn id, return public instruction info
1518
void Alpha_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id);
1619

arch/Alpha/AlphaModule.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ cs_err ALPHA_global_init(cs_struct *ud)
3131
#ifndef CAPSTONE_DIET
3232
ud->reg_access = Alpha_reg_access;
3333
#endif
34+
ud->insn_map = Alpha_insns;
35+
ud->insn_map_size = Alpha_insn_count;
3436

3537
return CS_ERR_OK;
3638
}

arch/RISCV/RISCVMapping.c

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,9 @@ static const insn_map insns[] = {
9797
#include "RISCVMappingInsn.inc"
9898
};
9999

100+
const insn_map *RISCV_insns = insns;
101+
const unsigned int RISCV_insn_count = ARR_SIZE(insns);
102+
100103
#ifndef CAPSTONE_DIET
101104

102105
static const map_insn_ops insn_operands[] = {
@@ -132,30 +135,29 @@ void RISCV_add_cs_detail(MCInst *MI, unsigned OpNum)
132135
// given internal insn id, return public instruction info
133136
void RISCV_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id)
134137
{
135-
unsigned int i;
138+
insn_map const *insn_map = NULL;
136139

137-
i = insn_find(insns, ARR_SIZE(insns), id, &h->insn_cache);
138-
if (i != 0) {
139-
insn->id = insns[i].mapid;
140+
if ((insn_map = lookup_insn_map(h, id))) {
141+
insn->id = insn_map->mapid;
140142

141143
if (h->detail_opt) {
142144
#ifndef CAPSTONE_DIET
143-
memcpy(insn->detail->regs_read, insns[i].regs_use,
144-
sizeof(insns[i].regs_use));
145+
memcpy(insn->detail->regs_read, insn_map->regs_use,
146+
sizeof(insn_map->regs_use));
145147
insn->detail->regs_read_count =
146-
(uint8_t)count_positive(insns[i].regs_use);
148+
(uint8_t)count_positive(insn_map->regs_use);
147149

148-
memcpy(insn->detail->regs_write, insns[i].regs_mod,
149-
sizeof(insns[i].regs_mod));
150+
memcpy(insn->detail->regs_write, insn_map->regs_mod,
151+
sizeof(insn_map->regs_mod));
150152
insn->detail->regs_write_count =
151-
(uint8_t)count_positive(insns[i].regs_mod);
153+
(uint8_t)count_positive(insn_map->regs_mod);
152154

153-
memcpy(insn->detail->groups, insns[i].groups,
154-
sizeof(insns[i].groups));
155+
memcpy(insn->detail->groups, insn_map->groups,
156+
sizeof(insn_map->groups));
155157
insn->detail->groups_count =
156-
(uint8_t)count_positive8(insns[i].groups);
158+
(uint8_t)count_positive8(insn_map->groups);
157159

158-
if (insns[i].branch || insns[i].indirect_branch) {
160+
if (insn_map->branch || insn_map->indirect_branch) {
159161
// this insn also belongs to JUMP group. add JUMP group
160162
insn->detail
161163
->groups[insn->detail->groups_count] =

arch/RISCV/RISCVMapping.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44

55
#include "../../include/capstone/capstone.h"
66

7+
extern const insn_map *RISCV_insns;
8+
extern const unsigned int RISCV_insn_count;
9+
710
// given internal insn id, return public instruction info
811
void RISCV_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id);
912

arch/RISCV/RISCVModule.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ cs_err RISCV_global_init(cs_struct *ud)
2929
ud->insn_id = RISCV_get_insn_id;
3030
ud->insn_name = RISCV_insn_name;
3131
ud->group_name = RISCV_group_name;
32+
ud->insn_map = RISCV_insns;
33+
ud->insn_map_size = RISCV_insn_count;
3234

3335
return CS_ERR_OK;
3436
}

arch/TMS320C64x/TMS320C64xMapping.c

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2682,32 +2682,34 @@ static const insn_map insns[] = {
26822682
},
26832683
};
26842684

2685+
const insn_map *TMS320C64x_insns = insns;
2686+
const unsigned int TMS320C64x_insn_count = ARR_SIZE(insns);
2687+
26852688
void TMS320C64x_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id)
26862689
{
2687-
unsigned short i;
2690+
insn_map const *insn_map = NULL;
26882691

2689-
i = insn_find(insns, ARR_SIZE(insns), id, &h->insn_cache);
2690-
if (i != 0) {
2691-
insn->id = insns[i].mapid;
2692+
if ((insn_map = lookup_insn_map(h, id))) {
2693+
insn->id = insn_map->mapid;
26922694

26932695
if (h->detail_opt) {
26942696
#ifndef CAPSTONE_DIET
2695-
memcpy(insn->detail->regs_read, insns[i].regs_use,
2696-
sizeof(insns[i].regs_use));
2697+
memcpy(insn->detail->regs_read, insn_map->regs_use,
2698+
sizeof(insn_map->regs_use));
26972699
insn->detail->regs_read_count =
2698-
(uint8_t)count_positive(insns[i].regs_use);
2700+
(uint8_t)count_positive(insn_map->regs_use);
26992701

2700-
memcpy(insn->detail->regs_write, insns[i].regs_mod,
2701-
sizeof(insns[i].regs_mod));
2702+
memcpy(insn->detail->regs_write, insn_map->regs_mod,
2703+
sizeof(insn_map->regs_mod));
27022704
insn->detail->regs_write_count =
2703-
(uint8_t)count_positive(insns[i].regs_mod);
2705+
(uint8_t)count_positive(insn_map->regs_mod);
27042706

2705-
memcpy(insn->detail->groups, insns[i].groups,
2706-
sizeof(insns[i].groups));
2707+
memcpy(insn->detail->groups, insn_map->groups,
2708+
sizeof(insn_map->groups));
27072709
insn->detail->groups_count =
2708-
(uint8_t)count_positive8(insns[i].groups);
2710+
(uint8_t)count_positive8(insn_map->groups);
27092711

2710-
if (insns[i].branch || insns[i].indirect_branch) {
2712+
if (insn_map->branch || insn_map->indirect_branch) {
27112713
insn->detail
27122714
->groups[insn->detail->groups_count] =
27132715
TMS320C64X_GRP_JUMP;

arch/TMS320C64x/TMS320C64xMapping.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66

77
#include "capstone/capstone.h"
88

9+
extern const insn_map *TMS320C64x_insns;
10+
extern const unsigned int TMS320C64x_insn_count;
11+
912
// return name of register in friendly string
1013
const char *TMS320C64x_reg_name(csh handle, unsigned int reg);
1114

0 commit comments

Comments
 (0)