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).
This commit is contained in:
Travis Finkenauer 2018-06-24 09:05:04 -04:00 committed by Nguyen Anh Quynh
parent ba25ab0fe1
commit 65da43d0b1
30 changed files with 456 additions and 244 deletions

View File

@ -238,7 +238,7 @@ static DecodeStatus _getInstruction(cs_struct *ud, MCInst *MI,
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

View File

@ -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 @@ static cs_err init(cs_struct *ud)
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

View File

@ -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

View File

@ -482,7 +482,7 @@ static DecodeStatus _ARM_getInstruction(cs_struct *ud, MCInst *MI, const uint8_t
}
}
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 @@ static DecodeStatus _Thumb_getInstruction(cs_struct *ud, MCInst *MI, const uint8
}
}
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 @@ static DecodeStatus _Thumb_getInstruction(cs_struct *ud, MCInst *MI, const uint8
// 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) |

View File

@ -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 @@ static cs_err init(cs_struct *ud)
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 @@ static cs_err option(cs_struct *handle, cs_opt_type type, size_t value)
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 @@ static cs_err option(cs_struct *handle, cs_opt_type type, size_t value)
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

12
arch/ARM/ARMModule.h Normal file
View File

@ -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

View File

@ -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 @@ static cs_err init(cs_struct *ud)
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

12
arch/EVM/EVMModule.h Normal file
View File

@ -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

View File

@ -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 @@ static cs_err init(cs_struct *ud)
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

12
arch/M680X/M680XModule.h Normal file
View File

@ -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

View File

@ -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 @@ static cs_err init(cs_struct *ud)
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

12
arch/M68K/M68KModule.h Normal file
View File

@ -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

View File

@ -509,7 +509,7 @@ bool Mips_getInstruction(csh ud, const uint8_t *code, size_t code_len, MCInst *i
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;
}

View File

@ -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 @@ static cs_err init(cs_struct *ud)
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

12
arch/Mips/MipsModule.h Normal file
View File

@ -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

View File

@ -363,7 +363,7 @@ static DecodeStatus getInstruction(MCInst *MI,
}
// 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

View File

@ -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 @@ static cs_err init(cs_struct *ud)
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

12
arch/PowerPC/PPCModule.h Normal file
View File

@ -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

View File

@ -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 @@ static cs_err init(cs_struct *ud)
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

12
arch/Sparc/SparcModule.h Normal file
View File

@ -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

View File

@ -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 @@ static cs_err init(cs_struct *ud)
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

View File

@ -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

View File

@ -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 @@ static cs_err init(cs_struct *ud)
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

View File

@ -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

View File

@ -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 @@ static cs_err init(cs_struct *ud)
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 @@ static cs_err option(cs_struct *handle, cs_opt_type type, size_t value)
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

12
arch/X86/X86Module.h Normal file
View File

@ -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

View File

@ -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 @@ static cs_err init(cs_struct *ud)
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

12
arch/XCore/XCoreModule.h Normal file
View File

@ -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

305
cs.c
View File

@ -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 };
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;
#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"
// 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
};
// 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
;
unsigned int all_arch = 0;
#if defined(CAPSTONE_USE_SYS_DYN_MEM)
#if !defined(CAPSTONE_HAS_OSXKERNEL) && !defined(_KERNEL_MODE)
@ -171,8 +358,6 @@ cs_vsnprintf_t cs_vsnprintf = NULL;
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 @@ unsigned int CAPSTONE_API cs_version(int *major, int *minor)
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 @@ cs_err CAPSTONE_API cs_open(cs_arch arch, cs_mode mode, csh *handle)
// 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 @@ cs_err CAPSTONE_API cs_open(cs_arch arch, cs_mode mode, csh *handle)
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 @@ cs_err CAPSTONE_API cs_option(csh ud, cs_opt_type type, size_t value)
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 @@ cs_err CAPSTONE_API cs_option(csh ud, cs_opt_type type, size_t value)
}
}
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);

View File

@ -55,7 +55,6 @@ struct cs_struct {
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 @@ struct cs_struct {
#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;