Declare global arch arrays with contents (next branch) (#1186)
* Declare global arch arrays with contents (#1171)
This eliminates the need for archs_enable() and eliminates the racey
initialization.
This makes the architecture-specific init and option functions
non-static so that they may be called from a different file.
Cherry-picked 853a2870
* Add cs_arch_disallowed_mode_mask global
Cherry-pick 94bce437:
mips: CS_MODE_MIPS32R6 implies CS_MODE_32
Cherry-pick 8998a3a1:
ppc: fix endian check (#1029)
Fixes bug where endianness could not be set for ppc.
Remove `big_endian` field of `cs_struct`.
Added a helper macro `MODE_IS_BIG_ENDIAN()` to check if
`CS_MODE_BIG_ENDIAN` is set.
Refactored `cs_open()` check for valid mode out of arch-specific code
into arch-independent code. Also added a valid mode check to
`cs_option()`. The checks use a new global array
`cs_arch_disallowed_mode_mask[]`.
* Make global arrays static
Make all_arch uint32_t to guarantee a certain number of bits (with
adequate room for growth).
diff --git a/arch/AArch64/AArch64Disassembler.c b/arch/AArch64/AArch64Disassembler.c
index fbba80f..22880ef 100644
--- a/arch/AArch64/AArch64Disassembler.c
+++ b/arch/AArch64/AArch64Disassembler.c
@@ -238,7 +238,7 @@
MI->flat_insn->detail->arm64.operands[i].vector_index = -1;
}
- if (ud->big_endian)
+ if (MODE_IS_BIG_ENDIAN(ud->mode))
insn = (code[3] << 0) | (code[2] << 8) |
(code[1] << 16) | ((uint32_t) code[0] << 24);
else
diff --git a/arch/AArch64/AArch64Module.c b/arch/AArch64/AArch64Module.c
index 67a1e12..7fc5ddf 100644
--- a/arch/AArch64/AArch64Module.c
+++ b/arch/AArch64/AArch64Module.c
@@ -8,15 +8,11 @@
#include "AArch64Disassembler.h"
#include "AArch64InstPrinter.h"
#include "AArch64Mapping.h"
+#include "AArch64Module.h"
-static cs_err init(cs_struct *ud)
+cs_err AArch64_global_init(cs_struct *ud)
{
MCRegisterInfo *mri;
-
- // verify if requested mode is valid
- if (ud->mode & ~(CS_MODE_LITTLE_ENDIAN | CS_MODE_ARM | CS_MODE_BIG_ENDIAN))
- return CS_ERR_MODE;
-
mri = cs_mem_malloc(sizeof(*mri));
AArch64_init(mri);
@@ -36,22 +32,13 @@
return CS_ERR_OK;
}
-static cs_err option(cs_struct *handle, cs_opt_type type, size_t value)
+cs_err AArch64_option(cs_struct *handle, cs_opt_type type, size_t value)
{
if (type == CS_OPT_MODE) {
- handle->big_endian = (((cs_mode)value & CS_MODE_BIG_ENDIAN) != 0);
+ handle->mode = (cs_mode)value;
}
return CS_ERR_OK;
}
-void AArch64_enable(void)
-{
- cs_arch_init[CS_ARCH_ARM64] = init;
- cs_arch_option[CS_ARCH_ARM64] = option;
-
- // support this arch
- all_arch |= (1 << CS_ARCH_ARM64);
-}
-
#endif
diff --git a/arch/AArch64/AArch64Module.h b/arch/AArch64/AArch64Module.h
new file mode 100644
index 0000000..73a132d
--- /dev/null
+++ b/arch/AArch64/AArch64Module.h
@@ -0,0 +1,12 @@
+/* Capstone Disassembly Engine */
+/* By Travis Finkenauer <tmfinken@gmail.com>, 2018 */
+
+#ifndef CS_AARCH64_MODULE_H
+#define CS_AARCH64_MODULE_H
+
+#include "../../utils.h"
+
+cs_err AArch64_global_init(cs_struct *ud);
+cs_err AArch64_option(cs_struct *handle, cs_opt_type type, size_t value);
+
+#endif
diff --git a/arch/ARM/ARMDisassembler.c b/arch/ARM/ARMDisassembler.c
index 30a699f..2851e0c 100644
--- a/arch/ARM/ARMDisassembler.c
+++ b/arch/ARM/ARMDisassembler.c
@@ -482,7 +482,7 @@
}
}
- if (ud->big_endian)
+ if (MODE_IS_BIG_ENDIAN(ud->mode))
insn = (code[3] << 0) |
(code[2] << 8) |
(code[1] << 16) |
@@ -725,7 +725,7 @@
}
}
- if (ud->big_endian)
+ if (MODE_IS_BIG_ENDIAN(ud->mode))
insn16 = (code[0] << 8) | code[1];
else
insn16 = (code[1] << 8) | code[0];
@@ -776,7 +776,7 @@
// not enough data
return MCDisassembler_Fail;
- if (ud->big_endian)
+ if (MODE_IS_BIG_ENDIAN(ud->mode))
insn32 = (code[3] << 0) |
(code[2] << 8) |
(code[1] << 16) |
diff --git a/arch/ARM/ARMModule.c b/arch/ARM/ARMModule.c
index f22a4b2..0ecadd8 100644
--- a/arch/ARM/ARMModule.c
+++ b/arch/ARM/ARMModule.c
@@ -8,16 +8,11 @@
#include "ARMDisassembler.h"
#include "ARMInstPrinter.h"
#include "ARMMapping.h"
+#include "ARMModule.h"
-static cs_err init(cs_struct *ud)
+cs_err ARM_global_init(cs_struct *ud)
{
MCRegisterInfo *mri;
-
- // verify if requested mode is valid
- if (ud->mode & ~(CS_MODE_LITTLE_ENDIAN | CS_MODE_ARM | CS_MODE_V8 |
- CS_MODE_MCLASS | CS_MODE_THUMB | CS_MODE_BIG_ENDIAN))
- return CS_ERR_MODE;
-
mri = cs_mem_malloc(sizeof(*mri));
ARM_init(mri);
@@ -42,7 +37,7 @@
return CS_ERR_OK;
}
-static cs_err option(cs_struct *handle, cs_opt_type type, size_t value)
+cs_err ARM_option(cs_struct *handle, cs_opt_type type, size_t value)
{
switch(type) {
case CS_OPT_MODE:
@@ -52,7 +47,6 @@
handle->disasm = ARM_getInstruction;
handle->mode = (cs_mode)value;
- handle->big_endian = ((handle->mode & CS_MODE_BIG_ENDIAN) != 0);
break;
case CS_OPT_SYNTAX:
@@ -66,13 +60,4 @@
return CS_ERR_OK;
}
-void ARM_enable(void)
-{
- cs_arch_init[CS_ARCH_ARM] = init;
- cs_arch_option[CS_ARCH_ARM] = option;
-
- // support this arch
- all_arch |= (1 << CS_ARCH_ARM);
-}
-
#endif
diff --git a/arch/ARM/ARMModule.h b/arch/ARM/ARMModule.h
new file mode 100644
index 0000000..f844972
--- /dev/null
+++ b/arch/ARM/ARMModule.h
@@ -0,0 +1,12 @@
+/* Capstone Disassembly Engine */
+/* By Travis Finkenauer <tmfinken@gmail.com>, 2018 */
+
+#ifndef CS_ARM_MODULE_H
+#define CS_ARM_MODULE_H
+
+#include "../../utils.h"
+
+cs_err ARM_global_init(cs_struct *ud);
+cs_err ARM_option(cs_struct *handle, cs_opt_type type, size_t value);
+
+#endif
diff --git a/arch/EVM/EVMModule.c b/arch/EVM/EVMModule.c
index faf809e..ec84fe2 100644
--- a/arch/EVM/EVMModule.c
+++ b/arch/EVM/EVMModule.c
@@ -7,8 +7,9 @@
#include "EVMDisassembler.h"
#include "EVMInstPrinter.h"
#include "EVMMapping.h"
+#include "EVMModule.h"
-static cs_err init(cs_struct *ud)
+cs_err EVM_global_init(cs_struct *ud)
{
// verify if requested mode is valid
if (ud->mode)
@@ -24,18 +25,9 @@
return CS_ERR_OK;
}
-static cs_err option(cs_struct *handle, cs_opt_type type, size_t value)
+cs_err EVM_option(cs_struct *handle, cs_opt_type type, size_t value)
{
return CS_ERR_OK;
}
-void EVM_enable(void)
-{
- cs_arch_init[CS_ARCH_EVM] = init;
- cs_arch_option[CS_ARCH_EVM] = option;
-
- // support this arch
- all_arch |= (1 << CS_ARCH_EVM);
-}
-
#endif
diff --git a/arch/EVM/EVMModule.h b/arch/EVM/EVMModule.h
new file mode 100644
index 0000000..0bc6d0a
--- /dev/null
+++ b/arch/EVM/EVMModule.h
@@ -0,0 +1,12 @@
+/* Capstone Disassembly Engine */
+/* By Travis Finkenauer <tmfinken@gmail.com>, 2018 */
+
+#ifndef CS_EVM_MODULE_H
+#define CS_EVM_MODULE_H
+
+#include "../../utils.h"
+
+cs_err EVM_global_init(cs_struct *ud);
+cs_err EVM_option(cs_struct *handle, cs_opt_type type, size_t value);
+
+#endif
diff --git a/arch/M680X/M680XModule.c b/arch/M680X/M680XModule.c
index de45d48..3b89463 100644
--- a/arch/M680X/M680XModule.c
+++ b/arch/M680X/M680XModule.c
@@ -8,8 +8,9 @@
#include "M680XDisassembler.h"
#include "M680XDisassemblerInternals.h"
#include "M680XInstPrinter.h"
+#include "M680XModule.h"
-static cs_err init(cs_struct *ud)
+cs_err M680X_global_init(cs_struct *ud)
{
m680x_info *info;
cs_err errcode;
@@ -66,20 +67,11 @@
return CS_ERR_OK;
}
-static cs_err option(cs_struct *handle, cs_opt_type type, size_t value)
+cs_err M680X_option(cs_struct *handle, cs_opt_type type, size_t value)
{
//TODO
return CS_ERR_OK;
}
-void M680X_enable(void)
-{
- cs_arch_init[CS_ARCH_M680X] = init;
- cs_arch_option[CS_ARCH_M680X] = option;
-
- // support this arch
- all_arch |= (1 << CS_ARCH_M680X);
-}
-
#endif
diff --git a/arch/M680X/M680XModule.h b/arch/M680X/M680XModule.h
new file mode 100644
index 0000000..6672eb2
--- /dev/null
+++ b/arch/M680X/M680XModule.h
@@ -0,0 +1,12 @@
+/* Capstone Disassembly Engine */
+/* By Travis Finkenauer <tmfinken@gmail.com>, 2018 */
+
+#ifndef CS_M680X_MODULE_H
+#define CS_M680X_MODULE_H
+
+#include "../../utils.h"
+
+cs_err M680X_global_init(cs_struct *ud);
+cs_err M680X_option(cs_struct *handle, cs_opt_type type, size_t value);
+
+#endif
diff --git a/arch/M68K/M68KModule.c b/arch/M68K/M68KModule.c
index bce596a..03e73f7 100644
--- a/arch/M68K/M68KModule.c
+++ b/arch/M68K/M68KModule.c
@@ -7,8 +7,9 @@
#include "../../MCRegisterInfo.h"
#include "M68KDisassembler.h"
#include "M68KInstPrinter.h"
+#include "M68KModule.h"
-static cs_err init(cs_struct *ud)
+cs_err M68K_global_init(cs_struct *ud)
{
m68k_info *info;
@@ -32,19 +33,10 @@
return CS_ERR_OK;
}
-static cs_err option(cs_struct *handle, cs_opt_type type, size_t value)
+cs_err M68K_option(cs_struct *handle, cs_opt_type type, size_t value)
{
return CS_ERR_OK;
}
-void M68K_enable(void)
-{
- cs_arch_init[CS_ARCH_M68K] = init;
- cs_arch_option[CS_ARCH_M68K] = option;
-
- // support this arch
- all_arch |= (1 << CS_ARCH_M68K);
-}
-
#endif
diff --git a/arch/M68K/M68KModule.h b/arch/M68K/M68KModule.h
new file mode 100644
index 0000000..65b20bd
--- /dev/null
+++ b/arch/M68K/M68KModule.h
@@ -0,0 +1,12 @@
+/* Capstone Disassembly Engine */
+/* By Travis Finkenauer <tmfinken@gmail.com>, 2018 */
+
+#ifndef CS_M68K_MODULE_H
+#define CS_M68K_MODULE_H
+
+#include "../../utils.h"
+
+cs_err M68K_global_init(cs_struct *ud);
+cs_err M68K_option(cs_struct *handle, cs_opt_type type, size_t value);
+
+#endif
diff --git a/arch/Mips/MipsDisassembler.c b/arch/Mips/MipsDisassembler.c
index 0b7d90e..f374d27 100644
--- a/arch/Mips/MipsDisassembler.c
+++ b/arch/Mips/MipsDisassembler.c
@@ -509,7 +509,7 @@
DecodeStatus status = MipsDisassembler_getInstruction(handle->mode, instr,
code, code_len,
size,
- address, handle->big_endian, (MCRegisterInfo *)info);
+ address, MODE_IS_BIG_ENDIAN(handle->mode), (MCRegisterInfo *)info);
return status == MCDisassembler_Success;
}
diff --git a/arch/Mips/MipsModule.c b/arch/Mips/MipsModule.c
index a113b74..93c6050 100644
--- a/arch/Mips/MipsModule.c
+++ b/arch/Mips/MipsModule.c
@@ -8,18 +8,22 @@
#include "MipsDisassembler.h"
#include "MipsInstPrinter.h"
#include "MipsMapping.h"
+#include "MipsModule.h"
+
+// Returns mode value with implied bits set
+static inline cs_mode updated_mode(cs_mode mode)
+{
+ if (mode & CS_MODE_MIPS32R6) {
+ mode |= CS_MODE_32;
+ }
+
+ return mode;
+}
-static cs_err init(cs_struct *ud)
+cs_err Mips_global_init(cs_struct *ud)
{
MCRegisterInfo *mri;
-
- // verify if requested mode is valid
- if (ud->mode & ~(CS_MODE_LITTLE_ENDIAN | CS_MODE_32 | CS_MODE_64 |
- CS_MODE_MICRO | CS_MODE_MIPS32R6 | CS_MODE_BIG_ENDIAN |
- CS_MODE_MIPS2 | CS_MODE_MIPS3))
- return CS_ERR_MODE;
-
mri = cs_mem_malloc(sizeof(*mri));
Mips_init(mri);
@@ -36,24 +40,14 @@
return CS_ERR_OK;
}
-static cs_err option(cs_struct *handle, cs_opt_type type, size_t value)
+cs_err Mips_option(cs_struct *handle, cs_opt_type type, size_t value)
{
if (type == CS_OPT_MODE) {
- handle->mode = (cs_mode)value;
- handle->big_endian = ((handle->mode & CS_MODE_BIG_ENDIAN) != 0);
+ handle->mode = updated_mode(value);
return CS_ERR_OK;
}
return CS_ERR_OPTION;
}
-void Mips_enable(void)
-{
- cs_arch_init[CS_ARCH_MIPS] = init;
- cs_arch_option[CS_ARCH_MIPS] = option;
-
- // support this arch
- all_arch |= (1 << CS_ARCH_MIPS);
-}
-
#endif
diff --git a/arch/Mips/MipsModule.h b/arch/Mips/MipsModule.h
new file mode 100644
index 0000000..d1aa2cf
--- /dev/null
+++ b/arch/Mips/MipsModule.h
@@ -0,0 +1,12 @@
+/* Capstone Disassembly Engine */
+/* By Travis Finkenauer <tmfinken@gmail.com>, 2018 */
+
+#ifndef CS_MIPS_MODULE_H
+#define CS_MIPS_MODULE_H
+
+#include "../../utils.h"
+
+cs_err Mips_global_init(cs_struct *ud);
+cs_err Mips_option(cs_struct *handle, cs_opt_type type, size_t value);
+
+#endif
diff --git a/arch/PowerPC/PPCDisassembler.c b/arch/PowerPC/PPCDisassembler.c
index dde43b6..12e59eb 100644
--- a/arch/PowerPC/PPCDisassembler.c
+++ b/arch/PowerPC/PPCDisassembler.c
@@ -363,7 +363,7 @@
}
// The instruction is big-endian encoded.
- if (MI->csh->mode & CS_MODE_BIG_ENDIAN)
+ if (MODE_IS_BIG_ENDIAN(MI->csh->mode))
insn = ((uint32_t) code[0] << 24) | (code[1] << 16) |
(code[2] << 8) | (code[3] << 0);
else
diff --git a/arch/PowerPC/PPCModule.c b/arch/PowerPC/PPCModule.c
index 0bba212..794b9a8 100644
--- a/arch/PowerPC/PPCModule.c
+++ b/arch/PowerPC/PPCModule.c
@@ -8,16 +8,11 @@
#include "PPCDisassembler.h"
#include "PPCInstPrinter.h"
#include "PPCMapping.h"
+#include "PPCModule.h"
-static cs_err init(cs_struct *ud)
+cs_err PPC_global_init(cs_struct *ud)
{
MCRegisterInfo *mri;
-
- // verify if requested mode is valid
- if (ud->mode & ~(CS_MODE_LITTLE_ENDIAN | CS_MODE_32 | CS_MODE_64 |
- CS_MODE_BIG_ENDIAN | CS_MODE_QPX))
- return CS_ERR_MODE;
-
mri = (MCRegisterInfo *) cs_mem_malloc(sizeof(*mri));
PPC_init(mri);
@@ -35,25 +30,16 @@
return CS_ERR_OK;
}
-static cs_err option(cs_struct *handle, cs_opt_type type, size_t value)
+cs_err PPC_option(cs_struct *handle, cs_opt_type type, size_t value)
{
if (type == CS_OPT_SYNTAX)
handle->syntax = (int) value;
if (type == CS_OPT_MODE) {
- handle->big_endian = (((cs_mode)value & CS_MODE_BIG_ENDIAN) != 0);
+ handle->mode = (cs_mode)value;
}
return CS_ERR_OK;
}
-void PPC_enable(void)
-{
- cs_arch_init[CS_ARCH_PPC] = init;
- cs_arch_option[CS_ARCH_PPC] = option;
-
- // support this arch
- all_arch |= (1 << CS_ARCH_PPC);
-}
-
#endif
diff --git a/arch/PowerPC/PPCModule.h b/arch/PowerPC/PPCModule.h
new file mode 100644
index 0000000..079cf60
--- /dev/null
+++ b/arch/PowerPC/PPCModule.h
@@ -0,0 +1,12 @@
+/* Capstone Disassembly Engine */
+/* By Travis Finkenauer <tmfinken@gmail.com>, 2018 */
+
+#ifndef CS_POWERPC_MODULE_H
+#define CS_POWERPC_MODULE_H
+
+#include "../../utils.h"
+
+cs_err PPC_global_init(cs_struct *ud);
+cs_err PPC_option(cs_struct *handle, cs_opt_type type, size_t value);
+
+#endif
diff --git a/arch/Sparc/SparcModule.c b/arch/Sparc/SparcModule.c
index 614234d..88a0a9e 100644
--- a/arch/Sparc/SparcModule.c
+++ b/arch/Sparc/SparcModule.c
@@ -8,15 +8,11 @@
#include "SparcDisassembler.h"
#include "SparcInstPrinter.h"
#include "SparcMapping.h"
+#include "SparcModule.h"
-static cs_err init(cs_struct *ud)
+cs_err Sparc_global_init(cs_struct *ud)
{
MCRegisterInfo *mri;
-
- // verify if requested mode is valid
- if (ud->mode & ~(CS_MODE_BIG_ENDIAN | CS_MODE_V9))
- return CS_ERR_MODE;
-
mri = cs_mem_malloc(sizeof(*mri));
Sparc_init(mri);
@@ -34,25 +30,16 @@
return CS_ERR_OK;
}
-static cs_err option(cs_struct *handle, cs_opt_type type, size_t value)
+cs_err Sparc_option(cs_struct *handle, cs_opt_type type, size_t value)
{
if (type == CS_OPT_SYNTAX)
handle->syntax = (int) value;
if (type == CS_OPT_MODE) {
- handle->big_endian = (((cs_mode)value & CS_MODE_BIG_ENDIAN) != 0);
+ handle->mode = (cs_mode)value;
}
return CS_ERR_OK;
}
-void Sparc_enable(void)
-{
- cs_arch_init[CS_ARCH_SPARC] = init;
- cs_arch_option[CS_ARCH_SPARC] = option;
-
- // support this arch
- all_arch |= (1 << CS_ARCH_SPARC);
-}
-
#endif
diff --git a/arch/Sparc/SparcModule.h b/arch/Sparc/SparcModule.h
new file mode 100644
index 0000000..1caaac1
--- /dev/null
+++ b/arch/Sparc/SparcModule.h
@@ -0,0 +1,12 @@
+/* Capstone Disassembly Engine */
+/* By Travis Finkenauer <tmfinken@gmail.com>, 2018 */
+
+#ifndef CS_SPARC_MODULE_H
+#define CS_SPARC_MODULE_H
+
+#include "../../utils.h"
+
+cs_err Sparc_global_init(cs_struct *ud);
+cs_err Sparc_option(cs_struct *handle, cs_opt_type type, size_t value);
+
+#endif
diff --git a/arch/SystemZ/SystemZModule.c b/arch/SystemZ/SystemZModule.c
index c35315c..bc51068 100644
--- a/arch/SystemZ/SystemZModule.c
+++ b/arch/SystemZ/SystemZModule.c
@@ -8,11 +8,11 @@
#include "SystemZDisassembler.h"
#include "SystemZInstPrinter.h"
#include "SystemZMapping.h"
+#include "SystemZModule.h"
-static cs_err init(cs_struct *ud)
+cs_err SystemZ_global_init(cs_struct *ud)
{
MCRegisterInfo *mri;
-
mri = cs_mem_malloc(sizeof(*mri));
SystemZ_init(mri);
@@ -30,21 +30,15 @@
return CS_ERR_OK;
}
-static cs_err option(cs_struct *handle, cs_opt_type type, size_t value)
+cs_err SystemZ_option(cs_struct *handle, cs_opt_type type, size_t value)
{
if (type == CS_OPT_SYNTAX)
handle->syntax = (int) value;
+ // Do not set mode because only CS_MODE_BIG_ENDIAN is valid; we cannot
+ // test for CS_MODE_LITTLE_ENDIAN because it is 0
+
return CS_ERR_OK;
}
-void SystemZ_enable(void)
-{
- cs_arch_init[CS_ARCH_SYSZ] = init;
- cs_arch_option[CS_ARCH_SYSZ] = option;
-
- // support this arch
- all_arch |= (1 << CS_ARCH_SYSZ);
-}
-
#endif
diff --git a/arch/SystemZ/SystemZModule.h b/arch/SystemZ/SystemZModule.h
new file mode 100644
index 0000000..ad403ba
--- /dev/null
+++ b/arch/SystemZ/SystemZModule.h
@@ -0,0 +1,12 @@
+/* Capstone Disassembly Engine */
+/* By Travis Finkenauer <tmfinken@gmail.com>, 2018 */
+
+#ifndef CS_SYSTEMZ_MODULE_H
+#define CS_SYSTEMZ_MODULE_H
+
+#include "../../utils.h"
+
+cs_err SystemZ_global_init(cs_struct *ud);
+cs_err SystemZ_option(cs_struct *handle, cs_opt_type type, size_t value);
+
+#endif
diff --git a/arch/TMS320C64x/TMS320C64xModule.c b/arch/TMS320C64x/TMS320C64xModule.c
index 2d6620a..ff678c7 100644
--- a/arch/TMS320C64x/TMS320C64xModule.c
+++ b/arch/TMS320C64x/TMS320C64xModule.c
@@ -8,8 +8,9 @@
#include "TMS320C64xDisassembler.h"
#include "TMS320C64xInstPrinter.h"
#include "TMS320C64xMapping.h"
+#include "TMS320C64xModule.h"
-static cs_err init(cs_struct *ud)
+cs_err TMS320C64x_global_init(cs_struct *ud)
{
MCRegisterInfo *mri;
@@ -30,17 +31,9 @@
return CS_ERR_OK;
}
-static cs_err option(cs_struct *handle, cs_opt_type type, size_t value)
+cs_err TMS320C64x_option(cs_struct *handle, cs_opt_type type, size_t value)
{
return CS_ERR_OK;
}
-void TMS320C64x_enable(void)
-{
- cs_arch_init[CS_ARCH_TMS320C64X] = init;
- cs_arch_option[CS_ARCH_TMS320C64X] = option;
-
- all_arch |= (1 << CS_ARCH_TMS320C64X);
-}
-
#endif
diff --git a/arch/TMS320C64x/TMS320C64xModule.h b/arch/TMS320C64x/TMS320C64xModule.h
new file mode 100644
index 0000000..f1c5312
--- /dev/null
+++ b/arch/TMS320C64x/TMS320C64xModule.h
@@ -0,0 +1,12 @@
+/* Capstone Disassembly Engine */
+/* By Travis Finkenauer <tmfinken@gmail.com>, 2018 */
+
+#ifndef CS_TMS320C64X_MODULE_H
+#define CS_TMS320C64X_MODULE_H
+
+#include "../../utils.h"
+
+cs_err TMS320C64x_global_init(cs_struct *ud);
+cs_err TMS320C64x_option(cs_struct *handle, cs_opt_type type, size_t value);
+
+#endif
diff --git a/arch/X86/X86Module.c b/arch/X86/X86Module.c
index 77a021c..98c6e47 100644
--- a/arch/X86/X86Module.c
+++ b/arch/X86/X86Module.c
@@ -8,15 +8,11 @@
#include "X86Disassembler.h"
#include "X86InstPrinter.h"
#include "X86Mapping.h"
+#include "X86Module.h"
-static cs_err init(cs_struct *ud)
+cs_err X86_global_init(cs_struct *ud)
{
MCRegisterInfo *mri;
-
- // verify if requested mode is valid
- if (ud->mode & ~(CS_MODE_LITTLE_ENDIAN | CS_MODE_32 | CS_MODE_64 | CS_MODE_16))
- return CS_ERR_MODE;
-
mri = cs_mem_malloc(sizeof(*mri));
X86_init(mri);
@@ -43,7 +39,7 @@
return CS_ERR_OK;
}
-static cs_err option(cs_struct *handle, cs_opt_type type, size_t value)
+cs_err X86_option(cs_struct *handle, cs_opt_type type, size_t value)
{
switch(type) {
default:
@@ -95,13 +91,4 @@
return CS_ERR_OK;
}
-void X86_enable(void)
-{
- cs_arch_init[CS_ARCH_X86] = init;
- cs_arch_option[CS_ARCH_X86] = option;
-
- // support this arch
- all_arch |= (1 << CS_ARCH_X86);
-}
-
#endif
diff --git a/arch/X86/X86Module.h b/arch/X86/X86Module.h
new file mode 100644
index 0000000..53d13ed
--- /dev/null
+++ b/arch/X86/X86Module.h
@@ -0,0 +1,12 @@
+/* Capstone Disassembly Engine */
+/* By Travis Finkenauer <tmfinken@gmail.com>, 2018 */
+
+#ifndef CS_X86_MODULE_H
+#define CS_X86_MODULE_H
+
+#include "../../utils.h"
+
+cs_err X86_global_init(cs_struct *ud);
+cs_err X86_option(cs_struct *handle, cs_opt_type type, size_t value);
+
+#endif
diff --git a/arch/XCore/XCoreModule.c b/arch/XCore/XCoreModule.c
index 0e41687..90940d4 100644
--- a/arch/XCore/XCoreModule.c
+++ b/arch/XCore/XCoreModule.c
@@ -8,11 +8,11 @@
#include "XCoreDisassembler.h"
#include "XCoreInstPrinter.h"
#include "XCoreMapping.h"
+#include "XCoreModule.h"
-static cs_err init(cs_struct *ud)
+cs_err XCore_global_init(cs_struct *ud)
{
MCRegisterInfo *mri;
-
mri = cs_mem_malloc(sizeof(*mri));
XCore_init(mri);
@@ -30,18 +30,12 @@
return CS_ERR_OK;
}
-static cs_err option(cs_struct *handle, cs_opt_type type, size_t value)
+cs_err XCore_option(cs_struct *handle, cs_opt_type type, size_t value)
{
+ // Do not set mode because only CS_MODE_BIG_ENDIAN is valid; we cannot
+ // test for CS_MODE_LITTLE_ENDIAN because it is 0
+
return CS_ERR_OK;
}
-void XCore_enable(void)
-{
- cs_arch_init[CS_ARCH_XCORE] = init;
- cs_arch_option[CS_ARCH_XCORE] = option;
-
- // support this arch
- all_arch |= (1 << CS_ARCH_XCORE);
-}
-
#endif
diff --git a/arch/XCore/XCoreModule.h b/arch/XCore/XCoreModule.h
new file mode 100644
index 0000000..c4a7d2b
--- /dev/null
+++ b/arch/XCore/XCoreModule.h
@@ -0,0 +1,12 @@
+/* Capstone Disassembly Engine */
+/* By Travis Finkenauer <tmfinken@gmail.com>, 2018 */
+
+#ifndef CS_XCORE_MODULE_H
+#define CS_XCORE_MODULE_H
+
+#include "../../utils.h"
+
+cs_err XCore_global_init(cs_struct *ud);
+cs_err XCore_option(cs_struct *handle, cs_opt_type type, size_t value);
+
+#endif
diff --git a/cs.c b/cs.c
index 4f181c2..d2ffecc 100644
--- a/cs.c
+++ b/cs.c
@@ -52,72 +52,259 @@
#define SKIPDATA_MNEM NULL
#endif
-cs_err (*cs_arch_init[MAX_ARCH])(cs_struct *) = { NULL };
-cs_err (*cs_arch_option[MAX_ARCH]) (cs_struct *, cs_opt_type, size_t value) = { NULL };
-void (*cs_arch_destroy[MAX_ARCH]) (cs_struct *) = { NULL };
+#include "arch/AArch64/AArch64Module.h"
+#include "arch/ARM/ARMModule.h"
+#include "arch/EVM/EVMModule.h"
+#include "arch/M680X/M680XModule.h"
+#include "arch/M68K/M68KModule.h"
+#include "arch/Mips/MipsModule.h"
+#include "arch/PowerPC/PPCModule.h"
+#include "arch/Sparc/SparcModule.h"
+#include "arch/SystemZ/SystemZModule.h"
+#include "arch/TMS320C64x/TMS320C64xModule.h"
+#include "arch/X86/X86Module.h"
+#include "arch/XCore/XCoreModule.h"
-extern void ARM_enable(void);
-extern void AArch64_enable(void);
-extern void M680X_enable(void);
-extern void M68K_enable(void);
-extern void Mips_enable(void);
-extern void X86_enable(void);
-extern void PPC_enable(void);
-extern void Sparc_enable(void);
-extern void SystemZ_enable(void);
-extern void XCore_enable(void);
-extern void TMS320C64x_enable(void);
-extern void EVM_enable(void);
-
-static void archs_enable(void)
-{
- static bool initialized = false;
-
- if (initialized)
- return;
-
+// constructor initialization for all archs
+static cs_err (*cs_arch_init[MAX_ARCH])(cs_struct *) = {
#ifdef CAPSTONE_HAS_ARM
- ARM_enable();
+ ARM_global_init,
+#else
+ NULL,
#endif
#ifdef CAPSTONE_HAS_ARM64
- AArch64_enable();
-#endif
-#ifdef CAPSTONE_HAS_M680X
- M680X_enable();
-#endif
-#ifdef CAPSTONE_HAS_M68K
- M68K_enable();
+ AArch64_global_init,
+#else
+ NULL,
#endif
#ifdef CAPSTONE_HAS_MIPS
- Mips_enable();
-#endif
-#ifdef CAPSTONE_HAS_POWERPC
- PPC_enable();
-#endif
-#ifdef CAPSTONE_HAS_SPARC
- Sparc_enable();
-#endif
-#ifdef CAPSTONE_HAS_SYSZ
- SystemZ_enable();
+ Mips_global_init,
+#else
+ NULL,
#endif
#ifdef CAPSTONE_HAS_X86
- X86_enable();
+ X86_global_init,
+#else
+ NULL,
+#endif
+#ifdef CAPSTONE_HAS_POWERPC
+ PPC_global_init,
+#else
+ NULL,
+#endif
+#ifdef CAPSTONE_HAS_SPARC
+ Sparc_global_init,
+#else
+ NULL,
+#endif
+#ifdef CAPSTONE_HAS_SYSZ
+ SystemZ_global_init,
+#else
+ NULL,
#endif
#ifdef CAPSTONE_HAS_XCORE
- XCore_enable();
+ XCore_global_init,
+#else
+ NULL,
+#endif
+#ifdef CAPSTONE_HAS_M68K
+ M68K_global_init,
+#else
+ NULL,
#endif
#ifdef CAPSTONE_HAS_TMS320C64X
- TMS320C64x_enable();
+ TMS320C64x_global_init,
+#else
+ NULL,
+#endif
+#ifdef CAPSTONE_HAS_M680X
+ M680X_global_init,
+#else
+ NULL,
#endif
#ifdef CAPSTONE_HAS_EVM
- EVM_enable();
+ EVM_global_init,
+#else
+ NULL,
#endif
+};
+// support cs_option() for all archs
+static cs_err (*cs_arch_option[MAX_ARCH]) (cs_struct *, cs_opt_type, size_t value) = {
+#ifdef CAPSTONE_HAS_ARM
+ ARM_option,
+#else
+ NULL,
+#endif
+#ifdef CAPSTONE_HAS_ARM64
+ AArch64_option,
+#else
+ NULL,
+#endif
+#ifdef CAPSTONE_HAS_MIPS
+ Mips_option,
+#else
+ NULL,
+#endif
+#ifdef CAPSTONE_HAS_X86
+ X86_option,
+#else
+ NULL,
+#endif
+#ifdef CAPSTONE_HAS_POWERPC
+ PPC_option,
+#else
+ NULL,
+#endif
+#ifdef CAPSTONE_HAS_SPARC
+ Sparc_option,
+#else
+ NULL,
+#endif
+#ifdef CAPSTONE_HAS_SYSZ
+ SystemZ_option,
+#else
+ NULL,
+#endif
+#ifdef CAPSTONE_HAS_XCORE
+ XCore_option,
+#else
+ NULL,
+#endif
+#ifdef CAPSTONE_HAS_M68K
+ M68K_option,
+#else
+ NULL,
+#endif
+#ifdef CAPSTONE_HAS_TMS320C64X
+ TMS320C64x_option,
+#else
+ NULL,
+#endif
+#ifdef CAPSTONE_HAS_M680X
+ M680X_option,
+#else
+ NULL,
+#endif
+#ifdef CAPSTONE_HAS_EVM
+ EVM_option,
+#else
+ NULL,
+#endif
+};
- initialized = true;
-}
+// bitmask for finding disallowed modes for an arch:
+// to be called in cs_open()/cs_option()
+static cs_mode cs_arch_disallowed_mode_mask[MAX_ARCH] = {
+#ifdef CAPSTONE_HAS_ARM
+ ~(CS_MODE_LITTLE_ENDIAN | CS_MODE_ARM | CS_MODE_V8 | CS_MODE_MCLASS
+ | CS_MODE_THUMB | CS_MODE_BIG_ENDIAN),
+#else
+ 0,
+#endif
+#ifdef CAPSTONE_HAS_ARM64
+ ~(CS_MODE_LITTLE_ENDIAN | CS_MODE_ARM | CS_MODE_BIG_ENDIAN),
+#else
+ 0,
+#endif
+#ifdef CAPSTONE_HAS_MIPS
+ ~(CS_MODE_LITTLE_ENDIAN | CS_MODE_32 | CS_MODE_64 | CS_MODE_MICRO
+ | CS_MODE_MIPS32R6 | CS_MODE_BIG_ENDIAN | CS_MODE_MIPS2 | CS_MODE_MIPS3),
+#else
+ 0,
+#endif
+#ifdef CAPSTONE_HAS_X86
+ ~(CS_MODE_LITTLE_ENDIAN | CS_MODE_32 | CS_MODE_64 | CS_MODE_16),
+#else
+ 0,
+#endif
+#ifdef CAPSTONE_HAS_POWERPC
+ ~(CS_MODE_LITTLE_ENDIAN | CS_MODE_32 | CS_MODE_64 | CS_MODE_BIG_ENDIAN
+ | CS_MODE_QPX),
+#else
+ 0,
+#endif
+#ifdef CAPSTONE_HAS_SPARC
+ ~(CS_MODE_BIG_ENDIAN | CS_MODE_V9),
+#else
+ 0,
+#endif
+#ifdef CAPSTONE_HAS_SYSZ
+ ~(CS_MODE_BIG_ENDIAN),
+#else
+ 0,
+#endif
+#ifdef CAPSTONE_HAS_XCORE
+ ~(CS_MODE_BIG_ENDIAN),
+#else
+ 0,
+#endif
+#ifdef CAPSTONE_HAS_M68K
+ ~(CS_MODE_BIG_ENDIAN | CS_MODE_M68K_000 | CS_MODE_M68K_010 | CS_MODE_M68K_020
+ | CS_MODE_M68K_030 | CS_MODE_M68K_040 | CS_MODE_M68K_060),
+#else
+ 0,
+#endif
+#ifdef CAPSTONE_HAS_TMS320C64X
+ ~(CS_MODE_BIG_ENDIAN),
+#else
+ 0,
+#endif
+#ifdef CAPSTONE_HAS_M680X
+ ~(CS_MODE_M680X_6301 | CS_MODE_M680X_6309 | CS_MODE_M680X_6800
+ | CS_MODE_M680X_6801 | CS_MODE_M680X_6805 | CS_MODE_M680X_6808
+ | CS_MODE_M680X_6809 | CS_MODE_M680X_6811 | CS_MODE_M680X_CPU12
+ | CS_MODE_M680X_HCS08),
+#else
+ 0,
+#endif
+#ifdef CAPSTONE_HAS_EVM
+ 0,
+#else
+ 0,
+#endif
+};
-unsigned int all_arch = 0;
+// bitmask of enabled architectures
+static uint32_t all_arch = 0
+#ifdef CAPSTONE_HAS_ARM
+ | (1 << CS_ARCH_ARM)
+#endif
+#ifdef CAPSTONE_HAS_ARM64
+ | (1 << CS_ARCH_ARM64)
+#endif
+#ifdef CAPSTONE_HAS_MIPS
+ | (1 << CS_ARCH_MIPS)
+#endif
+#ifdef CAPSTONE_HAS_X86
+ | (1 << CS_ARCH_X86)
+#endif
+#ifdef CAPSTONE_HAS_POWERPC
+ | (1 << CS_ARCH_PPC)
+#endif
+#ifdef CAPSTONE_HAS_SPARC
+ | (1 << CS_ARCH_SPARC)
+#endif
+#ifdef CAPSTONE_HAS_SYSZ
+ | (1 << CS_ARCH_SYSZ)
+#endif
+#ifdef CAPSTONE_HAS_XCORE
+ | (1 << CS_ARCH_XCORE)
+#endif
+#ifdef CAPSTONE_HAS_M68K
+ | (1 << CS_ARCH_M68K)
+#endif
+#ifdef CAPSTONE_HAS_TMS320C64X
+ | (1 << CS_ARCH_TMS320C64X)
+#endif
+#ifdef CAPSTONE_HAS_M680X
+ | (1 << CS_ARCH_M680X)
+#endif
+#ifdef CAPSTONE_HAS_EVM
+ | (1 << CS_ARCH_EVM)
+#endif
+;
+
#if defined(CAPSTONE_USE_SYS_DYN_MEM)
#if !defined(CAPSTONE_HAS_OSXKERNEL) && !defined(_KERNEL_MODE)
@@ -171,8 +358,6 @@
CAPSTONE_EXPORT
unsigned int CAPSTONE_API cs_version(int *major, int *minor)
{
- archs_enable();
-
if (major != NULL && minor != NULL) {
*major = CS_API_MAJOR;
*minor = CS_API_MINOR;
@@ -184,8 +369,6 @@
CAPSTONE_EXPORT
bool CAPSTONE_API cs_support(int query)
{
- archs_enable();
-
if (query == CS_ARCH_ALL)
return all_arch == ((1 << CS_ARCH_ARM) | (1 << CS_ARCH_ARM64) |
(1 << CS_ARCH_MIPS) | (1 << CS_ARCH_X86) |
@@ -278,9 +461,13 @@
// with cs_option(CS_OPT_MEM)
return CS_ERR_MEMSETUP;
- archs_enable();
-
if (arch < CS_ARCH_MAX && cs_arch_init[arch]) {
+ // verify if requested mode is valid
+ if (mode & cs_arch_disallowed_mode_mask[arch]) {
+ *handle = 0;
+ return CS_ERR_MODE;
+ }
+
ud = cs_mem_calloc(1, sizeof(*ud));
if (!ud) {
// memory insufficient
@@ -290,7 +477,6 @@
ud->errnum = CS_ERR_OK;
ud->arch = arch;
ud->mode = mode;
- ud->big_endian = (mode & CS_MODE_BIG_ENDIAN) != 0;
// by default, do not break instruction into details
ud->detail = CS_OPT_OFF;
@@ -464,8 +650,6 @@
struct cs_struct *handle;
cs_opt_mnem *opt;
- archs_enable();
-
// cs_option() can be called with NULL handle just for CS_OPT_MEM
// This is supposed to be executed before all other APIs (even cs_open())
if (type == CS_OPT_MEM) {
@@ -566,6 +750,13 @@
}
}
return CS_ERR_OK;
+
+ case CS_OPT_MODE:
+ // verify if requested mode is valid
+ if (value & cs_arch_disallowed_mode_mask[handle->arch]) {
+ return CS_ERR_OPTION;
+ }
+ break;
}
return cs_arch_option[handle->arch](handle, type, value);
diff --git a/cs_priv.h b/cs_priv.h
index c0c4ecc..0aa0738 100644
--- a/cs_priv.h
+++ b/cs_priv.h
@@ -55,7 +55,6 @@
void *printer_info; // aux info for printer
Disasm_t disasm; // disassembler
void *getinsn_info; // auxiliary info for printer
- bool big_endian;
GetName_t reg_name;
GetName_t insn_name;
GetName_t group_name;
@@ -78,13 +77,8 @@
#define MAX_ARCH CS_ARCH_MAX
-// constructor initialization for all archs
-extern cs_err (*cs_arch_init[MAX_ARCH]) (cs_struct *);
-
-// support cs_option() for all archs
-extern cs_err (*cs_arch_option[MAX_ARCH]) (cs_struct*, cs_opt_type, size_t value);
-
-extern unsigned int all_arch;
+// Returns a bool (0 or 1) whether big endian is enabled for a mode
+#define MODE_IS_BIG_ENDIAN(mode) (((mode) & CS_MODE_BIG_ENDIAN) != 0)
extern cs_malloc_t cs_mem_malloc;
extern cs_calloc_t cs_mem_calloc;