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