cache insns for fast lookup in mapping.c. based on the idea of Dang Hoang Vu
diff --git a/arch/AArch64/mapping.c b/arch/AArch64/mapping.c
index 0fb5ec0..3ffb6f8 100644
--- a/arch/AArch64/mapping.c
+++ b/arch/AArch64/mapping.c
@@ -254,6 +254,8 @@
}
static insn_map insns[] = {
+ { 0, 0, { 0 }, { 0 }, { 0 }, 0, 0 }, // dummy item
+
{ AArch64_ABS16b, ARM64_INS_ABS, { 0 }, { 0 }, { ARM64_GRP_NEON, 0 }, 0, 0 },
{ AArch64_ABS2d, ARM64_INS_ABS, { 0 }, { 0 }, { ARM64_GRP_NEON, 0 }, 0, 0 },
{ AArch64_ABS2s, ARM64_INS_ABS, { 0 }, { 0 }, { ARM64_GRP_NEON, 0 }, 0, 0 },
@@ -2990,10 +2992,13 @@
// { AArch64_SUBSxxx_lsl, ARM64_INS_NEGS, { 0 }, { ARM64_REG_NZCV, 0 }, { 0 } },
};
+static unsigned short *insn_cache = NULL;
+
+// given internal insn id, return public instruction info
void AArch64_get_insn_id(cs_insn *insn, unsigned int id, int detail)
{
- int i = insn_find(insns, ARR_SIZE(insns), id);
- if (i != -1) {
+ int i = insn_find(insns, ARR_SIZE(insns), id, &insn_cache);
+ if (i != 0) {
insn->id = insns[i].mapid;
if (detail) {
@@ -3523,3 +3528,10 @@
return (i != -1)? i : ARM64_REG_INVALID;
}
+void AArch64_free_cache(void)
+{
+ if (insn_cache)
+ free(insn_cache);
+
+ insn_cache = NULL;
+}
diff --git a/arch/AArch64/mapping.h b/arch/AArch64/mapping.h
index 08b2870..4bcd40d 100644
--- a/arch/AArch64/mapping.h
+++ b/arch/AArch64/mapping.h
@@ -21,4 +21,7 @@
// map instruction name to public instruction ID
arm64_reg AArch64_map_insn(const char *name);
+// free insn cache
+void AArch64_free_cache(void);
+
#endif
diff --git a/arch/AArch64/module.c b/arch/AArch64/module.c
index cbf638b..f22253c 100644
--- a/arch/AArch64/module.c
+++ b/arch/AArch64/module.c
@@ -30,10 +30,16 @@
return CS_ERR_OK;
}
+static void destroy(cs_struct *handle)
+{
+ AArch64_free_cache();
+}
+
static void __attribute__ ((constructor)) __init_arm64__()
{
arch_init[CS_ARCH_ARM64] = init;
- arch_option[CS_ARCH_ARM] = option;
+ arch_option[CS_ARCH_ARM64] = option;
+ arch_destroy[CS_ARCH_ARM64] = destroy;
// support this arch
all_arch |= (1 << CS_ARCH_ARM64);
diff --git a/arch/ARM/mapping.c b/arch/ARM/mapping.c
index 98e5575..d8b5584 100644
--- a/arch/ARM/mapping.c
+++ b/arch/ARM/mapping.c
@@ -135,6 +135,8 @@
}
static insn_map insns[] = {
+ { 0, 0, { 0 }, { 0 }, { 0 }, 0, 0 }, // dummy item
+
{ ARM_ADCri, ARM_INS_ADC, { ARM_REG_CPSR, 0 }, { ARM_REG_CPSR, 0 }, { ARM_GRP_ARM, 0 }, 0, 0 },
{ ARM_ADCrr, ARM_INS_ADC, { ARM_REG_CPSR, 0 }, { ARM_REG_CPSR, 0 }, { ARM_GRP_ARM, 0 }, 0, 0 },
{ ARM_ADCrsi, ARM_INS_ADC, { ARM_REG_CPSR, 0 }, { ARM_REG_CPSR, 0 }, { ARM_GRP_ARM, 0 }, 0, 0 },
@@ -2298,10 +2300,13 @@
{ ARM_tUXTH, ARM_INS_UXTH, { 0 }, { 0 }, { ARM_GRP_THUMB, ARM_GRP_THUMB1ONLY, ARM_GRP_V6, 0 }, 0, 0 },
};
+
+static unsigned short *insn_cache = NULL;
+
void ARM_get_insn_id(cs_insn *insn, unsigned int id, int detail)
{
- int i = insn_find(insns, ARR_SIZE(insns), id);
- if (i != -1) {
+ int i = insn_find(insns, ARR_SIZE(insns), id, &insn_cache);
+ if (i != 0) {
insn->id = insns[i].mapid;
if (detail) {
@@ -2788,11 +2793,19 @@
bool ARM_rel_branch(unsigned int id)
{
- int i = insn_find(insns, ARR_SIZE(insns), id);
- if (i != -1)
+ int i = insn_find(insns, ARR_SIZE(insns), id, &insn_cache);
+ if (i != 0)
return (insns[i].branch && !insns[i].indirect_branch);
else {
printf("ALERT: rel_branch() got incorrect id!\n");
return false;
}
}
+
+void ARM_free_cache(void)
+{
+ if (insn_cache)
+ free(insn_cache);
+
+ insn_cache = NULL;
+}
diff --git a/arch/ARM/mapping.h b/arch/ARM/mapping.h
index 10866fb..62b8d92 100644
--- a/arch/ARM/mapping.h
+++ b/arch/ARM/mapping.h
@@ -25,4 +25,7 @@
// check if this insn is relative branch
bool ARM_rel_branch(unsigned int insn_id);
+// free insn cache
+void ARM_free_cache(void);
+
#endif
diff --git a/arch/ARM/module.c b/arch/ARM/module.c
index 7484a34..54108dd 100644
--- a/arch/ARM/module.c
+++ b/arch/ARM/module.c
@@ -43,10 +43,16 @@
return CS_ERR_OK;
}
+static void destroy(cs_struct *handle)
+{
+ ARM_free_cache();
+}
+
static void __attribute__ ((constructor)) __init_arm__()
{
arch_init[CS_ARCH_ARM] = init;
arch_option[CS_ARCH_ARM] = option;
+ arch_destroy[CS_ARCH_ARM] = destroy;
// support this arch
all_arch |= (1 << CS_ARCH_ARM);
diff --git a/arch/Mips/mapping.c b/arch/Mips/mapping.c
index 4893ddb..4036293 100644
--- a/arch/Mips/mapping.c
+++ b/arch/Mips/mapping.c
@@ -182,6 +182,8 @@
}
static insn_map insns[] = {
+ { 0, 0, { 0 }, { 0 }, { 0 }, 0, 0 }, // dummy item
+
{ Mips_ABSQ_S_PH, MIPS_INS_ABSQ_S, { 0 }, { MIPS_REG_DSPOUTFLAG20, 0 }, { MIPS_GRP_DSP, 0 }, 0, 0 },
{ Mips_ABSQ_S_QB, MIPS_INS_ABSQ_S, { 0 }, { MIPS_REG_DSPOUTFLAG20, 0 }, { MIPS_GRP_DSPR2, 0 }, 0, 0 },
{ Mips_ABSQ_S_W, MIPS_INS_ABSQ_S, { 0 }, { MIPS_REG_DSPOUTFLAG20, 0 }, { MIPS_GRP_DSP, 0 }, 0, 0 },
@@ -1386,6 +1388,8 @@
{ Mips_SUBu, MIPS_INS_NEGU, { 0 }, { 0 }, { MIPS_GRP_STDENC, 0 }, 0, 0 },
};
+static unsigned short *insn_cache = NULL;
+
// given internal insn id, return public instruction info
void Mips_get_insn_id(cs_insn *insn, unsigned int id, int detail)
{
@@ -1417,8 +1421,8 @@
}
}
- i = insn_find(insns, ARR_SIZE(insns), id);
- if (i != -1) {
+ i = insn_find(insns, ARR_SIZE(insns), id, &insn_cache);
+ if (i != 0) {
insn->id = insns[i].mapid;
if (detail) {
@@ -2030,3 +2034,11 @@
// cannot find this register
return 0;
}
+
+void Mips_free_cache(void)
+{
+ if (insn_cache)
+ free(insn_cache);
+
+ insn_cache = NULL;
+}
diff --git a/arch/Mips/mapping.h b/arch/Mips/mapping.h
index 78642de..7d9e74c 100644
--- a/arch/Mips/mapping.h
+++ b/arch/Mips/mapping.h
@@ -25,4 +25,7 @@
// map internal raw register to 'public' register
mips_reg Mips_map_register(unsigned int r);
+// free insn cache
+void Mips_free_cache(void);
+
#endif
diff --git a/arch/Mips/module.c b/arch/Mips/module.c
index 73fd8f8..e4d12c9 100644
--- a/arch/Mips/module.c
+++ b/arch/Mips/module.c
@@ -41,10 +41,16 @@
return CS_ERR_OK;
}
+static void destroy(cs_struct *handle)
+{
+ Mips_free_cache();
+}
+
static void __attribute__ ((constructor)) __init_mips__()
{
arch_init[CS_ARCH_MIPS] = init;
arch_option[CS_ARCH_MIPS] = option;
+ arch_destroy[CS_ARCH_MIPS] = destroy;
// support this arch
all_arch |= (1 << CS_ARCH_MIPS);
diff --git a/arch/PowerPC/module.c b/arch/PowerPC/module.c
index 8f37347..3e53d9b 100644
--- a/arch/PowerPC/module.c
+++ b/arch/PowerPC/module.c
@@ -33,10 +33,15 @@
return CS_ERR_OK;
}
+static void destroy(cs_struct *handle)
+{
+}
+
static void __attribute__ ((constructor)) __init_mips__()
{
arch_init[CS_ARCH_PPC] = init;
arch_option[CS_ARCH_PPC] = option;
+ arch_destroy[CS_ARCH_PPC] = destroy;
// support this arch
all_arch |= (1 << CS_ARCH_PPC);
diff --git a/arch/X86/mapping.c b/arch/X86/mapping.c
index f668c78..620a626 100644
--- a/arch/X86/mapping.c
+++ b/arch/X86/mapping.c
@@ -1605,6 +1605,8 @@
#include "X86GenInstrInfo.inc"
static insn_map insns[] = {
+ { 0, 0, { 0 }, { 0 }, { 0 }, 0, 0 }, // dummy item
+
{ X86_AAA, X86_INS_AAA, { 0 }, { 0 }, { X86_GRP_MODE32, 0 }, 0, 0 },
{ X86_AAD8i8, X86_INS_AAD, { 0 }, { 0 }, { X86_GRP_MODE32, 0 }, 0, 0 },
{ X86_AAM8i8, X86_INS_AAM, { 0 }, { 0 }, { X86_GRP_MODE32, 0 }, 0, 0 },
@@ -6604,11 +6606,13 @@
}
}
+static unsigned short *insn_cache = NULL;
+
// given internal insn id, return public instruction info
void X86_get_insn_id(cs_insn *insn, unsigned int id, int detail)
{
- int i = insn_find(insns, ARR_SIZE(insns), id);
- if (i != -1) {
+ int i = insn_find(insns, ARR_SIZE(insns), id, &insn_cache);
+ if (i != 0) {
insn->id = insns[i].mapid;
if (detail) {
@@ -6636,3 +6640,10 @@
return insn_reverse_id(insns, ARR_SIZE(insns), id);
}
+void X86_free_cache(void)
+{
+ if (insn_cache)
+ free(insn_cache);
+
+ insn_cache = NULL;
+}
diff --git a/arch/X86/mapping.h b/arch/X86/mapping.h
index a6ec385..1065626 100644
--- a/arch/X86/mapping.h
+++ b/arch/X86/mapping.h
@@ -37,4 +37,7 @@
// post printer for X86.
void X86_post_printer(csh handle, cs_insn *pub_insn, char *insn_asm);
+// free insn cache
+void X86_free_cache(void);
+
#endif
diff --git a/arch/X86/module.c b/arch/X86/module.c
index 6c008a9..eab9f4c 100644
--- a/arch/X86/module.c
+++ b/arch/X86/module.c
@@ -44,10 +44,16 @@
return CS_ERR_OK;
}
+static void destroy(cs_struct *handle)
+{
+ X86_free_cache();
+}
+
static void __attribute__ ((constructor)) __init_x86__()
{
arch_init[CS_ARCH_X86] = init;
arch_option[CS_ARCH_X86] = option;
+ arch_destroy[CS_ARCH_X86] = destroy;
// support this arch
all_arch |= (1 << CS_ARCH_X86);