2014-04-29 03:21:04 +00:00
/* Capstone Disassembly Engine */
2015-03-04 09:45:23 +00:00
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2015 */
2014-05-09 19:40:00 +00:00
# if defined (WIN32) || defined (WIN64) || defined (_WIN32) || defined (_WIN64)
2016-09-27 15:08:58 +00:00
# pragma warning(disable:4996) // disable MSVC's warning on strcpy()
# pragma warning(disable:28719) // disable MSVC's warning on strcpy()
2014-05-09 19:40:00 +00:00
# endif
2015-04-09 17:28:19 +00:00
# if defined(CAPSTONE_HAS_OSXKERNEL)
2018-06-14 21:12:26 +00:00
# include <Availability.h>
2015-04-09 17:28:19 +00:00
# include <libkern/libkern.h>
# else
2013-12-24 08:49:36 +00:00
# include <stddef.h>
2013-11-27 04:11:31 +00:00
# include <stdio.h>
# include <stdlib.h>
2015-04-09 17:28:19 +00:00
# endif
2013-11-27 04:11:31 +00:00
# include <string.h>
2015-02-24 03:55:55 +00:00
# include <capstone/capstone.h>
2013-11-27 04:11:31 +00:00
# include "utils.h"
2014-01-05 03:35:47 +00:00
# include "MCRegisterInfo.h"
2013-11-27 04:11:31 +00:00
2016-04-23 22:51:24 +00:00
# if defined(_KERNEL_MODE)
# include "windows\winkernel_mm.h"
# endif
2016-05-16 15:32:58 +00:00
// Issue #681: Windows kernel does not support formatting float point
# if defined(_KERNEL_MODE) && !defined(CAPSTONE_DIET)
2016-05-17 03:32:36 +00:00
# if defined(CAPSTONE_HAS_ARM) || defined(CAPSTONE_HAS_ARM64) || defined(CAPSTONE_HAS_M68K)
2016-05-16 15:32:58 +00:00
# define CAPSTONE_STR_INTERNAL(x) #x
# define CAPSTONE_STR(x) CAPSTONE_STR_INTERNAL(x)
# define CAPSTONE_MSVC_WRANING_PREFIX __FILE__ "("CAPSTONE_STR(__LINE__)") : warning message : "
# pragma message(CAPSTONE_MSVC_WRANING_PREFIX "Windows driver does not support full features for selected architecture(s). Define CAPSTONE_DIET to compile Capstone with only supported features. See issue #681 for details.")
# undef CAPSTONE_MSVC_WRANING_PREFIX
# undef CAPSTONE_STR
# undef CAPSTONE_STR_INTERNAL
# endif
# endif // defined(_KERNEL_MODE) && !defined(CAPSTONE_DIET)
2016-04-23 22:51:24 +00:00
# if !defined(CAPSTONE_HAS_OSXKERNEL) && !defined(CAPSTONE_DIET) && !defined(_KERNEL_MODE)
2014-03-06 01:13:04 +00:00
# define INSN_CACHE_SIZE 32
2014-03-05 19:36:03 +00:00
# else
2014-03-07 00:40:35 +00:00
// reduce stack variable size for kernel/firmware
2014-03-05 19:36:03 +00:00
# define INSN_CACHE_SIZE 8
# endif
2014-01-22 01:46:42 +00:00
2014-04-09 15:49:30 +00:00
// default SKIPDATA mnemonic
2017-05-24 05:07:11 +00:00
# ifndef CAPSTONE_DIET
2014-04-10 02:26:49 +00:00
# define SKIPDATA_MNEM ".byte"
2017-05-24 05:07:11 +00:00
# else // No printing is available in diet mode
# define SKIPDATA_MNEM NULL
# endif
2014-04-09 15:49:30 +00:00
2018-06-21 06:52:35 +00:00
# include "arch/AArch64/AArch64Module.h"
# include "arch/ARM/ARMModule.h"
2018-06-24 13:05:04 +00:00
# include "arch/EVM/EVMModule.h"
2019-02-01 15:03:47 +00:00
# include "arch/WASM/WASMModule.h"
2018-06-24 13:05:04 +00:00
# include "arch/M680X/M680XModule.h"
# include "arch/M68K/M68KModule.h"
2018-06-21 06:52:35 +00:00
# include "arch/Mips/MipsModule.h"
# include "arch/PowerPC/PPCModule.h"
# include "arch/Sparc/SparcModule.h"
# include "arch/SystemZ/SystemZModule.h"
2018-06-24 13:05:04 +00:00
# include "arch/TMS320C64x/TMS320C64xModule.h"
2018-06-21 06:52:35 +00:00
# include "arch/X86/X86Module.h"
# include "arch/XCore/XCoreModule.h"
2018-12-02 20:39:41 +00:00
# include "arch/MOS65XX/MOS65XXModule.h"
2019-02-18 09:39:51 +00:00
# include "arch/BPF/BPFModule.h"
2014-01-19 04:03:22 +00:00
2018-06-21 17:03:26 +00:00
// constructor initialization for all archs
static cs_err ( * cs_arch_init [ MAX_ARCH ] ) ( cs_struct * ) = {
2014-01-09 05:22:56 +00:00
# ifdef CAPSTONE_HAS_ARM
2018-06-21 06:52:35 +00:00
ARM_global_init ,
# else
NULL ,
2014-01-09 05:22:56 +00:00
# endif
# ifdef CAPSTONE_HAS_ARM64
2018-06-21 06:52:35 +00:00
AArch64_global_init ,
# else
NULL ,
2014-01-09 05:22:56 +00:00
# endif
# ifdef CAPSTONE_HAS_MIPS
2018-06-21 06:52:35 +00:00
Mips_global_init ,
# else
NULL ,
# endif
# ifdef CAPSTONE_HAS_X86
X86_global_init ,
# else
NULL ,
2014-01-09 05:22:56 +00:00
# endif
# ifdef CAPSTONE_HAS_POWERPC
2018-06-21 06:52:35 +00:00
PPC_global_init ,
# else
NULL ,
2014-01-09 05:22:56 +00:00
# endif
2014-03-10 03:58:57 +00:00
# ifdef CAPSTONE_HAS_SPARC
2018-06-21 06:52:35 +00:00
Sparc_global_init ,
# else
NULL ,
2014-03-10 03:58:57 +00:00
# endif
2014-03-23 00:35:45 +00:00
# ifdef CAPSTONE_HAS_SYSZ
2018-06-21 06:52:35 +00:00
SystemZ_global_init ,
# else
NULL ,
# endif
# ifdef CAPSTONE_HAS_XCORE
XCore_global_init ,
# else
NULL ,
# endif
2015-08-03 16:45:08 +00:00
# ifdef CAPSTONE_HAS_M68K
2018-06-24 13:05:04 +00:00
M68K_global_init ,
# else
NULL ,
# endif
# ifdef CAPSTONE_HAS_TMS320C64X
TMS320C64x_global_init ,
# else
NULL ,
# endif
# ifdef CAPSTONE_HAS_M680X
M680X_global_init ,
# else
NULL ,
# endif
# ifdef CAPSTONE_HAS_EVM
EVM_global_init ,
# else
NULL ,
# endif
2019-02-02 15:27:54 +00:00
# ifdef CAPSTONE_HAS_MOS65XX
MOS65XX_global_init ,
2019-02-01 15:03:47 +00:00
# else
NULL ,
# endif
2019-02-02 15:27:54 +00:00
# ifdef CAPSTONE_HAS_WASM
WASM_global_init ,
2018-12-02 20:39:41 +00:00
# else
NULL ,
# endif
2019-02-18 09:39:51 +00:00
# ifdef CAPSTONE_HAS_BPF
BPF_global_init ,
# else
NULL ,
# endif
2018-06-21 06:52:35 +00:00
} ;
2018-06-21 17:03:26 +00:00
// support cs_option() for all archs
static cs_err ( * cs_arch_option [ MAX_ARCH ] ) ( cs_struct * , cs_opt_type , size_t value ) = {
2018-06-21 06:52:35 +00:00
# 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 ,
2014-03-23 00:35:45 +00:00
# endif
2014-03-10 03:58:57 +00:00
# ifdef CAPSTONE_HAS_X86
2018-06-21 06:52:35 +00:00
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 ,
2014-03-10 03:58:57 +00:00
# endif
2014-05-26 15:02:48 +00:00
# ifdef CAPSTONE_HAS_XCORE
2018-06-21 06:52:35 +00:00
XCore_option ,
# else
NULL ,
2014-05-26 15:02:48 +00:00
# endif
2018-06-24 13:05:04 +00:00
# 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
2019-02-18 16:10:36 +00:00
# ifdef CAPSTONE_HAS_MOS65XX
MOS65XX_option ,
2019-02-01 15:03:47 +00:00
# else
NULL ,
# endif
2019-02-18 16:10:36 +00:00
# ifdef CAPSTONE_HAS_WASM
WASM_option ,
2018-12-02 20:39:41 +00:00
# else
NULL ,
# endif
2019-02-18 09:39:51 +00:00
# ifdef CAPSTONE_HAS_BPF
BPF_option ,
# else
NULL ,
# endif
2018-06-21 06:52:35 +00:00
} ;
2014-05-26 15:02:48 +00:00
2018-06-21 17:03:26 +00:00
// bitmask for finding disallowed modes for an arch:
// to be called in cs_open()/cs_option()
2018-06-24 13:05:04 +00:00
static cs_mode cs_arch_disallowed_mode_mask [ MAX_ARCH ] = {
2018-06-21 06:52:35 +00:00
# ifdef CAPSTONE_HAS_ARM
2018-06-24 13:05:04 +00:00
~ ( CS_MODE_LITTLE_ENDIAN | CS_MODE_ARM | CS_MODE_V8 | CS_MODE_MCLASS
| CS_MODE_THUMB | CS_MODE_BIG_ENDIAN ) ,
2018-06-21 06:52:35 +00:00
# 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
2018-06-24 13:05:04 +00:00
~ ( 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 ) ,
2018-06-21 06:52:35 +00:00
# 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
2018-06-24 13:05:04 +00:00
~ ( CS_MODE_LITTLE_ENDIAN | CS_MODE_32 | CS_MODE_64 | CS_MODE_BIG_ENDIAN
| CS_MODE_QPX ) ,
2018-06-21 06:52:35 +00:00
# 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
2018-06-24 13:05:04 +00:00
# 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 ,
2014-05-26 15:02:48 +00:00
# endif
2016-05-03 12:52:11 +00:00
# ifdef CAPSTONE_HAS_TMS320C64X
2018-06-24 13:05:04 +00:00
~ ( 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 ,
2016-05-03 12:52:11 +00:00
# endif
2018-03-31 09:29:22 +00:00
# ifdef CAPSTONE_HAS_EVM
2018-06-24 13:05:04 +00:00
0 ,
# else
0 ,
2018-03-31 09:29:22 +00:00
# endif
2018-12-02 20:39:41 +00:00
# ifdef CAPSTONE_HAS_MOS65XX
~ ( CS_MODE_BIG_ENDIAN ) ,
# else
0 ,
# endif
2019-02-18 16:10:36 +00:00
# ifdef CAPSTONE_HAS_WASM
0 ,
# else
0 ,
# endif
2019-02-18 09:39:51 +00:00
# ifdef CAPSTONE_HAS_BPF
~ ( CS_MODE_LITTLE_ENDIAN | CS_MODE_BPF_CLASSIC | CS_MODE_BPF_EXTENDED
| CS_MODE_BIG_ENDIAN ) ,
# else
0 ,
# endif
2018-06-21 06:52:35 +00:00
} ;
2014-01-09 05:22:56 +00:00
2018-06-24 13:05:04 +00:00
// bitmask of enabled architectures
static uint32_t all_arch = 0
2018-06-21 06:52:35 +00:00
# ifdef CAPSTONE_HAS_ARM
2018-06-24 13:05:04 +00:00
| ( 1 < < CS_ARCH_ARM )
2018-06-21 06:52:35 +00:00
# endif
# ifdef CAPSTONE_HAS_ARM64
2018-06-24 13:05:04 +00:00
| ( 1 < < CS_ARCH_ARM64 )
2018-06-21 06:52:35 +00:00
# endif
# ifdef CAPSTONE_HAS_MIPS
2018-06-24 13:05:04 +00:00
| ( 1 < < CS_ARCH_MIPS )
2018-06-21 06:52:35 +00:00
# endif
# ifdef CAPSTONE_HAS_X86
2018-06-24 13:05:04 +00:00
| ( 1 < < CS_ARCH_X86 )
2018-06-21 06:52:35 +00:00
# endif
# ifdef CAPSTONE_HAS_POWERPC
2018-06-24 13:05:04 +00:00
| ( 1 < < CS_ARCH_PPC )
2018-06-21 06:52:35 +00:00
# endif
# ifdef CAPSTONE_HAS_SPARC
2018-06-24 13:05:04 +00:00
| ( 1 < < CS_ARCH_SPARC )
2018-06-21 06:52:35 +00:00
# endif
# ifdef CAPSTONE_HAS_SYSZ
2018-06-24 13:05:04 +00:00
| ( 1 < < CS_ARCH_SYSZ )
2018-06-21 06:52:35 +00:00
# endif
# ifdef CAPSTONE_HAS_XCORE
2018-06-24 13:05:04 +00:00
| ( 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 )
2018-06-21 06:52:35 +00:00
# endif
2019-02-18 16:10:36 +00:00
# ifdef CAPSTONE_HAS_MOS65XX
| ( 1 < < CS_ARCH_MOS65XX )
# endif
2019-02-01 15:03:47 +00:00
# ifdef CAPSTONE_HAS_WASM
| ( 1 < < CS_ARCH_WASM )
# endif
2019-02-18 09:39:51 +00:00
# ifdef CAPSTONE_HAS_BPF
2019-02-18 16:10:36 +00:00
| ( 1 < < CS_ARCH_BPF )
2019-02-18 09:39:51 +00:00
# endif
2018-06-21 06:52:35 +00:00
;
2013-12-21 04:16:47 +00:00
2016-04-23 22:51:24 +00:00
# if defined(CAPSTONE_USE_SYS_DYN_MEM)
# if !defined(CAPSTONE_HAS_OSXKERNEL) && !defined(_KERNEL_MODE)
2016-05-12 05:52:34 +00:00
// default
2014-01-11 04:55:31 +00:00
cs_malloc_t cs_mem_malloc = malloc ;
cs_calloc_t cs_mem_calloc = calloc ;
cs_realloc_t cs_mem_realloc = realloc ;
cs_free_t cs_mem_free = free ;
2016-04-12 07:25:37 +00:00
# if defined(_WIN32_WCE)
cs_vsnprintf_t cs_vsnprintf = _vsnprintf ;
2016-05-12 05:52:34 +00:00
# else
2014-01-15 12:44:03 +00:00
cs_vsnprintf_t cs_vsnprintf = vsnprintf ;
2016-05-12 05:52:34 +00:00
# endif // defined(_WIN32_WCE)
2016-04-23 22:51:24 +00:00
# elif defined(_KERNEL_MODE)
2016-05-12 05:52:34 +00:00
// Windows driver
2016-04-23 22:51:24 +00:00
cs_malloc_t cs_mem_malloc = cs_winkernel_malloc ;
cs_calloc_t cs_mem_calloc = cs_winkernel_calloc ;
cs_realloc_t cs_mem_realloc = cs_winkernel_realloc ;
cs_free_t cs_mem_free = cs_winkernel_free ;
cs_vsnprintf_t cs_vsnprintf = cs_winkernel_vsnprintf ;
2014-01-05 15:41:31 +00:00
# else
2016-05-12 05:52:34 +00:00
// OSX kernel
2015-11-10 22:02:26 +00:00
extern void * kern_os_malloc ( size_t size ) ;
extern void kern_os_free ( void * addr ) ;
extern void * kern_os_realloc ( void * addr , size_t nsize ) ;
static void * cs_kern_os_calloc ( size_t num , size_t size )
{
return kern_os_malloc ( num * size ) ; // malloc bzeroes the buffer
}
cs_malloc_t cs_mem_malloc = kern_os_malloc ;
cs_calloc_t cs_mem_calloc = cs_kern_os_calloc ;
cs_realloc_t cs_mem_realloc = kern_os_realloc ;
cs_free_t cs_mem_free = kern_os_free ;
cs_vsnprintf_t cs_vsnprintf = vsnprintf ;
2016-05-12 05:52:34 +00:00
# endif // !defined(CAPSTONE_HAS_OSXKERNEL) && !defined(_KERNEL_MODE)
2015-11-10 22:02:26 +00:00
# else
2016-05-12 05:52:34 +00:00
// User-defined
2014-01-11 04:55:31 +00:00
cs_malloc_t cs_mem_malloc = NULL ;
cs_calloc_t cs_mem_calloc = NULL ;
cs_realloc_t cs_mem_realloc = NULL ;
cs_free_t cs_mem_free = NULL ;
2014-01-15 12:44:03 +00:00
cs_vsnprintf_t cs_vsnprintf = NULL ;
2016-05-12 05:52:34 +00:00
# endif // defined(CAPSTONE_USE_SYS_DYN_MEM)
2013-12-22 07:20:07 +00:00
2014-06-03 10:33:15 +00:00
CAPSTONE_EXPORT
2016-04-01 01:14:43 +00:00
unsigned int CAPSTONE_API cs_version ( int * major , int * minor )
2013-12-10 05:31:20 +00:00
{
2013-12-22 06:16:28 +00:00
if ( major ! = NULL & & minor ! = NULL ) {
* major = CS_API_MAJOR ;
* minor = CS_API_MINOR ;
}
2013-12-22 02:40:58 +00:00
return ( CS_API_MAJOR < < 8 ) + CS_API_MINOR ;
}
2014-06-03 10:33:15 +00:00
CAPSTONE_EXPORT
2016-04-01 01:14:43 +00:00
bool CAPSTONE_API cs_support ( int query )
2013-12-22 02:40:58 +00:00
{
2014-02-22 15:41:16 +00:00
if ( query = = CS_ARCH_ALL )
2013-12-22 02:40:58 +00:00
return all_arch = = ( ( 1 < < CS_ARCH_ARM ) | ( 1 < < CS_ARCH_ARM64 ) |
2013-12-29 16:15:25 +00:00
( 1 < < CS_ARCH_MIPS ) | ( 1 < < CS_ARCH_X86 ) |
2014-03-23 00:35:45 +00:00
( 1 < < CS_ARCH_PPC ) | ( 1 < < CS_ARCH_SPARC ) |
2016-05-03 12:52:11 +00:00
( 1 < < CS_ARCH_SYSZ ) | ( 1 < < CS_ARCH_XCORE ) |
M680X: Target ready for pull request (#1034)
* Added new M680X target. Supports M6800/1/2/3/9, HD6301
* M680X: Reformat for coding guide lines. Set alphabetical order in HACK.TXT
* M680X: Prepare for python binding. Move cs_m680x, m680x_insn to m680x_info. Chec
> k cpu type, no default.
* M680X: Add python bindings. Added python tests.
* M680X: Added cpu types to usage message.
* cstool: Avoid segfault for invalid <arch+mode>.
* Make test_m680x.c/test_m680x.py output comparable (diff params: -bu). Keep xprint.py untouched.
* M680X: Update CMake/make for m680x support. Update .gitignore.
* M680X: Reduce compiler warnings.
* M680X: Reduce compiler warnings.
* M680X: Reduce compiler warnings.
* M680X: Make test_m680x.c/test_m680x.py output comparable (diff params: -bu).
* M680X: Add ocaml bindings and tests.
* M680X: Add java bindings and tests.
* M680X: Added tests for all indexed addressing modes. C/Python/Ocaml
* M680X: Naming, use page1 for PAGE1 instructions (without prefix).
* M680X: Naming, use page1 for PAGE1 instructions (without prefix).
* M680X: Used M680X_FIRST_OP_IN_MNEM in tests C/python/java/ocaml.
* M680X: Added access property to cs_m680x_op.
* M680X: Added operand size.
* M680X: Remove compiler warnings.
* M680X: Added READ/WRITE access property per operator.
* M680X: Make reg_inherent_hdlr independent of CPU type.
* M680X: Add HD6309 support + bug fixes
* M680X: Remove errors and warning.
* M680X: Add Bcc/LBcc to group BRAREL (relative branch).
* M680X: Add group JUMP to BVS/BVC/LBVS/LBVC. Remove BRAREL from BRN/LBRN.
* M680X: Remove LBRN from group BRAREL.
* M680X: Refactored cpu_type initialization for better readability.
* M680X: Add two operands for insn having two reg. in mnemonic. e.g. ABX.
* M680X: Remove typo in cstool.c
* M680X: Some format improvements in changed_regs.
* M680X: Remove insn id string list from tests (C/python/java/ocaml).
* M680X: SEXW, set access of reg. D to WRITE.
* M680X: Sort changed_regs in increasing m680x_insn order.
* M680X: Add M68HC11 support + Reduced from two to one INDEXED operand.
* M680X: cstool, also write '(in mnemonic)' for second reg. operand.
* M680X: Add BRN/LBRN to group JUMP and BRAREL.
* M680X: For Bcc/LBcc/BRSET/BRCLR set reg. CC to read access.
* M680X: Correctly print negative immediate values with option CS_OPT_UNSIGNED.
* M680X: Rename some instruction handlers.
* M680X: Add M68HC05 support.
* M680X: Dont print prefix '<' for direct addr. mode.
* M680X: Add M68HC08 support + resorted tables + bug fixes.
* M680X: Add Freescale HCS08 support.
* M680X: Changed group names, avoid spaces.
* M680X: Refactoring, rename addessing mode handlers.
* M680X: indexed addr. mode, changed pre/post inc-/decrement representation.
* M680X: Rename some M6809/HD6309 specific functions.
* M680X: Add CPU12 (68HC12/HCS12) support.
* M680X: Correctly display illegal instruction as FCB .
* M680X: bugfix: BRA/BRN/BSR/LBRA/LBRN/LBSR does not read CC reg.
* M680X: bugfix: Correctly check for sufficient code size for M6809 indexed addressing.
* M680X: Better support for changing insn id within handler for addessing mode.
* M680X: Remove warnings.
* M680X: In set_changed_regs_read_write_counts use own access_mode.
* M680X: Split cpu specific tables into separate *.inc files.
* M680X: Remove warnings.
* M680X: Removed address_mode. Addressing mode is available in operand.type
* M680X: Bugfix: BSET/BCLR/BRSET/BRCLR correct read/modify CC reg.
* M680X: Remove register TMP1. It is first visible in CPU12X.
* M680X: Performance improvement + bug fixes.
* M680X: Performance improvement, make cpu_tables const static.
* M680X: Simplify operand decoding by using two handlers.
* M680X: Replace M680X_OP_INDEX by M680X_OP_CONSTANT + bugfix in java/python/ocaml bindings.
* M680X: Format with astyle.
* M680X: Update documentation.
* M680X: Corrected author for m680x specific files.
* M680X: Make max. number of architectures single source.
2017-10-21 13:44:36 +00:00
( 1 < < CS_ARCH_M68K ) | ( 1 < < CS_ARCH_TMS320C64X ) |
2018-12-02 20:39:41 +00:00
( 1 < < CS_ARCH_M680X ) | ( 1 < < CS_ARCH_EVM ) |
2019-02-18 09:39:51 +00:00
( 1 < < CS_ARCH_MOS65XX ) | ( 1 < < CS_ARCH_WASM ) |
( 1 < < CS_ARCH_BPF ) ) ;
2013-12-22 02:40:58 +00:00
2014-02-27 05:54:28 +00:00
if ( ( unsigned int ) query < CS_ARCH_MAX )
2014-02-22 15:41:16 +00:00
return all_arch & ( 1 < < query ) ;
if ( query = = CS_SUPPORT_DIET ) {
# ifdef CAPSTONE_DIET
return true ;
# else
return false ;
# endif
}
2014-03-27 02:54:44 +00:00
if ( query = = CS_SUPPORT_X86_REDUCE ) {
# if defined(CAPSTONE_HAS_X86) && defined(CAPSTONE_X86_REDUCE)
2014-03-25 15:20:41 +00:00
return true ;
# else
return false ;
# endif
}
2014-02-22 15:41:16 +00:00
// unsupported query
return false ;
2013-12-10 05:31:20 +00:00
}
2014-06-03 10:33:15 +00:00
CAPSTONE_EXPORT
2016-04-01 01:14:43 +00:00
cs_err CAPSTONE_API cs_errno ( csh handle )
2013-11-27 04:11:31 +00:00
{
2014-05-12 05:41:49 +00:00
struct cs_struct * ud ;
2013-11-27 04:11:31 +00:00
if ( ! handle )
return CS_ERR_CSH ;
2014-05-08 22:44:49 +00:00
ud = ( struct cs_struct * ) ( uintptr_t ) handle ;
2013-11-27 04:11:31 +00:00
2013-11-27 07:24:47 +00:00
return ud - > errnum ;
2013-11-27 04:11:31 +00:00
}
2014-06-03 10:33:15 +00:00
CAPSTONE_EXPORT
2016-04-01 01:14:43 +00:00
const char * CAPSTONE_API cs_strerror ( cs_err code )
2014-01-03 14:49:07 +00:00
{
switch ( code ) {
default :
return " Unknown error code " ;
case CS_ERR_OK :
return " OK (CS_ERR_OK) " ;
case CS_ERR_MEM :
return " Out of memory (CS_ERR_MEM) " ;
case CS_ERR_ARCH :
2015-03-25 07:02:13 +00:00
return " Invalid/unsupported architecture(CS_ERR_ARCH) " ;
2014-01-03 14:49:07 +00:00
case CS_ERR_HANDLE :
return " Invalid handle (CS_ERR_HANDLE) " ;
case CS_ERR_CSH :
return " Invalid csh (CS_ERR_CSH) " ;
case CS_ERR_MODE :
return " Invalid mode (CS_ERR_MODE) " ;
case CS_ERR_OPTION :
return " Invalid option (CS_ERR_OPTION) " ;
case CS_ERR_DETAIL :
return " Details are unavailable (CS_ERR_DETAIL) " ;
2014-01-06 01:06:30 +00:00
case CS_ERR_MEMSETUP :
return " Dynamic memory management uninitialized (CS_ERR_MEMSETUP) " ;
2014-02-08 16:19:15 +00:00
case CS_ERR_VERSION :
return " Different API version between core & binding (CS_ERR_VERSION) " ;
2014-02-24 08:47:36 +00:00
case CS_ERR_DIET :
return " Information irrelevant in diet engine (CS_ERR_DIET) " ;
2014-04-10 09:20:01 +00:00
case CS_ERR_SKIPDATA :
return " Information irrelevant for 'data' instruction in SKIPDATA mode (CS_ERR_SKIPDATA) " ;
2015-08-09 17:52:18 +00:00
case CS_ERR_X86_ATT :
return " AT&T syntax is unavailable (CS_ERR_X86_ATT) " ;
case CS_ERR_X86_INTEL :
return " INTEL syntax is unavailable (CS_ERR_X86_INTEL) " ;
case CS_ERR_X86_MASM :
return " MASM syntax is unavailable (CS_ERR_X86_MASM) " ;
2014-01-03 14:49:07 +00:00
}
}
2014-06-03 10:33:15 +00:00
CAPSTONE_EXPORT
2016-04-01 01:14:43 +00:00
cs_err CAPSTONE_API cs_open ( cs_arch arch , cs_mode mode , csh * handle )
2013-11-27 04:11:31 +00:00
{
2014-05-08 23:33:35 +00:00
cs_err err ;
2014-05-12 05:41:49 +00:00
struct cs_struct * ud ;
2014-01-15 12:44:03 +00:00
if ( ! cs_mem_malloc | | ! cs_mem_calloc | | ! cs_mem_realloc | | ! cs_mem_free | | ! cs_vsnprintf )
2014-01-06 01:06:30 +00:00
// Error: before cs_open(), dynamic memory management must be initialized
// with cs_option(CS_OPT_MEM)
return CS_ERR_MEMSETUP ;
2018-03-19 14:23:09 +00:00
if ( arch < CS_ARCH_MAX & & cs_arch_init [ arch ] ) {
2017-10-20 15:33:24 +00:00
// verify if requested mode is valid
2018-03-19 14:23:09 +00:00
if ( mode & cs_arch_disallowed_mode_mask [ arch ] ) {
2017-10-20 15:33:24 +00:00
* handle = 0 ;
return CS_ERR_MODE ;
}
2014-01-11 04:55:31 +00:00
ud = cs_mem_calloc ( 1 , sizeof ( * ud ) ) ;
2014-01-06 01:52:57 +00:00
if ( ! ud ) {
// memory insufficient
return CS_ERR_MEM ;
}
2013-11-27 04:11:31 +00:00
2013-12-22 05:41:38 +00:00
ud - > errnum = CS_ERR_OK ;
ud - > arch = arch ;
ud - > mode = mode ;
2014-01-07 15:36:26 +00:00
// by default, do not break instruction into details
ud - > detail = CS_OPT_OFF ;
2013-12-22 05:41:38 +00:00
2014-04-09 15:49:30 +00:00
// default skipdata setup
ud - > skipdata_setup . mnemonic = SKIPDATA_MNEM ;
2018-03-19 14:23:09 +00:00
err = cs_arch_init [ ud - > arch ] ( ud ) ;
2014-01-21 07:26:02 +00:00
if ( err ) {
cs_mem_free ( ud ) ;
* handle = 0 ;
return err ;
}
2014-01-06 01:52:57 +00:00
* handle = ( uintptr_t ) ud ;
return CS_ERR_OK ;
2013-12-22 05:41:38 +00:00
} else {
* handle = 0 ;
return CS_ERR_ARCH ;
}
2013-11-27 04:11:31 +00:00
}
2014-06-03 10:33:15 +00:00
CAPSTONE_EXPORT
2016-04-01 01:14:43 +00:00
cs_err CAPSTONE_API cs_close ( csh * handle )
2013-11-27 04:11:31 +00:00
{
2014-05-12 05:41:49 +00:00
struct cs_struct * ud ;
2015-04-26 14:54:41 +00:00
struct insn_mnem * next , * tmp ;
2014-05-12 05:41:49 +00:00
2014-02-27 15:42:49 +00:00
if ( * handle = = 0 )
2014-02-27 14:20:39 +00:00
// invalid handle
2013-11-27 04:11:31 +00:00
return CS_ERR_CSH ;
2014-05-08 22:44:49 +00:00
ud = ( struct cs_struct * ) ( * handle ) ;
2013-11-27 04:11:31 +00:00
2014-02-27 15:59:08 +00:00
if ( ud - > printer_info )
cs_mem_free ( ud - > printer_info ) ;
2013-11-27 04:11:31 +00:00
2015-04-26 14:54:41 +00:00
// free the linked list of customized mnemonic
tmp = ud - > mnem_list ;
while ( tmp ) {
next = tmp - > next ;
cs_mem_free ( tmp ) ;
tmp = next ;
}
2014-01-11 04:55:31 +00:00
cs_mem_free ( ud - > insn_cache ) ;
2014-10-10 16:36:16 +00:00
2014-01-03 13:51:59 +00:00
memset ( ud , 0 , sizeof ( * ud ) ) ;
2014-01-11 04:55:31 +00:00
cs_mem_free ( ud ) ;
2014-01-03 13:51:59 +00:00
2014-02-28 01:38:11 +00:00
// invalidate this handle by ZERO out its value.
// this is to make sure it is unusable after cs_close()
2014-02-27 14:20:39 +00:00
* handle = 0 ;
2013-11-27 04:11:31 +00:00
return CS_ERR_OK ;
}
// fill insn with mnemonic & operands info
2014-01-23 15:42:40 +00:00
static void fill_insn ( struct cs_struct * handle , cs_insn * insn , char * buffer , MCInst * mci ,
2013-12-24 08:49:36 +00:00
PostPrinter_t postprinter , const uint8_t * code )
2013-11-27 04:11:31 +00:00
{
2014-05-13 23:32:56 +00:00
# ifndef CAPSTONE_DIET
2014-06-08 16:35:52 +00:00
char * sp , * mnem ;
2014-05-13 23:32:56 +00:00
# endif
2016-05-04 12:54:28 +00:00
uint16_t copy_size = MIN ( sizeof ( insn - > bytes ) , insn - > size ) ;
2013-11-27 04:11:31 +00:00
2014-10-30 12:34:22 +00:00
// fill the instruction bytes.
// we might skip some redundant bytes in front in the case of X86
memcpy ( insn - > bytes , code + insn - > size - copy_size , copy_size ) ;
insn - > size = copy_size ;
2013-12-24 08:49:36 +00:00
2013-12-14 02:45:09 +00:00
// alias instruction might have ID saved in OpcodePub
if ( MCInst_getOpcodePub ( mci ) )
insn - > id = MCInst_getOpcodePub ( mci ) ;
// post printer handles some corner cases (hacky)
2013-12-24 08:49:36 +00:00
if ( postprinter )
2014-05-19 08:46:31 +00:00
postprinter ( ( csh ) handle , insn , buffer , mci ) ;
2013-12-14 02:45:09 +00:00
2014-02-22 15:26:27 +00:00
# ifndef CAPSTONE_DIET
2013-11-27 04:11:31 +00:00
// fill in mnemonic & operands
2013-12-12 06:00:12 +00:00
// find first space or tab
2014-06-08 14:09:31 +00:00
mnem = insn - > mnemonic ;
2014-07-02 04:22:39 +00:00
for ( sp = buffer ; * sp ; sp + + ) {
if ( * sp = = ' ' | | * sp = = ' \t ' )
break ;
if ( * sp = = ' | ' ) // lock|rep prefix for x86
* sp = ' ' ;
// copy to @mnemonic
* mnem = * sp ;
mnem + + ;
2014-05-07 00:25:24 +00:00
}
2014-06-08 14:09:31 +00:00
* mnem = ' \0 ' ;
2015-04-26 14:54:41 +00:00
// we might have customized mnemonic
if ( handle - > mnem_list ) {
struct insn_mnem * tmp = handle - > mnem_list ;
while ( tmp ) {
if ( tmp - > insn . id = = insn - > id ) {
// found this instruction, so copy its mnemonic
( void ) strncpy ( insn - > mnemonic , tmp - > insn . mnemonic , sizeof ( insn - > mnemonic ) - 1 ) ;
insn - > mnemonic [ sizeof ( insn - > mnemonic ) - 1 ] = ' \0 ' ;
break ;
}
tmp = tmp - > next ;
}
}
2014-06-08 14:09:31 +00:00
// copy @op_str
2013-12-12 06:00:12 +00:00
if ( * sp ) {
2013-12-12 06:43:39 +00:00
// find the next non-space char
sp + + ;
for ( ; ( ( * sp = = ' ' ) | | ( * sp = = ' \t ' ) ) ; sp + + ) ;
strncpy ( insn - > op_str , sp , sizeof ( insn - > op_str ) - 1 ) ;
2013-11-27 04:11:31 +00:00
insn - > op_str [ sizeof ( insn - > op_str ) - 1 ] = ' \0 ' ;
} else
insn - > op_str [ 0 ] = ' \0 ' ;
2014-02-22 15:26:27 +00:00
# endif
2013-11-27 04:11:31 +00:00
}
2014-04-09 15:49:30 +00:00
// how many bytes will we skip when encountering data (CS_OPT_SKIPDATA)?
2014-04-10 03:53:46 +00:00
// this very much depends on instruction alignment requirement of each arch.
2014-04-09 15:49:30 +00:00
static uint8_t skipdata_size ( cs_struct * handle )
{
switch ( handle - > arch ) {
default :
// should never reach
2016-05-14 23:04:28 +00:00
return ( uint8_t ) - 1 ;
2014-04-09 15:49:30 +00:00
case CS_ARCH_ARM :
2014-04-10 03:53:46 +00:00
// skip 2 bytes on Thumb mode.
if ( handle - > mode & CS_MODE_THUMB )
return 2 ;
// otherwise, skip 4 bytes
return 4 ;
2014-04-09 15:49:30 +00:00
case CS_ARCH_ARM64 :
case CS_ARCH_MIPS :
case CS_ARCH_PPC :
case CS_ARCH_SPARC :
2014-04-10 03:53:46 +00:00
// skip 4 bytes
return 4 ;
2014-04-09 15:49:30 +00:00
case CS_ARCH_SYSZ :
2014-04-10 03:53:46 +00:00
// SystemZ instruction's length can be 2, 4 or 6 bytes,
// so we just skip 2 bytes
2014-04-09 15:49:30 +00:00
return 2 ;
case CS_ARCH_X86 :
// X86 has no restriction on instruction alignment
return 1 ;
2014-05-26 15:02:48 +00:00
case CS_ARCH_XCORE :
// XCore instruction's length can be 2 or 4 bytes,
// so we just skip 2 bytes
return 2 ;
2015-08-03 16:45:08 +00:00
case CS_ARCH_M68K :
// M68K has 2 bytes instruction alignment but contain multibyte instruction so we skip 2 bytes
return 2 ;
2016-05-03 12:52:11 +00:00
case CS_ARCH_TMS320C64X :
// TMS320C64x alignment is 4.
return 4 ;
M680X: Target ready for pull request (#1034)
* Added new M680X target. Supports M6800/1/2/3/9, HD6301
* M680X: Reformat for coding guide lines. Set alphabetical order in HACK.TXT
* M680X: Prepare for python binding. Move cs_m680x, m680x_insn to m680x_info. Chec
> k cpu type, no default.
* M680X: Add python bindings. Added python tests.
* M680X: Added cpu types to usage message.
* cstool: Avoid segfault for invalid <arch+mode>.
* Make test_m680x.c/test_m680x.py output comparable (diff params: -bu). Keep xprint.py untouched.
* M680X: Update CMake/make for m680x support. Update .gitignore.
* M680X: Reduce compiler warnings.
* M680X: Reduce compiler warnings.
* M680X: Reduce compiler warnings.
* M680X: Make test_m680x.c/test_m680x.py output comparable (diff params: -bu).
* M680X: Add ocaml bindings and tests.
* M680X: Add java bindings and tests.
* M680X: Added tests for all indexed addressing modes. C/Python/Ocaml
* M680X: Naming, use page1 for PAGE1 instructions (without prefix).
* M680X: Naming, use page1 for PAGE1 instructions (without prefix).
* M680X: Used M680X_FIRST_OP_IN_MNEM in tests C/python/java/ocaml.
* M680X: Added access property to cs_m680x_op.
* M680X: Added operand size.
* M680X: Remove compiler warnings.
* M680X: Added READ/WRITE access property per operator.
* M680X: Make reg_inherent_hdlr independent of CPU type.
* M680X: Add HD6309 support + bug fixes
* M680X: Remove errors and warning.
* M680X: Add Bcc/LBcc to group BRAREL (relative branch).
* M680X: Add group JUMP to BVS/BVC/LBVS/LBVC. Remove BRAREL from BRN/LBRN.
* M680X: Remove LBRN from group BRAREL.
* M680X: Refactored cpu_type initialization for better readability.
* M680X: Add two operands for insn having two reg. in mnemonic. e.g. ABX.
* M680X: Remove typo in cstool.c
* M680X: Some format improvements in changed_regs.
* M680X: Remove insn id string list from tests (C/python/java/ocaml).
* M680X: SEXW, set access of reg. D to WRITE.
* M680X: Sort changed_regs in increasing m680x_insn order.
* M680X: Add M68HC11 support + Reduced from two to one INDEXED operand.
* M680X: cstool, also write '(in mnemonic)' for second reg. operand.
* M680X: Add BRN/LBRN to group JUMP and BRAREL.
* M680X: For Bcc/LBcc/BRSET/BRCLR set reg. CC to read access.
* M680X: Correctly print negative immediate values with option CS_OPT_UNSIGNED.
* M680X: Rename some instruction handlers.
* M680X: Add M68HC05 support.
* M680X: Dont print prefix '<' for direct addr. mode.
* M680X: Add M68HC08 support + resorted tables + bug fixes.
* M680X: Add Freescale HCS08 support.
* M680X: Changed group names, avoid spaces.
* M680X: Refactoring, rename addessing mode handlers.
* M680X: indexed addr. mode, changed pre/post inc-/decrement representation.
* M680X: Rename some M6809/HD6309 specific functions.
* M680X: Add CPU12 (68HC12/HCS12) support.
* M680X: Correctly display illegal instruction as FCB .
* M680X: bugfix: BRA/BRN/BSR/LBRA/LBRN/LBSR does not read CC reg.
* M680X: bugfix: Correctly check for sufficient code size for M6809 indexed addressing.
* M680X: Better support for changing insn id within handler for addessing mode.
* M680X: Remove warnings.
* M680X: In set_changed_regs_read_write_counts use own access_mode.
* M680X: Split cpu specific tables into separate *.inc files.
* M680X: Remove warnings.
* M680X: Removed address_mode. Addressing mode is available in operand.type
* M680X: Bugfix: BSET/BCLR/BRSET/BRCLR correct read/modify CC reg.
* M680X: Remove register TMP1. It is first visible in CPU12X.
* M680X: Performance improvement + bug fixes.
* M680X: Performance improvement, make cpu_tables const static.
* M680X: Simplify operand decoding by using two handlers.
* M680X: Replace M680X_OP_INDEX by M680X_OP_CONSTANT + bugfix in java/python/ocaml bindings.
* M680X: Format with astyle.
* M680X: Update documentation.
* M680X: Corrected author for m680x specific files.
* M680X: Make max. number of architectures single source.
2017-10-21 13:44:36 +00:00
case CS_ARCH_M680X :
// M680X alignment is 1.
return 1 ;
2018-03-31 09:29:22 +00:00
case CS_ARCH_EVM :
// EVM alignment is 1.
return 1 ;
2019-02-01 15:03:47 +00:00
case CS_ARCH_WASM :
//WASM alignment is 1
return 1 ;
2018-12-02 20:39:41 +00:00
case CS_ARCH_MOS65XX :
// MOS65XX alignment is 1.
return 1 ;
2019-02-18 09:39:51 +00:00
case CS_ARCH_BPF :
// both classic and extended BPF have alignment 8.
return 8 ;
2014-04-09 15:49:30 +00:00
}
}
2014-06-03 10:33:15 +00:00
CAPSTONE_EXPORT
2016-04-01 01:14:43 +00:00
cs_err CAPSTONE_API cs_option ( csh ud , cs_opt_type type , size_t value )
2013-12-03 13:00:09 +00:00
{
2014-05-12 05:41:49 +00:00
struct cs_struct * handle ;
2015-04-26 14:54:41 +00:00
cs_opt_mnem * opt ;
2014-03-04 16:21:53 +00:00
2014-01-05 03:19:04 +00:00
// 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 ) {
cs_opt_mem * mem = ( cs_opt_mem * ) value ;
2014-01-11 04:55:31 +00:00
cs_mem_malloc = mem - > malloc ;
cs_mem_calloc = mem - > calloc ;
cs_mem_realloc = mem - > realloc ;
cs_mem_free = mem - > free ;
2014-01-15 12:44:03 +00:00
cs_vsnprintf = mem - > vsnprintf ;
2014-01-05 03:19:04 +00:00
return CS_ERR_OK ;
}
2014-05-08 22:44:49 +00:00
handle = ( struct cs_struct * ) ( uintptr_t ) ud ;
2013-12-20 04:40:28 +00:00
if ( ! handle )
return CS_ERR_CSH ;
2014-04-09 15:49:30 +00:00
switch ( type ) {
default :
break ;
2015-04-26 14:54:41 +00:00
2016-03-14 05:52:23 +00:00
case CS_OPT_UNSIGNED :
handle - > imm_unsigned = ( cs_opt_value ) value ;
return CS_ERR_OK ;
2014-04-09 15:49:30 +00:00
case CS_OPT_DETAIL :
2015-03-03 03:06:56 +00:00
handle - > detail = ( cs_opt_value ) value ;
2014-04-09 15:49:30 +00:00
return CS_ERR_OK ;
2015-04-26 14:54:41 +00:00
2014-04-09 15:49:30 +00:00
case CS_OPT_SKIPDATA :
handle - > skipdata = ( value = = CS_OPT_ON ) ;
if ( handle - > skipdata ) {
if ( handle - > skipdata_size = = 0 ) {
// set the default skipdata size
handle - > skipdata_size = skipdata_size ( handle ) ;
}
}
return CS_ERR_OK ;
2015-04-26 14:54:41 +00:00
2014-04-09 15:49:30 +00:00
case CS_OPT_SKIPDATA_SETUP :
if ( value )
handle - > skipdata_setup = * ( ( cs_opt_skipdata * ) value ) ;
return CS_ERR_OK ;
2015-04-26 14:54:41 +00:00
case CS_OPT_MNEMONIC :
opt = ( cs_opt_mnem * ) value ;
if ( opt - > id ) {
if ( opt - > mnemonic ) {
struct insn_mnem * tmp ;
// add new instruction, or replace existing instruction
// 1. find if we already had this insn in the linked list
tmp = handle - > mnem_list ;
while ( tmp ) {
if ( tmp - > insn . id = = opt - > id ) {
// found this instruction, so replace its mnemonic
( void ) strncpy ( tmp - > insn . mnemonic , opt - > mnemonic , sizeof ( tmp - > insn . mnemonic ) - 1 ) ;
tmp - > insn . mnemonic [ sizeof ( tmp - > insn . mnemonic ) - 1 ] = ' \0 ' ;
break ;
}
tmp = tmp - > next ;
}
// 2. add this instruction if we have not had it yet
if ( ! tmp ) {
tmp = cs_mem_malloc ( sizeof ( * tmp ) ) ;
tmp - > insn . id = opt - > id ;
( void ) strncpy ( tmp - > insn . mnemonic , opt - > mnemonic , sizeof ( tmp - > insn . mnemonic ) - 1 ) ;
tmp - > insn . mnemonic [ sizeof ( tmp - > insn . mnemonic ) - 1 ] = ' \0 ' ;
// this new instruction is heading the list
tmp - > next = handle - > mnem_list ;
handle - > mnem_list = tmp ;
}
return CS_ERR_OK ;
} else {
struct insn_mnem * prev , * tmp ;
// we want to delete an existing instruction
// iterate the list to find the instruction to remove it
tmp = handle - > mnem_list ;
prev = tmp ;
while ( tmp ) {
if ( tmp - > insn . id = = opt - > id ) {
// delete this instruction
if ( tmp = = prev ) {
// head of the list
handle - > mnem_list = tmp - > next ;
} else {
prev - > next = tmp - > next ;
}
cs_mem_free ( tmp ) ;
break ;
}
prev = tmp ;
tmp = tmp - > next ;
}
}
}
return CS_ERR_OK ;
2018-06-24 13:05:04 +00:00
2017-10-20 15:33:24 +00:00
case CS_OPT_MODE :
// verify if requested mode is valid
2018-03-19 14:23:09 +00:00
if ( value & cs_arch_disallowed_mode_mask [ handle - > arch ] ) {
2017-10-20 15:33:24 +00:00
return CS_ERR_OPTION ;
}
break ;
2013-12-21 01:59:31 +00:00
}
2013-12-20 04:40:28 +00:00
2018-03-19 14:23:09 +00:00
return cs_arch_option [ handle - > arch ] ( handle , type , value ) ;
2013-12-03 13:00:09 +00:00
}
2014-04-10 06:36:08 +00:00
// generate @op_str for data instruction of SKIPDATA
2017-05-24 05:07:11 +00:00
# ifndef CAPSTONE_DIET
2014-04-09 15:49:30 +00:00
static void skipdata_opstr ( char * opstr , const uint8_t * buffer , size_t size )
{
char * p = opstr ;
int len ;
size_t i ;
2016-04-01 01:14:43 +00:00
size_t available = sizeof ( ( ( cs_insn * ) NULL ) - > op_str ) ;
2014-04-09 15:49:30 +00:00
if ( ! size ) {
opstr [ 0 ] = ' \0 ' ;
return ;
}
2016-04-01 01:14:43 +00:00
len = cs_snprintf ( p , available , " 0x%02x " , buffer [ 0 ] ) ;
2014-04-09 15:49:30 +00:00
p + = len ;
2016-04-01 01:14:43 +00:00
available - = len ;
2014-04-09 15:49:30 +00:00
for ( i = 1 ; i < size ; i + + ) {
2016-04-01 01:14:43 +00:00
len = cs_snprintf ( p , available , " , 0x%02x " , buffer [ i ] ) ;
if ( len < 0 ) {
break ;
}
if ( ( size_t ) len > available - 1 ) {
break ;
}
2014-04-09 15:49:30 +00:00
p + = len ;
2016-04-01 01:14:43 +00:00
available - = len ;
2014-04-09 15:49:30 +00:00
}
}
2017-05-24 05:07:11 +00:00
# endif
2014-04-09 15:49:30 +00:00
2013-11-27 04:11:31 +00:00
// dynamicly allocate memory to contain disasm insn
// NOTE: caller must free() the allocated memory itself to avoid memory leaking
2014-06-03 10:33:15 +00:00
CAPSTONE_EXPORT
2016-04-01 01:14:43 +00:00
size_t CAPSTONE_API cs_disasm ( csh ud , const uint8_t * buffer , size_t size , uint64_t offset , size_t count , cs_insn * * insn )
2013-11-27 04:11:31 +00:00
{
2014-10-10 16:36:16 +00:00
struct cs_struct * handle ;
2013-11-27 04:11:31 +00:00
MCInst mci ;
uint16_t insn_size ;
2014-06-18 13:50:25 +00:00
size_t c = 0 , i ;
2014-10-02 16:39:56 +00:00
unsigned int f = 0 ; // index of the next instruction in the cache
cs_insn * insn_cache ; // cache contains disassembled instructions
2013-11-27 04:11:31 +00:00
void * total = NULL ;
2014-10-02 16:39:56 +00:00
size_t total_size = 0 ; // total size of output buffer containing all insns
2014-03-06 14:40:08 +00:00
bool r ;
2014-04-09 15:49:30 +00:00
void * tmp ;
size_t skipdata_bytes ;
2014-10-01 02:46:37 +00:00
uint64_t offset_org ; // save all the original info of the buffer
2014-07-10 07:42:16 +00:00
size_t size_org ;
const uint8_t * buffer_org ;
2014-09-30 05:17:36 +00:00
unsigned int cache_size = INSN_CACHE_SIZE ;
2014-10-02 04:12:18 +00:00
size_t next_offset ;
2013-11-27 04:11:31 +00:00
2014-10-10 16:36:16 +00:00
handle = ( struct cs_struct * ) ( uintptr_t ) ud ;
2014-02-27 03:10:41 +00:00
if ( ! handle ) {
2013-11-27 04:11:31 +00:00
// FIXME: how to handle this case:
2013-11-27 07:24:47 +00:00
// handle->errnum = CS_ERR_HANDLE;
2013-11-27 04:11:31 +00:00
return 0 ;
}
2013-11-27 07:24:47 +00:00
handle - > errnum = CS_ERR_OK ;
2013-11-27 04:11:31 +00:00
2016-04-27 06:43:10 +00:00
// reset IT block of ARM structure
2016-04-27 06:47:05 +00:00
if ( handle - > arch = = CS_ARCH_ARM )
handle - > ITBlock . size = 0 ;
2016-04-27 06:43:10 +00:00
2014-09-30 05:28:02 +00:00
# ifdef CAPSTONE_USE_SYS_DYN_MEM
2014-10-02 02:09:59 +00:00
if ( count > 0 & & count < = INSN_CACHE_SIZE )
2014-10-22 07:21:43 +00:00
cache_size = ( unsigned int ) count ;
2014-09-30 05:28:02 +00:00
# endif
2014-09-30 05:17:36 +00:00
2014-04-28 03:19:44 +00:00
// save the original offset for SKIPDATA
2014-07-10 07:42:16 +00:00
buffer_org = buffer ;
2014-04-10 06:36:08 +00:00
offset_org = offset ;
2014-07-10 07:42:16 +00:00
size_org = size ;
2014-10-01 02:46:37 +00:00
total_size = sizeof ( cs_insn ) * cache_size ;
2014-06-08 17:13:31 +00:00
total = cs_mem_malloc ( total_size ) ;
2014-12-15 03:22:46 +00:00
if ( total = = NULL ) {
// insufficient memory
2014-12-15 01:45:19 +00:00
handle - > errnum = CS_ERR_MEM ;
return 0 ;
}
2014-12-15 03:22:46 +00:00
2014-06-08 17:13:31 +00:00
insn_cache = total ;
2014-04-28 03:19:44 +00:00
2013-11-27 04:11:31 +00:00
while ( size > 0 ) {
2014-06-16 07:54:32 +00:00
MCInst_Init ( & mci ) ;
2013-12-29 16:15:25 +00:00
mci . csh = handle ;
2013-11-27 04:11:31 +00:00
2014-06-08 16:35:52 +00:00
// relative branches need to know the address & size of current insn
mci . address = offset ;
if ( handle - > detail ) {
// allocate memory for @detail pointer
2014-06-08 17:13:31 +00:00
insn_cache - > detail = cs_mem_malloc ( sizeof ( cs_detail ) ) ;
2014-06-08 16:35:52 +00:00
} else {
2014-06-08 17:13:31 +00:00
insn_cache - > detail = NULL ;
2014-06-08 16:35:52 +00:00
}
// save all the information for non-detailed mode
2014-06-08 17:13:31 +00:00
mci . flat_insn = insn_cache ;
2014-06-08 16:35:52 +00:00
mci . flat_insn - > address = offset ;
2014-08-27 14:31:54 +00:00
# ifdef CAPSTONE_DIET
// zero out mnemonic & op_str
mci . flat_insn - > mnemonic [ 0 ] = ' \0 ' ;
mci . flat_insn - > op_str [ 0 ] = ' \0 ' ;
# endif
2014-06-08 16:35:52 +00:00
2014-05-07 00:25:24 +00:00
r = handle - > disasm ( ud , buffer , size , & mci , & insn_size , offset , handle - > getinsn_info ) ;
2013-11-27 04:11:31 +00:00
if ( r ) {
SStream ss ;
SStream_Init ( & ss ) ;
2014-06-08 16:35:52 +00:00
mci . flat_insn - > size = insn_size ;
2014-11-03 08:32:06 +00:00
// map internal instruction opcode to public insn ID
2017-05-24 05:07:11 +00:00
2014-11-03 08:32:06 +00:00
handle - > insn_id ( handle , insn_cache , mci . Opcode ) ;
2013-11-27 04:11:31 +00:00
handle - > printer ( & mci , & ss , handle - > printer_info ) ;
2014-06-08 17:13:31 +00:00
fill_insn ( handle , insn_cache , ss . buffer , & mci , handle - > post_printer , buffer ) ;
2013-12-13 16:23:41 +00:00
2016-07-15 12:37:19 +00:00
// adjust for pseudo opcode (X86)
if ( handle - > arch = = CS_ARCH_X86 )
insn_cache - > id + = mci . popcode_adjust ;
2014-10-02 04:12:18 +00:00
next_offset = insn_size ;
2013-12-04 14:57:04 +00:00
} else {
2014-10-02 04:37:32 +00:00
// encounter a broken instruction
// free memory of @detail pointer
2014-06-18 13:50:25 +00:00
if ( handle - > detail ) {
cs_mem_free ( insn_cache - > detail ) ;
}
2014-04-09 15:49:30 +00:00
// if there is no request to skip data, or remaining data is too small,
// then bail out
if ( ! handle - > skipdata | | handle - > skipdata_size > size )
break ;
if ( handle - > skipdata_setup . callback ) {
2014-07-10 07:42:16 +00:00
skipdata_bytes = handle - > skipdata_setup . callback ( buffer_org , size_org ,
2014-08-26 07:57:04 +00:00
( size_t ) ( offset - offset_org ) , handle - > skipdata_setup . user_data ) ;
2014-04-09 15:49:30 +00:00
if ( skipdata_bytes > size )
// remaining data is not enough
break ;
if ( ! skipdata_bytes )
// user requested not to skip data, so bail out
break ;
} else
skipdata_bytes = handle - > skipdata_size ;
// we have to skip some amount of data, depending on arch & mode
2014-06-08 17:13:31 +00:00
insn_cache - > id = 0 ; // invalid ID for this "data" instruction
insn_cache - > address = offset ;
2014-10-10 16:36:16 +00:00
insn_cache - > size = ( uint16_t ) skipdata_bytes ;
2014-06-08 17:13:31 +00:00
memcpy ( insn_cache - > bytes , buffer , skipdata_bytes ) ;
2017-05-24 05:07:11 +00:00
# ifdef CAPSTONE_DIET
2017-05-25 08:01:48 +00:00
insn_cache - > mnemonic [ 0 ] = ' \0 ' ;
2017-05-24 05:07:11 +00:00
insn_cache - > op_str [ 0 ] = ' \0 ' ;
# else
2014-06-08 17:13:31 +00:00
strncpy ( insn_cache - > mnemonic , handle - > skipdata_setup . mnemonic ,
sizeof ( insn_cache - > mnemonic ) - 1 ) ;
skipdata_opstr ( insn_cache - > op_str , buffer , skipdata_bytes ) ;
2017-05-24 05:07:11 +00:00
# endif
2014-06-08 17:13:31 +00:00
insn_cache - > detail = NULL ;
2014-04-09 15:49:30 +00:00
2014-10-02 04:12:18 +00:00
next_offset = skipdata_bytes ;
}
2014-10-02 04:37:32 +00:00
2014-10-02 04:12:18 +00:00
// one more instruction entering the cache
f + + ;
2014-10-02 04:37:32 +00:00
2014-10-02 04:12:18 +00:00
// one more instruction disassembled
c + + ;
if ( count > 0 & & c = = count )
2014-10-02 16:39:56 +00:00
// already got requested number of instructions
2014-10-02 04:12:18 +00:00
break ;
2014-10-02 04:37:32 +00:00
2014-10-02 04:12:18 +00:00
if ( f = = cache_size ) {
2014-10-02 16:39:56 +00:00
// full cache, so expand the cache to contain incoming insns
2014-10-02 12:38:24 +00:00
cache_size = cache_size * 8 / 5 ; // * 1.6 ~ golden ratio
2014-10-02 04:12:18 +00:00
total_size + = ( sizeof ( cs_insn ) * cache_size ) ;
tmp = cs_mem_realloc ( total , total_size ) ;
if ( tmp = = NULL ) { // insufficient memory
if ( handle - > detail ) {
insn_cache = ( cs_insn * ) total ;
for ( i = 0 ; i < c ; i + + , insn_cache + + )
cs_mem_free ( insn_cache - > detail ) ;
2014-04-09 15:49:30 +00:00
}
2014-10-02 04:12:18 +00:00
cs_mem_free ( total ) ;
* insn = NULL ;
handle - > errnum = CS_ERR_MEM ;
return 0 ;
}
2014-04-09 15:49:30 +00:00
2014-10-02 04:12:18 +00:00
total = tmp ;
2014-10-02 16:39:56 +00:00
// continue to fill in the cache after the last instruction
insn_cache = ( cs_insn * ) ( ( char * ) total + sizeof ( cs_insn ) * c ) ;
2014-04-09 15:49:30 +00:00
2014-10-02 16:39:56 +00:00
// reset f back to 0, so we fill in the cache from begining
2014-10-02 04:12:18 +00:00
f = 0 ;
} else
insn_cache + + ;
buffer + = next_offset ;
size - = next_offset ;
offset + = next_offset ;
2013-11-27 04:11:31 +00:00
}
2014-10-02 02:31:37 +00:00
if ( ! c ) {
2014-10-02 04:37:32 +00:00
// we did not disassemble any instruction
2014-10-02 02:31:37 +00:00
cs_mem_free ( total ) ;
total = NULL ;
} else if ( f ! = cache_size ) {
2014-10-02 04:37:32 +00:00
// total did not fully use the last cache, so downsize it
2015-10-24 00:59:20 +00:00
tmp = cs_mem_realloc ( total , total_size - ( cache_size - f ) * sizeof ( * insn_cache ) ) ;
2013-11-27 04:11:31 +00:00
if ( tmp = = NULL ) { // insufficient memory
2014-06-18 13:50:25 +00:00
// free all detail pointers
if ( handle - > detail ) {
insn_cache = ( cs_insn * ) total ;
for ( i = 0 ; i < c ; i + + , insn_cache + + )
cs_mem_free ( insn_cache - > detail ) ;
}
2014-01-11 04:55:31 +00:00
cs_mem_free ( total ) ;
2014-06-19 03:15:18 +00:00
* insn = NULL ;
2014-06-18 13:50:25 +00:00
2013-11-27 07:24:47 +00:00
handle - > errnum = CS_ERR_MEM ;
2013-11-27 04:11:31 +00:00
return 0 ;
}
total = tmp ;
}
* insn = total ;
return c ;
}
2014-08-27 14:55:29 +00:00
CAPSTONE_EXPORT
CAPSTONE_DEPRECATED
2016-04-01 01:14:43 +00:00
size_t CAPSTONE_API cs_disasm_ex ( csh ud , const uint8_t * buffer , size_t size , uint64_t offset , size_t count , cs_insn * * insn )
2014-08-27 14:55:29 +00:00
{
return cs_disasm ( ud , buffer , size , offset , count , insn ) ;
}
2014-06-03 10:33:15 +00:00
CAPSTONE_EXPORT
2016-04-01 01:14:43 +00:00
void CAPSTONE_API cs_free ( cs_insn * insn , size_t count )
2013-11-27 04:11:31 +00:00
{
2013-12-24 08:49:36 +00:00
size_t i ;
// free all detail pointers
for ( i = 0 ; i < count ; i + + )
2014-01-11 04:55:31 +00:00
cs_mem_free ( insn [ i ] . detail ) ;
2013-12-24 08:49:36 +00:00
// then free pointer to cs_insn array
2014-01-11 04:55:31 +00:00
cs_mem_free ( insn ) ;
2013-11-27 04:11:31 +00:00
}
2014-10-10 16:36:16 +00:00
CAPSTONE_EXPORT
2016-04-01 01:14:43 +00:00
cs_insn * CAPSTONE_API cs_malloc ( csh ud )
2014-10-10 16:36:16 +00:00
{
cs_insn * insn ;
struct cs_struct * handle = ( struct cs_struct * ) ( uintptr_t ) ud ;
insn = cs_mem_malloc ( sizeof ( cs_insn ) ) ;
if ( ! insn ) {
// insufficient memory
handle - > errnum = CS_ERR_MEM ;
return NULL ;
} else {
if ( handle - > detail ) {
// allocate memory for @detail pointer
insn - > detail = cs_mem_malloc ( sizeof ( cs_detail ) ) ;
if ( insn - > detail = = NULL ) { // insufficient memory
cs_mem_free ( insn ) ;
handle - > errnum = CS_ERR_MEM ;
return NULL ;
}
} else
insn - > detail = NULL ;
}
return insn ;
}
2014-10-05 16:14:40 +00:00
// iterator for instruction "single-stepping"
CAPSTONE_EXPORT
2016-04-01 01:14:43 +00:00
bool CAPSTONE_API cs_disasm_iter ( csh ud , const uint8_t * * code , size_t * size ,
2014-10-10 16:36:16 +00:00
uint64_t * address , cs_insn * insn )
2014-10-05 16:14:40 +00:00
{
struct cs_struct * handle ;
uint16_t insn_size ;
MCInst mci ;
bool r ;
handle = ( struct cs_struct * ) ( uintptr_t ) ud ;
2014-10-10 16:36:16 +00:00
if ( ! handle ) {
2014-10-12 07:28:34 +00:00
return false ;
2014-10-05 16:14:40 +00:00
}
handle - > errnum = CS_ERR_OK ;
MCInst_Init ( & mci ) ;
mci . csh = handle ;
// relative branches need to know the address & size of current insn
mci . address = * address ;
// save all the information for non-detailed mode
2014-10-10 16:36:16 +00:00
mci . flat_insn = insn ;
2014-10-05 16:14:40 +00:00
mci . flat_insn - > address = * address ;
# ifdef CAPSTONE_DIET
// zero out mnemonic & op_str
mci . flat_insn - > mnemonic [ 0 ] = ' \0 ' ;
mci . flat_insn - > op_str [ 0 ] = ' \0 ' ;
# endif
r = handle - > disasm ( ud , * code , * size , & mci , & insn_size , * address , handle - > getinsn_info ) ;
2014-10-10 16:36:16 +00:00
if ( r ) {
2014-10-05 16:14:40 +00:00
SStream ss ;
SStream_Init ( & ss ) ;
mci . flat_insn - > size = insn_size ;
2014-11-03 08:32:06 +00:00
// map internal instruction opcode to public insn ID
handle - > insn_id ( handle , insn , mci . Opcode ) ;
2014-10-05 16:14:40 +00:00
handle - > printer ( & mci , & ss , handle - > printer_info ) ;
2014-11-03 08:32:06 +00:00
2014-10-10 16:36:16 +00:00
fill_insn ( handle , insn , ss . buffer , & mci , handle - > post_printer , * code ) ;
2014-11-03 08:32:06 +00:00
2016-07-15 12:37:19 +00:00
// adjust for pseudo opcode (X86)
if ( handle - > arch = = CS_ARCH_X86 )
insn - > id + = mci . popcode_adjust ;
2014-10-05 16:14:40 +00:00
* code + = insn_size ;
* size - = insn_size ;
* address + = insn_size ;
2014-10-10 16:36:16 +00:00
} else { // encounter a broken instruction
size_t skipdata_bytes ;
// if there is no request to skip data, or remaining data is too small,
// then bail out
if ( ! handle - > skipdata | | handle - > skipdata_size > * size )
return false ;
if ( handle - > skipdata_setup . callback ) {
skipdata_bytes = handle - > skipdata_setup . callback ( * code , * size ,
0 , handle - > skipdata_setup . user_data ) ;
if ( skipdata_bytes > * size )
// remaining data is not enough
return false ;
if ( ! skipdata_bytes )
// user requested not to skip data, so bail out
return false ;
} else
skipdata_bytes = handle - > skipdata_size ;
// we have to skip some amount of data, depending on arch & mode
insn - > id = 0 ; // invalid ID for this "data" instruction
insn - > address = * address ;
insn - > size = ( uint16_t ) skipdata_bytes ;
2017-05-24 05:07:11 +00:00
# ifdef CAPSTONE_DIET
insn - > mnemonic [ 0 ] = ' \0 ' ;
insn - > op_str [ 0 ] = ' \0 ' ;
# else
2014-10-10 16:36:16 +00:00
memcpy ( insn - > bytes , * code , skipdata_bytes ) ;
strncpy ( insn - > mnemonic , handle - > skipdata_setup . mnemonic ,
sizeof ( insn - > mnemonic ) - 1 ) ;
skipdata_opstr ( insn - > op_str , * code , skipdata_bytes ) ;
2017-05-24 05:07:11 +00:00
# endif
2014-10-10 16:36:16 +00:00
* code + = skipdata_bytes ;
* size - = skipdata_bytes ;
* address + = skipdata_bytes ;
2014-10-05 16:14:40 +00:00
}
2014-10-10 16:36:16 +00:00
return true ;
2014-10-05 16:14:40 +00:00
}
2013-11-27 04:11:31 +00:00
// return friendly name of regiser in a string
2014-06-03 10:33:15 +00:00
CAPSTONE_EXPORT
2016-04-01 01:14:43 +00:00
const char * CAPSTONE_API cs_reg_name ( csh ud , unsigned int reg )
2013-11-27 04:11:31 +00:00
{
2014-01-23 15:42:40 +00:00
struct cs_struct * handle = ( struct cs_struct * ) ( uintptr_t ) ud ;
2013-11-27 04:11:31 +00:00
if ( ! handle | | handle - > reg_name = = NULL ) {
return NULL ;
}
2013-12-09 02:26:18 +00:00
return handle - > reg_name ( ud , reg ) ;
2013-11-27 04:11:31 +00:00
}
2014-06-03 10:33:15 +00:00
CAPSTONE_EXPORT
2016-04-01 01:14:43 +00:00
const char * CAPSTONE_API cs_insn_name ( csh ud , unsigned int insn )
2013-11-27 04:11:31 +00:00
{
2014-01-23 15:42:40 +00:00
struct cs_struct * handle = ( struct cs_struct * ) ( uintptr_t ) ud ;
2013-11-27 04:11:31 +00:00
if ( ! handle | | handle - > insn_name = = NULL ) {
return NULL ;
}
2013-12-09 02:26:18 +00:00
return handle - > insn_name ( ud , insn ) ;
2013-11-27 04:11:31 +00:00
}
2014-07-08 00:59:27 +00:00
CAPSTONE_EXPORT
2016-04-01 01:14:43 +00:00
const char * CAPSTONE_API cs_group_name ( csh ud , unsigned int group )
2014-07-08 00:59:27 +00:00
{
struct cs_struct * handle = ( struct cs_struct * ) ( uintptr_t ) ud ;
if ( ! handle | | handle - > group_name = = NULL ) {
return NULL ;
}
return handle - > group_name ( ud , group ) ;
}
2014-06-03 10:33:15 +00:00
CAPSTONE_EXPORT
2016-04-01 01:14:43 +00:00
bool CAPSTONE_API cs_insn_group ( csh ud , const cs_insn * insn , unsigned int group_id )
2013-11-27 04:11:31 +00:00
{
2014-05-12 05:41:49 +00:00
struct cs_struct * handle ;
2013-12-24 08:49:36 +00:00
if ( ! ud )
return false ;
2014-05-08 22:44:49 +00:00
handle = ( struct cs_struct * ) ( uintptr_t ) ud ;
2014-05-07 15:25:38 +00:00
2013-12-24 08:49:36 +00:00
if ( ! handle - > detail ) {
handle - > errnum = CS_ERR_DETAIL ;
2013-11-27 04:11:31 +00:00
return false ;
2013-12-24 08:49:36 +00:00
}
2013-11-27 04:11:31 +00:00
2015-03-25 07:02:13 +00:00
if ( ! insn - > id ) {
2014-05-07 15:31:27 +00:00
handle - > errnum = CS_ERR_SKIPDATA ;
return false ;
}
2014-05-07 15:25:38 +00:00
2015-03-25 07:02:13 +00:00
if ( ! insn - > detail ) {
2014-05-07 15:31:27 +00:00
handle - > errnum = CS_ERR_DETAIL ;
return false ;
}
2014-05-07 15:25:38 +00:00
2015-03-25 07:02:13 +00:00
return arr_exist8 ( insn - > detail - > groups , insn - > detail - > groups_count , group_id ) ;
2013-11-27 04:11:31 +00:00
}
2014-06-03 10:33:15 +00:00
CAPSTONE_EXPORT
2016-04-01 01:14:43 +00:00
bool CAPSTONE_API cs_reg_read ( csh ud , const cs_insn * insn , unsigned int reg_id )
2013-11-27 04:11:31 +00:00
{
2014-05-12 05:41:49 +00:00
struct cs_struct * handle ;
2013-12-24 08:49:36 +00:00
if ( ! ud )
2013-11-27 04:11:31 +00:00
return false ;
2014-05-08 22:44:49 +00:00
handle = ( struct cs_struct * ) ( uintptr_t ) ud ;
2014-05-07 15:25:38 +00:00
2013-12-24 08:49:36 +00:00
if ( ! handle - > detail ) {
handle - > errnum = CS_ERR_DETAIL ;
return false ;
}
2015-03-25 07:02:13 +00:00
if ( ! insn - > id ) {
2014-05-07 15:31:27 +00:00
handle - > errnum = CS_ERR_SKIPDATA ;
return false ;
}
2014-05-07 15:25:38 +00:00
2015-03-25 07:02:13 +00:00
if ( ! insn - > detail ) {
2014-05-07 15:31:27 +00:00
handle - > errnum = CS_ERR_DETAIL ;
return false ;
}
2014-05-07 15:25:38 +00:00
2013-12-24 08:49:36 +00:00
return arr_exist ( insn - > detail - > regs_read , insn - > detail - > regs_read_count , reg_id ) ;
2013-11-27 04:11:31 +00:00
}
2014-06-03 10:33:15 +00:00
CAPSTONE_EXPORT
2016-04-01 01:14:43 +00:00
bool CAPSTONE_API cs_reg_write ( csh ud , const cs_insn * insn , unsigned int reg_id )
2013-11-27 04:11:31 +00:00
{
2014-05-12 05:41:49 +00:00
struct cs_struct * handle ;
2013-12-24 08:49:36 +00:00
if ( ! ud )
return false ;
2014-05-08 22:44:49 +00:00
handle = ( struct cs_struct * ) ( uintptr_t ) ud ;
2014-05-07 15:31:27 +00:00
2013-12-24 08:49:36 +00:00
if ( ! handle - > detail ) {
handle - > errnum = CS_ERR_DETAIL ;
2013-11-27 04:11:31 +00:00
return false ;
2013-12-24 08:49:36 +00:00
}
2013-11-27 04:11:31 +00:00
2015-03-25 07:02:13 +00:00
if ( ! insn - > id ) {
2014-05-07 15:31:27 +00:00
handle - > errnum = CS_ERR_SKIPDATA ;
return false ;
}
2014-05-07 15:25:38 +00:00
2015-03-25 07:02:13 +00:00
if ( ! insn - > detail ) {
2014-05-07 15:31:27 +00:00
handle - > errnum = CS_ERR_DETAIL ;
return false ;
}
2014-05-07 15:25:38 +00:00
2013-12-24 08:49:36 +00:00
return arr_exist ( insn - > detail - > regs_write , insn - > detail - > regs_write_count , reg_id ) ;
2013-11-27 04:11:31 +00:00
}
2014-06-03 10:33:15 +00:00
CAPSTONE_EXPORT
2016-04-01 01:14:43 +00:00
int CAPSTONE_API cs_op_count ( csh ud , const cs_insn * insn , unsigned int op_type )
2013-11-27 04:11:31 +00:00
{
2014-05-12 05:41:49 +00:00
struct cs_struct * handle ;
unsigned int count = 0 , i ;
2013-11-27 04:11:31 +00:00
if ( ! ud )
return - 1 ;
2014-05-08 22:44:49 +00:00
handle = ( struct cs_struct * ) ( uintptr_t ) ud ;
2014-05-07 15:25:38 +00:00
2014-01-15 13:27:23 +00:00
if ( ! handle - > detail ) {
handle - > errnum = CS_ERR_DETAIL ;
return - 1 ;
}
2015-03-25 07:02:13 +00:00
if ( ! insn - > id ) {
2014-05-07 15:31:27 +00:00
handle - > errnum = CS_ERR_SKIPDATA ;
return - 1 ;
}
2014-05-07 15:25:38 +00:00
2015-03-25 07:02:13 +00:00
if ( ! insn - > detail ) {
2014-05-07 15:31:27 +00:00
handle - > errnum = CS_ERR_DETAIL ;
return - 1 ;
}
2014-05-07 15:25:38 +00:00
2013-11-27 07:24:47 +00:00
handle - > errnum = CS_ERR_OK ;
2013-11-27 04:11:31 +00:00
switch ( handle - > arch ) {
default :
2013-11-27 07:24:47 +00:00
handle - > errnum = CS_ERR_HANDLE ;
2013-11-27 04:11:31 +00:00
return - 1 ;
case CS_ARCH_ARM :
2013-12-24 08:49:36 +00:00
for ( i = 0 ; i < insn - > detail - > arm . op_count ; i + + )
2014-01-22 17:45:00 +00:00
if ( insn - > detail - > arm . operands [ i ] . type = = ( arm_op_type ) op_type )
2013-11-27 04:11:31 +00:00
count + + ;
break ;
case CS_ARCH_ARM64 :
2013-12-24 08:49:36 +00:00
for ( i = 0 ; i < insn - > detail - > arm64 . op_count ; i + + )
2014-01-22 17:45:00 +00:00
if ( insn - > detail - > arm64 . operands [ i ] . type = = ( arm64_op_type ) op_type )
2013-11-27 04:11:31 +00:00
count + + ;
break ;
case CS_ARCH_X86 :
2013-12-24 08:49:36 +00:00
for ( i = 0 ; i < insn - > detail - > x86 . op_count ; i + + )
2014-01-22 17:45:00 +00:00
if ( insn - > detail - > x86 . operands [ i ] . type = = ( x86_op_type ) op_type )
2013-11-27 04:11:31 +00:00
count + + ;
break ;
case CS_ARCH_MIPS :
2013-12-24 08:49:36 +00:00
for ( i = 0 ; i < insn - > detail - > mips . op_count ; i + + )
2014-01-22 17:45:00 +00:00
if ( insn - > detail - > mips . operands [ i ] . type = = ( mips_op_type ) op_type )
2013-11-27 04:11:31 +00:00
count + + ;
break ;
2013-12-29 16:15:25 +00:00
case CS_ARCH_PPC :
for ( i = 0 ; i < insn - > detail - > ppc . op_count ; i + + )
2014-01-22 17:45:00 +00:00
if ( insn - > detail - > ppc . operands [ i ] . type = = ( ppc_op_type ) op_type )
2013-12-29 16:15:25 +00:00
count + + ;
break ;
2014-03-10 03:58:57 +00:00
case CS_ARCH_SPARC :
for ( i = 0 ; i < insn - > detail - > sparc . op_count ; i + + )
if ( insn - > detail - > sparc . operands [ i ] . type = = ( sparc_op_type ) op_type )
count + + ;
break ;
2014-03-23 00:35:45 +00:00
case CS_ARCH_SYSZ :
for ( i = 0 ; i < insn - > detail - > sysz . op_count ; i + + )
if ( insn - > detail - > sysz . operands [ i ] . type = = ( sysz_op_type ) op_type )
count + + ;
break ;
2014-05-26 15:02:48 +00:00
case CS_ARCH_XCORE :
for ( i = 0 ; i < insn - > detail - > xcore . op_count ; i + + )
if ( insn - > detail - > xcore . operands [ i ] . type = = ( xcore_op_type ) op_type )
count + + ;
break ;
2016-05-03 13:02:40 +00:00
case CS_ARCH_M68K :
for ( i = 0 ; i < insn - > detail - > m68k . op_count ; i + + )
if ( insn - > detail - > m68k . operands [ i ] . type = = ( m68k_op_type ) op_type )
count + + ;
break ;
2016-05-03 12:52:11 +00:00
case CS_ARCH_TMS320C64X :
for ( i = 0 ; i < insn - > detail - > tms320c64x . op_count ; i + + )
if ( insn - > detail - > tms320c64x . operands [ i ] . type = = ( tms320c64x_op_type ) op_type )
count + + ;
break ;
M680X: Target ready for pull request (#1034)
* Added new M680X target. Supports M6800/1/2/3/9, HD6301
* M680X: Reformat for coding guide lines. Set alphabetical order in HACK.TXT
* M680X: Prepare for python binding. Move cs_m680x, m680x_insn to m680x_info. Chec
> k cpu type, no default.
* M680X: Add python bindings. Added python tests.
* M680X: Added cpu types to usage message.
* cstool: Avoid segfault for invalid <arch+mode>.
* Make test_m680x.c/test_m680x.py output comparable (diff params: -bu). Keep xprint.py untouched.
* M680X: Update CMake/make for m680x support. Update .gitignore.
* M680X: Reduce compiler warnings.
* M680X: Reduce compiler warnings.
* M680X: Reduce compiler warnings.
* M680X: Make test_m680x.c/test_m680x.py output comparable (diff params: -bu).
* M680X: Add ocaml bindings and tests.
* M680X: Add java bindings and tests.
* M680X: Added tests for all indexed addressing modes. C/Python/Ocaml
* M680X: Naming, use page1 for PAGE1 instructions (without prefix).
* M680X: Naming, use page1 for PAGE1 instructions (without prefix).
* M680X: Used M680X_FIRST_OP_IN_MNEM in tests C/python/java/ocaml.
* M680X: Added access property to cs_m680x_op.
* M680X: Added operand size.
* M680X: Remove compiler warnings.
* M680X: Added READ/WRITE access property per operator.
* M680X: Make reg_inherent_hdlr independent of CPU type.
* M680X: Add HD6309 support + bug fixes
* M680X: Remove errors and warning.
* M680X: Add Bcc/LBcc to group BRAREL (relative branch).
* M680X: Add group JUMP to BVS/BVC/LBVS/LBVC. Remove BRAREL from BRN/LBRN.
* M680X: Remove LBRN from group BRAREL.
* M680X: Refactored cpu_type initialization for better readability.
* M680X: Add two operands for insn having two reg. in mnemonic. e.g. ABX.
* M680X: Remove typo in cstool.c
* M680X: Some format improvements in changed_regs.
* M680X: Remove insn id string list from tests (C/python/java/ocaml).
* M680X: SEXW, set access of reg. D to WRITE.
* M680X: Sort changed_regs in increasing m680x_insn order.
* M680X: Add M68HC11 support + Reduced from two to one INDEXED operand.
* M680X: cstool, also write '(in mnemonic)' for second reg. operand.
* M680X: Add BRN/LBRN to group JUMP and BRAREL.
* M680X: For Bcc/LBcc/BRSET/BRCLR set reg. CC to read access.
* M680X: Correctly print negative immediate values with option CS_OPT_UNSIGNED.
* M680X: Rename some instruction handlers.
* M680X: Add M68HC05 support.
* M680X: Dont print prefix '<' for direct addr. mode.
* M680X: Add M68HC08 support + resorted tables + bug fixes.
* M680X: Add Freescale HCS08 support.
* M680X: Changed group names, avoid spaces.
* M680X: Refactoring, rename addessing mode handlers.
* M680X: indexed addr. mode, changed pre/post inc-/decrement representation.
* M680X: Rename some M6809/HD6309 specific functions.
* M680X: Add CPU12 (68HC12/HCS12) support.
* M680X: Correctly display illegal instruction as FCB .
* M680X: bugfix: BRA/BRN/BSR/LBRA/LBRN/LBSR does not read CC reg.
* M680X: bugfix: Correctly check for sufficient code size for M6809 indexed addressing.
* M680X: Better support for changing insn id within handler for addessing mode.
* M680X: Remove warnings.
* M680X: In set_changed_regs_read_write_counts use own access_mode.
* M680X: Split cpu specific tables into separate *.inc files.
* M680X: Remove warnings.
* M680X: Removed address_mode. Addressing mode is available in operand.type
* M680X: Bugfix: BSET/BCLR/BRSET/BRCLR correct read/modify CC reg.
* M680X: Remove register TMP1. It is first visible in CPU12X.
* M680X: Performance improvement + bug fixes.
* M680X: Performance improvement, make cpu_tables const static.
* M680X: Simplify operand decoding by using two handlers.
* M680X: Replace M680X_OP_INDEX by M680X_OP_CONSTANT + bugfix in java/python/ocaml bindings.
* M680X: Format with astyle.
* M680X: Update documentation.
* M680X: Corrected author for m680x specific files.
* M680X: Make max. number of architectures single source.
2017-10-21 13:44:36 +00:00
case CS_ARCH_M680X :
for ( i = 0 ; i < insn - > detail - > m680x . op_count ; i + + )
if ( insn - > detail - > m680x . operands [ i ] . type = = ( m680x_op_type ) op_type )
count + + ;
break ;
2018-03-31 09:29:22 +00:00
case CS_ARCH_EVM :
2019-02-01 15:03:47 +00:00
break ;
2018-12-02 20:39:41 +00:00
case CS_ARCH_MOS65XX :
2019-02-18 11:52:51 +00:00
for ( i = 0 ; i < insn - > detail - > mos65xx . op_count ; i + + )
if ( insn - > detail - > mos65xx . operands [ i ] . type = = ( mos65xx_op_type ) op_type )
2018-12-02 20:39:41 +00:00
count + + ;
break ;
2019-02-01 15:03:47 +00:00
case CS_ARCH_WASM :
2019-02-01 23:50:40 +00:00
for ( i = 0 ; i < insn - > detail - > wasm . op_count ; i + + )
if ( insn - > detail - > wasm . operands [ i ] . type = = ( wasm_op_type ) op_type )
2019-02-01 15:03:47 +00:00
count + + ;
2018-03-31 09:29:22 +00:00
break ;
2019-02-18 09:39:51 +00:00
case CS_ARCH_BPF :
for ( i = 0 ; i < insn - > detail - > bpf . op_count ; i + + )
if ( insn - > detail - > bpf . operands [ i ] . type = = ( bpf_op_type ) op_type )
count + + ;
break ;
2013-11-27 04:11:31 +00:00
}
return count ;
}
2014-06-03 10:33:15 +00:00
CAPSTONE_EXPORT
2016-04-01 01:14:43 +00:00
int CAPSTONE_API cs_op_index ( csh ud , const cs_insn * insn , unsigned int op_type ,
2013-11-27 04:11:31 +00:00
unsigned int post )
{
2014-05-12 05:41:49 +00:00
struct cs_struct * handle ;
unsigned int count = 0 , i ;
2013-11-27 04:11:31 +00:00
if ( ! ud )
return - 1 ;
2014-05-08 22:44:49 +00:00
handle = ( struct cs_struct * ) ( uintptr_t ) ud ;
2014-05-07 15:25:38 +00:00
2014-01-15 13:27:23 +00:00
if ( ! handle - > detail ) {
handle - > errnum = CS_ERR_DETAIL ;
return - 1 ;
}
2015-03-25 07:02:13 +00:00
if ( ! insn - > id ) {
2014-05-07 15:31:27 +00:00
handle - > errnum = CS_ERR_SKIPDATA ;
return - 1 ;
}
2014-05-07 15:25:38 +00:00
2015-03-25 07:02:13 +00:00
if ( ! insn - > detail ) {
2014-05-07 15:31:27 +00:00
handle - > errnum = CS_ERR_DETAIL ;
return - 1 ;
}
2014-05-07 15:25:38 +00:00
2013-11-27 07:24:47 +00:00
handle - > errnum = CS_ERR_OK ;
2013-11-27 04:11:31 +00:00
switch ( handle - > arch ) {
default :
2013-11-27 07:24:47 +00:00
handle - > errnum = CS_ERR_HANDLE ;
2013-11-27 04:11:31 +00:00
return - 1 ;
case CS_ARCH_ARM :
2013-12-24 08:49:36 +00:00
for ( i = 0 ; i < insn - > detail - > arm . op_count ; i + + ) {
2014-01-22 17:45:00 +00:00
if ( insn - > detail - > arm . operands [ i ] . type = = ( arm_op_type ) op_type )
2013-11-27 04:11:31 +00:00
count + + ;
if ( count = = post )
return i ;
}
break ;
case CS_ARCH_ARM64 :
2013-12-24 08:49:36 +00:00
for ( i = 0 ; i < insn - > detail - > arm64 . op_count ; i + + ) {
2014-01-22 17:45:00 +00:00
if ( insn - > detail - > arm64 . operands [ i ] . type = = ( arm64_op_type ) op_type )
2013-11-27 04:11:31 +00:00
count + + ;
if ( count = = post )
return i ;
}
break ;
case CS_ARCH_X86 :
2013-12-24 08:49:36 +00:00
for ( i = 0 ; i < insn - > detail - > x86 . op_count ; i + + ) {
2014-01-22 17:45:00 +00:00
if ( insn - > detail - > x86 . operands [ i ] . type = = ( x86_op_type ) op_type )
2013-11-27 04:11:31 +00:00
count + + ;
if ( count = = post )
return i ;
}
break ;
case CS_ARCH_MIPS :
2013-12-24 08:49:36 +00:00
for ( i = 0 ; i < insn - > detail - > mips . op_count ; i + + ) {
2014-01-22 17:45:00 +00:00
if ( insn - > detail - > mips . operands [ i ] . type = = ( mips_op_type ) op_type )
2013-11-27 04:11:31 +00:00
count + + ;
if ( count = = post )
return i ;
}
break ;
2013-12-29 16:15:25 +00:00
case CS_ARCH_PPC :
for ( i = 0 ; i < insn - > detail - > ppc . op_count ; i + + ) {
2014-01-22 17:45:00 +00:00
if ( insn - > detail - > ppc . operands [ i ] . type = = ( ppc_op_type ) op_type )
2013-12-29 16:15:25 +00:00
count + + ;
if ( count = = post )
return i ;
}
break ;
2014-03-10 03:58:57 +00:00
case CS_ARCH_SPARC :
for ( i = 0 ; i < insn - > detail - > sparc . op_count ; i + + ) {
if ( insn - > detail - > sparc . operands [ i ] . type = = ( sparc_op_type ) op_type )
count + + ;
if ( count = = post )
return i ;
}
break ;
2014-03-23 00:35:45 +00:00
case CS_ARCH_SYSZ :
for ( i = 0 ; i < insn - > detail - > sysz . op_count ; i + + ) {
if ( insn - > detail - > sysz . operands [ i ] . type = = ( sysz_op_type ) op_type )
count + + ;
if ( count = = post )
return i ;
}
break ;
2014-05-26 15:02:48 +00:00
case CS_ARCH_XCORE :
for ( i = 0 ; i < insn - > detail - > xcore . op_count ; i + + ) {
if ( insn - > detail - > xcore . operands [ i ] . type = = ( xcore_op_type ) op_type )
count + + ;
if ( count = = post )
return i ;
}
break ;
2016-05-03 13:02:40 +00:00
case CS_ARCH_M68K :
for ( i = 0 ; i < insn - > detail - > m68k . op_count ; i + + ) {
if ( insn - > detail - > m68k . operands [ i ] . type = = ( m68k_op_type ) op_type )
count + + ;
if ( count = = post )
return i ;
}
break ;
2016-05-03 12:52:11 +00:00
case CS_ARCH_TMS320C64X :
for ( i = 0 ; i < insn - > detail - > tms320c64x . op_count ; i + + ) {
if ( insn - > detail - > tms320c64x . operands [ i ] . type = = ( tms320c64x_op_type ) op_type )
count + + ;
if ( count = = post )
return i ;
}
break ;
M680X: Target ready for pull request (#1034)
* Added new M680X target. Supports M6800/1/2/3/9, HD6301
* M680X: Reformat for coding guide lines. Set alphabetical order in HACK.TXT
* M680X: Prepare for python binding. Move cs_m680x, m680x_insn to m680x_info. Chec
> k cpu type, no default.
* M680X: Add python bindings. Added python tests.
* M680X: Added cpu types to usage message.
* cstool: Avoid segfault for invalid <arch+mode>.
* Make test_m680x.c/test_m680x.py output comparable (diff params: -bu). Keep xprint.py untouched.
* M680X: Update CMake/make for m680x support. Update .gitignore.
* M680X: Reduce compiler warnings.
* M680X: Reduce compiler warnings.
* M680X: Reduce compiler warnings.
* M680X: Make test_m680x.c/test_m680x.py output comparable (diff params: -bu).
* M680X: Add ocaml bindings and tests.
* M680X: Add java bindings and tests.
* M680X: Added tests for all indexed addressing modes. C/Python/Ocaml
* M680X: Naming, use page1 for PAGE1 instructions (without prefix).
* M680X: Naming, use page1 for PAGE1 instructions (without prefix).
* M680X: Used M680X_FIRST_OP_IN_MNEM in tests C/python/java/ocaml.
* M680X: Added access property to cs_m680x_op.
* M680X: Added operand size.
* M680X: Remove compiler warnings.
* M680X: Added READ/WRITE access property per operator.
* M680X: Make reg_inherent_hdlr independent of CPU type.
* M680X: Add HD6309 support + bug fixes
* M680X: Remove errors and warning.
* M680X: Add Bcc/LBcc to group BRAREL (relative branch).
* M680X: Add group JUMP to BVS/BVC/LBVS/LBVC. Remove BRAREL from BRN/LBRN.
* M680X: Remove LBRN from group BRAREL.
* M680X: Refactored cpu_type initialization for better readability.
* M680X: Add two operands for insn having two reg. in mnemonic. e.g. ABX.
* M680X: Remove typo in cstool.c
* M680X: Some format improvements in changed_regs.
* M680X: Remove insn id string list from tests (C/python/java/ocaml).
* M680X: SEXW, set access of reg. D to WRITE.
* M680X: Sort changed_regs in increasing m680x_insn order.
* M680X: Add M68HC11 support + Reduced from two to one INDEXED operand.
* M680X: cstool, also write '(in mnemonic)' for second reg. operand.
* M680X: Add BRN/LBRN to group JUMP and BRAREL.
* M680X: For Bcc/LBcc/BRSET/BRCLR set reg. CC to read access.
* M680X: Correctly print negative immediate values with option CS_OPT_UNSIGNED.
* M680X: Rename some instruction handlers.
* M680X: Add M68HC05 support.
* M680X: Dont print prefix '<' for direct addr. mode.
* M680X: Add M68HC08 support + resorted tables + bug fixes.
* M680X: Add Freescale HCS08 support.
* M680X: Changed group names, avoid spaces.
* M680X: Refactoring, rename addessing mode handlers.
* M680X: indexed addr. mode, changed pre/post inc-/decrement representation.
* M680X: Rename some M6809/HD6309 specific functions.
* M680X: Add CPU12 (68HC12/HCS12) support.
* M680X: Correctly display illegal instruction as FCB .
* M680X: bugfix: BRA/BRN/BSR/LBRA/LBRN/LBSR does not read CC reg.
* M680X: bugfix: Correctly check for sufficient code size for M6809 indexed addressing.
* M680X: Better support for changing insn id within handler for addessing mode.
* M680X: Remove warnings.
* M680X: In set_changed_regs_read_write_counts use own access_mode.
* M680X: Split cpu specific tables into separate *.inc files.
* M680X: Remove warnings.
* M680X: Removed address_mode. Addressing mode is available in operand.type
* M680X: Bugfix: BSET/BCLR/BRSET/BRCLR correct read/modify CC reg.
* M680X: Remove register TMP1. It is first visible in CPU12X.
* M680X: Performance improvement + bug fixes.
* M680X: Performance improvement, make cpu_tables const static.
* M680X: Simplify operand decoding by using two handlers.
* M680X: Replace M680X_OP_INDEX by M680X_OP_CONSTANT + bugfix in java/python/ocaml bindings.
* M680X: Format with astyle.
* M680X: Update documentation.
* M680X: Corrected author for m680x specific files.
* M680X: Make max. number of architectures single source.
2017-10-21 13:44:36 +00:00
case CS_ARCH_M680X :
for ( i = 0 ; i < insn - > detail - > m680x . op_count ; i + + ) {
if ( insn - > detail - > m680x . operands [ i ] . type = = ( m680x_op_type ) op_type )
count + + ;
if ( count = = post )
return i ;
}
break ;
2018-03-31 09:29:22 +00:00
case CS_ARCH_EVM :
#if 0
for ( i = 0 ; i < insn - > detail - > evm . op_count ; i + + ) {
if ( insn - > detail - > evm . operands [ i ] . type = = ( evm_op_type ) op_type )
count + + ;
if ( count = = post )
return i ;
}
# endif
break ;
2018-12-02 20:39:41 +00:00
case CS_ARCH_MOS65XX :
for ( i = 0 ; i < insn - > detail - > mos65xx . op_count ; i + + ) {
if ( insn - > detail - > mos65xx . operands [ i ] . type = = ( mos65xx_op_type ) op_type )
count + + ;
if ( count = = post )
return i ;
}
break ;
2019-02-01 15:03:47 +00:00
case CS_ARCH_WASM :
for ( i = 0 ; i < insn - > detail - > wasm . op_count ; i + + ) {
if ( insn - > detail - > wasm . operands [ i ] . type = = ( wasm_op_type ) op_type )
count + + ;
if ( count = = post )
return i ;
}
break ;
2019-02-18 09:39:51 +00:00
case CS_ARCH_BPF :
for ( i = 0 ; i < insn - > detail - > bpf . op_count ; i + + ) {
if ( insn - > detail - > bpf . operands [ i ] . type = = ( bpf_op_type ) op_type )
count + + ;
if ( count = = post )
return i ;
}
break ;
2013-11-27 04:11:31 +00:00
}
return - 1 ;
}
2015-03-25 07:02:13 +00:00
CAPSTONE_EXPORT
2016-05-12 04:48:32 +00:00
cs_err CAPSTONE_API cs_regs_access ( csh ud , const cs_insn * insn ,
2015-03-25 07:02:13 +00:00
cs_regs regs_read , uint8_t * regs_read_count ,
cs_regs regs_write , uint8_t * regs_write_count )
{
struct cs_struct * handle ;
if ( ! ud )
return - 1 ;
handle = ( struct cs_struct * ) ( uintptr_t ) ud ;
# ifdef CAPSTONE_DIET
// This API does not work in DIET mode
handle - > errnum = CS_ERR_DIET ;
return CS_ERR_DIET ;
# else
if ( ! handle - > detail ) {
handle - > errnum = CS_ERR_DETAIL ;
return CS_ERR_DETAIL ;
}
if ( ! insn - > id ) {
handle - > errnum = CS_ERR_SKIPDATA ;
return CS_ERR_SKIPDATA ;
}
if ( ! insn - > detail ) {
handle - > errnum = CS_ERR_DETAIL ;
return CS_ERR_DETAIL ;
}
if ( handle - > reg_access ) {
handle - > reg_access ( insn , regs_read , regs_read_count , regs_write , regs_write_count ) ;
} else {
// this arch is unsupported yet
handle - > errnum = CS_ERR_ARCH ;
return CS_ERR_ARCH ;
}
return CS_ERR_OK ;
# endif
}