mirror of
https://github.com/trustedsec/LLVM-Obfuscation-Experiments
synced 2026-06-08 17:57:15 +00:00
commit of experiment code
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
*.obj
|
||||
*.exe
|
||||
.vscode
|
||||
bin
|
||||
dist
|
||||
malware/arsenal-kit
|
||||
.git
|
||||
.pdb
|
||||
@@ -0,0 +1,13 @@
|
||||
This repo is a companion document to the blog post available at \<url\>
|
||||
|
||||
Individual projects under goodware / malware will have readme's referencing the original sources, which all all included here as well in no particular order.
|
||||
|
||||
https://github.com/B-Con/crypto-algorithms/tree/master
|
||||
https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html
|
||||
https://github.com/capstone-engine/capstone/archive/5.0.tar.gz
|
||||
https://download.cobaltstrike.com/scripts
|
||||
https://github.com/gentilkiwi/mimikatz
|
||||
https://github.com/trustedsec/COFFLoader
|
||||
https://github.com/trustedsec/trevorc2
|
||||
https://github.com/silentbreaksec/Throwback
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
cmake_minimum_required (VERSION 3.20)
|
||||
|
||||
MACRO(HEADER_DIRECTORIES return_list)
|
||||
FILE(GLOB_RECURSE new_list /opt/winsdk/sdk/*.h /opt/winsdk/crt/*.h)
|
||||
SET(dir_list "")
|
||||
FOREACH(file_path ${new_list})
|
||||
GET_FILENAME_COMPONENT(dir_path ${file_path} PATH)
|
||||
SET(dir_list ${dir_list} ${dir_path})
|
||||
ENDFOREACH()
|
||||
LIST(REMOVE_DUPLICATES dir_list)
|
||||
SET(${return_list} ${dir_list})
|
||||
ENDMACRO()
|
||||
|
||||
if(NOT CACHE_KEY)
|
||||
HEADER_DIRECTORIES(sdkheaders)
|
||||
set(CACHE_KEY "${sdkheaders}" CACHE INTERNAL "Cached result of the macro")
|
||||
else()
|
||||
set(sdkheaders ${CACHE_KEY})
|
||||
endif()
|
||||
|
||||
set(RC_INCLUDES "")
|
||||
FOREACH(OPT ${sdkheaders})
|
||||
set(RC_INCLUDES ${RC_INCLUDES} " -I ${OPT} ")
|
||||
ENDFOREACH()
|
||||
string(REPLACE ";" " " RC_INCLUDES ${RC_INCLUDES})
|
||||
|
||||
set(CMAKE_SYSTEM_NAME Windows)
|
||||
set(CMAKE_SYSTEM_VERSION 10.0)
|
||||
set(CMAKE_SYSTEM_PROCESSOR x86_64)
|
||||
|
||||
set(CMAKE_ASM_COMPILER "/usr/bin/llvm-ml")
|
||||
set(CMAKE_MASM_COMPILER "/usr/bin/llvm-ml")
|
||||
set(CMAKE_ASM_MASM_COMPILER "/usr/bin/llvm-ml")
|
||||
|
||||
set(CMAKE_C_COMPILER "/usr/bin/clang-cl")
|
||||
set(CMAKE_CXX_COMPILER "/usr/bin/clang-cl")
|
||||
set(CMAKE_RC_COMPILER "/usr/bin/llvm-rc")
|
||||
set(CMAKE_MT "/usr/bin/llvm-mt")
|
||||
set(CMAKE_LINKER "/usr/bin/lld-link")
|
||||
set(CMAKE_C_FLAGS_INIT "/winsdkdir /opt/winsdk/sdk /vctoolsdir /opt/winsdk/crt")
|
||||
set(CMAKE_CXX_FLAGS_INIT "/winsdkdir /opt/winsdk/sdk /vctoolsdir /opt/winsdk/crt")
|
||||
set(CMAKE_EXE_LINKER_FLAGS_INIT "/winsdkdir:/opt/winsdk/sdk /vctoolsdir:/opt/winsdk/crt /MANIFEST:NO")
|
||||
set(CMAKE_RC_FLAGS_INIT "${RC_INCLUDES}")
|
||||
set(CMAKE_C_STANDARD_INCLUDE_DIRECTORIES "${sdkheaders}")
|
||||
set(CMAKE_CXX_STANDARD_INCLUDE_DIRECTORIES "${sdkheaders}")
|
||||
@@ -0,0 +1,13 @@
|
||||
CFLAGS="-Xclang -fpass-plugin=/opt/winsdk/llvm-passes/libStringObfuscation.so" cmake --toolchain /opt/winsdk/LLVM-Obfuscation-Experiments/clang-cl64.toolchain ..
|
||||
CFLAGS="-Xclang -fpass-plugin=/opt/winsdk/llvm-passes/libMBAObfuscation.so -Xclang -fpass-plugin=/opt/winsdk/llvm-passes/libIndirectCall.so -Xclang -fpass-plugin=/opt/winsdk/llvm-passes/libFlattening.so -Xclang -fpass-plugin=/opt/winsdk/llvm-passes/libBogusControlFlow.so" cmake --toolchain /opt/winsdk/LLVM-Obfuscation-Experiments/clang-cl64.toolchain ..
|
||||
|
||||
|
||||
---
|
||||
|
||||
|
||||
CFLAGS="-Xclang -fpass-plugin=/opt/winsdk/llvm-passes/libMBAObfuscation.so" cmake --toolchain /opt/winsdk/LLVM-Obfuscation-Experiments/clang-cl64.toolchain ..
|
||||
CFLAGS="-Xclang -fpass-plugin=/opt/winsdk/llvm-passes/libBogusControlFlow.so" cmake --toolchain /opt/winsdk/LLVM-Obfuscation-Experiments/clang-cl64.toolchain ..
|
||||
CFLAGS="-Xclang -fpass-plugin=/opt/winsdk/llvm-passes/libFlattening.so" cmake --toolchain /opt/winsdk/LLVM-Obfuscation-Experiments/clang-cl64.toolchain ..
|
||||
CFLAGS="-Xclang -fpass-plugin=/opt/winsdk/llvm-passes/libIndirectCall.so" cmake --toolchain /opt/winsdk/LLVM-Obfuscation-Experiments/clang-cl64.toolchain ..
|
||||
|
||||
#for mimikatz you need to modify the CMAKELists file to add the options to the mimikatz cmakelists.txt
|
||||
@@ -0,0 +1,128 @@
|
||||
#should use the -cl version of clang as we are linking against visual studio libraries
|
||||
CC:=clang-cl
|
||||
#we want to use lld-link to line up with what visual studio expects / does
|
||||
#when inline with compiler one would use -fuse-ld=$(LLD)
|
||||
LLD:=lld-link
|
||||
#we want to use llvm-lib to make an msvc compatibile library
|
||||
LIB:=llvm-lib
|
||||
#named variable with base directory we are storing our LLVM passes in
|
||||
LLVMPASSDIR:=/opt/winsdk/llvm-passes
|
||||
#output directory info
|
||||
OUTPUTDIR:=bin
|
||||
BASEOBJDIR=obj
|
||||
OUTPUTNAME:=pickanexename
|
||||
OUTPUTEXT=.exe
|
||||
#populate this with the libraries you are using
|
||||
LIBRARIES:= kernel32.lib user32.lib
|
||||
|
||||
CFLAGS:=/permissive- /DNDEBUG /DUNICODE /D_UNICODE /Iinclude /W1 /Gy /Gw- /Ob1 /Ot /Oy /sdl- /Zo-
|
||||
#link must come after filenames and Cflags
|
||||
LDFLAGS:=/DEBUG:NONE /DYNAMICBASE /GUARD:NO /MANIFEST:EMBED /OPT:NOREF /SUBSYSTEM:WINDOWS
|
||||
|
||||
#out of tree optimizer passes
|
||||
LLVMOPT:=
|
||||
|
||||
WINSDK:=/winsdkdir /opt/winsdk/sdk
|
||||
VCTOOL:=/vctoolsdir /opt/winsdk/crt
|
||||
|
||||
WINSDKLINK:=/winsdkdir:/opt/winsdk/sdk
|
||||
VCTOOLLINK:=/vctoolsdir:/opt/winsdk/crt
|
||||
|
||||
SRC:= $(wildcard src/*.c)
|
||||
SRC += $(wildcard src/*.cpp)
|
||||
|
||||
ifneq ($(filter obfbogus,$(MAKECMDGOALS)),)
|
||||
LLVMOPT+= -Xclang -fpass-plugin=$(LLVMPASSDIR)/libBogusControlFlow.so
|
||||
endif
|
||||
|
||||
ifneq ($(filter obfflat,$(MAKECMDGOALS)),)
|
||||
LLVMOPT+= -Xclang -fpass-plugin=$(LLVMPASSDIR)/libFlattening.so
|
||||
endif
|
||||
|
||||
ifneq ($(filter obfindirect,$(MAKECMDGOALS)),)
|
||||
LLVMOPT+= -Xclang -fpass-plugin=$(LLVMPASSDIR)/libIndirectCall.so
|
||||
endif
|
||||
|
||||
ifneq ($(filter obfmba,$(MAKECMDGOALS)),)
|
||||
LLVMOPT+= -Xclang -fpass-plugin=$(LLVMPASSDIR)/libMBAObfuscation.so
|
||||
endif
|
||||
|
||||
ifneq ($(filter obfstr,$(MAKECMDGOALS)),)
|
||||
LLVMOPT+= -Xclang -fpass-plugin=$(LLVMPASSDIR)/libStringObfuscation.so
|
||||
endif
|
||||
|
||||
ifneq ($(filter 32bit,$(MAKECMDGOALS)),)
|
||||
CFLAGS+= -m32
|
||||
OBJDIR:=$(BASEOBJDIR)32
|
||||
OUTPUTNAME:=$(OUTPUTNAME)_32
|
||||
else
|
||||
OBJDIR:=$(BASEOBJDIR)64
|
||||
OUTPUTNAME:=$(OUTPUTNAME)_64
|
||||
endif
|
||||
|
||||
OBJFILES_C:= $(SRC:src/%.c=$(OBJDIR)/%.obj)
|
||||
OBJFILES:=$(OBJFILES_C:src/%.cpp=$(OBJDIR)/%.obj)
|
||||
|
||||
all: build
|
||||
|
||||
# Pattern rule for .c files
|
||||
$(OBJDIR)/%.obj: src/%.c
|
||||
$(CC) $(WINSDK) $(VCTOOL) $(LLVMOPT) $< $(CFLAGS) /c /Fo$@
|
||||
|
||||
# Pattern rule for .cpp files (if you have C++ sources)
|
||||
$(OBJDIR)/%.obj: src/%.cpp
|
||||
$(CC) $(WINSDK) $(VCTOOL) $(LLVMOPT) $< $(CFLAGS) /std:c++17 /c /Fo$@
|
||||
|
||||
|
||||
build: setup $(OBJFILES)
|
||||
$(LLD) $(WINSDKLINK) $(VCTOOLLINK) $(OBJFILES) $(LDFLAGS) /OUT:$(OUTPUTDIR)/$(OUTPUTNAME)$(OUTPUTEXT) $(LIBRARIES)
|
||||
|
||||
print-src:
|
||||
@echo $(SRC)
|
||||
|
||||
print-obj:
|
||||
@echo $(OBJFILES_C)
|
||||
|
||||
.PHONY: setup obfflat obfindirect obfmba obfstr 32bit obfbogus
|
||||
|
||||
setup:
|
||||
mkdir -p $(BASEOBJDIR)32
|
||||
mkdir -p $(BASEOBJDIR)64
|
||||
mkdir -p bin
|
||||
|
||||
all-tests:
|
||||
make part-clean
|
||||
make all obfbogus
|
||||
mv $(OUTPUTDIR)/$(OUTPUTNAME)$(OUTPUTEXT) $(OUTPUTDIR)/$(OUTPUTNAME)_bogus$(OUTPUTEXT)
|
||||
make part-clean
|
||||
make all obfflat
|
||||
mv $(OUTPUTDIR)/$(OUTPUTNAME)$(OUTPUTEXT) $(OUTPUTDIR)/$(OUTPUTNAME)_flat$(OUTPUTEXT)
|
||||
make part-clean
|
||||
make all obfindirect
|
||||
mv $(OUTPUTDIR)/$(OUTPUTNAME)$(OUTPUTEXT) $(OUTPUTDIR)/$(OUTPUTNAME)_indirect$(OUTPUTEXT)
|
||||
make part-clean
|
||||
make all obfmba
|
||||
mv $(OUTPUTDIR)/$(OUTPUTNAME)$(OUTPUTEXT) $(OUTPUTDIR)/$(OUTPUTNAME)_mba$(OUTPUTEXT)
|
||||
make part-clean
|
||||
make all obfstr
|
||||
mv $(OUTPUTDIR)/$(OUTPUTNAME)$(OUTPUTEXT) $(OUTPUTDIR)/$(OUTPUTNAME)_str$(OUTPUTEXT)
|
||||
make part-clean
|
||||
make all obfbogus obfflat obfindirect obfmba obfstr
|
||||
mv $(OUTPUTDIR)/$(OUTPUTNAME)$(OUTPUTEXT) $(OUTPUTDIR)/$(OUTPUTNAME)_all$(OUTPUTEXT)
|
||||
make part-clean
|
||||
make all
|
||||
make part-clean
|
||||
|
||||
|
||||
part-clean:
|
||||
rm -f $(BASEOBJDIR)32/*
|
||||
rm -f $(BASEOBJDIR)64/*
|
||||
|
||||
|
||||
clean:
|
||||
rm -f $(BASEOBJDIR)32/*
|
||||
rm -f $(BASEOBJDIR)64/*
|
||||
rm -f bin/*
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
I wrote this code
|
||||
@@ -0,0 +1,12 @@
|
||||
#include <Windows.h>
|
||||
|
||||
int WinMain(
|
||||
[in] HINSTANCE hInstance,
|
||||
[in, optional] HINSTANCE hPrevInstance,
|
||||
[in] LPSTR lpCmdLine,
|
||||
[in] int nShowCmd
|
||||
)
|
||||
{
|
||||
MessageBoxA(NULL, "Test compile1", "Test compile", 0);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
/*********************************************************************
|
||||
* Filename: aes.h
|
||||
* Author: Brad Conte (brad AT bradconte.com)
|
||||
* Copyright:
|
||||
* Disclaimer: This code is presented "as is" without any guarantees.
|
||||
* Details: Defines the API for the corresponding AES implementation.
|
||||
*********************************************************************/
|
||||
|
||||
#ifndef AES_H
|
||||
#define AES_H
|
||||
|
||||
/*************************** HEADER FILES ***************************/
|
||||
#include <stddef.h>
|
||||
|
||||
/****************************** MACROS ******************************/
|
||||
#define AES_BLOCK_SIZE 16 // AES operates on 16 bytes at a time
|
||||
|
||||
/**************************** DATA TYPES ****************************/
|
||||
typedef unsigned char BYTE; // 8-bit byte
|
||||
typedef unsigned int WORD; // 32-bit word, change to "long" for 16-bit machines
|
||||
|
||||
/*********************** FUNCTION DECLARATIONS **********************/
|
||||
///////////////////
|
||||
// AES
|
||||
///////////////////
|
||||
// Key setup must be done before any AES en/de-cryption functions can be used.
|
||||
void aes_key_setup(const BYTE key[], // The key, must be 128, 192, or 256 bits
|
||||
WORD w[], // Output key schedule to be used later
|
||||
int keysize); // Bit length of the key, 128, 192, or 256
|
||||
|
||||
void aes_encrypt(const BYTE in[], // 16 bytes of plaintext
|
||||
BYTE out[], // 16 bytes of ciphertext
|
||||
const WORD key[], // From the key setup
|
||||
int keysize); // Bit length of the key, 128, 192, or 256
|
||||
|
||||
void aes_decrypt(const BYTE in[], // 16 bytes of ciphertext
|
||||
BYTE out[], // 16 bytes of plaintext
|
||||
const WORD key[], // From the key setup
|
||||
int keysize); // Bit length of the key, 128, 192, or 256
|
||||
|
||||
///////////////////
|
||||
// AES - CBC
|
||||
///////////////////
|
||||
int aes_encrypt_cbc(const BYTE in[], // Plaintext
|
||||
size_t in_len, // Must be a multiple of AES_BLOCK_SIZE
|
||||
BYTE out[], // Ciphertext, same length as plaintext
|
||||
const WORD key[], // From the key setup
|
||||
int keysize, // Bit length of the key, 128, 192, or 256
|
||||
const BYTE iv[]); // IV, must be AES_BLOCK_SIZE bytes long
|
||||
|
||||
int aes_decrypt_cbc(const BYTE in[], size_t in_len, BYTE out[], const WORD key[], int keysize, const BYTE iv[]);
|
||||
|
||||
// Only output the CBC-MAC of the input.
|
||||
int aes_encrypt_cbc_mac(const BYTE in[], // plaintext
|
||||
size_t in_len, // Must be a multiple of AES_BLOCK_SIZE
|
||||
BYTE out[], // Output MAC
|
||||
const WORD key[], // From the key setup
|
||||
int keysize, // Bit length of the key, 128, 192, or 256
|
||||
const BYTE iv[]); // IV, must be AES_BLOCK_SIZE bytes long
|
||||
|
||||
///////////////////
|
||||
// AES - CTR
|
||||
///////////////////
|
||||
void increment_iv(BYTE iv[], // Must be a multiple of AES_BLOCK_SIZE
|
||||
int counter_size); // Bytes of the IV used for counting (low end)
|
||||
|
||||
void aes_encrypt_ctr(const BYTE in[], // Plaintext
|
||||
size_t in_len, // Any byte length
|
||||
BYTE out[], // Ciphertext, same length as plaintext
|
||||
const WORD key[], // From the key setup
|
||||
int keysize, // Bit length of the key, 128, 192, or 256
|
||||
const BYTE iv[]); // IV, must be AES_BLOCK_SIZE bytes long
|
||||
|
||||
void aes_decrypt_ctr(const BYTE in[], // Ciphertext
|
||||
size_t in_len, // Any byte length
|
||||
BYTE out[], // Plaintext, same length as ciphertext
|
||||
const WORD key[], // From the key setup
|
||||
int keysize, // Bit length of the key, 128, 192, or 256
|
||||
const BYTE iv[]); // IV, must be AES_BLOCK_SIZE bytes long
|
||||
|
||||
///////////////////
|
||||
// AES - CCM
|
||||
///////////////////
|
||||
// Returns True if the input parameters do not violate any constraint.
|
||||
int aes_encrypt_ccm(const BYTE plaintext[], // IN - Plaintext.
|
||||
WORD plaintext_len, // IN - Plaintext length.
|
||||
const BYTE associated_data[], // IN - Associated Data included in authentication, but not encryption.
|
||||
unsigned short associated_data_len, // IN - Associated Data length in bytes.
|
||||
const BYTE nonce[], // IN - The Nonce to be used for encryption.
|
||||
unsigned short nonce_len, // IN - Nonce length in bytes.
|
||||
BYTE ciphertext[], // OUT - Ciphertext, a concatination of the plaintext and the MAC.
|
||||
WORD *ciphertext_len, // OUT - The length of the ciphertext, always plaintext_len + mac_len.
|
||||
WORD mac_len, // IN - The desired length of the MAC, must be 4, 6, 8, 10, 12, 14, or 16.
|
||||
const BYTE key[], // IN - The AES key for encryption.
|
||||
int keysize); // IN - The length of the key in bits. Valid values are 128, 192, 256.
|
||||
|
||||
// Returns True if the input parameters do not violate any constraint.
|
||||
// Use mac_auth to ensure decryption/validation was preformed correctly.
|
||||
// If authentication does not succeed, the plaintext is zeroed out. To overwride
|
||||
// this, call with mac_auth = NULL. The proper proceedure is to decrypt with
|
||||
// authentication enabled (mac_auth != NULL) and make a second call to that
|
||||
// ignores authentication explicitly if the first call failes.
|
||||
int aes_decrypt_ccm(const BYTE ciphertext[], // IN - Ciphertext, the concatination of encrypted plaintext and MAC.
|
||||
WORD ciphertext_len, // IN - Ciphertext length in bytes.
|
||||
const BYTE assoc[], // IN - The Associated Data, required for authentication.
|
||||
unsigned short assoc_len, // IN - Associated Data length in bytes.
|
||||
const BYTE nonce[], // IN - The Nonce to use for decryption, same one as for encryption.
|
||||
unsigned short nonce_len, // IN - Nonce length in bytes.
|
||||
BYTE plaintext[], // OUT - The plaintext that was decrypted. Will need to be large enough to hold ciphertext_len - mac_len.
|
||||
WORD *plaintext_len, // OUT - Length in bytes of the output plaintext, always ciphertext_len - mac_len .
|
||||
WORD mac_len, // IN - The length of the MAC that was calculated.
|
||||
int *mac_auth, // OUT - TRUE if authentication succeeded, FALSE if it did not. NULL pointer will ignore the authentication.
|
||||
const BYTE key[], // IN - The AES key for decryption.
|
||||
int keysize); // IN - The length of the key in BITS. Valid values are 128, 192, 256.
|
||||
|
||||
///////////////////
|
||||
// Test functions
|
||||
///////////////////
|
||||
int aes_test();
|
||||
int aes_ecb_test();
|
||||
int aes_cbc_test();
|
||||
int aes_ctr_test();
|
||||
int aes_ccm_test();
|
||||
|
||||
#endif // AES_H
|
||||
@@ -0,0 +1,128 @@
|
||||
#should use the -cl version of clang as we are linking against visual studio libraries
|
||||
CC:=clang-cl
|
||||
#we want to use lld-link to line up with what visual studio expects / does
|
||||
#when inline with compiler one would use -fuse-ld=$(LLD)
|
||||
LLD:=lld-link
|
||||
#we want to use llvm-lib to make an msvc compatibile library
|
||||
LIB:=llvm-lib
|
||||
#named variable with base directory we are storing our LLVM passes in
|
||||
LLVMPASSDIR:=/opt/winsdk/llvm-passes
|
||||
#output directory info
|
||||
OUTPUTDIR:=bin
|
||||
BASEOBJDIR=obj
|
||||
OUTPUTNAME:=aes256
|
||||
OUTPUTEXT=.exe
|
||||
#populate this with the libraries you are using
|
||||
LIBRARIES:= kernel32.lib user32.lib
|
||||
|
||||
CFLAGS:=/permissive- /DNDEBUG /DUNICODE /D_UNICODE /Iinclude /W1 /Gy /Gw- /Ob1 /Ot /Oy /sdl- /Zo-
|
||||
#link must come after filenames and Cflags
|
||||
LDFLAGS:=/DEBUG:NONE /DYNAMICBASE /GUARD:NO /MANIFEST:EMBED /OPT:NOREF /SUBSYSTEM:CONSOLE
|
||||
|
||||
#out of tree optimizer passes
|
||||
LLVMOPT:=
|
||||
|
||||
WINSDK:=/winsdkdir /opt/winsdk/sdk
|
||||
VCTOOL:=/vctoolsdir /opt/winsdk/crt
|
||||
|
||||
WINSDKLINK:=/winsdkdir:/opt/winsdk/sdk
|
||||
VCTOOLLINK:=/vctoolsdir:/opt/winsdk/crt
|
||||
|
||||
SRC:= $(wildcard src/*.c)
|
||||
SRC += $(wildcard src/*.cpp)
|
||||
|
||||
ifneq ($(filter obfbogus,$(MAKECMDGOALS)),)
|
||||
LLVMOPT+= -Xclang -fpass-plugin=$(LLVMPASSDIR)/libBogusControlFlow.so
|
||||
endif
|
||||
|
||||
ifneq ($(filter obfflat,$(MAKECMDGOALS)),)
|
||||
LLVMOPT+= -Xclang -fpass-plugin=$(LLVMPASSDIR)/libFlattening.so
|
||||
endif
|
||||
|
||||
ifneq ($(filter obfindirect,$(MAKECMDGOALS)),)
|
||||
LLVMOPT+= -Xclang -fpass-plugin=$(LLVMPASSDIR)/libIndirectCall.so
|
||||
endif
|
||||
|
||||
ifneq ($(filter obfmba,$(MAKECMDGOALS)),)
|
||||
LLVMOPT+= -Xclang -fpass-plugin=$(LLVMPASSDIR)/libMBAObfuscation.so
|
||||
endif
|
||||
|
||||
ifneq ($(filter obfstr,$(MAKECMDGOALS)),)
|
||||
LLVMOPT+= -Xclang -fpass-plugin=$(LLVMPASSDIR)/libStringObfuscation.so
|
||||
endif
|
||||
|
||||
ifneq ($(filter 32bit,$(MAKECMDGOALS)),)
|
||||
CFLAGS+= -m32
|
||||
OBJDIR:=$(BASEOBJDIR)32
|
||||
OUTPUTNAME:=$(OUTPUTNAME)_32
|
||||
else
|
||||
OBJDIR:=$(BASEOBJDIR)64
|
||||
OUTPUTNAME:=$(OUTPUTNAME)_64
|
||||
endif
|
||||
|
||||
OBJFILES_C:= $(SRC:src/%.c=$(OBJDIR)/%.obj)
|
||||
OBJFILES:=$(OBJFILES_C:src/%.cpp=$(OBJDIR)/%.obj)
|
||||
|
||||
all: build
|
||||
|
||||
# Pattern rule for .c files
|
||||
$(OBJDIR)/%.obj: src/%.c
|
||||
$(CC) $(WINSDK) $(VCTOOL) $(LLVMOPT) $< $(CFLAGS) /c /Fo$@
|
||||
|
||||
# Pattern rule for .cpp files (if you have C++ sources)
|
||||
$(OBJDIR)/%.obj: src/%.cpp
|
||||
$(CC) $(WINSDK) $(VCTOOL) $(LLVMOPT) $< $(CFLAGS) /std:c++17 /c /Fo$@
|
||||
|
||||
|
||||
build: setup $(OBJFILES)
|
||||
$(LLD) $(WINSDKLINK) $(VCTOOLLINK) $(OBJFILES) $(LDFLAGS) /OUT:$(OUTPUTDIR)/$(OUTPUTNAME)$(OUTPUTEXT) $(LIBRARIES)
|
||||
|
||||
print-src:
|
||||
@echo $(SRC)
|
||||
|
||||
print-obj:
|
||||
@echo $(OBJFILES_C)
|
||||
|
||||
.PHONY: setup obfflat obfindirect obfmba obfstr 32bit obfbogus
|
||||
|
||||
setup:
|
||||
mkdir -p $(BASEOBJDIR)32
|
||||
mkdir -p $(BASEOBJDIR)64
|
||||
mkdir -p bin
|
||||
|
||||
all-tests:
|
||||
make part-clean
|
||||
make all obfbogus
|
||||
mv $(OUTPUTDIR)/$(OUTPUTNAME)$(OUTPUTEXT) $(OUTPUTDIR)/$(OUTPUTNAME)_bogus$(OUTPUTEXT)
|
||||
make part-clean
|
||||
make all obfflat
|
||||
mv $(OUTPUTDIR)/$(OUTPUTNAME)$(OUTPUTEXT) $(OUTPUTDIR)/$(OUTPUTNAME)_flat$(OUTPUTEXT)
|
||||
make part-clean
|
||||
make all obfindirect
|
||||
mv $(OUTPUTDIR)/$(OUTPUTNAME)$(OUTPUTEXT) $(OUTPUTDIR)/$(OUTPUTNAME)_indirect$(OUTPUTEXT)
|
||||
make part-clean
|
||||
make all obfmba
|
||||
mv $(OUTPUTDIR)/$(OUTPUTNAME)$(OUTPUTEXT) $(OUTPUTDIR)/$(OUTPUTNAME)_mba$(OUTPUTEXT)
|
||||
make part-clean
|
||||
# make all obfstr
|
||||
# mv $(OUTPUTDIR)/$(OUTPUTNAME)$(OUTPUTEXT) $(OUTPUTDIR)/$(OUTPUTNAME)_str$(OUTPUTEXT)
|
||||
# make part-clean
|
||||
make all obfbogus obfflat obfindirect obfmba
|
||||
mv $(OUTPUTDIR)/$(OUTPUTNAME)$(OUTPUTEXT) $(OUTPUTDIR)/$(OUTPUTNAME)_all$(OUTPUTEXT)
|
||||
make part-clean
|
||||
make all
|
||||
make part-clean
|
||||
|
||||
|
||||
part-clean:
|
||||
rm -f $(BASEOBJDIR)32/*
|
||||
rm -f $(BASEOBJDIR)64/*
|
||||
|
||||
|
||||
clean:
|
||||
rm -f $(BASEOBJDIR)32/*
|
||||
rm -f $(BASEOBJDIR)64/*
|
||||
rm -f bin/*
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
original source: https://github.com/B-Con/crypto-algorithms/tree/master
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,285 @@
|
||||
/*********************************************************************
|
||||
* Filename: aes_test.c
|
||||
* Author: Brad Conte (brad AT bradconte.com)
|
||||
* Copyright:
|
||||
* Disclaimer: This code is presented "as is" without any guarantees.
|
||||
* Details: Performs known-answer tests on the corresponding AES
|
||||
implementation. These tests do not encompass the full
|
||||
range of available test vectors and are not sufficient
|
||||
for FIPS-140 certification. However, if the tests pass
|
||||
it is very, very likely that the code is correct and was
|
||||
compiled properly. This code also serves as
|
||||
example usage of the functions.
|
||||
*********************************************************************/
|
||||
|
||||
/*************************** HEADER FILES ***************************/
|
||||
#include <stdio.h>
|
||||
#include <memory.h>
|
||||
#include "aes.h"
|
||||
|
||||
/*********************** FUNCTION DEFINITIONS ***********************/
|
||||
void print_hex(BYTE str[], int len)
|
||||
{
|
||||
int idx;
|
||||
|
||||
for(idx = 0; idx < len; idx++)
|
||||
printf("%02x", str[idx]);
|
||||
}
|
||||
|
||||
int aes_ecb_test()
|
||||
{
|
||||
WORD key_schedule[60], idx;
|
||||
BYTE enc_buf[128];
|
||||
BYTE plaintext[2][16] = {
|
||||
{0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96,0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a},
|
||||
{0xae,0x2d,0x8a,0x57,0x1e,0x03,0xac,0x9c,0x9e,0xb7,0x6f,0xac,0x45,0xaf,0x8e,0x51}
|
||||
};
|
||||
BYTE ciphertext[2][16] = {
|
||||
{0xf3,0xee,0xd1,0xbd,0xb5,0xd2,0xa0,0x3c,0x06,0x4b,0x5a,0x7e,0x3d,0xb1,0x81,0xf8},
|
||||
{0x59,0x1c,0xcb,0x10,0xd4,0x10,0xed,0x26,0xdc,0x5b,0xa7,0x4a,0x31,0x36,0x28,0x70}
|
||||
};
|
||||
BYTE key[1][32] = {
|
||||
{0x60,0x3d,0xeb,0x10,0x15,0xca,0x71,0xbe,0x2b,0x73,0xae,0xf0,0x85,0x7d,0x77,0x81,0x1f,0x35,0x2c,0x07,0x3b,0x61,0x08,0xd7,0x2d,0x98,0x10,0xa3,0x09,0x14,0xdf,0xf4}
|
||||
};
|
||||
int pass = 1;
|
||||
|
||||
// Raw ECB mode.
|
||||
//printf("* ECB mode:\n");
|
||||
aes_key_setup(key[0], key_schedule, 256);
|
||||
//printf( "Key : ");
|
||||
//print_hex(key[0], 32);
|
||||
|
||||
for(idx = 0; idx < 2; idx++) {
|
||||
aes_encrypt(plaintext[idx], enc_buf, key_schedule, 256);
|
||||
//printf("\nPlaintext : ");
|
||||
//print_hex(plaintext[idx], 16);
|
||||
//printf("\n-encrypted to: ");
|
||||
//print_hex(enc_buf, 16);
|
||||
pass = pass && !memcmp(enc_buf, ciphertext[idx], 16);
|
||||
|
||||
aes_decrypt(ciphertext[idx], enc_buf, key_schedule, 256);
|
||||
//printf("\nCiphertext : ");
|
||||
//print_hex(ciphertext[idx], 16);
|
||||
//printf("\n-decrypted to: ");
|
||||
//print_hex(enc_buf, 16);
|
||||
pass = pass && !memcmp(enc_buf, plaintext[idx], 16);
|
||||
|
||||
//printf("\n\n");
|
||||
}
|
||||
|
||||
return(pass);
|
||||
}
|
||||
|
||||
int aes_cbc_test()
|
||||
{
|
||||
WORD key_schedule[60];
|
||||
BYTE enc_buf[128];
|
||||
BYTE plaintext[1][32] = {
|
||||
{0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96,0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a,0xae,0x2d,0x8a,0x57,0x1e,0x03,0xac,0x9c,0x9e,0xb7,0x6f,0xac,0x45,0xaf,0x8e,0x51}
|
||||
};
|
||||
BYTE ciphertext[1][32] = {
|
||||
{0xf5,0x8c,0x4c,0x04,0xd6,0xe5,0xf1,0xba,0x77,0x9e,0xab,0xfb,0x5f,0x7b,0xfb,0xd6,0x9c,0xfc,0x4e,0x96,0x7e,0xdb,0x80,0x8d,0x67,0x9f,0x77,0x7b,0xc6,0x70,0x2c,0x7d}
|
||||
};
|
||||
BYTE iv[1][16] = {
|
||||
{0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f}
|
||||
};
|
||||
BYTE key[1][32] = {
|
||||
{0x60,0x3d,0xeb,0x10,0x15,0xca,0x71,0xbe,0x2b,0x73,0xae,0xf0,0x85,0x7d,0x77,0x81,0x1f,0x35,0x2c,0x07,0x3b,0x61,0x08,0xd7,0x2d,0x98,0x10,0xa3,0x09,0x14,0xdf,0xf4}
|
||||
};
|
||||
int pass = 1;
|
||||
|
||||
//printf("* CBC mode:\n");
|
||||
aes_key_setup(key[0], key_schedule, 256);
|
||||
|
||||
//printf( "Key : ");
|
||||
//print_hex(key[0], 32);
|
||||
//printf("\nIV : ");
|
||||
//print_hex(iv[0], 16);
|
||||
|
||||
aes_encrypt_cbc(plaintext[0], 32, enc_buf, key_schedule, 256, iv[0]);
|
||||
//printf("\nPlaintext : ");
|
||||
//print_hex(plaintext[0], 32);
|
||||
//printf("\n-encrypted to: ");
|
||||
//print_hex(enc_buf, 32);
|
||||
//printf("\nCiphertext : ");
|
||||
//print_hex(ciphertext[0], 32);
|
||||
pass = pass && !memcmp(enc_buf, ciphertext[0], 32);
|
||||
|
||||
aes_decrypt_cbc(ciphertext[0], 32, enc_buf, key_schedule, 256, iv[0]);
|
||||
//printf("\nCiphertext : ");
|
||||
//print_hex(ciphertext[0], 32);
|
||||
//printf("\n-decrypted to: ");
|
||||
//print_hex(enc_buf, 32);
|
||||
//printf("\nPlaintext : ");
|
||||
//print_hex(plaintext[0], 32);
|
||||
pass = pass && !memcmp(enc_buf, plaintext[0], 32);
|
||||
|
||||
//printf("\n\n");
|
||||
return(pass);
|
||||
}
|
||||
|
||||
int aes_ctr_test()
|
||||
{
|
||||
WORD key_schedule[60];
|
||||
BYTE enc_buf[128];
|
||||
BYTE plaintext[1][32] = {
|
||||
{0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96,0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a,0xae,0x2d,0x8a,0x57,0x1e,0x03,0xac,0x9c,0x9e,0xb7,0x6f,0xac,0x45,0xaf,0x8e,0x51}
|
||||
};
|
||||
BYTE ciphertext[1][32] = {
|
||||
{0x60,0x1e,0xc3,0x13,0x77,0x57,0x89,0xa5,0xb7,0xa7,0xf5,0x04,0xbb,0xf3,0xd2,0x28,0xf4,0x43,0xe3,0xca,0x4d,0x62,0xb5,0x9a,0xca,0x84,0xe9,0x90,0xca,0xca,0xf5,0xc5}
|
||||
};
|
||||
BYTE iv[1][16] = {
|
||||
{0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff},
|
||||
};
|
||||
BYTE key[1][32] = {
|
||||
{0x60,0x3d,0xeb,0x10,0x15,0xca,0x71,0xbe,0x2b,0x73,0xae,0xf0,0x85,0x7d,0x77,0x81,0x1f,0x35,0x2c,0x07,0x3b,0x61,0x08,0xd7,0x2d,0x98,0x10,0xa3,0x09,0x14,0xdf,0xf4}
|
||||
};
|
||||
int pass = 1;
|
||||
|
||||
//printf("* CTR mode:\n");
|
||||
aes_key_setup(key[0], key_schedule, 256);
|
||||
|
||||
//printf( "Key : ");
|
||||
//print_hex(key[0], 32);
|
||||
//printf("\nIV : ");
|
||||
//print_hex(iv[0], 16);
|
||||
|
||||
aes_encrypt_ctr(plaintext[0], 32, enc_buf, key_schedule, 256, iv[0]);
|
||||
//printf("\nPlaintext : ");
|
||||
//print_hex(plaintext[0], 32);
|
||||
//printf("\n-encrypted to: ");
|
||||
//print_hex(enc_buf, 32);
|
||||
pass = pass && !memcmp(enc_buf, ciphertext[0], 32);
|
||||
|
||||
aes_decrypt_ctr(ciphertext[0], 32, enc_buf, key_schedule, 256, iv[0]);
|
||||
//printf("\nCiphertext : ");
|
||||
//print_hex(ciphertext[0], 32);
|
||||
//printf("\n-decrypted to: ");
|
||||
//print_hex(enc_buf, 32);
|
||||
pass = pass && !memcmp(enc_buf, plaintext[0], 32);
|
||||
|
||||
//printf("\n\n");
|
||||
return(pass);
|
||||
}
|
||||
|
||||
int aes_ccm_test()
|
||||
{
|
||||
int mac_auth;
|
||||
WORD enc_buf_len;
|
||||
BYTE enc_buf[128];
|
||||
BYTE plaintext[3][32] = {
|
||||
{0x20,0x21,0x22,0x23},
|
||||
{0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f},
|
||||
{0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37}
|
||||
};
|
||||
BYTE assoc[3][32] = {
|
||||
{0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07},
|
||||
{0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f},
|
||||
{0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13}
|
||||
};
|
||||
BYTE ciphertext[3][32 + 16] = {
|
||||
{0x71,0x62,0x01,0x5b,0x4d,0xac,0x25,0x5d},
|
||||
{0xd2,0xa1,0xf0,0xe0,0x51,0xea,0x5f,0x62,0x08,0x1a,0x77,0x92,0x07,0x3d,0x59,0x3d,0x1f,0xc6,0x4f,0xbf,0xac,0xcd},
|
||||
{0xe3,0xb2,0x01,0xa9,0xf5,0xb7,0x1a,0x7a,0x9b,0x1c,0xea,0xec,0xcd,0x97,0xe7,0x0b,0x61,0x76,0xaa,0xd9,0xa4,0x42,0x8a,0xa5,0x48,0x43,0x92,0xfb,0xc1,0xb0,0x99,0x51}
|
||||
};
|
||||
BYTE iv[3][16] = {
|
||||
{0x10,0x11,0x12,0x13,0x14,0x15,0x16},
|
||||
{0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17},
|
||||
{0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b}
|
||||
};
|
||||
BYTE key[1][32] = {
|
||||
{0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f}
|
||||
};
|
||||
int pass = 1;
|
||||
|
||||
//printf("* CCM mode:\n");
|
||||
//printf("Key : ");
|
||||
//print_hex(key[0], 16);
|
||||
|
||||
//print_hex(plaintext[0], 4);
|
||||
//print_hex(assoc[0], 8);
|
||||
//print_hex(ciphertext[0], 8);
|
||||
//print_hex(iv[0], 7);
|
||||
//print_hex(key[0], 16);
|
||||
|
||||
aes_encrypt_ccm(plaintext[0], 4, assoc[0], 8, iv[0], 7, enc_buf, &enc_buf_len, 4, key[0], 128);
|
||||
//printf("\nNONCE : ");
|
||||
//print_hex(iv[0], 7);
|
||||
//printf("\nAssoc. Data : ");
|
||||
//print_hex(assoc[0], 8);
|
||||
//printf("\nPayload : ");
|
||||
//print_hex(plaintext[0], 4);
|
||||
//printf("\n-encrypted to: ");
|
||||
//print_hex(enc_buf, enc_buf_len);
|
||||
pass = pass && !memcmp(enc_buf, ciphertext[0], enc_buf_len);
|
||||
|
||||
aes_decrypt_ccm(ciphertext[0], 8, assoc[0], 8, iv[0], 7, enc_buf, &enc_buf_len, 4, &mac_auth, key[0], 128);
|
||||
//printf("\n-Ciphertext : ");
|
||||
//print_hex(ciphertext[0], 8);
|
||||
//printf("\n-decrypted to: ");
|
||||
//print_hex(enc_buf, enc_buf_len);
|
||||
//printf("\nAuthenticated: %d ", mac_auth);
|
||||
pass = pass && !memcmp(enc_buf, plaintext[0], enc_buf_len) && mac_auth;
|
||||
|
||||
|
||||
aes_encrypt_ccm(plaintext[1], 16, assoc[1], 16, iv[1], 8, enc_buf, &enc_buf_len, 6, key[0], 128);
|
||||
//printf("\n\nNONCE : ");
|
||||
//print_hex(iv[1], 8);
|
||||
//printf("\nAssoc. Data : ");
|
||||
//print_hex(assoc[1], 16);
|
||||
//printf("\nPayload : ");
|
||||
//print_hex(plaintext[1], 16);
|
||||
//printf("\n-encrypted to: ");
|
||||
//print_hex(enc_buf, enc_buf_len);
|
||||
pass = pass && !memcmp(enc_buf, ciphertext[1], enc_buf_len);
|
||||
|
||||
aes_decrypt_ccm(ciphertext[1], 22, assoc[1], 16, iv[1], 8, enc_buf, &enc_buf_len, 6, &mac_auth, key[0], 128);
|
||||
//printf("\n-Ciphertext : ");
|
||||
//print_hex(ciphertext[1], 22);
|
||||
//printf("\n-decrypted to: ");
|
||||
//print_hex(enc_buf, enc_buf_len);
|
||||
//printf("\nAuthenticated: %d ", mac_auth);
|
||||
pass = pass && !memcmp(enc_buf, plaintext[1], enc_buf_len) && mac_auth;
|
||||
|
||||
|
||||
aes_encrypt_ccm(plaintext[2], 24, assoc[2], 20, iv[2], 12, enc_buf, &enc_buf_len, 8, key[0], 128);
|
||||
//printf("\n\nNONCE : ");
|
||||
//print_hex(iv[2], 12);
|
||||
//printf("\nAssoc. Data : ");
|
||||
//print_hex(assoc[2], 20);
|
||||
//printf("\nPayload : ");
|
||||
//print_hex(plaintext[2], 24);
|
||||
//printf("\n-encrypted to: ");
|
||||
//print_hex(enc_buf, enc_buf_len);
|
||||
pass = pass && !memcmp(enc_buf, ciphertext[2], enc_buf_len);
|
||||
|
||||
aes_decrypt_ccm(ciphertext[2], 32, assoc[2], 20, iv[2], 12, enc_buf, &enc_buf_len, 8, &mac_auth, key[0], 128);
|
||||
//printf("\n-Ciphertext : ");
|
||||
//print_hex(ciphertext[2], 32);
|
||||
//printf("\n-decrypted to: ");
|
||||
//print_hex(enc_buf, enc_buf_len);
|
||||
//printf("\nAuthenticated: %d ", mac_auth);
|
||||
pass = pass && !memcmp(enc_buf, plaintext[2], enc_buf_len) && mac_auth;
|
||||
|
||||
//printf("\n\n");
|
||||
return(pass);
|
||||
}
|
||||
|
||||
int aes_test()
|
||||
{
|
||||
int pass = 1;
|
||||
|
||||
pass = pass && aes_ecb_test();
|
||||
pass = pass && aes_cbc_test();
|
||||
pass = pass && aes_ctr_test();
|
||||
pass = pass && aes_ccm_test();
|
||||
|
||||
return(pass);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
printf("AES Tests: %s\n", aes_test() ? "SUCCEEDED" : "FAILED");
|
||||
|
||||
return(0);
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
version: 4.0-{build}
|
||||
|
||||
os:
|
||||
- Visual Studio 2015
|
||||
|
||||
before_build:
|
||||
- call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" amd64
|
||||
|
||||
build_script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- cmake -DCMAKE_BUILD_TYPE=RELEASE -G "NMake Makefiles" ..
|
||||
- nmake
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
#
|
||||
# clang-format configuration file. Intended for clang-format >= 11.
|
||||
#
|
||||
# For more information, see:
|
||||
#
|
||||
# Documentation/process/clang-format.rst
|
||||
# https://clang.llvm.org/docs/ClangFormat.html
|
||||
# https://clang.llvm.org/docs/ClangFormatStyleOptions.html
|
||||
#
|
||||
---
|
||||
AccessModifierOffset: -4
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignConsecutiveAssignments: false
|
||||
AlignConsecutiveDeclarations: false
|
||||
AlignEscapedNewlines: DontAlign
|
||||
AlignOperands: true
|
||||
AlignTrailingComments:
|
||||
Kind: Always
|
||||
OverEmptyLines: 2
|
||||
AllowAllParametersOfDeclarationOnNextLine: false
|
||||
AllowShortBlocksOnASingleLine: false
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: None
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
AlwaysBreakTemplateDeclarations: false
|
||||
BinPackArguments: true
|
||||
BinPackParameters: true
|
||||
BraceWrapping:
|
||||
AfterClass: false
|
||||
AfterControlStatement: false
|
||||
AfterEnum: false
|
||||
AfterFunction: true
|
||||
AfterNamespace: true
|
||||
AfterObjCDeclaration: false
|
||||
AfterStruct: false
|
||||
AfterUnion: false
|
||||
AfterExternBlock: false
|
||||
BeforeCatch: false
|
||||
BeforeElse: false
|
||||
IndentBraces: false
|
||||
SplitEmptyFunction: true
|
||||
SplitEmptyRecord: true
|
||||
SplitEmptyNamespace: true
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeBraces: Custom
|
||||
BreakBeforeInheritanceComma: false
|
||||
BreakBeforeTernaryOperators: false
|
||||
BreakConstructorInitializersBeforeComma: false
|
||||
BreakConstructorInitializers: BeforeComma
|
||||
BreakAfterJavaFieldAnnotations: false
|
||||
BreakStringLiterals: false
|
||||
ColumnLimit: 80
|
||||
CommentPragmas: '^ IWYU pragma:'
|
||||
CompactNamespaces: false
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||
ConstructorInitializerIndentWidth: 8
|
||||
ContinuationIndentWidth: 8
|
||||
Cpp11BracedListStyle: false
|
||||
DerivePointerAlignment: false
|
||||
DisableFormat: false
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
FixNamespaceComments: false
|
||||
|
||||
IncludeBlocks: Preserve
|
||||
IncludeCategories:
|
||||
- Regex: '.*'
|
||||
Priority: 1
|
||||
IncludeIsMainRegex: '(Test)?$'
|
||||
IndentCaseLabels: false
|
||||
IndentGotoLabels: false
|
||||
IndentPPDirectives: None
|
||||
IndentWidth: 8
|
||||
IndentWrappedFunctionNames: false
|
||||
JavaScriptQuotes: Leave
|
||||
JavaScriptWrapImports: true
|
||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
MacroBlockBegin: ''
|
||||
MacroBlockEnd: ''
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: None
|
||||
ObjCBinPackProtocolList: Auto
|
||||
ObjCBlockIndentWidth: 8
|
||||
ObjCSpaceAfterProperty: true
|
||||
ObjCSpaceBeforeProtocolList: true
|
||||
|
||||
# Taken from git's rules
|
||||
PenaltyBreakAssignment: 10
|
||||
PenaltyBreakBeforeFirstCallParameter: 30
|
||||
PenaltyBreakComment: 10
|
||||
PenaltyBreakFirstLessLess: 0
|
||||
PenaltyBreakString: 10
|
||||
PenaltyExcessCharacter: 100
|
||||
PenaltyReturnTypeOnItsOwnLine: 60
|
||||
|
||||
PointerAlignment: Right
|
||||
ReflowComments: false
|
||||
SortIncludes: false
|
||||
SortUsingDeclarations: false
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceAfterTemplateKeyword: true
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeCtorInitializerColon: true
|
||||
SpaceBeforeInheritanceColon: true
|
||||
SpaceBeforeParens: ControlStatementsExceptForEachMacros
|
||||
SpaceBeforeRangeBasedForLoopColon: true
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 1
|
||||
SpacesInAngles: false
|
||||
SpacesInContainerLiterals: false
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
Standard: Cpp03
|
||||
TabWidth: 8
|
||||
UseTab: Always
|
||||
@@ -0,0 +1,22 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
|
||||
[*.{py,pyx,pxd}]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
# Follow Linux kernel coding style
|
||||
[*.{c,h,cpp,hpp,inc}]
|
||||
indent_style = tab
|
||||
indent_size = 8
|
||||
|
||||
# OCaml bindings
|
||||
[*.ml]
|
||||
indent_style = tab
|
||||
indent_size = 4
|
||||
|
||||
[Makefile]
|
||||
indent_style = tab
|
||||
@@ -0,0 +1 @@
|
||||
/arch/**/*.inc linguist-language=C
|
||||
+149
@@ -0,0 +1,149 @@
|
||||
name: Run Test
|
||||
on:
|
||||
push:
|
||||
paths-ignore:
|
||||
- ".gitignore"
|
||||
- "docs/**"
|
||||
- "ChangeLog"
|
||||
- "CREDITS.TXT"
|
||||
- "COMPILE.TXT"
|
||||
- "COMPILE_MSVC.TXT"
|
||||
- "COMPILE_CMAKE.TXT"
|
||||
- "HACK.TXT"
|
||||
- "LICENSE.TXT"
|
||||
- "LICENSE_LLVM.TXT"
|
||||
- "README.md"
|
||||
- "RELEASE_NOTES"
|
||||
- "SPONSORS.TXT"
|
||||
- "TODO"
|
||||
pull_request:
|
||||
|
||||
env:
|
||||
CI: true
|
||||
|
||||
jobs:
|
||||
Linux:
|
||||
runs-on: ${{ matrix.config.os }}
|
||||
name: ${{ matrix.config.name }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
config:
|
||||
- {
|
||||
name: 'ubuntu-20.04 x64 python3.6 cmake',
|
||||
os: ubuntu-20.04,
|
||||
arch: x64,
|
||||
python-arch: x64,
|
||||
python-version: '3.6',
|
||||
build-system: 'cmake',
|
||||
}
|
||||
- {
|
||||
name: 'ubuntu-22.04 x64 python3.9 make',
|
||||
os: ubuntu-22.04,
|
||||
arch: x64,
|
||||
python-arch: x64,
|
||||
python-version: '3.9',
|
||||
build-system: 'make',
|
||||
}
|
||||
- {
|
||||
name: 'ubuntu-22.04 x64 python3.9 cmake',
|
||||
os: ubuntu-22.04,
|
||||
arch: x64,
|
||||
python-arch: x64,
|
||||
python-version: '3.9',
|
||||
build-system: 'cmake',
|
||||
}
|
||||
- {
|
||||
name: 'ubuntu-22.04 x64 python3.11 cmake',
|
||||
os: ubuntu-22.04,
|
||||
arch: x64,
|
||||
python-arch: x64,
|
||||
python-version: '3.11',
|
||||
build-system: 'cmake',
|
||||
}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: ${{ matrix.config.python-version }}
|
||||
|
||||
- name: prepare
|
||||
shell: 'script -q -e -c "bash {0}"'
|
||||
run: |
|
||||
export LD_LIBRARY_PATH=`pwd`/tests/:$LD_LIBRARY_PATH
|
||||
wget https://github.com/groundx/capstonefuzz/raw/master/corpus/corpus-libFuzzer-capstone_fuzz_disasmnext-latest.zip
|
||||
unzip -q corpus-libFuzzer-capstone_fuzz_disasmnext-latest.zip -d suite/fuzz
|
||||
git clone https://git.cryptomilk.org/projects/cmocka.git suite/cstest/cmocka
|
||||
chmod +x suite/cstest/build_cstest.sh
|
||||
|
||||
- name: make
|
||||
if: startsWith(matrix.config.build-system, 'make')
|
||||
shell: 'script -q -e -c "bash {0}"'
|
||||
run: |
|
||||
./make.sh;
|
||||
make check;
|
||||
cp libcapstone.so.5 libcapstone.so.5.0
|
||||
# sudo make install
|
||||
|
||||
- name: cmake
|
||||
if: startsWith(matrix.config.build-system, 'cmake')
|
||||
shell: 'script -q -e -c "bash {0}"'
|
||||
run: |
|
||||
mkdir build && cd build;
|
||||
cmake -DCAPSTONE_INSTALL=1 -DBUILD_SHARED_LIBS=1 ..;
|
||||
cmake --build . --config Release;
|
||||
cp libcapstone.* ../;
|
||||
# sudo make install;
|
||||
|
||||
- name: build python binding
|
||||
shell: 'script -q -e -c "bash {0}"'
|
||||
run: |
|
||||
mkdir -p bindings/python/capstone/lib && cp libcapstone.so.5.* bindings/python/capstone/lib/libcapstone.so;
|
||||
cd bindings/python;
|
||||
make && make check ;
|
||||
cd ../..;
|
||||
|
||||
- name: cstest
|
||||
shell: 'script -q -e -c "bash {0}"'
|
||||
run: |
|
||||
cd suite/cstest && ./build_cstest.sh;
|
||||
python cstest_report.py -D -t build/cstest -d ../MC;
|
||||
python cstest_report.py -D -t build/cstest -f issues.cs; cd ..;
|
||||
|
||||
Windows:
|
||||
runs-on: ${{ matrix.config.os }}
|
||||
name: ${{ matrix.config.name }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
config:
|
||||
- name: 'windows x64 MSVC 64bit'
|
||||
os: windows-latest
|
||||
arch: x64
|
||||
platform: windows
|
||||
python-arch: x64
|
||||
python-version: '3.9'
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- uses: lukka/get-cmake@latest
|
||||
name: Get CMake
|
||||
|
||||
- name: '🛠️ Win MSVC 64 setup'
|
||||
if: contains(matrix.config.name, 'MSVC 64')
|
||||
uses: ilammy/msvc-dev-cmd@v1
|
||||
with:
|
||||
arch: 'x64'
|
||||
|
||||
- name: '🚧 Win MSVC 64 build'
|
||||
if: contains(matrix.config.name, 'MSVC 64')
|
||||
shell: bash
|
||||
run: |
|
||||
cmake --version
|
||||
cmake --preset=${{ matrix.config.platform }}-x64
|
||||
cmake --build --preset build-${{ matrix.config.platform }}-release
|
||||
cmake --build --preset install-${{ matrix.config.platform }}-release
|
||||
@@ -0,0 +1,50 @@
|
||||
name: Build Source Release
|
||||
|
||||
# Trigger whenever a release is created
|
||||
on:
|
||||
release:
|
||||
types:
|
||||
- created
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- name: archive
|
||||
id: archive
|
||||
run: |
|
||||
VERSION=${{ github.event.release.tag_name }}
|
||||
PKGNAME="capstone-$VERSION"
|
||||
SHASUM=$PKGNAME.tar.xz.sha256
|
||||
mkdir -p /tmp/$PKGNAME
|
||||
mv * /tmp/$PKGNAME
|
||||
mv /tmp/$PKGNAME .
|
||||
TARBALL=$PKGNAME.tar.xz
|
||||
tar cJf $TARBALL $PKGNAME
|
||||
sha256sum $TARBALL > $SHASUM
|
||||
echo "::set-output name=tarball::$TARBALL"
|
||||
echo "::set-output name=shasum::$SHASUM"
|
||||
- name: upload tarball
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ github.event.release.upload_url }}
|
||||
asset_path: ./${{ steps.archive.outputs.tarball }}
|
||||
asset_name: ${{ steps.archive.outputs.tarball }}
|
||||
asset_content_type: application/gzip
|
||||
|
||||
- name: upload shasum
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ github.event.release.upload_url }}
|
||||
asset_path: ./${{ steps.archive.outputs.shasum }}
|
||||
asset_name: ${{ steps.archive.outputs.shasum }}
|
||||
asset_content_type: text/plain
|
||||
@@ -0,0 +1,23 @@
|
||||
name: CIFuzz
|
||||
on: [pull_request]
|
||||
jobs:
|
||||
Fuzzing:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Build Fuzzers
|
||||
uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master
|
||||
with:
|
||||
oss-fuzz-project-name: 'capstone'
|
||||
dry-run: false
|
||||
- name: Run Fuzzers
|
||||
uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master
|
||||
with:
|
||||
oss-fuzz-project-name: 'capstone'
|
||||
fuzz-seconds: 600
|
||||
dry-run: false
|
||||
- name: Upload Crash
|
||||
uses: actions/upload-artifact@v3
|
||||
if: failure()
|
||||
with:
|
||||
name: artifacts
|
||||
path: ./out/artifacts
|
||||
@@ -0,0 +1,83 @@
|
||||
name: PyPI 📦 Distribution
|
||||
|
||||
on:
|
||||
push:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [macos-latest, ubuntu-latest, windows-latest]
|
||||
platform: [x32, x64]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.x'
|
||||
|
||||
- name: Set up MSVC x86
|
||||
if: matrix.os == 'windows-latest' && matrix.platform == 'x32'
|
||||
uses: ilammy/msvc-dev-cmd@v1
|
||||
with:
|
||||
arch: x86
|
||||
|
||||
- name: Set up MSVC x64
|
||||
if: matrix.os == 'windows-latest' && matrix.platform == 'x64'
|
||||
uses: ilammy/msvc-dev-cmd@v1
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
pip install setuptools wheel
|
||||
- name: Build distribution 📦
|
||||
shell: bash
|
||||
run: |
|
||||
if [ ${{ matrix.platform }} == 'x32' ] && [ ${{ matrix.os }} == 'windows-latest' ]; then
|
||||
cd bindings/python && python setup.py build -p win32 bdist_wheel -p win32
|
||||
elif [ ${{ matrix.platform }} == 'x32' ] && [ ${{ matrix.os }} == 'ubuntu-latest' ]; then
|
||||
docker run --rm -v `pwd`/:/work dockcross/manylinux1-x86 > ./dockcross
|
||||
chmod +x ./dockcross
|
||||
chmod +x bindings/python/build_wheel.sh
|
||||
./dockcross bindings/python/build_wheel.sh
|
||||
elif [ ${{ matrix.platform }} == 'x64' ] && [ ${{ matrix.os }} == 'ubuntu-latest' ]; then
|
||||
docker run --rm -v `pwd`/:/work dockcross/manylinux1-x64 > ./dockcross
|
||||
chmod +x ./dockcross
|
||||
chmod +x bindings/python/build_wheel.sh
|
||||
./dockcross bindings/python/build_wheel.sh
|
||||
elif [ ${{ matrix.platform }} == 'x32' ] && [ ${{ matrix.os }} == 'macos-latest' ]; then
|
||||
cd bindings/python && python setup.py sdist
|
||||
else
|
||||
cd bindings/python && python setup.py bdist_wheel
|
||||
fi
|
||||
- uses: actions/upload-artifact@v3
|
||||
with:
|
||||
path: ${{ github.workspace }}/bindings/python/dist/*
|
||||
|
||||
publish:
|
||||
needs: [build]
|
||||
runs-on: ubuntu-latest
|
||||
if: startsWith(github.ref, 'refs/tags')
|
||||
permissions:
|
||||
id-token: write
|
||||
steps:
|
||||
- uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: artifact
|
||||
path: dist
|
||||
|
||||
# - name: Publish distribution 📦 to test PyPI
|
||||
# uses: pypa/gh-action-pypi-publish@release/v1
|
||||
# with:
|
||||
# user: __token__
|
||||
# password: ${{ secrets.test_pypi_pass }}
|
||||
# repository_url: https://test.pypi.org/legacy/
|
||||
|
||||
- name: Publish distribution 📦 to PyPI
|
||||
if: ${{ success() }}
|
||||
uses: pypa/gh-action-pypi-publish@release/v1
|
||||
with:
|
||||
user: __token__
|
||||
password: ${{ secrets.pypi_pass }}
|
||||
@@ -0,0 +1,135 @@
|
||||
.DS_Store
|
||||
|
||||
# Object files
|
||||
*.o
|
||||
*.ko
|
||||
|
||||
# Gcc dependency-tracking files
|
||||
*.d
|
||||
|
||||
# Libraries
|
||||
*.lib
|
||||
*.a
|
||||
|
||||
# Shared objects (inc. Windows DLLs)
|
||||
*.dll
|
||||
*.so
|
||||
*.so.*
|
||||
*.dylib
|
||||
|
||||
# Executables
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
||||
|
||||
# python
|
||||
bindings/python/build/
|
||||
bindings/python/capstone.egg-info/
|
||||
*.pyc
|
||||
|
||||
# java
|
||||
bindings/java/capstone.jar
|
||||
|
||||
# ocaml
|
||||
bindings/ocaml/*.cmi
|
||||
bindings/ocaml/*.cmx
|
||||
bindings/ocaml/*.cmxa
|
||||
bindings/ocaml/*.mli
|
||||
bindings/ocaml/test
|
||||
bindings/ocaml/test_arm
|
||||
bindings/ocaml/test_arm64
|
||||
bindings/ocaml/test_basic
|
||||
bindings/ocaml/test_mips
|
||||
bindings/ocaml/test_x86
|
||||
bindings/ocaml/test_detail
|
||||
bindings/ocaml/test_ppc
|
||||
bindings/ocaml/test_sparc
|
||||
bindings/ocaml/test_systemz
|
||||
bindings/ocaml/test_xcore
|
||||
bindings/ocaml/test_m680x
|
||||
|
||||
|
||||
# test binaries
|
||||
tests/test_basic
|
||||
tests/test_detail
|
||||
tests/test_iter
|
||||
tests/test_arm
|
||||
tests/test_arm64
|
||||
tests/test_mips
|
||||
tests/test_x86
|
||||
tests/test_ppc
|
||||
tests/test_skipdata
|
||||
tests/test_sparc
|
||||
tests/test_systemz
|
||||
tests/test_xcore
|
||||
tests/test_tricore
|
||||
tests/*.static
|
||||
tests/test_customized_mnem
|
||||
tests/test_m68k
|
||||
tests/test_tms320c64x
|
||||
tests/test_m680x
|
||||
tests/test_evm
|
||||
tests/test_wasm
|
||||
tests/test_mos65xx
|
||||
tests/test_bpf
|
||||
tests/test_riscv
|
||||
|
||||
# regress binaries
|
||||
suite/regress/invalid_read_in_print_operand
|
||||
|
||||
# vim tmp file
|
||||
*.swp
|
||||
*~
|
||||
|
||||
capstone.pc
|
||||
|
||||
# local files
|
||||
_*
|
||||
|
||||
# freebsd ports: generated file with "make makesum" command
|
||||
packages/freebsd/ports/devel/capstone/distinfo
|
||||
|
||||
# VisualStudio
|
||||
ProjectUpgradeLog.log
|
||||
Debug/
|
||||
Release/
|
||||
ipch/
|
||||
build*/
|
||||
*.sdf
|
||||
*.opensdf
|
||||
*.suo
|
||||
*.user
|
||||
*.backup
|
||||
*.VC.db
|
||||
*.VC.opendb
|
||||
.vscode/
|
||||
|
||||
# CMake build directories
|
||||
build*/
|
||||
/build
|
||||
/out
|
||||
|
||||
# Xcode
|
||||
xcode/Capstone.xcodeproj/xcuserdata
|
||||
xcode/Capstone.xcodeproj/project.xcworkspace/xcuserdata
|
||||
|
||||
# suite/
|
||||
corpus-libFuzzer-capstone_fuzz_disasmnext-latest.zip
|
||||
test_arm_regression
|
||||
test_arm_regression.o
|
||||
fuzz_harness
|
||||
test_iter_benchmark
|
||||
test_file_benchmark
|
||||
fuzz_bindisasm
|
||||
fuzz_disasm
|
||||
fuzz_decode_platform
|
||||
capstone_get_setup
|
||||
suite/fuzz/
|
||||
suite/cstest/cmocka/
|
||||
|
||||
*.s
|
||||
|
||||
cstool/cstool
|
||||
|
||||
# android
|
||||
android-ndk-*
|
||||
@@ -0,0 +1,66 @@
|
||||
language: cpp
|
||||
sudo: false
|
||||
before_install:
|
||||
- export LD_LIBRARY_PATH=`pwd`/tests/:$LD_LIBRARY_PATH
|
||||
before_script:
|
||||
- wget https://github.com/groundx/capstonefuzz/raw/master/corpus/corpus-libFuzzer-capstone_fuzz_disasmnext-latest.zip
|
||||
- unzip -q corpus-libFuzzer-capstone_fuzz_disasmnext-latest.zip -d suite/fuzz
|
||||
# TODO remove built in cmocka compile and use system cmocka (including brewfile) once xenial is default
|
||||
- git clone https://git.cryptomilk.org/projects/cmocka.git suite/cstest/cmocka
|
||||
- chmod +x suite/cstest/build_cstest.sh
|
||||
- if [[ ${TRAVIS_OS_NAME} = linux ]]; then export PATH="/usr/lib/llvm-9/bin:${PATH}"; fi
|
||||
script:
|
||||
- ./make.sh
|
||||
- make check
|
||||
- sudo make install
|
||||
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then cp libcapstone.so.* bindings/python/libcapstone.so; fi
|
||||
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then cp libcapstone.*.dylib bindings/python/libcapstone.dylib; fi
|
||||
- if [[ "$NOPYTEST" != "true" ]]; then cd bindings/python && make check; cd ../..; fi
|
||||
- if [[ "$NOPYTEST" != "true" ]]; then cd suite/cstest && ./build_cstest.sh; fi
|
||||
- if [[ "$NOPYTEST" != "true" ]]; then python cstest_report.py -D -t build/cstest -d ../MC; fi
|
||||
- if [[ "$NOPYTEST" != "true" ]]; then python cstest_report.py -D -t build/cstest -f issues.cs; fi
|
||||
- if [ -n "$QA_FUZZIT" ]; then suite/fuzz/fuzzit.sh; fi
|
||||
compiler:
|
||||
- clang
|
||||
- gcc
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
matrix:
|
||||
include:
|
||||
- name: xenial gcc
|
||||
os: linux
|
||||
dist: xenial
|
||||
compiler: gcc
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- libcmocka-dev
|
||||
- name: xenial clang
|
||||
os: linux
|
||||
dist: xenial
|
||||
compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- libcmocka-dev
|
||||
- name: fuzza
|
||||
env: ASAN_OPTIONS=detect_leaks=0 CXXFLAGS="-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=address -fsanitize=fuzzer-no-link" CFLAGS="-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=address -fsanitize=fuzzer-no-link" LDFLAGS="-fsanitize=address" NOPYTEST=true QA_FUZZIT=asan
|
||||
compiler: clang
|
||||
os: linux
|
||||
- name: fuzzm
|
||||
env: CXXFLAGS="-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=memory -fsanitize=fuzzer-no-link" CFLAGS="-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=memory -fsanitize=fuzzer-no-link" LDFLAGS="-fsanitize=memory" NOPYTEST=true QA_FUZZIT=msan
|
||||
compiler: clang
|
||||
os: linux
|
||||
- name: fuzzu
|
||||
env: CXXFLAGS="-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=undefined -fsanitize=fuzzer-no-link" CFLAGS="-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=undefined -fno-sanitize-recover=undefined,integer -fsanitize=fuzzer-no-link" LDFLAGS="-fsanitize=undefined" NOPYTEST=true QA_FUZZIT=ubsan
|
||||
compiler: clang
|
||||
os: linux
|
||||
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- llvm-toolchain-trusty
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- clang-9
|
||||
@@ -0,0 +1,776 @@
|
||||
# For MSVC_RUNTIME_LIBRARY
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
|
||||
if(CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR)
|
||||
message(FATAL_ERROR "In-tree builds are not supported. Run CMake from a separate directory: cmake -B build")
|
||||
endif()
|
||||
|
||||
# Detect whether capstone is compiled as top-level or a subdirectory
|
||||
set(PROJECT_IS_TOP_LEVEL OFF)
|
||||
if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
|
||||
set(PROJECT_IS_TOP_LEVEL ON)
|
||||
|
||||
# Enable folder support
|
||||
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
||||
endif()
|
||||
|
||||
# https://cmake.org/cmake/help/latest/policy/CMP0042.html
|
||||
cmake_policy(SET CMP0042 NEW)
|
||||
|
||||
# https://cmake.org/cmake/help/latest/policy/CMP0091.html
|
||||
# Enable support for MSVC_RUNTIME_LIBRARY
|
||||
cmake_policy(SET CMP0091 NEW)
|
||||
|
||||
project(capstone
|
||||
VERSION 5.0
|
||||
)
|
||||
|
||||
if (MSVC)
|
||||
add_compile_options(/W1 /w14189)
|
||||
else()
|
||||
add_compile_options(-Wmissing-braces -Wunused-function -Warray-bounds -Wunused-variable -Wparentheses -Wint-in-bool-context)
|
||||
endif()
|
||||
|
||||
|
||||
# to configure the options specify them in in the command line or change them in the cmake UI.
|
||||
# Don't edit the makefile!
|
||||
option(BUILD_SHARED_LIBS "Build shared library" OFF)
|
||||
option(CAPSTONE_BUILD_STATIC_RUNTIME "Embed static runtime" ${BUILD_SHARED_LIBS})
|
||||
option(CAPSTONE_BUILD_DIET "Build diet library" OFF)
|
||||
option(CAPSTONE_BUILD_TESTS "Build tests" ${PROJECT_IS_TOP_LEVEL})
|
||||
option(CAPSTONE_BUILD_CSTOOL "Build cstool" ${PROJECT_IS_TOP_LEVEL})
|
||||
option(CAPSTONE_BUILD_CSTEST "Build cstest" OFF)
|
||||
option(CAPSTONE_USE_DEFAULT_ALLOC "Use default memory allocation functions" ON)
|
||||
option(CAPSTONE_ARCHITECTURE_DEFAULT "Whether architectures are enabled by default" ON)
|
||||
option(CAPSTONE_DEBUG "Whether to enable extra debug assertions" OFF)
|
||||
option(CAPSTONE_INSTALL "Generate install target" ${PROJECT_IS_TOP_LEVEL})
|
||||
|
||||
set(SUPPORTED_ARCHITECTURES ARM ARM64 M68K MIPS PPC SPARC SYSZ XCORE X86 TMS320C64X M680X EVM MOS65XX WASM BPF RISCV SH TRICORE)
|
||||
set(SUPPORTED_ARCHITECTURE_LABELS ARM ARM64 M68K MIPS PowerPC Sparc SystemZ XCore x86 TMS320C64x M680x EVM MOS65XX WASM BPF RISCV SH TriCore)
|
||||
|
||||
list(LENGTH SUPPORTED_ARCHITECTURES count)
|
||||
math(EXPR count "${count}-1")
|
||||
# create options controlling whether support for a particular architecture is needed
|
||||
foreach(i RANGE ${count})
|
||||
list(GET SUPPORTED_ARCHITECTURES ${i} supported_architecture)
|
||||
list(GET SUPPORTED_ARCHITECTURE_LABELS ${i} supported_architecture_label)
|
||||
option("CAPSTONE_${supported_architecture}_SUPPORT" "${supported_architecture_label} support" ${CAPSTONE_ARCHITECTURE_DEFAULT})
|
||||
endforeach()
|
||||
|
||||
# propagate architecture support variables to preprocessor
|
||||
foreach(supported_architecture ${SUPPORTED_ARCHITECTURES})
|
||||
set(option_name "CAPSTONE_${supported_architecture}_SUPPORT")
|
||||
if(${option_name})
|
||||
message("Enabling ${option_name}")
|
||||
add_definitions("-D${option_name}")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
option(CAPSTONE_X86_REDUCE "x86 with reduce instruction sets to minimize library" OFF)
|
||||
option(CAPSTONE_X86_ATT_DISABLE "Disable x86 AT&T syntax" OFF)
|
||||
option(CAPSTONE_OSXKERNEL_SUPPORT "Support to embed Capstone into OS X Kernel extensions" OFF)
|
||||
|
||||
if(CAPSTONE_BUILD_DIET)
|
||||
add_definitions(-DCAPSTONE_DIET)
|
||||
endif()
|
||||
|
||||
if(CAPSTONE_USE_DEFAULT_ALLOC)
|
||||
add_definitions(-DCAPSTONE_USE_SYS_DYN_MEM)
|
||||
endif()
|
||||
|
||||
if(CAPSTONE_X86_REDUCE)
|
||||
add_definitions(-DCAPSTONE_X86_REDUCE)
|
||||
endif()
|
||||
|
||||
if(CAPSTONE_X86_ATT_DISABLE)
|
||||
add_definitions(-DCAPSTONE_X86_ATT_DISABLE)
|
||||
endif()
|
||||
|
||||
if(CAPSTONE_DEBUG)
|
||||
add_definitions(-DCAPSTONE_DEBUG)
|
||||
endif()
|
||||
|
||||
# Force static runtime libraries
|
||||
if(CAPSTONE_BUILD_STATIC_RUNTIME)
|
||||
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
|
||||
endif()
|
||||
|
||||
## sources
|
||||
set(SOURCES_ENGINE
|
||||
cs.c
|
||||
Mapping.c
|
||||
MCInst.c
|
||||
MCInstrDesc.c
|
||||
MCRegisterInfo.c
|
||||
SStream.c
|
||||
utils.c
|
||||
)
|
||||
set(HEADERS_ENGINE
|
||||
cs_simple_types.h
|
||||
cs_priv.h
|
||||
LEB128.h
|
||||
Mapping.h
|
||||
MathExtras.h
|
||||
MCDisassembler.h
|
||||
MCFixedLenDisassembler.h
|
||||
MCInst.h
|
||||
MCInstrDesc.h
|
||||
MCRegisterInfo.h
|
||||
SStream.h
|
||||
utils.h
|
||||
)
|
||||
|
||||
set(HEADERS_COMMON
|
||||
include/capstone/arm64.h
|
||||
include/capstone/arm.h
|
||||
include/capstone/capstone.h
|
||||
include/capstone/evm.h
|
||||
include/capstone/wasm.h
|
||||
include/capstone/mips.h
|
||||
include/capstone/ppc.h
|
||||
include/capstone/x86.h
|
||||
include/capstone/sparc.h
|
||||
include/capstone/systemz.h
|
||||
include/capstone/xcore.h
|
||||
include/capstone/m68k.h
|
||||
include/capstone/tms320c64x.h
|
||||
include/capstone/m680x.h
|
||||
include/capstone/mos65xx.h
|
||||
include/capstone/bpf.h
|
||||
include/capstone/riscv.h
|
||||
include/capstone/sh.h
|
||||
include/capstone/tricore.h
|
||||
include/capstone/platform.h
|
||||
)
|
||||
|
||||
set(TEST_SOURCES test_basic.c test_detail.c test_skipdata.c test_iter.c)
|
||||
|
||||
## architecture support
|
||||
if(CAPSTONE_ARM_SUPPORT)
|
||||
add_definitions(-DCAPSTONE_HAS_ARM)
|
||||
set(SOURCES_ARM
|
||||
arch/ARM/ARMDisassembler.c
|
||||
arch/ARM/ARMInstPrinter.c
|
||||
arch/ARM/ARMMapping.c
|
||||
arch/ARM/ARMModule.c
|
||||
)
|
||||
set(HEADERS_ARM
|
||||
arch/ARM/ARMAddressingModes.h
|
||||
arch/ARM/ARMBaseInfo.h
|
||||
arch/ARM/ARMDisassembler.h
|
||||
arch/ARM/ARMInstPrinter.h
|
||||
arch/ARM/ARMMapping.h
|
||||
arch/ARM/ARMGenAsmWriter.inc
|
||||
arch/ARM/ARMGenDisassemblerTables.inc
|
||||
arch/ARM/ARMGenInstrInfo.inc
|
||||
arch/ARM/ARMGenRegisterInfo.inc
|
||||
arch/ARM/ARMGenSubtargetInfo.inc
|
||||
arch/ARM/ARMMappingInsn.inc
|
||||
arch/ARM/ARMMappingInsnOp.inc
|
||||
arch/ARM/ARMGenRegisterName.inc
|
||||
arch/ARM/ARMGenRegisterName_digit.inc
|
||||
arch/ARM/ARMGenSystemRegister.inc
|
||||
arch/ARM/ARMMappingInsnName.inc
|
||||
)
|
||||
set(TEST_SOURCES ${TEST_SOURCES} test_arm.c)
|
||||
endif()
|
||||
|
||||
if(CAPSTONE_ARM64_SUPPORT)
|
||||
add_definitions(-DCAPSTONE_HAS_ARM64)
|
||||
set(SOURCES_ARM64
|
||||
arch/AArch64/AArch64BaseInfo.c
|
||||
arch/AArch64/AArch64Disassembler.c
|
||||
arch/AArch64/AArch64InstPrinter.c
|
||||
arch/AArch64/AArch64Mapping.c
|
||||
arch/AArch64/AArch64Module.c
|
||||
)
|
||||
set(HEADERS_ARM64
|
||||
arch/AArch64/AArch64AddressingModes.h
|
||||
arch/AArch64/AArch64BaseInfo.h
|
||||
arch/AArch64/AArch64Disassembler.h
|
||||
arch/AArch64/AArch64InstPrinter.h
|
||||
arch/AArch64/AArch64Mapping.h
|
||||
arch/AArch64/AArch64GenAsmWriter.inc
|
||||
arch/AArch64/AArch64GenDisassemblerTables.inc
|
||||
arch/AArch64/AArch64GenInstrInfo.inc
|
||||
arch/AArch64/AArch64GenRegisterInfo.inc
|
||||
arch/AArch64/AArch64GenRegisterName.inc
|
||||
arch/AArch64/AArch64GenRegisterV.inc
|
||||
arch/AArch64/AArch64GenSubtargetInfo.inc
|
||||
arch/AArch64/AArch64GenSystemOperands.inc
|
||||
arch/AArch64/AArch64GenSystemOperands_enum.inc
|
||||
arch/AArch64/AArch64MappingInsn.inc
|
||||
arch/AArch64/AArch64MappingInsnName.inc
|
||||
arch/AArch64/AArch64MappingInsnOp.inc
|
||||
)
|
||||
set(TEST_SOURCES ${TEST_SOURCES} test_arm64.c)
|
||||
endif()
|
||||
|
||||
if(CAPSTONE_MIPS_SUPPORT)
|
||||
add_definitions(-DCAPSTONE_HAS_MIPS)
|
||||
set(SOURCES_MIPS
|
||||
arch/Mips/MipsDisassembler.c
|
||||
arch/Mips/MipsInstPrinter.c
|
||||
arch/Mips/MipsMapping.c
|
||||
arch/Mips/MipsModule.c
|
||||
)
|
||||
set(HEADERS_MIPS
|
||||
arch/Mips/MipsDisassembler.h
|
||||
arch/Mips/MipsGenAsmWriter.inc
|
||||
arch/Mips/MipsGenDisassemblerTables.inc
|
||||
arch/Mips/MipsGenInstrInfo.inc
|
||||
arch/Mips/MipsGenRegisterInfo.inc
|
||||
arch/Mips/MipsGenSubtargetInfo.inc
|
||||
arch/Mips/MipsInstPrinter.h
|
||||
arch/Mips/MipsMapping.h
|
||||
arch/Mips/MipsMappingInsn.inc
|
||||
)
|
||||
set(HEADERS_MIPS
|
||||
arch/Mips/MipsDisassembler.h
|
||||
arch/Mips/MipsGenAsmWriter.inc
|
||||
arch/Mips/MipsGenDisassemblerTables.inc
|
||||
arch/Mips/MipsGenInstrInfo.inc
|
||||
arch/Mips/MipsGenRegisterInfo.inc
|
||||
arch/Mips/MipsGenSubtargetInfo.inc
|
||||
arch/Mips/MipsInstPrinter.h
|
||||
arch/Mips/MipsMapping.h
|
||||
)
|
||||
set(TEST_SOURCES ${TEST_SOURCES} test_mips.c)
|
||||
endif()
|
||||
|
||||
if(CAPSTONE_PPC_SUPPORT)
|
||||
add_definitions(-DCAPSTONE_HAS_POWERPC)
|
||||
set(SOURCES_PPC
|
||||
arch/PowerPC/PPCDisassembler.c
|
||||
arch/PowerPC/PPCInstPrinter.c
|
||||
arch/PowerPC/PPCMapping.c
|
||||
arch/PowerPC/PPCModule.c
|
||||
)
|
||||
set(HEADERS_PPC
|
||||
arch/PowerPC/PPCDisassembler.h
|
||||
arch/PowerPC/PPCGenAsmWriter.inc
|
||||
arch/PowerPC/PPCInstPrinter.h
|
||||
arch/PowerPC/PPCMapping.h
|
||||
arch/PowerPC/PPCPredicates.h
|
||||
arch/PowerPC/PPCGenAsmWriter.inc
|
||||
arch/PowerPC/PPCGenRegisterName.inc
|
||||
arch/PowerPC/PPCGenDisassemblerTables.inc
|
||||
arch/PowerPC/PPCMappingInsn.inc
|
||||
arch/PowerPC/PPCMappingInsnName.inc
|
||||
arch/PowerPC/PPCGenSubtargetInfo.inc
|
||||
arch/PowerPC/PPCGenRegisterInfo.inc
|
||||
arch/PowerPC/PPCGenInstrInfo.inc
|
||||
)
|
||||
set(TEST_SOURCES ${TEST_SOURCES} test_ppc.c)
|
||||
endif()
|
||||
|
||||
if(CAPSTONE_X86_SUPPORT)
|
||||
add_definitions(-DCAPSTONE_HAS_X86)
|
||||
set(SOURCES_X86
|
||||
arch/X86/X86Disassembler.c
|
||||
arch/X86/X86DisassemblerDecoder.c
|
||||
arch/X86/X86IntelInstPrinter.c
|
||||
arch/X86/X86InstPrinterCommon.c
|
||||
arch/X86/X86Mapping.c
|
||||
arch/X86/X86Module.c
|
||||
)
|
||||
set(HEADERS_X86
|
||||
arch/X86/X86BaseInfo.h
|
||||
arch/X86/X86Disassembler.h
|
||||
arch/X86/X86DisassemblerDecoder.h
|
||||
arch/X86/X86DisassemblerDecoderCommon.h
|
||||
arch/X86/X86GenAsmWriter.inc
|
||||
arch/X86/X86GenAsmWriter1.inc
|
||||
arch/X86/X86GenAsmWriter1_reduce.inc
|
||||
arch/X86/X86GenAsmWriter_reduce.inc
|
||||
arch/X86/X86GenDisassemblerTables.inc
|
||||
arch/X86/X86GenDisassemblerTables_reduce.inc
|
||||
arch/X86/X86GenInstrInfo.inc
|
||||
arch/X86/X86GenInstrInfo_reduce.inc
|
||||
arch/X86/X86GenRegisterInfo.inc
|
||||
arch/X86/X86InstPrinter.h
|
||||
arch/X86/X86Mapping.h
|
||||
arch/X86/X86MappingInsn.inc
|
||||
arch/X86/X86MappingInsnOp.inc
|
||||
arch/X86/X86MappingInsnOp_reduce.inc
|
||||
arch/X86/X86MappingInsn_reduce.inc
|
||||
)
|
||||
set(HEADERS_X86
|
||||
arch/X86/X86BaseInfo.h
|
||||
arch/X86/X86Disassembler.h
|
||||
arch/X86/X86DisassemblerDecoder.h
|
||||
arch/X86/X86DisassemblerDecoderCommon.h
|
||||
arch/X86/X86GenAsmWriter.inc
|
||||
arch/X86/X86GenAsmWriter1.inc
|
||||
arch/X86/X86GenAsmWriter1_reduce.inc
|
||||
arch/X86/X86GenAsmWriter_reduce.inc
|
||||
arch/X86/X86GenDisassemblerTables.inc
|
||||
arch/X86/X86GenDisassemblerTables_reduce.inc
|
||||
arch/X86/X86GenInstrInfo.inc
|
||||
arch/X86/X86GenInstrInfo_reduce.inc
|
||||
arch/X86/X86GenRegisterInfo.inc
|
||||
arch/X86/X86InstPrinter.h
|
||||
arch/X86/X86Mapping.h
|
||||
)
|
||||
if(NOT CAPSTONE_BUILD_DIET)
|
||||
set(SOURCES_X86 ${SOURCES_X86} arch/X86/X86ATTInstPrinter.c)
|
||||
endif()
|
||||
set(TEST_SOURCES ${TEST_SOURCES} test_x86.c test_customized_mnem.c)
|
||||
endif()
|
||||
|
||||
if(CAPSTONE_SPARC_SUPPORT)
|
||||
add_definitions(-DCAPSTONE_HAS_SPARC)
|
||||
set(SOURCES_SPARC
|
||||
arch/Sparc/SparcDisassembler.c
|
||||
arch/Sparc/SparcInstPrinter.c
|
||||
arch/Sparc/SparcMapping.c
|
||||
arch/Sparc/SparcModule.c
|
||||
)
|
||||
set(HEADERS_SPARC
|
||||
arch/Sparc/Sparc.h
|
||||
arch/Sparc/SparcDisassembler.h
|
||||
arch/Sparc/SparcGenAsmWriter.inc
|
||||
arch/Sparc/SparcGenDisassemblerTables.inc
|
||||
arch/Sparc/SparcGenInstrInfo.inc
|
||||
arch/Sparc/SparcGenRegisterInfo.inc
|
||||
arch/Sparc/SparcGenSubtargetInfo.inc
|
||||
arch/Sparc/SparcInstPrinter.h
|
||||
arch/Sparc/SparcMapping.h
|
||||
arch/Sparc/SparcMappingInsn.inc
|
||||
)
|
||||
set(TEST_SOURCES ${TEST_SOURCES} test_sparc.c)
|
||||
endif()
|
||||
|
||||
if(CAPSTONE_SYSZ_SUPPORT)
|
||||
add_definitions(-DCAPSTONE_HAS_SYSZ)
|
||||
set(SOURCES_SYSZ
|
||||
arch/SystemZ/SystemZDisassembler.c
|
||||
arch/SystemZ/SystemZInstPrinter.c
|
||||
arch/SystemZ/SystemZMapping.c
|
||||
arch/SystemZ/SystemZModule.c
|
||||
arch/SystemZ/SystemZMCTargetDesc.c
|
||||
)
|
||||
set(HEADERS_SYSZ
|
||||
arch/SystemZ/SystemZDisassembler.h
|
||||
arch/SystemZ/SystemZGenAsmWriter.inc
|
||||
arch/SystemZ/SystemZGenDisassemblerTables.inc
|
||||
arch/SystemZ/SystemZGenInsnNameMaps.inc
|
||||
arch/SystemZ/SystemZGenInstrInfo.inc
|
||||
arch/SystemZ/SystemZGenRegisterInfo.inc
|
||||
arch/SystemZ/SystemZGenSubtargetInfo.inc
|
||||
arch/SystemZ/SystemZInstPrinter.h
|
||||
arch/SystemZ/SystemZMapping.h
|
||||
arch/SystemZ/SystemZMappingInsn.inc
|
||||
arch/SystemZ/SystemZMCTargetDesc.h
|
||||
)
|
||||
set(TEST_SOURCES ${TEST_SOURCES} test_systemz.c)
|
||||
endif()
|
||||
|
||||
if(CAPSTONE_XCORE_SUPPORT)
|
||||
add_definitions(-DCAPSTONE_HAS_XCORE)
|
||||
set(SOURCES_XCORE
|
||||
arch/XCore/XCoreDisassembler.c
|
||||
arch/XCore/XCoreInstPrinter.c
|
||||
arch/XCore/XCoreMapping.c
|
||||
arch/XCore/XCoreModule.c
|
||||
)
|
||||
set(HEADERS_XCORE
|
||||
arch/XCore/XCoreDisassembler.h
|
||||
arch/XCore/XCoreGenAsmWriter.inc
|
||||
arch/XCore/XCoreGenDisassemblerTables.inc
|
||||
arch/XCore/XCoreGenInstrInfo.inc
|
||||
arch/XCore/XCoreGenRegisterInfo.inc
|
||||
arch/XCore/XCoreInstPrinter.h
|
||||
arch/XCore/XCoreMapping.h
|
||||
arch/XCore/XCoreMappingInsn.inc
|
||||
)
|
||||
set(TEST_SOURCES ${TEST_SOURCES} test_xcore.c)
|
||||
endif()
|
||||
|
||||
if(CAPSTONE_M68K_SUPPORT)
|
||||
add_definitions(-DCAPSTONE_HAS_M68K)
|
||||
set(SOURCES_M68K
|
||||
arch/M68K/M68KDisassembler.c
|
||||
arch/M68K/M68KInstPrinter.c
|
||||
arch/M68K/M68KModule.c
|
||||
)
|
||||
set(HEADERS_M68K
|
||||
arch/M68K/M68KDisassembler.h
|
||||
)
|
||||
set(TEST_SOURCES ${TEST_SOURCES} test_m68k.c)
|
||||
endif()
|
||||
|
||||
if(CAPSTONE_TMS320C64X_SUPPORT)
|
||||
add_definitions(-DCAPSTONE_HAS_TMS320C64X)
|
||||
set(SOURCES_TMS320C64X
|
||||
arch/TMS320C64x/TMS320C64xDisassembler.c
|
||||
arch/TMS320C64x/TMS320C64xInstPrinter.c
|
||||
arch/TMS320C64x/TMS320C64xMapping.c
|
||||
arch/TMS320C64x/TMS320C64xModule.c
|
||||
)
|
||||
set(HEADERS_TMS320C64X
|
||||
arch/TMS320C64x/TMS320C64xDisassembler.h
|
||||
arch/TMS320C64x/TMS320C64xGenAsmWriter.inc
|
||||
arch/TMS320C64x/TMS320C64xGenDisassemblerTables.inc
|
||||
arch/TMS320C64x/TMS320C64xGenInstrInfo.inc
|
||||
arch/TMS320C64x/TMS320C64xGenRegisterInfo.inc
|
||||
arch/TMS320C64x/TMS320C64xInstPrinter.h
|
||||
arch/TMS320C64x/TMS320C64xMapping.h
|
||||
)
|
||||
set(TEST_SOURCES ${TEST_SOURCES} test_tms320c64x.c)
|
||||
endif()
|
||||
|
||||
if(CAPSTONE_M680X_SUPPORT)
|
||||
add_definitions(-DCAPSTONE_HAS_M680X)
|
||||
set(SOURCES_M680X
|
||||
arch/M680X/M680XDisassembler.c
|
||||
arch/M680X/M680XInstPrinter.c
|
||||
arch/M680X/M680XModule.c
|
||||
)
|
||||
set(HEADERS_M680X
|
||||
arch/M680X/M680XInstPrinter.h
|
||||
arch/M680X/M680XDisassembler.h
|
||||
arch/M680X/M680XDisassemblerInternals.h
|
||||
)
|
||||
set(TEST_SOURCES ${TEST_SOURCES} test_m680x.c)
|
||||
endif()
|
||||
|
||||
if(CAPSTONE_EVM_SUPPORT)
|
||||
add_definitions(-DCAPSTONE_HAS_EVM)
|
||||
set(SOURCES_EVM
|
||||
arch/EVM/EVMDisassembler.c
|
||||
arch/EVM/EVMInstPrinter.c
|
||||
arch/EVM/EVMMapping.c
|
||||
arch/EVM/EVMModule.c
|
||||
)
|
||||
set(HEADERS_EVM
|
||||
arch/EVM/EVMDisassembler.h
|
||||
arch/EVM/EVMInstPrinter.h
|
||||
arch/EVM/EVMMapping.h
|
||||
arch/EVM/EVMMappingInsn.inc
|
||||
)
|
||||
set(TEST_SOURCES ${TEST_SOURCES} test_evm.c)
|
||||
endif()
|
||||
|
||||
if(CAPSTONE_WASM_SUPPORT)
|
||||
add_definitions(-DCAPSTONE_HAS_WASM)
|
||||
set(SOURCES_WASM
|
||||
arch/WASM/WASMDisassembler.c
|
||||
arch/WASM/WASMInstPrinter.c
|
||||
arch/WASM/WASMMapping.c
|
||||
arch/WASM/WASMModule.c
|
||||
)
|
||||
set(HEADERS_WASM
|
||||
arch/WASM/WASMDisassembler.h
|
||||
arch/WASM/WASMInstPrinter.h
|
||||
arch/WASM/WASMMapping.h
|
||||
)
|
||||
set(TEST_SOURCES ${TEST_SOURCES} test_wasm.c)
|
||||
endif()
|
||||
|
||||
if(CAPSTONE_MOS65XX_SUPPORT)
|
||||
add_definitions(-DCAPSTONE_HAS_MOS65XX)
|
||||
set(SOURCES_MOS65XX
|
||||
arch/MOS65XX/MOS65XXModule.c
|
||||
arch/MOS65XX/MOS65XXDisassembler.c)
|
||||
set(HEADERS_SOURCES_MOS65XX
|
||||
arch/MOS65XX/MOS65XXDisassembler.h
|
||||
)
|
||||
set(TEST_SOURCES ${TEST_SOURCES} test_mos65xx.c)
|
||||
endif()
|
||||
|
||||
if(CAPSTONE_BPF_SUPPORT)
|
||||
add_definitions(-DCAPSTONE_HAS_BPF)
|
||||
set(SOURCES_BPF
|
||||
arch/BPF/BPFDisassembler.c
|
||||
arch/BPF/BPFInstPrinter.c
|
||||
arch/BPF/BPFMapping.c
|
||||
arch/BPF/BPFModule.c
|
||||
)
|
||||
set(HEADERS_BPF
|
||||
arch/BPF/BPFConstants.h
|
||||
arch/BPF/BPFDisassembler.h
|
||||
arch/BPF/BPFInstPrinter.h
|
||||
arch/BPF/BPFMapping.h
|
||||
arch/BPF/BPFModule.h
|
||||
)
|
||||
set(TEST_SOURCES ${TEST_SOURCES} test_bpf.c)
|
||||
endif()
|
||||
|
||||
if(CAPSTONE_RISCV_SUPPORT)
|
||||
add_definitions(-DCAPSTONE_HAS_RISCV)
|
||||
set(SOURCES_RISCV
|
||||
arch/RISCV/RISCVDisassembler.c
|
||||
arch/RISCV/RISCVInstPrinter.c
|
||||
arch/RISCV/RISCVMapping.c
|
||||
arch/RISCV/RISCVModule.c
|
||||
)
|
||||
set(HEADERS_RISCV
|
||||
arch/RISCV/RISCVBaseInfo.h
|
||||
arch/RISCV/RISCVDisassembler.h
|
||||
arch/RISCV/RISCVInstPrinter.h
|
||||
arch/RISCV/RISCVMapping.h
|
||||
arch/RISCV/RISCVModule.h
|
||||
arch/RISCV/RISCVGenAsmWriter.inc
|
||||
arch/RISCV/RISCVGenDisassemblerTables.inc
|
||||
arch/RISCV/RISCVGenInsnNameMaps.inc
|
||||
arch/RISCV/RISCVGenInstrInfo.inc
|
||||
arch/RISCV/RISCVGenRegisterInfo.inc
|
||||
arch/RISCV/RISCVGenSubtargetInfo.inc
|
||||
arch/RISCV/RISCVMappingInsn.inc
|
||||
)
|
||||
set(TEST_SOURCES ${TEST_SOURCES} test_riscv.c)
|
||||
endif()
|
||||
|
||||
if(CAPSTONE_SH_SUPPORT)
|
||||
add_definitions(-DCAPSTONE_HAS_SH)
|
||||
set(SOURCES_SH
|
||||
arch/SH/SHDisassembler.c
|
||||
arch/SH/SHInstPrinter.c
|
||||
arch/SH/SHModule.c
|
||||
)
|
||||
set(HEADERS_SH
|
||||
arch/SH/SHDisassembler.h
|
||||
arch/SH/SHInstPrinter.h
|
||||
arch/SH/SHModule.h
|
||||
arch/SH/SHInsnTable.inc
|
||||
)
|
||||
set(TEST_SOURCES ${TEST_SOURCES} test_sh.c)
|
||||
endif()
|
||||
|
||||
if (CAPSTONE_TRICORE_SUPPORT)
|
||||
add_definitions(-DCAPSTONE_HAS_TRICORE)
|
||||
set(SOURCES_TRICORE
|
||||
arch/TriCore/TriCoreDisassembler.c
|
||||
arch/TriCore/TriCoreInstPrinter.c
|
||||
arch/TriCore/TriCoreMapping.c
|
||||
arch/TriCore/TriCoreModule.c
|
||||
)
|
||||
set(HEADERS_TRICORE
|
||||
arch/TriCore/TriCoreDisassembler.h
|
||||
arch/TriCore/TriCoreLinkage.h
|
||||
arch/TriCore/TriCoreGenAsmWriter.inc
|
||||
arch/TriCore/TriCoreGenDisassemblerTables.inc
|
||||
arch/TriCore/TriCoreGenInstrInfo.inc
|
||||
arch/TriCore/TriCoreGenRegisterInfo.inc
|
||||
arch/TriCore/TriCoreMapping.h
|
||||
arch/TriCore/TriCoreModule.h
|
||||
)
|
||||
set(TEST_SOURCES ${TEST_SOURCES} test_tricore.c)
|
||||
endif ()
|
||||
|
||||
if (CAPSTONE_OSXKERNEL_SUPPORT)
|
||||
add_definitions(-DCAPSTONE_HAS_OSXKERNEL)
|
||||
endif()
|
||||
|
||||
set(ALL_SOURCES
|
||||
${SOURCES_ENGINE}
|
||||
${SOURCES_ARM}
|
||||
${SOURCES_ARM64}
|
||||
${SOURCES_MIPS}
|
||||
${SOURCES_PPC}
|
||||
${SOURCES_X86}
|
||||
${SOURCES_SPARC}
|
||||
${SOURCES_SYSZ}
|
||||
${SOURCES_XCORE}
|
||||
${SOURCES_M68K}
|
||||
${SOURCES_TMS320C64X}
|
||||
${SOURCES_M680X}
|
||||
${SOURCES_EVM}
|
||||
${SOURCES_WASM}
|
||||
${SOURCES_MOS65XX}
|
||||
${SOURCES_BPF}
|
||||
${SOURCES_RISCV}
|
||||
${SOURCES_SH}
|
||||
${SOURCES_TRICORE}
|
||||
)
|
||||
|
||||
set(ALL_HEADERS
|
||||
${HEADERS_COMMON}
|
||||
${HEADERS_ENGINE}
|
||||
${HEADERS_ARM}
|
||||
${HEADERS_ARM64}
|
||||
${HEADERS_MIPS}
|
||||
${HEADERS_PPC}
|
||||
${HEADERS_X86}
|
||||
${HEADERS_SPARC}
|
||||
${HEADERS_SYSZ}
|
||||
${HEADERS_XCORE}
|
||||
${HEADERS_M68K}
|
||||
${HEADERS_TMS320C64X}
|
||||
${HEADERS_M680X}
|
||||
${HEADERS_EVM}
|
||||
${HEADERS_WASM}
|
||||
${HEADERS_MOS65XX}
|
||||
${HEADERS_BPF}
|
||||
${HEADERS_RISCV}
|
||||
${HEADERS_SH}
|
||||
${HEADERS_TRICORE}
|
||||
)
|
||||
|
||||
## properties
|
||||
# version info
|
||||
set_property(GLOBAL PROPERTY VERSION ${PROJECT_VERSION})
|
||||
|
||||
## targets
|
||||
add_library(capstone ${ALL_SOURCES} ${ALL_HEADERS})
|
||||
add_library(capstone::capstone ALIAS capstone)
|
||||
target_include_directories(capstone PUBLIC
|
||||
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
|
||||
)
|
||||
set_property(TARGET capstone PROPERTY C_STANDARD 99)
|
||||
|
||||
if(BUILD_SHARED_LIBS)
|
||||
target_compile_definitions(capstone PUBLIC CAPSTONE_SHARED)
|
||||
set_target_properties(capstone PROPERTIES
|
||||
VERSION ${PROJECT_VERSION}
|
||||
SOVERSION ${PROJECT_VERSION_MAJOR}
|
||||
)
|
||||
endif()
|
||||
|
||||
if(CAPSTONE_BUILD_TESTS)
|
||||
set(CMAKE_FOLDER "Tests")
|
||||
enable_testing()
|
||||
foreach(TSRC ${TEST_SOURCES})
|
||||
string(REGEX REPLACE ".c$" "" TBIN ${TSRC})
|
||||
add_executable(${TBIN} "tests/${TSRC}")
|
||||
target_link_libraries(${TBIN} PRIVATE capstone)
|
||||
add_test(NAME "capstone_${TBIN}" COMMAND ${TBIN})
|
||||
endforeach()
|
||||
if(CAPSTONE_ARM_SUPPORT)
|
||||
set(ARM_REGRESS_TEST test_arm_regression.c)
|
||||
string(REGEX REPLACE ".c$" "" ARM_REGRESS_BIN ${ARM_REGRESS_TEST})
|
||||
add_executable(${ARM_REGRESS_BIN} "suite/arm/${ARM_REGRESS_TEST}")
|
||||
target_link_libraries(${ARM_REGRESS_BIN} PRIVATE capstone)
|
||||
add_test(NAME "capstone_${ARM_REGRESS_BIN}" COMMAND ${ARM_REGRESS_BIN})
|
||||
endif()
|
||||
# fuzz target built with the tests
|
||||
add_executable(fuzz_disasm suite/fuzz/onefile.c suite/fuzz/fuzz_disasm.c suite/fuzz/platform.c)
|
||||
target_link_libraries(fuzz_disasm PRIVATE capstone)
|
||||
unset(CMAKE_FOLDER)
|
||||
endif()
|
||||
|
||||
source_group("Source\\Engine" FILES ${SOURCES_ENGINE})
|
||||
source_group("Source\\ARM" FILES ${SOURCES_ARM})
|
||||
source_group("Source\\ARM64" FILES ${SOURCES_ARM64})
|
||||
source_group("Source\\Mips" FILES ${SOURCES_MIPS})
|
||||
source_group("Source\\PowerPC" FILES ${SOURCES_PPC})
|
||||
source_group("Source\\Sparc" FILES ${SOURCES_SPARC})
|
||||
source_group("Source\\SystemZ" FILES ${SOURCES_SYSZ})
|
||||
source_group("Source\\X86" FILES ${SOURCES_X86})
|
||||
source_group("Source\\XCore" FILES ${SOURCES_XCORE})
|
||||
source_group("Source\\M68K" FILES ${SOURCES_M68K})
|
||||
source_group("Source\\TMS320C64x" FILES ${SOURCES_TMS320C64X})
|
||||
source_group("Source\\M680X" FILES ${SOURCES_M680X})
|
||||
source_group("Source\\EVM" FILES ${SOURCES_EVM})
|
||||
source_group("Source\\WASM" FILES ${SOURCES_WASM})
|
||||
source_group("Source\\MOS65XX" FILES ${SOURCES_MOS65XX})
|
||||
source_group("Source\\BPF" FILES ${SOURCES_BPF})
|
||||
source_group("Source\\RISCV" FILES ${SOURCES_RISCV})
|
||||
source_group("Source\\SH" FILES ${SOURCES_SH})
|
||||
source_group("Source\\TriCore" FILES ${SOURCES_TRICORE})
|
||||
|
||||
source_group("Include\\Common" FILES ${HEADERS_COMMON})
|
||||
source_group("Include\\Engine" FILES ${HEADERS_ENGINE})
|
||||
source_group("Include\\ARM" FILES ${HEADERS_ARM})
|
||||
source_group("Include\\ARM64" FILES ${HEADERS_ARM64})
|
||||
source_group("Include\\Mips" FILES ${HEADERS_MIPS})
|
||||
source_group("Include\\PowerPC" FILES ${HEADERS_PPC})
|
||||
source_group("Include\\Sparc" FILES ${HEADERS_SPARC})
|
||||
source_group("Include\\SystemZ" FILES ${HEADERS_SYSZ})
|
||||
source_group("Include\\X86" FILES ${HEADERS_X86})
|
||||
source_group("Include\\XCore" FILES ${HEADERS_XCORE})
|
||||
source_group("Include\\M68K" FILES ${HEADERS_M68K})
|
||||
source_group("Include\\TMS320C64x" FILES ${HEADERS_TMS320C64X})
|
||||
source_group("Include\\M680X" FILES ${HEADERS_MC680X})
|
||||
source_group("Include\\EVM" FILES ${HEADERS_EVM})
|
||||
source_group("Include\\WASM" FILES ${HEADERS_WASM})
|
||||
source_group("Include\\MOS65XX" FILES ${HEADERS_MOS65XX})
|
||||
source_group("Include\\BPF" FILES ${HEADERS_BPF})
|
||||
source_group("Include\\RISCV" FILES ${HEADERS_RISCV})
|
||||
source_group("Include\\SH" FILES ${HEADERS_SH})
|
||||
source_group("Include\\TriCore" FILES ${HEADERS_TRICORE})
|
||||
|
||||
## installation
|
||||
if(CAPSTONE_INSTALL)
|
||||
include("GNUInstallDirs")
|
||||
|
||||
install(FILES ${HEADERS_COMMON} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/capstone)
|
||||
|
||||
configure_file(capstone.pc.in ${CMAKE_BINARY_DIR}/capstone.pc @ONLY)
|
||||
install(FILES ${CMAKE_BINARY_DIR}/capstone.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
|
||||
|
||||
include(CMakePackageConfigHelpers)
|
||||
set(CAPSTONE_CMAKE_CONFIG_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/capstone")
|
||||
configure_package_config_file(
|
||||
capstone-config.cmake.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/capstone-config.cmake
|
||||
INSTALL_DESTINATION ${CAPSTONE_CMAKE_CONFIG_INSTALL_DIR}
|
||||
)
|
||||
write_basic_package_version_file(
|
||||
${CMAKE_CURRENT_BINARY_DIR}/capstone-config-version.cmake
|
||||
VERSION ${PROJECT_VERSION}
|
||||
COMPATIBILITY SameMajorVersion
|
||||
)
|
||||
|
||||
install(FILES
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/capstone-config.cmake"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/capstone-config-version.cmake"
|
||||
DESTINATION ${CAPSTONE_CMAKE_CONFIG_INSTALL_DIR}
|
||||
)
|
||||
|
||||
install(TARGETS capstone
|
||||
EXPORT capstone-targets
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
||||
)
|
||||
|
||||
install(EXPORT capstone-targets
|
||||
NAMESPACE capstone::
|
||||
DESTINATION ${CAPSTONE_CMAKE_CONFIG_INSTALL_DIR}
|
||||
)
|
||||
|
||||
# uninstall target
|
||||
if(NOT TARGET UNINSTALL)
|
||||
configure_file(
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
|
||||
IMMEDIATE @ONLY
|
||||
)
|
||||
set(CMAKE_FOLDER)
|
||||
add_custom_target(UNINSTALL COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)
|
||||
set_target_properties(UNINSTALL PROPERTIES
|
||||
FOLDER CMakePredefinedTargets
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(CAPSTONE_BUILD_CSTOOL)
|
||||
file(GLOB CSTOOL_SRC cstool/*.c)
|
||||
add_executable(cstool ${CSTOOL_SRC})
|
||||
target_link_libraries(cstool PRIVATE capstone)
|
||||
|
||||
if(CAPSTONE_INSTALL)
|
||||
install(TARGETS cstool EXPORT capstone-targets DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(CAPSTONE_BUILD_CSTEST)
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(CMOCKA REQUIRED IMPORTED_TARGET cmocka)
|
||||
|
||||
file(GLOB CSTEST_SRC suite/cstest/src/*.c)
|
||||
add_executable(cstest ${CSTEST_SRC})
|
||||
target_link_libraries(cstest PUBLIC capstone PkgConfig::CMOCKA)
|
||||
target_include_directories(cstest PRIVATE
|
||||
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
|
||||
${PROJECT_SOURCE_DIR}/suite/cstest/include
|
||||
${CMOCKA_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
if(CAPSTONE_INSTALL)
|
||||
install(TARGETS cstest EXPORT capstone-targets DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||
endif()
|
||||
endif()
|
||||
@@ -0,0 +1,133 @@
|
||||
{
|
||||
"version": 3,
|
||||
"configurePresets": [
|
||||
{
|
||||
"name": "locations-base",
|
||||
"hidden": true,
|
||||
"binaryDir": "${sourceDir}/build/${presetName}",
|
||||
"installDir": "${sourceDir}/out/install/${presetName}"
|
||||
},
|
||||
{
|
||||
"name": "warnings-base",
|
||||
"hidden": true,
|
||||
"warnings": {
|
||||
"dev": true,
|
||||
"deprecated": true,
|
||||
"systemVars": true
|
||||
},
|
||||
"errors": {
|
||||
"dev": true,
|
||||
"deprecated": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "ninja",
|
||||
"hidden": true,
|
||||
"displayName": "Ninja",
|
||||
"generator": "Ninja Multi-Config",
|
||||
"cacheVariables": {
|
||||
"CMAKE_DEFAULT_BUILD_TYPE": "Debug"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "x64",
|
||||
"hidden": true,
|
||||
"architecture": {
|
||||
"value": "x64",
|
||||
"strategy": "external"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "linux-x64",
|
||||
"inherits": [ "ninja", "x64", "locations-base", "warnings-base" ],
|
||||
"condition": {"type": "equals", "lhs": "${hostSystemName}", "rhs": "Linux"}
|
||||
},
|
||||
{
|
||||
"name": "macos-x64",
|
||||
"inherits": [ "ninja", "x64", "locations-base", "warnings-base" ],
|
||||
"condition": {"type": "equals", "lhs": "${hostSystemName}", "rhs": "Darwin"}
|
||||
},
|
||||
{
|
||||
"name": "windows-x64",
|
||||
"inherits": [ "ninja", "x64", "locations-base", "warnings-base" ],
|
||||
"condition": {"type": "equals", "lhs": "${hostSystemName}", "rhs": "Windows"}
|
||||
}
|
||||
],
|
||||
"buildPresets": [
|
||||
{
|
||||
"name": "build-linux",
|
||||
"configurePreset": "linux-x64",
|
||||
"nativeToolOptions": [ "-v" ],
|
||||
"condition": {"type": "equals", "lhs": "${hostSystemName}", "rhs": "Linux"}
|
||||
},
|
||||
{
|
||||
"name": "build-macos",
|
||||
"configurePreset": "macos-x64",
|
||||
"nativeToolOptions": [ "-v" ],
|
||||
"condition": {"type": "equals", "lhs": "${hostSystemName}", "rhs": "Darwin"}
|
||||
},
|
||||
{
|
||||
"name": "build-windows",
|
||||
"configurePreset": "windows-x64",
|
||||
"nativeToolOptions": [ "-v" ],
|
||||
"condition": {"type": "equals", "lhs": "${hostSystemName}", "rhs": "Windows"}
|
||||
},
|
||||
{
|
||||
"name": "build-linux-release",
|
||||
"inherits": "build-linux",
|
||||
"configuration": "Release",
|
||||
"condition": {"type": "equals", "lhs": "${hostSystemName}", "rhs": "Linux"}
|
||||
},
|
||||
{
|
||||
"name": "build-macos-release",
|
||||
"inherits": "build-macos",
|
||||
"configuration": "Release",
|
||||
"condition": {"type": "equals", "lhs": "${hostSystemName}", "rhs": "Darwin"}
|
||||
},
|
||||
{
|
||||
"name": "build-windows-release",
|
||||
"inherits": "build-windows",
|
||||
"configuration": "Release",
|
||||
"condition": {"type": "equals", "lhs": "${hostSystemName}", "rhs": "Windows"}
|
||||
},
|
||||
{
|
||||
"name": "install-linux",
|
||||
"configurePreset": "linux-x64",
|
||||
"inherits": "build-linux",
|
||||
"targets": [ "install" ],
|
||||
"condition": {"type": "equals", "lhs": "${hostSystemName}", "rhs": "Linux"}
|
||||
},
|
||||
{
|
||||
"name": "install-macos",
|
||||
"configurePreset": "macos-x64",
|
||||
"inherits": "build-macos",
|
||||
"targets": [ "install" ],
|
||||
"condition": {"type": "equals", "lhs": "${hostSystemName}", "rhs": "Darwin"}
|
||||
},
|
||||
{
|
||||
"name": "install-windows",
|
||||
"configurePreset": "windows-x64",
|
||||
"inherits": "build-windows",
|
||||
"targets": [ "install" ],
|
||||
"condition": {"type": "equals", "lhs": "${hostSystemName}", "rhs": "Windows"}
|
||||
},
|
||||
{
|
||||
"name": "install-linux-release",
|
||||
"inherits": "install-linux",
|
||||
"configuration": "Release",
|
||||
"condition": {"type": "equals", "lhs": "${hostSystemName}", "rhs": "Linux"}
|
||||
},
|
||||
{
|
||||
"name": "install-macos-release",
|
||||
"inherits": "install-macos",
|
||||
"configuration": "Release",
|
||||
"condition": {"type": "equals", "lhs": "${hostSystemName}", "rhs": "Darwin"}
|
||||
},
|
||||
{
|
||||
"name": "install-windows-release",
|
||||
"inherits": "install-windows",
|
||||
"configuration": "Release",
|
||||
"condition": {"type": "equals", "lhs": "${hostSystemName}", "rhs": "Windows"}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,204 @@
|
||||
This documentation explains how to compile, install & run Capstone on MacOSX,
|
||||
Linux, *BSD & Solaris. We also show steps to cross-compile for Microsoft Windows.
|
||||
|
||||
To natively compile for Windows using Microsoft Visual Studio, see COMPILE_MSVC.TXT.
|
||||
|
||||
To compile using CMake, see COMPILE_CMAKE.TXT.
|
||||
|
||||
To compile using XCode on MacOSX, see xcode/README.md.
|
||||
|
||||
To compile for Windows CE (a.k.a, Windows Embedded Compact), see windowsce/COMPILE.md.
|
||||
|
||||
*-*-*-*-*-*
|
||||
|
||||
Capstone requires no prerequisite packages, so it is easy to compile & install.
|
||||
|
||||
|
||||
|
||||
(0) Tailor Capstone to your need.
|
||||
|
||||
Out of all archtitectures supported by Capstone, if you just need several
|
||||
selected archs, choose the ones you want to compile in by editing "config.mk"
|
||||
before going to next steps.
|
||||
|
||||
By default, all architectures are compiled.
|
||||
|
||||
The other way of customize Capstone without having to edit config.mk is to
|
||||
pass the desired options on the commandline to ./make.sh. Currently,
|
||||
Capstone supports 8 options, as followings.
|
||||
|
||||
- CAPSTONE_ARCHS: specify list of architectures to compiled in.
|
||||
- CAPSTONE_USE_SYS_DYN_MEM: change this if you have your own dynamic memory management.
|
||||
- CAPSTONE_DIET: use this to make the output binaries more compact.
|
||||
- CAPSTONE_X86_REDUCE: another option to make X86 binary smaller.
|
||||
- CAPSTONE_X86_ATT_DISABLE: disables AT&T syntax on x86.
|
||||
- CAPSTONE_STATIC: build static library.
|
||||
- CAPSTONE_SHARED: build dynamic (shared) library.
|
||||
- CAPSTONE_DEBUG: enable debug build supporting assert().
|
||||
|
||||
By default, Capstone uses system dynamic memory management, both DIET and X86_REDUCE
|
||||
modes are disable, and builds all the static & shared libraries.
|
||||
|
||||
To avoid editing config.mk for these customization, we can pass their values to
|
||||
make.sh, as followings.
|
||||
|
||||
$ CAPSTONE_ARCHS="arm aarch64 x86" CAPSTONE_USE_SYS_DYN_MEM=no CAPSTONE_DIET=yes CAPSTONE_X86_REDUCE=yes ./make.sh
|
||||
|
||||
NOTE: on commandline, put these values in front of ./make.sh, not after it.
|
||||
|
||||
For each option, refer to docs/README for more details.
|
||||
|
||||
|
||||
|
||||
(1) Compile from source
|
||||
|
||||
On *nix (such as MacOSX, Linux, *BSD, Solaris):
|
||||
|
||||
- To compile for current platform, run:
|
||||
|
||||
$ ./make.sh
|
||||
|
||||
- On 64-bit OS, run the command below to cross-compile Capstone for 32-bit binary:
|
||||
|
||||
$ ./make.sh nix32
|
||||
|
||||
|
||||
|
||||
(2) Install Capstone on *nix
|
||||
|
||||
To install Capstone, run:
|
||||
|
||||
$ sudo ./make.sh install
|
||||
|
||||
For FreeBSD/OpenBSD, where sudo is unavailable, run:
|
||||
|
||||
$ su; ./make.sh install
|
||||
|
||||
Users are then required to enter root password to copy Capstone into machine
|
||||
system directories.
|
||||
|
||||
Afterwards, run ./tests/test* to see the tests disassembling sample code.
|
||||
|
||||
|
||||
NOTE: The core framework installed by "./make.sh install" consist of
|
||||
following files:
|
||||
|
||||
/usr/include/capstone/arm.h
|
||||
/usr/include/capstone/arm64.h
|
||||
/usr/include/capstone/bpf.h
|
||||
/usr/include/capstone/capstone.h
|
||||
/usr/include/capstone/evm.h
|
||||
/usr/include/capstone/m680x.h
|
||||
/usr/include/capstone/m68k.h
|
||||
/usr/include/capstone/mips.h
|
||||
/usr/include/capstone/mos65xx.h
|
||||
/usr/include/capstone/platform.h
|
||||
/usr/include/capstone/ppc.h
|
||||
/usr/include/capstone/sparc.h
|
||||
/usr/include/capstone/systemz.h
|
||||
/usr/include/capstone/tms320c64x.h
|
||||
/usr/include/capstone/wasm.h
|
||||
/usr/include/capstone/x86.h
|
||||
/usr/include/capstone/xcore.h
|
||||
/usr/include/capstone/tricore.h
|
||||
/usr/lib/libcapstone.a
|
||||
/usr/lib/libcapstone.so (for Linux/*nix), or /usr/lib/libcapstone.dylib (OSX)
|
||||
|
||||
|
||||
|
||||
(3) Cross-compile for Windows from *nix
|
||||
|
||||
To cross-compile for Windows, Linux & gcc-mingw-w64-i686 (and also gcc-mingw-w64-x86-64
|
||||
for 64-bit binaries) are required.
|
||||
|
||||
- To cross-compile Windows 32-bit binary, simply run:
|
||||
|
||||
$ ./make.sh cross-win32
|
||||
|
||||
- To cross-compile Windows 64-bit binary, run:
|
||||
|
||||
$ ./make.sh cross-win64
|
||||
|
||||
Resulted files libcapstone.dll, libcapstone.dll.a & tests/test*.exe can then
|
||||
be used on Windows machine.
|
||||
|
||||
|
||||
|
||||
(4) Cross-compile for iOS from Mac OSX.
|
||||
|
||||
To cross-compile for iOS (iPhone/iPad/iPod), Mac OSX with XCode installed is required.
|
||||
|
||||
- To cross-compile for ArmV7 (iPod 4, iPad 1/2/3, iPhone4, iPhone4S), run:
|
||||
$ ./make.sh ios_armv7
|
||||
|
||||
- To cross-compile for ArmV7s (iPad 4, iPhone 5C, iPad mini), run:
|
||||
$ ./make.sh ios_armv7s
|
||||
|
||||
- To cross-compile for Arm64 (iPhone 5S, iPad mini Retina, iPad Air), run:
|
||||
$ ./make.sh ios_arm64
|
||||
|
||||
- To cross-compile for all iDevices (armv7 + armv7s + arm64), run:
|
||||
$ ./make.sh ios
|
||||
|
||||
Resulted files libcapstone.dylib, libcapstone.a & tests/test* can then
|
||||
be used on iOS devices.
|
||||
|
||||
|
||||
|
||||
(5) Cross-compile for Android
|
||||
|
||||
To cross-compile for Android (smartphone/tablet), Android NDK is required.
|
||||
NOTE: Only ARM and ARM64 are currently supported.
|
||||
|
||||
$ NDK=/android/android-ndk-r10e ./make.sh cross-android arm
|
||||
or
|
||||
$ NDK=/android/android-ndk-r10e ./make.sh cross-android arm64
|
||||
|
||||
Resulted files libcapstone.so, libcapstone.a & tests/test* can then
|
||||
be used on Android devices.
|
||||
|
||||
|
||||
|
||||
(6) Compile on Windows with Cygwin
|
||||
|
||||
To compile under Cygwin gcc-mingw-w64-i686 or x86_64-w64-mingw32 run:
|
||||
|
||||
- To compile Windows 32-bit binary under Cygwin, run:
|
||||
|
||||
$ ./make.sh cygwin-mingw32
|
||||
|
||||
- To compile Windows 64-bit binary under Cygwin, run:
|
||||
|
||||
$ ./make.sh cygwin-mingw64
|
||||
|
||||
Resulted files libcapstone.dll, libcapstone.dll.a & tests/test*.exe can then
|
||||
be used on Windows machine.
|
||||
|
||||
|
||||
|
||||
(7) By default, "cc" (default C compiler on the system) is used as compiler.
|
||||
|
||||
- To use "clang" compiler instead, run the command below:
|
||||
|
||||
$ ./make.sh clang
|
||||
|
||||
- To use "gcc" compiler instead, run:
|
||||
|
||||
$ ./make.sh gcc
|
||||
|
||||
|
||||
|
||||
(8) To uninstall Capstone, run the command below:
|
||||
|
||||
$ sudo ./make.sh uninstall
|
||||
|
||||
|
||||
|
||||
(9) Language bindings
|
||||
|
||||
So far, Python, Ocaml & Java are supported by bindings in the main code.
|
||||
Look for the bindings under directory bindings/, and refer to README file
|
||||
of corresponding languages.
|
||||
|
||||
Community also provide bindings for C#, Go, Ruby, NodeJS, C++ & Vala. Links to
|
||||
these can be found at address http://capstone-engine.org/download.html
|
||||
@@ -0,0 +1,125 @@
|
||||
This documentation explains how to compile Capstone with CMake, focus on
|
||||
using Microsoft Visual C as the compiler.
|
||||
|
||||
To compile Capstone on *nix, see COMPILE.TXT.
|
||||
|
||||
To compile Capstone on Windows using Visual Studio, see COMPILE_MSVC.TXT.
|
||||
|
||||
*-*-*-*-*-*
|
||||
|
||||
This documentation requires CMake & Windows SDK or MS Visual Studio installed on
|
||||
your machine.
|
||||
|
||||
Get CMake for free from http://www.cmake.org.
|
||||
|
||||
|
||||
|
||||
(0) Tailor Capstone to your need.
|
||||
|
||||
Out of archtitectures supported by Capstone, if you just need several selected archs,
|
||||
run "cmake" with the unwanted archs disabled (set to 0) as followings.
|
||||
|
||||
- CAPSTONE_ARM_SUPPORT: support ARM. Run cmake with -DCAPSTONE_ARM_SUPPORT=0 to remove ARM.
|
||||
- CAPSTONE_ARM64_SUPPORT: support ARM64. Run cmake with -DCAPSTONE_ARM64_SUPPORT=0 to remove ARM64.
|
||||
- CAPSTONE_M680X_SUPPORT: support M680X. Run cmake with -DCAPSTONE_M680X_SUPPORT=0 to remove M680X.
|
||||
- CAPSTONE_M68K_SUPPORT: support M68K. Run cmake with -DCAPSTONE_M68K_SUPPORT=0 to remove M68K.
|
||||
- CAPSTONE_MIPS_SUPPORT: support Mips. Run cmake with -DCAPSTONE_MIPS_SUPPORT=0 to remove Mips.
|
||||
- CAPSTONE_MOS65XX_SUPPORT: support MOS65XX. Run cmake with -DCAPSTONE_MOS65XX_SUPPORT=0 to remove MOS65XX.
|
||||
- CAPSTONE_PPC_SUPPORT: support PPC. Run cmake with -DCAPSTONE_PPC_SUPPORT=0 to remove PPC.
|
||||
- CAPSTONE_SPARC_SUPPORT: support Sparc. Run cmake with -DCAPSTONE_SPARC_SUPPORT=0 to remove Sparc.
|
||||
- CAPSTONE_SYSZ_SUPPORT: support SystemZ. Run cmake with -DCAPSTONE_SYSZ_SUPPORT=0 to remove SystemZ.
|
||||
- CAPSTONE_XCORE_SUPPORT: support XCore. Run cmake with -DCAPSTONE_XCORE_SUPPORT=0 to remove XCore.
|
||||
- CAPSTONE_TRICORE_SUPPORT: support TriCore. Run cmake with -DCAPSTONE_TRICORE_SUPPORT=0 to remove TriCore.
|
||||
- CAPSTONE_X86_SUPPORT: support X86. Run cmake with -DCAPSTONE_X86_SUPPORT=0 to remove X86.
|
||||
- CAPSTONE_X86_TMS320C64X: support TMS320C64X. Run cmake with -DCAPSTONE_TMS320C64X_SUPPORT=0 to remove TMS320C64X.
|
||||
- CAPSTONE_X86_M680X: support M680X. Run cmake with -DCAPSTONE_M680X_SUPPORT=0 to remove M680X.
|
||||
- CAPSTONE_X86_EVM: support EVM. Run cmake with -DCAPSTONE_EVM_SUPPORT=0 to remove EVM.
|
||||
- CAPSTONE_X86_WASM: support Web Assembly. Run cmake with -DCAPSTONE_WASM_SUPPORT=0 to remove WASM.
|
||||
- CAPSTONE_BPF_SUPPORT: support BPF. Run cmake with -DCAPSTONE_BPF_SUPPORT=0 to remove BPF.
|
||||
- CAPSTONE_RISCV_SUPPORT: support RISCV. Run cmake with -DCAPSTONE_RISCV_SUPPORT=0 to remove RISCV.
|
||||
- CAPSTONE_ARCHITECUTRE_DEFAULT: Whether architectures are enabled by default.
|
||||
Set this of OFF with -DCAPSTONE_ARCHITECUTRE_DEFAULT=OFF to dissable all architectures by default.
|
||||
You can then enable them again with one of the CAPSTONE_<ARCH>_SUPPORT options.
|
||||
|
||||
By default, all architectures are compiled in.
|
||||
|
||||
|
||||
Besides, Capstone also allows some more customization via following macros.
|
||||
|
||||
- CAPSTONE_USE_SYS_DYN_MEM: change this to OFF to use your own dynamic memory management.
|
||||
- CAPSTONE_BUILD_DIET: change this to ON to make the binaries more compact.
|
||||
- CAPSTONE_X86_REDUCE: change this to ON to make X86 binary smaller.
|
||||
- CAPSTONE_X86_ATT_DISABLE: change this to ON to disable AT&T syntax on x86.
|
||||
- CAPSTONE_DEBUG: change this to ON to enable extra debug assertions.
|
||||
|
||||
By default, Capstone use system dynamic memory management, and both DIET and X86_REDUCE
|
||||
modes are disabled. To use your own memory allocations, turn ON both DIET &
|
||||
X86_REDUCE, run "cmake" with: -DCAPSTONE_USE_SYS_DYN_MEM=0 -DCAPSTONE_BUILD_DIET=1 -DCAPSTONE_X86_REDUCE=1
|
||||
|
||||
|
||||
For each option, refer to docs/README for more details.
|
||||
|
||||
|
||||
|
||||
(1) CMake allows you to generate different generators to build Capstone. Below is
|
||||
some examples on how to build Capstone on Windows with CMake.
|
||||
|
||||
(*) You can let CMake select a generator for you. Do:
|
||||
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
|
||||
This last command is also where you can pass additional CMake configuration flags
|
||||
using `-D<key>=<value>`.
|
||||
For a debug build add `-DCMAKE_BUILD_TYPE=Debug`.
|
||||
To export `compile_commands.json` add `-DCMAKE_EXPORT_COMPILE_COMMANDS=ON`.
|
||||
|
||||
Then to build use:
|
||||
|
||||
cmake --build . --config [Release/Debug]
|
||||
|
||||
|
||||
(*) To build Capstone using Nmake of Windows SDK, do:
|
||||
|
||||
mkdir build
|
||||
cd build
|
||||
..\nmake.bat
|
||||
|
||||
After this, find the samples test*.exe, capstone.lib & capstone.dll
|
||||
in the same directory.
|
||||
|
||||
|
||||
|
||||
(*) To build Capstone using Visual Studio, choose the generator accordingly to the
|
||||
version of Visual Studio on your machine. For example, with Visual Studio 2013, do:
|
||||
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -G "Visual Studio 12" ..
|
||||
|
||||
After this, find capstone.sln in the same directory. Open it with Visual Studio
|
||||
and build the solution including libraries & all test as usual.
|
||||
|
||||
|
||||
|
||||
(2) You can make sure the prior steps successfully worked by launching one of the
|
||||
testing binary (test*.exe).
|
||||
|
||||
(3) You can also enable just one specific architecture by passing the architecture name
|
||||
to either the cmake.sh or nmake.bat scripts. e.g.:
|
||||
|
||||
../cmake.sh x86
|
||||
|
||||
Will just target the x86 architecture. The list of available architectures is: ARM,
|
||||
ARM64, M68K, MIPS, PowerPC, Sparc, SystemZ, XCore, x86, TMS320C64x, M680x, EVM, MOS65XX,
|
||||
WASM, BPF, RISCV.
|
||||
|
||||
(4) You can also create an installation image with cmake, by using the 'install' target.
|
||||
Use:
|
||||
|
||||
cmake --build . --config Release --target install
|
||||
|
||||
This will normally install an image in a default location (`C:\Program Files` on Windows),
|
||||
so it's good to explicitly set this location when configuring CMake. Use: `-DCMAKE_INSTALL_PREFIX=image`
|
||||
for instance, to put the installation in the 'image' subdirectory of the build directory.
|
||||
@@ -0,0 +1,123 @@
|
||||
This documentation explains how to compile Capstone on Windows using
|
||||
Microsoft Visual Studio version 2010 or newer.
|
||||
|
||||
To compile Capstone on *nix, see COMPILE.TXT
|
||||
|
||||
To compile Capstone with CMake, see COMPILE_CMAKE.TXT
|
||||
|
||||
*-*-*-*-*-*
|
||||
|
||||
Capstone requires no prerequisite packages with default configurations, so it is
|
||||
easy to compile & install. Open the Visual Studio solution "msvc/capstone.sln"
|
||||
and follow the instructions below.
|
||||
|
||||
NOTE: This requires Visual Studio 2010 or newer versions.
|
||||
|
||||
If you wish to embed Capstone in a kernel driver, Visual Studio 2013 or newer
|
||||
versions, and Windows Driver Kit 8.1 Update 1 or newer versions are required.
|
||||
|
||||
|
||||
(0) Tailor Capstone to your need.
|
||||
|
||||
Out of 9 archtitectures supported by Capstone (Arm, Arm64, M68K, Mips, PPC,
|
||||
Sparc, SystemZ, X86 & XCore), if you just need several selected archs, choose
|
||||
the ones you want to compile in by opening Visual Studio solution "msvc\capstone.sln",
|
||||
then directly editing the projects "capstone_static" & "capstone_dll" for static
|
||||
and dynamic libraries, respectively. This must be done before going to the next
|
||||
steps.
|
||||
|
||||
In VisualStudio interface, modify the preprocessor definitions via
|
||||
"Project Properties" -> "Configuration Properties" -> "C/C++" -> "Preprocessor"
|
||||
to customize Capstone library, as followings.
|
||||
|
||||
- CAPSTONE_HAS_ARM: support ARM. Delete this to remove ARM support.
|
||||
- CAPSTONE_HAS_ARM64: support ARM64. Delete this to remove ARM64 support.
|
||||
- CAPSTONE_HAS_M68K: support M68K. Delete this to remove M68K support.
|
||||
- CAPSTONE_HAS_MIPS: support Mips. Delete this to remove Mips support.
|
||||
- CAPSTONE_HAS_POWERPC: support PPC. Delete this to remove PPC support.
|
||||
- CAPSTONE_HAS_SPARC: support Sparc. Delete this to remove Sparc support.
|
||||
- CAPSTONE_HAS_SYSZ: support SystemZ. Delete this to remove SystemZ support.
|
||||
- CAPSTONE_HAS_X86: support X86. Delete this to remove X86 support.
|
||||
- CAPSTONE_HAS_XCORE: support XCore. Delete this to remove XCore support.
|
||||
- CAPSTONE_HAS_TRICORE: support TriCore. Delete this to remove TriCore support.
|
||||
|
||||
By default, all 9 architectures are compiled in.
|
||||
|
||||
|
||||
Besides, Capstone also allows some more customization via following macros.
|
||||
|
||||
- CAPSTONE_USE_SYS_DYN_MEM: delete this to use your own dynamic memory management.
|
||||
- CAPSTONE_DIET_NO: rename this to "CAPSTONE_DIET" to make the binaries more compact.
|
||||
- CAPSTONE_X86_REDUCE_NO: rename this to "CAPSTONE_X86_REDUCE" to make X86 binary smaller.
|
||||
- CAPSTONE_X86_ATT_DISABLE_NO: rename this to "CAPSTONE_X86_ATT_DISABLE" to disable
|
||||
AT&T syntax on x86.
|
||||
|
||||
By default, Capstone use system dynamic memory management, and both DIET and X86_REDUCE
|
||||
modes are disable.
|
||||
|
||||
|
||||
For each option, refer to docs/README for more details.
|
||||
|
||||
|
||||
|
||||
(1) Compile from source on Windows with Visual Studio
|
||||
|
||||
- Choose the configuration and the platform you want: Release/Debug & Win32/Win64.
|
||||
- Build only the libraries, or the libraries along with all the tests.
|
||||
- "capstone_static_winkernel" is for compiling Capstone for a driver and
|
||||
"test_winkernel" is a test for a driver, and those are excluded from build by
|
||||
default. To compile them, open the Configuration Manager through the [Build]
|
||||
menu and check "Build" check boxes for those project.
|
||||
|
||||
|
||||
|
||||
(2) You can make sure the prior steps successfully worked by launching one of the
|
||||
testing binary (test*.exe).
|
||||
|
||||
The testing binary for a driver "test_winkernel.sys" is made up of all tests for
|
||||
supported architectures configured with the step (0) along side its own tests.
|
||||
Below explains a procedure to run the test driver and check test results.
|
||||
|
||||
On the x64 platform, the test signing mode has to be enabled to install the test
|
||||
driver. To do it, open the command prompt with the administrator privileges and
|
||||
type the following command, and then restart the system to activate the change:
|
||||
|
||||
>bcdedit /set testsigning on
|
||||
|
||||
Test results from the test driver is sent to kernel debug buffer. In order to
|
||||
see those results, download DebugView and run it with the administrator
|
||||
privileges, then check [Capture Kernel] through the [Capture] menu.
|
||||
|
||||
DebugView: https://technet.microsoft.com/en-us/sysinternals/debugview.aspx
|
||||
|
||||
To install and uninstall the driver, use the 'sc' command. For installing and
|
||||
executing test_winkernel.sys, execute the following commands with the
|
||||
administrator privileges:
|
||||
|
||||
>sc create test_winkernel type= kernel binPath= <full path to test_winkernel.sys>
|
||||
[SC] CreateService SUCCESS
|
||||
|
||||
>sc start test_winkernel
|
||||
[SC] StartService FAILED 995:
|
||||
|
||||
The I/O operation has been aborted because of either a thread exit or an application request.
|
||||
|
||||
To uninstall the driver, execute the following commands with the administrator
|
||||
privileges:
|
||||
|
||||
>sc delete test_winkernel
|
||||
>bcdedit /deletevalue testsigning
|
||||
|
||||
|
||||
|
||||
(3) Installing and building capstone via vcpkg
|
||||
|
||||
You can download and install capstone using the vcpkg(https://github.com/Microsoft/vcpkg) dependency manager:
|
||||
|
||||
git clone https://github.com/Microsoft/vcpkg.git
|
||||
cd vcpkg
|
||||
./bootstrap-vcpkg.sh
|
||||
./vcpkg integrate install
|
||||
vcpkg install capstone
|
||||
|
||||
The capstone port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please create an issue or pull request on the vcpkg repository(https://github.com/Microsoft/vcpkg).
|
||||
@@ -0,0 +1,90 @@
|
||||
This file credits all the contributors of the Capstone engine project.
|
||||
|
||||
Key developers
|
||||
==============
|
||||
Nguyen Anh Quynh <aquynh -at- gmail.com>
|
||||
Chenxu Wu (kabeor) kabeor@qiling.io
|
||||
|
||||
|
||||
Past key developers
|
||||
===================
|
||||
Tan Sheng Di <shengdi -at- coseinc.com>
|
||||
- Bindings: Ruby
|
||||
|
||||
Ben Nagy <ben -at- coseinc.com>
|
||||
- Bindings: Ruby, Go
|
||||
|
||||
Dang Hoang Vu <dang.hvu -at- gmail.com>
|
||||
- Bindings: Java
|
||||
|
||||
|
||||
Beta testers (in random order)
|
||||
==============================
|
||||
Pancake
|
||||
Van Hauser
|
||||
FX of Phenoelit
|
||||
The Grugq, The Grugq <-- our hero for submitting the first ever patch!
|
||||
Isaac Dawson, Veracode Inc
|
||||
Patroklos Argyroudis, Census Inc. (http://census-labs.com)
|
||||
Attila Suszter
|
||||
Le Dinh Long
|
||||
Nicolas Ruff
|
||||
Gunther
|
||||
Alex Ionescu, Winsider Seminars & Solutions Inc.
|
||||
Snare
|
||||
Daniel Godas-Lopez
|
||||
Joshua J. Drake
|
||||
Edgar Barbosa
|
||||
Ralf-Philipp Weinmann
|
||||
Hugo Fortier
|
||||
Joxean Koret
|
||||
Bruce Dang
|
||||
Andrew Dunham
|
||||
|
||||
|
||||
Contributors (in no particular order)
|
||||
=====================================
|
||||
(Please let us know if you want to have your name here)
|
||||
|
||||
Ole André Vadla Ravnås (author of the 100th Pull-Request in our Github repo, thanks!)
|
||||
Axel "0vercl0k" Souchet (@0vercl0k) & Alex Ionescu: port to MSVC.
|
||||
Daniel Pistelli: Cmake support.
|
||||
Peter Hlavaty: integrate Capstone for Windows kernel drivers.
|
||||
Guillaume Jeanne: Ocaml binding.
|
||||
Martin Tofall, Obsidium Software: Optimize X86 performance & size + x86 encoding features.
|
||||
David Martínez Moreno & Hilko Bengen: Debian package.
|
||||
Félix Cloutier: Xcode project.
|
||||
Benoit Lecocq: OpenBSD package.
|
||||
Christophe Avoinne (Hlide): Improve memory management for better performance.
|
||||
Michael Cohen & Nguyen Tan Cong: Python module installer.
|
||||
Adel Gadllah, Francisco Alonso & Stefan Cornelius: RPM package.
|
||||
Felix Gröbert (Google): fuzz testing harness.
|
||||
Xipiter LLC: Capstone logo redesigned.
|
||||
Satoshi Tanda: Support Windows kernel driver.
|
||||
Tang Yuhang: cstool.
|
||||
Andrew Dutcher: better Python setup.
|
||||
Ruben Boonen: PowerShell binding.
|
||||
David Zimmer: VB6 binding.
|
||||
Philippe Antoine: Integration with oss-fuzz and various fixes.
|
||||
Bui Dinh Cuong: Explicit registers accessed for Arm64.
|
||||
Vincent Bénony: Explicit registers accessed for X86.
|
||||
Adel Gadllah, Francisco Alonso & Stefan Cornelius: RPM package.
|
||||
Felix Gröbert (Google): fuzz testing harness.
|
||||
Daniel Collin & Nicolas Planel: M68K architecture.
|
||||
Pranith Kumar: Explicit registers accessed for Arm64.
|
||||
Xipiter LLC: Capstone logo redesigned.
|
||||
Satoshi Tanda: Support Windows kernel driver.
|
||||
Koutheir Attouchi: Support for Windows CE.
|
||||
Fotis Loukos: TMS320C64x architecture.
|
||||
Wolfgang Schwotzer: M680X architecture.
|
||||
Philippe Antoine: Integration with oss-fuzz and various fixes.
|
||||
Stephen Eckels (stevemk14ebr): x86 encoding features
|
||||
Tong Yu(Spike) & Kai Jern, Lau (xwings): WASM architecture.
|
||||
Sebastian Macke: MOS65XX architecture
|
||||
Ilya Leoshkevich: SystemZ architecture improvements.
|
||||
Do Minh Tuan: Regression testing tool (cstest)
|
||||
david942j: BPF (both classic and extended) architecture.
|
||||
fanfuqiang & citypw & porto703 : RISCV architecture.
|
||||
Josh "blacktop" Maine: Arm64 architecture improvements.
|
||||
Finn Wilkinson: AArch64 update to Armv9.2-a (SME + SVE2 support)
|
||||
Billow & Sidneyp : TriCore architecture.
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,108 @@
|
||||
Code structure
|
||||
--------------
|
||||
|
||||
Capstone source is organized as followings.
|
||||
|
||||
. <- core engine + README + COMPILE.TXT etc
|
||||
├── arch <- code handling disasm engine for each arch
|
||||
│ ├── AArch64 <- ARM64 (aka ARMv8) engine
|
||||
│ ├── ARM <- ARM engine
|
||||
│ ├── BPF <- Berkeley Packet Filter engine
|
||||
│ ├── EVM <- Ethereum engine
|
||||
│ ├── M680X <- M680X engine
|
||||
│ ├── M68K <- M68K engine
|
||||
│ ├── Mips <- Mips engine
|
||||
│ ├── MOS65XX <- MOS65XX engine
|
||||
│ ├── PowerPC <- PowerPC engine
|
||||
│ ├── RISCV <- RISCV engine
|
||||
│ ├── SH <- SH engine
|
||||
│ ├── Sparc <- Sparc engine
|
||||
│ ├── SystemZ <- SystemZ engine
|
||||
│ ├── TMS320C64x <- TMS320C64x engine
|
||||
│ ├── TriCore <- TriCore engine
|
||||
│ └── WASM <- WASM engine
|
||||
├── bindings <- all bindings are under this dir
|
||||
│ ├── java <- Java bindings + test code
|
||||
│ ├── ocaml <- Ocaml bindings + test code
|
||||
│ └── python <- Python bindings + test code
|
||||
├── contrib <- Code contributed by community to help Capstone integration
|
||||
├── cstool <- Cstool
|
||||
├── docs <- Documentation
|
||||
├── include <- API headers in C language (*.h)
|
||||
├── msvc <- Microsoft Visual Studio support (for Windows compile)
|
||||
├── packages <- Packages for Linux/OSX/BSD.
|
||||
├── windows <- Windows support (for Windows kernel driver compile)
|
||||
├── suite <- Development test tools - for Capstone developers only
|
||||
├── tests <- Test code (in C language)
|
||||
└── xcode <- Xcode support (for MacOSX compile)
|
||||
|
||||
|
||||
Follow instructions in COMPILE.TXT for how to compile and run test code.
|
||||
|
||||
Note: if you find some strange bugs, it is recommended to firstly clean
|
||||
the code and try to recompile/reinstall again. This can be done with:
|
||||
|
||||
$ ./make.sh
|
||||
$ sudo ./make.sh install
|
||||
|
||||
Then test Capstone with cstool, for example:
|
||||
|
||||
$ cstool x32 "90 91"
|
||||
|
||||
At the same time, for Java/Ocaml/Python bindings, be sure to always use
|
||||
the bindings coming with the core to avoid potential incompatibility issue
|
||||
with older versions.
|
||||
See bindings/<language>/README for detail instructions on how to compile &
|
||||
install the bindings.
|
||||
|
||||
|
||||
Coding style
|
||||
------------
|
||||
- C code follows Linux kernel coding style, using tabs for indentation.
|
||||
- Python code uses 4 spaces for indentation.
|
||||
|
||||
|
||||
Adding an architecture
|
||||
----------------------
|
||||
|
||||
Obviously, you first need to write all the logic and put it in a new directory arch/newarch
|
||||
Then, you have to modify other files.
|
||||
(You can look for one architecture such as EVM in these files to get what you need to do)
|
||||
|
||||
Integrate:
|
||||
- cs.c
|
||||
- cstool/cstool.c
|
||||
- cstool/cstool_newarch.c: print the architecture specific details
|
||||
- include/capstone/capstone.h
|
||||
- include/capstone/newarch.h: create this file to export all specifics about the new architecture
|
||||
|
||||
Compile:
|
||||
- CMakeLists.txt
|
||||
- Makefile
|
||||
- config.mk
|
||||
|
||||
Tests:
|
||||
- tests/Makefile
|
||||
- tests/test_basic.c
|
||||
- tests/test_detail.c
|
||||
- tests/test_iter.c
|
||||
- tests/test_newarch.c
|
||||
- suite/fuzz/platform.c: add the architecture and its modes to the list of fuzzed platforms
|
||||
- suite/capstone_get_setup.c
|
||||
- suite/MC/newarch/mode.mc: samples
|
||||
- suite/test_corpus.py: correspondence between architecture and mode as text and architecture number for fuzzing
|
||||
|
||||
Bindings:
|
||||
- bindings/Makefile
|
||||
- bindings/const_generator.py: add the header file and the architecture
|
||||
- bindings/python/Makefile
|
||||
- bindings/python/capstone/__init__.py
|
||||
- bindings/python/capstone/newarch.py: define the python structures
|
||||
- bindings/python/capstone/newarch_const.py: generate this file
|
||||
- bindings/python/test_newarch.py: create a basic decoding test
|
||||
- bindings/python/test_all.py
|
||||
|
||||
Docs:
|
||||
- README.md
|
||||
- HACK.txt
|
||||
- CREDITS.txt: add your name
|
||||
@@ -0,0 +1,38 @@
|
||||
//===- llvm/Support/LEB128.h - [SU]LEB128 utility functions -----*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file declares some utility functions for encoding SLEB128 and
|
||||
// ULEB128 values.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/* Capstone Disassembly Engine */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
|
||||
|
||||
#ifndef CS_LLVM_SUPPORT_LEB128_H
|
||||
#define CS_LLVM_SUPPORT_LEB128_H
|
||||
|
||||
#include "include/capstone/capstone.h"
|
||||
|
||||
/// Utility function to decode a ULEB128 value.
|
||||
static inline uint64_t decodeULEB128(const uint8_t *p, unsigned *n)
|
||||
{
|
||||
const uint8_t *orig_p = p;
|
||||
uint64_t Value = 0;
|
||||
unsigned Shift = 0;
|
||||
do {
|
||||
Value += (uint64_t)(*p & 0x7f) << Shift;
|
||||
Shift += 7;
|
||||
} while (*p++ >= 128);
|
||||
if (n)
|
||||
*n = (unsigned)(p - orig_p);
|
||||
return Value;
|
||||
}
|
||||
|
||||
#endif // LLVM_SYSTEM_LEB128_H
|
||||
@@ -0,0 +1,31 @@
|
||||
This is the software license for Capstone disassembly framework.
|
||||
Capstone has been designed & implemented by Nguyen Anh Quynh <aquynh@gmail.com>
|
||||
|
||||
See http://www.capstone-engine.org for further information.
|
||||
|
||||
Copyright (c) 2013, COSEINC.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of the developer(s) nor the names of its
|
||||
contributors may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
@@ -0,0 +1,71 @@
|
||||
==============================================================================
|
||||
LLVM Release License
|
||||
==============================================================================
|
||||
University of Illinois/NCSA
|
||||
Open Source License
|
||||
|
||||
Copyright (c) 2003-2013 University of Illinois at Urbana-Champaign.
|
||||
All rights reserved.
|
||||
|
||||
Developed by:
|
||||
|
||||
LLVM Team
|
||||
|
||||
University of Illinois at Urbana-Champaign
|
||||
|
||||
http://llvm.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal with
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimers.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimers in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the names of the LLVM Team, University of Illinois at
|
||||
Urbana-Champaign, nor the names of its contributors may be used to
|
||||
endorse or promote products derived from this Software without specific
|
||||
prior written permission.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
|
||||
SOFTWARE.
|
||||
|
||||
==============================================================================
|
||||
Copyrights and Licenses for Third Party Software Distributed with LLVM:
|
||||
==============================================================================
|
||||
The LLVM software contains code written by third parties. Such software will
|
||||
have its own individual LICENSE.TXT file in the directory in which it appears.
|
||||
This file will describe the copyrights, license, and restrictions which apply
|
||||
to that code.
|
||||
|
||||
The disclaimer of warranty in the University of Illinois Open Source License
|
||||
applies to all code in the LLVM Distribution, and nothing in any of the
|
||||
other licenses gives permission to use the names of the LLVM Team or the
|
||||
University of Illinois to endorse or promote products derived from this
|
||||
Software.
|
||||
|
||||
The following pieces of software have additional or alternate copyrights,
|
||||
licenses, and/or restrictions:
|
||||
|
||||
Program Directory
|
||||
------- ---------
|
||||
Autoconf llvm/autoconf
|
||||
llvm/projects/ModuleMaker/autoconf
|
||||
llvm/projects/sample/autoconf
|
||||
Google Test llvm/utils/unittest/googletest
|
||||
OpenBSD regex llvm/lib/Support/{reg*, COPYRIGHT.regex}
|
||||
pyyaml tests llvm/test/YAMLParser/{*.data, LICENSE.TXT}
|
||||
ARM contributions llvm/lib/Target/ARM/LICENSE.TXT
|
||||
md5 contributions llvm/lib/Support/MD5.cpp llvm/include/llvm/Support/MD5.h
|
||||
@@ -0,0 +1,14 @@
|
||||
/* Capstone Disassembly Engine */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
|
||||
|
||||
#ifndef CS_MCDISASSEMBLER_H
|
||||
#define CS_MCDISASSEMBLER_H
|
||||
|
||||
typedef enum DecodeStatus {
|
||||
MCDisassembler_Fail = 0,
|
||||
MCDisassembler_SoftFail = 1,
|
||||
MCDisassembler_Success = 3,
|
||||
} DecodeStatus;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
//===-- llvm/MC/MCFixedLenDisassembler.h - Decoder driver -------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Fixed length disassembler decoder state machine driver.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/* Capstone Disassembly Engine */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
|
||||
|
||||
#ifndef CS_LLVM_MC_MCFIXEDLENDISASSEMBLER_H
|
||||
#define CS_LLVM_MC_MCFIXEDLENDISASSEMBLER_H
|
||||
|
||||
// Disassembler state machine opcodes.
|
||||
enum DecoderOps {
|
||||
MCD_OPC_ExtractField = 1, // OPC_ExtractField(uint8_t Start, uint8_t Len)
|
||||
MCD_OPC_FilterValue, // OPC_FilterValue(uleb128 Val, uint16_t NumToSkip)
|
||||
MCD_OPC_CheckField, // OPC_CheckField(uint8_t Start, uint8_t Len,
|
||||
// uleb128 Val, uint16_t NumToSkip)
|
||||
MCD_OPC_CheckPredicate, // OPC_CheckPredicate(uleb128 PIdx, uint16_t NumToSkip)
|
||||
MCD_OPC_Decode, // OPC_Decode(uleb128 Opcode, uleb128 DIdx)
|
||||
MCD_OPC_TryDecode, // OPC_TryDecode(uleb128 Opcode, uleb128 DIdx,
|
||||
// uint16_t NumToSkip)
|
||||
MCD_OPC_SoftFail, // OPC_SoftFail(uleb128 PMask, uleb128 NMask)
|
||||
MCD_OPC_Fail // OPC_Fail()
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,270 @@
|
||||
/* Capstone Disassembly Engine */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
|
||||
|
||||
#if defined(CAPSTONE_HAS_OSXKERNEL)
|
||||
#include <Availability.h>
|
||||
#include <libkern/libkern.h>
|
||||
#else
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "MCInst.h"
|
||||
#include "utils.h"
|
||||
|
||||
#define MCINST_CACHE (ARR_SIZE(mcInst->Operands) - 1)
|
||||
|
||||
void MCInst_Init(MCInst *inst)
|
||||
{
|
||||
// unnecessary to initialize in loop . its expensive and inst->size shuold be honored
|
||||
inst->Operands[0].Kind = kInvalid;
|
||||
inst->Operands[0].ImmVal = 0;
|
||||
|
||||
inst->Opcode = 0;
|
||||
inst->OpcodePub = 0;
|
||||
inst->size = 0;
|
||||
inst->has_imm = false;
|
||||
inst->op1_size = 0;
|
||||
inst->writeback = false;
|
||||
inst->ac_idx = 0;
|
||||
inst->popcode_adjust = 0;
|
||||
inst->assembly[0] = '\0';
|
||||
inst->wasm_data.type = WASM_OP_INVALID;
|
||||
inst->xAcquireRelease = 0;
|
||||
for (int i = 0; i < MAX_MC_OPS; ++i)
|
||||
inst->tied_op_idx[i] = -1;
|
||||
}
|
||||
|
||||
void MCInst_clear(MCInst *inst)
|
||||
{
|
||||
inst->size = 0;
|
||||
}
|
||||
|
||||
// does not free @Op
|
||||
void MCInst_insert0(MCInst *inst, int index, MCOperand *Op)
|
||||
{
|
||||
assert(index < MAX_MC_OPS);
|
||||
int i;
|
||||
|
||||
for(i = inst->size; i > index; i--)
|
||||
//memcpy(&(inst->Operands[i]), &(inst->Operands[i-1]), sizeof(MCOperand));
|
||||
inst->Operands[i] = inst->Operands[i-1];
|
||||
|
||||
inst->Operands[index] = *Op;
|
||||
inst->size++;
|
||||
}
|
||||
|
||||
void MCInst_setOpcode(MCInst *inst, unsigned Op)
|
||||
{
|
||||
inst->Opcode = Op;
|
||||
}
|
||||
|
||||
void MCInst_setOpcodePub(MCInst *inst, unsigned Op)
|
||||
{
|
||||
inst->OpcodePub = Op;
|
||||
}
|
||||
|
||||
unsigned MCInst_getOpcode(const MCInst *inst)
|
||||
{
|
||||
return inst->Opcode;
|
||||
}
|
||||
|
||||
unsigned MCInst_getOpcodePub(const MCInst *inst)
|
||||
{
|
||||
return inst->OpcodePub;
|
||||
}
|
||||
|
||||
MCOperand *MCInst_getOperand(MCInst *inst, unsigned i)
|
||||
{
|
||||
assert(i < MAX_MC_OPS);
|
||||
return &inst->Operands[i];
|
||||
}
|
||||
|
||||
unsigned MCInst_getNumOperands(const MCInst *inst)
|
||||
{
|
||||
return inst->size;
|
||||
}
|
||||
|
||||
// This addOperand2 function doesnt free Op
|
||||
void MCInst_addOperand2(MCInst *inst, MCOperand *Op)
|
||||
{
|
||||
assert(inst->size < MAX_MC_OPS);
|
||||
inst->Operands[inst->size] = *Op;
|
||||
|
||||
inst->size++;
|
||||
}
|
||||
|
||||
bool MCOperand_isValid(const MCOperand *op)
|
||||
{
|
||||
return op->Kind != kInvalid;
|
||||
}
|
||||
|
||||
bool MCOperand_isReg(const MCOperand *op)
|
||||
{
|
||||
return op->Kind == kRegister;
|
||||
}
|
||||
|
||||
bool MCOperand_isImm(const MCOperand *op)
|
||||
{
|
||||
return op->Kind == kImmediate;
|
||||
}
|
||||
|
||||
bool MCOperand_isFPImm(const MCOperand *op)
|
||||
{
|
||||
return op->Kind == kFPImmediate;
|
||||
}
|
||||
|
||||
bool MCOperand_isDFPImm(const MCOperand *op)
|
||||
{
|
||||
return op->Kind == kDFPImmediate;
|
||||
}
|
||||
|
||||
bool MCOperand_isExpr(const MCOperand *op)
|
||||
{
|
||||
return op->Kind == kExpr;
|
||||
}
|
||||
|
||||
bool MCOperand_isInst(const MCOperand *op)
|
||||
{
|
||||
return op->Kind == kInst;
|
||||
}
|
||||
|
||||
/// getReg - Returns the register number.
|
||||
unsigned MCOperand_getReg(const MCOperand *op)
|
||||
{
|
||||
return op->RegVal;
|
||||
}
|
||||
|
||||
/// setReg - Set the register number.
|
||||
void MCOperand_setReg(MCOperand *op, unsigned Reg)
|
||||
{
|
||||
op->RegVal = Reg;
|
||||
}
|
||||
|
||||
int64_t MCOperand_getImm(MCOperand *op)
|
||||
{
|
||||
return op->ImmVal;
|
||||
}
|
||||
|
||||
void MCOperand_setImm(MCOperand *op, int64_t Val)
|
||||
{
|
||||
op->ImmVal = Val;
|
||||
}
|
||||
|
||||
double MCOperand_getFPImm(const MCOperand *op)
|
||||
{
|
||||
return op->FPImmVal;
|
||||
}
|
||||
|
||||
void MCOperand_setFPImm(MCOperand *op, double Val)
|
||||
{
|
||||
op->FPImmVal = Val;
|
||||
}
|
||||
|
||||
MCOperand *MCOperand_CreateReg1(MCInst *mcInst, unsigned Reg)
|
||||
{
|
||||
MCOperand *op = &(mcInst->Operands[MCINST_CACHE]);
|
||||
|
||||
op->MachineOperandType = kRegister;
|
||||
op->Kind = kRegister;
|
||||
op->RegVal = Reg;
|
||||
|
||||
return op;
|
||||
}
|
||||
|
||||
void MCOperand_CreateReg0(MCInst *mcInst, unsigned Reg)
|
||||
{
|
||||
MCOperand *op = &(mcInst->Operands[mcInst->size]);
|
||||
mcInst->size++;
|
||||
|
||||
op->MachineOperandType = kRegister;
|
||||
op->Kind = kRegister;
|
||||
op->RegVal = Reg;
|
||||
}
|
||||
|
||||
MCOperand *MCOperand_CreateImm1(MCInst *mcInst, int64_t Val)
|
||||
{
|
||||
MCOperand *op = &(mcInst->Operands[MCINST_CACHE]);
|
||||
|
||||
op->MachineOperandType = kImmediate;
|
||||
op->Kind = kImmediate;
|
||||
op->ImmVal = Val;
|
||||
|
||||
return op;
|
||||
}
|
||||
|
||||
void MCOperand_CreateImm0(MCInst *mcInst, int64_t Val)
|
||||
{
|
||||
assert(mcInst->size < MAX_MC_OPS);
|
||||
MCOperand *op = &(mcInst->Operands[mcInst->size]);
|
||||
mcInst->size++;
|
||||
|
||||
op->MachineOperandType = kImmediate;
|
||||
op->Kind = kImmediate;
|
||||
op->ImmVal = Val;
|
||||
}
|
||||
|
||||
/// Check if any operand of the MCInstrDesc is predicable
|
||||
bool MCInst_isPredicable(const MCInstrDesc *MIDesc)
|
||||
{
|
||||
const MCOperandInfo *OpInfo = MIDesc->OpInfo;
|
||||
unsigned NumOps = MIDesc->NumOperands;
|
||||
for (unsigned i = 0; i < NumOps; ++i) {
|
||||
if (MCOperandInfo_isPredicate(&OpInfo[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Checks if tied operands exist in the instruction and sets
|
||||
/// - The writeback flag in detail
|
||||
/// - Saves the indices of the tied destination operands.
|
||||
void MCInst_handleWriteback(MCInst *MI, const MCInstrDesc *InstDesc)
|
||||
{
|
||||
const MCOperandInfo *OpInfo = InstDesc[MCInst_getOpcode(MI)].OpInfo;
|
||||
unsigned short NumOps = InstDesc[MCInst_getOpcode(MI)].NumOperands;
|
||||
|
||||
unsigned i;
|
||||
for (i = 0; i < NumOps; ++i) {
|
||||
if (MCOperandInfo_isTiedToOp(&OpInfo[i])) {
|
||||
int idx = MCOperandInfo_getOperandConstraint(
|
||||
&InstDesc[MCInst_getOpcode(MI)], i,
|
||||
MCOI_TIED_TO);
|
||||
|
||||
if (idx == -1)
|
||||
continue;
|
||||
|
||||
if (i >= MAX_MC_OPS) {
|
||||
assert(0 &&
|
||||
"Maximum number of MC operands reached.");
|
||||
}
|
||||
MI->tied_op_idx[i] = idx;
|
||||
|
||||
if (MI->flat_insn->detail)
|
||||
MI->flat_insn->detail->writeback = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Check if operand with OpNum is tied by another operand
|
||||
/// (operand is tying destination).
|
||||
bool MCInst_opIsTied(const MCInst *MI, unsigned OpNum)
|
||||
{
|
||||
assert(OpNum < MAX_MC_OPS && "Maximum number of MC operands exceeded.");
|
||||
for (int i = 0; i < MAX_MC_OPS; ++i) {
|
||||
if (MI->tied_op_idx[i] == OpNum)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Check if operand with OpNum is tying another operand
|
||||
/// (operand is tying src).
|
||||
bool MCInst_opIsTying(const MCInst *MI, unsigned OpNum)
|
||||
{
|
||||
assert(OpNum < MAX_MC_OPS && "Maximum number of MC operands exceeded.");
|
||||
return MI->tied_op_idx[OpNum] != -1;
|
||||
}
|
||||
@@ -0,0 +1,165 @@
|
||||
//===-- llvm/MC/MCInst.h - MCInst class -------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains the declaration of the MCInst and MCOperand classes, which
|
||||
// is the basic representation used to represent low-level machine code
|
||||
// instructions.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/* Capstone Disassembly Engine */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
|
||||
|
||||
#ifndef CS_MCINST_H
|
||||
#define CS_MCINST_H
|
||||
|
||||
#include "include/capstone/capstone.h"
|
||||
#include "MCInstrDesc.h"
|
||||
#include "MCRegisterInfo.h"
|
||||
|
||||
typedef struct MCInst MCInst;
|
||||
typedef struct cs_struct cs_struct;
|
||||
typedef struct MCOperand MCOperand;
|
||||
|
||||
/// MCOperand - Instances of this class represent operands of the MCInst class.
|
||||
/// This is a simple discriminated union.
|
||||
struct MCOperand {
|
||||
enum {
|
||||
kInvalid = 0, ///< Uninitialized.
|
||||
kRegister, ///< Register operand.
|
||||
kImmediate, ///< Immediate operand.
|
||||
kFPImmediate, ///< Floating-point immediate operand.
|
||||
kDFPImmediate, ///< Double-Floating-point immediate operand.
|
||||
kExpr, ///< Relocatable immediate operand.
|
||||
kInst ///< Sub-instruction operand.
|
||||
|
||||
} MachineOperandType;
|
||||
unsigned char Kind;
|
||||
|
||||
union {
|
||||
unsigned RegVal;
|
||||
int64_t ImmVal;
|
||||
double FPImmVal;
|
||||
};
|
||||
};
|
||||
|
||||
bool MCOperand_isValid(const MCOperand *op);
|
||||
|
||||
bool MCOperand_isReg(const MCOperand *op);
|
||||
|
||||
bool MCOperand_isImm(const MCOperand *op);
|
||||
|
||||
bool MCOperand_isFPImm(const MCOperand *op);
|
||||
|
||||
bool MCOperand_isDFPImm(const MCOperand *op);
|
||||
|
||||
bool MCOperand_isExpr(const MCOperand *op);
|
||||
|
||||
bool MCOperand_isInst(const MCOperand *op);
|
||||
|
||||
/// getReg - Returns the register number.
|
||||
unsigned MCOperand_getReg(const MCOperand *op);
|
||||
|
||||
/// setReg - Set the register number.
|
||||
void MCOperand_setReg(MCOperand *op, unsigned Reg);
|
||||
|
||||
int64_t MCOperand_getImm(MCOperand *op);
|
||||
|
||||
void MCOperand_setImm(MCOperand *op, int64_t Val);
|
||||
|
||||
double MCOperand_getFPImm(const MCOperand *op);
|
||||
|
||||
void MCOperand_setFPImm(MCOperand *op, double Val);
|
||||
|
||||
const MCInst *MCOperand_getInst(const MCOperand *op);
|
||||
|
||||
void MCOperand_setInst(MCOperand *op, const MCInst *Val);
|
||||
|
||||
// create Reg operand in the next slot
|
||||
void MCOperand_CreateReg0(MCInst *inst, unsigned Reg);
|
||||
|
||||
// create Reg operand use the last-unused slot
|
||||
MCOperand *MCOperand_CreateReg1(MCInst *inst, unsigned Reg);
|
||||
|
||||
// create Imm operand in the next slot
|
||||
void MCOperand_CreateImm0(MCInst *inst, int64_t Val);
|
||||
|
||||
// create Imm operand in the last-unused slot
|
||||
MCOperand *MCOperand_CreateImm1(MCInst *inst, int64_t Val);
|
||||
|
||||
#define MAX_MC_OPS 48
|
||||
|
||||
/// MCInst - Instances of this class represent a single low-level machine
|
||||
/// instruction.
|
||||
struct MCInst {
|
||||
unsigned OpcodePub; // public opcode (<arch>_INS_yyy in header files <arch>.h)
|
||||
uint8_t size; // number of operands
|
||||
bool has_imm; // indicate this instruction has an X86_OP_IMM operand - used for ATT syntax
|
||||
uint8_t op1_size; // size of 1st operand - for X86 Intel syntax
|
||||
unsigned Opcode; // private opcode
|
||||
MCOperand Operands[MAX_MC_OPS];
|
||||
cs_insn *flat_insn; // insn to be exposed to public
|
||||
uint64_t address; // address of this insn
|
||||
cs_struct *csh; // save the main csh
|
||||
uint8_t x86opsize; // opsize for [mem] operand
|
||||
|
||||
// These flags could be used to pass some info from one target subcomponent
|
||||
// to another, for example, from disassembler to asm printer. The values of
|
||||
// the flags have any sense on target level only (e.g. prefixes on x86).
|
||||
unsigned flags;
|
||||
|
||||
// (Optional) instruction prefix, which can be up to 4 bytes.
|
||||
// A prefix byte gets value 0 when irrelevant.
|
||||
// This is copied from cs_x86 struct
|
||||
uint8_t x86_prefix[4];
|
||||
uint8_t imm_size; // immediate size for X86_OP_IMM operand
|
||||
bool writeback; // writeback for ARM
|
||||
int8_t tied_op_idx
|
||||
[MAX_MC_OPS]; ///< Tied operand indices. Index = Src op; Value: Dest op
|
||||
// operand access index for list of registers sharing the same access right (for ARM)
|
||||
uint8_t ac_idx;
|
||||
uint8_t popcode_adjust; // Pseudo X86 instruction adjust
|
||||
char assembly[8]; // for special instruction, so that we dont need printer
|
||||
unsigned char evm_data[32]; // for EVM PUSH operand
|
||||
cs_wasm_op wasm_data; // for WASM operand
|
||||
MCRegisterInfo *MRI;
|
||||
uint8_t xAcquireRelease; // X86 xacquire/xrelease
|
||||
};
|
||||
|
||||
void MCInst_Init(MCInst *inst);
|
||||
|
||||
void MCInst_clear(MCInst *inst);
|
||||
|
||||
// do not free operand after inserting
|
||||
void MCInst_insert0(MCInst *inst, int index, MCOperand *Op);
|
||||
|
||||
void MCInst_setOpcode(MCInst *inst, unsigned Op);
|
||||
|
||||
unsigned MCInst_getOpcode(const MCInst*);
|
||||
|
||||
void MCInst_setOpcodePub(MCInst *inst, unsigned Op);
|
||||
|
||||
unsigned MCInst_getOpcodePub(const MCInst*);
|
||||
|
||||
MCOperand *MCInst_getOperand(MCInst *inst, unsigned i);
|
||||
|
||||
unsigned MCInst_getNumOperands(const MCInst *inst);
|
||||
|
||||
// This addOperand2 function doesnt free Op
|
||||
void MCInst_addOperand2(MCInst *inst, MCOperand *Op);
|
||||
|
||||
bool MCInst_isPredicable(const MCInstrDesc *MIDesc);
|
||||
|
||||
void MCInst_handleWriteback(MCInst *MI, const MCInstrDesc *InstDesc);
|
||||
|
||||
bool MCInst_opIsTied(const MCInst *MI, unsigned OpNum);
|
||||
|
||||
bool MCInst_opIsTying(const MCInst *MI, unsigned OpNum);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,41 @@
|
||||
/* Capstone Disassembly Engine */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
|
||||
|
||||
#include "MCInstrDesc.h"
|
||||
|
||||
/// isPredicate - Set if this is one of the operands that made up of
|
||||
/// the predicate operand that controls an isPredicable() instruction.
|
||||
bool MCOperandInfo_isPredicate(const MCOperandInfo *m)
|
||||
{
|
||||
return m->Flags & (1 << MCOI_Predicate);
|
||||
}
|
||||
|
||||
/// isOptionalDef - Set if this operand is a optional def.
|
||||
///
|
||||
bool MCOperandInfo_isOptionalDef(const MCOperandInfo *m)
|
||||
{
|
||||
return m->Flags & (1 << MCOI_OptionalDef);
|
||||
}
|
||||
|
||||
/// Checks if operand is tied to another one.
|
||||
bool MCOperandInfo_isTiedToOp(const MCOperandInfo *m)
|
||||
{
|
||||
if (m->Constraints & (1 << MCOI_TIED_TO))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Returns the value of the specified operand constraint if
|
||||
/// it is present. Returns -1 if it is not present.
|
||||
int MCOperandInfo_getOperandConstraint(const MCInstrDesc *InstrDesc,
|
||||
unsigned OpNum,
|
||||
MCOI_OperandConstraint Constraint)
|
||||
{
|
||||
const MCOperandInfo OpInfo = InstrDesc->OpInfo[OpNum];
|
||||
if (OpNum < InstrDesc->NumOperands &&
|
||||
(OpInfo.Constraints & (1 << Constraint))) {
|
||||
unsigned ValuePos = 4 + Constraint * 4;
|
||||
return (OpInfo.Constraints >> ValuePos) & 0xf;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
@@ -0,0 +1,167 @@
|
||||
//===-- llvm/MC/MCInstrDesc.h - Instruction Descriptors -*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines the MCOperandInfo and MCInstrDesc classes, which
|
||||
// are used to describe target instructions and their operands.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/* Capstone Disassembly Engine */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
|
||||
|
||||
#ifndef CS_LLVM_MC_MCINSTRDESC_H
|
||||
#define CS_LLVM_MC_MCINSTRDESC_H
|
||||
|
||||
#include "MCRegisterInfo.h"
|
||||
#include "capstone/platform.h"
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Machine Operand Flags and Description
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// Operand constraints. These are encoded in 16 bits with one of the
|
||||
/// low-order 3 bits specifying that a constraint is present and the
|
||||
/// corresponding high-order hex digit specifying the constraint value.
|
||||
/// This allows for a maximum of 3 constraints.
|
||||
typedef enum {
|
||||
MCOI_TIED_TO = 0, // Operand tied to another operand.
|
||||
MCOI_EARLY_CLOBBER // Operand is an early clobber register operand
|
||||
} MCOI_OperandConstraint;
|
||||
|
||||
// Define a macro to produce each constraint value.
|
||||
#define CONSTRAINT_MCOI_TIED_TO(op) \
|
||||
((1 << MCOI_TIED_TO) | ((op) << (4 + MCOI_TIED_TO * 4)))
|
||||
|
||||
#define CONSTRAINT_MCOI_EARLY_CLOBBER \
|
||||
(1 << MCOI_EARLY_CLOBBER)
|
||||
|
||||
/// OperandFlags - These are flags set on operands, but should be considered
|
||||
/// private, all access should go through the MCOperandInfo accessors.
|
||||
/// See the accessors for a description of what these are.
|
||||
enum MCOI_OperandFlags {
|
||||
MCOI_LookupPtrRegClass = 0,
|
||||
MCOI_Predicate,
|
||||
MCOI_OptionalDef
|
||||
};
|
||||
|
||||
/// Operand Type - Operands are tagged with one of the values of this enum.
|
||||
enum MCOI_OperandType {
|
||||
MCOI_OPERAND_UNKNOWN = 0,
|
||||
MCOI_OPERAND_IMMEDIATE = 1,
|
||||
MCOI_OPERAND_REGISTER = 2,
|
||||
MCOI_OPERAND_MEMORY = 3,
|
||||
MCOI_OPERAND_PCREL = 4,
|
||||
|
||||
MCOI_OPERAND_FIRST_GENERIC = 6,
|
||||
MCOI_OPERAND_GENERIC_0 = 6,
|
||||
MCOI_OPERAND_GENERIC_1 = 7,
|
||||
MCOI_OPERAND_GENERIC_2 = 8,
|
||||
MCOI_OPERAND_GENERIC_3 = 9,
|
||||
MCOI_OPERAND_GENERIC_4 = 10,
|
||||
MCOI_OPERAND_GENERIC_5 = 11,
|
||||
MCOI_OPERAND_LAST_GENERIC = 11,
|
||||
|
||||
MCOI_OPERAND_FIRST_GENERIC_IMM = 12,
|
||||
MCOI_OPERAND_GENERIC_IMM_0 = 12,
|
||||
MCOI_OPERAND_LAST_GENERIC_IMM = 12,
|
||||
|
||||
MCOI_OPERAND_FIRST_TARGET = 13,
|
||||
};
|
||||
|
||||
|
||||
/// MCOperandInfo - This holds information about one operand of a machine
|
||||
/// instruction, indicating the register class for register operands, etc.
|
||||
///
|
||||
typedef struct MCOperandInfo {
|
||||
/// This specifies the register class enumeration of the operand
|
||||
/// if the operand is a register. If isLookupPtrRegClass is set, then this is
|
||||
/// an index that is passed to TargetRegisterInfo::getPointerRegClass(x) to
|
||||
/// get a dynamic register class.
|
||||
int16_t RegClass;
|
||||
|
||||
/// These are flags from the MCOI::OperandFlags enum.
|
||||
uint8_t Flags;
|
||||
|
||||
/// Information about the type of the operand.
|
||||
uint8_t OperandType;
|
||||
|
||||
/// The lower 16 bits are used to specify which constraints are set.
|
||||
/// The higher 16 bits are used to specify the value of constraints (4 bits each).
|
||||
uint32_t Constraints;
|
||||
/// Currently no other information.
|
||||
} MCOperandInfo;
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Machine Instruction Flags and Description
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// MCInstrDesc flags - These should be considered private to the
|
||||
/// implementation of the MCInstrDesc class. Clients should use the predicate
|
||||
/// methods on MCInstrDesc, not use these directly. These all correspond to
|
||||
/// bitfields in the MCInstrDesc::Flags field.
|
||||
enum {
|
||||
MCID_Variadic = 0,
|
||||
MCID_HasOptionalDef,
|
||||
MCID_Pseudo,
|
||||
MCID_Return,
|
||||
MCID_Call,
|
||||
MCID_Barrier,
|
||||
MCID_Terminator,
|
||||
MCID_Branch,
|
||||
MCID_IndirectBranch,
|
||||
MCID_Compare,
|
||||
MCID_MoveImm,
|
||||
MCID_MoveReg,
|
||||
MCID_Bitcast,
|
||||
MCID_Select,
|
||||
MCID_DelaySlot,
|
||||
MCID_FoldableAsLoad,
|
||||
MCID_MayLoad,
|
||||
MCID_MayStore,
|
||||
MCID_Predicable,
|
||||
MCID_NotDuplicable,
|
||||
MCID_UnmodeledSideEffects,
|
||||
MCID_Commutable,
|
||||
MCID_ConvertibleTo3Addr,
|
||||
MCID_UsesCustomInserter,
|
||||
MCID_HasPostISelHook,
|
||||
MCID_Rematerializable,
|
||||
MCID_CheapAsAMove,
|
||||
MCID_ExtraSrcRegAllocReq,
|
||||
MCID_ExtraDefRegAllocReq,
|
||||
MCID_RegSequence,
|
||||
MCID_ExtractSubreg,
|
||||
MCID_InsertSubreg,
|
||||
MCID_Convergent,
|
||||
MCID_Add,
|
||||
MCID_Trap,
|
||||
};
|
||||
|
||||
/// MCInstrDesc - Describe properties that are true of each instruction in the
|
||||
/// target description file. This captures information about side effects,
|
||||
/// register use and many other things. There is one instance of this struct
|
||||
/// for each target instruction class, and the MachineInstr class points to
|
||||
/// this struct directly to describe itself.
|
||||
typedef struct MCInstrDesc {
|
||||
unsigned char NumOperands; // Num of args (may be more if variable_ops)
|
||||
const MCOperandInfo *OpInfo; // 'NumOperands' entries about operands
|
||||
} MCInstrDesc;
|
||||
|
||||
bool MCOperandInfo_isPredicate(const MCOperandInfo *m);
|
||||
|
||||
bool MCOperandInfo_isOptionalDef(const MCOperandInfo *m);
|
||||
|
||||
bool MCOperandInfo_isTiedToOp(const MCOperandInfo *m);
|
||||
|
||||
int MCOperandInfo_getOperandConstraint(const MCInstrDesc *OpInfo,
|
||||
unsigned OpNum,
|
||||
MCOI_OperandConstraint Constraint);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,151 @@
|
||||
//=== MC/MCRegisterInfo.cpp - Target Register Description -------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements MCRegisterInfo functions.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/* Capstone Disassembly Engine */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
|
||||
|
||||
#include "MCRegisterInfo.h"
|
||||
|
||||
/// DiffListIterator - Base iterator class that can traverse the
|
||||
/// differentially encoded register and regunit lists in DiffLists.
|
||||
/// Don't use this class directly, use one of the specialized sub-classes
|
||||
/// defined below.
|
||||
typedef struct DiffListIterator {
|
||||
uint16_t Val;
|
||||
const MCPhysReg *List;
|
||||
} DiffListIterator;
|
||||
|
||||
void MCRegisterInfo_InitMCRegisterInfo(MCRegisterInfo *RI,
|
||||
const MCRegisterDesc *D, unsigned NR,
|
||||
unsigned RA, unsigned PC,
|
||||
const MCRegisterClass *C, unsigned NC,
|
||||
uint16_t (*RURoots)[2], unsigned NRU,
|
||||
const MCPhysReg *DL,
|
||||
const char *Strings,
|
||||
const uint16_t *SubIndices, unsigned NumIndices,
|
||||
const uint16_t *RET)
|
||||
{
|
||||
RI->Desc = D;
|
||||
RI->NumRegs = NR;
|
||||
RI->RAReg = RA;
|
||||
RI->PCReg = PC;
|
||||
RI->Classes = C;
|
||||
RI->DiffLists = DL;
|
||||
RI->RegStrings = Strings;
|
||||
RI->NumClasses = NC;
|
||||
RI->RegUnitRoots = RURoots;
|
||||
RI->NumRegUnits = NRU;
|
||||
RI->SubRegIndices = SubIndices;
|
||||
RI->NumSubRegIndices = NumIndices;
|
||||
RI->RegEncodingTable = RET;
|
||||
}
|
||||
|
||||
static void DiffListIterator_init(DiffListIterator *d, MCPhysReg InitVal, const MCPhysReg *DiffList)
|
||||
{
|
||||
d->Val = InitVal;
|
||||
d->List = DiffList;
|
||||
}
|
||||
|
||||
static uint16_t DiffListIterator_getVal(DiffListIterator *d)
|
||||
{
|
||||
return d->Val;
|
||||
}
|
||||
|
||||
static bool DiffListIterator_next(DiffListIterator *d)
|
||||
{
|
||||
MCPhysReg D;
|
||||
|
||||
if (d->List == 0)
|
||||
return false;
|
||||
|
||||
D = *d->List;
|
||||
d->List++;
|
||||
d->Val += D;
|
||||
|
||||
if (!D)
|
||||
d->List = 0;
|
||||
|
||||
return (D != 0);
|
||||
}
|
||||
|
||||
static bool DiffListIterator_isValid(DiffListIterator *d)
|
||||
{
|
||||
return (d->List != 0);
|
||||
}
|
||||
|
||||
unsigned MCRegisterInfo_getMatchingSuperReg(const MCRegisterInfo *RI, unsigned Reg, unsigned SubIdx, const MCRegisterClass *RC)
|
||||
{
|
||||
DiffListIterator iter;
|
||||
|
||||
if (Reg >= RI->NumRegs) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
DiffListIterator_init(&iter, (MCPhysReg)Reg, RI->DiffLists + RI->Desc[Reg].SuperRegs);
|
||||
DiffListIterator_next(&iter);
|
||||
|
||||
while(DiffListIterator_isValid(&iter)) {
|
||||
uint16_t val = DiffListIterator_getVal(&iter);
|
||||
if (MCRegisterClass_contains(RC, val) && Reg == MCRegisterInfo_getSubReg(RI, val, SubIdx))
|
||||
return val;
|
||||
|
||||
DiffListIterator_next(&iter);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned MCRegisterInfo_getSubReg(const MCRegisterInfo *RI, unsigned Reg, unsigned Idx)
|
||||
{
|
||||
DiffListIterator iter;
|
||||
const uint16_t *SRI = RI->SubRegIndices + RI->Desc[Reg].SubRegIndices;
|
||||
|
||||
DiffListIterator_init(&iter, (MCPhysReg)Reg, RI->DiffLists + RI->Desc[Reg].SubRegs);
|
||||
DiffListIterator_next(&iter);
|
||||
|
||||
while(DiffListIterator_isValid(&iter)) {
|
||||
if (*SRI == Idx)
|
||||
return DiffListIterator_getVal(&iter);
|
||||
DiffListIterator_next(&iter);
|
||||
++SRI;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const MCRegisterClass* MCRegisterInfo_getRegClass(const MCRegisterInfo *RI, unsigned i)
|
||||
{
|
||||
//assert(i < getNumRegClasses() && "Register Class ID out of range");
|
||||
if (i >= RI->NumClasses)
|
||||
return 0;
|
||||
return &(RI->Classes[i]);
|
||||
}
|
||||
|
||||
bool MCRegisterClass_contains(const MCRegisterClass *c, unsigned Reg)
|
||||
{
|
||||
unsigned InByte = 0;
|
||||
unsigned Byte = 0;
|
||||
|
||||
// Make sure that MCRegisterInfo_getRegClass didn't return 0
|
||||
// (for calls to GETREGCLASS_CONTAIN0)
|
||||
if(!c)
|
||||
return false;
|
||||
|
||||
InByte = Reg % 8;
|
||||
Byte = Reg / 8;
|
||||
|
||||
if (Byte >= c->RegSetSize)
|
||||
return false;
|
||||
|
||||
return (c->RegSet[Byte] & (1 << InByte)) != 0;
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
//=== MC/MCRegisterInfo.h - Target Register Description ---------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file describes an abstract interface used to get information about a
|
||||
// target machines register file. This information is used for a variety of
|
||||
// purposed, especially register allocation.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/* Capstone Disassembly Engine */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
|
||||
|
||||
#ifndef CS_LLVM_MC_MCREGISTERINFO_H
|
||||
#define CS_LLVM_MC_MCREGISTERINFO_H
|
||||
|
||||
#include "capstone/platform.h"
|
||||
|
||||
/// An unsigned integer type large enough to represent all physical registers,
|
||||
/// but not necessarily virtual registers.
|
||||
typedef uint16_t MCPhysReg;
|
||||
typedef const MCPhysReg* iterator;
|
||||
|
||||
typedef struct MCRegisterClass2 {
|
||||
iterator RegsBegin;
|
||||
const uint8_t *RegSet;
|
||||
uint8_t RegsSize;
|
||||
uint8_t RegSetSize;
|
||||
} MCRegisterClass2;
|
||||
|
||||
typedef struct MCRegisterClass {
|
||||
iterator RegsBegin;
|
||||
const uint8_t *RegSet;
|
||||
uint16_t RegSetSize;
|
||||
} MCRegisterClass;
|
||||
|
||||
/// MCRegisterDesc - This record contains information about a particular
|
||||
/// register. The SubRegs field is a zero terminated array of registers that
|
||||
/// are sub-registers of the specific register, e.g. AL, AH are sub-registers
|
||||
/// of AX. The SuperRegs field is a zero terminated array of registers that are
|
||||
/// super-registers of AX.
|
||||
typedef struct MCRegisterDesc {
|
||||
uint32_t Name; // Printable name for the reg (for debugging)
|
||||
uint32_t SubRegs; // Sub-register set, described above
|
||||
uint32_t SuperRegs; // Super-register set, described above
|
||||
|
||||
// Offset into MCRI::SubRegIndices of a list of sub-register indices for each
|
||||
// sub-register in SubRegs.
|
||||
uint32_t SubRegIndices;
|
||||
|
||||
// RegUnits - Points to the list of register units. The low 4 bits holds the
|
||||
// Scale, the high bits hold an offset into DiffLists. See MCRegUnitIterator.
|
||||
uint32_t RegUnits;
|
||||
|
||||
/// Index into list with lane mask sequences. The sequence contains a lanemask
|
||||
/// for every register unit.
|
||||
uint16_t RegUnitLaneMasks; // ???
|
||||
} MCRegisterDesc;
|
||||
|
||||
/// MCRegisterInfo base class - We assume that the target defines a static
|
||||
/// array of MCRegisterDesc objects that represent all of the machine
|
||||
/// registers that the target has. As such, we simply have to track a pointer
|
||||
/// to this array so that we can turn register number into a register
|
||||
/// descriptor.
|
||||
///
|
||||
/// Note this class is designed to be a base class of TargetRegisterInfo, which
|
||||
/// is the interface used by codegen. However, specific targets *should never*
|
||||
/// specialize this class. MCRegisterInfo should only contain getters to access
|
||||
/// TableGen generated physical register data. It must not be extended with
|
||||
/// virtual methods.
|
||||
typedef struct MCRegisterInfo {
|
||||
const MCRegisterDesc *Desc; // Pointer to the descriptor array
|
||||
unsigned NumRegs; // Number of entries in the array
|
||||
unsigned RAReg; // Return address register
|
||||
unsigned PCReg; // Program counter register
|
||||
const MCRegisterClass *Classes; // Pointer to the regclass array
|
||||
unsigned NumClasses; // Number of entries in the array
|
||||
unsigned NumRegUnits; // Number of regunits.
|
||||
uint16_t (*RegUnitRoots)[2]; // Pointer to regunit root table.
|
||||
const MCPhysReg *DiffLists; // Pointer to the difflists array
|
||||
// const LaneBitmask *RegUnitMaskSequences; // Pointer to lane mask sequences
|
||||
const char *RegStrings; // Pointer to the string table.
|
||||
// const char *RegClassStrings; // Pointer to the class strings.
|
||||
const uint16_t *SubRegIndices; // Pointer to the subreg lookup
|
||||
// array.
|
||||
unsigned NumSubRegIndices; // Number of subreg indices.
|
||||
const uint16_t *RegEncodingTable; // Pointer to array of register
|
||||
// encodings.
|
||||
} MCRegisterInfo;
|
||||
|
||||
void MCRegisterInfo_InitMCRegisterInfo(MCRegisterInfo *RI,
|
||||
const MCRegisterDesc *D, unsigned NR, unsigned RA,
|
||||
unsigned PC,
|
||||
const MCRegisterClass *C, unsigned NC,
|
||||
uint16_t (*RURoots)[2],
|
||||
unsigned NRU,
|
||||
const MCPhysReg *DL,
|
||||
const char *Strings,
|
||||
const uint16_t *SubIndices,
|
||||
unsigned NumIndices,
|
||||
const uint16_t *RET);
|
||||
|
||||
unsigned MCRegisterInfo_getMatchingSuperReg(const MCRegisterInfo *RI, unsigned Reg, unsigned SubIdx, const MCRegisterClass *RC);
|
||||
|
||||
unsigned MCRegisterInfo_getSubReg(const MCRegisterInfo *RI, unsigned Reg, unsigned Idx);
|
||||
|
||||
const MCRegisterClass* MCRegisterInfo_getRegClass(const MCRegisterInfo *RI, unsigned i);
|
||||
|
||||
bool MCRegisterClass_contains(const MCRegisterClass *c, unsigned Reg);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,636 @@
|
||||
# Capstone Disassembly Engine
|
||||
# By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2014
|
||||
|
||||
include config.mk
|
||||
include pkgconfig.mk # package version
|
||||
include functions.mk
|
||||
|
||||
# Verbose output?
|
||||
V ?= 0
|
||||
|
||||
OS := $(shell uname)
|
||||
ifeq ($(OS),Darwin)
|
||||
LIBARCHS ?= x86_64 arm64
|
||||
PREFIX ?= /usr/local
|
||||
endif
|
||||
|
||||
ifeq ($(PKG_EXTRA),)
|
||||
PKG_VERSION = $(PKG_MAJOR).$(PKG_MINOR)
|
||||
else
|
||||
PKG_VERSION = $(PKG_MAJOR).$(PKG_MINOR).$(PKG_EXTRA)
|
||||
endif
|
||||
|
||||
ifeq ($(CROSS),)
|
||||
RANLIB ?= ranlib
|
||||
else ifeq ($(ANDROID), 1)
|
||||
CC = $(CROSS)/../../bin/clang
|
||||
AR = $(CROSS)/ar
|
||||
RANLIB = $(CROSS)/ranlib
|
||||
STRIP = $(CROSS)/strip
|
||||
else
|
||||
CC = $(CROSS)gcc
|
||||
AR = $(CROSS)ar
|
||||
RANLIB = $(CROSS)ranlib
|
||||
STRIP = $(CROSS)strip
|
||||
endif
|
||||
|
||||
ifeq ($(OS),OS/390)
|
||||
RANLIB = touch
|
||||
endif
|
||||
|
||||
ifneq (,$(findstring yes,$(CAPSTONE_DIET)))
|
||||
CFLAGS ?= -Os
|
||||
CFLAGS += -DCAPSTONE_DIET
|
||||
else
|
||||
CFLAGS ?= -O3
|
||||
endif
|
||||
|
||||
# C99 has been enforced elsewhere like xcode
|
||||
CFLAGS += -std=gnu99
|
||||
|
||||
ifneq (,$(findstring yes,$(CAPSTONE_X86_ATT_DISABLE)))
|
||||
CFLAGS += -DCAPSTONE_X86_ATT_DISABLE
|
||||
endif
|
||||
|
||||
ifeq ($(CC),xlc)
|
||||
CFLAGS += -qcpluscmt -qkeyword=inline -qlanglvl=extc1x -Iinclude
|
||||
ifneq ($(OS),OS/390)
|
||||
CFLAGS += -fPIC
|
||||
endif
|
||||
else
|
||||
CFLAGS += -fPIC -Wall -Wwrite-strings -Wmissing-prototypes -Iinclude
|
||||
endif
|
||||
|
||||
ifeq ($(CAPSTONE_USE_SYS_DYN_MEM),yes)
|
||||
CFLAGS += -DCAPSTONE_USE_SYS_DYN_MEM
|
||||
endif
|
||||
|
||||
ifeq ($(CAPSTONE_HAS_OSXKERNEL), yes)
|
||||
CFLAGS += -DCAPSTONE_HAS_OSXKERNEL
|
||||
SDKROOT ?= $(shell xcodebuild -version -sdk macosx Path)
|
||||
CFLAGS += -mmacosx-version-min=10.5 \
|
||||
-isysroot$(SDKROOT) \
|
||||
-I$(SDKROOT)/System/Library/Frameworks/Kernel.framework/Headers \
|
||||
-mkernel \
|
||||
-fno-builtin
|
||||
endif
|
||||
|
||||
PREFIX ?= /usr
|
||||
DESTDIR ?=
|
||||
ifndef BUILDDIR
|
||||
BLDIR = .
|
||||
OBJDIR = .
|
||||
else
|
||||
BLDIR = $(abspath $(BUILDDIR))
|
||||
OBJDIR = $(BLDIR)/obj
|
||||
endif
|
||||
INCDIR ?= $(PREFIX)/include
|
||||
|
||||
UNAME_S := $(shell uname -s)
|
||||
|
||||
LIBDIRARCH ?= lib
|
||||
# Uncomment the below line to installs x86_64 libs to lib64/ directory.
|
||||
# Or better, pass 'LIBDIRARCH=lib64' to 'make install/uninstall' via 'make.sh'.
|
||||
#LIBDIRARCH ?= lib64
|
||||
LIBDIR = $(DESTDIR)$(PREFIX)/$(LIBDIRARCH)
|
||||
BINDIR = $(DESTDIR)$(PREFIX)/bin
|
||||
|
||||
LIBDATADIR = $(LIBDIR)
|
||||
|
||||
# Don't redefine $LIBDATADIR when global environment variable
|
||||
# USE_GENERIC_LIBDATADIR is set. This is used by the pkgsrc framework.
|
||||
|
||||
ifndef USE_GENERIC_LIBDATADIR
|
||||
ifeq ($(UNAME_S), FreeBSD)
|
||||
LIBDATADIR = $(DESTDIR)$(PREFIX)/libdata
|
||||
endif
|
||||
ifeq ($(UNAME_S), DragonFly)
|
||||
LIBDATADIR = $(DESTDIR)$(PREFIX)/libdata
|
||||
endif
|
||||
endif
|
||||
|
||||
INSTALL_BIN ?= install
|
||||
INSTALL_DATA ?= $(INSTALL_BIN) -m0644
|
||||
INSTALL_LIB ?= $(INSTALL_BIN) -m0755
|
||||
|
||||
LIBNAME = capstone
|
||||
|
||||
|
||||
DEP_ARM =
|
||||
DEP_ARM += $(wildcard arch/ARM/ARM*.inc)
|
||||
|
||||
LIBOBJ_ARM =
|
||||
ifneq (,$(findstring arm,$(CAPSTONE_ARCHS)))
|
||||
CFLAGS += -DCAPSTONE_HAS_ARM
|
||||
LIBSRC_ARM += $(wildcard arch/ARM/ARM*.c)
|
||||
LIBOBJ_ARM += $(LIBSRC_ARM:%.c=$(OBJDIR)/%.o)
|
||||
endif
|
||||
|
||||
DEP_ARM64 =
|
||||
DEP_ARM64 += $(wildcard arch/AArch64/AArch64*.inc)
|
||||
|
||||
LIBOBJ_ARM64 =
|
||||
ifneq (,$(findstring aarch64,$(CAPSTONE_ARCHS)))
|
||||
CFLAGS += -DCAPSTONE_HAS_ARM64
|
||||
LIBSRC_ARM64 += $(wildcard arch/AArch64/AArch64*.c)
|
||||
LIBOBJ_ARM64 += $(LIBSRC_ARM64:%.c=$(OBJDIR)/%.o)
|
||||
endif
|
||||
|
||||
|
||||
DEP_M68K =
|
||||
DEP_M68K += $(wildcard arch/M68K/M68K*.inc)
|
||||
DEP_M68K += $(wildcard arch/M68K/M68K*.h)
|
||||
|
||||
LIBOBJ_M68K =
|
||||
ifneq (,$(findstring m68k,$(CAPSTONE_ARCHS)))
|
||||
CFLAGS += -DCAPSTONE_HAS_M68K
|
||||
LIBSRC_M68K += $(wildcard arch/M68K/M68K*.c)
|
||||
LIBOBJ_M68K += $(LIBSRC_M68K:%.c=$(OBJDIR)/%.o)
|
||||
endif
|
||||
|
||||
DEP_MIPS =
|
||||
DEP_MIPS += $(wildcard arch/Mips/Mips*.inc)
|
||||
|
||||
LIBOBJ_MIPS =
|
||||
ifneq (,$(findstring mips,$(CAPSTONE_ARCHS)))
|
||||
CFLAGS += -DCAPSTONE_HAS_MIPS
|
||||
LIBSRC_MIPS += $(wildcard arch/Mips/Mips*.c)
|
||||
LIBOBJ_MIPS += $(LIBSRC_MIPS:%.c=$(OBJDIR)/%.o)
|
||||
endif
|
||||
|
||||
DEP_SH = $(wildcard arch/SH/SH*.inc)
|
||||
|
||||
LIBOBJ_SH =
|
||||
ifneq (,$(findstring sh,$(CAPSTONE_ARCHS)))
|
||||
CFLAGS += -DCAPSTONE_HAS_SH
|
||||
LIBSRC_SH += $(wildcard arch/SH/SH*.c)
|
||||
LIBOBJ_SH += $(LIBSRC_SH:%.c=$(OBJDIR)/%.o)
|
||||
endif
|
||||
|
||||
DEP_PPC =
|
||||
DEP_PPC += $(wildcard arch/PowerPC/PPC*.inc)
|
||||
|
||||
LIBOBJ_PPC =
|
||||
ifneq (,$(findstring powerpc,$(CAPSTONE_ARCHS)))
|
||||
CFLAGS += -DCAPSTONE_HAS_POWERPC
|
||||
LIBSRC_PPC += $(wildcard arch/PowerPC/PPC*.c)
|
||||
LIBOBJ_PPC += $(LIBSRC_PPC:%.c=$(OBJDIR)/%.o)
|
||||
endif
|
||||
|
||||
|
||||
DEP_SPARC =
|
||||
DEP_SPARC += $(wildcard arch/Sparc/Sparc*.inc)
|
||||
|
||||
LIBOBJ_SPARC =
|
||||
ifneq (,$(findstring sparc,$(CAPSTONE_ARCHS)))
|
||||
CFLAGS += -DCAPSTONE_HAS_SPARC
|
||||
LIBSRC_SPARC += $(wildcard arch/Sparc/Sparc*.c)
|
||||
LIBOBJ_SPARC += $(LIBSRC_SPARC:%.c=$(OBJDIR)/%.o)
|
||||
endif
|
||||
|
||||
|
||||
DEP_SYSZ =
|
||||
DEP_SYSZ += $(wildcard arch/SystemZ/SystemZ*.inc)
|
||||
|
||||
LIBOBJ_SYSZ =
|
||||
ifneq (,$(findstring systemz,$(CAPSTONE_ARCHS)))
|
||||
CFLAGS += -DCAPSTONE_HAS_SYSZ
|
||||
LIBSRC_SYSZ += $(wildcard arch/SystemZ/SystemZ*.c)
|
||||
LIBOBJ_SYSZ += $(LIBSRC_SYSZ:%.c=$(OBJDIR)/%.o)
|
||||
endif
|
||||
|
||||
|
||||
# by default, we compile full X86 instruction sets
|
||||
X86_REDUCE =
|
||||
ifneq (,$(findstring yes,$(CAPSTONE_X86_REDUCE)))
|
||||
X86_REDUCE = _reduce
|
||||
CFLAGS += -DCAPSTONE_X86_REDUCE -Os
|
||||
endif
|
||||
|
||||
|
||||
DEP_X86 =
|
||||
DEP_X86 += $(wildcard arch/X86/X86*.inc)
|
||||
|
||||
LIBOBJ_X86 =
|
||||
ifneq (,$(findstring x86,$(CAPSTONE_ARCHS)))
|
||||
CFLAGS += -DCAPSTONE_HAS_X86
|
||||
LIBOBJ_X86 += $(OBJDIR)/arch/X86/X86DisassemblerDecoder.o
|
||||
LIBOBJ_X86 += $(OBJDIR)/arch/X86/X86Disassembler.o
|
||||
LIBOBJ_X86 += $(OBJDIR)/arch/X86/X86InstPrinterCommon.o
|
||||
LIBOBJ_X86 += $(OBJDIR)/arch/X86/X86IntelInstPrinter.o
|
||||
# assembly syntax is irrelevant in Diet mode, when this info is suppressed
|
||||
ifeq (,$(findstring yes,$(CAPSTONE_DIET)))
|
||||
ifeq (,$(findstring yes,$(CAPSTONE_X86_ATT_DISABLE)))
|
||||
LIBOBJ_X86 += $(OBJDIR)/arch/X86/X86ATTInstPrinter.o
|
||||
endif
|
||||
endif
|
||||
LIBOBJ_X86 += $(OBJDIR)/arch/X86/X86Mapping.o
|
||||
LIBOBJ_X86 += $(OBJDIR)/arch/X86/X86Module.o
|
||||
endif
|
||||
|
||||
|
||||
DEP_XCORE =
|
||||
DEP_XCORE += $(wildcard arch/XCore/XCore*.inc)
|
||||
|
||||
LIBOBJ_XCORE =
|
||||
ifneq (,$(findstring xcore,$(CAPSTONE_ARCHS)))
|
||||
CFLAGS += -DCAPSTONE_HAS_XCORE
|
||||
LIBSRC_XCORE += $(wildcard arch/XCore/XCore*.c)
|
||||
LIBOBJ_XCORE += $(LIBSRC_XCORE:%.c=$(OBJDIR)/%.o)
|
||||
endif
|
||||
|
||||
|
||||
DEP_TMS320C64X =
|
||||
DEP_TMS320C64X += $(wildcard arch/TMS320C64x/TMS320C64x*.inc)
|
||||
|
||||
LIBOBJ_TMS320C64X =
|
||||
ifneq (,$(findstring tms320c64x,$(CAPSTONE_ARCHS)))
|
||||
CFLAGS += -DCAPSTONE_HAS_TMS320C64X
|
||||
LIBSRC_TMS320C64X += $(wildcard arch/TMS320C64x/TMS320C64x*.c)
|
||||
LIBOBJ_TMS320C64X += $(LIBSRC_TMS320C64X:%.c=$(OBJDIR)/%.o)
|
||||
endif
|
||||
|
||||
DEP_M680X =
|
||||
DEP_M680X += $(wildcard arch/M680X/*.inc)
|
||||
DEP_M680X += $(wildcard arch/M680X/M680X*.h)
|
||||
|
||||
LIBOBJ_M680X =
|
||||
ifneq (,$(findstring m680x,$(CAPSTONE_ARCHS)))
|
||||
CFLAGS += -DCAPSTONE_HAS_M680X
|
||||
LIBSRC_M680X += $(wildcard arch/M680X/*.c)
|
||||
LIBOBJ_M680X += $(LIBSRC_M680X:%.c=$(OBJDIR)/%.o)
|
||||
endif
|
||||
|
||||
|
||||
DEP_EVM =
|
||||
DEP_EVM += $(wildcard arch/EVM/EVM*.inc)
|
||||
|
||||
LIBOBJ_EVM =
|
||||
ifneq (,$(findstring evm,$(CAPSTONE_ARCHS)))
|
||||
CFLAGS += -DCAPSTONE_HAS_EVM
|
||||
LIBSRC_EVM += $(wildcard arch/EVM/EVM*.c)
|
||||
LIBOBJ_EVM += $(LIBSRC_EVM:%.c=$(OBJDIR)/%.o)
|
||||
endif
|
||||
|
||||
DEP_RISCV =
|
||||
DEP_RISCV += $(wildcard arch/RISCV/RISCV*.inc)
|
||||
|
||||
LIBOBJ_RISCV =
|
||||
ifneq (,$(findstring riscv,$(CAPSTONE_ARCHS)))
|
||||
CFLAGS += -DCAPSTONE_HAS_RISCV
|
||||
LIBSRC_RISCV += $(wildcard arch/RISCV/RISCV*.c)
|
||||
LIBOBJ_RISCV += $(LIBSRC_RISCV:%.c=$(OBJDIR)/%.o)
|
||||
endif
|
||||
|
||||
DEP_WASM =
|
||||
DEP_WASM += $(wildcard arch/WASM/WASM*.inc)
|
||||
|
||||
LIBOBJ_WASM =
|
||||
ifneq (,$(findstring wasm,$(CAPSTONE_ARCHS)))
|
||||
CFLAGS += -DCAPSTONE_HAS_WASM
|
||||
LIBSRC_WASM += $(wildcard arch/WASM/WASM*.c)
|
||||
LIBOBJ_WASM += $(LIBSRC_WASM:%.c=$(OBJDIR)/%.o)
|
||||
endif
|
||||
|
||||
|
||||
DEP_MOS65XX =
|
||||
DEP_MOS65XX += $(wildcard arch/MOS65XX/MOS65XX*.inc)
|
||||
|
||||
LIBOBJ_MOS65XX =
|
||||
ifneq (,$(findstring mos65xx,$(CAPSTONE_ARCHS)))
|
||||
CFLAGS += -DCAPSTONE_HAS_MOS65XX
|
||||
LIBSRC_MOS65XX += $(wildcard arch/MOS65XX/MOS65XX*.c)
|
||||
LIBOBJ_MOS65XX += $(LIBSRC_MOS65XX:%.c=$(OBJDIR)/%.o)
|
||||
endif
|
||||
|
||||
|
||||
DEP_BPF =
|
||||
DEP_BPF += $(wildcard arch/BPF/BPF*.inc)
|
||||
|
||||
LIBOBJ_BPF =
|
||||
ifneq (,$(findstring bpf,$(CAPSTONE_ARCHS)))
|
||||
CFLAGS += -DCAPSTONE_HAS_BPF
|
||||
LIBSRC_BPF += $(wildcard arch/BPF/BPF*.c)
|
||||
LIBOBJ_BPF += $(LIBSRC_BPF:%.c=$(OBJDIR)/%.o)
|
||||
endif
|
||||
|
||||
DEP_TRICORE =
|
||||
DEP_TRICORE +=$(wildcard arch/TriCore/TriCore*.inc)
|
||||
|
||||
LIBOBJ_TRICORE =
|
||||
ifneq (,$(findstring tricore,$(CAPSTONE_ARCHS)))
|
||||
CFLAGS += -DCAPSTONE_HAS_TRICORE
|
||||
LIBSRC_TRICORE += $(wildcard arch/TriCore/TriCore*.c)
|
||||
LIBOBJ_TRICORE += $(LIBSRC_TRICORE:%.c=$(OBJDIR)/%.o)
|
||||
endif
|
||||
|
||||
|
||||
LIBOBJ =
|
||||
LIBOBJ += $(OBJDIR)/cs.o $(OBJDIR)/utils.o $(OBJDIR)/SStream.o $(OBJDIR)/MCInstrDesc.o $(OBJDIR)/MCRegisterInfo.o $(OBJDIR)/MCInst.o $(OBJDIR)/Mapping.o
|
||||
LIBOBJ += $(LIBOBJ_ARM) $(LIBOBJ_ARM64) $(LIBOBJ_M68K) $(LIBOBJ_MIPS) $(LIBOBJ_PPC) $(LIBOBJ_RISCV) $(LIBOBJ_SPARC) $(LIBOBJ_SYSZ) $(LIBOBJ_SH)
|
||||
LIBOBJ += $(LIBOBJ_X86) $(LIBOBJ_XCORE) $(LIBOBJ_TMS320C64X) $(LIBOBJ_M680X) $(LIBOBJ_EVM) $(LIBOBJ_MOS65XX) $(LIBOBJ_WASM) $(LIBOBJ_BPF)
|
||||
LIBOBJ += $(LIBOBJ_TRICORE)
|
||||
|
||||
|
||||
ifeq ($(PKG_EXTRA),)
|
||||
PKGCFGDIR = $(LIBDATADIR)/pkgconfig
|
||||
else
|
||||
PKGCFGDIR ?= $(LIBDATADIR)/pkgconfig
|
||||
ifeq ($(PKGCFGDIR),)
|
||||
PKGCFGDIR = $(LIBDATADIR)/pkgconfig
|
||||
endif
|
||||
endif
|
||||
|
||||
API_MAJOR=$(shell echo `grep -e CS_API_MAJOR include/capstone/capstone.h | grep -v = | awk '{print $$3}'` | awk '{print $$1}')
|
||||
VERSION_EXT =
|
||||
|
||||
IS_APPLE := $(shell $(CC) -dM -E - < /dev/null 2> /dev/null | grep __apple_build_version__ | wc -l | tr -d " ")
|
||||
ifeq ($(IS_APPLE),1)
|
||||
# on MacOS, do not build in Universal format by default
|
||||
MACOS_UNIVERSAL ?= no
|
||||
ifeq ($(MACOS_UNIVERSAL),yes)
|
||||
CFLAGS += $(foreach arch,$(LIBARCHS),-arch $(arch))
|
||||
LDFLAGS += $(foreach arch,$(LIBARCHS),-arch $(arch))
|
||||
endif
|
||||
EXT = dylib
|
||||
VERSION_EXT = $(API_MAJOR).$(EXT)
|
||||
$(LIBNAME)_LDFLAGS += -dynamiclib -install_name lib$(LIBNAME).$(VERSION_EXT) -current_version $(PKG_MAJOR).$(PKG_MINOR).$(PKG_EXTRA) -compatibility_version $(PKG_MAJOR).$(PKG_MINOR)
|
||||
AR_EXT = a
|
||||
# Homebrew wants to make sure its formula does not disable FORTIFY_SOURCE
|
||||
# However, this is not really necessary because 'CAPSTONE_USE_SYS_DYN_MEM=yes' by default
|
||||
ifneq ($(HOMEBREW_CAPSTONE),1)
|
||||
ifneq ($(CAPSTONE_USE_SYS_DYN_MEM),yes)
|
||||
# remove string check because OSX kernel complains about missing symbols
|
||||
CFLAGS += -D_FORTIFY_SOURCE=0
|
||||
endif
|
||||
endif
|
||||
else
|
||||
CFLAGS += $(foreach arch,$(LIBARCHS),-arch $(arch))
|
||||
LDFLAGS += $(foreach arch,$(LIBARCHS),-arch $(arch))
|
||||
ifeq ($(OS), AIX)
|
||||
$(LIBNAME)_LDFLAGS += -qmkshrobj
|
||||
else
|
||||
$(LIBNAME)_LDFLAGS += -shared
|
||||
endif
|
||||
# Cygwin?
|
||||
IS_CYGWIN := $(shell $(CC) -dumpmachine 2>/dev/null | grep -i cygwin | wc -l)
|
||||
ifeq ($(IS_CYGWIN),1)
|
||||
EXT = dll
|
||||
AR_EXT = lib
|
||||
# Cygwin doesn't like -fPIC
|
||||
CFLAGS := $(CFLAGS:-fPIC=)
|
||||
# On Windows we need the shared library to be executable
|
||||
else
|
||||
# mingw?
|
||||
IS_MINGW := $(shell $(CC) --version 2>/dev/null | grep -i "\(mingw\|MSYS\)" | wc -l)
|
||||
ifeq ($(IS_MINGW),1)
|
||||
EXT = dll
|
||||
AR_EXT = lib
|
||||
# mingw doesn't like -fPIC either
|
||||
CFLAGS := $(CFLAGS:-fPIC=)
|
||||
# On Windows we need the shared library to be executable
|
||||
else
|
||||
# Linux, *BSD
|
||||
EXT = so
|
||||
VERSION_EXT = $(EXT).$(API_MAJOR)
|
||||
AR_EXT = a
|
||||
$(LIBNAME)_LDFLAGS += -Wl,-soname,lib$(LIBNAME).$(VERSION_EXT)
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(CAPSTONE_SHARED),yes)
|
||||
ifeq ($(IS_MINGW),1)
|
||||
LIBRARY = $(BLDIR)/$(LIBNAME).$(VERSION_EXT)
|
||||
else ifeq ($(IS_CYGWIN),1)
|
||||
LIBRARY = $(BLDIR)/$(LIBNAME).$(EXT)
|
||||
else # *nix
|
||||
LIBRARY = $(BLDIR)/lib$(LIBNAME).$(VERSION_EXT)
|
||||
CFLAGS += -fvisibility=hidden
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(CAPSTONE_STATIC),yes)
|
||||
ifeq ($(IS_MINGW),1)
|
||||
ARCHIVE = $(BLDIR)/$(LIBNAME).$(AR_EXT)
|
||||
else ifeq ($(IS_CYGWIN),1)
|
||||
ARCHIVE = $(BLDIR)/$(LIBNAME).$(AR_EXT)
|
||||
else
|
||||
ARCHIVE = $(BLDIR)/lib$(LIBNAME).$(AR_EXT)
|
||||
endif
|
||||
endif
|
||||
|
||||
PKGCFGF = $(BLDIR)/$(LIBNAME).pc
|
||||
|
||||
.PHONY: all clean install uninstall dist
|
||||
|
||||
all: $(LIBRARY) $(ARCHIVE) $(PKGCFGF)
|
||||
ifeq (,$(findstring yes,$(CAPSTONE_BUILD_CORE_ONLY)))
|
||||
@V=$(V) CC=$(CC) $(MAKE) -C cstool
|
||||
ifndef BUILDDIR
|
||||
$(MAKE) -C tests
|
||||
else
|
||||
$(MAKE) -C tests BUILDDIR=$(BLDIR)
|
||||
endif
|
||||
$(call install-library,$(BLDIR)/tests/)
|
||||
endif
|
||||
|
||||
ifeq ($(CAPSTONE_SHARED),yes)
|
||||
$(LIBRARY): $(LIBOBJ)
|
||||
ifeq ($(V),0)
|
||||
$(call log,LINK,$(@:$(BLDIR)/%=%))
|
||||
@$(create-library)
|
||||
else
|
||||
$(create-library)
|
||||
endif
|
||||
endif
|
||||
|
||||
$(LIBOBJ): config.mk
|
||||
|
||||
$(LIBOBJ_ARM): $(DEP_ARM)
|
||||
$(LIBOBJ_ARM64): $(DEP_ARM64)
|
||||
$(LIBOBJ_M68K): $(DEP_M68K)
|
||||
$(LIBOBJ_MIPS): $(DEP_MIPS)
|
||||
$(LIBOBJ_PPC): $(DEP_PPC)
|
||||
$(LIBOBJ_SH): $(DEP_SH)
|
||||
$(LIBOBJ_SPARC): $(DEP_SPARC)
|
||||
$(LIBOBJ_SYSZ): $(DEP_SYSZ)
|
||||
$(LIBOBJ_X86): $(DEP_X86)
|
||||
$(LIBOBJ_XCORE): $(DEP_XCORE)
|
||||
$(LIBOBJ_TMS320C64X): $(DEP_TMS320C64X)
|
||||
$(LIBOBJ_M680X): $(DEP_M680X)
|
||||
$(LIBOBJ_EVM): $(DEP_EVM)
|
||||
$(LIBOBJ_RISCV): $(DEP_RISCV)
|
||||
$(LIBOBJ_WASM): $(DEP_WASM)
|
||||
$(LIBOBJ_MOS65XX): $(DEP_MOS65XX)
|
||||
$(LIBOBJ_BPF): $(DEP_BPF)
|
||||
$(LIBOBJ_TRICORE): $(DEP_TRICORE)
|
||||
|
||||
ifeq ($(CAPSTONE_STATIC),yes)
|
||||
$(ARCHIVE): $(LIBOBJ)
|
||||
@rm -f $(ARCHIVE)
|
||||
ifeq ($(V),0)
|
||||
$(call log,AR,$(@:$(BLDIR)/%=%))
|
||||
@$(create-archive)
|
||||
else
|
||||
$(create-archive)
|
||||
endif
|
||||
endif
|
||||
|
||||
$(PKGCFGF):
|
||||
ifeq ($(V),0)
|
||||
$(call log,GEN,$(@:$(BLDIR)/%=%))
|
||||
@$(generate-pkgcfg)
|
||||
else
|
||||
$(generate-pkgcfg)
|
||||
endif
|
||||
|
||||
# create a list of auto dependencies
|
||||
AUTODEPS:= $(patsubst %.o,%.d, $(LIBOBJ))
|
||||
|
||||
# include by auto dependencies
|
||||
-include $(AUTODEPS)
|
||||
|
||||
install: $(PKGCFGF) $(ARCHIVE) $(LIBRARY)
|
||||
mkdir -p $(LIBDIR)
|
||||
$(call install-library,$(LIBDIR))
|
||||
ifeq ($(CAPSTONE_STATIC),yes)
|
||||
$(INSTALL_DATA) $(ARCHIVE) $(LIBDIR)
|
||||
endif
|
||||
mkdir -p $(DESTDIR)$(INCDIR)/$(LIBNAME)
|
||||
$(INSTALL_DATA) include/capstone/*.h $(DESTDIR)$(INCDIR)/$(LIBNAME)
|
||||
mkdir -p $(PKGCFGDIR)
|
||||
$(INSTALL_DATA) $(PKGCFGF) $(PKGCFGDIR)
|
||||
ifeq (,$(findstring yes,$(CAPSTONE_BUILD_CORE_ONLY)))
|
||||
mkdir -p $(BINDIR)
|
||||
$(INSTALL_LIB) cstool/cstool $(BINDIR)
|
||||
endif
|
||||
|
||||
uninstall:
|
||||
rm -rf $(DESTDIR)$(INCDIR)/$(LIBNAME)
|
||||
rm -f $(LIBDIR)/lib$(LIBNAME).*
|
||||
rm -f $(PKGCFGDIR)/$(LIBNAME).pc
|
||||
ifeq (,$(findstring yes,$(CAPSTONE_BUILD_CORE_ONLY)))
|
||||
rm -f $(BINDIR)/cstool
|
||||
endif
|
||||
|
||||
clean:
|
||||
rm -f $(LIBOBJ)
|
||||
rm -f $(BLDIR)/lib$(LIBNAME).* $(BLDIR)/$(LIBNAME).pc
|
||||
rm -f $(PKGCFGF)
|
||||
rm -f $(AUTODEPS)
|
||||
[ "${ANDROID}" = "1" ] && rm -rf android-ndk-* || true
|
||||
|
||||
ifeq (,$(findstring yes,$(CAPSTONE_BUILD_CORE_ONLY)))
|
||||
$(MAKE) -C cstool clean
|
||||
$(MAKE) -C tests clean
|
||||
$(MAKE) -C suite/fuzz clean
|
||||
rm -f $(BLDIR)/tests/lib$(LIBNAME).$(EXT)
|
||||
endif
|
||||
|
||||
ifdef BUILDDIR
|
||||
rm -rf $(BUILDDIR)
|
||||
endif
|
||||
|
||||
ifeq (,$(findstring yes,$(CAPSTONE_BUILD_CORE_ONLY)))
|
||||
$(MAKE) -C bindings/python clean
|
||||
$(MAKE) -C bindings/java clean
|
||||
$(MAKE) -C bindings/ocaml clean
|
||||
endif
|
||||
|
||||
|
||||
TAG ?= HEAD
|
||||
ifeq ($(TAG), HEAD)
|
||||
DIST_VERSION = latest
|
||||
else
|
||||
DIST_VERSION = $(TAG)
|
||||
endif
|
||||
|
||||
dist:
|
||||
git archive --format=tar.gz --prefix=capstone-$(DIST_VERSION)/ $(TAG) > capstone-$(DIST_VERSION).tgz
|
||||
git archive --format=zip --prefix=capstone-$(DIST_VERSION)/ $(TAG) > capstone-$(DIST_VERSION).zip
|
||||
|
||||
TESTS = test_basic test_detail test_arm test_arm64 test_m68k test_mips test_ppc test_sparc test_tricore
|
||||
TESTS += test_systemz test_x86 test_xcore test_iter test_evm test_riscv test_mos65xx test_wasm test_bpf
|
||||
TESTS += test_basic.static test_detail.static test_arm.static test_arm64.static
|
||||
TESTS += test_m68k.static test_mips.static test_ppc.static test_sparc.static
|
||||
TESTS += test_systemz.static test_x86.static test_xcore.static test_m680x.static
|
||||
TESTS += test_skipdata test_skipdata.static test_iter.static test_evm.static test_riscv.static
|
||||
TESTS += test_mos65xx.static test_wasm.static test_bpf.static
|
||||
|
||||
check: $(TESTS)
|
||||
|
||||
checkfuzz: fuzztest fuzzallcorp
|
||||
|
||||
test_%:
|
||||
./tests/$@ > /dev/null && echo OK || echo FAILED
|
||||
|
||||
FUZZ_INPUTS = $(shell find suite/MC -type f -name '*.cs')
|
||||
|
||||
buildfuzz:
|
||||
ifndef BUILDDIR
|
||||
$(MAKE) -C suite/fuzz
|
||||
else
|
||||
$(MAKE) -C suite/fuzz BUILDDIR=$(BLDIR)
|
||||
endif
|
||||
|
||||
fuzztest:
|
||||
./suite/fuzz/fuzz_disasm $(FUZZ_INPUTS)
|
||||
|
||||
fuzzallcorp:
|
||||
ifneq ($(wildcard suite/fuzz/corpus-libFuzzer-capstone_fuzz_disasmnext-latest),)
|
||||
./suite/fuzz/fuzz_bindisasm suite/fuzz/corpus-libFuzzer-capstone_fuzz_disasmnext-latest/ > fuzz_bindisasm.log || (tail -1 fuzz_bindisasm.log; false)
|
||||
else
|
||||
@echo "Skipping tests on whole corpus"
|
||||
endif
|
||||
|
||||
$(OBJDIR)/%.o: %.c
|
||||
@mkdir -p $(@D)
|
||||
ifeq ($(V),0)
|
||||
$(call log,CC,$(@:$(OBJDIR)/%=%))
|
||||
@$(compile)
|
||||
else
|
||||
$(compile)
|
||||
endif
|
||||
|
||||
|
||||
ifeq ($(CAPSTONE_SHARED),yes)
|
||||
define install-library
|
||||
$(INSTALL_LIB) $(LIBRARY) $1
|
||||
$(if $(VERSION_EXT),
|
||||
cd $1 && \
|
||||
rm -f lib$(LIBNAME).$(EXT) && \
|
||||
ln -s lib$(LIBNAME).$(VERSION_EXT) lib$(LIBNAME).$(EXT))
|
||||
endef
|
||||
else
|
||||
define install-library
|
||||
endef
|
||||
endif
|
||||
|
||||
ifeq ($(AR_FLAGS),)
|
||||
AR_FLAGS := q
|
||||
endif
|
||||
|
||||
define create-archive
|
||||
$(AR) $(AR_FLAGS) $(ARCHIVE) $(LIBOBJ)
|
||||
$(RANLIB) $(ARCHIVE)
|
||||
endef
|
||||
|
||||
|
||||
define create-library
|
||||
$(CC) $(LDFLAGS) $($(LIBNAME)_LDFLAGS) $(LIBOBJ) -o $(LIBRARY)
|
||||
endef
|
||||
|
||||
|
||||
define generate-pkgcfg
|
||||
mkdir -p $(BLDIR)
|
||||
echo 'Name: capstone' > $(PKGCFGF)
|
||||
echo 'Description: Capstone disassembly engine' >> $(PKGCFGF)
|
||||
echo 'Version: $(PKG_VERSION)' >> $(PKGCFGF)
|
||||
echo 'libdir=$(LIBDIR)' >> $(PKGCFGF)
|
||||
echo 'includedir=$(INCDIR)/capstone' >> $(PKGCFGF)
|
||||
echo 'archive=$${libdir}/libcapstone.a' >> $(PKGCFGF)
|
||||
echo 'Libs: -L$${libdir} -lcapstone' >> $(PKGCFGF)
|
||||
echo 'Cflags: -I$${includedir}' >> $(PKGCFGF)
|
||||
echo 'archs=${CAPSTONE_ARCHS}' >> $(PKGCFGF)
|
||||
endef
|
||||
@@ -0,0 +1,254 @@
|
||||
/* Capstone Disassembly Engine */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
|
||||
/* Rot127 <unisono@quyllur.org>, 2022-2023 */
|
||||
|
||||
#include "Mapping.h"
|
||||
|
||||
// create a cache for fast id lookup
|
||||
static unsigned short *make_id2insn(const insn_map *insns, unsigned int size)
|
||||
{
|
||||
// NOTE: assume that the max id is always put at the end of insns array
|
||||
unsigned short max_id = insns[size - 1].id;
|
||||
unsigned short i;
|
||||
|
||||
unsigned short *cache =
|
||||
(unsigned short *)cs_mem_calloc(max_id + 1, sizeof(*cache));
|
||||
|
||||
for (i = 1; i < size; i++)
|
||||
cache[insns[i].id] = i;
|
||||
|
||||
return cache;
|
||||
}
|
||||
|
||||
// look for @id in @insns, given its size in @max. first time call will update
|
||||
// @cache. return 0 if not found
|
||||
unsigned short insn_find(const insn_map *insns, unsigned int max,
|
||||
unsigned int id, unsigned short **cache)
|
||||
{
|
||||
if (id > insns[max - 1].id)
|
||||
return 0;
|
||||
|
||||
if (*cache == NULL)
|
||||
*cache = make_id2insn(insns, max);
|
||||
|
||||
return (*cache)[id];
|
||||
}
|
||||
|
||||
// Gives the id for the given @name if it is saved in @map.
|
||||
// Returns the id or -1 if not found.
|
||||
int name2id(const name_map *map, int max, const char *name)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < max; i++) {
|
||||
if (!strcmp(map[i].name, name)) {
|
||||
return map[i].id;
|
||||
}
|
||||
}
|
||||
|
||||
// nothing match
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Gives the name for the given @id if it is saved in @map.
|
||||
// Returns the name or NULL if not found.
|
||||
const char *id2name(const name_map *map, int max, const unsigned int id)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < max; i++) {
|
||||
if (map[i].id == id) {
|
||||
return map[i].name;
|
||||
}
|
||||
}
|
||||
|
||||
// nothing match
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/// Adds a register to the implicit write register list.
|
||||
/// It will not add the same register twice.
|
||||
void map_add_implicit_write(MCInst *MI, uint32_t Reg)
|
||||
{
|
||||
if (!MI->flat_insn->detail)
|
||||
return;
|
||||
|
||||
uint16_t *regs_write = MI->flat_insn->detail->regs_write;
|
||||
for (int i = 0; i < MAX_IMPL_W_REGS; ++i) {
|
||||
if (i == MI->flat_insn->detail->regs_write_count) {
|
||||
regs_write[i] = Reg;
|
||||
MI->flat_insn->detail->regs_write_count++;
|
||||
return;
|
||||
}
|
||||
if (regs_write[i] == Reg)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/// Copies the implicit read registers of @imap to @MI->flat_insn.
|
||||
/// Already present registers will be preserved.
|
||||
void map_implicit_reads(MCInst *MI, const insn_map *imap)
|
||||
{
|
||||
#ifndef CAPSTONE_DIET
|
||||
if (!MI->flat_insn->detail)
|
||||
return;
|
||||
|
||||
cs_detail *detail = MI->flat_insn->detail;
|
||||
unsigned Opcode = MCInst_getOpcode(MI);
|
||||
unsigned i = 0;
|
||||
uint16_t reg = imap[Opcode].regs_use[i];
|
||||
while (reg != 0) {
|
||||
if (i >= MAX_IMPL_R_REGS ||
|
||||
detail->regs_read_count >= MAX_IMPL_R_REGS) {
|
||||
printf("ERROR: Too many implicit read register defined in "
|
||||
"instruction mapping.\n");
|
||||
return;
|
||||
}
|
||||
detail->regs_read[detail->regs_read_count++] = reg;
|
||||
reg = imap[Opcode].regs_use[++i];
|
||||
}
|
||||
#endif // CAPSTONE_DIET
|
||||
}
|
||||
|
||||
/// Copies the implicit write registers of @imap to @MI->flat_insn.
|
||||
/// Already present registers will be preserved.
|
||||
void map_implicit_writes(MCInst *MI, const insn_map *imap)
|
||||
{
|
||||
#ifndef CAPSTONE_DIET
|
||||
if (!MI->flat_insn->detail)
|
||||
return;
|
||||
|
||||
cs_detail *detail = MI->flat_insn->detail;
|
||||
unsigned Opcode = MCInst_getOpcode(MI);
|
||||
unsigned i = 0;
|
||||
uint16_t reg = imap[Opcode].regs_mod[i];
|
||||
while (reg != 0) {
|
||||
if (i >= MAX_IMPL_W_REGS ||
|
||||
detail->regs_write_count >= MAX_IMPL_W_REGS) {
|
||||
printf("ERROR: Too many implicit write register defined in "
|
||||
"instruction mapping.\n");
|
||||
return;
|
||||
}
|
||||
detail->regs_write[detail->regs_write_count++] = reg;
|
||||
reg = imap[Opcode].regs_mod[++i];
|
||||
}
|
||||
#endif // CAPSTONE_DIET
|
||||
}
|
||||
|
||||
/// Copies the groups from @imap to @MI->flat_insn.
|
||||
/// Already present groups will be preserved.
|
||||
void map_groups(MCInst *MI, const insn_map *imap)
|
||||
{
|
||||
#ifndef CAPSTONE_DIET
|
||||
if (!MI->flat_insn->detail)
|
||||
return;
|
||||
|
||||
cs_detail *detail = MI->flat_insn->detail;
|
||||
unsigned Opcode = MCInst_getOpcode(MI);
|
||||
unsigned i = 0;
|
||||
uint16_t group = imap[Opcode].groups[i];
|
||||
while (group != 0) {
|
||||
if (detail->groups_count >= MAX_NUM_GROUPS) {
|
||||
printf("ERROR: Too many groups defined in instruction mapping.\n");
|
||||
return;
|
||||
}
|
||||
detail->groups[detail->groups_count++] = group;
|
||||
group = imap[Opcode].groups[++i];
|
||||
}
|
||||
#endif // CAPSTONE_DIET
|
||||
}
|
||||
|
||||
// Search for the CS instruction id for the given @MC_Opcode in @imap.
|
||||
// return -1 if none is found.
|
||||
unsigned int find_cs_id(unsigned MC_Opcode, const insn_map *imap,
|
||||
unsigned imap_size)
|
||||
{
|
||||
// binary searching since the IDs are sorted in order
|
||||
unsigned int left, right, m;
|
||||
unsigned int max = imap_size;
|
||||
|
||||
right = max - 1;
|
||||
|
||||
if (MC_Opcode < imap[0].id || MC_Opcode > imap[right].id)
|
||||
// not found
|
||||
return -1;
|
||||
|
||||
left = 0;
|
||||
|
||||
while (left <= right) {
|
||||
m = (left + right) / 2;
|
||||
if (MC_Opcode == imap[m].id) {
|
||||
return m;
|
||||
}
|
||||
|
||||
if (MC_Opcode < imap[m].id)
|
||||
right = m - 1;
|
||||
else
|
||||
left = m + 1;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/// Sets the Capstone instruction id which maps to the @MI opcode.
|
||||
/// If no mapping is found the function returns and prints an error.
|
||||
void map_cs_id(MCInst *MI, const insn_map *imap, unsigned int imap_size)
|
||||
{
|
||||
unsigned int i = find_cs_id(MCInst_getOpcode(MI), imap, imap_size);
|
||||
if (i != -1) {
|
||||
MI->flat_insn->id = imap[i].mapid;
|
||||
return;
|
||||
}
|
||||
printf("ERROR: Could not find CS id for MCInst opcode: %d\n",
|
||||
MCInst_getOpcode(MI));
|
||||
return;
|
||||
}
|
||||
|
||||
/// Returns the operand type information from the
|
||||
/// mapping table for instruction operands.
|
||||
/// Only usable by `auto-sync` archs!
|
||||
const cs_op_type mapping_get_op_type(MCInst *MI, unsigned OpNum,
|
||||
const map_insn_ops *insn_ops_map,
|
||||
size_t map_size)
|
||||
{
|
||||
assert(MI);
|
||||
assert(MI->Opcode < map_size);
|
||||
assert(OpNum < sizeof(insn_ops_map[MI->Opcode].ops) /
|
||||
sizeof(insn_ops_map[MI->Opcode].ops[0]));
|
||||
|
||||
return insn_ops_map[MI->Opcode].ops[OpNum].type;
|
||||
}
|
||||
|
||||
/// Returns the operand access flags from the
|
||||
/// mapping table for instruction operands.
|
||||
/// Only usable by `auto-sync` archs!
|
||||
const cs_ac_type mapping_get_op_access(MCInst *MI, unsigned OpNum,
|
||||
const map_insn_ops *insn_ops_map,
|
||||
size_t map_size)
|
||||
{
|
||||
assert(MI);
|
||||
assert(MI->Opcode < map_size);
|
||||
assert(OpNum < sizeof(insn_ops_map[MI->Opcode].ops) /
|
||||
sizeof(insn_ops_map[MI->Opcode].ops[0]));
|
||||
|
||||
cs_ac_type access = insn_ops_map[MI->Opcode].ops[OpNum].access;
|
||||
if (MCInst_opIsTied(MI, OpNum) || MCInst_opIsTying(MI, OpNum))
|
||||
access |= (access == CS_AC_READ) ? CS_AC_WRITE : CS_AC_READ;
|
||||
return access;
|
||||
}
|
||||
|
||||
/// Returns the operand at detail->arch.operands[op_count + offset]
|
||||
/// Or NULL if detail is not set.
|
||||
#define DEFINE_get_detail_op(arch, ARCH) \
|
||||
cs_##arch##_op *ARCH##_get_detail_op(MCInst *MI, int offset) \
|
||||
{ \
|
||||
if (!MI->flat_insn->detail) \
|
||||
return NULL; \
|
||||
int OpIdx = MI->flat_insn->detail->arch.op_count + offset; \
|
||||
assert(OpIdx >= 0 && OpIdx < MAX_MC_OPS); \
|
||||
return &MI->flat_insn->detail->arch.operands[OpIdx]; \
|
||||
}
|
||||
|
||||
DEFINE_get_detail_op(arm, ARM);
|
||||
DEFINE_get_detail_op(ppc, PPC);
|
||||
DEFINE_get_detail_op(tricore, TriCore);
|
||||
@@ -0,0 +1,174 @@
|
||||
/* Capstone Disassembly Engine */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
|
||||
/* Rot127 <unisono@quyllur.org>, 2022-2023 */
|
||||
|
||||
#ifndef CS_MAPPING_H
|
||||
#define CS_MAPPING_H
|
||||
|
||||
#if defined(CAPSTONE_HAS_OSXKERNEL)
|
||||
#include <libkern/libkern.h>
|
||||
#else
|
||||
#include "include/capstone/capstone.h"
|
||||
#include <stddef.h>
|
||||
#endif
|
||||
#include "cs_priv.h"
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
// map instruction to its characteristics
|
||||
typedef struct insn_map {
|
||||
unsigned short id; // The LLVM instruction id
|
||||
unsigned short mapid; // The Capstone instruction id
|
||||
#ifndef CAPSTONE_DIET
|
||||
uint16_t regs_use[MAX_IMPL_R_REGS]; ///< list of implicit registers used by
|
||||
///< this instruction
|
||||
uint16_t regs_mod[MAX_IMPL_W_REGS]; ///< list of implicit registers modified
|
||||
///< by this instruction
|
||||
unsigned char groups
|
||||
[MAX_NUM_GROUPS]; ///< list of group this instruction belong to
|
||||
bool branch; // branch instruction?
|
||||
bool indirect_branch; // indirect branch instruction?
|
||||
#endif
|
||||
} insn_map;
|
||||
|
||||
// look for @id in @m, given its size in @max. first time call will update
|
||||
// @cache. return 0 if not found
|
||||
unsigned short insn_find(const insn_map *m, unsigned int max, unsigned int id,
|
||||
unsigned short **cache);
|
||||
|
||||
unsigned int find_cs_id(unsigned MC_Opcode, const insn_map *imap,
|
||||
unsigned imap_size);
|
||||
|
||||
#define MAX_NO_DATA_TYPES 10
|
||||
|
||||
///< A LLVM<->CS Mapping entry of an MCOperand.
|
||||
typedef struct {
|
||||
uint8_t /* cs_op_type */ type; ///< Operand type (e.g.: reg, imm, mem)
|
||||
uint8_t /* cs_ac_type */ access; ///< The access type (read, write)
|
||||
uint8_t /* cs_data_type */
|
||||
dtypes[MAX_NO_DATA_TYPES]; ///< List of op types. Terminated by
|
||||
///< CS_DATA_TYPE_LAST
|
||||
} mapping_op;
|
||||
|
||||
#define MAX_NO_INSN_MAP_OPS 16
|
||||
|
||||
///< MCOperands of an instruction.
|
||||
typedef struct {
|
||||
mapping_op
|
||||
ops[MAX_NO_INSN_MAP_OPS]; ///< NULL terminated array of insn_op.
|
||||
} map_insn_ops;
|
||||
|
||||
/// Only usable by `auto-sync` archs!
|
||||
const cs_op_type mapping_get_op_type(MCInst *MI, unsigned OpNum,
|
||||
const map_insn_ops *insn_ops_map,
|
||||
size_t map_size);
|
||||
|
||||
/// Only usable by `auto-sync` archs!
|
||||
const cs_ac_type mapping_get_op_access(MCInst *MI, unsigned OpNum,
|
||||
const map_insn_ops *insn_ops_map,
|
||||
size_t map_size);
|
||||
|
||||
/// Macro for easier access of operand types from the map.
|
||||
/// Assumes the istruction operands map is called "insn_operands"
|
||||
/// Only usable by `auto-sync` archs!
|
||||
#define map_get_op_type(MI, OpNum) \
|
||||
mapping_get_op_type(MI, OpNum, (const map_insn_ops *)insn_operands, \
|
||||
sizeof(insn_operands) / sizeof(insn_operands[0]))
|
||||
|
||||
/// Macro for easier access of operand access flags from the map.
|
||||
/// Assumes the istruction operands map is called "insn_operands"
|
||||
/// Only usable by `auto-sync` archs!
|
||||
#define map_get_op_access(MI, OpNum) \
|
||||
mapping_get_op_access(MI, OpNum, (const map_insn_ops *)insn_operands, \
|
||||
sizeof(insn_operands) / \
|
||||
sizeof(insn_operands[0]))
|
||||
|
||||
///< Map for ids to their string
|
||||
typedef struct name_map {
|
||||
unsigned int id;
|
||||
const char *name;
|
||||
} name_map;
|
||||
|
||||
// map a name to its ID
|
||||
// return 0 if not found
|
||||
int name2id(const name_map *map, int max, const char *name);
|
||||
|
||||
// map ID to a name
|
||||
// return NULL if not found
|
||||
const char *id2name(const name_map *map, int max, const unsigned int id);
|
||||
|
||||
void map_add_implicit_write(MCInst *MI, uint32_t Reg);
|
||||
|
||||
void map_implicit_reads(MCInst *MI, const insn_map *imap);
|
||||
|
||||
void map_implicit_writes(MCInst *MI, const insn_map *imap);
|
||||
|
||||
void map_groups(MCInst *MI, const insn_map *imap);
|
||||
|
||||
void map_cs_id(MCInst *MI, const insn_map *imap, unsigned int imap_size);
|
||||
|
||||
#define DECL_get_detail_op(arch, ARCH) \
|
||||
cs_##arch##_op *ARCH##_get_detail_op(MCInst *MI, int offset);
|
||||
|
||||
DECL_get_detail_op(arm, ARM);
|
||||
DECL_get_detail_op(ppc, PPC);
|
||||
DECL_get_detail_op(tricore, TriCore);
|
||||
|
||||
/// Increments the detail->arch.op_count by one.
|
||||
#define DEFINE_inc_detail_op_count(arch, ARCH) \
|
||||
static inline void ARCH##_inc_op_count(MCInst *MI) \
|
||||
{ \
|
||||
MI->flat_insn->detail->arch.op_count++; \
|
||||
}
|
||||
|
||||
/// Decrements the detail->arch.op_count by one.
|
||||
#define DEFINE_dec_detail_op_count(arch, ARCH) \
|
||||
static inline void ARCH##_dec_op_count(MCInst *MI) \
|
||||
{ \
|
||||
MI->flat_insn->detail->arch.op_count--; \
|
||||
}
|
||||
|
||||
DEFINE_inc_detail_op_count(arm, ARM);
|
||||
DEFINE_dec_detail_op_count(arm, ARM);
|
||||
DEFINE_inc_detail_op_count(ppc, PPC);
|
||||
DEFINE_dec_detail_op_count(ppc, PPC);
|
||||
DEFINE_inc_detail_op_count(tricore, TriCore);
|
||||
DEFINE_dec_detail_op_count(tricore, TriCore);
|
||||
|
||||
/// Returns true if a memory operand is currently edited.
|
||||
static inline bool doing_mem(const MCInst *MI)
|
||||
{
|
||||
return MI->csh->doing_mem;
|
||||
}
|
||||
|
||||
/// Sets the doing_mem flag to @status.
|
||||
static inline void set_doing_mem(const MCInst *MI, bool status)
|
||||
{
|
||||
MI->csh->doing_mem = status;
|
||||
}
|
||||
|
||||
/// Returns detail->arch
|
||||
#define DEFINE_get_arch_detail(arch, ARCH) \
|
||||
static inline cs_##arch *ARCH##_get_detail(const MCInst *MI) \
|
||||
{ \
|
||||
assert(MI && MI->flat_insn && MI->flat_insn->detail); \
|
||||
return &MI->flat_insn->detail->arch; \
|
||||
}
|
||||
|
||||
DEFINE_get_arch_detail(arm, ARM);
|
||||
DEFINE_get_arch_detail(ppc, PPC);
|
||||
DEFINE_get_arch_detail(tricore, TriCore);
|
||||
|
||||
static inline bool detail_is_set(const MCInst *MI)
|
||||
{
|
||||
assert(MI && MI->flat_insn);
|
||||
return MI->flat_insn->detail != NULL;
|
||||
}
|
||||
|
||||
static inline cs_detail *get_detail(const MCInst *MI)
|
||||
{
|
||||
assert(MI && MI->flat_insn);
|
||||
return MI->flat_insn->detail;
|
||||
}
|
||||
|
||||
#endif // CS_MAPPING_H
|
||||
@@ -0,0 +1,442 @@
|
||||
//===-- llvm/Support/MathExtras.h - Useful math functions -------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains some functions that are useful for math stuff.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/* Capstone Disassembly Engine */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
|
||||
|
||||
#ifndef CS_LLVM_SUPPORT_MATHEXTRAS_H
|
||||
#define CS_LLVM_SUPPORT_MATHEXTRAS_H
|
||||
|
||||
#if defined(_WIN32_WCE) && (_WIN32_WCE < 0x800)
|
||||
#include "windowsce/intrin.h"
|
||||
#elif defined(_MSC_VER)
|
||||
#include <intrin.h>
|
||||
#endif
|
||||
|
||||
#ifndef __cplusplus
|
||||
#if defined (WIN32) || defined (WIN64) || defined (_WIN32) || defined (_WIN64)
|
||||
#define inline /* inline */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// NOTE: The following support functions use the _32/_64 extensions instead of
|
||||
// type overloading so that signed and unsigned integers can be used without
|
||||
// ambiguity.
|
||||
|
||||
/// Hi_32 - This function returns the high 32 bits of a 64 bit value.
|
||||
static inline uint32_t Hi_32(uint64_t Value) {
|
||||
return (uint32_t)(Value >> 32);
|
||||
}
|
||||
|
||||
/// Lo_32 - This function returns the low 32 bits of a 64 bit value.
|
||||
static inline uint32_t Lo_32(uint64_t Value) {
|
||||
return (uint32_t)(Value);
|
||||
}
|
||||
|
||||
/// isUIntN - Checks if an unsigned integer fits into the given (dynamic)
|
||||
/// bit width.
|
||||
static inline bool isUIntN(unsigned N, uint64_t x) {
|
||||
return x == (x & (~0ULL >> (64 - N)));
|
||||
}
|
||||
|
||||
/// isIntN - Checks if an signed integer fits into the given (dynamic)
|
||||
/// bit width.
|
||||
//static inline bool isIntN(unsigned N, int64_t x) {
|
||||
// return N >= 64 || (-(INT64_C(1)<<(N-1)) <= x && x < (INT64_C(1)<<(N-1)));
|
||||
//}
|
||||
|
||||
/// isMask_32 - This function returns true if the argument is a sequence of ones
|
||||
/// starting at the least significant bit with the remainder zero (32 bit
|
||||
/// version). Ex. isMask_32(0x0000FFFFU) == true.
|
||||
static inline bool isMask_32(uint32_t Value) {
|
||||
return Value && ((Value + 1) & Value) == 0;
|
||||
}
|
||||
|
||||
/// isMask_64 - This function returns true if the argument is a sequence of ones
|
||||
/// starting at the least significant bit with the remainder zero (64 bit
|
||||
/// version).
|
||||
static inline bool isMask_64(uint64_t Value) {
|
||||
return Value && ((Value + 1) & Value) == 0;
|
||||
}
|
||||
|
||||
/// isShiftedMask_32 - This function returns true if the argument contains a
|
||||
/// sequence of ones with the remainder zero (32 bit version.)
|
||||
/// Ex. isShiftedMask_32(0x0000FF00U) == true.
|
||||
static inline bool isShiftedMask_32(uint32_t Value) {
|
||||
return isMask_32((Value - 1) | Value);
|
||||
}
|
||||
|
||||
/// isShiftedMask_64 - This function returns true if the argument contains a
|
||||
/// sequence of ones with the remainder zero (64 bit version.)
|
||||
static inline bool isShiftedMask_64(uint64_t Value) {
|
||||
return isMask_64((Value - 1) | Value);
|
||||
}
|
||||
|
||||
/// isPowerOf2_32 - This function returns true if the argument is a power of
|
||||
/// two > 0. Ex. isPowerOf2_32(0x00100000U) == true (32 bit edition.)
|
||||
static inline bool isPowerOf2_32(uint32_t Value) {
|
||||
return Value && !(Value & (Value - 1));
|
||||
}
|
||||
|
||||
/// CountLeadingZeros_32 - this function performs the platform optimal form of
|
||||
/// counting the number of zeros from the most significant bit to the first one
|
||||
/// bit. Ex. CountLeadingZeros_32(0x00F000FF) == 8.
|
||||
/// Returns 32 if the word is zero.
|
||||
static inline unsigned CountLeadingZeros_32(uint32_t Value) {
|
||||
unsigned Count; // result
|
||||
#if __GNUC__ >= 4
|
||||
// PowerPC is defined for __builtin_clz(0)
|
||||
#if !defined(__ppc__) && !defined(__ppc64__)
|
||||
if (!Value) return 32;
|
||||
#endif
|
||||
Count = __builtin_clz(Value);
|
||||
#else
|
||||
unsigned Shift;
|
||||
if (!Value) return 32;
|
||||
Count = 0;
|
||||
// bisection method for count leading zeros
|
||||
for (Shift = 32 >> 1; Shift; Shift >>= 1) {
|
||||
uint32_t Tmp = Value >> Shift;
|
||||
if (Tmp) {
|
||||
Value = Tmp;
|
||||
} else {
|
||||
Count |= Shift;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return Count;
|
||||
}
|
||||
|
||||
/// CountLeadingOnes_32 - this function performs the operation of
|
||||
/// counting the number of ones from the most significant bit to the first zero
|
||||
/// bit. Ex. CountLeadingOnes_32(0xFF0FFF00) == 8.
|
||||
/// Returns 32 if the word is all ones.
|
||||
static inline unsigned CountLeadingOnes_32(uint32_t Value) {
|
||||
return CountLeadingZeros_32(~Value);
|
||||
}
|
||||
|
||||
/// CountLeadingZeros_64 - This function performs the platform optimal form
|
||||
/// of counting the number of zeros from the most significant bit to the first
|
||||
/// one bit (64 bit edition.)
|
||||
/// Returns 64 if the word is zero.
|
||||
static inline unsigned CountLeadingZeros_64(uint64_t Value) {
|
||||
unsigned Count; // result
|
||||
#if __GNUC__ >= 4
|
||||
// PowerPC is defined for __builtin_clzll(0)
|
||||
#if !defined(__ppc__) && !defined(__ppc64__)
|
||||
if (!Value) return 64;
|
||||
#endif
|
||||
Count = __builtin_clzll(Value);
|
||||
#else
|
||||
#ifndef _MSC_VER
|
||||
unsigned Shift;
|
||||
if (sizeof(long) == sizeof(int64_t))
|
||||
{
|
||||
if (!Value) return 64;
|
||||
Count = 0;
|
||||
// bisection method for count leading zeros
|
||||
for (Shift = 64 >> 1; Shift; Shift >>= 1) {
|
||||
uint64_t Tmp = Value >> Shift;
|
||||
if (Tmp) {
|
||||
Value = Tmp;
|
||||
} else {
|
||||
Count |= Shift;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
// get hi portion
|
||||
uint32_t Hi = Hi_32(Value);
|
||||
|
||||
// if some bits in hi portion
|
||||
if (Hi) {
|
||||
// leading zeros in hi portion plus all bits in lo portion
|
||||
Count = CountLeadingZeros_32(Hi);
|
||||
} else {
|
||||
// get lo portion
|
||||
uint32_t Lo = Lo_32(Value);
|
||||
// same as 32 bit value
|
||||
Count = CountLeadingZeros_32(Lo)+32;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return Count;
|
||||
}
|
||||
|
||||
/// CountLeadingOnes_64 - This function performs the operation
|
||||
/// of counting the number of ones from the most significant bit to the first
|
||||
/// zero bit (64 bit edition.)
|
||||
/// Returns 64 if the word is all ones.
|
||||
static inline unsigned CountLeadingOnes_64(uint64_t Value) {
|
||||
return CountLeadingZeros_64(~Value);
|
||||
}
|
||||
|
||||
/// CountTrailingZeros_32 - this function performs the platform optimal form of
|
||||
/// counting the number of zeros from the least significant bit to the first one
|
||||
/// bit. Ex. CountTrailingZeros_32(0xFF00FF00) == 8.
|
||||
/// Returns 32 if the word is zero.
|
||||
static inline unsigned CountTrailingZeros_32(uint32_t Value) {
|
||||
#if __GNUC__ >= 4
|
||||
return Value ? __builtin_ctz(Value) : 32;
|
||||
#else
|
||||
static const unsigned Mod37BitPosition[] = {
|
||||
32, 0, 1, 26, 2, 23, 27, 0, 3, 16, 24, 30, 28, 11, 0, 13,
|
||||
4, 7, 17, 0, 25, 22, 31, 15, 29, 10, 12, 6, 0, 21, 14, 9,
|
||||
5, 20, 8, 19, 18
|
||||
};
|
||||
// Replace "-Value" by "1+~Value" in the following commented code to avoid
|
||||
// MSVC warning C4146
|
||||
// return Mod37BitPosition[(-Value & Value) % 37];
|
||||
return Mod37BitPosition[((1 + ~Value) & Value) % 37];
|
||||
#endif
|
||||
}
|
||||
|
||||
/// CountTrailingOnes_32 - this function performs the operation of
|
||||
/// counting the number of ones from the least significant bit to the first zero
|
||||
/// bit. Ex. CountTrailingOnes_32(0x00FF00FF) == 8.
|
||||
/// Returns 32 if the word is all ones.
|
||||
static inline unsigned CountTrailingOnes_32(uint32_t Value) {
|
||||
return CountTrailingZeros_32(~Value);
|
||||
}
|
||||
|
||||
/// CountTrailingZeros_64 - This function performs the platform optimal form
|
||||
/// of counting the number of zeros from the least significant bit to the first
|
||||
/// one bit (64 bit edition.)
|
||||
/// Returns 64 if the word is zero.
|
||||
static inline unsigned CountTrailingZeros_64(uint64_t Value) {
|
||||
#if __GNUC__ >= 4
|
||||
return Value ? __builtin_ctzll(Value) : 64;
|
||||
#else
|
||||
static const unsigned Mod67Position[] = {
|
||||
64, 0, 1, 39, 2, 15, 40, 23, 3, 12, 16, 59, 41, 19, 24, 54,
|
||||
4, 64, 13, 10, 17, 62, 60, 28, 42, 30, 20, 51, 25, 44, 55,
|
||||
47, 5, 32, 65, 38, 14, 22, 11, 58, 18, 53, 63, 9, 61, 27,
|
||||
29, 50, 43, 46, 31, 37, 21, 57, 52, 8, 26, 49, 45, 36, 56,
|
||||
7, 48, 35, 6, 34, 33, 0
|
||||
};
|
||||
// Replace "-Value" by "1+~Value" in the following commented code to avoid
|
||||
// MSVC warning C4146
|
||||
// return Mod67Position[(-Value & Value) % 67];
|
||||
return Mod67Position[((1 + ~Value) & Value) % 67];
|
||||
#endif
|
||||
}
|
||||
|
||||
/// CountTrailingOnes_64 - This function performs the operation
|
||||
/// of counting the number of ones from the least significant bit to the first
|
||||
/// zero bit (64 bit edition.)
|
||||
/// Returns 64 if the word is all ones.
|
||||
static inline unsigned CountTrailingOnes_64(uint64_t Value) {
|
||||
return CountTrailingZeros_64(~Value);
|
||||
}
|
||||
|
||||
/// CountPopulation_32 - this function counts the number of set bits in a value.
|
||||
/// Ex. CountPopulation(0xF000F000) = 8
|
||||
/// Returns 0 if the word is zero.
|
||||
static inline unsigned CountPopulation_32(uint32_t Value) {
|
||||
#if __GNUC__ >= 4
|
||||
return __builtin_popcount(Value);
|
||||
#else
|
||||
uint32_t v = Value - ((Value >> 1) & 0x55555555);
|
||||
v = (v & 0x33333333) + ((v >> 2) & 0x33333333);
|
||||
return (((v + (v >> 4)) & 0xF0F0F0F) * 0x1010101) >> 24;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// CountPopulation_64 - this function counts the number of set bits in a value,
|
||||
/// (64 bit edition.)
|
||||
static inline unsigned CountPopulation_64(uint64_t Value) {
|
||||
#if __GNUC__ >= 4
|
||||
return __builtin_popcountll(Value);
|
||||
#else
|
||||
uint64_t v = Value - ((Value >> 1) & 0x5555555555555555ULL);
|
||||
v = (v & 0x3333333333333333ULL) + ((v >> 2) & 0x3333333333333333ULL);
|
||||
v = (v + (v >> 4)) & 0x0F0F0F0F0F0F0F0FULL;
|
||||
return (uint64_t)((v * 0x0101010101010101ULL) >> 56);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Log2_32 - This function returns the floor log base 2 of the specified value,
|
||||
/// -1 if the value is zero. (32 bit edition.)
|
||||
/// Ex. Log2_32(32) == 5, Log2_32(1) == 0, Log2_32(0) == -1, Log2_32(6) == 2
|
||||
static inline unsigned Log2_32(uint32_t Value) {
|
||||
return 31 - CountLeadingZeros_32(Value);
|
||||
}
|
||||
|
||||
/// Log2_64 - This function returns the floor log base 2 of the specified value,
|
||||
/// -1 if the value is zero. (64 bit edition.)
|
||||
static inline unsigned Log2_64(uint64_t Value) {
|
||||
return 63 - CountLeadingZeros_64(Value);
|
||||
}
|
||||
|
||||
/// Log2_32_Ceil - This function returns the ceil log base 2 of the specified
|
||||
/// value, 32 if the value is zero. (32 bit edition).
|
||||
/// Ex. Log2_32_Ceil(32) == 5, Log2_32_Ceil(1) == 0, Log2_32_Ceil(6) == 3
|
||||
static inline unsigned Log2_32_Ceil(uint32_t Value) {
|
||||
return 32-CountLeadingZeros_32(Value-1);
|
||||
}
|
||||
|
||||
/// Log2_64_Ceil - This function returns the ceil log base 2 of the specified
|
||||
/// value, 64 if the value is zero. (64 bit edition.)
|
||||
static inline unsigned Log2_64_Ceil(uint64_t Value) {
|
||||
return 64-CountLeadingZeros_64(Value-1);
|
||||
}
|
||||
|
||||
/// GreatestCommonDivisor64 - Return the greatest common divisor of the two
|
||||
/// values using Euclid's algorithm.
|
||||
static inline uint64_t GreatestCommonDivisor64(uint64_t A, uint64_t B) {
|
||||
while (B) {
|
||||
uint64_t T = B;
|
||||
B = A % B;
|
||||
A = T;
|
||||
}
|
||||
return A;
|
||||
}
|
||||
|
||||
/// BitsToDouble - This function takes a 64-bit integer and returns the bit
|
||||
/// equivalent double.
|
||||
static inline double BitsToDouble(uint64_t Bits) {
|
||||
union {
|
||||
uint64_t L;
|
||||
double D;
|
||||
} T;
|
||||
T.L = Bits;
|
||||
return T.D;
|
||||
}
|
||||
|
||||
/// BitsToFloat - This function takes a 32-bit integer and returns the bit
|
||||
/// equivalent float.
|
||||
static inline float BitsToFloat(uint32_t Bits) {
|
||||
union {
|
||||
uint32_t I;
|
||||
float F;
|
||||
} T;
|
||||
T.I = Bits;
|
||||
return T.F;
|
||||
}
|
||||
|
||||
/// DoubleToBits - This function takes a double and returns the bit
|
||||
/// equivalent 64-bit integer. Note that copying doubles around
|
||||
/// changes the bits of NaNs on some hosts, notably x86, so this
|
||||
/// routine cannot be used if these bits are needed.
|
||||
static inline uint64_t DoubleToBits(double Double) {
|
||||
union {
|
||||
uint64_t L;
|
||||
double D;
|
||||
} T;
|
||||
T.D = Double;
|
||||
return T.L;
|
||||
}
|
||||
|
||||
/// FloatToBits - This function takes a float and returns the bit
|
||||
/// equivalent 32-bit integer. Note that copying floats around
|
||||
/// changes the bits of NaNs on some hosts, notably x86, so this
|
||||
/// routine cannot be used if these bits are needed.
|
||||
static inline uint32_t FloatToBits(float Float) {
|
||||
union {
|
||||
uint32_t I;
|
||||
float F;
|
||||
} T;
|
||||
T.F = Float;
|
||||
return T.I;
|
||||
}
|
||||
|
||||
/// MinAlign - A and B are either alignments or offsets. Return the minimum
|
||||
/// alignment that may be assumed after adding the two together.
|
||||
static inline uint64_t MinAlign(uint64_t A, uint64_t B) {
|
||||
// The largest power of 2 that divides both A and B.
|
||||
//
|
||||
// Replace "-Value" by "1+~Value" in the following commented code to avoid
|
||||
// MSVC warning C4146
|
||||
// return (A | B) & -(A | B);
|
||||
return (A | B) & (1 + ~(A | B));
|
||||
}
|
||||
|
||||
/// NextPowerOf2 - Returns the next power of two (in 64-bits)
|
||||
/// that is strictly greater than A. Returns zero on overflow.
|
||||
static inline uint64_t NextPowerOf2(uint64_t A) {
|
||||
A |= (A >> 1);
|
||||
A |= (A >> 2);
|
||||
A |= (A >> 4);
|
||||
A |= (A >> 8);
|
||||
A |= (A >> 16);
|
||||
A |= (A >> 32);
|
||||
return A + 1;
|
||||
}
|
||||
|
||||
/// Returns the next integer (mod 2**64) that is greater than or equal to
|
||||
/// \p Value and is a multiple of \p Align. \p Align must be non-zero.
|
||||
///
|
||||
/// Examples:
|
||||
/// \code
|
||||
/// RoundUpToAlignment(5, 8) = 8
|
||||
/// RoundUpToAlignment(17, 8) = 24
|
||||
/// RoundUpToAlignment(~0LL, 8) = 0
|
||||
/// \endcode
|
||||
static inline uint64_t RoundUpToAlignment(uint64_t Value, uint64_t Align) {
|
||||
return ((Value + Align - 1) / Align) * Align;
|
||||
}
|
||||
|
||||
/// Returns the offset to the next integer (mod 2**64) that is greater than
|
||||
/// or equal to \p Value and is a multiple of \p Align. \p Align must be
|
||||
/// non-zero.
|
||||
static inline uint64_t OffsetToAlignment(uint64_t Value, uint64_t Align) {
|
||||
return RoundUpToAlignment(Value, Align) - Value;
|
||||
}
|
||||
|
||||
/// abs64 - absolute value of a 64-bit int. Not all environments support
|
||||
/// "abs" on whatever their name for the 64-bit int type is. The absolute
|
||||
/// value of the largest negative number is undefined, as with "abs".
|
||||
static inline int64_t abs64(int64_t x) {
|
||||
return (x < 0) ? -x : x;
|
||||
}
|
||||
|
||||
/// \brief Sign extend number in the bottom B bits of X to a 32-bit int.
|
||||
/// Requires 0 < B <= 32.
|
||||
static inline int32_t SignExtend32(uint32_t X, unsigned B) {
|
||||
return (int32_t)(X << (32 - B)) >> (32 - B);
|
||||
}
|
||||
|
||||
/// \brief Sign extend number in the bottom B bits of X to a 64-bit int.
|
||||
/// Requires 0 < B <= 64.
|
||||
static inline int64_t SignExtend64(uint64_t X, unsigned B) {
|
||||
return (int64_t)(X << (64 - B)) >> (64 - B);
|
||||
}
|
||||
|
||||
/// \brief Count number of 0's from the most significant bit to the least
|
||||
/// stopping at the first 1.
|
||||
///
|
||||
/// Only unsigned integral types are allowed.
|
||||
///
|
||||
/// \param ZB the behavior on an input of 0. Only ZB_Width and ZB_Undefined are
|
||||
/// valid arguments.
|
||||
static inline unsigned int countLeadingZeros(int x)
|
||||
{
|
||||
int i;
|
||||
const unsigned bits = sizeof(x) * 8;
|
||||
unsigned count = bits;
|
||||
|
||||
if (x < 0) {
|
||||
return 0;
|
||||
}
|
||||
for (i = bits; --i; ) {
|
||||
if (x == 0) break;
|
||||
count--;
|
||||
x >>= 1;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,77 @@
|
||||
This is not the official capstone repo. Code here is only retained to show how the obfuscation experiment was set up and compiled
|
||||
|
||||
|
||||
Capstone Engine
|
||||
===============
|
||||
|
||||
[](https://ci.appveyor.com/project/aquynh/capstone/branch/next)
|
||||
[](https://pypi.python.org/pypi/capstone)
|
||||
[](https://pepy.tech/project/capstone)
|
||||
[](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:capstone)
|
||||
|
||||
Capstone is a disassembly framework with the target of becoming the ultimate
|
||||
disasm engine for binary analysis and reversing in the security community.
|
||||
|
||||
Created by Nguyen Anh Quynh, then developed and maintained by a small community,
|
||||
Capstone offers some unparalleled features:
|
||||
|
||||
- Support multiple hardware architectures: ARM, ARM64 (ARMv8), BPF, Ethereum VM,
|
||||
M68K, M680X, Mips, MOS65XX, PPC, RISC-V(rv32G/rv64G), SH, Sparc, SystemZ,
|
||||
TMS320C64X, TriCore, Webassembly, XCore and X86 (16, 32, 64).
|
||||
|
||||
- Having clean/simple/lightweight/intuitive architecture-neutral API.
|
||||
|
||||
- Provide details on disassembled instruction (called “decomposer” by others).
|
||||
|
||||
- Provide semantics of the disassembled instruction, such as list of implicit
|
||||
registers read & written.
|
||||
|
||||
- Implemented in pure C language, with lightweight bindings for Swift, D, Clojure, F#,
|
||||
Common Lisp, Visual Basic, PHP, PowerShell, Emacs, Haskell, Perl, Python,
|
||||
Ruby, C#, NodeJS, Java, GO, C++, OCaml, Lua, Rust, Delphi, Free Pascal & Vala
|
||||
ready either in main code, or provided externally by the community).
|
||||
|
||||
- Native support for all popular platforms: Windows, Mac OSX, iOS, Android,
|
||||
Linux, \*BSD, Solaris, etc.
|
||||
|
||||
- Thread-safe by design.
|
||||
|
||||
- Special support for embedding into firmware or OS kernel.
|
||||
|
||||
- High performance & suitable for malware analysis (capable of handling various
|
||||
X86 malware tricks).
|
||||
|
||||
- Distributed under the open source BSD license.
|
||||
|
||||
Further information is available at https://www.capstone-engine.org
|
||||
|
||||
|
||||
Compile
|
||||
-------
|
||||
|
||||
See COMPILE.TXT file for how to compile and install Capstone.
|
||||
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
|
||||
See docs/README for how to customize & program your own tools with Capstone.
|
||||
|
||||
|
||||
Hack
|
||||
----
|
||||
|
||||
See HACK.TXT file for the structure of the source code.
|
||||
|
||||
|
||||
Fuzz
|
||||
----
|
||||
|
||||
See suite/fuzz/README.md for more information.
|
||||
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
This project is released under the BSD license. If you redistribute the binary
|
||||
or source code of Capstone, please attach file LICENSE.TXT with your products.
|
||||
@@ -0,0 +1,20 @@
|
||||
* Version 4.0.1 - January 10th, 2019
|
||||
|
||||
Release 4.0.1 was sponsored by the following companies (in no particular order).
|
||||
|
||||
- NowSecure: https://www.nowsecure.com
|
||||
- Verichains: https://verichains.io
|
||||
- Vsec: https://vsec.com.vn
|
||||
|
||||
-----------------------------------
|
||||
* Version 4.0 - December 18th, 2018
|
||||
|
||||
Capstone 4.0 version marks 5 years of the project!
|
||||
This release was sponsored by the following companies (in no particular order).
|
||||
|
||||
- Thinkst Canary: https://canary.tools
|
||||
- NowSecure: https://www.nowsecure.com
|
||||
- ECQ: https://e-cq.net
|
||||
- Senrio: https://senr.io
|
||||
- GracefulBits: https://gracefulbits.com
|
||||
- Catena Cyber: https://catenacyber.fr
|
||||
@@ -0,0 +1,181 @@
|
||||
/* Capstone Disassembly Engine */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
|
||||
|
||||
#include <stdarg.h>
|
||||
#if defined(CAPSTONE_HAS_OSXKERNEL)
|
||||
#include <Availability.h>
|
||||
#include <libkern/libkern.h>
|
||||
#include <i386/limits.h>
|
||||
#else
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
|
||||
#include <capstone/platform.h>
|
||||
|
||||
#include "SStream.h"
|
||||
#include "cs_priv.h"
|
||||
#include "utils.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable: 4996) // disable MSVC's warning on strcpy()
|
||||
#endif
|
||||
|
||||
void SStream_Init(SStream *ss)
|
||||
{
|
||||
ss->index = 0;
|
||||
ss->buffer[0] = '\0';
|
||||
}
|
||||
|
||||
void SStream_concat0(SStream *ss, const char *s)
|
||||
{
|
||||
#ifndef CAPSTONE_DIET
|
||||
unsigned int len = (unsigned int) strlen(s);
|
||||
|
||||
memcpy(ss->buffer + ss->index, s, len);
|
||||
ss->index += len;
|
||||
ss->buffer[ss->index] = '\0';
|
||||
#endif
|
||||
}
|
||||
|
||||
void SStream_concat1(SStream *ss, const char c)
|
||||
{
|
||||
#ifndef CAPSTONE_DIET
|
||||
ss->buffer[ss->index] = c;
|
||||
ss->index++;
|
||||
ss->buffer[ss->index] = '\0';
|
||||
#endif
|
||||
}
|
||||
|
||||
void SStream_concat(SStream *ss, const char *fmt, ...)
|
||||
{
|
||||
#ifndef CAPSTONE_DIET
|
||||
va_list ap;
|
||||
int ret;
|
||||
|
||||
va_start(ap, fmt);
|
||||
ret = cs_vsnprintf(ss->buffer + ss->index, sizeof(ss->buffer) - (ss->index + 1), fmt, ap);
|
||||
va_end(ap);
|
||||
ss->index += ret;
|
||||
#endif
|
||||
}
|
||||
|
||||
// print number with prefix #
|
||||
void printInt64Bang(SStream *O, int64_t val)
|
||||
{
|
||||
if (val >= 0) {
|
||||
if (val > HEX_THRESHOLD)
|
||||
SStream_concat(O, "#0x%"PRIx64, val);
|
||||
else
|
||||
SStream_concat(O, "#%"PRIu64, val);
|
||||
} else {
|
||||
if (val <- HEX_THRESHOLD) {
|
||||
if (val == LONG_MIN)
|
||||
SStream_concat(O, "#-0x%"PRIx64, (uint64_t)val);
|
||||
else
|
||||
SStream_concat(O, "#-0x%"PRIx64, (uint64_t)-val);
|
||||
} else
|
||||
SStream_concat(O, "#-%"PRIu64, -val);
|
||||
}
|
||||
}
|
||||
|
||||
void printUInt64Bang(SStream *O, uint64_t val)
|
||||
{
|
||||
if (val > HEX_THRESHOLD)
|
||||
SStream_concat(O, "#0x%"PRIx64, val);
|
||||
else
|
||||
SStream_concat(O, "#%"PRIu64, val);
|
||||
}
|
||||
|
||||
// print number
|
||||
void printInt64(SStream *O, int64_t val)
|
||||
{
|
||||
if (val >= 0) {
|
||||
if (val > HEX_THRESHOLD)
|
||||
SStream_concat(O, "0x%"PRIx64, val);
|
||||
else
|
||||
SStream_concat(O, "%"PRIu64, val);
|
||||
} else {
|
||||
if (val <- HEX_THRESHOLD) {
|
||||
if (val == LONG_MIN)
|
||||
SStream_concat(O, "-0x%"PRIx64, (uint64_t)val);
|
||||
else
|
||||
SStream_concat(O, "-0x%"PRIx64, (uint64_t)-val);
|
||||
} else
|
||||
SStream_concat(O, "-%"PRIu64, -val);
|
||||
}
|
||||
}
|
||||
|
||||
void printUInt64(SStream *O, uint64_t val)
|
||||
{
|
||||
if (val > HEX_THRESHOLD)
|
||||
SStream_concat(O, "0x%"PRIx64, val);
|
||||
else
|
||||
SStream_concat(O, "%"PRIu64, val);
|
||||
}
|
||||
|
||||
// print number in decimal mode
|
||||
void printInt32BangDec(SStream *O, int32_t val)
|
||||
{
|
||||
if (val >= 0)
|
||||
SStream_concat(O, "#%u", val);
|
||||
else {
|
||||
if (val == INT_MIN)
|
||||
SStream_concat(O, "#-%u", val);
|
||||
else
|
||||
SStream_concat(O, "#-%u", (uint32_t)-val);
|
||||
}
|
||||
}
|
||||
|
||||
void printInt32Bang(SStream *O, int32_t val)
|
||||
{
|
||||
if (val >= 0) {
|
||||
if (val > HEX_THRESHOLD)
|
||||
SStream_concat(O, "#0x%x", val);
|
||||
else
|
||||
SStream_concat(O, "#%u", val);
|
||||
} else {
|
||||
if (val <- HEX_THRESHOLD) {
|
||||
if (val == INT_MIN)
|
||||
SStream_concat(O, "#-0x%x", (uint32_t)val);
|
||||
else
|
||||
SStream_concat(O, "#-0x%x", (uint32_t)-val);
|
||||
} else
|
||||
SStream_concat(O, "#-%u", -val);
|
||||
}
|
||||
}
|
||||
|
||||
void printInt32(SStream *O, int32_t val)
|
||||
{
|
||||
if (val >= 0) {
|
||||
if (val > HEX_THRESHOLD)
|
||||
SStream_concat(O, "0x%x", val);
|
||||
else
|
||||
SStream_concat(O, "%u", val);
|
||||
} else {
|
||||
if (val <- HEX_THRESHOLD) {
|
||||
if (val == INT_MIN)
|
||||
SStream_concat(O, "-0x%x", (uint32_t)val);
|
||||
else
|
||||
SStream_concat(O, "-0x%x", (uint32_t)-val);
|
||||
} else
|
||||
SStream_concat(O, "-%u", -val);
|
||||
}
|
||||
}
|
||||
|
||||
void printUInt32Bang(SStream *O, uint32_t val)
|
||||
{
|
||||
if (val > HEX_THRESHOLD)
|
||||
SStream_concat(O, "#0x%x", val);
|
||||
else
|
||||
SStream_concat(O, "#%u", val);
|
||||
}
|
||||
|
||||
void printUInt32(SStream *O, uint32_t val)
|
||||
{
|
||||
if (val > HEX_THRESHOLD)
|
||||
SStream_concat(O, "0x%x", val);
|
||||
else
|
||||
SStream_concat(O, "%u", val);
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/* Capstone Disassembly Engine */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
|
||||
|
||||
#ifndef CS_SSTREAM_H_
|
||||
#define CS_SSTREAM_H_
|
||||
|
||||
#include "include/capstone/platform.h"
|
||||
|
||||
typedef struct SStream {
|
||||
char buffer[512];
|
||||
int index;
|
||||
} SStream;
|
||||
|
||||
void SStream_Init(SStream *ss);
|
||||
|
||||
void SStream_concat(SStream *ss, const char *fmt, ...);
|
||||
|
||||
void SStream_concat0(SStream *ss, const char *s);
|
||||
|
||||
void SStream_concat1(SStream *ss, const char c);
|
||||
|
||||
void printInt64Bang(SStream *O, int64_t val);
|
||||
|
||||
void printUInt64Bang(SStream *O, uint64_t val);
|
||||
|
||||
void printInt64(SStream *O, int64_t val);
|
||||
void printUInt64(SStream *O, uint64_t val);
|
||||
|
||||
void printInt32Bang(SStream *O, int32_t val);
|
||||
|
||||
void printInt32(SStream *O, int32_t val);
|
||||
|
||||
void printUInt32Bang(SStream *O, uint32_t val);
|
||||
|
||||
void printUInt32(SStream *O, uint32_t val);
|
||||
|
||||
// print number in decimal mode
|
||||
void printInt32BangDec(SStream *O, int32_t val);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,945 @@
|
||||
//===- AArch64AddressingModes.h - AArch64 Addressing Modes ------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains the AArch64 addressing mode implementation stuff.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef CS_AARCH64_ADDRESSINGMODES_H
|
||||
#define CS_AARCH64_ADDRESSINGMODES_H
|
||||
|
||||
/* Capstone Disassembly Engine */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
|
||||
|
||||
#include "../../MathExtras.h"
|
||||
|
||||
/// AArch64_AM - AArch64 Addressing Mode Stuff
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Shifts
|
||||
//
|
||||
typedef enum AArch64_AM_ShiftExtendType {
|
||||
AArch64_AM_InvalidShiftExtend = -1,
|
||||
AArch64_AM_LSL = 0,
|
||||
AArch64_AM_LSR,
|
||||
AArch64_AM_ASR,
|
||||
AArch64_AM_ROR,
|
||||
AArch64_AM_MSL,
|
||||
|
||||
AArch64_AM_UXTB,
|
||||
AArch64_AM_UXTH,
|
||||
AArch64_AM_UXTW,
|
||||
AArch64_AM_UXTX,
|
||||
|
||||
AArch64_AM_SXTB,
|
||||
AArch64_AM_SXTH,
|
||||
AArch64_AM_SXTW,
|
||||
AArch64_AM_SXTX,
|
||||
} AArch64_AM_ShiftExtendType;
|
||||
|
||||
/// getShiftName - Get the string encoding for the shift type.
|
||||
static inline const char *AArch64_AM_getShiftExtendName(AArch64_AM_ShiftExtendType ST)
|
||||
{
|
||||
switch (ST) {
|
||||
default: return NULL; // never reach
|
||||
case AArch64_AM_LSL: return "lsl";
|
||||
case AArch64_AM_LSR: return "lsr";
|
||||
case AArch64_AM_ASR: return "asr";
|
||||
case AArch64_AM_ROR: return "ror";
|
||||
case AArch64_AM_MSL: return "msl";
|
||||
case AArch64_AM_UXTB: return "uxtb";
|
||||
case AArch64_AM_UXTH: return "uxth";
|
||||
case AArch64_AM_UXTW: return "uxtw";
|
||||
case AArch64_AM_UXTX: return "uxtx";
|
||||
case AArch64_AM_SXTB: return "sxtb";
|
||||
case AArch64_AM_SXTH: return "sxth";
|
||||
case AArch64_AM_SXTW: return "sxtw";
|
||||
case AArch64_AM_SXTX: return "sxtx";
|
||||
}
|
||||
}
|
||||
|
||||
/// getShiftType - Extract the shift type.
|
||||
static inline AArch64_AM_ShiftExtendType AArch64_AM_getShiftType(unsigned Imm)
|
||||
{
|
||||
switch ((Imm >> 6) & 0x7) {
|
||||
default: return AArch64_AM_InvalidShiftExtend;
|
||||
case 0: return AArch64_AM_LSL;
|
||||
case 1: return AArch64_AM_LSR;
|
||||
case 2: return AArch64_AM_ASR;
|
||||
case 3: return AArch64_AM_ROR;
|
||||
case 4: return AArch64_AM_MSL;
|
||||
}
|
||||
}
|
||||
|
||||
/// getShiftValue - Extract the shift value.
|
||||
static inline unsigned AArch64_AM_getShiftValue(unsigned Imm)
|
||||
{
|
||||
return Imm & 0x3f;
|
||||
}
|
||||
|
||||
static inline unsigned AArch64_AM_getShifterImm(AArch64_AM_ShiftExtendType ST, unsigned Imm)
|
||||
{
|
||||
// assert((Imm & 0x3f) == Imm && "Illegal shifted immedate value!");
|
||||
unsigned STEnc = 0;
|
||||
|
||||
switch (ST) {
|
||||
default: // llvm_unreachable("Invalid shift requested");
|
||||
case AArch64_AM_LSL: STEnc = 0; break;
|
||||
case AArch64_AM_LSR: STEnc = 1; break;
|
||||
case AArch64_AM_ASR: STEnc = 2; break;
|
||||
case AArch64_AM_ROR: STEnc = 3; break;
|
||||
case AArch64_AM_MSL: STEnc = 4; break;
|
||||
}
|
||||
|
||||
return (STEnc << 6) | (Imm & 0x3f);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Extends
|
||||
//
|
||||
|
||||
/// getArithShiftValue - get the arithmetic shift value.
|
||||
static inline unsigned AArch64_AM_getArithShiftValue(unsigned Imm)
|
||||
{
|
||||
return Imm & 0x7;
|
||||
}
|
||||
|
||||
/// getExtendType - Extract the extend type for operands of arithmetic ops.
|
||||
static inline AArch64_AM_ShiftExtendType AArch64_AM_getExtendType(unsigned Imm)
|
||||
{
|
||||
// assert((Imm & 0x7) == Imm && "invalid immediate!");
|
||||
switch (Imm) {
|
||||
default: // llvm_unreachable("Compiler bug!");
|
||||
case 0: return AArch64_AM_UXTB;
|
||||
case 1: return AArch64_AM_UXTH;
|
||||
case 2: return AArch64_AM_UXTW;
|
||||
case 3: return AArch64_AM_UXTX;
|
||||
case 4: return AArch64_AM_SXTB;
|
||||
case 5: return AArch64_AM_SXTH;
|
||||
case 6: return AArch64_AM_SXTW;
|
||||
case 7: return AArch64_AM_SXTX;
|
||||
}
|
||||
}
|
||||
|
||||
static inline AArch64_AM_ShiftExtendType AArch64_AM_getArithExtendType(unsigned Imm)
|
||||
{
|
||||
return AArch64_AM_getExtendType((Imm >> 3) & 0x7);
|
||||
}
|
||||
|
||||
/// Mapping from extend bits to required operation:
|
||||
/// shifter: 000 ==> uxtb
|
||||
/// 001 ==> uxth
|
||||
/// 010 ==> uxtw
|
||||
/// 011 ==> uxtx
|
||||
/// 100 ==> sxtb
|
||||
/// 101 ==> sxth
|
||||
/// 110 ==> sxtw
|
||||
/// 111 ==> sxtx
|
||||
static inline unsigned AArch64_AM_getExtendEncoding(AArch64_AM_ShiftExtendType ET)
|
||||
{
|
||||
switch (ET) {
|
||||
default: // llvm_unreachable("Invalid extend type requested");
|
||||
case AArch64_AM_UXTB: return 0; break;
|
||||
case AArch64_AM_UXTH: return 1; break;
|
||||
case AArch64_AM_UXTW: return 2; break;
|
||||
case AArch64_AM_UXTX: return 3; break;
|
||||
case AArch64_AM_SXTB: return 4; break;
|
||||
case AArch64_AM_SXTH: return 5; break;
|
||||
case AArch64_AM_SXTW: return 6; break;
|
||||
case AArch64_AM_SXTX: return 7; break;
|
||||
}
|
||||
}
|
||||
|
||||
/// getArithExtendImm - Encode the extend type and shift amount for an
|
||||
/// arithmetic instruction:
|
||||
/// imm: 3-bit extend amount
|
||||
/// {5-3} = shifter
|
||||
/// {2-0} = imm3
|
||||
static inline unsigned AArch64_AM_getArithExtendImm(AArch64_AM_ShiftExtendType ET, unsigned Imm)
|
||||
{
|
||||
// assert((Imm & 0x7) == Imm && "Illegal shifted immedate value!");
|
||||
return (AArch64_AM_getExtendEncoding(ET) << 3) | (Imm & 0x7);
|
||||
}
|
||||
|
||||
/// getMemDoShift - Extract the "do shift" flag value for load/store
|
||||
/// instructions.
|
||||
static inline bool AArch64_AM_getMemDoShift(unsigned Imm)
|
||||
{
|
||||
return (Imm & 0x1) != 0;
|
||||
}
|
||||
|
||||
/// getExtendType - Extract the extend type for the offset operand of
|
||||
/// loads/stores.
|
||||
static inline AArch64_AM_ShiftExtendType AArch64_AM_getMemExtendType(unsigned Imm)
|
||||
{
|
||||
return AArch64_AM_getExtendType((Imm >> 1) & 0x7);
|
||||
}
|
||||
|
||||
static inline uint64_t ror(uint64_t elt, unsigned size)
|
||||
{
|
||||
return ((elt & 1) << (size-1)) | (elt >> 1);
|
||||
}
|
||||
|
||||
/// processLogicalImmediate - Determine if an immediate value can be encoded
|
||||
/// as the immediate operand of a logical instruction for the given register
|
||||
/// size. If so, return true with "encoding" set to the encoded value in
|
||||
/// the form N:immr:imms.
|
||||
static inline bool AArch64_AM_processLogicalImmediate(uint64_t Imm, unsigned RegSize, uint64_t *Encoding)
|
||||
{
|
||||
unsigned Size, Immr, N;
|
||||
uint32_t CTO, I;
|
||||
uint64_t Mask, NImms;
|
||||
|
||||
if (Imm == 0ULL || Imm == ~0ULL ||
|
||||
(RegSize != 64 && (Imm >> RegSize != 0 || Imm == (~0ULL >> (64 - RegSize))))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// First, determine the element size.
|
||||
Size = RegSize;
|
||||
do {
|
||||
uint64_t Mask;
|
||||
|
||||
Size /= 2;
|
||||
Mask = (1ULL << Size) - 1;
|
||||
if ((Imm & Mask) != ((Imm >> Size) & Mask)) {
|
||||
Size *= 2;
|
||||
break;
|
||||
}
|
||||
} while (Size > 2);
|
||||
|
||||
// Second, determine the rotation to make the element be: 0^m 1^n.
|
||||
Mask = ((uint64_t)-1LL) >> (64 - Size);
|
||||
Imm &= Mask;
|
||||
|
||||
if (isShiftedMask_64(Imm)) {
|
||||
I = CountTrailingZeros_32(Imm);
|
||||
// assert(I < 64 && "undefined behavior");
|
||||
CTO = CountTrailingOnes_32(Imm >> I);
|
||||
} else {
|
||||
unsigned CLO;
|
||||
|
||||
Imm |= ~Mask;
|
||||
if (!isShiftedMask_64(~Imm))
|
||||
return false;
|
||||
|
||||
CLO = CountLeadingOnes_32(Imm);
|
||||
I = 64 - CLO;
|
||||
CTO = CLO + CountTrailingOnes_32(Imm) - (64 - Size);
|
||||
}
|
||||
|
||||
// Encode in Immr the number of RORs it would take to get *from* 0^m 1^n
|
||||
// to our target value, where I is the number of RORs to go the opposite
|
||||
// direction.
|
||||
// assert(Size > I && "I should be smaller than element size");
|
||||
Immr = (Size - I) & (Size - 1);
|
||||
|
||||
// If size has a 1 in the n'th bit, create a value that has zeroes in
|
||||
// bits [0, n] and ones above that.
|
||||
NImms = ~(Size-1) << 1;
|
||||
|
||||
// Or the CTO value into the low bits, which must be below the Nth bit
|
||||
// bit mentioned above.
|
||||
NImms |= (CTO-1);
|
||||
|
||||
// Extract the seventh bit and toggle it to create the N field.
|
||||
N = ((NImms >> 6) & 1) ^ 1;
|
||||
|
||||
*Encoding = (N << 12) | (Immr << 6) | (NImms & 0x3f);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// isLogicalImmediate - Return true if the immediate is valid for a logical
|
||||
/// immediate instruction of the given register size. Return false otherwise.
|
||||
static inline bool isLogicalImmediate(uint64_t imm, unsigned regSize)
|
||||
{
|
||||
uint64_t encoding;
|
||||
return AArch64_AM_processLogicalImmediate(imm, regSize, &encoding);
|
||||
}
|
||||
|
||||
/// encodeLogicalImmediate - Return the encoded immediate value for a logical
|
||||
/// immediate instruction of the given register size.
|
||||
static inline uint64_t AArch64_AM_encodeLogicalImmediate(uint64_t imm, unsigned regSize)
|
||||
{
|
||||
uint64_t encoding = 0;
|
||||
|
||||
bool res = AArch64_AM_processLogicalImmediate(imm, regSize, &encoding);
|
||||
// assert(res && "invalid logical immediate");
|
||||
(void)res;
|
||||
|
||||
return encoding;
|
||||
}
|
||||
|
||||
/// decodeLogicalImmediate - Decode a logical immediate value in the form
|
||||
/// "N:immr:imms" (where the immr and imms fields are each 6 bits) into the
|
||||
/// integer value it represents with regSize bits.
|
||||
static inline uint64_t AArch64_AM_decodeLogicalImmediate(uint64_t val, unsigned regSize)
|
||||
{
|
||||
// Extract the N, imms, and immr fields.
|
||||
unsigned N = (val >> 12) & 1;
|
||||
unsigned immr = (val >> 6) & 0x3f;
|
||||
unsigned imms = val & 0x3f;
|
||||
unsigned i, size, R, S;
|
||||
uint64_t pattern;
|
||||
|
||||
// assert((regSize == 64 || N == 0) && "undefined logical immediate encoding");
|
||||
int len = 31 - CountLeadingZeros_32((N << 6) | (~imms & 0x3f));
|
||||
|
||||
// assert(len >= 0 && "undefined logical immediate encoding");
|
||||
size = (1 << len);
|
||||
R = immr & (size - 1);
|
||||
S = imms & (size - 1);
|
||||
|
||||
// assert(S != size - 1 && "undefined logical immediate encoding");
|
||||
pattern = (1ULL << (S + 1)) - 1;
|
||||
|
||||
for (i = 0; i < R; ++i)
|
||||
pattern = ror(pattern, size);
|
||||
|
||||
// Replicate the pattern to fill the regSize.
|
||||
while (size != regSize) {
|
||||
pattern |= (pattern << size);
|
||||
size *= 2;
|
||||
}
|
||||
|
||||
return pattern;
|
||||
}
|
||||
|
||||
/// isValidDecodeLogicalImmediate - Check to see if the logical immediate value
|
||||
/// in the form "N:immr:imms" (where the immr and imms fields are each 6 bits)
|
||||
/// is a valid encoding for an integer value with regSize bits.
|
||||
static inline bool AArch64_AM_isValidDecodeLogicalImmediate(uint64_t val, unsigned regSize)
|
||||
{
|
||||
unsigned size, S;
|
||||
int len;
|
||||
// Extract the N and imms fields needed for checking.
|
||||
unsigned N = (val >> 12) & 1;
|
||||
unsigned imms = val & 0x3f;
|
||||
|
||||
if (regSize == 32 && N != 0) // undefined logical immediate encoding
|
||||
return false;
|
||||
len = 31 - CountLeadingZeros_32((N << 6) | (~imms & 0x3f));
|
||||
if (len < 0) // undefined logical immediate encoding
|
||||
return false;
|
||||
size = (1 << len);
|
||||
S = imms & (size - 1);
|
||||
if (S == size - 1) // undefined logical immediate encoding
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Floating-point Immediates
|
||||
//
|
||||
static inline float AArch64_AM_getFPImmFloat(unsigned Imm)
|
||||
{
|
||||
// We expect an 8-bit binary encoding of a floating-point number here.
|
||||
union {
|
||||
uint32_t I;
|
||||
float F;
|
||||
} FPUnion;
|
||||
|
||||
uint8_t Sign = (Imm >> 7) & 0x1;
|
||||
uint8_t Exp = (Imm >> 4) & 0x7;
|
||||
uint8_t Mantissa = Imm & 0xf;
|
||||
|
||||
// 8-bit FP iEEEE Float Encoding
|
||||
// abcd efgh aBbbbbbc defgh000 00000000 00000000
|
||||
//
|
||||
// where B = NOT(b);
|
||||
|
||||
FPUnion.I = 0;
|
||||
FPUnion.I |= ((uint32_t)Sign) << 31;
|
||||
FPUnion.I |= ((Exp & 0x4) != 0 ? 0 : 1) << 30;
|
||||
FPUnion.I |= ((Exp & 0x4) != 0 ? 0x1f : 0) << 25;
|
||||
FPUnion.I |= (Exp & 0x3) << 23;
|
||||
FPUnion.I |= Mantissa << 19;
|
||||
|
||||
return FPUnion.F;
|
||||
}
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// AdvSIMD Modified Immediates
|
||||
//===--------------------------------------------------------------------===//
|
||||
|
||||
// 0x00 0x00 0x00 abcdefgh 0x00 0x00 0x00 abcdefgh
|
||||
static inline bool AArch64_AM_isAdvSIMDModImmType1(uint64_t Imm)
|
||||
{
|
||||
return ((Imm >> 32) == (Imm & 0xffffffffULL)) &&
|
||||
((Imm & 0xffffff00ffffff00ULL) == 0);
|
||||
}
|
||||
|
||||
static inline uint8_t AArch64_AM_encodeAdvSIMDModImmType1(uint64_t Imm)
|
||||
{
|
||||
return (Imm & 0xffULL);
|
||||
}
|
||||
|
||||
static inline uint64_t AArch64_AM_decodeAdvSIMDModImmType1(uint8_t Imm)
|
||||
{
|
||||
uint64_t EncVal = Imm;
|
||||
|
||||
return (EncVal << 32) | EncVal;
|
||||
}
|
||||
|
||||
// 0x00 0x00 abcdefgh 0x00 0x00 0x00 abcdefgh 0x00
|
||||
static inline bool AArch64_AM_isAdvSIMDModImmType2(uint64_t Imm)
|
||||
{
|
||||
return ((Imm >> 32) == (Imm & 0xffffffffULL)) &&
|
||||
((Imm & 0xffff00ffffff00ffULL) == 0);
|
||||
}
|
||||
|
||||
static inline uint8_t AArch64_AM_encodeAdvSIMDModImmType2(uint64_t Imm)
|
||||
{
|
||||
return (Imm & 0xff00ULL) >> 8;
|
||||
}
|
||||
|
||||
static inline uint64_t AArch64_AM_decodeAdvSIMDModImmType2(uint8_t Imm)
|
||||
{
|
||||
uint64_t EncVal = Imm;
|
||||
return (EncVal << 40) | (EncVal << 8);
|
||||
}
|
||||
|
||||
// 0x00 abcdefgh 0x00 0x00 0x00 abcdefgh 0x00 0x00
|
||||
static inline bool AArch64_AM_isAdvSIMDModImmType3(uint64_t Imm)
|
||||
{
|
||||
return ((Imm >> 32) == (Imm & 0xffffffffULL)) &&
|
||||
((Imm & 0xff00ffffff00ffffULL) == 0);
|
||||
}
|
||||
|
||||
static inline uint8_t AArch64_AM_encodeAdvSIMDModImmType3(uint64_t Imm)
|
||||
{
|
||||
return (Imm & 0xff0000ULL) >> 16;
|
||||
}
|
||||
|
||||
static inline uint64_t AArch64_AM_decodeAdvSIMDModImmType3(uint8_t Imm)
|
||||
{
|
||||
uint64_t EncVal = Imm;
|
||||
return (EncVal << 48) | (EncVal << 16);
|
||||
}
|
||||
|
||||
// abcdefgh 0x00 0x00 0x00 abcdefgh 0x00 0x00 0x00
|
||||
static inline bool AArch64_AM_isAdvSIMDModImmType4(uint64_t Imm)
|
||||
{
|
||||
return ((Imm >> 32) == (Imm & 0xffffffffULL)) &&
|
||||
((Imm & 0x00ffffff00ffffffULL) == 0);
|
||||
}
|
||||
|
||||
static inline uint8_t AArch64_AM_encodeAdvSIMDModImmType4(uint64_t Imm)
|
||||
{
|
||||
return (Imm & 0xff000000ULL) >> 24;
|
||||
}
|
||||
|
||||
static inline uint64_t AArch64_AM_decodeAdvSIMDModImmType4(uint8_t Imm)
|
||||
{
|
||||
uint64_t EncVal = Imm;
|
||||
return (EncVal << 56) | (EncVal << 24);
|
||||
}
|
||||
|
||||
// 0x00 abcdefgh 0x00 abcdefgh 0x00 abcdefgh 0x00 abcdefgh
|
||||
static inline bool AArch64_AM_isAdvSIMDModImmType5(uint64_t Imm)
|
||||
{
|
||||
return ((Imm >> 32) == (Imm & 0xffffffffULL)) &&
|
||||
(((Imm & 0x00ff0000ULL) >> 16) == (Imm & 0x000000ffULL)) &&
|
||||
((Imm & 0xff00ff00ff00ff00ULL) == 0);
|
||||
}
|
||||
|
||||
static inline uint8_t AArch64_AM_encodeAdvSIMDModImmType5(uint64_t Imm)
|
||||
{
|
||||
return (Imm & 0xffULL);
|
||||
}
|
||||
|
||||
static inline uint64_t AArch64_AM_decodeAdvSIMDModImmType5(uint8_t Imm)
|
||||
{
|
||||
uint64_t EncVal = Imm;
|
||||
return (EncVal << 48) | (EncVal << 32) | (EncVal << 16) | EncVal;
|
||||
}
|
||||
|
||||
// abcdefgh 0x00 abcdefgh 0x00 abcdefgh 0x00 abcdefgh 0x00
|
||||
static inline bool AArch64_AM_isAdvSIMDModImmType6(uint64_t Imm)
|
||||
{
|
||||
return ((Imm >> 32) == (Imm & 0xffffffffULL)) &&
|
||||
(((Imm & 0xff000000ULL) >> 16) == (Imm & 0x0000ff00ULL)) &&
|
||||
((Imm & 0x00ff00ff00ff00ffULL) == 0);
|
||||
}
|
||||
|
||||
static inline uint8_t AArch64_AM_encodeAdvSIMDModImmType6(uint64_t Imm)
|
||||
{
|
||||
return (Imm & 0xff00ULL) >> 8;
|
||||
}
|
||||
|
||||
static inline uint64_t AArch64_AM_decodeAdvSIMDModImmType6(uint8_t Imm)
|
||||
{
|
||||
uint64_t EncVal = Imm;
|
||||
return (EncVal << 56) | (EncVal << 40) | (EncVal << 24) | (EncVal << 8);
|
||||
}
|
||||
|
||||
// 0x00 0x00 abcdefgh 0xFF 0x00 0x00 abcdefgh 0xFF
|
||||
static inline bool AArch64_AM_isAdvSIMDModImmType7(uint64_t Imm)
|
||||
{
|
||||
return ((Imm >> 32) == (Imm & 0xffffffffULL)) &&
|
||||
((Imm & 0xffff00ffffff00ffULL) == 0x000000ff000000ffULL);
|
||||
}
|
||||
|
||||
static inline uint8_t AArch64_AM_encodeAdvSIMDModImmType7(uint64_t Imm)
|
||||
{
|
||||
return (Imm & 0xff00ULL) >> 8;
|
||||
}
|
||||
|
||||
static inline uint64_t AArch64_AM_decodeAdvSIMDModImmType7(uint8_t Imm)
|
||||
{
|
||||
uint64_t EncVal = Imm;
|
||||
return (EncVal << 40) | (EncVal << 8) | 0x000000ff000000ffULL;
|
||||
}
|
||||
|
||||
// 0x00 abcdefgh 0xFF 0xFF 0x00 abcdefgh 0xFF 0xFF
|
||||
static inline bool AArch64_AM_isAdvSIMDModImmType8(uint64_t Imm)
|
||||
{
|
||||
return ((Imm >> 32) == (Imm & 0xffffffffULL)) &&
|
||||
((Imm & 0xff00ffffff00ffffULL) == 0x0000ffff0000ffffULL);
|
||||
}
|
||||
|
||||
static inline uint64_t AArch64_AM_decodeAdvSIMDModImmType8(uint8_t Imm)
|
||||
{
|
||||
uint64_t EncVal = Imm;
|
||||
return (EncVal << 48) | (EncVal << 16) | 0x0000ffff0000ffffULL;
|
||||
}
|
||||
|
||||
static inline uint8_t AArch64_AM_encodeAdvSIMDModImmType8(uint64_t Imm)
|
||||
{
|
||||
return (Imm & 0x00ff0000ULL) >> 16;
|
||||
}
|
||||
|
||||
// abcdefgh abcdefgh abcdefgh abcdefgh abcdefgh abcdefgh abcdefgh abcdefgh
|
||||
static inline bool AArch64_AM_isAdvSIMDModImmType9(uint64_t Imm)
|
||||
{
|
||||
return ((Imm >> 32) == (Imm & 0xffffffffULL)) &&
|
||||
((Imm >> 48) == (Imm & 0x0000ffffULL)) &&
|
||||
((Imm >> 56) == (Imm & 0x000000ffULL));
|
||||
}
|
||||
|
||||
static inline uint8_t AArch64_AM_encodeAdvSIMDModImmType9(uint64_t Imm)
|
||||
{
|
||||
return (Imm & 0xffULL);
|
||||
}
|
||||
|
||||
static inline uint64_t AArch64_AM_decodeAdvSIMDModImmType9(uint8_t Imm)
|
||||
{
|
||||
uint64_t EncVal = Imm;
|
||||
EncVal |= (EncVal << 8);
|
||||
EncVal |= (EncVal << 16);
|
||||
EncVal |= (EncVal << 32);
|
||||
|
||||
return EncVal;
|
||||
}
|
||||
|
||||
// aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
|
||||
// cmode: 1110, op: 1
|
||||
static inline bool AArch64_AM_isAdvSIMDModImmType10(uint64_t Imm)
|
||||
{
|
||||
uint64_t ByteA = Imm & 0xff00000000000000ULL;
|
||||
uint64_t ByteB = Imm & 0x00ff000000000000ULL;
|
||||
uint64_t ByteC = Imm & 0x0000ff0000000000ULL;
|
||||
uint64_t ByteD = Imm & 0x000000ff00000000ULL;
|
||||
uint64_t ByteE = Imm & 0x00000000ff000000ULL;
|
||||
uint64_t ByteF = Imm & 0x0000000000ff0000ULL;
|
||||
uint64_t ByteG = Imm & 0x000000000000ff00ULL;
|
||||
uint64_t ByteH = Imm & 0x00000000000000ffULL;
|
||||
|
||||
return (ByteA == 0ULL || ByteA == 0xff00000000000000ULL) &&
|
||||
(ByteB == 0ULL || ByteB == 0x00ff000000000000ULL) &&
|
||||
(ByteC == 0ULL || ByteC == 0x0000ff0000000000ULL) &&
|
||||
(ByteD == 0ULL || ByteD == 0x000000ff00000000ULL) &&
|
||||
(ByteE == 0ULL || ByteE == 0x00000000ff000000ULL) &&
|
||||
(ByteF == 0ULL || ByteF == 0x0000000000ff0000ULL) &&
|
||||
(ByteG == 0ULL || ByteG == 0x000000000000ff00ULL) &&
|
||||
(ByteH == 0ULL || ByteH == 0x00000000000000ffULL);
|
||||
}
|
||||
|
||||
static inline uint8_t AArch64_AM_encodeAdvSIMDModImmType10(uint64_t Imm)
|
||||
{
|
||||
uint8_t BitA = (Imm & 0xff00000000000000ULL) != 0;
|
||||
uint8_t BitB = (Imm & 0x00ff000000000000ULL) != 0;
|
||||
uint8_t BitC = (Imm & 0x0000ff0000000000ULL) != 0;
|
||||
uint8_t BitD = (Imm & 0x000000ff00000000ULL) != 0;
|
||||
uint8_t BitE = (Imm & 0x00000000ff000000ULL) != 0;
|
||||
uint8_t BitF = (Imm & 0x0000000000ff0000ULL) != 0;
|
||||
uint8_t BitG = (Imm & 0x000000000000ff00ULL) != 0;
|
||||
uint8_t BitH = (Imm & 0x00000000000000ffULL) != 0;
|
||||
|
||||
uint8_t EncVal = BitA;
|
||||
|
||||
EncVal <<= 1;
|
||||
EncVal |= BitB;
|
||||
EncVal <<= 1;
|
||||
EncVal |= BitC;
|
||||
EncVal <<= 1;
|
||||
EncVal |= BitD;
|
||||
EncVal <<= 1;
|
||||
EncVal |= BitE;
|
||||
EncVal <<= 1;
|
||||
EncVal |= BitF;
|
||||
EncVal <<= 1;
|
||||
EncVal |= BitG;
|
||||
EncVal <<= 1;
|
||||
EncVal |= BitH;
|
||||
|
||||
return EncVal;
|
||||
}
|
||||
|
||||
static inline uint64_t AArch64_AM_decodeAdvSIMDModImmType10(uint8_t Imm)
|
||||
{
|
||||
uint64_t EncVal = 0;
|
||||
|
||||
if (Imm & 0x80)
|
||||
EncVal |= 0xff00000000000000ULL;
|
||||
|
||||
if (Imm & 0x40)
|
||||
EncVal |= 0x00ff000000000000ULL;
|
||||
|
||||
if (Imm & 0x20)
|
||||
EncVal |= 0x0000ff0000000000ULL;
|
||||
|
||||
if (Imm & 0x10)
|
||||
EncVal |= 0x000000ff00000000ULL;
|
||||
|
||||
if (Imm & 0x08)
|
||||
EncVal |= 0x00000000ff000000ULL;
|
||||
|
||||
if (Imm & 0x04)
|
||||
EncVal |= 0x0000000000ff0000ULL;
|
||||
|
||||
if (Imm & 0x02)
|
||||
EncVal |= 0x000000000000ff00ULL;
|
||||
|
||||
if (Imm & 0x01)
|
||||
EncVal |= 0x00000000000000ffULL;
|
||||
|
||||
return EncVal;
|
||||
}
|
||||
|
||||
// aBbbbbbc defgh000 0x00 0x00 aBbbbbbc defgh000 0x00 0x00
|
||||
static inline bool AArch64_AM_isAdvSIMDModImmType11(uint64_t Imm)
|
||||
{
|
||||
uint64_t BString = (Imm & 0x7E000000ULL) >> 25;
|
||||
|
||||
return ((Imm >> 32) == (Imm & 0xffffffffULL)) &&
|
||||
(BString == 0x1f || BString == 0x20) &&
|
||||
((Imm & 0x0007ffff0007ffffULL) == 0);
|
||||
}
|
||||
|
||||
static inline uint8_t AArch64_AM_encodeAdvSIMDModImmType11(uint64_t Imm)
|
||||
{
|
||||
uint8_t BitA = (Imm & 0x80000000ULL) != 0;
|
||||
uint8_t BitB = (Imm & 0x20000000ULL) != 0;
|
||||
uint8_t BitC = (Imm & 0x01000000ULL) != 0;
|
||||
uint8_t BitD = (Imm & 0x00800000ULL) != 0;
|
||||
uint8_t BitE = (Imm & 0x00400000ULL) != 0;
|
||||
uint8_t BitF = (Imm & 0x00200000ULL) != 0;
|
||||
uint8_t BitG = (Imm & 0x00100000ULL) != 0;
|
||||
uint8_t BitH = (Imm & 0x00080000ULL) != 0;
|
||||
|
||||
uint8_t EncVal = BitA;
|
||||
EncVal <<= 1;
|
||||
EncVal |= BitB;
|
||||
EncVal <<= 1;
|
||||
EncVal |= BitC;
|
||||
EncVal <<= 1;
|
||||
EncVal |= BitD;
|
||||
EncVal <<= 1;
|
||||
EncVal |= BitE;
|
||||
EncVal <<= 1;
|
||||
EncVal |= BitF;
|
||||
EncVal <<= 1;
|
||||
EncVal |= BitG;
|
||||
EncVal <<= 1;
|
||||
EncVal |= BitH;
|
||||
|
||||
return EncVal;
|
||||
}
|
||||
|
||||
static inline uint64_t AArch64_AM_decodeAdvSIMDModImmType11(uint8_t Imm)
|
||||
{
|
||||
uint64_t EncVal = 0;
|
||||
|
||||
if (Imm & 0x80)
|
||||
EncVal |= 0x80000000ULL;
|
||||
|
||||
if (Imm & 0x40)
|
||||
EncVal |= 0x3e000000ULL;
|
||||
else
|
||||
EncVal |= 0x40000000ULL;
|
||||
|
||||
if (Imm & 0x20)
|
||||
EncVal |= 0x01000000ULL;
|
||||
|
||||
if (Imm & 0x10)
|
||||
EncVal |= 0x00800000ULL;
|
||||
|
||||
if (Imm & 0x08)
|
||||
EncVal |= 0x00400000ULL;
|
||||
|
||||
if (Imm & 0x04)
|
||||
EncVal |= 0x00200000ULL;
|
||||
|
||||
if (Imm & 0x02)
|
||||
EncVal |= 0x00100000ULL;
|
||||
|
||||
if (Imm & 0x01)
|
||||
EncVal |= 0x00080000ULL;
|
||||
|
||||
return (EncVal << 32) | EncVal;
|
||||
}
|
||||
|
||||
// aBbbbbbb bbcdefgh 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
static inline bool AArch64_AM_isAdvSIMDModImmType12(uint64_t Imm)
|
||||
{
|
||||
uint64_t BString = (Imm & 0x7fc0000000000000ULL) >> 54;
|
||||
return ((BString == 0xff || BString == 0x100) &&
|
||||
((Imm & 0x0000ffffffffffffULL) == 0));
|
||||
}
|
||||
|
||||
static inline uint8_t AArch64_AM_encodeAdvSIMDModImmType12(uint64_t Imm)
|
||||
{
|
||||
uint8_t BitA = (Imm & 0x8000000000000000ULL) != 0;
|
||||
uint8_t BitB = (Imm & 0x0040000000000000ULL) != 0;
|
||||
uint8_t BitC = (Imm & 0x0020000000000000ULL) != 0;
|
||||
uint8_t BitD = (Imm & 0x0010000000000000ULL) != 0;
|
||||
uint8_t BitE = (Imm & 0x0008000000000000ULL) != 0;
|
||||
uint8_t BitF = (Imm & 0x0004000000000000ULL) != 0;
|
||||
uint8_t BitG = (Imm & 0x0002000000000000ULL) != 0;
|
||||
uint8_t BitH = (Imm & 0x0001000000000000ULL) != 0;
|
||||
|
||||
uint8_t EncVal = BitA;
|
||||
EncVal <<= 1;
|
||||
EncVal |= BitB;
|
||||
EncVal <<= 1;
|
||||
EncVal |= BitC;
|
||||
EncVal <<= 1;
|
||||
EncVal |= BitD;
|
||||
EncVal <<= 1;
|
||||
EncVal |= BitE;
|
||||
EncVal <<= 1;
|
||||
EncVal |= BitF;
|
||||
EncVal <<= 1;
|
||||
EncVal |= BitG;
|
||||
EncVal <<= 1;
|
||||
EncVal |= BitH;
|
||||
|
||||
return EncVal;
|
||||
}
|
||||
|
||||
static inline uint64_t AArch64_AM_decodeAdvSIMDModImmType12(uint8_t Imm)
|
||||
{
|
||||
uint64_t EncVal = 0;
|
||||
if (Imm & 0x80)
|
||||
EncVal |= 0x8000000000000000ULL;
|
||||
|
||||
if (Imm & 0x40)
|
||||
EncVal |= 0x3fc0000000000000ULL;
|
||||
else
|
||||
EncVal |= 0x4000000000000000ULL;
|
||||
|
||||
if (Imm & 0x20)
|
||||
EncVal |= 0x0020000000000000ULL;
|
||||
|
||||
if (Imm & 0x10)
|
||||
EncVal |= 0x0010000000000000ULL;
|
||||
|
||||
if (Imm & 0x08)
|
||||
EncVal |= 0x0008000000000000ULL;
|
||||
|
||||
if (Imm & 0x04)
|
||||
EncVal |= 0x0004000000000000ULL;
|
||||
|
||||
if (Imm & 0x02)
|
||||
EncVal |= 0x0002000000000000ULL;
|
||||
|
||||
if (Imm & 0x01)
|
||||
EncVal |= 0x0001000000000000ULL;
|
||||
|
||||
return (EncVal << 32) | EncVal;
|
||||
}
|
||||
|
||||
/// Returns true if Imm is the concatenation of a repeating pattern of type T.
|
||||
static inline bool AArch64_AM_isSVEMaskOfIdenticalElements8(int64_t Imm)
|
||||
{
|
||||
#define _VECSIZE (sizeof(int64_t)/sizeof(int8_t))
|
||||
unsigned int i;
|
||||
union {
|
||||
int64_t Whole;
|
||||
int8_t Parts[_VECSIZE];
|
||||
} Vec;
|
||||
|
||||
Vec.Whole = Imm;
|
||||
|
||||
for(i = 1; i < _VECSIZE; i++) {
|
||||
if (Vec.Parts[i] != Vec.Parts[0])
|
||||
return false;
|
||||
}
|
||||
#undef _VECSIZE
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool AArch64_AM_isSVEMaskOfIdenticalElements16(int64_t Imm)
|
||||
{
|
||||
#define _VECSIZE (sizeof(int64_t)/sizeof(int16_t))
|
||||
unsigned int i;
|
||||
union {
|
||||
int64_t Whole;
|
||||
int16_t Parts[_VECSIZE];
|
||||
} Vec;
|
||||
|
||||
Vec.Whole = Imm;
|
||||
|
||||
for(i = 1; i < _VECSIZE; i++) {
|
||||
if (Vec.Parts[i] != Vec.Parts[0])
|
||||
return false;
|
||||
}
|
||||
#undef _VECSIZE
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool AArch64_AM_isSVEMaskOfIdenticalElements32(int64_t Imm)
|
||||
{
|
||||
#define _VECSIZE (sizeof(int64_t)/sizeof(int32_t))
|
||||
unsigned int i;
|
||||
union {
|
||||
int64_t Whole;
|
||||
int32_t Parts[_VECSIZE];
|
||||
} Vec;
|
||||
|
||||
Vec.Whole = Imm;
|
||||
|
||||
for(i = 1; i < _VECSIZE; i++) {
|
||||
if (Vec.Parts[i] != Vec.Parts[0])
|
||||
return false;
|
||||
}
|
||||
#undef _VECSIZE
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool AArch64_AM_isSVEMaskOfIdenticalElements64(int64_t Imm)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool isSVECpyImm8(int64_t Imm)
|
||||
{
|
||||
bool IsImm8 = (int8_t)Imm == Imm;
|
||||
|
||||
return IsImm8 || (uint8_t)Imm == Imm;
|
||||
}
|
||||
|
||||
static inline bool isSVECpyImm16(int64_t Imm)
|
||||
{
|
||||
bool IsImm8 = (int8_t)Imm == Imm;
|
||||
bool IsImm16 = (int16_t)(Imm & ~0xff) == Imm;
|
||||
|
||||
return IsImm8 || IsImm16 || (uint16_t)(Imm & ~0xff) == Imm;
|
||||
}
|
||||
|
||||
static inline bool isSVECpyImm32(int64_t Imm)
|
||||
{
|
||||
bool IsImm8 = (int8_t)Imm == Imm;
|
||||
bool IsImm16 = (int16_t)(Imm & ~0xff) == Imm;
|
||||
|
||||
return IsImm8 || IsImm16;
|
||||
}
|
||||
|
||||
static inline bool isSVECpyImm64(int64_t Imm)
|
||||
{
|
||||
bool IsImm8 = (int8_t)Imm == Imm;
|
||||
bool IsImm16 = (int16_t)(Imm & ~0xff) == Imm;
|
||||
|
||||
return IsImm8 || IsImm16;
|
||||
}
|
||||
|
||||
/// Return true if Imm is valid for DUPM and has no single CPY/DUP equivalent.
|
||||
static inline bool AArch64_AM_isSVEMoveMaskPreferredLogicalImmediate(int64_t Imm)
|
||||
{
|
||||
union {
|
||||
int64_t D;
|
||||
int32_t S[2];
|
||||
int16_t H[4];
|
||||
int8_t B[8];
|
||||
} Vec = {Imm};
|
||||
|
||||
if (isSVECpyImm64(Vec.D))
|
||||
return false;
|
||||
|
||||
if (AArch64_AM_isSVEMaskOfIdenticalElements32(Imm) &&
|
||||
isSVECpyImm32(Vec.S[0]))
|
||||
return false;
|
||||
|
||||
if (AArch64_AM_isSVEMaskOfIdenticalElements16(Imm) &&
|
||||
isSVECpyImm16(Vec.H[0]))
|
||||
return false;
|
||||
|
||||
if (AArch64_AM_isSVEMaskOfIdenticalElements8(Imm) &&
|
||||
isSVECpyImm8(Vec.B[0]))
|
||||
return false;
|
||||
|
||||
return isLogicalImmediate(Vec.D, 64);
|
||||
}
|
||||
|
||||
inline static bool isAnyMOVZMovAlias(uint64_t Value, int RegWidth)
|
||||
{
|
||||
int Shift;
|
||||
|
||||
for (Shift = 0; Shift <= RegWidth - 16; Shift += 16)
|
||||
if ((Value & ~(0xffffULL << Shift)) == 0)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
inline static bool isMOVZMovAlias(uint64_t Value, int Shift, int RegWidth)
|
||||
{
|
||||
if (RegWidth == 32)
|
||||
Value &= 0xffffffffULL;
|
||||
|
||||
// "lsl #0" takes precedence: in practice this only affects "#0, lsl #0".
|
||||
if (Value == 0 && Shift != 0)
|
||||
return false;
|
||||
|
||||
return (Value & ~(0xffffULL << Shift)) == 0;
|
||||
}
|
||||
|
||||
inline static bool AArch64_AM_isMOVNMovAlias(uint64_t Value, int Shift, int RegWidth)
|
||||
{
|
||||
// MOVZ takes precedence over MOVN.
|
||||
if (isAnyMOVZMovAlias(Value, RegWidth))
|
||||
return false;
|
||||
|
||||
Value = ~Value;
|
||||
if (RegWidth == 32)
|
||||
Value &= 0xffffffffULL;
|
||||
|
||||
return isMOVZMovAlias(Value, Shift, RegWidth);
|
||||
}
|
||||
|
||||
inline static bool AArch64_AM_isAnyMOVWMovAlias(uint64_t Value, int RegWidth)
|
||||
{
|
||||
if (isAnyMOVZMovAlias(Value, RegWidth))
|
||||
return true;
|
||||
|
||||
// It's not a MOVZ, but it might be a MOVN.
|
||||
Value = ~Value;
|
||||
if (RegWidth == 32)
|
||||
Value &= 0xffffffffULL;
|
||||
|
||||
return isAnyMOVZMovAlias(Value, RegWidth);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,77 @@
|
||||
//===-- AArch64BaseInfo.cpp - AArch64 Base encoding information------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file provides basic encoding and assembly information for AArch64.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/* Capstone Disassembly Engine */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
|
||||
|
||||
#ifdef CAPSTONE_HAS_ARM64
|
||||
|
||||
#if defined (WIN32) || defined (WIN64) || defined (_WIN32) || defined (_WIN64)
|
||||
#pragma warning(disable:4996) // disable MSVC's warning on strcpy()
|
||||
#pragma warning(disable:28719) // disable MSVC's warning on strcpy()
|
||||
#endif
|
||||
|
||||
#include "../../utils.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "AArch64BaseInfo.h"
|
||||
|
||||
#include "AArch64GenSystemOperands.inc"
|
||||
|
||||
// return a string representing the number X
|
||||
// NOTE: result must be big enough to contain the data
|
||||
static void utostr(uint64_t X, bool isNeg, char *result)
|
||||
{
|
||||
char Buffer[22];
|
||||
char *BufPtr = Buffer + 21;
|
||||
|
||||
Buffer[21] = '\0';
|
||||
if (X == 0) *--BufPtr = '0'; // Handle special case...
|
||||
|
||||
while (X) {
|
||||
*--BufPtr = X % 10 + '0';
|
||||
X /= 10;
|
||||
}
|
||||
|
||||
if (isNeg) *--BufPtr = '-'; // Add negative sign...
|
||||
|
||||
// suppose that result is big enough
|
||||
strncpy(result, BufPtr, sizeof(Buffer));
|
||||
}
|
||||
|
||||
// NOTE: result must be big enough to contain the result
|
||||
void AArch64SysReg_genericRegisterString(uint32_t Bits, char *result)
|
||||
{
|
||||
// assert(Bits < 0x10000);
|
||||
char Op0Str[32], Op1Str[32], CRnStr[32], CRmStr[32], Op2Str[32];
|
||||
int dummy;
|
||||
uint32_t Op0 = (Bits >> 14) & 0x3;
|
||||
uint32_t Op1 = (Bits >> 11) & 0x7;
|
||||
uint32_t CRn = (Bits >> 7) & 0xf;
|
||||
uint32_t CRm = (Bits >> 3) & 0xf;
|
||||
uint32_t Op2 = Bits & 0x7;
|
||||
|
||||
utostr(Op0, false, Op0Str);
|
||||
utostr(Op1, false, Op1Str);
|
||||
utostr(Op2, false, Op2Str);
|
||||
utostr(CRn, false, CRnStr);
|
||||
utostr(CRm, false, CRmStr);
|
||||
|
||||
dummy = cs_snprintf(result, 128, "s%s_%s_c%s_c%s_%s",
|
||||
Op0Str, Op1Str, CRnStr, CRmStr, Op2Str);
|
||||
(void)dummy;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,585 @@
|
||||
//===-- AArch64BaseInfo.h - Top level definitions for AArch64- --*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains small standalone helper functions and enum definitions for
|
||||
// the AArch64 target useful for the compiler back-end and the MC libraries.
|
||||
// As such, it deliberately does not include references to LLVM core
|
||||
// code gen types, passes, etc..
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/* Capstone Disassembly Engine */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
|
||||
|
||||
#ifndef CS_LLVM_AARCH64_BASEINFO_H
|
||||
#define CS_LLVM_AARCH64_BASEINFO_H
|
||||
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include "AArch64Mapping.h"
|
||||
|
||||
#ifndef __cplusplus
|
||||
#if defined (WIN32) || defined (WIN64) || defined (_WIN32) || defined (_WIN64)
|
||||
#define inline /* inline */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
inline static unsigned getWRegFromXReg(unsigned Reg)
|
||||
{
|
||||
switch (Reg) {
|
||||
default: break;
|
||||
case ARM64_REG_X0: return ARM64_REG_W0;
|
||||
case ARM64_REG_X1: return ARM64_REG_W1;
|
||||
case ARM64_REG_X2: return ARM64_REG_W2;
|
||||
case ARM64_REG_X3: return ARM64_REG_W3;
|
||||
case ARM64_REG_X4: return ARM64_REG_W4;
|
||||
case ARM64_REG_X5: return ARM64_REG_W5;
|
||||
case ARM64_REG_X6: return ARM64_REG_W6;
|
||||
case ARM64_REG_X7: return ARM64_REG_W7;
|
||||
case ARM64_REG_X8: return ARM64_REG_W8;
|
||||
case ARM64_REG_X9: return ARM64_REG_W9;
|
||||
case ARM64_REG_X10: return ARM64_REG_W10;
|
||||
case ARM64_REG_X11: return ARM64_REG_W11;
|
||||
case ARM64_REG_X12: return ARM64_REG_W12;
|
||||
case ARM64_REG_X13: return ARM64_REG_W13;
|
||||
case ARM64_REG_X14: return ARM64_REG_W14;
|
||||
case ARM64_REG_X15: return ARM64_REG_W15;
|
||||
case ARM64_REG_X16: return ARM64_REG_W16;
|
||||
case ARM64_REG_X17: return ARM64_REG_W17;
|
||||
case ARM64_REG_X18: return ARM64_REG_W18;
|
||||
case ARM64_REG_X19: return ARM64_REG_W19;
|
||||
case ARM64_REG_X20: return ARM64_REG_W20;
|
||||
case ARM64_REG_X21: return ARM64_REG_W21;
|
||||
case ARM64_REG_X22: return ARM64_REG_W22;
|
||||
case ARM64_REG_X23: return ARM64_REG_W23;
|
||||
case ARM64_REG_X24: return ARM64_REG_W24;
|
||||
case ARM64_REG_X25: return ARM64_REG_W25;
|
||||
case ARM64_REG_X26: return ARM64_REG_W26;
|
||||
case ARM64_REG_X27: return ARM64_REG_W27;
|
||||
case ARM64_REG_X28: return ARM64_REG_W28;
|
||||
case ARM64_REG_FP: return ARM64_REG_W29;
|
||||
case ARM64_REG_LR: return ARM64_REG_W30;
|
||||
case ARM64_REG_SP: return ARM64_REG_WSP;
|
||||
case ARM64_REG_XZR: return ARM64_REG_WZR;
|
||||
}
|
||||
|
||||
// For anything else, return it unchanged.
|
||||
return Reg;
|
||||
}
|
||||
|
||||
inline static unsigned getXRegFromWReg(unsigned Reg)
|
||||
{
|
||||
switch (Reg) {
|
||||
case ARM64_REG_W0: return ARM64_REG_X0;
|
||||
case ARM64_REG_W1: return ARM64_REG_X1;
|
||||
case ARM64_REG_W2: return ARM64_REG_X2;
|
||||
case ARM64_REG_W3: return ARM64_REG_X3;
|
||||
case ARM64_REG_W4: return ARM64_REG_X4;
|
||||
case ARM64_REG_W5: return ARM64_REG_X5;
|
||||
case ARM64_REG_W6: return ARM64_REG_X6;
|
||||
case ARM64_REG_W7: return ARM64_REG_X7;
|
||||
case ARM64_REG_W8: return ARM64_REG_X8;
|
||||
case ARM64_REG_W9: return ARM64_REG_X9;
|
||||
case ARM64_REG_W10: return ARM64_REG_X10;
|
||||
case ARM64_REG_W11: return ARM64_REG_X11;
|
||||
case ARM64_REG_W12: return ARM64_REG_X12;
|
||||
case ARM64_REG_W13: return ARM64_REG_X13;
|
||||
case ARM64_REG_W14: return ARM64_REG_X14;
|
||||
case ARM64_REG_W15: return ARM64_REG_X15;
|
||||
case ARM64_REG_W16: return ARM64_REG_X16;
|
||||
case ARM64_REG_W17: return ARM64_REG_X17;
|
||||
case ARM64_REG_W18: return ARM64_REG_X18;
|
||||
case ARM64_REG_W19: return ARM64_REG_X19;
|
||||
case ARM64_REG_W20: return ARM64_REG_X20;
|
||||
case ARM64_REG_W21: return ARM64_REG_X21;
|
||||
case ARM64_REG_W22: return ARM64_REG_X22;
|
||||
case ARM64_REG_W23: return ARM64_REG_X23;
|
||||
case ARM64_REG_W24: return ARM64_REG_X24;
|
||||
case ARM64_REG_W25: return ARM64_REG_X25;
|
||||
case ARM64_REG_W26: return ARM64_REG_X26;
|
||||
case ARM64_REG_W27: return ARM64_REG_X27;
|
||||
case ARM64_REG_W28: return ARM64_REG_X28;
|
||||
case ARM64_REG_W29: return ARM64_REG_FP;
|
||||
case ARM64_REG_W30: return ARM64_REG_LR;
|
||||
case ARM64_REG_WSP: return ARM64_REG_SP;
|
||||
case ARM64_REG_WZR: return ARM64_REG_XZR;
|
||||
}
|
||||
|
||||
// For anything else, return it unchanged.
|
||||
return Reg;
|
||||
}
|
||||
|
||||
inline static unsigned getBRegFromDReg(unsigned Reg)
|
||||
{
|
||||
switch (Reg) {
|
||||
case ARM64_REG_D0: return ARM64_REG_B0;
|
||||
case ARM64_REG_D1: return ARM64_REG_B1;
|
||||
case ARM64_REG_D2: return ARM64_REG_B2;
|
||||
case ARM64_REG_D3: return ARM64_REG_B3;
|
||||
case ARM64_REG_D4: return ARM64_REG_B4;
|
||||
case ARM64_REG_D5: return ARM64_REG_B5;
|
||||
case ARM64_REG_D6: return ARM64_REG_B6;
|
||||
case ARM64_REG_D7: return ARM64_REG_B7;
|
||||
case ARM64_REG_D8: return ARM64_REG_B8;
|
||||
case ARM64_REG_D9: return ARM64_REG_B9;
|
||||
case ARM64_REG_D10: return ARM64_REG_B10;
|
||||
case ARM64_REG_D11: return ARM64_REG_B11;
|
||||
case ARM64_REG_D12: return ARM64_REG_B12;
|
||||
case ARM64_REG_D13: return ARM64_REG_B13;
|
||||
case ARM64_REG_D14: return ARM64_REG_B14;
|
||||
case ARM64_REG_D15: return ARM64_REG_B15;
|
||||
case ARM64_REG_D16: return ARM64_REG_B16;
|
||||
case ARM64_REG_D17: return ARM64_REG_B17;
|
||||
case ARM64_REG_D18: return ARM64_REG_B18;
|
||||
case ARM64_REG_D19: return ARM64_REG_B19;
|
||||
case ARM64_REG_D20: return ARM64_REG_B20;
|
||||
case ARM64_REG_D21: return ARM64_REG_B21;
|
||||
case ARM64_REG_D22: return ARM64_REG_B22;
|
||||
case ARM64_REG_D23: return ARM64_REG_B23;
|
||||
case ARM64_REG_D24: return ARM64_REG_B24;
|
||||
case ARM64_REG_D25: return ARM64_REG_B25;
|
||||
case ARM64_REG_D26: return ARM64_REG_B26;
|
||||
case ARM64_REG_D27: return ARM64_REG_B27;
|
||||
case ARM64_REG_D28: return ARM64_REG_B28;
|
||||
case ARM64_REG_D29: return ARM64_REG_B29;
|
||||
case ARM64_REG_D30: return ARM64_REG_B30;
|
||||
case ARM64_REG_D31: return ARM64_REG_B31;
|
||||
}
|
||||
|
||||
// For anything else, return it unchanged.
|
||||
return Reg;
|
||||
}
|
||||
|
||||
inline static unsigned getDRegFromBReg(unsigned Reg)
|
||||
{
|
||||
switch (Reg) {
|
||||
case ARM64_REG_B0: return ARM64_REG_D0;
|
||||
case ARM64_REG_B1: return ARM64_REG_D1;
|
||||
case ARM64_REG_B2: return ARM64_REG_D2;
|
||||
case ARM64_REG_B3: return ARM64_REG_D3;
|
||||
case ARM64_REG_B4: return ARM64_REG_D4;
|
||||
case ARM64_REG_B5: return ARM64_REG_D5;
|
||||
case ARM64_REG_B6: return ARM64_REG_D6;
|
||||
case ARM64_REG_B7: return ARM64_REG_D7;
|
||||
case ARM64_REG_B8: return ARM64_REG_D8;
|
||||
case ARM64_REG_B9: return ARM64_REG_D9;
|
||||
case ARM64_REG_B10: return ARM64_REG_D10;
|
||||
case ARM64_REG_B11: return ARM64_REG_D11;
|
||||
case ARM64_REG_B12: return ARM64_REG_D12;
|
||||
case ARM64_REG_B13: return ARM64_REG_D13;
|
||||
case ARM64_REG_B14: return ARM64_REG_D14;
|
||||
case ARM64_REG_B15: return ARM64_REG_D15;
|
||||
case ARM64_REG_B16: return ARM64_REG_D16;
|
||||
case ARM64_REG_B17: return ARM64_REG_D17;
|
||||
case ARM64_REG_B18: return ARM64_REG_D18;
|
||||
case ARM64_REG_B19: return ARM64_REG_D19;
|
||||
case ARM64_REG_B20: return ARM64_REG_D20;
|
||||
case ARM64_REG_B21: return ARM64_REG_D21;
|
||||
case ARM64_REG_B22: return ARM64_REG_D22;
|
||||
case ARM64_REG_B23: return ARM64_REG_D23;
|
||||
case ARM64_REG_B24: return ARM64_REG_D24;
|
||||
case ARM64_REG_B25: return ARM64_REG_D25;
|
||||
case ARM64_REG_B26: return ARM64_REG_D26;
|
||||
case ARM64_REG_B27: return ARM64_REG_D27;
|
||||
case ARM64_REG_B28: return ARM64_REG_D28;
|
||||
case ARM64_REG_B29: return ARM64_REG_D29;
|
||||
case ARM64_REG_B30: return ARM64_REG_D30;
|
||||
case ARM64_REG_B31: return ARM64_REG_D31;
|
||||
}
|
||||
|
||||
// For anything else, return it unchanged.
|
||||
return Reg;
|
||||
}
|
||||
|
||||
// // Enums corresponding to AArch64 condition codes
|
||||
// The CondCodes constants map directly to the 4-bit encoding of the
|
||||
// condition field for predicated instructions.
|
||||
typedef enum AArch64CC_CondCode { // Meaning (integer) Meaning (floating-point)
|
||||
AArch64CC_EQ = 0x0, // Equal Equal
|
||||
AArch64CC_NE = 0x1, // Not equal Not equal, or unordered
|
||||
AArch64CC_HS = 0x2, // Unsigned higher or same >, ==, or unordered
|
||||
AArch64CC_LO = 0x3, // Unsigned lower Less than
|
||||
AArch64CC_MI = 0x4, // Minus, negative Less than
|
||||
AArch64CC_PL = 0x5, // Plus, positive or zero >, ==, or unordered
|
||||
AArch64CC_VS = 0x6, // Overflow Unordered
|
||||
AArch64CC_VC = 0x7, // No overflow Not unordered
|
||||
AArch64CC_HI = 0x8, // Unsigned higher Greater than, or unordered
|
||||
AArch64CC_LS = 0x9, // Unsigned lower or same Less than or equal
|
||||
AArch64CC_GE = 0xa, // Greater than or equal Greater than or equal
|
||||
AArch64CC_LT = 0xb, // Less than Less than, or unordered
|
||||
AArch64CC_GT = 0xc, // Greater than Greater than
|
||||
AArch64CC_LE = 0xd, // Less than or equal <, ==, or unordered
|
||||
AArch64CC_AL = 0xe, // Always (unconditional) Always (unconditional)
|
||||
AArch64CC_NV = 0xf, // Always (unconditional) Always (unconditional)
|
||||
// Note the NV exists purely to disassemble 0b1111. Execution is "always".
|
||||
AArch64CC_Invalid
|
||||
} AArch64CC_CondCode;
|
||||
|
||||
inline static AArch64CC_CondCode getInvertedCondCode(AArch64CC_CondCode Code)
|
||||
{
|
||||
// To reverse a condition it's necessary to only invert the low bit:
|
||||
return (AArch64CC_CondCode)((unsigned)Code ^ 0x1);
|
||||
}
|
||||
|
||||
inline static const char *getCondCodeName(AArch64CC_CondCode CC)
|
||||
{
|
||||
switch (CC) {
|
||||
default: return NULL; // never reach
|
||||
case AArch64CC_EQ: return "eq";
|
||||
case AArch64CC_NE: return "ne";
|
||||
case AArch64CC_HS: return "hs";
|
||||
case AArch64CC_LO: return "lo";
|
||||
case AArch64CC_MI: return "mi";
|
||||
case AArch64CC_PL: return "pl";
|
||||
case AArch64CC_VS: return "vs";
|
||||
case AArch64CC_VC: return "vc";
|
||||
case AArch64CC_HI: return "hi";
|
||||
case AArch64CC_LS: return "ls";
|
||||
case AArch64CC_GE: return "ge";
|
||||
case AArch64CC_LT: return "lt";
|
||||
case AArch64CC_GT: return "gt";
|
||||
case AArch64CC_LE: return "le";
|
||||
case AArch64CC_AL: return "al";
|
||||
case AArch64CC_NV: return "nv";
|
||||
}
|
||||
}
|
||||
|
||||
/// Given a condition code, return NZCV flags that would satisfy that condition.
|
||||
/// The flag bits are in the format expected by the ccmp instructions.
|
||||
/// Note that many different flag settings can satisfy a given condition code,
|
||||
/// this function just returns one of them.
|
||||
inline static unsigned getNZCVToSatisfyCondCode(AArch64CC_CondCode Code)
|
||||
{
|
||||
// NZCV flags encoded as expected by ccmp instructions, ARMv8 ISA 5.5.7.
|
||||
enum { N = 8, Z = 4, C = 2, V = 1 };
|
||||
switch (Code) {
|
||||
default: // llvm_unreachable("Unknown condition code");
|
||||
case AArch64CC_EQ: return Z; // Z == 1
|
||||
case AArch64CC_NE: return 0; // Z == 0
|
||||
case AArch64CC_HS: return C; // C == 1
|
||||
case AArch64CC_LO: return 0; // C == 0
|
||||
case AArch64CC_MI: return N; // N == 1
|
||||
case AArch64CC_PL: return 0; // N == 0
|
||||
case AArch64CC_VS: return V; // V == 1
|
||||
case AArch64CC_VC: return 0; // V == 0
|
||||
case AArch64CC_HI: return C; // C == 1 && Z == 0
|
||||
case AArch64CC_LS: return 0; // C == 0 || Z == 1
|
||||
case AArch64CC_GE: return 0; // N == V
|
||||
case AArch64CC_LT: return N; // N != V
|
||||
case AArch64CC_GT: return 0; // Z == 0 && N == V
|
||||
case AArch64CC_LE: return Z; // Z == 1 || N != V
|
||||
}
|
||||
}
|
||||
|
||||
/// Instances of this class can perform bidirectional mapping from random
|
||||
/// identifier strings to operand encodings. For example "MSR" takes a named
|
||||
/// system-register which must be encoded somehow and decoded for printing. This
|
||||
/// central location means that the information for those transformations is not
|
||||
/// duplicated and remains in sync.
|
||||
///
|
||||
/// FIXME: currently the algorithm is a completely unoptimised linear
|
||||
/// search. Obviously this could be improved, but we would probably want to work
|
||||
/// out just how often these instructions are emitted before working on it. It
|
||||
/// might even be optimal to just reorder the tables for the common instructions
|
||||
/// rather than changing the algorithm.
|
||||
typedef struct A64NamedImmMapper_Mapping {
|
||||
const char *Name;
|
||||
uint32_t Value;
|
||||
} A64NamedImmMapper_Mapping;
|
||||
|
||||
typedef struct A64NamedImmMapper {
|
||||
const A64NamedImmMapper_Mapping *Pairs;
|
||||
size_t NumPairs;
|
||||
uint32_t TooBigImm;
|
||||
} A64NamedImmMapper;
|
||||
|
||||
typedef struct A64SysRegMapper {
|
||||
const A64NamedImmMapper_Mapping *SysRegPairs;
|
||||
const A64NamedImmMapper_Mapping *InstPairs;
|
||||
size_t NumInstPairs;
|
||||
} A64SysRegMapper;
|
||||
|
||||
typedef enum A64SE_ShiftExtSpecifiers {
|
||||
A64SE_Invalid = -1,
|
||||
A64SE_LSL,
|
||||
A64SE_MSL,
|
||||
A64SE_LSR,
|
||||
A64SE_ASR,
|
||||
A64SE_ROR,
|
||||
|
||||
A64SE_UXTB,
|
||||
A64SE_UXTH,
|
||||
A64SE_UXTW,
|
||||
A64SE_UXTX,
|
||||
|
||||
A64SE_SXTB,
|
||||
A64SE_SXTH,
|
||||
A64SE_SXTW,
|
||||
A64SE_SXTX
|
||||
} A64SE_ShiftExtSpecifiers;
|
||||
|
||||
typedef enum A64Layout_VectorLayout {
|
||||
A64Layout_Invalid = -1,
|
||||
A64Layout_VL_8B,
|
||||
A64Layout_VL_4H,
|
||||
A64Layout_VL_2S,
|
||||
A64Layout_VL_1D,
|
||||
|
||||
A64Layout_VL_16B,
|
||||
A64Layout_VL_8H,
|
||||
A64Layout_VL_4S,
|
||||
A64Layout_VL_2D,
|
||||
|
||||
// Bare layout for the 128-bit vector
|
||||
// (only show ".b", ".h", ".s", ".d" without vector number)
|
||||
A64Layout_VL_B,
|
||||
A64Layout_VL_H,
|
||||
A64Layout_VL_S,
|
||||
A64Layout_VL_D
|
||||
} A64Layout_VectorLayout;
|
||||
|
||||
inline static const char *
|
||||
AArch64VectorLayoutToString(A64Layout_VectorLayout Layout)
|
||||
{
|
||||
switch (Layout) {
|
||||
default: return NULL; // never reach
|
||||
case A64Layout_VL_8B: return ".8b";
|
||||
case A64Layout_VL_4H: return ".4h";
|
||||
case A64Layout_VL_2S: return ".2s";
|
||||
case A64Layout_VL_1D: return ".1d";
|
||||
case A64Layout_VL_16B: return ".16b";
|
||||
case A64Layout_VL_8H: return ".8h";
|
||||
case A64Layout_VL_4S: return ".4s";
|
||||
case A64Layout_VL_2D: return ".2d";
|
||||
case A64Layout_VL_B: return ".b";
|
||||
case A64Layout_VL_H: return ".h";
|
||||
case A64Layout_VL_S: return ".s";
|
||||
case A64Layout_VL_D: return ".d";
|
||||
}
|
||||
}
|
||||
|
||||
inline static A64Layout_VectorLayout
|
||||
AArch64StringToVectorLayout(char *LayoutStr)
|
||||
{
|
||||
if (!strcmp(LayoutStr, ".8b"))
|
||||
return A64Layout_VL_8B;
|
||||
|
||||
if (!strcmp(LayoutStr, ".4h"))
|
||||
return A64Layout_VL_4H;
|
||||
|
||||
if (!strcmp(LayoutStr, ".2s"))
|
||||
return A64Layout_VL_2S;
|
||||
|
||||
if (!strcmp(LayoutStr, ".1d"))
|
||||
return A64Layout_VL_1D;
|
||||
|
||||
if (!strcmp(LayoutStr, ".16b"))
|
||||
return A64Layout_VL_16B;
|
||||
|
||||
if (!strcmp(LayoutStr, ".8h"))
|
||||
return A64Layout_VL_8H;
|
||||
|
||||
if (!strcmp(LayoutStr, ".4s"))
|
||||
return A64Layout_VL_4S;
|
||||
|
||||
if (!strcmp(LayoutStr, ".2d"))
|
||||
return A64Layout_VL_2D;
|
||||
|
||||
if (!strcmp(LayoutStr, ".b"))
|
||||
return A64Layout_VL_B;
|
||||
|
||||
if (!strcmp(LayoutStr, ".s"))
|
||||
return A64Layout_VL_S;
|
||||
|
||||
if (!strcmp(LayoutStr, ".d"))
|
||||
return A64Layout_VL_D;
|
||||
|
||||
return A64Layout_Invalid;
|
||||
}
|
||||
|
||||
/// Target Operand Flag enum.
|
||||
enum TOF {
|
||||
//===------------------------------------------------------------------===//
|
||||
// AArch64 Specific MachineOperand flags.
|
||||
|
||||
MO_NO_FLAG,
|
||||
|
||||
MO_FRAGMENT = 0xf,
|
||||
|
||||
/// MO_PAGE - A symbol operand with this flag represents the pc-relative
|
||||
/// offset of the 4K page containing the symbol. This is used with the
|
||||
/// ADRP instruction.
|
||||
MO_PAGE = 1,
|
||||
|
||||
/// MO_PAGEOFF - A symbol operand with this flag represents the offset of
|
||||
/// that symbol within a 4K page. This offset is added to the page address
|
||||
/// to produce the complete address.
|
||||
MO_PAGEOFF = 2,
|
||||
|
||||
/// MO_G3 - A symbol operand with this flag (granule 3) represents the high
|
||||
/// 16-bits of a 64-bit address, used in a MOVZ or MOVK instruction
|
||||
MO_G3 = 3,
|
||||
|
||||
/// MO_G2 - A symbol operand with this flag (granule 2) represents the bits
|
||||
/// 32-47 of a 64-bit address, used in a MOVZ or MOVK instruction
|
||||
MO_G2 = 4,
|
||||
|
||||
/// MO_G1 - A symbol operand with this flag (granule 1) represents the bits
|
||||
/// 16-31 of a 64-bit address, used in a MOVZ or MOVK instruction
|
||||
MO_G1 = 5,
|
||||
|
||||
/// MO_G0 - A symbol operand with this flag (granule 0) represents the bits
|
||||
/// 0-15 of a 64-bit address, used in a MOVZ or MOVK instruction
|
||||
MO_G0 = 6,
|
||||
|
||||
/// MO_HI12 - This flag indicates that a symbol operand represents the bits
|
||||
/// 13-24 of a 64-bit address, used in a arithmetic immediate-shifted-left-
|
||||
/// by-12-bits instruction.
|
||||
MO_HI12 = 7,
|
||||
|
||||
/// MO_GOT - This flag indicates that a symbol operand represents the
|
||||
/// address of the GOT entry for the symbol, rather than the address of
|
||||
/// the symbol itself.
|
||||
MO_GOT = 0x10,
|
||||
|
||||
/// MO_NC - Indicates whether the linker is expected to check the symbol
|
||||
/// reference for overflow. For example in an ADRP/ADD pair of relocations
|
||||
/// the ADRP usually does check, but not the ADD.
|
||||
MO_NC = 0x20,
|
||||
|
||||
/// MO_TLS - Indicates that the operand being accessed is some kind of
|
||||
/// thread-local symbol. On Darwin, only one type of thread-local access
|
||||
/// exists (pre linker-relaxation), but on ELF the TLSModel used for the
|
||||
/// referee will affect interpretation.
|
||||
MO_TLS = 0x40,
|
||||
|
||||
/// MO_DLLIMPORT - On a symbol operand, this represents that the reference
|
||||
/// to the symbol is for an import stub. This is used for DLL import
|
||||
/// storage class indication on Windows.
|
||||
MO_DLLIMPORT = 0x80,
|
||||
};
|
||||
|
||||
typedef struct SysAlias {
|
||||
const char *Name;
|
||||
uint16_t Encoding;
|
||||
} SysAlias;
|
||||
|
||||
#define AT SysAlias
|
||||
#define DB SysAlias
|
||||
#define DC SysAlias
|
||||
#define SVEPRFM SysAlias
|
||||
#define PRFM SysAlias
|
||||
#define PSB SysAlias
|
||||
#define ISB SysAlias
|
||||
#define TSB SysAlias
|
||||
#define PState SysAlias
|
||||
#define SVEPREDPAT SysAlias
|
||||
#define SVCR SysAlias
|
||||
#define BTI SysAlias
|
||||
|
||||
typedef struct SysAliasReg {
|
||||
const char *Name;
|
||||
uint16_t Encoding;
|
||||
bool NeedsReg;
|
||||
} SysAliasReg;
|
||||
|
||||
#define IC SysAliasReg
|
||||
#define TLBI SysAliasReg
|
||||
|
||||
typedef struct SysAliasSysReg {
|
||||
const char *Name;
|
||||
uint16_t Encoding;
|
||||
bool Readable;
|
||||
bool Writeable;
|
||||
} SysAliasSysReg;
|
||||
|
||||
#define SysReg SysAliasSysReg
|
||||
|
||||
typedef struct SysAliasImm {
|
||||
const char *Name;
|
||||
uint16_t Encoding;
|
||||
uint16_t ImmValue;
|
||||
} SysAliasImm;
|
||||
|
||||
#define DBnXS SysAliasImm
|
||||
|
||||
typedef struct ExactFPImm {
|
||||
const char *Name;
|
||||
int Enum;
|
||||
const char *Repr;
|
||||
} ExactFPImm;
|
||||
|
||||
const AT *lookupATByEncoding(uint16_t Encoding);
|
||||
const DB *lookupDBByEncoding(uint16_t Encoding);
|
||||
const DC *lookupDCByEncoding(uint16_t Encoding);
|
||||
const IC *lookupICByEncoding(uint16_t Encoding);
|
||||
const TLBI *lookupTLBIByEncoding(uint16_t Encoding);
|
||||
const SVEPRFM *lookupSVEPRFMByEncoding(uint16_t Encoding);
|
||||
const PRFM *lookupPRFMByEncoding(uint16_t Encoding);
|
||||
const PSB *lookupPSBByEncoding(uint16_t Encoding);
|
||||
const ISB *lookupISBByEncoding(uint16_t Encoding);
|
||||
const TSB *lookupTSBByEncoding(uint16_t Encoding);
|
||||
const SysReg *lookupSysRegByEncoding(uint16_t Encoding);
|
||||
const PState *lookupPStateByEncoding(uint16_t Encoding);
|
||||
const SVEPREDPAT *lookupSVEPREDPATByEncoding(uint16_t Encoding);
|
||||
const ExactFPImm *lookupExactFPImmByEnum(uint16_t Encoding);
|
||||
const SVCR *lookupSVCRByEncoding(uint8_t Encoding);
|
||||
const BTI *lookupBTIByEncoding(uint8_t Encoding);
|
||||
const DBnXS *lookupDBnXSByEncoding(uint8_t Encoding);
|
||||
|
||||
// NOTE: result must be 128 bytes to contain the result
|
||||
void AArch64SysReg_genericRegisterString(uint32_t Bits, char *result);
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// The following Structs and Enum are taken from MCInstPrinter.h in llvm.
|
||||
// These are required for the updated printAliasInstr() function in
|
||||
// $ARCHGenAsmWriter.inc
|
||||
|
||||
/// Map from opcode to pattern list by binary search.
|
||||
typedef struct PatternsForOpcode {
|
||||
uint32_t Opcode;
|
||||
uint16_t PatternStart;
|
||||
uint16_t NumPatterns;
|
||||
} PatternsForOpcode;
|
||||
|
||||
/// Data for each alias pattern. Includes feature bits, string, number of
|
||||
/// operands, and a variadic list of conditions to check.
|
||||
typedef struct AliasPattern {
|
||||
uint32_t AsmStrOffset;
|
||||
uint32_t AliasCondStart;
|
||||
uint8_t NumOperands;
|
||||
uint8_t NumConds;
|
||||
} AliasPattern;
|
||||
|
||||
enum CondKind {
|
||||
AliasPatternCond_K_Feature, // Match only if a feature is enabled.
|
||||
AliasPatternCond_K_NegFeature, // Match only if a feature is disabled.
|
||||
AliasPatternCond_K_OrFeature, // Match only if one of a set of features is
|
||||
// enabled.
|
||||
AliasPatternCond_K_OrNegFeature, // Match only if one of a set of features is
|
||||
// disabled.
|
||||
AliasPatternCond_K_EndOrFeatures, // Note end of list of K_Or(Neg)?Features.
|
||||
AliasPatternCond_K_Ignore, // Match any operand.
|
||||
AliasPatternCond_K_Reg, // Match a specific register.
|
||||
AliasPatternCond_K_TiedReg, // Match another already matched register.
|
||||
AliasPatternCond_K_Imm, // Match a specific immediate.
|
||||
AliasPatternCond_K_RegClass, // Match registers in a class.
|
||||
AliasPatternCond_K_Custom, // Call custom matcher by index.
|
||||
};
|
||||
|
||||
typedef struct AliasPatternCond {
|
||||
int Kind;
|
||||
uint32_t Value;
|
||||
} AliasPatternCond;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#include "AArch64GenSystemOperands_enum.inc"
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,18 @@
|
||||
/* Capstone Disassembly Engine */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
|
||||
|
||||
#ifndef CS_AARCH64_DISASSEMBLER_H
|
||||
#define CS_AARCH64_DISASSEMBLER_H
|
||||
|
||||
#include "capstone/capstone.h"
|
||||
#include "../../MCRegisterInfo.h"
|
||||
#include "../../MCInst.h"
|
||||
|
||||
void AArch64_init(MCRegisterInfo *MRI);
|
||||
|
||||
bool AArch64_getInstruction(csh ud, const uint8_t *code, size_t code_len,
|
||||
MCInst *instr, uint16_t *size, uint64_t address, void *info);
|
||||
|
||||
uint64_t AArch64_getFeatureBits(int feature);
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,714 @@
|
||||
/* Capstone Disassembly Engine, http://www.capstone-engine.org */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
|
||||
|
||||
/// getRegisterName - This method is automatically generated by tblgen
|
||||
/// from the register set description. This returns the assembler name
|
||||
/// for the specified register.
|
||||
static const char *getRegisterName(unsigned RegNo, unsigned AltIdx)
|
||||
{
|
||||
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Woverlength-strings"
|
||||
#endif
|
||||
#ifndef CAPSTONE_DIET
|
||||
static const char AsmStrsNoRegAltName[] = {
|
||||
/* 0 */ "D7_D8_D9_D10\0"
|
||||
/* 13 */ "Q7_Q8_Q9_Q10\0"
|
||||
/* 26 */ "Z7_Z8_Z9_Z10\0"
|
||||
/* 39 */ "b10\0"
|
||||
/* 43 */ "d10\0"
|
||||
/* 47 */ "h10\0"
|
||||
/* 51 */ "p10\0"
|
||||
/* 55 */ "q10\0"
|
||||
/* 59 */ "s10\0"
|
||||
/* 63 */ "w10\0"
|
||||
/* 67 */ "x10\0"
|
||||
/* 71 */ "z10\0"
|
||||
/* 75 */ "D17_D18_D19_D20\0"
|
||||
/* 91 */ "Q17_Q18_Q19_Q20\0"
|
||||
/* 107 */ "Z17_Z18_Z19_Z20\0"
|
||||
/* 123 */ "b20\0"
|
||||
/* 127 */ "d20\0"
|
||||
/* 131 */ "h20\0"
|
||||
/* 135 */ "q20\0"
|
||||
/* 139 */ "s20\0"
|
||||
/* 143 */ "w20\0"
|
||||
/* 147 */ "x20\0"
|
||||
/* 151 */ "z20\0"
|
||||
/* 155 */ "D27_D28_D29_D30\0"
|
||||
/* 171 */ "Q27_Q28_Q29_Q30\0"
|
||||
/* 187 */ "Z27_Z28_Z29_Z30\0"
|
||||
/* 203 */ "b30\0"
|
||||
/* 207 */ "d30\0"
|
||||
/* 211 */ "h30\0"
|
||||
/* 215 */ "q30\0"
|
||||
/* 219 */ "s30\0"
|
||||
/* 223 */ "w30\0"
|
||||
/* 227 */ "x30\0"
|
||||
/* 231 */ "z30\0"
|
||||
/* 235 */ "D29_D30_D31_D0\0"
|
||||
/* 250 */ "Q29_Q30_Q31_Q0\0"
|
||||
/* 265 */ "Z29_Z30_Z31_Z0\0"
|
||||
/* 280 */ "b0\0"
|
||||
/* 283 */ "d0\0"
|
||||
/* 286 */ "h0\0"
|
||||
/* 289 */ "p0\0"
|
||||
/* 292 */ "q0\0"
|
||||
/* 295 */ "s0\0"
|
||||
/* 298 */ "w0\0"
|
||||
/* 301 */ "x0\0"
|
||||
/* 304 */ "z0\0"
|
||||
/* 307 */ "D8_D9_D10_D11\0"
|
||||
/* 321 */ "Q8_Q9_Q10_Q11\0"
|
||||
/* 335 */ "W10_W11\0"
|
||||
/* 343 */ "X4_X5_X6_X7_X8_X9_X10_X11\0"
|
||||
/* 369 */ "Z8_Z9_Z10_Z11\0"
|
||||
/* 383 */ "b11\0"
|
||||
/* 387 */ "d11\0"
|
||||
/* 391 */ "h11\0"
|
||||
/* 395 */ "p11\0"
|
||||
/* 399 */ "q11\0"
|
||||
/* 403 */ "s11\0"
|
||||
/* 407 */ "w11\0"
|
||||
/* 411 */ "x11\0"
|
||||
/* 415 */ "z11\0"
|
||||
/* 419 */ "D18_D19_D20_D21\0"
|
||||
/* 435 */ "Q18_Q19_Q20_Q21\0"
|
||||
/* 451 */ "W20_W21\0"
|
||||
/* 459 */ "X14_X15_X16_X17_X18_X19_X20_X21\0"
|
||||
/* 491 */ "Z18_Z19_Z20_Z21\0"
|
||||
/* 507 */ "b21\0"
|
||||
/* 511 */ "d21\0"
|
||||
/* 515 */ "h21\0"
|
||||
/* 519 */ "q21\0"
|
||||
/* 523 */ "s21\0"
|
||||
/* 527 */ "w21\0"
|
||||
/* 531 */ "x21\0"
|
||||
/* 535 */ "z21\0"
|
||||
/* 539 */ "D28_D29_D30_D31\0"
|
||||
/* 555 */ "Q28_Q29_Q30_Q31\0"
|
||||
/* 571 */ "Z28_Z29_Z30_Z31\0"
|
||||
/* 587 */ "b31\0"
|
||||
/* 591 */ "d31\0"
|
||||
/* 595 */ "h31\0"
|
||||
/* 599 */ "q31\0"
|
||||
/* 603 */ "s31\0"
|
||||
/* 607 */ "z31\0"
|
||||
/* 611 */ "D30_D31_D0_D1\0"
|
||||
/* 625 */ "Q30_Q31_Q0_Q1\0"
|
||||
/* 639 */ "W0_W1\0"
|
||||
/* 645 */ "X0_X1\0"
|
||||
/* 651 */ "Z30_Z31_Z0_Z1\0"
|
||||
/* 665 */ "b1\0"
|
||||
/* 668 */ "d1\0"
|
||||
/* 671 */ "h1\0"
|
||||
/* 674 */ "p1\0"
|
||||
/* 677 */ "q1\0"
|
||||
/* 680 */ "s1\0"
|
||||
/* 683 */ "w1\0"
|
||||
/* 686 */ "x1\0"
|
||||
/* 689 */ "z1\0"
|
||||
/* 692 */ "D9_D10_D11_D12\0"
|
||||
/* 707 */ "Q9_Q10_Q11_Q12\0"
|
||||
/* 722 */ "Z9_Z10_Z11_Z12\0"
|
||||
/* 737 */ "b12\0"
|
||||
/* 741 */ "d12\0"
|
||||
/* 745 */ "h12\0"
|
||||
/* 749 */ "p12\0"
|
||||
/* 753 */ "q12\0"
|
||||
/* 757 */ "s12\0"
|
||||
/* 761 */ "w12\0"
|
||||
/* 765 */ "x12\0"
|
||||
/* 769 */ "z12\0"
|
||||
/* 773 */ "D19_D20_D21_D22\0"
|
||||
/* 789 */ "Q19_Q20_Q21_Q22\0"
|
||||
/* 805 */ "Z19_Z20_Z21_Z22\0"
|
||||
/* 821 */ "b22\0"
|
||||
/* 825 */ "d22\0"
|
||||
/* 829 */ "h22\0"
|
||||
/* 833 */ "q22\0"
|
||||
/* 837 */ "s22\0"
|
||||
/* 841 */ "w22\0"
|
||||
/* 845 */ "x22\0"
|
||||
/* 849 */ "z22\0"
|
||||
/* 853 */ "D31_D0_D1_D2\0"
|
||||
/* 866 */ "Q31_Q0_Q1_Q2\0"
|
||||
/* 879 */ "Z31_Z0_Z1_Z2\0"
|
||||
/* 892 */ "b2\0"
|
||||
/* 895 */ "d2\0"
|
||||
/* 898 */ "h2\0"
|
||||
/* 901 */ "p2\0"
|
||||
/* 904 */ "q2\0"
|
||||
/* 907 */ "s2\0"
|
||||
/* 910 */ "w2\0"
|
||||
/* 913 */ "x2\0"
|
||||
/* 916 */ "z2\0"
|
||||
/* 919 */ "D10_D11_D12_D13\0"
|
||||
/* 935 */ "Q10_Q11_Q12_Q13\0"
|
||||
/* 951 */ "W12_W13\0"
|
||||
/* 959 */ "X6_X7_X8_X9_X10_X11_X12_X13\0"
|
||||
/* 987 */ "Z10_Z11_Z12_Z13\0"
|
||||
/* 1003 */ "b13\0"
|
||||
/* 1007 */ "d13\0"
|
||||
/* 1011 */ "h13\0"
|
||||
/* 1015 */ "p13\0"
|
||||
/* 1019 */ "q13\0"
|
||||
/* 1023 */ "s13\0"
|
||||
/* 1027 */ "w13\0"
|
||||
/* 1031 */ "x13\0"
|
||||
/* 1035 */ "z13\0"
|
||||
/* 1039 */ "D20_D21_D22_D23\0"
|
||||
/* 1055 */ "Q20_Q21_Q22_Q23\0"
|
||||
/* 1071 */ "W22_W23\0"
|
||||
/* 1079 */ "X16_X17_X18_X19_X20_X21_X22_X23\0"
|
||||
/* 1111 */ "Z20_Z21_Z22_Z23\0"
|
||||
/* 1127 */ "b23\0"
|
||||
/* 1131 */ "d23\0"
|
||||
/* 1135 */ "h23\0"
|
||||
/* 1139 */ "q23\0"
|
||||
/* 1143 */ "s23\0"
|
||||
/* 1147 */ "w23\0"
|
||||
/* 1151 */ "x23\0"
|
||||
/* 1155 */ "z23\0"
|
||||
/* 1159 */ "D0_D1_D2_D3\0"
|
||||
/* 1171 */ "Q0_Q1_Q2_Q3\0"
|
||||
/* 1183 */ "W2_W3\0"
|
||||
/* 1189 */ "X2_X3\0"
|
||||
/* 1195 */ "Z0_Z1_Z2_Z3\0"
|
||||
/* 1207 */ "b3\0"
|
||||
/* 1210 */ "d3\0"
|
||||
/* 1213 */ "h3\0"
|
||||
/* 1216 */ "p3\0"
|
||||
/* 1219 */ "q3\0"
|
||||
/* 1222 */ "s3\0"
|
||||
/* 1225 */ "w3\0"
|
||||
/* 1228 */ "x3\0"
|
||||
/* 1231 */ "z3\0"
|
||||
/* 1234 */ "D11_D12_D13_D14\0"
|
||||
/* 1250 */ "Q11_Q12_Q13_Q14\0"
|
||||
/* 1266 */ "Z11_Z12_Z13_Z14\0"
|
||||
/* 1282 */ "b14\0"
|
||||
/* 1286 */ "d14\0"
|
||||
/* 1290 */ "h14\0"
|
||||
/* 1294 */ "p14\0"
|
||||
/* 1298 */ "q14\0"
|
||||
/* 1302 */ "s14\0"
|
||||
/* 1306 */ "w14\0"
|
||||
/* 1310 */ "x14\0"
|
||||
/* 1314 */ "z14\0"
|
||||
/* 1318 */ "D21_D22_D23_D24\0"
|
||||
/* 1334 */ "Q21_Q22_Q23_Q24\0"
|
||||
/* 1350 */ "Z21_Z22_Z23_Z24\0"
|
||||
/* 1366 */ "b24\0"
|
||||
/* 1370 */ "d24\0"
|
||||
/* 1374 */ "h24\0"
|
||||
/* 1378 */ "q24\0"
|
||||
/* 1382 */ "s24\0"
|
||||
/* 1386 */ "w24\0"
|
||||
/* 1390 */ "x24\0"
|
||||
/* 1394 */ "z24\0"
|
||||
/* 1398 */ "D1_D2_D3_D4\0"
|
||||
/* 1410 */ "Q1_Q2_Q3_Q4\0"
|
||||
/* 1422 */ "Z1_Z2_Z3_Z4\0"
|
||||
/* 1434 */ "b4\0"
|
||||
/* 1437 */ "d4\0"
|
||||
/* 1440 */ "h4\0"
|
||||
/* 1443 */ "p4\0"
|
||||
/* 1446 */ "q4\0"
|
||||
/* 1449 */ "s4\0"
|
||||
/* 1452 */ "w4\0"
|
||||
/* 1455 */ "x4\0"
|
||||
/* 1458 */ "z4\0"
|
||||
/* 1461 */ "D12_D13_D14_D15\0"
|
||||
/* 1477 */ "Q12_Q13_Q14_Q15\0"
|
||||
/* 1493 */ "W14_W15\0"
|
||||
/* 1501 */ "X8_X9_X10_X11_X12_X13_X14_X15\0"
|
||||
/* 1531 */ "Z12_Z13_Z14_Z15\0"
|
||||
/* 1547 */ "b15\0"
|
||||
/* 1551 */ "d15\0"
|
||||
/* 1555 */ "h15\0"
|
||||
/* 1559 */ "p15\0"
|
||||
/* 1563 */ "q15\0"
|
||||
/* 1567 */ "s15\0"
|
||||
/* 1571 */ "w15\0"
|
||||
/* 1575 */ "x15\0"
|
||||
/* 1579 */ "z15\0"
|
||||
/* 1583 */ "D22_D23_D24_D25\0"
|
||||
/* 1599 */ "Q22_Q23_Q24_Q25\0"
|
||||
/* 1615 */ "W24_W25\0"
|
||||
/* 1623 */ "X18_X19_X20_X21_X22_X23_X24_X25\0"
|
||||
/* 1655 */ "Z22_Z23_Z24_Z25\0"
|
||||
/* 1671 */ "b25\0"
|
||||
/* 1675 */ "d25\0"
|
||||
/* 1679 */ "h25\0"
|
||||
/* 1683 */ "q25\0"
|
||||
/* 1687 */ "s25\0"
|
||||
/* 1691 */ "w25\0"
|
||||
/* 1695 */ "x25\0"
|
||||
/* 1699 */ "z25\0"
|
||||
/* 1703 */ "D2_D3_D4_D5\0"
|
||||
/* 1715 */ "Q2_Q3_Q4_Q5\0"
|
||||
/* 1727 */ "W4_W5\0"
|
||||
/* 1733 */ "X4_X5\0"
|
||||
/* 1739 */ "Z2_Z3_Z4_Z5\0"
|
||||
/* 1751 */ "b5\0"
|
||||
/* 1754 */ "d5\0"
|
||||
/* 1757 */ "h5\0"
|
||||
/* 1760 */ "p5\0"
|
||||
/* 1763 */ "q5\0"
|
||||
/* 1766 */ "s5\0"
|
||||
/* 1769 */ "w5\0"
|
||||
/* 1772 */ "x5\0"
|
||||
/* 1775 */ "z5\0"
|
||||
/* 1778 */ "D13_D14_D15_D16\0"
|
||||
/* 1794 */ "Q13_Q14_Q15_Q16\0"
|
||||
/* 1810 */ "Z13_Z14_Z15_Z16\0"
|
||||
/* 1826 */ "b16\0"
|
||||
/* 1830 */ "d16\0"
|
||||
/* 1834 */ "h16\0"
|
||||
/* 1838 */ "q16\0"
|
||||
/* 1842 */ "s16\0"
|
||||
/* 1846 */ "w16\0"
|
||||
/* 1850 */ "x16\0"
|
||||
/* 1854 */ "z16\0"
|
||||
/* 1858 */ "D23_D24_D25_D26\0"
|
||||
/* 1874 */ "Q23_Q24_Q25_Q26\0"
|
||||
/* 1890 */ "Z23_Z24_Z25_Z26\0"
|
||||
/* 1906 */ "b26\0"
|
||||
/* 1910 */ "d26\0"
|
||||
/* 1914 */ "h26\0"
|
||||
/* 1918 */ "q26\0"
|
||||
/* 1922 */ "s26\0"
|
||||
/* 1926 */ "w26\0"
|
||||
/* 1930 */ "x26\0"
|
||||
/* 1934 */ "z26\0"
|
||||
/* 1938 */ "D3_D4_D5_D6\0"
|
||||
/* 1950 */ "Q3_Q4_Q5_Q6\0"
|
||||
/* 1962 */ "Z3_Z4_Z5_Z6\0"
|
||||
/* 1974 */ "b6\0"
|
||||
/* 1977 */ "d6\0"
|
||||
/* 1980 */ "h6\0"
|
||||
/* 1983 */ "p6\0"
|
||||
/* 1986 */ "q6\0"
|
||||
/* 1989 */ "s6\0"
|
||||
/* 1992 */ "w6\0"
|
||||
/* 1995 */ "x6\0"
|
||||
/* 1998 */ "z6\0"
|
||||
/* 2001 */ "D14_D15_D16_D17\0"
|
||||
/* 2017 */ "Q14_Q15_Q16_Q17\0"
|
||||
/* 2033 */ "W16_W17\0"
|
||||
/* 2041 */ "X10_X11_X12_X13_X14_X15_X16_X17\0"
|
||||
/* 2073 */ "Z14_Z15_Z16_Z17\0"
|
||||
/* 2089 */ "b17\0"
|
||||
/* 2093 */ "d17\0"
|
||||
/* 2097 */ "h17\0"
|
||||
/* 2101 */ "q17\0"
|
||||
/* 2105 */ "s17\0"
|
||||
/* 2109 */ "w17\0"
|
||||
/* 2113 */ "x17\0"
|
||||
/* 2117 */ "z17\0"
|
||||
/* 2121 */ "D24_D25_D26_D27\0"
|
||||
/* 2137 */ "Q24_Q25_Q26_Q27\0"
|
||||
/* 2153 */ "W26_W27\0"
|
||||
/* 2161 */ "X20_X21_X22_X23_X24_X25_X26_X27\0"
|
||||
/* 2193 */ "Z24_Z25_Z26_Z27\0"
|
||||
/* 2209 */ "b27\0"
|
||||
/* 2213 */ "d27\0"
|
||||
/* 2217 */ "h27\0"
|
||||
/* 2221 */ "q27\0"
|
||||
/* 2225 */ "s27\0"
|
||||
/* 2229 */ "w27\0"
|
||||
/* 2233 */ "x27\0"
|
||||
/* 2237 */ "z27\0"
|
||||
/* 2241 */ "D4_D5_D6_D7\0"
|
||||
/* 2253 */ "Q4_Q5_Q6_Q7\0"
|
||||
/* 2265 */ "W6_W7\0"
|
||||
/* 2271 */ "X0_X1_X2_X3_X4_X5_X6_X7\0"
|
||||
/* 2295 */ "Z4_Z5_Z6_Z7\0"
|
||||
/* 2307 */ "b7\0"
|
||||
/* 2310 */ "d7\0"
|
||||
/* 2313 */ "h7\0"
|
||||
/* 2316 */ "p7\0"
|
||||
/* 2319 */ "q7\0"
|
||||
/* 2322 */ "s7\0"
|
||||
/* 2325 */ "w7\0"
|
||||
/* 2328 */ "x7\0"
|
||||
/* 2331 */ "z7\0"
|
||||
/* 2334 */ "D15_D16_D17_D18\0"
|
||||
/* 2350 */ "Q15_Q16_Q17_Q18\0"
|
||||
/* 2366 */ "Z15_Z16_Z17_Z18\0"
|
||||
/* 2382 */ "b18\0"
|
||||
/* 2386 */ "d18\0"
|
||||
/* 2390 */ "h18\0"
|
||||
/* 2394 */ "q18\0"
|
||||
/* 2398 */ "s18\0"
|
||||
/* 2402 */ "w18\0"
|
||||
/* 2406 */ "x18\0"
|
||||
/* 2410 */ "z18\0"
|
||||
/* 2414 */ "D25_D26_D27_D28\0"
|
||||
/* 2430 */ "Q25_Q26_Q27_Q28\0"
|
||||
/* 2446 */ "Z25_Z26_Z27_Z28\0"
|
||||
/* 2462 */ "b28\0"
|
||||
/* 2466 */ "d28\0"
|
||||
/* 2470 */ "h28\0"
|
||||
/* 2474 */ "q28\0"
|
||||
/* 2478 */ "s28\0"
|
||||
/* 2482 */ "w28\0"
|
||||
/* 2486 */ "x28\0"
|
||||
/* 2490 */ "z28\0"
|
||||
/* 2494 */ "D5_D6_D7_D8\0"
|
||||
/* 2506 */ "Q5_Q6_Q7_Q8\0"
|
||||
/* 2518 */ "Z5_Z6_Z7_Z8\0"
|
||||
/* 2530 */ "b8\0"
|
||||
/* 2533 */ "d8\0"
|
||||
/* 2536 */ "h8\0"
|
||||
/* 2539 */ "p8\0"
|
||||
/* 2542 */ "q8\0"
|
||||
/* 2545 */ "s8\0"
|
||||
/* 2548 */ "w8\0"
|
||||
/* 2551 */ "x8\0"
|
||||
/* 2554 */ "z8\0"
|
||||
/* 2557 */ "D16_D17_D18_D19\0"
|
||||
/* 2573 */ "Q16_Q17_Q18_Q19\0"
|
||||
/* 2589 */ "W18_W19\0"
|
||||
/* 2597 */ "X12_X13_X14_X15_X16_X17_X18_X19\0"
|
||||
/* 2629 */ "Z16_Z17_Z18_Z19\0"
|
||||
/* 2645 */ "b19\0"
|
||||
/* 2649 */ "d19\0"
|
||||
/* 2653 */ "h19\0"
|
||||
/* 2657 */ "q19\0"
|
||||
/* 2661 */ "s19\0"
|
||||
/* 2665 */ "w19\0"
|
||||
/* 2669 */ "x19\0"
|
||||
/* 2673 */ "z19\0"
|
||||
/* 2677 */ "D26_D27_D28_D29\0"
|
||||
/* 2693 */ "Q26_Q27_Q28_Q29\0"
|
||||
/* 2709 */ "W28_W29\0"
|
||||
/* 2717 */ "Z26_Z27_Z28_Z29\0"
|
||||
/* 2733 */ "b29\0"
|
||||
/* 2737 */ "d29\0"
|
||||
/* 2741 */ "h29\0"
|
||||
/* 2745 */ "q29\0"
|
||||
/* 2749 */ "s29\0"
|
||||
/* 2753 */ "w29\0"
|
||||
/* 2757 */ "x29\0"
|
||||
/* 2761 */ "z29\0"
|
||||
/* 2765 */ "D6_D7_D8_D9\0"
|
||||
/* 2777 */ "Q6_Q7_Q8_Q9\0"
|
||||
/* 2789 */ "W8_W9\0"
|
||||
/* 2795 */ "X2_X3_X4_X5_X6_X7_X8_X9\0"
|
||||
/* 2819 */ "Z6_Z7_Z8_Z9\0"
|
||||
/* 2831 */ "b9\0"
|
||||
/* 2834 */ "d9\0"
|
||||
/* 2837 */ "h9\0"
|
||||
/* 2840 */ "p9\0"
|
||||
/* 2843 */ "q9\0"
|
||||
/* 2846 */ "s9\0"
|
||||
/* 2849 */ "w9\0"
|
||||
/* 2852 */ "x9\0"
|
||||
/* 2855 */ "z9\0"
|
||||
/* 2858 */ "X22_X23_X24_X25_X26_X27_X28_FP\0"
|
||||
/* 2889 */ "W30_WZR\0"
|
||||
/* 2897 */ "LR_XZR\0"
|
||||
/* 2904 */ "za\0"
|
||||
/* 2907 */ "za0.b\0"
|
||||
/* 2913 */ "za0.d\0"
|
||||
/* 2919 */ "za1.d\0"
|
||||
/* 2925 */ "za2.d\0"
|
||||
/* 2931 */ "za3.d\0"
|
||||
/* 2937 */ "za4.d\0"
|
||||
/* 2943 */ "za5.d\0"
|
||||
/* 2949 */ "za6.d\0"
|
||||
/* 2955 */ "za7.d\0"
|
||||
/* 2961 */ "vg\0"
|
||||
/* 2964 */ "za0.h\0"
|
||||
/* 2970 */ "za1.h\0"
|
||||
/* 2976 */ "z10_hi\0"
|
||||
/* 2983 */ "z20_hi\0"
|
||||
/* 2990 */ "z30_hi\0"
|
||||
/* 2997 */ "z0_hi\0"
|
||||
/* 3003 */ "z11_hi\0"
|
||||
/* 3010 */ "z21_hi\0"
|
||||
/* 3017 */ "z31_hi\0"
|
||||
/* 3024 */ "z1_hi\0"
|
||||
/* 3030 */ "z12_hi\0"
|
||||
/* 3037 */ "z22_hi\0"
|
||||
/* 3044 */ "z2_hi\0"
|
||||
/* 3050 */ "z13_hi\0"
|
||||
/* 3057 */ "z23_hi\0"
|
||||
/* 3064 */ "z3_hi\0"
|
||||
/* 3070 */ "z14_hi\0"
|
||||
/* 3077 */ "z24_hi\0"
|
||||
/* 3084 */ "z4_hi\0"
|
||||
/* 3090 */ "z15_hi\0"
|
||||
/* 3097 */ "z25_hi\0"
|
||||
/* 3104 */ "z5_hi\0"
|
||||
/* 3110 */ "z16_hi\0"
|
||||
/* 3117 */ "z26_hi\0"
|
||||
/* 3124 */ "z6_hi\0"
|
||||
/* 3130 */ "z17_hi\0"
|
||||
/* 3137 */ "z27_hi\0"
|
||||
/* 3144 */ "z7_hi\0"
|
||||
/* 3150 */ "z18_hi\0"
|
||||
/* 3157 */ "z28_hi\0"
|
||||
/* 3164 */ "z8_hi\0"
|
||||
/* 3170 */ "z19_hi\0"
|
||||
/* 3177 */ "z29_hi\0"
|
||||
/* 3184 */ "z9_hi\0"
|
||||
/* 3190 */ "wsp\0"
|
||||
/* 3194 */ "za10.q\0"
|
||||
/* 3201 */ "za0.q\0"
|
||||
/* 3207 */ "za11.q\0"
|
||||
/* 3214 */ "za1.q\0"
|
||||
/* 3220 */ "za12.q\0"
|
||||
/* 3227 */ "za2.q\0"
|
||||
/* 3233 */ "za13.q\0"
|
||||
/* 3240 */ "za3.q\0"
|
||||
/* 3246 */ "za14.q\0"
|
||||
/* 3253 */ "za4.q\0"
|
||||
/* 3259 */ "za15.q\0"
|
||||
/* 3266 */ "za5.q\0"
|
||||
/* 3272 */ "za6.q\0"
|
||||
/* 3278 */ "za7.q\0"
|
||||
/* 3284 */ "za8.q\0"
|
||||
/* 3290 */ "za9.q\0"
|
||||
/* 3296 */ "ffr\0"
|
||||
/* 3300 */ "wzr\0"
|
||||
/* 3304 */ "xzr\0"
|
||||
/* 3308 */ "za0.s\0"
|
||||
/* 3314 */ "za1.s\0"
|
||||
/* 3320 */ "za2.s\0"
|
||||
/* 3326 */ "za3.s\0"
|
||||
/* 3332 */ "nzcv\0"
|
||||
};
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
static const uint16_t RegAsmOffsetNoRegAltName[] = {
|
||||
3296, 2757, 227, 3332, 3191, 2961, 3190, 3300, 3304, 2904, 280, 665, 892, 1207,
|
||||
1434, 1751, 1974, 2307, 2530, 2831, 39, 383, 737, 1003, 1282, 1547, 1826, 2089,
|
||||
2382, 2645, 123, 507, 821, 1127, 1366, 1671, 1906, 2209, 2462, 2733, 203, 587,
|
||||
283, 668, 895, 1210, 1437, 1754, 1977, 2310, 2533, 2834, 43, 387, 741, 1007,
|
||||
1286, 1551, 1830, 2093, 2386, 2649, 127, 511, 825, 1131, 1370, 1675, 1910, 2213,
|
||||
2466, 2737, 207, 591, 286, 671, 898, 1213, 1440, 1757, 1980, 2313, 2536, 2837,
|
||||
47, 391, 745, 1011, 1290, 1555, 1834, 2097, 2390, 2653, 131, 515, 829, 1135,
|
||||
1374, 1679, 1914, 2217, 2470, 2741, 211, 595, 289, 674, 901, 1216, 1443, 1760,
|
||||
1983, 2316, 2539, 2840, 51, 395, 749, 1015, 1294, 1559, 292, 677, 904, 1219,
|
||||
1446, 1763, 1986, 2319, 2542, 2843, 55, 399, 753, 1019, 1298, 1563, 1838, 2101,
|
||||
2394, 2657, 135, 519, 833, 1139, 1378, 1683, 1918, 2221, 2474, 2745, 215, 599,
|
||||
295, 680, 907, 1222, 1449, 1766, 1989, 2322, 2545, 2846, 59, 403, 757, 1023,
|
||||
1302, 1567, 1842, 2105, 2398, 2661, 139, 523, 837, 1143, 1382, 1687, 1922, 2225,
|
||||
2478, 2749, 219, 603, 298, 683, 910, 1225, 1452, 1769, 1992, 2325, 2548, 2849,
|
||||
63, 407, 761, 1027, 1306, 1571, 1846, 2109, 2402, 2665, 143, 527, 841, 1147,
|
||||
1386, 1691, 1926, 2229, 2482, 2753, 223, 301, 686, 913, 1228, 1455, 1772, 1995,
|
||||
2328, 2551, 2852, 67, 411, 765, 1031, 1310, 1575, 1850, 2113, 2406, 2669, 147,
|
||||
531, 845, 1151, 1390, 1695, 1930, 2233, 2486, 304, 689, 916, 1231, 1458, 1775,
|
||||
1998, 2331, 2554, 2855, 71, 415, 769, 1035, 1314, 1579, 1854, 2117, 2410, 2673,
|
||||
151, 535, 849, 1155, 1394, 1699, 1934, 2237, 2490, 2761, 231, 607, 2907, 2913,
|
||||
2919, 2925, 2931, 2937, 2943, 2949, 2955, 2964, 2970, 3201, 3214, 3227, 3240, 3253,
|
||||
3266, 3272, 3278, 3284, 3290, 3194, 3207, 3220, 3233, 3246, 3259, 3308, 3314, 3320,
|
||||
3326, 2997, 3024, 3044, 3064, 3084, 3104, 3124, 3144, 3164, 3184, 2976, 3003, 3030,
|
||||
3050, 3070, 3090, 3110, 3130, 3150, 3170, 2983, 3010, 3037, 3057, 3077, 3097, 3117,
|
||||
3137, 3157, 3177, 2990, 3017, 619, 860, 1165, 1404, 1709, 1944, 2247, 2500, 2771,
|
||||
6, 313, 699, 927, 1242, 1469, 1786, 2009, 2342, 2565, 83, 427, 781, 1047,
|
||||
1326, 1591, 1866, 2129, 2422, 2685, 163, 547, 243, 1159, 1398, 1703, 1938, 2241,
|
||||
2494, 2765, 0, 307, 692, 919, 1234, 1461, 1778, 2001, 2334, 2557, 75, 419,
|
||||
773, 1039, 1318, 1583, 1858, 2121, 2414, 2677, 155, 539, 235, 611, 853, 857,
|
||||
1162, 1401, 1706, 1941, 2244, 2497, 2768, 3, 310, 695, 923, 1238, 1465, 1782,
|
||||
2005, 2338, 2561, 79, 423, 777, 1043, 1322, 1587, 1862, 2125, 2418, 2681, 159,
|
||||
543, 239, 615, 633, 873, 1177, 1416, 1721, 1956, 2259, 2512, 2783, 19, 327,
|
||||
714, 943, 1258, 1485, 1802, 2025, 2358, 2581, 99, 443, 797, 1063, 1342, 1607,
|
||||
1882, 2145, 2438, 2701, 179, 563, 258, 1171, 1410, 1715, 1950, 2253, 2506, 2777,
|
||||
13, 321, 707, 935, 1250, 1477, 1794, 2017, 2350, 2573, 91, 435, 789, 1055,
|
||||
1334, 1599, 1874, 2137, 2430, 2693, 171, 555, 250, 625, 866, 870, 1174, 1413,
|
||||
1718, 1953, 2256, 2509, 2780, 16, 324, 710, 939, 1254, 1481, 1798, 2021, 2354,
|
||||
2577, 95, 439, 793, 1059, 1338, 1603, 1878, 2141, 2434, 2697, 175, 559, 254,
|
||||
629, 2858, 2271, 2795, 343, 959, 1501, 2041, 2597, 459, 1079, 1623, 2161, 2889,
|
||||
639, 1183, 1727, 2265, 2789, 335, 951, 1493, 2033, 2589, 451, 1071, 1615, 2153,
|
||||
2709, 2897, 2882, 645, 1189, 1733, 2289, 2813, 361, 979, 1523, 2065, 2621, 483,
|
||||
1103, 1647, 2185, 659, 886, 1201, 1428, 1745, 1968, 2301, 2524, 2825, 32, 375,
|
||||
729, 995, 1274, 1539, 1818, 2081, 2374, 2637, 115, 499, 813, 1119, 1358, 1663,
|
||||
1898, 2201, 2454, 2725, 195, 579, 273, 1195, 1422, 1739, 1962, 2295, 2518, 2819,
|
||||
26, 369, 722, 987, 1266, 1531, 1810, 2073, 2366, 2629, 107, 491, 805, 1111,
|
||||
1350, 1655, 1890, 2193, 2446, 2717, 187, 571, 265, 651, 879, 883, 1198, 1425,
|
||||
1742, 1965, 2298, 2521, 2822, 29, 372, 725, 991, 1270, 1535, 1814, 2077, 2370,
|
||||
2633, 111, 495, 809, 1115, 1354, 1659, 1894, 2197, 2450, 2721, 191, 575, 269,
|
||||
655,
|
||||
};
|
||||
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Woverlength-strings"
|
||||
#endif
|
||||
static const char AsmStrsvlist1[] = {
|
||||
/* 0 */ "\0"
|
||||
};
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
static const uint8_t RegAsmOffsetvlist1[] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0,
|
||||
};
|
||||
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Woverlength-strings"
|
||||
#endif
|
||||
static const char AsmStrsvreg[] = {
|
||||
/* 0 */ "v10\0"
|
||||
/* 4 */ "v20\0"
|
||||
/* 8 */ "v30\0"
|
||||
/* 12 */ "v0\0"
|
||||
/* 15 */ "v11\0"
|
||||
/* 19 */ "v21\0"
|
||||
/* 23 */ "v31\0"
|
||||
/* 27 */ "v1\0"
|
||||
/* 30 */ "v12\0"
|
||||
/* 34 */ "v22\0"
|
||||
/* 38 */ "v2\0"
|
||||
/* 41 */ "v13\0"
|
||||
/* 45 */ "v23\0"
|
||||
/* 49 */ "v3\0"
|
||||
/* 52 */ "v14\0"
|
||||
/* 56 */ "v24\0"
|
||||
/* 60 */ "v4\0"
|
||||
/* 63 */ "v15\0"
|
||||
/* 67 */ "v25\0"
|
||||
/* 71 */ "v5\0"
|
||||
/* 74 */ "v16\0"
|
||||
/* 78 */ "v26\0"
|
||||
/* 82 */ "v6\0"
|
||||
/* 85 */ "v17\0"
|
||||
/* 89 */ "v27\0"
|
||||
/* 93 */ "v7\0"
|
||||
/* 96 */ "v18\0"
|
||||
/* 100 */ "v28\0"
|
||||
/* 104 */ "v8\0"
|
||||
/* 107 */ "v19\0"
|
||||
/* 111 */ "v29\0"
|
||||
/* 115 */ "v9\0"
|
||||
};
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
static const uint8_t RegAsmOffsetvreg[] = {
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
12, 27, 38, 49, 60, 71, 82, 93, 104, 115, 0, 15, 30, 41,
|
||||
52, 63, 74, 85, 96, 107, 4, 19, 34, 45, 56, 67, 78, 89,
|
||||
100, 111, 8, 23, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 12, 27, 38, 49,
|
||||
60, 71, 82, 93, 104, 115, 0, 15, 30, 41, 52, 63, 74, 85,
|
||||
96, 107, 4, 19, 34, 45, 56, 67, 78, 89, 100, 111, 8, 23,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 12, 27, 38, 49, 60, 71, 82, 93, 104,
|
||||
115, 0, 15, 30, 41, 52, 63, 74, 85, 96, 107, 4, 19, 34,
|
||||
45, 56, 67, 78, 89, 100, 111, 8, 23, 12, 27, 38, 49, 60,
|
||||
71, 82, 93, 104, 115, 0, 15, 30, 41, 52, 63, 74, 85, 96,
|
||||
107, 4, 19, 34, 45, 56, 67, 78, 89, 100, 111, 8, 23, 12,
|
||||
27, 38, 49, 60, 71, 82, 93, 104, 115, 0, 15, 30, 41, 52,
|
||||
63, 74, 85, 96, 107, 4, 19, 34, 45, 56, 67, 78, 89, 100,
|
||||
111, 8, 23, 12, 27, 38, 49, 60, 71, 82, 93, 104, 115, 0,
|
||||
15, 30, 41, 52, 63, 74, 85, 96, 107, 4, 19, 34, 45, 56,
|
||||
67, 78, 89, 100, 111, 8, 23, 12, 27, 38, 49, 60, 71, 82,
|
||||
93, 104, 115, 0, 15, 30, 41, 52, 63, 74, 85, 96, 107, 4,
|
||||
19, 34, 45, 56, 67, 78, 89, 100, 111, 8, 23, 12, 27, 38,
|
||||
49, 60, 71, 82, 93, 104, 115, 0, 15, 30, 41, 52, 63, 74,
|
||||
85, 96, 107, 4, 19, 34, 45, 56, 67, 78, 89, 100, 111, 8,
|
||||
23, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3,
|
||||
};
|
||||
|
||||
switch(AltIdx) {
|
||||
default:
|
||||
return (const char *)(sizeof(RegAsmOffsetvreg)/sizeof(RegAsmOffsetvreg[0]));
|
||||
case AArch64_NoRegAltName:
|
||||
return AsmStrsNoRegAltName+RegAsmOffsetNoRegAltName[RegNo-1];
|
||||
case AArch64_vlist1:
|
||||
return AsmStrsvlist1+RegAsmOffsetvlist1[RegNo-1];
|
||||
case AArch64_vreg:
|
||||
return AsmStrsvreg+RegAsmOffsetvreg[RegNo-1];
|
||||
}
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,673 @@
|
||||
// size = 673
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
ARM64_REG_V0,
|
||||
ARM64_REG_V1,
|
||||
ARM64_REG_V2,
|
||||
ARM64_REG_V3,
|
||||
ARM64_REG_V4,
|
||||
ARM64_REG_V5,
|
||||
ARM64_REG_V6,
|
||||
ARM64_REG_V7,
|
||||
ARM64_REG_V8,
|
||||
ARM64_REG_V9,
|
||||
ARM64_REG_V10,
|
||||
ARM64_REG_V11,
|
||||
ARM64_REG_V12,
|
||||
ARM64_REG_V13,
|
||||
ARM64_REG_V14,
|
||||
ARM64_REG_V15,
|
||||
ARM64_REG_V16,
|
||||
ARM64_REG_V17,
|
||||
ARM64_REG_V18,
|
||||
ARM64_REG_V19,
|
||||
ARM64_REG_V20,
|
||||
ARM64_REG_V21,
|
||||
ARM64_REG_V22,
|
||||
ARM64_REG_V23,
|
||||
ARM64_REG_V24,
|
||||
ARM64_REG_V25,
|
||||
ARM64_REG_V26,
|
||||
ARM64_REG_V27,
|
||||
ARM64_REG_V28,
|
||||
ARM64_REG_V29,
|
||||
ARM64_REG_V30,
|
||||
ARM64_REG_V31,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
ARM64_REG_V0,
|
||||
ARM64_REG_V1,
|
||||
ARM64_REG_V2,
|
||||
ARM64_REG_V3,
|
||||
ARM64_REG_V4,
|
||||
ARM64_REG_V5,
|
||||
ARM64_REG_V6,
|
||||
ARM64_REG_V7,
|
||||
ARM64_REG_V8,
|
||||
ARM64_REG_V9,
|
||||
ARM64_REG_V10,
|
||||
ARM64_REG_V11,
|
||||
ARM64_REG_V12,
|
||||
ARM64_REG_V13,
|
||||
ARM64_REG_V14,
|
||||
ARM64_REG_V15,
|
||||
ARM64_REG_V16,
|
||||
ARM64_REG_V17,
|
||||
ARM64_REG_V18,
|
||||
ARM64_REG_V19,
|
||||
ARM64_REG_V20,
|
||||
ARM64_REG_V21,
|
||||
ARM64_REG_V22,
|
||||
ARM64_REG_V23,
|
||||
ARM64_REG_V24,
|
||||
ARM64_REG_V25,
|
||||
ARM64_REG_V26,
|
||||
ARM64_REG_V27,
|
||||
ARM64_REG_V28,
|
||||
ARM64_REG_V29,
|
||||
ARM64_REG_V30,
|
||||
ARM64_REG_V31,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
ARM64_REG_V0,
|
||||
ARM64_REG_V1,
|
||||
ARM64_REG_V2,
|
||||
ARM64_REG_V3,
|
||||
ARM64_REG_V4,
|
||||
ARM64_REG_V5,
|
||||
ARM64_REG_V6,
|
||||
ARM64_REG_V7,
|
||||
ARM64_REG_V8,
|
||||
ARM64_REG_V9,
|
||||
ARM64_REG_V10,
|
||||
ARM64_REG_V11,
|
||||
ARM64_REG_V12,
|
||||
ARM64_REG_V13,
|
||||
ARM64_REG_V14,
|
||||
ARM64_REG_V15,
|
||||
ARM64_REG_V16,
|
||||
ARM64_REG_V17,
|
||||
ARM64_REG_V18,
|
||||
ARM64_REG_V19,
|
||||
ARM64_REG_V20,
|
||||
ARM64_REG_V21,
|
||||
ARM64_REG_V22,
|
||||
ARM64_REG_V23,
|
||||
ARM64_REG_V24,
|
||||
ARM64_REG_V25,
|
||||
ARM64_REG_V26,
|
||||
ARM64_REG_V27,
|
||||
ARM64_REG_V28,
|
||||
ARM64_REG_V29,
|
||||
ARM64_REG_V30,
|
||||
ARM64_REG_V31,
|
||||
ARM64_REG_V0,
|
||||
ARM64_REG_V1,
|
||||
ARM64_REG_V2,
|
||||
ARM64_REG_V3,
|
||||
ARM64_REG_V4,
|
||||
ARM64_REG_V5,
|
||||
ARM64_REG_V6,
|
||||
ARM64_REG_V7,
|
||||
ARM64_REG_V8,
|
||||
ARM64_REG_V9,
|
||||
ARM64_REG_V10,
|
||||
ARM64_REG_V11,
|
||||
ARM64_REG_V12,
|
||||
ARM64_REG_V13,
|
||||
ARM64_REG_V14,
|
||||
ARM64_REG_V15,
|
||||
ARM64_REG_V16,
|
||||
ARM64_REG_V17,
|
||||
ARM64_REG_V18,
|
||||
ARM64_REG_V19,
|
||||
ARM64_REG_V20,
|
||||
ARM64_REG_V21,
|
||||
ARM64_REG_V22,
|
||||
ARM64_REG_V23,
|
||||
ARM64_REG_V24,
|
||||
ARM64_REG_V25,
|
||||
ARM64_REG_V26,
|
||||
ARM64_REG_V27,
|
||||
ARM64_REG_V28,
|
||||
ARM64_REG_V29,
|
||||
ARM64_REG_V30,
|
||||
ARM64_REG_V31,
|
||||
ARM64_REG_V0,
|
||||
ARM64_REG_V1,
|
||||
ARM64_REG_V2,
|
||||
ARM64_REG_V3,
|
||||
ARM64_REG_V4,
|
||||
ARM64_REG_V5,
|
||||
ARM64_REG_V6,
|
||||
ARM64_REG_V7,
|
||||
ARM64_REG_V8,
|
||||
ARM64_REG_V9,
|
||||
ARM64_REG_V10,
|
||||
ARM64_REG_V11,
|
||||
ARM64_REG_V12,
|
||||
ARM64_REG_V13,
|
||||
ARM64_REG_V14,
|
||||
ARM64_REG_V15,
|
||||
ARM64_REG_V16,
|
||||
ARM64_REG_V17,
|
||||
ARM64_REG_V18,
|
||||
ARM64_REG_V19,
|
||||
ARM64_REG_V20,
|
||||
ARM64_REG_V21,
|
||||
ARM64_REG_V22,
|
||||
ARM64_REG_V23,
|
||||
ARM64_REG_V24,
|
||||
ARM64_REG_V25,
|
||||
ARM64_REG_V26,
|
||||
ARM64_REG_V27,
|
||||
ARM64_REG_V28,
|
||||
ARM64_REG_V29,
|
||||
ARM64_REG_V30,
|
||||
ARM64_REG_V31,
|
||||
ARM64_REG_V0,
|
||||
ARM64_REG_V1,
|
||||
ARM64_REG_V2,
|
||||
ARM64_REG_V3,
|
||||
ARM64_REG_V4,
|
||||
ARM64_REG_V5,
|
||||
ARM64_REG_V6,
|
||||
ARM64_REG_V7,
|
||||
ARM64_REG_V8,
|
||||
ARM64_REG_V9,
|
||||
ARM64_REG_V10,
|
||||
ARM64_REG_V11,
|
||||
ARM64_REG_V12,
|
||||
ARM64_REG_V13,
|
||||
ARM64_REG_V14,
|
||||
ARM64_REG_V15,
|
||||
ARM64_REG_V16,
|
||||
ARM64_REG_V17,
|
||||
ARM64_REG_V18,
|
||||
ARM64_REG_V19,
|
||||
ARM64_REG_V20,
|
||||
ARM64_REG_V21,
|
||||
ARM64_REG_V22,
|
||||
ARM64_REG_V23,
|
||||
ARM64_REG_V24,
|
||||
ARM64_REG_V25,
|
||||
ARM64_REG_V26,
|
||||
ARM64_REG_V27,
|
||||
ARM64_REG_V28,
|
||||
ARM64_REG_V29,
|
||||
ARM64_REG_V30,
|
||||
ARM64_REG_V31,
|
||||
ARM64_REG_V0,
|
||||
ARM64_REG_V1,
|
||||
ARM64_REG_V2,
|
||||
ARM64_REG_V3,
|
||||
ARM64_REG_V4,
|
||||
ARM64_REG_V5,
|
||||
ARM64_REG_V6,
|
||||
ARM64_REG_V7,
|
||||
ARM64_REG_V8,
|
||||
ARM64_REG_V9,
|
||||
ARM64_REG_V10,
|
||||
ARM64_REG_V11,
|
||||
ARM64_REG_V12,
|
||||
ARM64_REG_V13,
|
||||
ARM64_REG_V14,
|
||||
ARM64_REG_V15,
|
||||
ARM64_REG_V16,
|
||||
ARM64_REG_V17,
|
||||
ARM64_REG_V18,
|
||||
ARM64_REG_V19,
|
||||
ARM64_REG_V20,
|
||||
ARM64_REG_V21,
|
||||
ARM64_REG_V22,
|
||||
ARM64_REG_V23,
|
||||
ARM64_REG_V24,
|
||||
ARM64_REG_V25,
|
||||
ARM64_REG_V26,
|
||||
ARM64_REG_V27,
|
||||
ARM64_REG_V28,
|
||||
ARM64_REG_V29,
|
||||
ARM64_REG_V30,
|
||||
ARM64_REG_V31,
|
||||
ARM64_REG_V0,
|
||||
ARM64_REG_V1,
|
||||
ARM64_REG_V2,
|
||||
ARM64_REG_V3,
|
||||
ARM64_REG_V4,
|
||||
ARM64_REG_V5,
|
||||
ARM64_REG_V6,
|
||||
ARM64_REG_V7,
|
||||
ARM64_REG_V8,
|
||||
ARM64_REG_V9,
|
||||
ARM64_REG_V10,
|
||||
ARM64_REG_V11,
|
||||
ARM64_REG_V12,
|
||||
ARM64_REG_V13,
|
||||
ARM64_REG_V14,
|
||||
ARM64_REG_V15,
|
||||
ARM64_REG_V16,
|
||||
ARM64_REG_V17,
|
||||
ARM64_REG_V18,
|
||||
ARM64_REG_V19,
|
||||
ARM64_REG_V20,
|
||||
ARM64_REG_V21,
|
||||
ARM64_REG_V22,
|
||||
ARM64_REG_V23,
|
||||
ARM64_REG_V24,
|
||||
ARM64_REG_V25,
|
||||
ARM64_REG_V26,
|
||||
ARM64_REG_V27,
|
||||
ARM64_REG_V28,
|
||||
ARM64_REG_V29,
|
||||
ARM64_REG_V30,
|
||||
ARM64_REG_V31,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
@@ -0,0 +1,229 @@
|
||||
|
||||
/* Capstone Disassembly Engine, http://www.capstone-engine.org */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
|
||||
|
||||
/*===- TableGen'erated file -------------------------------------*- C++ -*-===*|* *|
|
||||
|* Subtarget Enumeration Source Fragment *|
|
||||
|* *|
|
||||
|* Automatically generated file, do not edit! *|
|
||||
|* *|
|
||||
\*===----------------------------------------------------------------------===*/
|
||||
|
||||
|
||||
enum {
|
||||
AArch64_FeatureAES = 0,
|
||||
AArch64_FeatureAM = 1,
|
||||
AArch64_FeatureAMVS = 2,
|
||||
AArch64_FeatureAggressiveFMA = 3,
|
||||
AArch64_FeatureAltFPCmp = 4,
|
||||
AArch64_FeatureAlternateSExtLoadCVTF32Pattern = 5,
|
||||
AArch64_FeatureAppleA7SysReg = 6,
|
||||
AArch64_FeatureArithmeticBccFusion = 7,
|
||||
AArch64_FeatureArithmeticCbzFusion = 8,
|
||||
AArch64_FeatureBF16 = 9,
|
||||
AArch64_FeatureBRBE = 10,
|
||||
AArch64_FeatureBalanceFPOps = 11,
|
||||
AArch64_FeatureBranchTargetId = 12,
|
||||
AArch64_FeatureCCIDX = 13,
|
||||
AArch64_FeatureCCPP = 14,
|
||||
AArch64_FeatureCONTEXTIDREL2 = 15,
|
||||
AArch64_FeatureCRC = 16,
|
||||
AArch64_FeatureCacheDeepPersist = 17,
|
||||
AArch64_FeatureCallSavedX8 = 18,
|
||||
AArch64_FeatureCallSavedX9 = 19,
|
||||
AArch64_FeatureCallSavedX10 = 20,
|
||||
AArch64_FeatureCallSavedX11 = 21,
|
||||
AArch64_FeatureCallSavedX12 = 22,
|
||||
AArch64_FeatureCallSavedX13 = 23,
|
||||
AArch64_FeatureCallSavedX14 = 24,
|
||||
AArch64_FeatureCallSavedX15 = 25,
|
||||
AArch64_FeatureCallSavedX18 = 26,
|
||||
AArch64_FeatureCmpBccFusion = 27,
|
||||
AArch64_FeatureComplxNum = 28,
|
||||
AArch64_FeatureCrypto = 29,
|
||||
AArch64_FeatureCustomCheapAsMoveHandling = 30,
|
||||
AArch64_FeatureDIT = 31,
|
||||
AArch64_FeatureDisableLatencySchedHeuristic = 32,
|
||||
AArch64_FeatureDotProd = 33,
|
||||
AArch64_FeatureEL2VMSA = 34,
|
||||
AArch64_FeatureEL3 = 35,
|
||||
AArch64_FeatureETE = 36,
|
||||
AArch64_FeatureEnhancedCounterVirtualization = 37,
|
||||
AArch64_FeatureExperimentalZeroingPseudos = 38,
|
||||
AArch64_FeatureExynosCheapAsMoveHandling = 39,
|
||||
AArch64_FeatureFP16FML = 40,
|
||||
AArch64_FeatureFPARMv8 = 41,
|
||||
AArch64_FeatureFRInt3264 = 42,
|
||||
AArch64_FeatureFineGrainedTraps = 43,
|
||||
AArch64_FeatureFixCortexA53_835769 = 44,
|
||||
AArch64_FeatureFlagM = 45,
|
||||
AArch64_FeatureForce32BitJumpTables = 46,
|
||||
AArch64_FeatureFullFP16 = 47,
|
||||
AArch64_FeatureFuseAES = 48,
|
||||
AArch64_FeatureFuseAddress = 49,
|
||||
AArch64_FeatureFuseArithmeticLogic = 50,
|
||||
AArch64_FeatureFuseCCSelect = 51,
|
||||
AArch64_FeatureFuseCryptoEOR = 52,
|
||||
AArch64_FeatureFuseLiterals = 53,
|
||||
AArch64_FeatureHBC = 54,
|
||||
AArch64_FeatureHCX = 55,
|
||||
AArch64_FeatureHardenSlsBlr = 56,
|
||||
AArch64_FeatureHardenSlsNoComdat = 57,
|
||||
AArch64_FeatureHardenSlsRetBr = 58,
|
||||
AArch64_FeatureJS = 59,
|
||||
AArch64_FeatureLOR = 60,
|
||||
AArch64_FeatureLS64 = 61,
|
||||
AArch64_FeatureLSE = 62,
|
||||
AArch64_FeatureLSE2 = 63,
|
||||
AArch64_FeatureLSLFast = 64,
|
||||
AArch64_FeatureMOPS = 65,
|
||||
AArch64_FeatureMPAM = 66,
|
||||
AArch64_FeatureMTE = 67,
|
||||
AArch64_FeatureMatMulFP32 = 68,
|
||||
AArch64_FeatureMatMulFP64 = 69,
|
||||
AArch64_FeatureMatMulInt8 = 70,
|
||||
AArch64_FeatureNEON = 71,
|
||||
AArch64_FeatureNV = 72,
|
||||
AArch64_FeatureNoBTIAtReturnTwice = 73,
|
||||
AArch64_FeatureNoNegativeImmediates = 74,
|
||||
AArch64_FeatureNoZCZeroingFP = 75,
|
||||
AArch64_FeatureOutlineAtomics = 76,
|
||||
AArch64_FeaturePAN = 77,
|
||||
AArch64_FeaturePAN_RWV = 78,
|
||||
AArch64_FeaturePAuth = 79,
|
||||
AArch64_FeaturePerfMon = 80,
|
||||
AArch64_FeaturePostRAScheduler = 81,
|
||||
AArch64_FeaturePredRes = 82,
|
||||
AArch64_FeaturePredictableSelectIsExpensive = 83,
|
||||
AArch64_FeaturePsUAO = 84,
|
||||
AArch64_FeatureRAS = 85,
|
||||
AArch64_FeatureRCPC = 86,
|
||||
AArch64_FeatureRCPC_IMMO = 87,
|
||||
AArch64_FeatureRDM = 88,
|
||||
AArch64_FeatureRME = 89,
|
||||
AArch64_FeatureRandGen = 90,
|
||||
AArch64_FeatureReserveX1 = 91,
|
||||
AArch64_FeatureReserveX2 = 92,
|
||||
AArch64_FeatureReserveX3 = 93,
|
||||
AArch64_FeatureReserveX4 = 94,
|
||||
AArch64_FeatureReserveX5 = 95,
|
||||
AArch64_FeatureReserveX6 = 96,
|
||||
AArch64_FeatureReserveX7 = 97,
|
||||
AArch64_FeatureReserveX9 = 98,
|
||||
AArch64_FeatureReserveX10 = 99,
|
||||
AArch64_FeatureReserveX11 = 100,
|
||||
AArch64_FeatureReserveX12 = 101,
|
||||
AArch64_FeatureReserveX13 = 102,
|
||||
AArch64_FeatureReserveX14 = 103,
|
||||
AArch64_FeatureReserveX15 = 104,
|
||||
AArch64_FeatureReserveX18 = 105,
|
||||
AArch64_FeatureReserveX20 = 106,
|
||||
AArch64_FeatureReserveX21 = 107,
|
||||
AArch64_FeatureReserveX22 = 108,
|
||||
AArch64_FeatureReserveX23 = 109,
|
||||
AArch64_FeatureReserveX24 = 110,
|
||||
AArch64_FeatureReserveX25 = 111,
|
||||
AArch64_FeatureReserveX26 = 112,
|
||||
AArch64_FeatureReserveX27 = 113,
|
||||
AArch64_FeatureReserveX28 = 114,
|
||||
AArch64_FeatureReserveX30 = 115,
|
||||
AArch64_FeatureSB = 116,
|
||||
AArch64_FeatureSEL2 = 117,
|
||||
AArch64_FeatureSHA2 = 118,
|
||||
AArch64_FeatureSHA3 = 119,
|
||||
AArch64_FeatureSM4 = 120,
|
||||
AArch64_FeatureSME = 121,
|
||||
AArch64_FeatureSMEF64 = 122,
|
||||
AArch64_FeatureSMEI64 = 123,
|
||||
AArch64_FeatureSPE = 124,
|
||||
AArch64_FeatureSPE_EEF = 125,
|
||||
AArch64_FeatureSSBS = 126,
|
||||
AArch64_FeatureSVE = 127,
|
||||
AArch64_FeatureSVE2 = 128,
|
||||
AArch64_FeatureSVE2AES = 129,
|
||||
AArch64_FeatureSVE2BitPerm = 130,
|
||||
AArch64_FeatureSVE2SHA3 = 131,
|
||||
AArch64_FeatureSVE2SM4 = 132,
|
||||
AArch64_FeatureSlowMisaligned128Store = 133,
|
||||
AArch64_FeatureSlowPaired128 = 134,
|
||||
AArch64_FeatureSlowSTRQro = 135,
|
||||
AArch64_FeatureSpecRestrict = 136,
|
||||
AArch64_FeatureStreamingSVE = 137,
|
||||
AArch64_FeatureStrictAlign = 138,
|
||||
AArch64_FeatureTLB_RMI = 139,
|
||||
AArch64_FeatureTME = 140,
|
||||
AArch64_FeatureTRACEV8_4 = 141,
|
||||
AArch64_FeatureTRBE = 142,
|
||||
AArch64_FeatureTaggedGlobals = 143,
|
||||
AArch64_FeatureUseEL1ForTP = 144,
|
||||
AArch64_FeatureUseEL2ForTP = 145,
|
||||
AArch64_FeatureUseEL3ForTP = 146,
|
||||
AArch64_FeatureUseRSqrt = 147,
|
||||
AArch64_FeatureUseScalarIncVL = 148,
|
||||
AArch64_FeatureVH = 149,
|
||||
AArch64_FeatureWFxT = 150,
|
||||
AArch64_FeatureXS = 151,
|
||||
AArch64_FeatureZCRegMove = 152,
|
||||
AArch64_FeatureZCZeroing = 153,
|
||||
AArch64_FeatureZCZeroingFPWorkaround = 154,
|
||||
AArch64_FeatureZCZeroingGP = 155,
|
||||
AArch64_HasV8_0aOps = 156,
|
||||
AArch64_HasV8_0rOps = 157,
|
||||
AArch64_HasV8_1aOps = 158,
|
||||
AArch64_HasV8_2aOps = 159,
|
||||
AArch64_HasV8_3aOps = 160,
|
||||
AArch64_HasV8_4aOps = 161,
|
||||
AArch64_HasV8_5aOps = 162,
|
||||
AArch64_HasV8_6aOps = 163,
|
||||
AArch64_HasV8_7aOps = 164,
|
||||
AArch64_HasV8_8aOps = 165,
|
||||
AArch64_HasV9_0aOps = 166,
|
||||
AArch64_HasV9_1aOps = 167,
|
||||
AArch64_HasV9_2aOps = 168,
|
||||
AArch64_HasV9_3aOps = 169,
|
||||
AArch64_TuneA35 = 170,
|
||||
AArch64_TuneA53 = 171,
|
||||
AArch64_TuneA55 = 172,
|
||||
AArch64_TuneA57 = 173,
|
||||
AArch64_TuneA64FX = 174,
|
||||
AArch64_TuneA65 = 175,
|
||||
AArch64_TuneA72 = 176,
|
||||
AArch64_TuneA73 = 177,
|
||||
AArch64_TuneA75 = 178,
|
||||
AArch64_TuneA76 = 179,
|
||||
AArch64_TuneA77 = 180,
|
||||
AArch64_TuneA78 = 181,
|
||||
AArch64_TuneA78C = 182,
|
||||
AArch64_TuneA510 = 183,
|
||||
AArch64_TuneA710 = 184,
|
||||
AArch64_TuneAmpere1 = 185,
|
||||
AArch64_TuneAppleA7 = 186,
|
||||
AArch64_TuneAppleA10 = 187,
|
||||
AArch64_TuneAppleA11 = 188,
|
||||
AArch64_TuneAppleA12 = 189,
|
||||
AArch64_TuneAppleA13 = 190,
|
||||
AArch64_TuneAppleA14 = 191,
|
||||
AArch64_TuneCarmel = 192,
|
||||
AArch64_TuneExynosM3 = 193,
|
||||
AArch64_TuneExynosM4 = 194,
|
||||
AArch64_TuneFalkor = 195,
|
||||
AArch64_TuneKryo = 196,
|
||||
AArch64_TuneNeoverse512TVB = 197,
|
||||
AArch64_TuneNeoverseE1 = 198,
|
||||
AArch64_TuneNeoverseN1 = 199,
|
||||
AArch64_TuneNeoverseN2 = 200,
|
||||
AArch64_TuneNeoverseV1 = 201,
|
||||
AArch64_TuneR82 = 202,
|
||||
AArch64_TuneSaphira = 203,
|
||||
AArch64_TuneTSV110 = 204,
|
||||
AArch64_TuneThunderX = 205,
|
||||
AArch64_TuneThunderX2T99 = 206,
|
||||
AArch64_TuneThunderX3T110 = 207,
|
||||
AArch64_TuneThunderXT81 = 208,
|
||||
AArch64_TuneThunderXT83 = 209,
|
||||
AArch64_TuneThunderXT88 = 210,
|
||||
AArch64_TuneX1 = 211,
|
||||
AArch64_TuneX2 = 212,
|
||||
AArch64_NumSubtargetFeatures = 213
|
||||
};
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,21 @@
|
||||
/* Capstone Disassembly Engine, http://www.capstone-engine.org */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
|
||||
|
||||
enum PStateValues {
|
||||
AArch64PState_SPSel = 5,
|
||||
AArch64PState_DAIFSet = 30,
|
||||
AArch64PState_DAIFClr = 31,
|
||||
AArch64PState_PAN = 4,
|
||||
AArch64PState_UAO = 3,
|
||||
AArch64PState_DIT = 26,
|
||||
AArch64PState_SSBS = 25,
|
||||
AArch64PState_TCO = 28,
|
||||
};
|
||||
|
||||
enum ExactFPImmValues {
|
||||
AArch64ExactFPImm_zero = 0,
|
||||
AArch64ExactFPImm_half = 1,
|
||||
AArch64ExactFPImm_one = 2,
|
||||
AArch64ExactFPImm_two = 3,
|
||||
};
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,28 @@
|
||||
//===-- AArch64InstPrinter.h - Convert AArch64 MCInst to assembly syntax --===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This class prints an AArch64 MCInst to a .s file.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/* Capstone Disassembly Engine */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
|
||||
|
||||
#ifndef CS_LLVM_AARCH64INSTPRINTER_H
|
||||
#define CS_LLVM_AARCH64INSTPRINTER_H
|
||||
|
||||
#include "../../MCInst.h"
|
||||
#include "../../MCRegisterInfo.h"
|
||||
#include "../../SStream.h"
|
||||
|
||||
void AArch64_printInst(MCInst *MI, SStream *O, void *);
|
||||
|
||||
void AArch64_post_printer(csh handle, cs_insn *pub_insn, char *insn_asm, MCInst *mci);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,883 @@
|
||||
/* Capstone Disassembly Engine */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
|
||||
|
||||
#ifdef CAPSTONE_HAS_ARM64
|
||||
|
||||
#include <stdio.h> // debug
|
||||
#include <string.h>
|
||||
|
||||
#include "../../utils.h"
|
||||
|
||||
#include "AArch64Mapping.h"
|
||||
|
||||
#define GET_INSTRINFO_ENUM
|
||||
#include "AArch64GenInstrInfo.inc"
|
||||
|
||||
#ifndef CAPSTONE_DIET
|
||||
// NOTE: this reg_name_maps[] reflects the order of registers in arm64_reg
|
||||
static const char * const reg_name_maps[] = {
|
||||
NULL, /* ARM64_REG_INVALID */
|
||||
|
||||
"ffr",
|
||||
"fp",
|
||||
"lr",
|
||||
"nzcv",
|
||||
"sp",
|
||||
"vg",
|
||||
"wsp",
|
||||
"wzr",
|
||||
"xzr",
|
||||
|
||||
"za",
|
||||
|
||||
"b0",
|
||||
"b1",
|
||||
"b2",
|
||||
"b3",
|
||||
"b4",
|
||||
"b5",
|
||||
"b6",
|
||||
"b7",
|
||||
"b8",
|
||||
"b9",
|
||||
"b10",
|
||||
"b11",
|
||||
"b12",
|
||||
"b13",
|
||||
"b14",
|
||||
"b15",
|
||||
"b16",
|
||||
"b17",
|
||||
"b18",
|
||||
"b19",
|
||||
"b20",
|
||||
"b21",
|
||||
"b22",
|
||||
"b23",
|
||||
"b24",
|
||||
"b25",
|
||||
"b26",
|
||||
"b27",
|
||||
"b28",
|
||||
"b29",
|
||||
"b30",
|
||||
"b31",
|
||||
|
||||
"d0",
|
||||
"d1",
|
||||
"d2",
|
||||
"d3",
|
||||
"d4",
|
||||
"d5",
|
||||
"d6",
|
||||
"d7",
|
||||
"d8",
|
||||
"d9",
|
||||
"d10",
|
||||
"d11",
|
||||
"d12",
|
||||
"d13",
|
||||
"d14",
|
||||
"d15",
|
||||
"d16",
|
||||
"d17",
|
||||
"d18",
|
||||
"d19",
|
||||
"d20",
|
||||
"d21",
|
||||
"d22",
|
||||
"d23",
|
||||
"d24",
|
||||
"d25",
|
||||
"d26",
|
||||
"d27",
|
||||
"d28",
|
||||
"d29",
|
||||
"d30",
|
||||
"d31",
|
||||
|
||||
"h0",
|
||||
"h1",
|
||||
"h2",
|
||||
"h3",
|
||||
"h4",
|
||||
"h5",
|
||||
"h6",
|
||||
"h7",
|
||||
"h8",
|
||||
"h9",
|
||||
"h10",
|
||||
"h11",
|
||||
"h12",
|
||||
"h13",
|
||||
"h14",
|
||||
"h15",
|
||||
"h16",
|
||||
"h17",
|
||||
"h18",
|
||||
"h19",
|
||||
"h20",
|
||||
"h21",
|
||||
"h22",
|
||||
"h23",
|
||||
"h24",
|
||||
"h25",
|
||||
"h26",
|
||||
"h27",
|
||||
"h28",
|
||||
"h29",
|
||||
"h30",
|
||||
"h31",
|
||||
|
||||
"p0",
|
||||
"p1",
|
||||
"p2",
|
||||
"p3",
|
||||
"p4",
|
||||
"p5",
|
||||
"p6",
|
||||
"p7",
|
||||
"p8",
|
||||
"p9",
|
||||
"p10",
|
||||
"p11",
|
||||
"p12",
|
||||
"p13",
|
||||
"p14",
|
||||
"p15",
|
||||
|
||||
"q0",
|
||||
"q1",
|
||||
"q2",
|
||||
"q3",
|
||||
"q4",
|
||||
"q5",
|
||||
"q6",
|
||||
"q7",
|
||||
"q8",
|
||||
"q9",
|
||||
"q10",
|
||||
"q11",
|
||||
"q12",
|
||||
"q13",
|
||||
"q14",
|
||||
"q15",
|
||||
"q16",
|
||||
"q17",
|
||||
"q18",
|
||||
"q19",
|
||||
"q20",
|
||||
"q21",
|
||||
"q22",
|
||||
"q23",
|
||||
"q24",
|
||||
"q25",
|
||||
"q26",
|
||||
"q27",
|
||||
"q28",
|
||||
"q29",
|
||||
"q30",
|
||||
"q31",
|
||||
|
||||
"s0",
|
||||
"s1",
|
||||
"s2",
|
||||
"s3",
|
||||
"s4",
|
||||
"s5",
|
||||
"s6",
|
||||
"s7",
|
||||
"s8",
|
||||
"s9",
|
||||
"s10",
|
||||
"s11",
|
||||
"s12",
|
||||
"s13",
|
||||
"s14",
|
||||
"s15",
|
||||
"s16",
|
||||
"s17",
|
||||
"s18",
|
||||
"s19",
|
||||
"s20",
|
||||
"s21",
|
||||
"s22",
|
||||
"s23",
|
||||
"s24",
|
||||
"s25",
|
||||
"s26",
|
||||
"s27",
|
||||
"s28",
|
||||
"s29",
|
||||
"s30",
|
||||
"s31",
|
||||
|
||||
"w0",
|
||||
"w1",
|
||||
"w2",
|
||||
"w3",
|
||||
"w4",
|
||||
"w5",
|
||||
"w6",
|
||||
"w7",
|
||||
"w8",
|
||||
"w9",
|
||||
"w10",
|
||||
"w11",
|
||||
"w12",
|
||||
"w13",
|
||||
"w14",
|
||||
"w15",
|
||||
"w16",
|
||||
"w17",
|
||||
"w18",
|
||||
"w19",
|
||||
"w20",
|
||||
"w21",
|
||||
"w22",
|
||||
"w23",
|
||||
"w24",
|
||||
"w25",
|
||||
"w26",
|
||||
"w27",
|
||||
"w28",
|
||||
"w29",
|
||||
"w30",
|
||||
|
||||
"x0",
|
||||
"x1",
|
||||
"x2",
|
||||
"x3",
|
||||
"x4",
|
||||
"x5",
|
||||
"x6",
|
||||
"x7",
|
||||
"x8",
|
||||
"x9",
|
||||
"x10",
|
||||
"x11",
|
||||
"x12",
|
||||
"x13",
|
||||
"x14",
|
||||
"x15",
|
||||
"x16",
|
||||
"x17",
|
||||
"x18",
|
||||
"x19",
|
||||
"x20",
|
||||
"x21",
|
||||
"x22",
|
||||
"x23",
|
||||
"x24",
|
||||
"x25",
|
||||
"x26",
|
||||
"x27",
|
||||
"x28",
|
||||
|
||||
"z0",
|
||||
"z1",
|
||||
"z2",
|
||||
"z3",
|
||||
"z4",
|
||||
"z5",
|
||||
"z6",
|
||||
"z7",
|
||||
"z8",
|
||||
"z9",
|
||||
"z10",
|
||||
"z11",
|
||||
"z12",
|
||||
"z13",
|
||||
"z14",
|
||||
"z15",
|
||||
"z16",
|
||||
"z17",
|
||||
"z18",
|
||||
"z19",
|
||||
"z20",
|
||||
"z21",
|
||||
"z22",
|
||||
"z23",
|
||||
"z24",
|
||||
"z25",
|
||||
"z26",
|
||||
"z27",
|
||||
"z28",
|
||||
"z29",
|
||||
"z30",
|
||||
"z31",
|
||||
|
||||
"zab0",
|
||||
|
||||
"zad0",
|
||||
"zad1",
|
||||
"zad2",
|
||||
"zad3",
|
||||
"zad4",
|
||||
"zad5",
|
||||
"zad6",
|
||||
"zad7",
|
||||
|
||||
"zah0",
|
||||
"zah1",
|
||||
|
||||
"zaq0",
|
||||
"zaq1",
|
||||
"zaq2",
|
||||
"zaq3",
|
||||
"zaq4",
|
||||
"zaq5",
|
||||
"zaq6",
|
||||
"zaq7",
|
||||
"zaq8",
|
||||
"zaq9",
|
||||
"zaq10",
|
||||
"zaq11",
|
||||
"zaq12",
|
||||
"zaq13",
|
||||
"zaq14",
|
||||
"zaq15",
|
||||
|
||||
"zas0",
|
||||
"zas1",
|
||||
"zas2",
|
||||
"zas3",
|
||||
|
||||
"v0",
|
||||
"v1",
|
||||
"v2",
|
||||
"v3",
|
||||
"v4",
|
||||
"v5",
|
||||
"v6",
|
||||
"v7",
|
||||
"v8",
|
||||
"v9",
|
||||
"v10",
|
||||
"v11",
|
||||
"v12",
|
||||
"v13",
|
||||
"v14",
|
||||
"v15",
|
||||
"v16",
|
||||
"v17",
|
||||
"v18",
|
||||
"v19",
|
||||
"v20",
|
||||
"v21",
|
||||
"v22",
|
||||
"v23",
|
||||
"v24",
|
||||
"v25",
|
||||
"v26",
|
||||
"v27",
|
||||
"v28",
|
||||
"v29",
|
||||
"v30",
|
||||
"v31",
|
||||
};
|
||||
#endif
|
||||
|
||||
const char *AArch64_reg_name(csh handle, unsigned int reg)
|
||||
{
|
||||
#ifndef CAPSTONE_DIET
|
||||
if (reg >= ARR_SIZE(reg_name_maps))
|
||||
return NULL;
|
||||
|
||||
return reg_name_maps[reg];
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
static const insn_map insns[] = {
|
||||
// dummy item
|
||||
{
|
||||
0, 0,
|
||||
#ifndef CAPSTONE_DIET
|
||||
{ 0 }, { 0 }, { 0 }, 0, 0
|
||||
#endif
|
||||
},
|
||||
|
||||
#include "AArch64MappingInsn.inc"
|
||||
};
|
||||
|
||||
// given internal insn id, return public instruction info
|
||||
void AArch64_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id)
|
||||
{
|
||||
int i = insn_find(insns, ARR_SIZE(insns), id, &h->insn_cache);
|
||||
if (i != 0) {
|
||||
insn->id = insns[i].mapid;
|
||||
|
||||
if (h->detail) {
|
||||
#ifndef CAPSTONE_DIET
|
||||
cs_struct handle;
|
||||
handle.detail = h->detail;
|
||||
|
||||
memcpy(insn->detail->regs_read, insns[i].regs_use, sizeof(insns[i].regs_use));
|
||||
insn->detail->regs_read_count = (uint8_t)count_positive(insns[i].regs_use);
|
||||
|
||||
memcpy(insn->detail->regs_write, insns[i].regs_mod, sizeof(insns[i].regs_mod));
|
||||
insn->detail->regs_write_count = (uint8_t)count_positive(insns[i].regs_mod);
|
||||
|
||||
memcpy(insn->detail->groups, insns[i].groups, sizeof(insns[i].groups));
|
||||
insn->detail->groups_count = (uint8_t)count_positive8(insns[i].groups);
|
||||
|
||||
insn->detail->arm64.update_flags = cs_reg_write((csh)&handle, insn, ARM64_REG_NZCV);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const char * const insn_name_maps[] = {
|
||||
NULL, // ARM64_INS_INVALID
|
||||
#include "AArch64MappingInsnName.inc"
|
||||
"sbfiz",
|
||||
"ubfiz",
|
||||
"sbfx",
|
||||
"ubfx",
|
||||
"bfi",
|
||||
"bfxil",
|
||||
"ic",
|
||||
"dc",
|
||||
"at",
|
||||
"tlbi",
|
||||
"smstart",
|
||||
"smstop",
|
||||
};
|
||||
|
||||
const char *AArch64_insn_name(csh handle, unsigned int id)
|
||||
{
|
||||
#ifndef CAPSTONE_DIET
|
||||
if (id >= ARM64_INS_ENDING)
|
||||
return NULL;
|
||||
|
||||
if (id < ARR_SIZE(insn_name_maps))
|
||||
return insn_name_maps[id];
|
||||
|
||||
// not found
|
||||
return NULL;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef CAPSTONE_DIET
|
||||
static const name_map group_name_maps[] = {
|
||||
// generic groups
|
||||
{ ARM64_GRP_INVALID, NULL },
|
||||
{ ARM64_GRP_JUMP, "jump" },
|
||||
{ ARM64_GRP_CALL, "call" },
|
||||
{ ARM64_GRP_RET, "return" },
|
||||
{ ARM64_GRP_PRIVILEGE, "privilege" },
|
||||
{ ARM64_GRP_INT, "int" },
|
||||
{ ARM64_GRP_BRANCH_RELATIVE, "branch_relative" },
|
||||
{ ARM64_GRP_PAC, "pointer authentication" },
|
||||
|
||||
// architecture-specific groups
|
||||
{ ARM64_GRP_CRYPTO, "crypto" },
|
||||
{ ARM64_GRP_FPARMV8, "fparmv8" },
|
||||
{ ARM64_GRP_NEON, "neon" },
|
||||
{ ARM64_GRP_CRC, "crc" },
|
||||
|
||||
{ ARM64_GRP_AES, "aes" },
|
||||
{ ARM64_GRP_DOTPROD, "dotprod" },
|
||||
{ ARM64_GRP_FULLFP16, "fullfp16" },
|
||||
{ ARM64_GRP_LSE, "lse" },
|
||||
{ ARM64_GRP_RCPC, "rcpc" },
|
||||
{ ARM64_GRP_RDM, "rdm" },
|
||||
{ ARM64_GRP_SHA2, "sha2" },
|
||||
{ ARM64_GRP_SHA3, "sha3" },
|
||||
{ ARM64_GRP_SM4, "sm4" },
|
||||
{ ARM64_GRP_SVE, "sve" },
|
||||
{ ARM64_GRP_SVE2, "sve2" },
|
||||
{ ARM64_GRP_SVE2AES, "sve2-aes" },
|
||||
{ ARM64_GRP_SVE2BitPerm, "sve2-bitperm" },
|
||||
{ ARM64_GRP_SVE2SHA3, "sve2-sha3" },
|
||||
{ ARM64_GRP_SVE2SM4, "sve2-sm4" },
|
||||
{ ARM64_GRP_SME, "sme" },
|
||||
{ ARM64_GRP_SMEF64, "sme-f64" },
|
||||
{ ARM64_GRP_SMEI64, "sme-i64" },
|
||||
{ ARM64_GRP_MatMulFP32, "f32mm" },
|
||||
{ ARM64_GRP_MatMulFP64, "f64mm" },
|
||||
{ ARM64_GRP_MatMulInt8, "i8mm" },
|
||||
{ ARM64_GRP_V8_1A, "v8_1a" },
|
||||
{ ARM64_GRP_V8_3A, "v8_3a" },
|
||||
{ ARM64_GRP_V8_4A, "v8_4a" },
|
||||
};
|
||||
#endif
|
||||
|
||||
const char *AArch64_group_name(csh handle, unsigned int id)
|
||||
{
|
||||
#ifndef CAPSTONE_DIET
|
||||
return id2name(group_name_maps, ARR_SIZE(group_name_maps), id);
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
// map instruction name to public instruction ID
|
||||
arm64_insn AArch64_map_insn(const char *name)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for(i = 1; i < ARR_SIZE(insn_name_maps); i++) {
|
||||
if (!strcmp(name, insn_name_maps[i]))
|
||||
return i;
|
||||
}
|
||||
|
||||
// not found
|
||||
return ARM64_INS_INVALID;
|
||||
}
|
||||
|
||||
// map internal raw vregister to 'public' register
|
||||
arm64_reg AArch64_map_vregister(unsigned int r)
|
||||
{
|
||||
static const unsigned short RegAsmOffsetvreg[] = {
|
||||
#include "AArch64GenRegisterV.inc"
|
||||
};
|
||||
|
||||
if (r < ARR_SIZE(RegAsmOffsetvreg))
|
||||
return RegAsmOffsetvreg[r - 1];
|
||||
|
||||
// cannot find this register
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const name_map sys_op_name_map[] = {
|
||||
{ ARM64_TLBI_ALLE1, "alle1"} ,
|
||||
{ ARM64_TLBI_ALLE1IS, "alle1is"} ,
|
||||
{ ARM64_TLBI_ALLE1ISNXS, "alle1isnxs"} ,
|
||||
{ ARM64_TLBI_ALLE1NXS, "alle1nxs"} ,
|
||||
{ ARM64_TLBI_ALLE1OS, "alle1os"} ,
|
||||
{ ARM64_TLBI_ALLE1OSNXS, "alle1osnxs"} ,
|
||||
{ ARM64_TLBI_ALLE2, "alle2"} ,
|
||||
{ ARM64_TLBI_ALLE2IS, "alle2is"} ,
|
||||
{ ARM64_TLBI_ALLE2ISNXS, "alle2isnxs"} ,
|
||||
{ ARM64_TLBI_ALLE2NXS, "alle2nxs"} ,
|
||||
{ ARM64_TLBI_ALLE2OS, "alle2os"} ,
|
||||
{ ARM64_TLBI_ALLE2OSNXS, "alle2osnxs"} ,
|
||||
{ ARM64_TLBI_ALLE3, "alle3"} ,
|
||||
{ ARM64_TLBI_ALLE3IS, "alle3is"} ,
|
||||
{ ARM64_TLBI_ALLE3ISNXS, "alle3isnxs"} ,
|
||||
{ ARM64_TLBI_ALLE3NXS, "alle3nxs"} ,
|
||||
{ ARM64_TLBI_ALLE3OS, "alle3os"} ,
|
||||
{ ARM64_TLBI_ALLE3OSNXS, "alle3osnxs"} ,
|
||||
{ ARM64_TLBI_ASIDE1, "aside1"} ,
|
||||
{ ARM64_TLBI_ASIDE1IS, "aside1is"} ,
|
||||
{ ARM64_TLBI_ASIDE1ISNXS, "aside1isnxs"} ,
|
||||
{ ARM64_TLBI_ASIDE1NXS, "aside1nxs"} ,
|
||||
{ ARM64_TLBI_ASIDE1OS, "aside1os"} ,
|
||||
{ ARM64_TLBI_ASIDE1OSNXS, "aside1osnxs"} ,
|
||||
{ ARM64_TLBI_IPAS2E1, "ipas2e1"} ,
|
||||
{ ARM64_TLBI_IPAS2E1IS, "ipas2e1is"} ,
|
||||
{ ARM64_TLBI_IPAS2E1ISNXS, "ipas2e1isnxs"} ,
|
||||
{ ARM64_TLBI_IPAS2E1NXS, "ipas2e1nxs"} ,
|
||||
{ ARM64_TLBI_IPAS2E1OS, "ipas2e1os"} ,
|
||||
{ ARM64_TLBI_IPAS2E1OSNXS, "ipas2e1osnxs"} ,
|
||||
{ ARM64_TLBI_IPAS2LE1, "ipas2le1"} ,
|
||||
{ ARM64_TLBI_IPAS2LE1IS, "ipas2le1is"} ,
|
||||
{ ARM64_TLBI_IPAS2LE1ISNXS, "ipas2le1isnxs"} ,
|
||||
{ ARM64_TLBI_IPAS2LE1NXS, "ipas2le1nxs"} ,
|
||||
{ ARM64_TLBI_IPAS2LE1OS, "ipas2le1os"} ,
|
||||
{ ARM64_TLBI_IPAS2LE1OSNXS, "ipas2le1osnxs"} ,
|
||||
{ ARM64_TLBI_PAALL, "paall"} ,
|
||||
{ ARM64_TLBI_PAALLNXS, "paallnxs"} ,
|
||||
{ ARM64_TLBI_PAALLOS, "paallos"} ,
|
||||
{ ARM64_TLBI_PAALLOSNXS, "paallosnxs"} ,
|
||||
{ ARM64_TLBI_RIPAS2E1, "ripas2e1"} ,
|
||||
{ ARM64_TLBI_RIPAS2E1IS, "ripas2e1is"} ,
|
||||
{ ARM64_TLBI_RIPAS2E1ISNXS, "ripas2e1isnxs"} ,
|
||||
{ ARM64_TLBI_RIPAS2E1NXS, "ripas2e1nxs"} ,
|
||||
{ ARM64_TLBI_RIPAS2E1OS, "ripas2e1os"} ,
|
||||
{ ARM64_TLBI_RIPAS2E1OSNXS, "ripas2e1osnxs"} ,
|
||||
{ ARM64_TLBI_RIPAS2LE1, "ripas2le1"} ,
|
||||
{ ARM64_TLBI_RIPAS2LE1IS, "ripas2le1is"} ,
|
||||
{ ARM64_TLBI_RIPAS2LE1ISNXS, "ripas2le1isnxs"} ,
|
||||
{ ARM64_TLBI_RIPAS2LE1NXS, "ripas2le1nxs"} ,
|
||||
{ ARM64_TLBI_RIPAS2LE1OS, "ripas2le1os"} ,
|
||||
{ ARM64_TLBI_RIPAS2LE1OSNXS, "ripas2le1osnxs"} ,
|
||||
{ ARM64_TLBI_RPALOS, "rpalos"} ,
|
||||
{ ARM64_TLBI_RPALOSNXS, "rpalosnxs"} ,
|
||||
{ ARM64_TLBI_RPAOS, "rpaos"} ,
|
||||
{ ARM64_TLBI_RPAOSNXS, "rpaosnxs"} ,
|
||||
{ ARM64_TLBI_RVAAE1, "rvaae1"} ,
|
||||
{ ARM64_TLBI_RVAAE1IS, "rvaae1is"} ,
|
||||
{ ARM64_TLBI_RVAAE1ISNXS, "rvaae1isnxs"} ,
|
||||
{ ARM64_TLBI_RVAAE1NXS, "rvaae1nxs"} ,
|
||||
{ ARM64_TLBI_RVAAE1OS, "rvaae1os"} ,
|
||||
{ ARM64_TLBI_RVAAE1OSNXS, "rvaae1osnxs"} ,
|
||||
{ ARM64_TLBI_RVAALE1, "rvaale1"} ,
|
||||
{ ARM64_TLBI_RVAALE1IS, "rvaale1is"} ,
|
||||
{ ARM64_TLBI_RVAALE1ISNXS, "rvaale1isnxs"} ,
|
||||
{ ARM64_TLBI_RVAALE1NXS, "rvaale1nxs"} ,
|
||||
{ ARM64_TLBI_RVAALE1OS, "rvaale1os"} ,
|
||||
{ ARM64_TLBI_RVAALE1OSNXS, "rvaale1osnxs"} ,
|
||||
{ ARM64_TLBI_RVAE1, "rvae1"} ,
|
||||
{ ARM64_TLBI_RVAE1IS, "rvae1is"} ,
|
||||
{ ARM64_TLBI_RVAE1ISNXS, "rvae1isnxs"} ,
|
||||
{ ARM64_TLBI_RVAE1NXS, "rvae1nxs"} ,
|
||||
{ ARM64_TLBI_RVAE1OS, "rvae1os"} ,
|
||||
{ ARM64_TLBI_RVAE1OSNXS, "rvae1osnxs"} ,
|
||||
{ ARM64_TLBI_RVAE2, "rvae2"} ,
|
||||
{ ARM64_TLBI_RVAE2IS, "rvae2is"} ,
|
||||
{ ARM64_TLBI_RVAE2ISNXS, "rvae2isnxs"} ,
|
||||
{ ARM64_TLBI_RVAE2NXS, "rvae2nxs"} ,
|
||||
{ ARM64_TLBI_RVAE2OS, "rvae2os"} ,
|
||||
{ ARM64_TLBI_RVAE2OSNXS, "rvae2osnxs"} ,
|
||||
{ ARM64_TLBI_RVAE3, "rvae3"} ,
|
||||
{ ARM64_TLBI_RVAE3IS, "rvae3is"} ,
|
||||
{ ARM64_TLBI_RVAE3ISNXS, "rvae3isnxs"} ,
|
||||
{ ARM64_TLBI_RVAE3NXS, "rvae3nxs"} ,
|
||||
{ ARM64_TLBI_RVAE3OS, "rvae3os"} ,
|
||||
{ ARM64_TLBI_RVAE3OSNXS, "rvae3osnxs"} ,
|
||||
{ ARM64_TLBI_RVALE1, "rvale1"} ,
|
||||
{ ARM64_TLBI_RVALE1IS, "rvale1is"} ,
|
||||
{ ARM64_TLBI_RVALE1ISNXS, "rvale1isnxs"} ,
|
||||
{ ARM64_TLBI_RVALE1NXS, "rvale1nxs"} ,
|
||||
{ ARM64_TLBI_RVALE1OS, "rvale1os"} ,
|
||||
{ ARM64_TLBI_RVALE1OSNXS, "rvale1osnxs"} ,
|
||||
{ ARM64_TLBI_RVALE2, "rvale2"} ,
|
||||
{ ARM64_TLBI_RVALE2IS, "rvale2is"} ,
|
||||
{ ARM64_TLBI_RVALE2ISNXS, "rvale2isnxs"} ,
|
||||
{ ARM64_TLBI_RVALE2NXS, "rvale2nxs"} ,
|
||||
{ ARM64_TLBI_RVALE2OS, "rvale2os"} ,
|
||||
{ ARM64_TLBI_RVALE2OSNXS, "rvale2osnxs"} ,
|
||||
{ ARM64_TLBI_RVALE3, "rvale3"} ,
|
||||
{ ARM64_TLBI_RVALE3IS, "rvale3is"} ,
|
||||
{ ARM64_TLBI_RVALE3ISNXS, "rvale3isnxs"} ,
|
||||
{ ARM64_TLBI_RVALE3NXS, "rvale3nxs"} ,
|
||||
{ ARM64_TLBI_RVALE3OS, "rvale3os"} ,
|
||||
{ ARM64_TLBI_RVALE3OSNXS, "rvale3osnxs"} ,
|
||||
{ ARM64_TLBI_VAAE1, "vaae1"} ,
|
||||
{ ARM64_TLBI_VAAE1IS, "vaae1is"} ,
|
||||
{ ARM64_TLBI_VAAE1ISNXS, "vaae1isnxs"} ,
|
||||
{ ARM64_TLBI_VAAE1NXS, "vaae1nxs"} ,
|
||||
{ ARM64_TLBI_VAAE1OS, "vaae1os"} ,
|
||||
{ ARM64_TLBI_VAAE1OSNXS, "vaae1osnxs"} ,
|
||||
{ ARM64_TLBI_VAALE1, "vaale1"} ,
|
||||
{ ARM64_TLBI_VAALE1IS, "vaale1is"} ,
|
||||
{ ARM64_TLBI_VAALE1ISNXS, "vaale1isnxs"} ,
|
||||
{ ARM64_TLBI_VAALE1NXS, "vaale1nxs"} ,
|
||||
{ ARM64_TLBI_VAALE1OS, "vaale1os"} ,
|
||||
{ ARM64_TLBI_VAALE1OSNXS, "vaale1osnxs"} ,
|
||||
{ ARM64_TLBI_VAE1, "vae1"} ,
|
||||
{ ARM64_TLBI_VAE1IS, "vae1is"} ,
|
||||
{ ARM64_TLBI_VAE1ISNXS, "vae1isnxs"} ,
|
||||
{ ARM64_TLBI_VAE1NXS, "vae1nxs"} ,
|
||||
{ ARM64_TLBI_VAE1OS, "vae1os"} ,
|
||||
{ ARM64_TLBI_VAE1OSNXS, "vae1osnxs"} ,
|
||||
{ ARM64_TLBI_VAE2, "vae2"} ,
|
||||
{ ARM64_TLBI_VAE2IS, "vae2is"} ,
|
||||
{ ARM64_TLBI_VAE2ISNXS, "vae2isnxs"} ,
|
||||
{ ARM64_TLBI_VAE2NXS, "vae2nxs"} ,
|
||||
{ ARM64_TLBI_VAE2OS, "vae2os"} ,
|
||||
{ ARM64_TLBI_VAE2OSNXS, "vae2osnxs"} ,
|
||||
{ ARM64_TLBI_VAE3, "vae3"} ,
|
||||
{ ARM64_TLBI_VAE3IS, "vae3is"} ,
|
||||
{ ARM64_TLBI_VAE3ISNXS, "vae3isnxs"} ,
|
||||
{ ARM64_TLBI_VAE3NXS, "vae3nxs"} ,
|
||||
{ ARM64_TLBI_VAE3OS, "vae3os"} ,
|
||||
{ ARM64_TLBI_VAE3OSNXS, "vae3osnxs"} ,
|
||||
{ ARM64_TLBI_VALE1, "vale1"} ,
|
||||
{ ARM64_TLBI_VALE1IS, "vale1is"} ,
|
||||
{ ARM64_TLBI_VALE1ISNXS, "vale1isnxs"} ,
|
||||
{ ARM64_TLBI_VALE1NXS, "vale1nxs"} ,
|
||||
{ ARM64_TLBI_VALE1OS, "vale1os"} ,
|
||||
{ ARM64_TLBI_VALE1OSNXS, "vale1osnxs"} ,
|
||||
{ ARM64_TLBI_VALE2, "vale2"} ,
|
||||
{ ARM64_TLBI_VALE2IS, "vale2is"} ,
|
||||
{ ARM64_TLBI_VALE2ISNXS, "vale2isnxs"} ,
|
||||
{ ARM64_TLBI_VALE2NXS, "vale2nxs"} ,
|
||||
{ ARM64_TLBI_VALE2OS, "vale2os"} ,
|
||||
{ ARM64_TLBI_VALE2OSNXS, "vale2osnxs"} ,
|
||||
{ ARM64_TLBI_VALE3, "vale3"} ,
|
||||
{ ARM64_TLBI_VALE3IS, "vale3is"} ,
|
||||
{ ARM64_TLBI_VALE3ISNXS, "vale3isnxs"} ,
|
||||
{ ARM64_TLBI_VALE3NXS, "vale3nxs"} ,
|
||||
{ ARM64_TLBI_VALE3OS, "vale3os"} ,
|
||||
{ ARM64_TLBI_VALE3OSNXS, "vale3osnxs"} ,
|
||||
{ ARM64_TLBI_VMALLE1, "vmalle1"} ,
|
||||
{ ARM64_TLBI_VMALLE1IS, "vmalle1is"} ,
|
||||
{ ARM64_TLBI_VMALLE1ISNXS, "vmalle1isnxs"} ,
|
||||
{ ARM64_TLBI_VMALLE1NXS, "vmalle1nxs"} ,
|
||||
{ ARM64_TLBI_VMALLE1OS, "vmalle1os"} ,
|
||||
{ ARM64_TLBI_VMALLE1OSNXS, "vmalle1osnxs"} ,
|
||||
{ ARM64_TLBI_VMALLS12E1, "vmalls12e1"} ,
|
||||
{ ARM64_TLBI_VMALLS12E1IS, "vmalls12e1is"} ,
|
||||
{ ARM64_TLBI_VMALLS12E1ISNXS, "vmalls12e1isnxs"} ,
|
||||
{ ARM64_TLBI_VMALLS12E1NXS, "vmalls12e1nxs"} ,
|
||||
{ ARM64_TLBI_VMALLS12E1OS, "vmalls12e1os"} ,
|
||||
{ ARM64_TLBI_VMALLS12E1OSNXS, "vmalls12e1osnxs"} ,
|
||||
{ ARM64_AT_S1E1R, "s1e1r"} ,
|
||||
{ ARM64_AT_S1E2R, "s1e2r"} ,
|
||||
{ ARM64_AT_S1E3R, "s1e3r"} ,
|
||||
{ ARM64_AT_S1E1W, "s1e1w"} ,
|
||||
{ ARM64_AT_S1E2W, "s1e2w"} ,
|
||||
{ ARM64_AT_S1E3W, "s1e3w"} ,
|
||||
{ ARM64_AT_S1E0R, "s1e0r"} ,
|
||||
{ ARM64_AT_S1E0W, "s1e0w"} ,
|
||||
{ ARM64_AT_S12E1R, "s12e1r"} ,
|
||||
{ ARM64_AT_S12E1W, "s12e1w"} ,
|
||||
{ ARM64_AT_S12E0R, "s12e0r"} ,
|
||||
{ ARM64_AT_S12E0W, "s12e0w"} ,
|
||||
{ ARM64_AT_S1E1RP, "s1e1rp"} ,
|
||||
{ ARM64_AT_S1E1WP, "s1e1wp"} ,
|
||||
{ ARM64_DC_CGDSW, "cgdsw"} ,
|
||||
{ ARM64_DC_CGDVAC, "cgdvac"} ,
|
||||
{ ARM64_DC_CGDVADP, "cgdvadp"} ,
|
||||
{ ARM64_DC_CGDVAP, "cgdvap"} ,
|
||||
{ ARM64_DC_CGSW, "cgsw"} ,
|
||||
{ ARM64_DC_CGVAC, "cgvac"} ,
|
||||
{ ARM64_DC_CGVADP, "cgvadp"} ,
|
||||
{ ARM64_DC_CGVAP, "cgvap"} ,
|
||||
{ ARM64_DC_CIGDSW, "cigdsw"} ,
|
||||
{ ARM64_DC_CIGDVAC, "cigdvac"} ,
|
||||
{ ARM64_DC_CIGSW, "cigsw"} ,
|
||||
{ ARM64_DC_CIGVAC, "cigvac"} ,
|
||||
{ ARM64_DC_CISW, "cisw"} ,
|
||||
{ ARM64_DC_CIVAC, "civac"} ,
|
||||
{ ARM64_DC_CSW, "csw"} ,
|
||||
{ ARM64_DC_CVAC, "cvac"} ,
|
||||
{ ARM64_DC_CVADP, "cvadp"} ,
|
||||
{ ARM64_DC_CVAP, "cvap"} ,
|
||||
{ ARM64_DC_CVAU, "cvau"} ,
|
||||
{ ARM64_DC_GVA, "gva"} ,
|
||||
{ ARM64_DC_GZVA, "gzva"} ,
|
||||
{ ARM64_DC_IGDSW, "igdsw"} ,
|
||||
{ ARM64_DC_IGDVAC, "igdvac"} ,
|
||||
{ ARM64_DC_IGSW, "igsw"} ,
|
||||
{ ARM64_DC_IGVAC, "igvac"} ,
|
||||
{ ARM64_DC_ISW, "isw"} ,
|
||||
{ ARM64_DC_IVAC, "ivac"} ,
|
||||
{ ARM64_DC_ZVA, "zva"} ,
|
||||
{ ARM64_IC_IALLUIS, "ialluis"} ,
|
||||
{ ARM64_IC_IALLU, "iallu"} ,
|
||||
{ ARM64_IC_IVAU, "ivau"} ,
|
||||
};
|
||||
|
||||
arm64_sys_op AArch64_map_sys_op(const char *name)
|
||||
{
|
||||
int result = name2id(sys_op_name_map, ARR_SIZE(sys_op_name_map), name);
|
||||
if (result == -1) {
|
||||
return ARM64_SYS_INVALID;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void arm64_op_addReg(MCInst *MI, int reg)
|
||||
{
|
||||
if (MI->csh->detail) {
|
||||
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
|
||||
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = reg;
|
||||
MI->flat_insn->detail->arm64.op_count++;
|
||||
}
|
||||
}
|
||||
|
||||
void arm64_op_addVectorArrSpecifier(MCInst * MI, int sp)
|
||||
{
|
||||
if (MI->csh->detail) {
|
||||
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count - 1].vas = sp;
|
||||
}
|
||||
}
|
||||
|
||||
void arm64_op_addFP(MCInst *MI, float fp)
|
||||
{
|
||||
if (MI->csh->detail) {
|
||||
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_FP;
|
||||
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].fp = fp;
|
||||
MI->flat_insn->detail->arm64.op_count++;
|
||||
}
|
||||
}
|
||||
|
||||
void arm64_op_addImm(MCInst *MI, int64_t imm)
|
||||
{
|
||||
if (MI->csh->detail) {
|
||||
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
|
||||
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = (int)imm;
|
||||
MI->flat_insn->detail->arm64.op_count++;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef CAPSTONE_DIET
|
||||
|
||||
// map instruction to its characteristics
|
||||
typedef struct insn_op {
|
||||
unsigned int eflags_update; // how this instruction update status flags
|
||||
uint8_t access[5];
|
||||
} insn_op;
|
||||
|
||||
static const insn_op insn_ops[] = {
|
||||
{
|
||||
/* NULL item */
|
||||
0, { 0 }
|
||||
},
|
||||
|
||||
#include "AArch64MappingInsnOp.inc"
|
||||
};
|
||||
|
||||
// given internal insn id, return operand access info
|
||||
const uint8_t *AArch64_get_op_access(cs_struct *h, unsigned int id)
|
||||
{
|
||||
int i = insn_find(insns, ARR_SIZE(insns), id, &h->insn_cache);
|
||||
if (i != 0) {
|
||||
return insn_ops[i].access;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void AArch64_reg_access(const cs_insn *insn,
|
||||
cs_regs regs_read, uint8_t *regs_read_count,
|
||||
cs_regs regs_write, uint8_t *regs_write_count)
|
||||
{
|
||||
uint8_t i;
|
||||
uint8_t read_count, write_count;
|
||||
cs_arm64 *arm64 = &(insn->detail->arm64);
|
||||
|
||||
read_count = insn->detail->regs_read_count;
|
||||
write_count = insn->detail->regs_write_count;
|
||||
|
||||
// implicit registers
|
||||
memcpy(regs_read, insn->detail->regs_read, read_count * sizeof(insn->detail->regs_read[0]));
|
||||
memcpy(regs_write, insn->detail->regs_write, write_count * sizeof(insn->detail->regs_write[0]));
|
||||
|
||||
// explicit registers
|
||||
for (i = 0; i < arm64->op_count; i++) {
|
||||
cs_arm64_op *op = &(arm64->operands[i]);
|
||||
switch((int)op->type) {
|
||||
case ARM64_OP_REG:
|
||||
if ((op->access & CS_AC_READ) && !arr_exist(regs_read, read_count, op->reg)) {
|
||||
regs_read[read_count] = (uint16_t)op->reg;
|
||||
read_count++;
|
||||
}
|
||||
if ((op->access & CS_AC_WRITE) && !arr_exist(regs_write, write_count, op->reg)) {
|
||||
regs_write[write_count] = (uint16_t)op->reg;
|
||||
write_count++;
|
||||
}
|
||||
break;
|
||||
case ARM_OP_MEM:
|
||||
// registers appeared in memory references always being read
|
||||
if ((op->mem.base != ARM64_REG_INVALID) && !arr_exist(regs_read, read_count, op->mem.base)) {
|
||||
regs_read[read_count] = (uint16_t)op->mem.base;
|
||||
read_count++;
|
||||
}
|
||||
if ((op->mem.index != ARM64_REG_INVALID) && !arr_exist(regs_read, read_count, op->mem.index)) {
|
||||
regs_read[read_count] = (uint16_t)op->mem.index;
|
||||
read_count++;
|
||||
}
|
||||
if ((arm64->writeback) && (op->mem.base != ARM64_REG_INVALID) && !arr_exist(regs_write, write_count, op->mem.base)) {
|
||||
regs_write[write_count] = (uint16_t)op->mem.base;
|
||||
write_count++;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
*regs_read_count = read_count;
|
||||
*regs_write_count = write_count;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,43 @@
|
||||
/* Capstone Disassembly Engine */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
|
||||
|
||||
#ifndef CS_ARM64_MAP_H
|
||||
#define CS_ARM64_MAP_H
|
||||
|
||||
#include "capstone/capstone.h"
|
||||
|
||||
#define ARR_SIZE(a) (sizeof(a)/sizeof(a[0]))
|
||||
|
||||
// return name of regiser in friendly string
|
||||
const char *AArch64_reg_name(csh handle, unsigned int reg);
|
||||
|
||||
// given internal insn id, return public instruction info
|
||||
void AArch64_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id);
|
||||
|
||||
const char *AArch64_insn_name(csh handle, unsigned int id);
|
||||
|
||||
const char *AArch64_group_name(csh handle, unsigned int id);
|
||||
|
||||
// map instruction name to public instruction ID
|
||||
arm64_insn AArch64_map_insn(const char *name);
|
||||
|
||||
// map internal vregister to public register
|
||||
arm64_reg AArch64_map_vregister(unsigned int r);
|
||||
|
||||
arm64_sys_op AArch64_map_sys_op(const char *name);
|
||||
|
||||
void arm64_op_addReg(MCInst *MI, int reg);
|
||||
|
||||
void arm64_op_addVectorArrSpecifier(MCInst * MI, int sp);
|
||||
|
||||
void arm64_op_addFP(MCInst *MI, float fp);
|
||||
|
||||
void arm64_op_addImm(MCInst *MI, int64_t imm);
|
||||
|
||||
const uint8_t *AArch64_get_op_access(cs_struct *h, unsigned int id);
|
||||
|
||||
void AArch64_reg_access(const cs_insn *insn,
|
||||
cs_regs regs_read, uint8_t *regs_read_count,
|
||||
cs_regs regs_write, uint8_t *regs_write_count);
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,44 @@
|
||||
/* Capstone Disassembly Engine */
|
||||
/* By Dang Hoang Vu <danghvu@gmail.com> 2013 */
|
||||
|
||||
#ifdef CAPSTONE_HAS_ARM64
|
||||
|
||||
#include "../../utils.h"
|
||||
#include "../../MCRegisterInfo.h"
|
||||
#include "AArch64Disassembler.h"
|
||||
#include "AArch64InstPrinter.h"
|
||||
#include "AArch64Mapping.h"
|
||||
#include "AArch64Module.h"
|
||||
|
||||
cs_err AArch64_global_init(cs_struct *ud)
|
||||
{
|
||||
MCRegisterInfo *mri;
|
||||
mri = cs_mem_malloc(sizeof(*mri));
|
||||
|
||||
AArch64_init(mri);
|
||||
ud->printer = AArch64_printInst;
|
||||
ud->printer_info = mri;
|
||||
ud->getinsn_info = mri;
|
||||
ud->disasm = AArch64_getInstruction;
|
||||
ud->reg_name = AArch64_reg_name;
|
||||
ud->insn_id = AArch64_get_insn_id;
|
||||
ud->insn_name = AArch64_insn_name;
|
||||
ud->group_name = AArch64_group_name;
|
||||
ud->post_printer = AArch64_post_printer;
|
||||
#ifndef CAPSTONE_DIET
|
||||
ud->reg_access = AArch64_reg_access;
|
||||
#endif
|
||||
|
||||
return CS_ERR_OK;
|
||||
}
|
||||
|
||||
cs_err AArch64_option(cs_struct *handle, cs_opt_type type, size_t value)
|
||||
{
|
||||
if (type == CS_OPT_MODE) {
|
||||
handle->mode = (cs_mode)value;
|
||||
}
|
||||
|
||||
return CS_ERR_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -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
|
||||
@@ -0,0 +1,698 @@
|
||||
//===-- ARMAddressingModes.h - ARM Addressing Modes -------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains the ARM addressing mode implementation stuff.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/* Capstone Disassembly Engine */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
|
||||
|
||||
#ifndef CS_LLVM_TARGET_ARM_ARMADDRESSINGMODES_H
|
||||
#define CS_LLVM_TARGET_ARM_ARMADDRESSINGMODES_H
|
||||
|
||||
#include "capstone/platform.h"
|
||||
#include "../../MathExtras.h"
|
||||
|
||||
/// ARM_AM - ARM Addressing Mode Stuff
|
||||
typedef enum ARM_AM_ShiftOpc {
|
||||
ARM_AM_no_shift = 0,
|
||||
ARM_AM_asr,
|
||||
ARM_AM_lsl,
|
||||
ARM_AM_lsr,
|
||||
ARM_AM_ror,
|
||||
ARM_AM_rrx
|
||||
} ARM_AM_ShiftOpc;
|
||||
|
||||
typedef enum ARM_AM_AddrOpc {
|
||||
ARM_AM_sub = 0,
|
||||
ARM_AM_add
|
||||
} ARM_AM_AddrOpc;
|
||||
|
||||
static inline const char *ARM_AM_getAddrOpcStr(ARM_AM_AddrOpc Op)
|
||||
{
|
||||
return Op == ARM_AM_sub ? "-" : "";
|
||||
}
|
||||
|
||||
static inline const char *ARM_AM_getShiftOpcStr(ARM_AM_ShiftOpc Op)
|
||||
{
|
||||
switch (Op) {
|
||||
default: return ""; //llvm_unreachable("Unknown shift opc!");
|
||||
case ARM_AM_asr: return "asr";
|
||||
case ARM_AM_lsl: return "lsl";
|
||||
case ARM_AM_lsr: return "lsr";
|
||||
case ARM_AM_ror: return "ror";
|
||||
case ARM_AM_rrx: return "rrx";
|
||||
}
|
||||
}
|
||||
|
||||
static inline unsigned ARM_AM_getShiftOpcEncoding(ARM_AM_ShiftOpc Op)
|
||||
{
|
||||
switch (Op) {
|
||||
default: return (unsigned int)-1; //llvm_unreachable("Unknown shift opc!");
|
||||
case ARM_AM_asr: return 2;
|
||||
case ARM_AM_lsl: return 0;
|
||||
case ARM_AM_lsr: return 1;
|
||||
case ARM_AM_ror: return 3;
|
||||
}
|
||||
}
|
||||
|
||||
typedef enum ARM_AM_AMSubMode {
|
||||
ARM_AM_bad_am_submode = 0,
|
||||
ARM_AM_ia,
|
||||
ARM_AM_ib,
|
||||
ARM_AM_da,
|
||||
ARM_AM_db
|
||||
} ARM_AM_AMSubMode;
|
||||
|
||||
static inline const char *ARM_AM_getAMSubModeStr(ARM_AM_AMSubMode Mode)
|
||||
{
|
||||
switch (Mode) {
|
||||
default: return "";
|
||||
case ARM_AM_ia: return "ia";
|
||||
case ARM_AM_ib: return "ib";
|
||||
case ARM_AM_da: return "da";
|
||||
case ARM_AM_db: return "db";
|
||||
}
|
||||
}
|
||||
|
||||
/// rotr32 - Rotate a 32-bit unsigned value right by a specified # bits.
|
||||
///
|
||||
static inline unsigned rotr32(unsigned Val, unsigned Amt)
|
||||
{
|
||||
//assert(Amt < 32 && "Invalid rotate amount");
|
||||
return (Val >> Amt) | (Val << ((32-Amt)&31));
|
||||
}
|
||||
|
||||
/// rotl32 - Rotate a 32-bit unsigned value left by a specified # bits.
|
||||
///
|
||||
static inline unsigned rotl32(unsigned Val, unsigned Amt)
|
||||
{
|
||||
//assert(Amt < 32 && "Invalid rotate amount");
|
||||
return (Val << Amt) | (Val >> ((32-Amt)&31));
|
||||
}
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Addressing Mode #1: shift_operand with registers
|
||||
//===--------------------------------------------------------------------===//
|
||||
//
|
||||
// This 'addressing mode' is used for arithmetic instructions. It can
|
||||
// represent things like:
|
||||
// reg
|
||||
// reg [asr|lsl|lsr|ror|rrx] reg
|
||||
// reg [asr|lsl|lsr|ror|rrx] imm
|
||||
//
|
||||
// This is stored three operands [rega, regb, opc]. The first is the base
|
||||
// reg, the second is the shift amount (or reg0 if not present or imm). The
|
||||
// third operand encodes the shift opcode and the imm if a reg isn't present.
|
||||
//
|
||||
static inline unsigned getSORegOpc(ARM_AM_ShiftOpc ShOp, unsigned Imm)
|
||||
{
|
||||
return ShOp | (Imm << 3);
|
||||
}
|
||||
|
||||
static inline unsigned getSORegOffset(unsigned Op)
|
||||
{
|
||||
return Op >> 3;
|
||||
}
|
||||
|
||||
static inline ARM_AM_ShiftOpc ARM_AM_getSORegShOp(unsigned Op)
|
||||
{
|
||||
return (ARM_AM_ShiftOpc)(Op & 7);
|
||||
}
|
||||
|
||||
/// getSOImmValImm - Given an encoded imm field for the reg/imm form, return
|
||||
/// the 8-bit imm value.
|
||||
static inline unsigned getSOImmValImm(unsigned Imm)
|
||||
{
|
||||
return Imm & 0xFF;
|
||||
}
|
||||
|
||||
/// getSOImmValRot - Given an encoded imm field for the reg/imm form, return
|
||||
/// the rotate amount.
|
||||
static inline unsigned getSOImmValRot(unsigned Imm)
|
||||
{
|
||||
return (Imm >> 8) * 2;
|
||||
}
|
||||
|
||||
/// getSOImmValRotate - Try to handle Imm with an immediate shifter operand,
|
||||
/// computing the rotate amount to use. If this immediate value cannot be
|
||||
/// handled with a single shifter-op, determine a good rotate amount that will
|
||||
/// take a maximal chunk of bits out of the immediate.
|
||||
static inline unsigned getSOImmValRotate(unsigned Imm)
|
||||
{
|
||||
unsigned TZ, RotAmt;
|
||||
// 8-bit (or less) immediates are trivially shifter_operands with a rotate
|
||||
// of zero.
|
||||
if ((Imm & ~255U) == 0) return 0;
|
||||
|
||||
// Use CTZ to compute the rotate amount.
|
||||
TZ = CountTrailingZeros_32(Imm);
|
||||
|
||||
// Rotate amount must be even. Something like 0x200 must be rotated 8 bits,
|
||||
// not 9.
|
||||
RotAmt = TZ & ~1;
|
||||
|
||||
// If we can handle this spread, return it.
|
||||
if ((rotr32(Imm, RotAmt) & ~255U) == 0)
|
||||
return (32-RotAmt)&31; // HW rotates right, not left.
|
||||
|
||||
// For values like 0xF000000F, we should ignore the low 6 bits, then
|
||||
// retry the hunt.
|
||||
if (Imm & 63U) {
|
||||
unsigned TZ2 = CountTrailingZeros_32(Imm & ~63U);
|
||||
unsigned RotAmt2 = TZ2 & ~1;
|
||||
if ((rotr32(Imm, RotAmt2) & ~255U) == 0)
|
||||
return (32-RotAmt2)&31; // HW rotates right, not left.
|
||||
}
|
||||
|
||||
// Otherwise, we have no way to cover this span of bits with a single
|
||||
// shifter_op immediate. Return a chunk of bits that will be useful to
|
||||
// handle.
|
||||
return (32-RotAmt)&31; // HW rotates right, not left.
|
||||
}
|
||||
|
||||
/// getSOImmVal - Given a 32-bit immediate, if it is something that can fit
|
||||
/// into an shifter_operand immediate operand, return the 12-bit encoding for
|
||||
/// it. If not, return -1.
|
||||
static inline int getSOImmVal(unsigned Arg)
|
||||
{
|
||||
unsigned RotAmt;
|
||||
// 8-bit (or less) immediates are trivially shifter_operands with a rotate
|
||||
// of zero.
|
||||
if ((Arg & ~255U) == 0) return Arg;
|
||||
|
||||
RotAmt = getSOImmValRotate(Arg);
|
||||
|
||||
// If this cannot be handled with a single shifter_op, bail out.
|
||||
if (rotr32(~255U, RotAmt) & Arg)
|
||||
return -1;
|
||||
|
||||
// Encode this correctly.
|
||||
return rotl32(Arg, RotAmt) | ((RotAmt>>1) << 8);
|
||||
}
|
||||
|
||||
/// isSOImmTwoPartVal - Return true if the specified value can be obtained by
|
||||
/// or'ing together two SOImmVal's.
|
||||
static inline bool isSOImmTwoPartVal(unsigned V)
|
||||
{
|
||||
// If this can be handled with a single shifter_op, bail out.
|
||||
V = rotr32(~255U, getSOImmValRotate(V)) & V;
|
||||
if (V == 0)
|
||||
return false;
|
||||
|
||||
// If this can be handled with two shifter_op's, accept.
|
||||
V = rotr32(~255U, getSOImmValRotate(V)) & V;
|
||||
return V == 0;
|
||||
}
|
||||
|
||||
/// getSOImmTwoPartFirst - If V is a value that satisfies isSOImmTwoPartVal,
|
||||
/// return the first chunk of it.
|
||||
static inline unsigned getSOImmTwoPartFirst(unsigned V)
|
||||
{
|
||||
return rotr32(255U, getSOImmValRotate(V)) & V;
|
||||
}
|
||||
|
||||
/// getSOImmTwoPartSecond - If V is a value that satisfies isSOImmTwoPartVal,
|
||||
/// return the second chunk of it.
|
||||
static inline unsigned getSOImmTwoPartSecond(unsigned V)
|
||||
{
|
||||
// Mask out the first hunk.
|
||||
V = rotr32(~255U, getSOImmValRotate(V)) & V;
|
||||
|
||||
// Take what's left.
|
||||
//assert(V == (rotr32(255U, getSOImmValRotate(V)) & V));
|
||||
return V;
|
||||
}
|
||||
|
||||
/// getThumbImmValShift - Try to handle Imm with a 8-bit immediate followed
|
||||
/// by a left shift. Returns the shift amount to use.
|
||||
static inline unsigned getThumbImmValShift(unsigned Imm)
|
||||
{
|
||||
// 8-bit (or less) immediates are trivially immediate operand with a shift
|
||||
// of zero.
|
||||
if ((Imm & ~255U) == 0) return 0;
|
||||
|
||||
// Use CTZ to compute the shift amount.
|
||||
return CountTrailingZeros_32(Imm);
|
||||
}
|
||||
|
||||
/// isThumbImmShiftedVal - Return true if the specified value can be obtained
|
||||
/// by left shifting a 8-bit immediate.
|
||||
static inline bool isThumbImmShiftedVal(unsigned V)
|
||||
{
|
||||
// If this can be handled with
|
||||
V = (~255U << getThumbImmValShift(V)) & V;
|
||||
return V == 0;
|
||||
}
|
||||
|
||||
/// getThumbImm16ValShift - Try to handle Imm with a 16-bit immediate followed
|
||||
/// by a left shift. Returns the shift amount to use.
|
||||
static inline unsigned getThumbImm16ValShift(unsigned Imm)
|
||||
{
|
||||
// 16-bit (or less) immediates are trivially immediate operand with a shift
|
||||
// of zero.
|
||||
if ((Imm & ~65535U) == 0) return 0;
|
||||
|
||||
// Use CTZ to compute the shift amount.
|
||||
return CountTrailingZeros_32(Imm);
|
||||
}
|
||||
|
||||
/// isThumbImm16ShiftedVal - Return true if the specified value can be
|
||||
/// obtained by left shifting a 16-bit immediate.
|
||||
static inline bool isThumbImm16ShiftedVal(unsigned V)
|
||||
{
|
||||
// If this can be handled with
|
||||
V = (~65535U << getThumbImm16ValShift(V)) & V;
|
||||
return V == 0;
|
||||
}
|
||||
|
||||
/// getThumbImmNonShiftedVal - If V is a value that satisfies
|
||||
/// isThumbImmShiftedVal, return the non-shiftd value.
|
||||
static inline unsigned getThumbImmNonShiftedVal(unsigned V)
|
||||
{
|
||||
return V >> getThumbImmValShift(V);
|
||||
}
|
||||
|
||||
|
||||
/// getT2SOImmValSplat - Return the 12-bit encoded representation
|
||||
/// if the specified value can be obtained by splatting the low 8 bits
|
||||
/// into every other byte or every byte of a 32-bit value. i.e.,
|
||||
/// 00000000 00000000 00000000 abcdefgh control = 0
|
||||
/// 00000000 abcdefgh 00000000 abcdefgh control = 1
|
||||
/// abcdefgh 00000000 abcdefgh 00000000 control = 2
|
||||
/// abcdefgh abcdefgh abcdefgh abcdefgh control = 3
|
||||
/// Return -1 if none of the above apply.
|
||||
/// See ARM Reference Manual A6.3.2.
|
||||
static inline int getT2SOImmValSplatVal(unsigned V)
|
||||
{
|
||||
unsigned u, Vs, Imm;
|
||||
// control = 0
|
||||
if ((V & 0xffffff00) == 0)
|
||||
return V;
|
||||
|
||||
// If the value is zeroes in the first byte, just shift those off
|
||||
Vs = ((V & 0xff) == 0) ? V >> 8 : V;
|
||||
// Any passing value only has 8 bits of payload, splatted across the word
|
||||
Imm = Vs & 0xff;
|
||||
// Likewise, any passing values have the payload splatted into the 3rd byte
|
||||
u = Imm | (Imm << 16);
|
||||
|
||||
// control = 1 or 2
|
||||
if (Vs == u)
|
||||
return (((Vs == V) ? 1 : 2) << 8) | Imm;
|
||||
|
||||
// control = 3
|
||||
if (Vs == (u | (u << 8)))
|
||||
return (3 << 8) | Imm;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/// getT2SOImmValRotateVal - Return the 12-bit encoded representation if the
|
||||
/// specified value is a rotated 8-bit value. Return -1 if no rotation
|
||||
/// encoding is possible.
|
||||
/// See ARM Reference Manual A6.3.2.
|
||||
static inline int getT2SOImmValRotateVal(unsigned V)
|
||||
{
|
||||
unsigned RotAmt = CountLeadingZeros_32(V);
|
||||
if (RotAmt >= 24)
|
||||
return -1;
|
||||
|
||||
// If 'Arg' can be handled with a single shifter_op return the value.
|
||||
if ((rotr32(0xff000000U, RotAmt) & V) == V)
|
||||
return (rotr32(V, 24 - RotAmt) & 0x7f) | ((RotAmt + 8) << 7);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/// getT2SOImmVal - Given a 32-bit immediate, if it is something that can fit
|
||||
/// into a Thumb-2 shifter_operand immediate operand, return the 12-bit
|
||||
/// encoding for it. If not, return -1.
|
||||
/// See ARM Reference Manual A6.3.2.
|
||||
static inline int getT2SOImmVal(unsigned Arg)
|
||||
{
|
||||
int Rot;
|
||||
// If 'Arg' is an 8-bit splat, then get the encoded value.
|
||||
int Splat = getT2SOImmValSplatVal(Arg);
|
||||
if (Splat != -1)
|
||||
return Splat;
|
||||
|
||||
// If 'Arg' can be handled with a single shifter_op return the value.
|
||||
Rot = getT2SOImmValRotateVal(Arg);
|
||||
if (Rot != -1)
|
||||
return Rot;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline unsigned getT2SOImmValRotate(unsigned V)
|
||||
{
|
||||
unsigned RotAmt;
|
||||
|
||||
if ((V & ~255U) == 0)
|
||||
return 0;
|
||||
|
||||
// Use CTZ to compute the rotate amount.
|
||||
RotAmt = CountTrailingZeros_32(V);
|
||||
return (32 - RotAmt) & 31;
|
||||
}
|
||||
|
||||
static inline bool isT2SOImmTwoPartVal (unsigned Imm)
|
||||
{
|
||||
unsigned V = Imm;
|
||||
// Passing values can be any combination of splat values and shifter
|
||||
// values. If this can be handled with a single shifter or splat, bail
|
||||
// out. Those should be handled directly, not with a two-part val.
|
||||
if (getT2SOImmValSplatVal(V) != -1)
|
||||
return false;
|
||||
V = rotr32 (~255U, getT2SOImmValRotate(V)) & V;
|
||||
if (V == 0)
|
||||
return false;
|
||||
|
||||
// If this can be handled as an immediate, accept.
|
||||
if (getT2SOImmVal(V) != -1) return true;
|
||||
|
||||
// Likewise, try masking out a splat value first.
|
||||
V = Imm;
|
||||
if (getT2SOImmValSplatVal(V & 0xff00ff00U) != -1)
|
||||
V &= ~0xff00ff00U;
|
||||
else if (getT2SOImmValSplatVal(V & 0x00ff00ffU) != -1)
|
||||
V &= ~0x00ff00ffU;
|
||||
// If what's left can be handled as an immediate, accept.
|
||||
if (getT2SOImmVal(V) != -1) return true;
|
||||
|
||||
// Otherwise, do not accept.
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline unsigned getT2SOImmTwoPartFirst(unsigned Imm)
|
||||
{
|
||||
//assert (isT2SOImmTwoPartVal(Imm) &&
|
||||
// "Immedate cannot be encoded as two part immediate!");
|
||||
// Try a shifter operand as one part
|
||||
unsigned V = rotr32 (~(unsigned int)255, getT2SOImmValRotate(Imm)) & Imm;
|
||||
// If the rest is encodable as an immediate, then return it.
|
||||
if (getT2SOImmVal(V) != -1) return V;
|
||||
|
||||
// Try masking out a splat value first.
|
||||
if (getT2SOImmValSplatVal(Imm & 0xff00ff00U) != -1)
|
||||
return Imm & 0xff00ff00U;
|
||||
|
||||
// The other splat is all that's left as an option.
|
||||
//assert (getT2SOImmValSplatVal(Imm & 0x00ff00ffU) != -1);
|
||||
return Imm & 0x00ff00ffU;
|
||||
}
|
||||
|
||||
static inline unsigned getT2SOImmTwoPartSecond(unsigned Imm)
|
||||
{
|
||||
// Mask out the first hunk
|
||||
Imm ^= getT2SOImmTwoPartFirst(Imm);
|
||||
// Return what's left
|
||||
//assert (getT2SOImmVal(Imm) != -1 &&
|
||||
// "Unable to encode second part of T2 two part SO immediate");
|
||||
return Imm;
|
||||
}
|
||||
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Addressing Mode #2
|
||||
//===--------------------------------------------------------------------===//
|
||||
//
|
||||
// This is used for most simple load/store instructions.
|
||||
//
|
||||
// addrmode2 := reg +/- reg shop imm
|
||||
// addrmode2 := reg +/- imm12
|
||||
//
|
||||
// The first operand is always a Reg. The second operand is a reg if in
|
||||
// reg/reg form, otherwise it's reg#0. The third field encodes the operation
|
||||
// in bit 12, the immediate in bits 0-11, and the shift op in 13-15. The
|
||||
// fourth operand 16-17 encodes the index mode.
|
||||
//
|
||||
// If this addressing mode is a frame index (before prolog/epilog insertion
|
||||
// and code rewriting), this operand will have the form: FI#, reg0, <offs>
|
||||
// with no shift amount for the frame offset.
|
||||
//
|
||||
static inline unsigned ARM_AM_getAM2Opc(ARM_AM_AddrOpc Opc, unsigned Imm12, ARM_AM_ShiftOpc SO,
|
||||
unsigned IdxMode)
|
||||
{
|
||||
//assert(Imm12 < (1 << 12) && "Imm too large!");
|
||||
bool isSub = Opc == ARM_AM_sub;
|
||||
return Imm12 | ((int)isSub << 12) | (SO << 13) | (IdxMode << 16) ;
|
||||
}
|
||||
|
||||
static inline unsigned getAM2Offset(unsigned AM2Opc)
|
||||
{
|
||||
return AM2Opc & ((1 << 12)-1);
|
||||
}
|
||||
|
||||
static inline ARM_AM_AddrOpc getAM2Op(unsigned AM2Opc)
|
||||
{
|
||||
return ((AM2Opc >> 12) & 1) ? ARM_AM_sub : ARM_AM_add;
|
||||
}
|
||||
|
||||
static inline ARM_AM_ShiftOpc getAM2ShiftOpc(unsigned AM2Opc)
|
||||
{
|
||||
return (ARM_AM_ShiftOpc)((AM2Opc >> 13) & 7);
|
||||
}
|
||||
|
||||
static inline unsigned getAM2IdxMode(unsigned AM2Opc)
|
||||
{
|
||||
return (AM2Opc >> 16);
|
||||
}
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Addressing Mode #3
|
||||
//===--------------------------------------------------------------------===//
|
||||
//
|
||||
// This is used for sign-extending loads, and load/store-pair instructions.
|
||||
//
|
||||
// addrmode3 := reg +/- reg
|
||||
// addrmode3 := reg +/- imm8
|
||||
//
|
||||
// The first operand is always a Reg. The second operand is a reg if in
|
||||
// reg/reg form, otherwise it's reg#0. The third field encodes the operation
|
||||
// in bit 8, the immediate in bits 0-7. The fourth operand 9-10 encodes the
|
||||
// index mode.
|
||||
|
||||
/// getAM3Opc - This function encodes the addrmode3 opc field.
|
||||
static inline unsigned getAM3Opc(ARM_AM_AddrOpc Opc, unsigned char Offset,
|
||||
unsigned IdxMode)
|
||||
{
|
||||
bool isSub = Opc == ARM_AM_sub;
|
||||
return ((int)isSub << 8) | Offset | (IdxMode << 9);
|
||||
}
|
||||
|
||||
static inline unsigned char getAM3Offset(unsigned AM3Opc)
|
||||
{
|
||||
return AM3Opc & 0xFF;
|
||||
}
|
||||
|
||||
static inline ARM_AM_AddrOpc getAM3Op(unsigned AM3Opc)
|
||||
{
|
||||
return ((AM3Opc >> 8) & 1) ? ARM_AM_sub : ARM_AM_add;
|
||||
}
|
||||
|
||||
static inline unsigned getAM3IdxMode(unsigned AM3Opc)
|
||||
{
|
||||
return (AM3Opc >> 9);
|
||||
}
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Addressing Mode #4
|
||||
//===--------------------------------------------------------------------===//
|
||||
//
|
||||
// This is used for load / store multiple instructions.
|
||||
//
|
||||
// addrmode4 := reg, <mode>
|
||||
//
|
||||
// The four modes are:
|
||||
// IA - Increment after
|
||||
// IB - Increment before
|
||||
// DA - Decrement after
|
||||
// DB - Decrement before
|
||||
// For VFP instructions, only the IA and DB modes are valid.
|
||||
|
||||
static inline ARM_AM_AMSubMode getAM4SubMode(unsigned Mode)
|
||||
{
|
||||
return (ARM_AM_AMSubMode)(Mode & 0x7);
|
||||
}
|
||||
|
||||
static inline unsigned getAM4ModeImm(ARM_AM_AMSubMode SubMode)
|
||||
{
|
||||
return (int)SubMode;
|
||||
}
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Addressing Mode #5
|
||||
//===--------------------------------------------------------------------===//
|
||||
//
|
||||
// This is used for coprocessor instructions, such as FP load/stores.
|
||||
//
|
||||
// addrmode5 := reg +/- imm8*4
|
||||
//
|
||||
// The first operand is always a Reg. The second operand encodes the
|
||||
// operation in bit 8 and the immediate in bits 0-7.
|
||||
|
||||
/// getAM5Opc - This function encodes the addrmode5 opc field.
|
||||
static inline unsigned ARM_AM_getAM5Opc(ARM_AM_AddrOpc Opc, unsigned char Offset)
|
||||
{
|
||||
bool isSub = Opc == ARM_AM_sub;
|
||||
return ((int)isSub << 8) | Offset;
|
||||
}
|
||||
static inline unsigned char ARM_AM_getAM5Offset(unsigned AM5Opc)
|
||||
{
|
||||
return AM5Opc & 0xFF;
|
||||
}
|
||||
static inline ARM_AM_AddrOpc ARM_AM_getAM5Op(unsigned AM5Opc)
|
||||
{
|
||||
return ((AM5Opc >> 8) & 1) ? ARM_AM_sub : ARM_AM_add;
|
||||
}
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Addressing Mode #5 FP16
|
||||
//===--------------------------------------------------------------------===//
|
||||
//
|
||||
// This is used for coprocessor instructions, such as 16-bit FP load/stores.
|
||||
//
|
||||
// addrmode5fp16 := reg +/- imm8*2
|
||||
//
|
||||
// The first operand is always a Reg. The second operand encodes the
|
||||
// operation (add or subtract) in bit 8 and the immediate in bits 0-7.
|
||||
|
||||
/// getAM5FP16Opc - This function encodes the addrmode5fp16 opc field.
|
||||
static inline unsigned getAM5FP16Opc(ARM_AM_AddrOpc Opc, unsigned char Offset)
|
||||
{
|
||||
bool isSub = Opc == ARM_AM_sub;
|
||||
return ((int)isSub << 8) | Offset;
|
||||
}
|
||||
|
||||
static inline unsigned char getAM5FP16Offset(unsigned AM5Opc)
|
||||
{
|
||||
return AM5Opc & 0xFF;
|
||||
}
|
||||
|
||||
static inline ARM_AM_AddrOpc getAM5FP16Op(unsigned AM5Opc)
|
||||
{
|
||||
return ((AM5Opc >> 8) & 1) ? ARM_AM_sub : ARM_AM_add;
|
||||
}
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Addressing Mode #6
|
||||
//===--------------------------------------------------------------------===//
|
||||
//
|
||||
// This is used for NEON load / store instructions.
|
||||
//
|
||||
// addrmode6 := reg with optional alignment
|
||||
//
|
||||
// This is stored in two operands [regaddr, align]. The first is the
|
||||
// address register. The second operand is the value of the alignment
|
||||
// specifier in bytes or zero if no explicit alignment.
|
||||
// Valid alignments depend on the specific instruction.
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// NEON Modified Immediates
|
||||
//===--------------------------------------------------------------------===//
|
||||
//
|
||||
// Several NEON instructions (e.g., VMOV) take a "modified immediate"
|
||||
// vector operand, where a small immediate encoded in the instruction
|
||||
// specifies a full NEON vector value. These modified immediates are
|
||||
// represented here as encoded integers. The low 8 bits hold the immediate
|
||||
// value; bit 12 holds the "Op" field of the instruction, and bits 11-8 hold
|
||||
// the "Cmode" field of the instruction. The interfaces below treat the
|
||||
// Op and Cmode values as a single 5-bit value.
|
||||
|
||||
static inline unsigned createNEONModImm(unsigned OpCmode, unsigned Val)
|
||||
{
|
||||
return (OpCmode << 8) | Val;
|
||||
}
|
||||
static inline unsigned getNEONModImmOpCmode(unsigned ModImm)
|
||||
{
|
||||
return (ModImm >> 8) & 0x1f;
|
||||
}
|
||||
static inline unsigned getNEONModImmVal(unsigned ModImm)
|
||||
{
|
||||
return ModImm & 0xff;
|
||||
}
|
||||
|
||||
/// decodeNEONModImm - Decode a NEON modified immediate value into the
|
||||
/// element value and the element size in bits. (If the element size is
|
||||
/// smaller than the vector, it is splatted into all the elements.)
|
||||
static inline uint64_t ARM_AM_decodeNEONModImm(unsigned ModImm, unsigned *EltBits)
|
||||
{
|
||||
unsigned OpCmode = getNEONModImmOpCmode(ModImm);
|
||||
unsigned Imm8 = getNEONModImmVal(ModImm);
|
||||
uint64_t Val = 0;
|
||||
unsigned ByteNum;
|
||||
|
||||
if (OpCmode == 0xe) {
|
||||
// 8-bit vector elements
|
||||
Val = Imm8;
|
||||
*EltBits = 8;
|
||||
} else if ((OpCmode & 0xc) == 0x8) {
|
||||
// 16-bit vector elements
|
||||
ByteNum = (OpCmode & 0x6) >> 1;
|
||||
Val = (uint64_t)Imm8 << (8 * ByteNum);
|
||||
*EltBits = 16;
|
||||
} else if ((OpCmode & 0x8) == 0) {
|
||||
// 32-bit vector elements, zero with one byte set
|
||||
ByteNum = (OpCmode & 0x6) >> 1;
|
||||
Val = (uint64_t)Imm8 << (8 * ByteNum);
|
||||
*EltBits = 32;
|
||||
} else if ((OpCmode & 0xe) == 0xc) {
|
||||
// 32-bit vector elements, one byte with low bits set
|
||||
ByteNum = 1 + (OpCmode & 0x1);
|
||||
Val = (Imm8 << (8 * ByteNum)) | (0xffff >> (8 * (2 - ByteNum)));
|
||||
*EltBits = 32;
|
||||
} else if (OpCmode == 0x1e) {
|
||||
// 64-bit vector elements
|
||||
for (ByteNum = 0; ByteNum < 8; ++ByteNum) {
|
||||
if ((ModImm >> ByteNum) & 1)
|
||||
Val |= (uint64_t)0xff << (8 * ByteNum);
|
||||
}
|
||||
*EltBits = 64;
|
||||
} else {
|
||||
//llvm_unreachable("Unsupported NEON immediate");
|
||||
}
|
||||
return Val;
|
||||
}
|
||||
|
||||
ARM_AM_AMSubMode getLoadStoreMultipleSubMode(int Opcode);
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Floating-point Immediates
|
||||
//
|
||||
static inline float getFPImmFloat(unsigned Imm)
|
||||
{
|
||||
// We expect an 8-bit binary encoding of a floating-point number here.
|
||||
union {
|
||||
uint32_t I;
|
||||
float F;
|
||||
} FPUnion;
|
||||
|
||||
uint8_t Sign = (Imm >> 7) & 0x1;
|
||||
uint8_t Exp = (Imm >> 4) & 0x7;
|
||||
uint8_t Mantissa = Imm & 0xf;
|
||||
|
||||
// 8-bit FP iEEEE Float Encoding
|
||||
// abcd efgh aBbbbbbc defgh000 00000000 00000000
|
||||
//
|
||||
// where B = NOT(b);
|
||||
|
||||
FPUnion.I = 0;
|
||||
FPUnion.I |= ((uint32_t) Sign) << 31;
|
||||
FPUnion.I |= ((Exp & 0x4) != 0 ? 0 : 1) << 30;
|
||||
FPUnion.I |= ((Exp & 0x4) != 0 ? 0x1f : 0) << 25;
|
||||
FPUnion.I |= (Exp & 0x3) << 23;
|
||||
FPUnion.I |= Mantissa << 19;
|
||||
return FPUnion.F;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,486 @@
|
||||
//===-- ARMBaseInfo.h - Top level definitions for ARM -------- --*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains small standalone helper functions and enum definitions for
|
||||
// the ARM target useful for the compiler back-end and the MC libraries.
|
||||
// As such, it deliberately does not include references to LLVM core
|
||||
// code gen types, passes, etc..
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/* Capstone Disassembly Engine */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
|
||||
|
||||
#ifndef CS_ARMBASEINFO_H
|
||||
#define CS_ARMBASEINFO_H
|
||||
|
||||
#include "capstone/arm.h"
|
||||
|
||||
// Defines symbolic names for ARM registers. This defines a mapping from
|
||||
// register name to register number.
|
||||
//
|
||||
#define GET_REGINFO_ENUM
|
||||
#include "ARMGenRegisterInfo.inc"
|
||||
|
||||
// Enums corresponding to ARM condition codes
|
||||
// The CondCodes constants map directly to the 4-bit encoding of the
|
||||
// condition field for predicated instructions.
|
||||
typedef enum ARMCC_CondCodes { // Meaning (integer) Meaning (floating-point)
|
||||
ARMCC_EQ, // Equal Equal
|
||||
ARMCC_NE, // Not equal Not equal, or unordered
|
||||
ARMCC_HS, // Carry set >, ==, or unordered
|
||||
ARMCC_LO, // Carry clear Less than
|
||||
ARMCC_MI, // Minus, negative Less than
|
||||
ARMCC_PL, // Plus, positive or zero >, ==, or unordered
|
||||
ARMCC_VS, // Overflow Unordered
|
||||
ARMCC_VC, // No overflow Not unordered
|
||||
ARMCC_HI, // Unsigned higher Greater than, or unordered
|
||||
ARMCC_LS, // Unsigned lower or same Less than or equal
|
||||
ARMCC_GE, // Greater than or equal Greater than or equal
|
||||
ARMCC_LT, // Less than Less than, or unordered
|
||||
ARMCC_GT, // Greater than Greater than
|
||||
ARMCC_LE, // Less than or equal <, ==, or unordered
|
||||
ARMCC_AL // Always (unconditional) Always (unconditional)
|
||||
} ARMCC_CondCodes;
|
||||
|
||||
inline static ARMCC_CondCodes ARMCC_getOppositeCondition(ARMCC_CondCodes CC)
|
||||
{
|
||||
switch (CC) {
|
||||
case ARMCC_EQ: return ARMCC_NE;
|
||||
case ARMCC_NE: return ARMCC_EQ;
|
||||
case ARMCC_HS: return ARMCC_LO;
|
||||
case ARMCC_LO: return ARMCC_HS;
|
||||
case ARMCC_MI: return ARMCC_PL;
|
||||
case ARMCC_PL: return ARMCC_MI;
|
||||
case ARMCC_VS: return ARMCC_VC;
|
||||
case ARMCC_VC: return ARMCC_VS;
|
||||
case ARMCC_HI: return ARMCC_LS;
|
||||
case ARMCC_LS: return ARMCC_HI;
|
||||
case ARMCC_GE: return ARMCC_LT;
|
||||
case ARMCC_LT: return ARMCC_GE;
|
||||
case ARMCC_GT: return ARMCC_LE;
|
||||
case ARMCC_LE: return ARMCC_GT;
|
||||
default: return ARMCC_AL;
|
||||
}
|
||||
}
|
||||
|
||||
inline static const char *ARMCC_ARMCondCodeToString(ARMCC_CondCodes CC)
|
||||
{
|
||||
switch (CC) {
|
||||
case ARMCC_EQ: return "eq";
|
||||
case ARMCC_NE: return "ne";
|
||||
case ARMCC_HS: return "hs";
|
||||
case ARMCC_LO: return "lo";
|
||||
case ARMCC_MI: return "mi";
|
||||
case ARMCC_PL: return "pl";
|
||||
case ARMCC_VS: return "vs";
|
||||
case ARMCC_VC: return "vc";
|
||||
case ARMCC_HI: return "hi";
|
||||
case ARMCC_LS: return "ls";
|
||||
case ARMCC_GE: return "ge";
|
||||
case ARMCC_LT: return "lt";
|
||||
case ARMCC_GT: return "gt";
|
||||
case ARMCC_LE: return "le";
|
||||
case ARMCC_AL: return "al";
|
||||
default: return "";
|
||||
}
|
||||
}
|
||||
|
||||
inline static const char *ARM_PROC_IFlagsToString(unsigned val)
|
||||
{
|
||||
switch (val) {
|
||||
case ARM_CPSFLAG_F: return "f";
|
||||
case ARM_CPSFLAG_I: return "i";
|
||||
case ARM_CPSFLAG_A: return "a";
|
||||
default: return "";
|
||||
}
|
||||
}
|
||||
|
||||
inline static const char *ARM_PROC_IModToString(unsigned val)
|
||||
{
|
||||
switch (val) {
|
||||
case ARM_CPSMODE_IE: return "ie";
|
||||
case ARM_CPSMODE_ID: return "id";
|
||||
default: return "";
|
||||
}
|
||||
}
|
||||
|
||||
inline static const char *ARM_MB_MemBOptToString(unsigned val, bool HasV8)
|
||||
{
|
||||
// TODO: add details
|
||||
switch (val + 1) {
|
||||
default: return "BUGBUG";
|
||||
case ARM_MB_SY: return "sy";
|
||||
case ARM_MB_ST: return "st";
|
||||
case ARM_MB_LD: return HasV8 ? "ld" : "#0xd";
|
||||
case ARM_MB_RESERVED_12: return "#0xc";
|
||||
case ARM_MB_ISH: return "ish";
|
||||
case ARM_MB_ISHST: return "ishst";
|
||||
case ARM_MB_ISHLD: return HasV8 ? "ishld" : "#9";
|
||||
case ARM_MB_RESERVED_8: return "#8";
|
||||
case ARM_MB_NSH: return "nsh";
|
||||
case ARM_MB_NSHST: return "nshst";
|
||||
case ARM_MB_NSHLD: return HasV8 ? "nshld" : "#5";
|
||||
case ARM_MB_RESERVED_4: return "#4";
|
||||
case ARM_MB_OSH: return "osh";
|
||||
case ARM_MB_OSHST: return "oshst";
|
||||
case ARM_MB_OSHLD: return HasV8 ? "oshld" : "#1";
|
||||
case ARM_MB_RESERVED_0: return "#0";
|
||||
}
|
||||
}
|
||||
|
||||
enum ARM_ISB_InstSyncBOpt {
|
||||
ARM_ISB_RESERVED_0 = 0,
|
||||
ARM_ISB_RESERVED_1 = 1,
|
||||
ARM_ISB_RESERVED_2 = 2,
|
||||
ARM_ISB_RESERVED_3 = 3,
|
||||
ARM_ISB_RESERVED_4 = 4,
|
||||
ARM_ISB_RESERVED_5 = 5,
|
||||
ARM_ISB_RESERVED_6 = 6,
|
||||
ARM_ISB_RESERVED_7 = 7,
|
||||
ARM_ISB_RESERVED_8 = 8,
|
||||
ARM_ISB_RESERVED_9 = 9,
|
||||
ARM_ISB_RESERVED_10 = 10,
|
||||
ARM_ISB_RESERVED_11 = 11,
|
||||
ARM_ISB_RESERVED_12 = 12,
|
||||
ARM_ISB_RESERVED_13 = 13,
|
||||
ARM_ISB_RESERVED_14 = 14,
|
||||
ARM_ISB_SY = 15
|
||||
};
|
||||
|
||||
inline static const char *ARM_ISB_InstSyncBOptToString(unsigned val)
|
||||
{
|
||||
switch (val) {
|
||||
default: // never reach
|
||||
case ARM_ISB_RESERVED_0: return "#0x0";
|
||||
case ARM_ISB_RESERVED_1: return "#0x1";
|
||||
case ARM_ISB_RESERVED_2: return "#0x2";
|
||||
case ARM_ISB_RESERVED_3: return "#0x3";
|
||||
case ARM_ISB_RESERVED_4: return "#0x4";
|
||||
case ARM_ISB_RESERVED_5: return "#0x5";
|
||||
case ARM_ISB_RESERVED_6: return "#0x6";
|
||||
case ARM_ISB_RESERVED_7: return "#0x7";
|
||||
case ARM_ISB_RESERVED_8: return "#0x8";
|
||||
case ARM_ISB_RESERVED_9: return "#0x9";
|
||||
case ARM_ISB_RESERVED_10: return "#0xa";
|
||||
case ARM_ISB_RESERVED_11: return "#0xb";
|
||||
case ARM_ISB_RESERVED_12: return "#0xc";
|
||||
case ARM_ISB_RESERVED_13: return "#0xd";
|
||||
case ARM_ISB_RESERVED_14: return "#0xe";
|
||||
case ARM_ISB_SY: return "sy";
|
||||
}
|
||||
}
|
||||
|
||||
/// isARMLowRegister - Returns true if the register is a low register (r0-r7).
|
||||
///
|
||||
static inline bool isARMLowRegister(unsigned Reg)
|
||||
{
|
||||
//using namespace ARM;
|
||||
switch (Reg) {
|
||||
case ARM_R0: case ARM_R1: case ARM_R2: case ARM_R3:
|
||||
case ARM_R4: case ARM_R5: case ARM_R6: case ARM_R7:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// ARMII - This namespace holds all of the target specific flags that
|
||||
/// instruction info tracks.
|
||||
///
|
||||
/// ARM Index Modes
|
||||
enum ARMII_IndexMode {
|
||||
ARMII_IndexModeNone = 0,
|
||||
ARMII_IndexModePre = 1,
|
||||
ARMII_IndexModePost = 2,
|
||||
ARMII_IndexModeUpd = 3
|
||||
};
|
||||
|
||||
/// ARM Addressing Modes
|
||||
typedef enum ARMII_AddrMode {
|
||||
ARMII_AddrModeNone = 0,
|
||||
ARMII_AddrMode1 = 1,
|
||||
ARMII_AddrMode2 = 2,
|
||||
ARMII_AddrMode3 = 3,
|
||||
ARMII_AddrMode4 = 4,
|
||||
ARMII_AddrMode5 = 5,
|
||||
ARMII_AddrMode6 = 6,
|
||||
ARMII_AddrModeT1_1 = 7,
|
||||
ARMII_AddrModeT1_2 = 8,
|
||||
ARMII_AddrModeT1_4 = 9,
|
||||
ARMII_AddrModeT1_s = 10, // i8 * 4 for pc and sp relative data
|
||||
ARMII_AddrModeT2_i12 = 11,
|
||||
ARMII_AddrModeT2_i8 = 12,
|
||||
ARMII_AddrModeT2_so = 13,
|
||||
ARMII_AddrModeT2_pc = 14, // +/- i12 for pc relative data
|
||||
ARMII_AddrModeT2_i8s4 = 15, // i8 * 4
|
||||
ARMII_AddrMode_i12 = 16
|
||||
} ARMII_AddrMode;
|
||||
|
||||
inline static const char *ARMII_AddrModeToString(ARMII_AddrMode addrmode)
|
||||
{
|
||||
switch (addrmode) {
|
||||
case ARMII_AddrModeNone: return "AddrModeNone";
|
||||
case ARMII_AddrMode1: return "AddrMode1";
|
||||
case ARMII_AddrMode2: return "AddrMode2";
|
||||
case ARMII_AddrMode3: return "AddrMode3";
|
||||
case ARMII_AddrMode4: return "AddrMode4";
|
||||
case ARMII_AddrMode5: return "AddrMode5";
|
||||
case ARMII_AddrMode6: return "AddrMode6";
|
||||
case ARMII_AddrModeT1_1: return "AddrModeT1_1";
|
||||
case ARMII_AddrModeT1_2: return "AddrModeT1_2";
|
||||
case ARMII_AddrModeT1_4: return "AddrModeT1_4";
|
||||
case ARMII_AddrModeT1_s: return "AddrModeT1_s";
|
||||
case ARMII_AddrModeT2_i12: return "AddrModeT2_i12";
|
||||
case ARMII_AddrModeT2_i8: return "AddrModeT2_i8";
|
||||
case ARMII_AddrModeT2_so: return "AddrModeT2_so";
|
||||
case ARMII_AddrModeT2_pc: return "AddrModeT2_pc";
|
||||
case ARMII_AddrModeT2_i8s4: return "AddrModeT2_i8s4";
|
||||
case ARMII_AddrMode_i12: return "AddrMode_i12";
|
||||
}
|
||||
}
|
||||
|
||||
/// Target Operand Flag enum.
|
||||
enum ARMII_TOF {
|
||||
//===------------------------------------------------------------------===//
|
||||
// ARM Specific MachineOperand flags.
|
||||
|
||||
ARMII_MO_NO_FLAG,
|
||||
|
||||
/// MO_LO16 - On a symbol operand, this represents a relocation containing
|
||||
/// lower 16 bit of the address. Used only via movw instruction.
|
||||
ARMII_MO_LO16,
|
||||
|
||||
/// MO_HI16 - On a symbol operand, this represents a relocation containing
|
||||
/// higher 16 bit of the address. Used only via movt instruction.
|
||||
ARMII_MO_HI16,
|
||||
|
||||
/// MO_LO16_NONLAZY - On a symbol operand "FOO", this represents a
|
||||
/// relocation containing lower 16 bit of the non-lazy-ptr indirect symbol,
|
||||
/// i.e. "FOO$non_lazy_ptr".
|
||||
/// Used only via movw instruction.
|
||||
ARMII_MO_LO16_NONLAZY,
|
||||
|
||||
/// MO_HI16_NONLAZY - On a symbol operand "FOO", this represents a
|
||||
/// relocation containing lower 16 bit of the non-lazy-ptr indirect symbol,
|
||||
/// i.e. "FOO$non_lazy_ptr". Used only via movt instruction.
|
||||
ARMII_MO_HI16_NONLAZY,
|
||||
|
||||
/// MO_LO16_NONLAZY_PIC - On a symbol operand "FOO", this represents a
|
||||
/// relocation containing lower 16 bit of the PC relative address of the
|
||||
/// non-lazy-ptr indirect symbol, i.e. "FOO$non_lazy_ptr - LABEL".
|
||||
/// Used only via movw instruction.
|
||||
ARMII_MO_LO16_NONLAZY_PIC,
|
||||
|
||||
/// MO_HI16_NONLAZY_PIC - On a symbol operand "FOO", this represents a
|
||||
/// relocation containing lower 16 bit of the PC relative address of the
|
||||
/// non-lazy-ptr indirect symbol, i.e. "FOO$non_lazy_ptr - LABEL".
|
||||
/// Used only via movt instruction.
|
||||
ARMII_MO_HI16_NONLAZY_PIC,
|
||||
|
||||
/// MO_PLT - On a symbol operand, this represents an ELF PLT reference on a
|
||||
/// call operand.
|
||||
ARMII_MO_PLT
|
||||
};
|
||||
|
||||
enum {
|
||||
//===------------------------------------------------------------------===//
|
||||
// Instruction Flags.
|
||||
|
||||
//===------------------------------------------------------------------===//
|
||||
// This four-bit field describes the addressing mode used.
|
||||
ARMII_AddrModeMask = 0x1f, // The AddrMode enums are declared in ARMBaseInfo.h
|
||||
|
||||
// IndexMode - Unindex, pre-indexed, or post-indexed are valid for load
|
||||
// and store ops only. Generic "updating" flag is used for ld/st multiple.
|
||||
// The index mode enums are declared in ARMBaseInfo.h
|
||||
ARMII_IndexModeShift = 5,
|
||||
ARMII_IndexModeMask = 3 << ARMII_IndexModeShift,
|
||||
|
||||
//===------------------------------------------------------------------===//
|
||||
// Instruction encoding formats.
|
||||
//
|
||||
ARMII_FormShift = 7,
|
||||
ARMII_FormMask = 0x3f << ARMII_FormShift,
|
||||
|
||||
// Pseudo instructions
|
||||
ARMII_Pseudo = 0 << ARMII_FormShift,
|
||||
|
||||
// Multiply instructions
|
||||
ARMII_MulFrm = 1 << ARMII_FormShift,
|
||||
|
||||
// Branch instructions
|
||||
ARMII_BrFrm = 2 << ARMII_FormShift,
|
||||
ARMII_BrMiscFrm = 3 << ARMII_FormShift,
|
||||
|
||||
// Data Processing instructions
|
||||
ARMII_DPFrm = 4 << ARMII_FormShift,
|
||||
ARMII_DPSoRegFrm = 5 << ARMII_FormShift,
|
||||
|
||||
// Load and Store
|
||||
ARMII_LdFrm = 6 << ARMII_FormShift,
|
||||
ARMII_StFrm = 7 << ARMII_FormShift,
|
||||
ARMII_LdMiscFrm = 8 << ARMII_FormShift,
|
||||
ARMII_StMiscFrm = 9 << ARMII_FormShift,
|
||||
ARMII_LdStMulFrm = 10 << ARMII_FormShift,
|
||||
|
||||
ARMII_LdStExFrm = 11 << ARMII_FormShift,
|
||||
|
||||
// Miscellaneous arithmetic instructions
|
||||
ARMII_ArithMiscFrm = 12 << ARMII_FormShift,
|
||||
ARMII_SatFrm = 13 << ARMII_FormShift,
|
||||
|
||||
// Extend instructions
|
||||
ARMII_ExtFrm = 14 << ARMII_FormShift,
|
||||
|
||||
// VFP formats
|
||||
ARMII_VFPUnaryFrm = 15 << ARMII_FormShift,
|
||||
ARMII_VFPBinaryFrm = 16 << ARMII_FormShift,
|
||||
ARMII_VFPConv1Frm = 17 << ARMII_FormShift,
|
||||
ARMII_VFPConv2Frm = 18 << ARMII_FormShift,
|
||||
ARMII_VFPConv3Frm = 19 << ARMII_FormShift,
|
||||
ARMII_VFPConv4Frm = 20 << ARMII_FormShift,
|
||||
ARMII_VFPConv5Frm = 21 << ARMII_FormShift,
|
||||
ARMII_VFPLdStFrm = 22 << ARMII_FormShift,
|
||||
ARMII_VFPLdStMulFrm = 23 << ARMII_FormShift,
|
||||
ARMII_VFPMiscFrm = 24 << ARMII_FormShift,
|
||||
|
||||
// Thumb format
|
||||
ARMII_ThumbFrm = 25 << ARMII_FormShift,
|
||||
|
||||
// Miscelleaneous format
|
||||
ARMII_MiscFrm = 26 << ARMII_FormShift,
|
||||
|
||||
// NEON formats
|
||||
ARMII_NGetLnFrm = 27 << ARMII_FormShift,
|
||||
ARMII_NSetLnFrm = 28 << ARMII_FormShift,
|
||||
ARMII_NDupFrm = 29 << ARMII_FormShift,
|
||||
ARMII_NLdStFrm = 30 << ARMII_FormShift,
|
||||
ARMII_N1RegModImmFrm= 31 << ARMII_FormShift,
|
||||
ARMII_N2RegFrm = 32 << ARMII_FormShift,
|
||||
ARMII_NVCVTFrm = 33 << ARMII_FormShift,
|
||||
ARMII_NVDupLnFrm = 34 << ARMII_FormShift,
|
||||
ARMII_N2RegVShLFrm = 35 << ARMII_FormShift,
|
||||
ARMII_N2RegVShRFrm = 36 << ARMII_FormShift,
|
||||
ARMII_N3RegFrm = 37 << ARMII_FormShift,
|
||||
ARMII_N3RegVShFrm = 38 << ARMII_FormShift,
|
||||
ARMII_NVExtFrm = 39 << ARMII_FormShift,
|
||||
ARMII_NVMulSLFrm = 40 << ARMII_FormShift,
|
||||
ARMII_NVTBLFrm = 41 << ARMII_FormShift,
|
||||
|
||||
//===------------------------------------------------------------------===//
|
||||
// Misc flags.
|
||||
|
||||
// UnaryDP - Indicates this is a unary data processing instruction, i.e.
|
||||
// it doesn't have a Rn operand.
|
||||
ARMII_UnaryDP = 1 << 13,
|
||||
|
||||
// Xform16Bit - Indicates this Thumb2 instruction may be transformed into
|
||||
// a 16-bit Thumb instruction if certain conditions are met.
|
||||
ARMII_Xform16Bit = 1 << 14,
|
||||
|
||||
// ThumbArithFlagSetting - The instruction is a 16-bit flag setting Thumb
|
||||
// instruction. Used by the parser to determine whether to require the 'S'
|
||||
// suffix on the mnemonic (when not in an IT block) or preclude it (when
|
||||
// in an IT block).
|
||||
ARMII_ThumbArithFlagSetting = 1 << 18,
|
||||
|
||||
//===------------------------------------------------------------------===//
|
||||
// Code domain.
|
||||
ARMII_DomainShift = 15,
|
||||
ARMII_DomainMask = 7 << ARMII_DomainShift,
|
||||
ARMII_DomainGeneral = 0 << ARMII_DomainShift,
|
||||
ARMII_DomainVFP = 1 << ARMII_DomainShift,
|
||||
ARMII_DomainNEON = 2 << ARMII_DomainShift,
|
||||
ARMII_DomainNEONA8 = 4 << ARMII_DomainShift,
|
||||
|
||||
//===------------------------------------------------------------------===//
|
||||
// Field shifts - such shifts are used to set field while generating
|
||||
// machine instructions.
|
||||
//
|
||||
// FIXME: This list will need adjusting/fixing as the MC code emitter
|
||||
// takes shape and the ARMCodeEmitter.cpp bits go away.
|
||||
ARMII_ShiftTypeShift = 4,
|
||||
|
||||
ARMII_M_BitShift = 5,
|
||||
ARMII_ShiftImmShift = 5,
|
||||
ARMII_ShiftShift = 7,
|
||||
ARMII_N_BitShift = 7,
|
||||
ARMII_ImmHiShift = 8,
|
||||
ARMII_SoRotImmShift = 8,
|
||||
ARMII_RegRsShift = 8,
|
||||
ARMII_ExtRotImmShift = 10,
|
||||
ARMII_RegRdLoShift = 12,
|
||||
ARMII_RegRdShift = 12,
|
||||
ARMII_RegRdHiShift = 16,
|
||||
ARMII_RegRnShift = 16,
|
||||
ARMII_S_BitShift = 20,
|
||||
ARMII_W_BitShift = 21,
|
||||
ARMII_AM3_I_BitShift = 22,
|
||||
ARMII_D_BitShift = 22,
|
||||
ARMII_U_BitShift = 23,
|
||||
ARMII_P_BitShift = 24,
|
||||
ARMII_I_BitShift = 25,
|
||||
ARMII_CondShift = 28
|
||||
};
|
||||
|
||||
typedef struct MClassSysReg {
|
||||
const char *Name;
|
||||
arm_sysreg sysreg;
|
||||
uint16_t M1Encoding12;
|
||||
uint16_t M2M3Encoding8;
|
||||
uint16_t Encoding;
|
||||
int FeaturesRequired[2]; // 2 is enough for MClassSysRegsList
|
||||
} MClassSysReg;
|
||||
|
||||
enum TraceSyncBOpt {
|
||||
CSYNC = 0
|
||||
};
|
||||
|
||||
const MClassSysReg *lookupMClassSysRegByM2M3Encoding8(uint16_t encoding);
|
||||
const MClassSysReg *lookupMClassSysRegByM1Encoding12(uint16_t M1Encoding12);
|
||||
|
||||
// returns APSR with _<bits> qualifier.
|
||||
// Note: ARMv7-M deprecates using MSR APSR without a _<bits> qualifier
|
||||
static inline const MClassSysReg *lookupMClassSysRegAPSRNonDeprecated(unsigned SYSm)
|
||||
{
|
||||
return lookupMClassSysRegByM2M3Encoding8((1<<9) | (SYSm & 0xFF));
|
||||
}
|
||||
|
||||
static inline const MClassSysReg *lookupMClassSysRegBy8bitSYSmValue(unsigned SYSm)
|
||||
{
|
||||
return lookupMClassSysRegByM2M3Encoding8((1<<8) | (SYSm & 0xFF));
|
||||
}
|
||||
|
||||
// returns true if TestFeatures are all present in FeaturesRequired
|
||||
static inline bool MClassSysReg_isInRequiredFeatures(const MClassSysReg *TheReg, int TestFeatures)
|
||||
{
|
||||
return (TheReg->FeaturesRequired[0] == TestFeatures || TheReg->FeaturesRequired[1] == TestFeatures);
|
||||
}
|
||||
|
||||
// lookup system register using 12-bit SYSm value.
|
||||
// Note: the search is uniqued using M1 mask
|
||||
static inline const MClassSysReg *lookupMClassSysRegBy12bitSYSmValue(unsigned SYSm)
|
||||
{
|
||||
return lookupMClassSysRegByM1Encoding12(SYSm);
|
||||
}
|
||||
|
||||
static inline const char *ARM_TSB_TraceSyncBOptToString(unsigned val)
|
||||
{
|
||||
switch (val) {
|
||||
default:
|
||||
// llvm_unreachable("Unknown trace synchronization barrier operation");
|
||||
return NULL;
|
||||
|
||||
case CSYNC:
|
||||
return "csync";
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,18 @@
|
||||
/* Capstone Disassembly Engine */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
|
||||
|
||||
#ifndef CS_ARMDISASSEMBLER_H
|
||||
#define CS_ARMDISASSEMBLER_H
|
||||
|
||||
#include "capstone/capstone.h"
|
||||
#include "../../MCRegisterInfo.h"
|
||||
|
||||
void ARM_init(MCRegisterInfo *MRI);
|
||||
|
||||
bool ARM_getInstruction(csh handle, const uint8_t *code, size_t code_len, MCInst *instr, uint16_t *size, uint64_t address, void *info);
|
||||
|
||||
bool Thumb_getInstruction(csh handle, const uint8_t *code, size_t code_len, MCInst *instr, uint16_t *size, uint64_t address, void *info);
|
||||
|
||||
bool ARM_getFeatureBits(unsigned int mode, unsigned int feature);
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,231 @@
|
||||
/* Capstone Disassembly Engine, http://www.capstone-engine.org */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
|
||||
|
||||
/// getRegisterName - This method is automatically generated by tblgen
|
||||
/// from the register set description. This returns the assembler name
|
||||
/// for the specified register.
|
||||
static const char *getRegisterName(unsigned RegNo)
|
||||
{
|
||||
|
||||
#ifndef CAPSTONE_DIET
|
||||
static const char AsmStrs[] = {
|
||||
/* 0 */ 'D', '4', '_', 'D', '6', '_', 'D', '8', '_', 'D', '1', '0', 0,
|
||||
/* 13 */ 'D', '7', '_', 'D', '8', '_', 'D', '9', '_', 'D', '1', '0', 0,
|
||||
/* 26 */ 'Q', '7', '_', 'Q', '8', '_', 'Q', '9', '_', 'Q', '1', '0', 0,
|
||||
/* 39 */ 'd', '1', '0', 0,
|
||||
/* 43 */ 'q', '1', '0', 0,
|
||||
/* 47 */ 's', '1', '0', 0,
|
||||
/* 51 */ 'D', '1', '4', '_', 'D', '1', '6', '_', 'D', '1', '8', '_', 'D', '2', '0', 0,
|
||||
/* 67 */ 'D', '1', '7', '_', 'D', '1', '8', '_', 'D', '1', '9', '_', 'D', '2', '0', 0,
|
||||
/* 83 */ 'd', '2', '0', 0,
|
||||
/* 87 */ 's', '2', '0', 0,
|
||||
/* 91 */ 'D', '2', '4', '_', 'D', '2', '6', '_', 'D', '2', '8', '_', 'D', '3', '0', 0,
|
||||
/* 107 */ 'D', '2', '7', '_', 'D', '2', '8', '_', 'D', '2', '9', '_', 'D', '3', '0', 0,
|
||||
/* 123 */ 'd', '3', '0', 0,
|
||||
/* 127 */ 's', '3', '0', 0,
|
||||
/* 131 */ 'd', '0', 0,
|
||||
/* 134 */ 'q', '0', 0,
|
||||
/* 137 */ 'm', 'v', 'f', 'r', '0', 0,
|
||||
/* 143 */ 's', '0', 0,
|
||||
/* 146 */ 'D', '9', '_', 'D', '1', '0', '_', 'D', '1', '1', 0,
|
||||
/* 157 */ 'D', '5', '_', 'D', '7', '_', 'D', '9', '_', 'D', '1', '1', 0,
|
||||
/* 170 */ 'Q', '8', '_', 'Q', '9', '_', 'Q', '1', '0', '_', 'Q', '1', '1', 0,
|
||||
/* 184 */ 'R', '1', '0', '_', 'R', '1', '1', 0,
|
||||
/* 192 */ 'd', '1', '1', 0,
|
||||
/* 196 */ 'q', '1', '1', 0,
|
||||
/* 200 */ 's', '1', '1', 0,
|
||||
/* 204 */ 'D', '1', '9', '_', 'D', '2', '0', '_', 'D', '2', '1', 0,
|
||||
/* 216 */ 'D', '1', '5', '_', 'D', '1', '7', '_', 'D', '1', '9', '_', 'D', '2', '1', 0,
|
||||
/* 232 */ 'd', '2', '1', 0,
|
||||
/* 236 */ 's', '2', '1', 0,
|
||||
/* 240 */ 'D', '2', '9', '_', 'D', '3', '0', '_', 'D', '3', '1', 0,
|
||||
/* 252 */ 'D', '2', '5', '_', 'D', '2', '7', '_', 'D', '2', '9', '_', 'D', '3', '1', 0,
|
||||
/* 268 */ 'd', '3', '1', 0,
|
||||
/* 272 */ 's', '3', '1', 0,
|
||||
/* 276 */ 'Q', '0', '_', 'Q', '1', 0,
|
||||
/* 282 */ 'R', '0', '_', 'R', '1', 0,
|
||||
/* 288 */ 'd', '1', 0,
|
||||
/* 291 */ 'q', '1', 0,
|
||||
/* 294 */ 'm', 'v', 'f', 'r', '1', 0,
|
||||
/* 300 */ 's', '1', 0,
|
||||
/* 303 */ 'D', '6', '_', 'D', '8', '_', 'D', '1', '0', '_', 'D', '1', '2', 0,
|
||||
/* 317 */ 'D', '9', '_', 'D', '1', '0', '_', 'D', '1', '1', '_', 'D', '1', '2', 0,
|
||||
/* 332 */ 'Q', '9', '_', 'Q', '1', '0', '_', 'Q', '1', '1', '_', 'Q', '1', '2', 0,
|
||||
/* 347 */ 'd', '1', '2', 0,
|
||||
/* 351 */ 'q', '1', '2', 0,
|
||||
/* 355 */ 's', '1', '2', 0,
|
||||
/* 359 */ 'D', '1', '6', '_', 'D', '1', '8', '_', 'D', '2', '0', '_', 'D', '2', '2', 0,
|
||||
/* 375 */ 'D', '1', '9', '_', 'D', '2', '0', '_', 'D', '2', '1', '_', 'D', '2', '2', 0,
|
||||
/* 391 */ 'd', '2', '2', 0,
|
||||
/* 395 */ 's', '2', '2', 0,
|
||||
/* 399 */ 'D', '0', '_', 'D', '2', 0,
|
||||
/* 405 */ 'D', '0', '_', 'D', '1', '_', 'D', '2', 0,
|
||||
/* 414 */ 'Q', '1', '_', 'Q', '2', 0,
|
||||
/* 420 */ 'd', '2', 0,
|
||||
/* 423 */ 'q', '2', 0,
|
||||
/* 426 */ 'm', 'v', 'f', 'r', '2', 0,
|
||||
/* 432 */ 's', '2', 0,
|
||||
/* 435 */ 'f', 'p', 'i', 'n', 's', 't', '2', 0,
|
||||
/* 443 */ 'D', '7', '_', 'D', '9', '_', 'D', '1', '1', '_', 'D', '1', '3', 0,
|
||||
/* 457 */ 'D', '1', '1', '_', 'D', '1', '2', '_', 'D', '1', '3', 0,
|
||||
/* 469 */ 'Q', '1', '0', '_', 'Q', '1', '1', '_', 'Q', '1', '2', '_', 'Q', '1', '3', 0,
|
||||
/* 485 */ 'd', '1', '3', 0,
|
||||
/* 489 */ 'q', '1', '3', 0,
|
||||
/* 493 */ 's', '1', '3', 0,
|
||||
/* 497 */ 'D', '1', '7', '_', 'D', '1', '9', '_', 'D', '2', '1', '_', 'D', '2', '3', 0,
|
||||
/* 513 */ 'D', '2', '1', '_', 'D', '2', '2', '_', 'D', '2', '3', 0,
|
||||
/* 525 */ 'd', '2', '3', 0,
|
||||
/* 529 */ 's', '2', '3', 0,
|
||||
/* 533 */ 'D', '1', '_', 'D', '3', 0,
|
||||
/* 539 */ 'D', '1', '_', 'D', '2', '_', 'D', '3', 0,
|
||||
/* 548 */ 'Q', '0', '_', 'Q', '1', '_', 'Q', '2', '_', 'Q', '3', 0,
|
||||
/* 560 */ 'R', '2', '_', 'R', '3', 0,
|
||||
/* 566 */ 'd', '3', 0,
|
||||
/* 569 */ 'q', '3', 0,
|
||||
/* 572 */ 'r', '3', 0,
|
||||
/* 575 */ 's', '3', 0,
|
||||
/* 578 */ 'D', '8', '_', 'D', '1', '0', '_', 'D', '1', '2', '_', 'D', '1', '4', 0,
|
||||
/* 593 */ 'D', '1', '1', '_', 'D', '1', '2', '_', 'D', '1', '3', '_', 'D', '1', '4', 0,
|
||||
/* 609 */ 'Q', '1', '1', '_', 'Q', '1', '2', '_', 'Q', '1', '3', '_', 'Q', '1', '4', 0,
|
||||
/* 625 */ 'd', '1', '4', 0,
|
||||
/* 629 */ 'q', '1', '4', 0,
|
||||
/* 633 */ 's', '1', '4', 0,
|
||||
/* 637 */ 'D', '1', '8', '_', 'D', '2', '0', '_', 'D', '2', '2', '_', 'D', '2', '4', 0,
|
||||
/* 653 */ 'D', '2', '1', '_', 'D', '2', '2', '_', 'D', '2', '3', '_', 'D', '2', '4', 0,
|
||||
/* 669 */ 'd', '2', '4', 0,
|
||||
/* 673 */ 's', '2', '4', 0,
|
||||
/* 677 */ 'D', '0', '_', 'D', '2', '_', 'D', '4', 0,
|
||||
/* 686 */ 'D', '1', '_', 'D', '2', '_', 'D', '3', '_', 'D', '4', 0,
|
||||
/* 698 */ 'Q', '1', '_', 'Q', '2', '_', 'Q', '3', '_', 'Q', '4', 0,
|
||||
/* 710 */ 'd', '4', 0,
|
||||
/* 713 */ 'q', '4', 0,
|
||||
/* 716 */ 'r', '4', 0,
|
||||
/* 719 */ 's', '4', 0,
|
||||
/* 722 */ 'D', '9', '_', 'D', '1', '1', '_', 'D', '1', '3', '_', 'D', '1', '5', 0,
|
||||
/* 737 */ 'D', '1', '3', '_', 'D', '1', '4', '_', 'D', '1', '5', 0,
|
||||
/* 749 */ 'Q', '1', '2', '_', 'Q', '1', '3', '_', 'Q', '1', '4', '_', 'Q', '1', '5', 0,
|
||||
/* 765 */ 'd', '1', '5', 0,
|
||||
/* 769 */ 'q', '1', '5', 0,
|
||||
/* 773 */ 's', '1', '5', 0,
|
||||
/* 777 */ 'D', '1', '9', '_', 'D', '2', '1', '_', 'D', '2', '3', '_', 'D', '2', '5', 0,
|
||||
/* 793 */ 'D', '2', '3', '_', 'D', '2', '4', '_', 'D', '2', '5', 0,
|
||||
/* 805 */ 'd', '2', '5', 0,
|
||||
/* 809 */ 's', '2', '5', 0,
|
||||
/* 813 */ 'D', '1', '_', 'D', '3', '_', 'D', '5', 0,
|
||||
/* 822 */ 'D', '3', '_', 'D', '4', '_', 'D', '5', 0,
|
||||
/* 831 */ 'Q', '2', '_', 'Q', '3', '_', 'Q', '4', '_', 'Q', '5', 0,
|
||||
/* 843 */ 'R', '4', '_', 'R', '5', 0,
|
||||
/* 849 */ 'd', '5', 0,
|
||||
/* 852 */ 'q', '5', 0,
|
||||
/* 855 */ 'r', '5', 0,
|
||||
/* 858 */ 's', '5', 0,
|
||||
/* 861 */ 'D', '1', '0', '_', 'D', '1', '2', '_', 'D', '1', '4', '_', 'D', '1', '6', 0,
|
||||
/* 877 */ 'D', '1', '3', '_', 'D', '1', '4', '_', 'D', '1', '5', '_', 'D', '1', '6', 0,
|
||||
/* 893 */ 'd', '1', '6', 0,
|
||||
/* 897 */ 's', '1', '6', 0,
|
||||
/* 901 */ 'D', '2', '0', '_', 'D', '2', '2', '_', 'D', '2', '4', '_', 'D', '2', '6', 0,
|
||||
/* 917 */ 'D', '2', '3', '_', 'D', '2', '4', '_', 'D', '2', '5', '_', 'D', '2', '6', 0,
|
||||
/* 933 */ 'd', '2', '6', 0,
|
||||
/* 937 */ 's', '2', '6', 0,
|
||||
/* 941 */ 'D', '0', '_', 'D', '2', '_', 'D', '4', '_', 'D', '6', 0,
|
||||
/* 953 */ 'D', '3', '_', 'D', '4', '_', 'D', '5', '_', 'D', '6', 0,
|
||||
/* 965 */ 'Q', '3', '_', 'Q', '4', '_', 'Q', '5', '_', 'Q', '6', 0,
|
||||
/* 977 */ 'd', '6', 0,
|
||||
/* 980 */ 'q', '6', 0,
|
||||
/* 983 */ 'r', '6', 0,
|
||||
/* 986 */ 's', '6', 0,
|
||||
/* 989 */ 'D', '1', '1', '_', 'D', '1', '3', '_', 'D', '1', '5', '_', 'D', '1', '7', 0,
|
||||
/* 1005 */ 'D', '1', '5', '_', 'D', '1', '6', '_', 'D', '1', '7', 0,
|
||||
/* 1017 */ 'd', '1', '7', 0,
|
||||
/* 1021 */ 's', '1', '7', 0,
|
||||
/* 1025 */ 'D', '2', '1', '_', 'D', '2', '3', '_', 'D', '2', '5', '_', 'D', '2', '7', 0,
|
||||
/* 1041 */ 'D', '2', '5', '_', 'D', '2', '6', '_', 'D', '2', '7', 0,
|
||||
/* 1053 */ 'd', '2', '7', 0,
|
||||
/* 1057 */ 's', '2', '7', 0,
|
||||
/* 1061 */ 'D', '1', '_', 'D', '3', '_', 'D', '5', '_', 'D', '7', 0,
|
||||
/* 1073 */ 'D', '5', '_', 'D', '6', '_', 'D', '7', 0,
|
||||
/* 1082 */ 'Q', '4', '_', 'Q', '5', '_', 'Q', '6', '_', 'Q', '7', 0,
|
||||
/* 1094 */ 'R', '6', '_', 'R', '7', 0,
|
||||
/* 1100 */ 'd', '7', 0,
|
||||
/* 1103 */ 'q', '7', 0,
|
||||
/* 1106 */ 'r', '7', 0,
|
||||
/* 1109 */ 's', '7', 0,
|
||||
/* 1112 */ 'D', '1', '2', '_', 'D', '1', '4', '_', 'D', '1', '6', '_', 'D', '1', '8', 0,
|
||||
/* 1128 */ 'D', '1', '5', '_', 'D', '1', '6', '_', 'D', '1', '7', '_', 'D', '1', '8', 0,
|
||||
/* 1144 */ 'd', '1', '8', 0,
|
||||
/* 1148 */ 's', '1', '8', 0,
|
||||
/* 1152 */ 'D', '2', '2', '_', 'D', '2', '4', '_', 'D', '2', '6', '_', 'D', '2', '8', 0,
|
||||
/* 1168 */ 'D', '2', '5', '_', 'D', '2', '6', '_', 'D', '2', '7', '_', 'D', '2', '8', 0,
|
||||
/* 1184 */ 'd', '2', '8', 0,
|
||||
/* 1188 */ 's', '2', '8', 0,
|
||||
/* 1192 */ 'D', '2', '_', 'D', '4', '_', 'D', '6', '_', 'D', '8', 0,
|
||||
/* 1204 */ 'D', '5', '_', 'D', '6', '_', 'D', '7', '_', 'D', '8', 0,
|
||||
/* 1216 */ 'Q', '5', '_', 'Q', '6', '_', 'Q', '7', '_', 'Q', '8', 0,
|
||||
/* 1228 */ 'd', '8', 0,
|
||||
/* 1231 */ 'q', '8', 0,
|
||||
/* 1234 */ 'r', '8', 0,
|
||||
/* 1237 */ 's', '8', 0,
|
||||
/* 1240 */ 'D', '1', '3', '_', 'D', '1', '5', '_', 'D', '1', '7', '_', 'D', '1', '9', 0,
|
||||
/* 1256 */ 'D', '1', '7', '_', 'D', '1', '8', '_', 'D', '1', '9', 0,
|
||||
/* 1268 */ 'd', '1', '9', 0,
|
||||
/* 1272 */ 's', '1', '9', 0,
|
||||
/* 1276 */ 'D', '2', '3', '_', 'D', '2', '5', '_', 'D', '2', '7', '_', 'D', '2', '9', 0,
|
||||
/* 1292 */ 'D', '2', '7', '_', 'D', '2', '8', '_', 'D', '2', '9', 0,
|
||||
/* 1304 */ 'd', '2', '9', 0,
|
||||
/* 1308 */ 's', '2', '9', 0,
|
||||
/* 1312 */ 'D', '3', '_', 'D', '5', '_', 'D', '7', '_', 'D', '9', 0,
|
||||
/* 1324 */ 'D', '7', '_', 'D', '8', '_', 'D', '9', 0,
|
||||
/* 1333 */ 'Q', '6', '_', 'Q', '7', '_', 'Q', '8', '_', 'Q', '9', 0,
|
||||
/* 1345 */ 'R', '8', '_', 'R', '9', 0,
|
||||
/* 1351 */ 'd', '9', 0,
|
||||
/* 1354 */ 'q', '9', 0,
|
||||
/* 1357 */ 's', '9', 0,
|
||||
/* 1360 */ 'R', '1', '2', '_', 'S', 'P', 0,
|
||||
/* 1367 */ 's', 'b', 0,
|
||||
/* 1370 */ 'p', 'c', 0,
|
||||
/* 1373 */ 'f', 'p', 'e', 'x', 'c', 0,
|
||||
/* 1379 */ 'f', 'p', 's', 'i', 'd', 0,
|
||||
/* 1385 */ 'i', 't', 's', 't', 'a', 't', 'e', 0,
|
||||
/* 1393 */ 's', 'l', 0,
|
||||
/* 1396 */ 'f', 'p', 0,
|
||||
/* 1399 */ 'i', 'p', 0,
|
||||
/* 1402 */ 's', 'p', 0,
|
||||
/* 1405 */ 'f', 'p', 's', 'c', 'r', 0,
|
||||
/* 1411 */ 'l', 'r', 0,
|
||||
/* 1414 */ 'a', 'p', 's', 'r', 0,
|
||||
/* 1419 */ 'c', 'p', 's', 'r', 0,
|
||||
/* 1424 */ 's', 'p', 's', 'r', 0,
|
||||
/* 1429 */ 'f', 'p', 'i', 'n', 's', 't', 0,
|
||||
/* 1436 */ 'f', 'p', 's', 'c', 'r', '_', 'n', 'z', 'c', 'v', 0,
|
||||
/* 1447 */ 'a', 'p', 's', 'r', '_', 'n', 'z', 'c', 'v', 0,
|
||||
};
|
||||
|
||||
static const uint16_t RegAsmOffset[] = {
|
||||
1414, 1447, 1419, 1373, 1429, 1405, 1436, 1379, 1385, 1411, 1370, 1402, 1424, 131,
|
||||
288, 420, 566, 710, 849, 977, 1100, 1228, 1351, 39, 192, 347, 485, 625,
|
||||
765, 893, 1017, 1144, 1268, 83, 232, 391, 525, 669, 805, 933, 1053, 1184,
|
||||
1304, 123, 268, 435, 137, 294, 426, 134, 291, 423, 569, 713, 852, 980,
|
||||
1103, 1231, 1354, 43, 196, 351, 489, 629, 769, 140, 297, 429, 572, 716,
|
||||
855, 983, 1106, 1234, 1367, 1393, 1396, 1399, 143, 300, 432, 575, 719, 858,
|
||||
986, 1109, 1237, 1357, 47, 200, 355, 493, 633, 773, 897, 1021, 1148, 1272,
|
||||
87, 236, 395, 529, 673, 809, 937, 1057, 1188, 1308, 127, 272, 399, 533,
|
||||
680, 816, 947, 1067, 1198, 1318, 6, 163, 309, 449, 585, 729, 869, 997,
|
||||
1120, 1248, 59, 224, 367, 505, 645, 785, 909, 1033, 1160, 1284, 99, 260,
|
||||
276, 414, 554, 704, 837, 971, 1088, 1222, 1339, 32, 176, 339, 477, 617,
|
||||
757, 548, 698, 831, 965, 1082, 1216, 1333, 26, 170, 332, 469, 609, 749,
|
||||
1360, 282, 560, 843, 1094, 1345, 184, 405, 539, 689, 822, 956, 1073, 1207,
|
||||
1324, 16, 146, 320, 457, 597, 737, 881, 1005, 1132, 1256, 71, 204, 379,
|
||||
513, 657, 793, 921, 1041, 1172, 1292, 111, 240, 677, 813, 944, 1064, 1195,
|
||||
1315, 3, 160, 306, 446, 581, 725, 865, 993, 1116, 1244, 55, 220, 363,
|
||||
501, 641, 781, 905, 1029, 1156, 1280, 95, 256, 941, 1061, 1192, 1312, 0,
|
||||
157, 303, 443, 578, 722, 861, 989, 1112, 1240, 51, 216, 359, 497, 637,
|
||||
777, 901, 1025, 1152, 1276, 91, 252, 408, 692, 959, 1210, 19, 324, 601,
|
||||
885, 1136, 75, 383, 661, 925, 1176, 115, 686, 953, 1204, 13, 317, 593,
|
||||
877, 1128, 67, 375, 653, 917, 1168, 107,
|
||||
};
|
||||
|
||||
return AsmStrs+RegAsmOffset[RegNo-1];
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,231 @@
|
||||
/* Capstone Disassembly Engine, http://www.capstone-engine.org */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
|
||||
|
||||
/// getRegisterName - This method is automatically generated by tblgen
|
||||
/// from the register set description. This returns the assembler name
|
||||
/// for the specified register.
|
||||
static const char *getRegisterName_digit(unsigned RegNo)
|
||||
{
|
||||
|
||||
#ifndef CAPSTONE_DIET
|
||||
static const char AsmStrs[] = {
|
||||
/* 0 */ 'D', '4', '_', 'D', '6', '_', 'D', '8', '_', 'D', '1', '0', 0,
|
||||
/* 13 */ 'D', '7', '_', 'D', '8', '_', 'D', '9', '_', 'D', '1', '0', 0,
|
||||
/* 26 */ 'Q', '7', '_', 'Q', '8', '_', 'Q', '9', '_', 'Q', '1', '0', 0,
|
||||
/* 39 */ 'd', '1', '0', 0,
|
||||
/* 43 */ 'q', '1', '0', 0,
|
||||
/* 47 */ 'r', '1', '0', 0,
|
||||
/* 51 */ 's', '1', '0', 0,
|
||||
/* 55 */ 'D', '1', '4', '_', 'D', '1', '6', '_', 'D', '1', '8', '_', 'D', '2', '0', 0,
|
||||
/* 71 */ 'D', '1', '7', '_', 'D', '1', '8', '_', 'D', '1', '9', '_', 'D', '2', '0', 0,
|
||||
/* 87 */ 'd', '2', '0', 0,
|
||||
/* 91 */ 's', '2', '0', 0,
|
||||
/* 95 */ 'D', '2', '4', '_', 'D', '2', '6', '_', 'D', '2', '8', '_', 'D', '3', '0', 0,
|
||||
/* 111 */ 'D', '2', '7', '_', 'D', '2', '8', '_', 'D', '2', '9', '_', 'D', '3', '0', 0,
|
||||
/* 127 */ 'd', '3', '0', 0,
|
||||
/* 131 */ 's', '3', '0', 0,
|
||||
/* 135 */ 'd', '0', 0,
|
||||
/* 138 */ 'q', '0', 0,
|
||||
/* 141 */ 'm', 'v', 'f', 'r', '0', 0,
|
||||
/* 147 */ 's', '0', 0,
|
||||
/* 150 */ 'D', '9', '_', 'D', '1', '0', '_', 'D', '1', '1', 0,
|
||||
/* 161 */ 'D', '5', '_', 'D', '7', '_', 'D', '9', '_', 'D', '1', '1', 0,
|
||||
/* 174 */ 'Q', '8', '_', 'Q', '9', '_', 'Q', '1', '0', '_', 'Q', '1', '1', 0,
|
||||
/* 188 */ 'R', '1', '0', '_', 'R', '1', '1', 0,
|
||||
/* 196 */ 'd', '1', '1', 0,
|
||||
/* 200 */ 'q', '1', '1', 0,
|
||||
/* 204 */ 'r', '1', '1', 0,
|
||||
/* 208 */ 's', '1', '1', 0,
|
||||
/* 212 */ 'D', '1', '9', '_', 'D', '2', '0', '_', 'D', '2', '1', 0,
|
||||
/* 224 */ 'D', '1', '5', '_', 'D', '1', '7', '_', 'D', '1', '9', '_', 'D', '2', '1', 0,
|
||||
/* 240 */ 'd', '2', '1', 0,
|
||||
/* 244 */ 's', '2', '1', 0,
|
||||
/* 248 */ 'D', '2', '9', '_', 'D', '3', '0', '_', 'D', '3', '1', 0,
|
||||
/* 260 */ 'D', '2', '5', '_', 'D', '2', '7', '_', 'D', '2', '9', '_', 'D', '3', '1', 0,
|
||||
/* 276 */ 'd', '3', '1', 0,
|
||||
/* 280 */ 's', '3', '1', 0,
|
||||
/* 284 */ 'Q', '0', '_', 'Q', '1', 0,
|
||||
/* 290 */ 'R', '0', '_', 'R', '1', 0,
|
||||
/* 296 */ 'd', '1', 0,
|
||||
/* 299 */ 'q', '1', 0,
|
||||
/* 302 */ 'm', 'v', 'f', 'r', '1', 0,
|
||||
/* 308 */ 's', '1', 0,
|
||||
/* 311 */ 'D', '6', '_', 'D', '8', '_', 'D', '1', '0', '_', 'D', '1', '2', 0,
|
||||
/* 325 */ 'D', '9', '_', 'D', '1', '0', '_', 'D', '1', '1', '_', 'D', '1', '2', 0,
|
||||
/* 340 */ 'Q', '9', '_', 'Q', '1', '0', '_', 'Q', '1', '1', '_', 'Q', '1', '2', 0,
|
||||
/* 355 */ 'd', '1', '2', 0,
|
||||
/* 359 */ 'q', '1', '2', 0,
|
||||
/* 363 */ 'r', '1', '2', 0,
|
||||
/* 367 */ 's', '1', '2', 0,
|
||||
/* 371 */ 'D', '1', '6', '_', 'D', '1', '8', '_', 'D', '2', '0', '_', 'D', '2', '2', 0,
|
||||
/* 387 */ 'D', '1', '9', '_', 'D', '2', '0', '_', 'D', '2', '1', '_', 'D', '2', '2', 0,
|
||||
/* 403 */ 'd', '2', '2', 0,
|
||||
/* 407 */ 's', '2', '2', 0,
|
||||
/* 411 */ 'D', '0', '_', 'D', '2', 0,
|
||||
/* 417 */ 'D', '0', '_', 'D', '1', '_', 'D', '2', 0,
|
||||
/* 426 */ 'Q', '1', '_', 'Q', '2', 0,
|
||||
/* 432 */ 'd', '2', 0,
|
||||
/* 435 */ 'q', '2', 0,
|
||||
/* 438 */ 'm', 'v', 'f', 'r', '2', 0,
|
||||
/* 444 */ 's', '2', 0,
|
||||
/* 447 */ 'f', 'p', 'i', 'n', 's', 't', '2', 0,
|
||||
/* 455 */ 'D', '7', '_', 'D', '9', '_', 'D', '1', '1', '_', 'D', '1', '3', 0,
|
||||
/* 469 */ 'D', '1', '1', '_', 'D', '1', '2', '_', 'D', '1', '3', 0,
|
||||
/* 481 */ 'Q', '1', '0', '_', 'Q', '1', '1', '_', 'Q', '1', '2', '_', 'Q', '1', '3', 0,
|
||||
/* 497 */ 'd', '1', '3', 0,
|
||||
/* 501 */ 'q', '1', '3', 0,
|
||||
/* 505 */ 'r', '1', '3', 0,
|
||||
/* 509 */ 's', '1', '3', 0,
|
||||
/* 513 */ 'D', '1', '7', '_', 'D', '1', '9', '_', 'D', '2', '1', '_', 'D', '2', '3', 0,
|
||||
/* 529 */ 'D', '2', '1', '_', 'D', '2', '2', '_', 'D', '2', '3', 0,
|
||||
/* 541 */ 'd', '2', '3', 0,
|
||||
/* 545 */ 's', '2', '3', 0,
|
||||
/* 549 */ 'D', '1', '_', 'D', '3', 0,
|
||||
/* 555 */ 'D', '1', '_', 'D', '2', '_', 'D', '3', 0,
|
||||
/* 564 */ 'Q', '0', '_', 'Q', '1', '_', 'Q', '2', '_', 'Q', '3', 0,
|
||||
/* 576 */ 'R', '2', '_', 'R', '3', 0,
|
||||
/* 582 */ 'd', '3', 0,
|
||||
/* 585 */ 'q', '3', 0,
|
||||
/* 588 */ 'r', '3', 0,
|
||||
/* 591 */ 's', '3', 0,
|
||||
/* 594 */ 'D', '8', '_', 'D', '1', '0', '_', 'D', '1', '2', '_', 'D', '1', '4', 0,
|
||||
/* 609 */ 'D', '1', '1', '_', 'D', '1', '2', '_', 'D', '1', '3', '_', 'D', '1', '4', 0,
|
||||
/* 625 */ 'Q', '1', '1', '_', 'Q', '1', '2', '_', 'Q', '1', '3', '_', 'Q', '1', '4', 0,
|
||||
/* 641 */ 'd', '1', '4', 0,
|
||||
/* 645 */ 'q', '1', '4', 0,
|
||||
/* 649 */ 'r', '1', '4', 0,
|
||||
/* 653 */ 's', '1', '4', 0,
|
||||
/* 657 */ 'D', '1', '8', '_', 'D', '2', '0', '_', 'D', '2', '2', '_', 'D', '2', '4', 0,
|
||||
/* 673 */ 'D', '2', '1', '_', 'D', '2', '2', '_', 'D', '2', '3', '_', 'D', '2', '4', 0,
|
||||
/* 689 */ 'd', '2', '4', 0,
|
||||
/* 693 */ 's', '2', '4', 0,
|
||||
/* 697 */ 'D', '0', '_', 'D', '2', '_', 'D', '4', 0,
|
||||
/* 706 */ 'D', '1', '_', 'D', '2', '_', 'D', '3', '_', 'D', '4', 0,
|
||||
/* 718 */ 'Q', '1', '_', 'Q', '2', '_', 'Q', '3', '_', 'Q', '4', 0,
|
||||
/* 730 */ 'd', '4', 0,
|
||||
/* 733 */ 'q', '4', 0,
|
||||
/* 736 */ 'r', '4', 0,
|
||||
/* 739 */ 's', '4', 0,
|
||||
/* 742 */ 'D', '9', '_', 'D', '1', '1', '_', 'D', '1', '3', '_', 'D', '1', '5', 0,
|
||||
/* 757 */ 'D', '1', '3', '_', 'D', '1', '4', '_', 'D', '1', '5', 0,
|
||||
/* 769 */ 'Q', '1', '2', '_', 'Q', '1', '3', '_', 'Q', '1', '4', '_', 'Q', '1', '5', 0,
|
||||
/* 785 */ 'd', '1', '5', 0,
|
||||
/* 789 */ 'q', '1', '5', 0,
|
||||
/* 793 */ 's', '1', '5', 0,
|
||||
/* 797 */ 'D', '1', '9', '_', 'D', '2', '1', '_', 'D', '2', '3', '_', 'D', '2', '5', 0,
|
||||
/* 813 */ 'D', '2', '3', '_', 'D', '2', '4', '_', 'D', '2', '5', 0,
|
||||
/* 825 */ 'd', '2', '5', 0,
|
||||
/* 829 */ 's', '2', '5', 0,
|
||||
/* 833 */ 'D', '1', '_', 'D', '3', '_', 'D', '5', 0,
|
||||
/* 842 */ 'D', '3', '_', 'D', '4', '_', 'D', '5', 0,
|
||||
/* 851 */ 'Q', '2', '_', 'Q', '3', '_', 'Q', '4', '_', 'Q', '5', 0,
|
||||
/* 863 */ 'R', '4', '_', 'R', '5', 0,
|
||||
/* 869 */ 'd', '5', 0,
|
||||
/* 872 */ 'q', '5', 0,
|
||||
/* 875 */ 'r', '5', 0,
|
||||
/* 878 */ 's', '5', 0,
|
||||
/* 881 */ 'D', '1', '0', '_', 'D', '1', '2', '_', 'D', '1', '4', '_', 'D', '1', '6', 0,
|
||||
/* 897 */ 'D', '1', '3', '_', 'D', '1', '4', '_', 'D', '1', '5', '_', 'D', '1', '6', 0,
|
||||
/* 913 */ 'd', '1', '6', 0,
|
||||
/* 917 */ 's', '1', '6', 0,
|
||||
/* 921 */ 'D', '2', '0', '_', 'D', '2', '2', '_', 'D', '2', '4', '_', 'D', '2', '6', 0,
|
||||
/* 937 */ 'D', '2', '3', '_', 'D', '2', '4', '_', 'D', '2', '5', '_', 'D', '2', '6', 0,
|
||||
/* 953 */ 'd', '2', '6', 0,
|
||||
/* 957 */ 's', '2', '6', 0,
|
||||
/* 961 */ 'D', '0', '_', 'D', '2', '_', 'D', '4', '_', 'D', '6', 0,
|
||||
/* 973 */ 'D', '3', '_', 'D', '4', '_', 'D', '5', '_', 'D', '6', 0,
|
||||
/* 985 */ 'Q', '3', '_', 'Q', '4', '_', 'Q', '5', '_', 'Q', '6', 0,
|
||||
/* 997 */ 'd', '6', 0,
|
||||
/* 1000 */ 'q', '6', 0,
|
||||
/* 1003 */ 'r', '6', 0,
|
||||
/* 1006 */ 's', '6', 0,
|
||||
/* 1009 */ 'D', '1', '1', '_', 'D', '1', '3', '_', 'D', '1', '5', '_', 'D', '1', '7', 0,
|
||||
/* 1025 */ 'D', '1', '5', '_', 'D', '1', '6', '_', 'D', '1', '7', 0,
|
||||
/* 1037 */ 'd', '1', '7', 0,
|
||||
/* 1041 */ 's', '1', '7', 0,
|
||||
/* 1045 */ 'D', '2', '1', '_', 'D', '2', '3', '_', 'D', '2', '5', '_', 'D', '2', '7', 0,
|
||||
/* 1061 */ 'D', '2', '5', '_', 'D', '2', '6', '_', 'D', '2', '7', 0,
|
||||
/* 1073 */ 'd', '2', '7', 0,
|
||||
/* 1077 */ 's', '2', '7', 0,
|
||||
/* 1081 */ 'D', '1', '_', 'D', '3', '_', 'D', '5', '_', 'D', '7', 0,
|
||||
/* 1093 */ 'D', '5', '_', 'D', '6', '_', 'D', '7', 0,
|
||||
/* 1102 */ 'Q', '4', '_', 'Q', '5', '_', 'Q', '6', '_', 'Q', '7', 0,
|
||||
/* 1114 */ 'R', '6', '_', 'R', '7', 0,
|
||||
/* 1120 */ 'd', '7', 0,
|
||||
/* 1123 */ 'q', '7', 0,
|
||||
/* 1126 */ 'r', '7', 0,
|
||||
/* 1129 */ 's', '7', 0,
|
||||
/* 1132 */ 'D', '1', '2', '_', 'D', '1', '4', '_', 'D', '1', '6', '_', 'D', '1', '8', 0,
|
||||
/* 1148 */ 'D', '1', '5', '_', 'D', '1', '6', '_', 'D', '1', '7', '_', 'D', '1', '8', 0,
|
||||
/* 1164 */ 'd', '1', '8', 0,
|
||||
/* 1168 */ 's', '1', '8', 0,
|
||||
/* 1172 */ 'D', '2', '2', '_', 'D', '2', '4', '_', 'D', '2', '6', '_', 'D', '2', '8', 0,
|
||||
/* 1188 */ 'D', '2', '5', '_', 'D', '2', '6', '_', 'D', '2', '7', '_', 'D', '2', '8', 0,
|
||||
/* 1204 */ 'd', '2', '8', 0,
|
||||
/* 1208 */ 's', '2', '8', 0,
|
||||
/* 1212 */ 'D', '2', '_', 'D', '4', '_', 'D', '6', '_', 'D', '8', 0,
|
||||
/* 1224 */ 'D', '5', '_', 'D', '6', '_', 'D', '7', '_', 'D', '8', 0,
|
||||
/* 1236 */ 'Q', '5', '_', 'Q', '6', '_', 'Q', '7', '_', 'Q', '8', 0,
|
||||
/* 1248 */ 'd', '8', 0,
|
||||
/* 1251 */ 'q', '8', 0,
|
||||
/* 1254 */ 'r', '8', 0,
|
||||
/* 1257 */ 's', '8', 0,
|
||||
/* 1260 */ 'D', '1', '3', '_', 'D', '1', '5', '_', 'D', '1', '7', '_', 'D', '1', '9', 0,
|
||||
/* 1276 */ 'D', '1', '7', '_', 'D', '1', '8', '_', 'D', '1', '9', 0,
|
||||
/* 1288 */ 'd', '1', '9', 0,
|
||||
/* 1292 */ 's', '1', '9', 0,
|
||||
/* 1296 */ 'D', '2', '3', '_', 'D', '2', '5', '_', 'D', '2', '7', '_', 'D', '2', '9', 0,
|
||||
/* 1312 */ 'D', '2', '7', '_', 'D', '2', '8', '_', 'D', '2', '9', 0,
|
||||
/* 1324 */ 'd', '2', '9', 0,
|
||||
/* 1328 */ 's', '2', '9', 0,
|
||||
/* 1332 */ 'D', '3', '_', 'D', '5', '_', 'D', '7', '_', 'D', '9', 0,
|
||||
/* 1344 */ 'D', '7', '_', 'D', '8', '_', 'D', '9', 0,
|
||||
/* 1353 */ 'Q', '6', '_', 'Q', '7', '_', 'Q', '8', '_', 'Q', '9', 0,
|
||||
/* 1365 */ 'R', '8', '_', 'R', '9', 0,
|
||||
/* 1371 */ 'd', '9', 0,
|
||||
/* 1374 */ 'q', '9', 0,
|
||||
/* 1377 */ 'r', '9', 0,
|
||||
/* 1380 */ 's', '9', 0,
|
||||
/* 1383 */ 'R', '1', '2', '_', 'S', 'P', 0,
|
||||
/* 1390 */ 'p', 'c', 0,
|
||||
/* 1393 */ 'f', 'p', 'e', 'x', 'c', 0,
|
||||
/* 1399 */ 'f', 'p', 's', 'i', 'd', 0,
|
||||
/* 1405 */ 'i', 't', 's', 't', 'a', 't', 'e', 0,
|
||||
/* 1413 */ 'f', 'p', 's', 'c', 'r', 0,
|
||||
/* 1419 */ 'a', 'p', 's', 'r', 0,
|
||||
/* 1424 */ 'c', 'p', 's', 'r', 0,
|
||||
/* 1429 */ 's', 'p', 's', 'r', 0,
|
||||
/* 1434 */ 'f', 'p', 'i', 'n', 's', 't', 0,
|
||||
/* 1441 */ 'f', 'p', 's', 'c', 'r', '_', 'n', 'z', 'c', 'v', 0,
|
||||
/* 1452 */ 'a', 'p', 's', 'r', '_', 'n', 'z', 'c', 'v', 0,
|
||||
};
|
||||
|
||||
static const uint16_t RegAsmOffset[] = {
|
||||
1419, 1452, 1424, 1393, 1434, 1413, 1441, 1399, 1405, 649, 1390, 505, 1429, 135,
|
||||
296, 432, 582, 730, 869, 997, 1120, 1248, 1371, 39, 196, 355, 497, 641,
|
||||
785, 913, 1037, 1164, 1288, 87, 240, 403, 541, 689, 825, 953, 1073, 1204,
|
||||
1324, 127, 276, 447, 141, 302, 438, 138, 299, 435, 585, 733, 872, 1000,
|
||||
1123, 1251, 1374, 43, 200, 359, 501, 645, 789, 144, 305, 441, 588, 736,
|
||||
875, 1003, 1126, 1254, 1377, 47, 204, 363, 147, 308, 444, 591, 739, 878,
|
||||
1006, 1129, 1257, 1380, 51, 208, 367, 509, 653, 793, 917, 1041, 1168, 1292,
|
||||
91, 244, 407, 545, 693, 829, 957, 1077, 1208, 1328, 131, 280, 411, 549,
|
||||
700, 836, 967, 1087, 1218, 1338, 6, 167, 317, 461, 601, 749, 889, 1017,
|
||||
1140, 1268, 63, 232, 379, 521, 665, 805, 929, 1053, 1180, 1304, 103, 268,
|
||||
284, 426, 570, 724, 857, 991, 1108, 1242, 1359, 32, 180, 347, 489, 633,
|
||||
777, 564, 718, 851, 985, 1102, 1236, 1353, 26, 174, 340, 481, 625, 769,
|
||||
1383, 290, 576, 863, 1114, 1365, 188, 417, 555, 709, 842, 976, 1093, 1227,
|
||||
1344, 16, 150, 328, 469, 613, 757, 901, 1025, 1152, 1276, 75, 212, 391,
|
||||
529, 677, 813, 941, 1061, 1192, 1312, 115, 248, 697, 833, 964, 1084, 1215,
|
||||
1335, 3, 164, 314, 458, 597, 745, 885, 1013, 1136, 1264, 59, 228, 375,
|
||||
517, 661, 801, 925, 1049, 1176, 1300, 99, 264, 961, 1081, 1212, 1332, 0,
|
||||
161, 311, 455, 594, 742, 881, 1009, 1132, 1260, 55, 224, 371, 513, 657,
|
||||
797, 921, 1045, 1172, 1296, 95, 260, 420, 712, 979, 1230, 19, 332, 617,
|
||||
905, 1156, 79, 395, 681, 945, 1196, 119, 706, 973, 1224, 13, 325, 609,
|
||||
897, 1148, 71, 387, 673, 937, 1188, 111,
|
||||
};
|
||||
|
||||
return AsmStrs+RegAsmOffset[RegNo-1];
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
|
||||
/* Capstone Disassembly Engine, http://www.capstone-engine.org */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
|
||||
|
||||
/*===- TableGen'erated file -------------------------------------*- C++ -*-===*|* *|
|
||||
|* Subtarget Enumeration Source Fragment *|
|
||||
|* *|
|
||||
|* Automatically generated file, do not edit! *|
|
||||
|* *|
|
||||
\*===----------------------------------------------------------------------===*/
|
||||
|
||||
|
||||
enum {
|
||||
ARM_ARMv2 = 0,
|
||||
ARM_ARMv2a = 1,
|
||||
ARM_ARMv3 = 2,
|
||||
ARM_ARMv3m = 3,
|
||||
ARM_ARMv4 = 4,
|
||||
ARM_ARMv4t = 5,
|
||||
ARM_ARMv5t = 6,
|
||||
ARM_ARMv5te = 7,
|
||||
ARM_ARMv5tej = 8,
|
||||
ARM_ARMv6 = 9,
|
||||
ARM_ARMv6j = 10,
|
||||
ARM_ARMv6k = 11,
|
||||
ARM_ARMv6kz = 12,
|
||||
ARM_ARMv6m = 13,
|
||||
ARM_ARMv6sm = 14,
|
||||
ARM_ARMv6t2 = 15,
|
||||
ARM_ARMv7a = 16,
|
||||
ARM_ARMv7em = 17,
|
||||
ARM_ARMv7k = 18,
|
||||
ARM_ARMv7m = 19,
|
||||
ARM_ARMv7r = 20,
|
||||
ARM_ARMv7s = 21,
|
||||
ARM_ARMv7ve = 22,
|
||||
ARM_ARMv8a = 23,
|
||||
ARM_ARMv8mBaseline = 24,
|
||||
ARM_ARMv8mMainline = 25,
|
||||
ARM_ARMv8r = 26,
|
||||
ARM_ARMv81a = 27,
|
||||
ARM_ARMv82a = 28,
|
||||
ARM_ARMv83a = 29,
|
||||
ARM_ARMv84a = 30,
|
||||
ARM_Feature8MSecExt = 31,
|
||||
ARM_FeatureAClass = 32,
|
||||
ARM_FeatureAES = 33,
|
||||
ARM_FeatureAcquireRelease = 34,
|
||||
ARM_FeatureAvoidMOVsShOp = 35,
|
||||
ARM_FeatureAvoidPartialCPSR = 36,
|
||||
ARM_FeatureCRC = 37,
|
||||
ARM_FeatureCheapPredicableCPSR = 38,
|
||||
ARM_FeatureCheckVLDnAlign = 39,
|
||||
ARM_FeatureCrypto = 40,
|
||||
ARM_FeatureD16 = 41,
|
||||
ARM_FeatureDB = 42,
|
||||
ARM_FeatureDFB = 43,
|
||||
ARM_FeatureDSP = 44,
|
||||
ARM_FeatureDontWidenVMOVS = 45,
|
||||
ARM_FeatureDotProd = 46,
|
||||
ARM_FeatureExecuteOnly = 47,
|
||||
ARM_FeatureExpandMLx = 48,
|
||||
ARM_FeatureFP16 = 49,
|
||||
ARM_FeatureFPAO = 50,
|
||||
ARM_FeatureFPARMv8 = 51,
|
||||
ARM_FeatureFullFP16 = 52,
|
||||
ARM_FeatureFuseAES = 53,
|
||||
ARM_FeatureFuseLiterals = 54,
|
||||
ARM_FeatureHWDivARM = 55,
|
||||
ARM_FeatureHWDivThumb = 56,
|
||||
ARM_FeatureHasNoBranchPredictor = 57,
|
||||
ARM_FeatureHasRetAddrStack = 58,
|
||||
ARM_FeatureHasSlowFPVMLx = 59,
|
||||
ARM_FeatureHasVMLxHazards = 60,
|
||||
ARM_FeatureLongCalls = 61,
|
||||
ARM_FeatureMClass = 62,
|
||||
ARM_FeatureMP = 63,
|
||||
ARM_FeatureMuxedUnits = 64,
|
||||
ARM_FeatureNEON = 65,
|
||||
ARM_FeatureNEONForFP = 66,
|
||||
ARM_FeatureNEONForFPMovs = 67,
|
||||
ARM_FeatureNaClTrap = 68,
|
||||
ARM_FeatureNoARM = 69,
|
||||
ARM_FeatureNoMovt = 70,
|
||||
ARM_FeatureNoNegativeImmediates = 71,
|
||||
ARM_FeatureNoPostRASched = 72,
|
||||
ARM_FeatureNonpipelinedVFP = 73,
|
||||
ARM_FeaturePerfMon = 74,
|
||||
ARM_FeaturePref32BitThumb = 75,
|
||||
ARM_FeaturePrefISHSTBarrier = 76,
|
||||
ARM_FeaturePreferVMOVSR = 77,
|
||||
ARM_FeatureProfUnpredicate = 78,
|
||||
ARM_FeatureRAS = 79,
|
||||
ARM_FeatureRClass = 80,
|
||||
ARM_FeatureReadTp = 81,
|
||||
ARM_FeatureReserveR9 = 82,
|
||||
ARM_FeatureSHA2 = 83,
|
||||
ARM_FeatureSlowFPBrcc = 84,
|
||||
ARM_FeatureSlowLoadDSubreg = 85,
|
||||
ARM_FeatureSlowOddRegister = 86,
|
||||
ARM_FeatureSlowVDUP32 = 87,
|
||||
ARM_FeatureSlowVGETLNi32 = 88,
|
||||
ARM_FeatureSplatVFPToNeon = 89,
|
||||
ARM_FeatureStrictAlign = 90,
|
||||
ARM_FeatureThumb2 = 91,
|
||||
ARM_FeatureTrustZone = 92,
|
||||
ARM_FeatureUseAA = 93,
|
||||
ARM_FeatureUseMISched = 94,
|
||||
ARM_FeatureV7Clrex = 95,
|
||||
ARM_FeatureVFP2 = 96,
|
||||
ARM_FeatureVFP3 = 97,
|
||||
ARM_FeatureVFP4 = 98,
|
||||
ARM_FeatureVFPOnlySP = 99,
|
||||
ARM_FeatureVMLxForwarding = 100,
|
||||
ARM_FeatureVirtualization = 101,
|
||||
ARM_FeatureZCZeroing = 102,
|
||||
ARM_HasV4TOps = 103,
|
||||
ARM_HasV5TEOps = 104,
|
||||
ARM_HasV5TOps = 105,
|
||||
ARM_HasV6KOps = 106,
|
||||
ARM_HasV6MOps = 107,
|
||||
ARM_HasV6Ops = 108,
|
||||
ARM_HasV6T2Ops = 109,
|
||||
ARM_HasV7Ops = 110,
|
||||
ARM_HasV8MBaselineOps = 111,
|
||||
ARM_HasV8MMainlineOps = 112,
|
||||
ARM_HasV8Ops = 113,
|
||||
ARM_HasV8_1aOps = 114,
|
||||
ARM_HasV8_2aOps = 115,
|
||||
ARM_HasV8_3aOps = 116,
|
||||
ARM_HasV8_4aOps = 117,
|
||||
ARM_IWMMXT = 118,
|
||||
ARM_IWMMXT2 = 119,
|
||||
ARM_ModeSoftFloat = 120,
|
||||
ARM_ModeThumb = 121,
|
||||
ARM_ProcA5 = 122,
|
||||
ARM_ProcA7 = 123,
|
||||
ARM_ProcA8 = 124,
|
||||
ARM_ProcA9 = 125,
|
||||
ARM_ProcA12 = 126,
|
||||
ARM_ProcA15 = 127,
|
||||
ARM_ProcA17 = 128,
|
||||
ARM_ProcA32 = 129,
|
||||
ARM_ProcA35 = 130,
|
||||
ARM_ProcA53 = 131,
|
||||
ARM_ProcA55 = 132,
|
||||
ARM_ProcA57 = 133,
|
||||
ARM_ProcA72 = 134,
|
||||
ARM_ProcA73 = 135,
|
||||
ARM_ProcA75 = 136,
|
||||
ARM_ProcExynosM1 = 137,
|
||||
ARM_ProcKrait = 138,
|
||||
ARM_ProcKryo = 139,
|
||||
ARM_ProcM3 = 140,
|
||||
ARM_ProcR4 = 141,
|
||||
ARM_ProcR5 = 142,
|
||||
ARM_ProcR7 = 143,
|
||||
ARM_ProcR52 = 144,
|
||||
ARM_ProcSwift = 145,
|
||||
ARM_XScale = 146,
|
||||
};
|
||||
|
||||
@@ -0,0 +1,270 @@
|
||||
|
||||
/* Capstone Disassembly Engine, http://www.capstone-engine.org */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
|
||||
|
||||
/*===- TableGen'erated file -------------------------------------*- C++ -*-===*|* *|
|
||||
|* GenSystemRegister Source Fragment *|
|
||||
|* *|
|
||||
|* Automatically generated file, do not edit! *|
|
||||
|* *|
|
||||
\*===----------------------------------------------------------------------===*/
|
||||
|
||||
|
||||
enum BankedRegValues {
|
||||
elr_hyp = 0,
|
||||
lr_abt = 1,
|
||||
lr_fiq = 2,
|
||||
lr_irq = 3,
|
||||
lr_mon = 4,
|
||||
lr_svc = 5,
|
||||
lr_und = 6,
|
||||
lr_usr = 7,
|
||||
r10_fiq = 8,
|
||||
r10_usr = 9,
|
||||
r11_fiq = 10,
|
||||
r11_usr = 11,
|
||||
r12_fiq = 12,
|
||||
r12_usr = 13,
|
||||
r8_fiq = 14,
|
||||
r8_usr = 15,
|
||||
r9_fiq = 16,
|
||||
r9_usr = 17,
|
||||
sp_abt = 18,
|
||||
sp_fiq = 19,
|
||||
sp_hyp = 20,
|
||||
sp_irq = 21,
|
||||
sp_mon = 22,
|
||||
sp_svc = 23,
|
||||
sp_und = 24,
|
||||
sp_usr = 25,
|
||||
spsr_abt = 26,
|
||||
spsr_fiq = 27,
|
||||
spsr_hyp = 28,
|
||||
spsr_irq = 29,
|
||||
spsr_mon = 30,
|
||||
spsr_svc = 31,
|
||||
spsr_und = 32,
|
||||
};
|
||||
|
||||
static const MClassSysReg MClassSysRegsList[] = {
|
||||
{ "apsr_g", ARM_SYSREG_APSR_G, 0x400, 0x0, 0x400, {ARM_FeatureDSP} }, // 0
|
||||
{ "apsr_nzcvqg", ARM_SYSREG_APSR_NZCVQG, 0xC00, 0x300, 0xC00, {ARM_FeatureDSP} }, // 1
|
||||
{ "iapsr_g", ARM_SYSREG_IAPSR_G, 0x401, 0x1, 0x401, {ARM_FeatureDSP} }, // 2
|
||||
{ "iapsr_nzcvqg", ARM_SYSREG_IAPSR_NZCVQG, 0xC01, 0x301, 0xC01, {ARM_FeatureDSP} }, // 3
|
||||
{ "eapsr_g", ARM_SYSREG_EAPSR_G, 0x402, 0x2, 0x402, {ARM_FeatureDSP} }, // 4
|
||||
{ "eapsr_nzcvqg", ARM_SYSREG_EAPSR_NZCVQG, 0xC02, 0x302, 0xC02, {ARM_FeatureDSP} }, // 5
|
||||
{ "xpsr_g", ARM_SYSREG_XPSR_G, 0x403, 0x3, 0x403, {ARM_FeatureDSP} }, // 6
|
||||
{ "xpsr_nzcvqg", ARM_SYSREG_XPSR_NZCVQG, 0xC03, 0x303, 0xC03, {ARM_FeatureDSP} }, // 7
|
||||
{ "apsr", ARM_SYSREG_APSR, 0x800, 0x100, 0x800, { 0 } }, // 8
|
||||
{ "apsr_nzcvq", ARM_SYSREG_APSR_NZCVQ, 0x1800, 0x200, 0x800, { 0 } }, // 9
|
||||
{ "iapsr", ARM_SYSREG_IAPSR, 0x801, 0x101, 0x801, { 0 } }, // 10
|
||||
{ "iapsr_nzcvq", ARM_SYSREG_IAPSR_NZCVQ, 0x1801, 0x201, 0x801, { 0 } }, // 11
|
||||
{ "eapsr", ARM_SYSREG_EAPSR, 0x802, 0x102, 0x802, { 0 } }, // 12
|
||||
{ "eapsr_nzcvq", ARM_SYSREG_EAPSR_NZCVQ, 0x1802, 0x202, 0x802, { 0 } }, // 13
|
||||
{ "xpsr", ARM_SYSREG_XPSR, 0x803, 0x103, 0x803, { 0 } }, // 14
|
||||
{ "xpsr_nzcvq", ARM_SYSREG_XPSR_NZCVQ, 0x1803, 0x203, 0x803, { 0 } }, // 15
|
||||
{ "ipsr", ARM_SYSREG_IPSR, 0x805, 0x105, 0x805, { 0 } }, // 16
|
||||
{ "epsr", ARM_SYSREG_EPSR, 0x806, 0x106, 0x806, { 0 } }, // 17
|
||||
{ "iepsr", ARM_SYSREG_IEPSR, 0x807, 0x107, 0x807, { 0 } }, // 18
|
||||
{ "msp", ARM_SYSREG_MSP, 0x808, 0x108, 0x808, { 0 } }, // 19
|
||||
{ "psp", ARM_SYSREG_PSP, 0x809, 0x109, 0x809, { 0 } }, // 20
|
||||
{ "msplim", ARM_SYSREG_MSPLIM, 0x80A, 0x10A, 0x80A, {ARM_HasV8MBaselineOps} }, // 21
|
||||
{ "psplim", ARM_SYSREG_PSPLIM, 0x80B, 0x10B, 0x80B, {ARM_HasV8MBaselineOps} }, // 22
|
||||
{ "primask", ARM_SYSREG_PRIMASK, 0x810, 0x110, 0x810, { 0 } }, // 23
|
||||
{ "basepri", ARM_SYSREG_BASEPRI, 0x811, 0x111, 0x811, {ARM_HasV7Ops} }, // 24
|
||||
{ "basepri_max", ARM_SYSREG_BASEPRI_MAX, 0x812, 0x112, 0x812, {ARM_HasV7Ops} }, // 25
|
||||
{ "faultmask", ARM_SYSREG_FAULTMASK, 0x813, 0x113, 0x813, {ARM_HasV7Ops} }, // 26
|
||||
{ "control", ARM_SYSREG_CONTROL, 0x814, 0x114, 0x814, { 0 } }, // 27
|
||||
{ "msp_ns", ARM_SYSREG_MSP_NS, 0x888, 0x188, 0x888, {ARM_Feature8MSecExt} }, // 28
|
||||
{ "psp_ns", ARM_SYSREG_PSP_NS, 0x889, 0x189, 0x889, {ARM_Feature8MSecExt} }, // 29
|
||||
{ "msplim_ns", ARM_SYSREG_MSPLIM_NS, 0x88A, 0x18A, 0x88A, {ARM_Feature8MSecExt, ARM_HasV8MBaselineOps} }, // 30
|
||||
{ "psplim_ns", ARM_SYSREG_PSPLIM_NS, 0x88B, 0x18B, 0x88B, {ARM_Feature8MSecExt, ARM_HasV8MBaselineOps} }, // 31
|
||||
{ "primask_ns", ARM_SYSREG_PRIMASK_NS, 0x890, 0x190, 0x890, { 0 } }, // 32
|
||||
{ "basepri_ns", ARM_SYSREG_BASEPRI_NS, 0x891, 0x191, 0x891, {ARM_Feature8MSecExt, ARM_HasV7Ops} }, // 33
|
||||
{ "faultmask_ns", ARM_SYSREG_FAULTMASK_NS, 0x893, 0x193, 0x893, {ARM_Feature8MSecExt, ARM_HasV7Ops} }, // 34
|
||||
{ "control_ns", ARM_SYSREG_CONTROL_NS, 0x894, 0x194, 0x894, {ARM_Feature8MSecExt} }, // 35
|
||||
{ "sp_ns", ARM_SYSREG_SP_NS, 0x898, 0x198, 0x898, {ARM_Feature8MSecExt} }, // 36
|
||||
};
|
||||
|
||||
static const BankedReg BankedRegsList[] = {
|
||||
{ "r8_usr", ARM_SYSREG_R8_USR, 0x0 }, // 0
|
||||
{ "r9_usr", ARM_SYSREG_R9_USR, 0x1 }, // 1
|
||||
{ "r10_usr", ARM_SYSREG_R10_USR, 0x2 }, // 2
|
||||
{ "r11_usr", ARM_SYSREG_R11_USR, 0x3 }, // 3
|
||||
{ "r12_usr", ARM_SYSREG_R12_USR, 0x4 }, // 4
|
||||
{ "sp_usr", ARM_SYSREG_SP_USR, 0x5 }, // 5
|
||||
{ "lr_usr", ARM_SYSREG_LR_USR, 0x6 }, // 6
|
||||
{ "r8_fiq", ARM_SYSREG_R8_FIQ, 0x8 }, // 7
|
||||
{ "r9_fiq", ARM_SYSREG_R9_FIQ, 0x9 }, // 8
|
||||
{ "r10_fiq", ARM_SYSREG_R10_FIQ, 0xA }, // 9
|
||||
{ "r11_fiq", ARM_SYSREG_R11_FIQ, 0xB }, // 10
|
||||
{ "r12_fiq", ARM_SYSREG_R12_FIQ, 0xC }, // 11
|
||||
{ "sp_fiq", ARM_SYSREG_SP_FIQ, 0xD }, // 12
|
||||
{ "lr_fiq", ARM_SYSREG_LR_FIQ, 0xE }, // 13
|
||||
{ "lr_irq", ARM_SYSREG_LR_IRQ, 0x10 }, // 14
|
||||
{ "sp_irq", ARM_SYSREG_SP_IRQ, 0x11 }, // 15
|
||||
{ "lr_svc", ARM_SYSREG_LR_SVC, 0x12 }, // 16
|
||||
{ "sp_svc", ARM_SYSREG_SP_SVC, 0x13 }, // 17
|
||||
{ "lr_abt", ARM_SYSREG_LR_ABT, 0x14 }, // 18
|
||||
{ "sp_abt", ARM_SYSREG_SP_ABT, 0x15 }, // 19
|
||||
{ "lr_und", ARM_SYSREG_LR_UND, 0x16 }, // 20
|
||||
{ "sp_und", ARM_SYSREG_SP_UND, 0x17 }, // 21
|
||||
{ "lr_mon", ARM_SYSREG_LR_MON, 0x1C }, // 22
|
||||
{ "sp_mon", ARM_SYSREG_SP_MON, 0x1D }, // 23
|
||||
{ "elr_hyp", ARM_SYSREG_ELR_HYP, 0x1E }, // 24
|
||||
{ "sp_hyp", ARM_SYSREG_SP_HYP, 0x1F }, // 25
|
||||
{ "spsr_fiq", ARM_SYSREG_SPSR_FIQ, 0x2E }, // 26
|
||||
{ "spsr_irq", ARM_SYSREG_SPSR_IRQ, 0x30 }, // 27
|
||||
{ "spsr_svc", ARM_SYSREG_SPSR_SVC, 0x32 }, // 28
|
||||
{ "spsr_abt", ARM_SYSREG_SPSR_ABT, 0x34 }, // 29
|
||||
{ "spsr_und", ARM_SYSREG_SPSR_UND, 0x36 }, // 30
|
||||
{ "spsr_mon", ARM_SYSREG_SPSR_MON, 0x3C }, // 31
|
||||
{ "spsr_hyp", ARM_SYSREG_SPSR_HYP, 0x3E }, // 32
|
||||
};
|
||||
|
||||
const MClassSysReg *lookupMClassSysRegByM2M3Encoding8(uint16_t encoding)
|
||||
{
|
||||
unsigned int i;
|
||||
static const struct IndexType Index[] = {
|
||||
{ 0x0, 0 },
|
||||
{ 0x1, 2 },
|
||||
{ 0x2, 4 },
|
||||
{ 0x3, 6 },
|
||||
{ 0x100, 8 },
|
||||
{ 0x101, 10 },
|
||||
{ 0x102, 12 },
|
||||
{ 0x103, 14 },
|
||||
{ 0x105, 16 },
|
||||
{ 0x106, 17 },
|
||||
{ 0x107, 18 },
|
||||
{ 0x108, 19 },
|
||||
{ 0x109, 20 },
|
||||
{ 0x10A, 21 },
|
||||
{ 0x10B, 22 },
|
||||
{ 0x110, 23 },
|
||||
{ 0x111, 24 },
|
||||
{ 0x112, 25 },
|
||||
{ 0x113, 26 },
|
||||
{ 0x114, 27 },
|
||||
{ 0x188, 28 },
|
||||
{ 0x189, 29 },
|
||||
{ 0x18A, 30 },
|
||||
{ 0x18B, 31 },
|
||||
{ 0x190, 32 },
|
||||
{ 0x191, 33 },
|
||||
{ 0x193, 34 },
|
||||
{ 0x194, 35 },
|
||||
{ 0x198, 36 },
|
||||
{ 0x200, 9 },
|
||||
{ 0x201, 11 },
|
||||
{ 0x202, 13 },
|
||||
{ 0x203, 15 },
|
||||
{ 0x300, 1 },
|
||||
{ 0x301, 3 },
|
||||
{ 0x302, 5 },
|
||||
{ 0x303, 7 },
|
||||
};
|
||||
|
||||
i = binsearch_IndexTypeEncoding(Index, ARR_SIZE(Index), encoding);
|
||||
if (i == -1)
|
||||
return NULL;
|
||||
else
|
||||
return &MClassSysRegsList[Index[i].index];
|
||||
}
|
||||
|
||||
const MClassSysReg *lookupMClassSysRegByM1Encoding12(uint16_t encoding)
|
||||
{
|
||||
unsigned int i;
|
||||
static const struct IndexType Index[] = {
|
||||
{ 0x400, 0 },
|
||||
{ 0x401, 2 },
|
||||
{ 0x402, 4 },
|
||||
{ 0x403, 6 },
|
||||
{ 0x800, 8 },
|
||||
{ 0x801, 10 },
|
||||
{ 0x802, 12 },
|
||||
{ 0x803, 14 },
|
||||
{ 0x805, 16 },
|
||||
{ 0x806, 17 },
|
||||
{ 0x807, 18 },
|
||||
{ 0x808, 19 },
|
||||
{ 0x809, 20 },
|
||||
{ 0x80A, 21 },
|
||||
{ 0x80B, 22 },
|
||||
{ 0x810, 23 },
|
||||
{ 0x811, 24 },
|
||||
{ 0x812, 25 },
|
||||
{ 0x813, 26 },
|
||||
{ 0x814, 27 },
|
||||
{ 0x888, 28 },
|
||||
{ 0x889, 29 },
|
||||
{ 0x88A, 30 },
|
||||
{ 0x88B, 31 },
|
||||
{ 0x890, 32 },
|
||||
{ 0x891, 33 },
|
||||
{ 0x893, 34 },
|
||||
{ 0x894, 35 },
|
||||
{ 0x898, 36 },
|
||||
{ 0xC00, 1 },
|
||||
{ 0xC01, 3 },
|
||||
{ 0xC02, 5 },
|
||||
{ 0xC03, 7 },
|
||||
{ 0x1800, 9 },
|
||||
{ 0x1801, 11 },
|
||||
{ 0x1802, 13 },
|
||||
{ 0x1803, 15 },
|
||||
};
|
||||
|
||||
i = binsearch_IndexTypeEncoding(Index, ARR_SIZE(Index), encoding);
|
||||
if (i == -1)
|
||||
return NULL;
|
||||
else
|
||||
return &MClassSysRegsList[Index[i].index];
|
||||
}
|
||||
|
||||
const BankedReg *lookupBankedRegByEncoding(uint8_t encoding)
|
||||
{
|
||||
unsigned int i;
|
||||
static const struct IndexType Index[] = {
|
||||
{ 0x0, 0 },
|
||||
{ 0x1, 1 },
|
||||
{ 0x2, 2 },
|
||||
{ 0x3, 3 },
|
||||
{ 0x4, 4 },
|
||||
{ 0x5, 5 },
|
||||
{ 0x6, 6 },
|
||||
{ 0x8, 7 },
|
||||
{ 0x9, 8 },
|
||||
{ 0xA, 9 },
|
||||
{ 0xB, 10 },
|
||||
{ 0xC, 11 },
|
||||
{ 0xD, 12 },
|
||||
{ 0xE, 13 },
|
||||
{ 0x10, 14 },
|
||||
{ 0x11, 15 },
|
||||
{ 0x12, 16 },
|
||||
{ 0x13, 17 },
|
||||
{ 0x14, 18 },
|
||||
{ 0x15, 19 },
|
||||
{ 0x16, 20 },
|
||||
{ 0x17, 21 },
|
||||
{ 0x1C, 22 },
|
||||
{ 0x1D, 23 },
|
||||
{ 0x1E, 24 },
|
||||
{ 0x1F, 25 },
|
||||
{ 0x2E, 26 },
|
||||
{ 0x30, 27 },
|
||||
{ 0x32, 28 },
|
||||
{ 0x34, 29 },
|
||||
{ 0x36, 30 },
|
||||
{ 0x3C, 31 },
|
||||
{ 0x3E, 32 },
|
||||
};
|
||||
|
||||
i = binsearch_IndexTypeEncoding(Index, ARR_SIZE(Index), encoding);
|
||||
if (i == -1)
|
||||
return NULL;
|
||||
else
|
||||
return &BankedRegsList[Index[i].index];
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,43 @@
|
||||
//===- ARMInstPrinter.h - Convert ARM MCInst to assembly syntax -*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This class prints an ARM MCInst to a .s file.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/* Capstone Disassembly Engine */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
|
||||
|
||||
#ifndef CS_ARMINSTPRINTER_H
|
||||
#define CS_ARMINSTPRINTER_H
|
||||
|
||||
#include "../../MCInst.h"
|
||||
#include "../../MCRegisterInfo.h"
|
||||
#include "../../SStream.h"
|
||||
|
||||
void ARM_printInst(MCInst *MI, SStream *O, void *Info);
|
||||
void ARM_post_printer(csh handle, cs_insn *pub_insn, char *mnem, MCInst *mci);
|
||||
|
||||
// setup handle->get_regname
|
||||
void ARM_getRegName(cs_struct *handle, int value);
|
||||
|
||||
// specify vector data type for vector instructions
|
||||
void ARM_addVectorDataType(MCInst *MI, arm_vectordata_type vd);
|
||||
|
||||
void ARM_addVectorDataSize(MCInst *MI, int size);
|
||||
|
||||
void ARM_addReg(MCInst *MI, int reg);
|
||||
|
||||
// load usermode registers (LDM, STM)
|
||||
void ARM_addUserMode(MCInst *MI);
|
||||
|
||||
// sysreg for MRS/MSR
|
||||
void ARM_addSysReg(MCInst *MI, arm_sysreg reg);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,551 @@
|
||||
/* Capstone Disassembly Engine */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
|
||||
|
||||
#ifdef CAPSTONE_HAS_ARM
|
||||
|
||||
#include <stdio.h> // debug
|
||||
#include <string.h>
|
||||
|
||||
#include "../../cs_priv.h"
|
||||
|
||||
#include "ARMMapping.h"
|
||||
|
||||
#define GET_INSTRINFO_ENUM
|
||||
#include "ARMGenInstrInfo.inc"
|
||||
|
||||
#ifndef CAPSTONE_DIET
|
||||
static const name_map reg_name_maps[] = {
|
||||
{ ARM_REG_INVALID, NULL },
|
||||
{ ARM_REG_APSR, "apsr"},
|
||||
{ ARM_REG_APSR_NZCV, "apsr_nzcv"},
|
||||
{ ARM_REG_CPSR, "cpsr"},
|
||||
{ ARM_REG_FPEXC, "fpexc"},
|
||||
{ ARM_REG_FPINST, "fpinst"},
|
||||
{ ARM_REG_FPSCR, "fpscr"},
|
||||
{ ARM_REG_FPSCR_NZCV, "fpscr_nzcv"},
|
||||
{ ARM_REG_FPSID, "fpsid"},
|
||||
{ ARM_REG_ITSTATE, "itstate"},
|
||||
{ ARM_REG_LR, "lr"},
|
||||
{ ARM_REG_PC, "pc"},
|
||||
{ ARM_REG_SP, "sp"},
|
||||
{ ARM_REG_SPSR, "spsr"},
|
||||
{ ARM_REG_D0, "d0"},
|
||||
{ ARM_REG_D1, "d1"},
|
||||
{ ARM_REG_D2, "d2"},
|
||||
{ ARM_REG_D3, "d3"},
|
||||
{ ARM_REG_D4, "d4"},
|
||||
{ ARM_REG_D5, "d5"},
|
||||
{ ARM_REG_D6, "d6"},
|
||||
{ ARM_REG_D7, "d7"},
|
||||
{ ARM_REG_D8, "d8"},
|
||||
{ ARM_REG_D9, "d9"},
|
||||
{ ARM_REG_D10, "d10"},
|
||||
{ ARM_REG_D11, "d11"},
|
||||
{ ARM_REG_D12, "d12"},
|
||||
{ ARM_REG_D13, "d13"},
|
||||
{ ARM_REG_D14, "d14"},
|
||||
{ ARM_REG_D15, "d15"},
|
||||
{ ARM_REG_D16, "d16"},
|
||||
{ ARM_REG_D17, "d17"},
|
||||
{ ARM_REG_D18, "d18"},
|
||||
{ ARM_REG_D19, "d19"},
|
||||
{ ARM_REG_D20, "d20"},
|
||||
{ ARM_REG_D21, "d21"},
|
||||
{ ARM_REG_D22, "d22"},
|
||||
{ ARM_REG_D23, "d23"},
|
||||
{ ARM_REG_D24, "d24"},
|
||||
{ ARM_REG_D25, "d25"},
|
||||
{ ARM_REG_D26, "d26"},
|
||||
{ ARM_REG_D27, "d27"},
|
||||
{ ARM_REG_D28, "d28"},
|
||||
{ ARM_REG_D29, "d29"},
|
||||
{ ARM_REG_D30, "d30"},
|
||||
{ ARM_REG_D31, "d31"},
|
||||
{ ARM_REG_FPINST2, "fpinst2"},
|
||||
{ ARM_REG_MVFR0, "mvfr0"},
|
||||
{ ARM_REG_MVFR1, "mvfr1"},
|
||||
{ ARM_REG_MVFR2, "mvfr2"},
|
||||
{ ARM_REG_Q0, "q0"},
|
||||
{ ARM_REG_Q1, "q1"},
|
||||
{ ARM_REG_Q2, "q2"},
|
||||
{ ARM_REG_Q3, "q3"},
|
||||
{ ARM_REG_Q4, "q4"},
|
||||
{ ARM_REG_Q5, "q5"},
|
||||
{ ARM_REG_Q6, "q6"},
|
||||
{ ARM_REG_Q7, "q7"},
|
||||
{ ARM_REG_Q8, "q8"},
|
||||
{ ARM_REG_Q9, "q9"},
|
||||
{ ARM_REG_Q10, "q10"},
|
||||
{ ARM_REG_Q11, "q11"},
|
||||
{ ARM_REG_Q12, "q12"},
|
||||
{ ARM_REG_Q13, "q13"},
|
||||
{ ARM_REG_Q14, "q14"},
|
||||
{ ARM_REG_Q15, "q15"},
|
||||
{ ARM_REG_R0, "r0"},
|
||||
{ ARM_REG_R1, "r1"},
|
||||
{ ARM_REG_R2, "r2"},
|
||||
{ ARM_REG_R3, "r3"},
|
||||
{ ARM_REG_R4, "r4"},
|
||||
{ ARM_REG_R5, "r5"},
|
||||
{ ARM_REG_R6, "r6"},
|
||||
{ ARM_REG_R7, "r7"},
|
||||
{ ARM_REG_R8, "r8"},
|
||||
{ ARM_REG_R9, "sb"},
|
||||
{ ARM_REG_R10, "sl"},
|
||||
{ ARM_REG_R11, "fp"},
|
||||
{ ARM_REG_R12, "ip"},
|
||||
{ ARM_REG_S0, "s0"},
|
||||
{ ARM_REG_S1, "s1"},
|
||||
{ ARM_REG_S2, "s2"},
|
||||
{ ARM_REG_S3, "s3"},
|
||||
{ ARM_REG_S4, "s4"},
|
||||
{ ARM_REG_S5, "s5"},
|
||||
{ ARM_REG_S6, "s6"},
|
||||
{ ARM_REG_S7, "s7"},
|
||||
{ ARM_REG_S8, "s8"},
|
||||
{ ARM_REG_S9, "s9"},
|
||||
{ ARM_REG_S10, "s10"},
|
||||
{ ARM_REG_S11, "s11"},
|
||||
{ ARM_REG_S12, "s12"},
|
||||
{ ARM_REG_S13, "s13"},
|
||||
{ ARM_REG_S14, "s14"},
|
||||
{ ARM_REG_S15, "s15"},
|
||||
{ ARM_REG_S16, "s16"},
|
||||
{ ARM_REG_S17, "s17"},
|
||||
{ ARM_REG_S18, "s18"},
|
||||
{ ARM_REG_S19, "s19"},
|
||||
{ ARM_REG_S20, "s20"},
|
||||
{ ARM_REG_S21, "s21"},
|
||||
{ ARM_REG_S22, "s22"},
|
||||
{ ARM_REG_S23, "s23"},
|
||||
{ ARM_REG_S24, "s24"},
|
||||
{ ARM_REG_S25, "s25"},
|
||||
{ ARM_REG_S26, "s26"},
|
||||
{ ARM_REG_S27, "s27"},
|
||||
{ ARM_REG_S28, "s28"},
|
||||
{ ARM_REG_S29, "s29"},
|
||||
{ ARM_REG_S30, "s30"},
|
||||
{ ARM_REG_S31, "s31"},
|
||||
};
|
||||
static const name_map reg_name_maps2[] = {
|
||||
{ ARM_REG_INVALID, NULL },
|
||||
{ ARM_REG_APSR, "apsr"},
|
||||
{ ARM_REG_APSR_NZCV, "apsr_nzcv"},
|
||||
{ ARM_REG_CPSR, "cpsr"},
|
||||
{ ARM_REG_FPEXC, "fpexc"},
|
||||
{ ARM_REG_FPINST, "fpinst"},
|
||||
{ ARM_REG_FPSCR, "fpscr"},
|
||||
{ ARM_REG_FPSCR_NZCV, "fpscr_nzcv"},
|
||||
{ ARM_REG_FPSID, "fpsid"},
|
||||
{ ARM_REG_ITSTATE, "itstate"},
|
||||
{ ARM_REG_LR, "lr"},
|
||||
{ ARM_REG_PC, "pc"},
|
||||
{ ARM_REG_SP, "sp"},
|
||||
{ ARM_REG_SPSR, "spsr"},
|
||||
{ ARM_REG_D0, "d0"},
|
||||
{ ARM_REG_D1, "d1"},
|
||||
{ ARM_REG_D2, "d2"},
|
||||
{ ARM_REG_D3, "d3"},
|
||||
{ ARM_REG_D4, "d4"},
|
||||
{ ARM_REG_D5, "d5"},
|
||||
{ ARM_REG_D6, "d6"},
|
||||
{ ARM_REG_D7, "d7"},
|
||||
{ ARM_REG_D8, "d8"},
|
||||
{ ARM_REG_D9, "d9"},
|
||||
{ ARM_REG_D10, "d10"},
|
||||
{ ARM_REG_D11, "d11"},
|
||||
{ ARM_REG_D12, "d12"},
|
||||
{ ARM_REG_D13, "d13"},
|
||||
{ ARM_REG_D14, "d14"},
|
||||
{ ARM_REG_D15, "d15"},
|
||||
{ ARM_REG_D16, "d16"},
|
||||
{ ARM_REG_D17, "d17"},
|
||||
{ ARM_REG_D18, "d18"},
|
||||
{ ARM_REG_D19, "d19"},
|
||||
{ ARM_REG_D20, "d20"},
|
||||
{ ARM_REG_D21, "d21"},
|
||||
{ ARM_REG_D22, "d22"},
|
||||
{ ARM_REG_D23, "d23"},
|
||||
{ ARM_REG_D24, "d24"},
|
||||
{ ARM_REG_D25, "d25"},
|
||||
{ ARM_REG_D26, "d26"},
|
||||
{ ARM_REG_D27, "d27"},
|
||||
{ ARM_REG_D28, "d28"},
|
||||
{ ARM_REG_D29, "d29"},
|
||||
{ ARM_REG_D30, "d30"},
|
||||
{ ARM_REG_D31, "d31"},
|
||||
{ ARM_REG_FPINST2, "fpinst2"},
|
||||
{ ARM_REG_MVFR0, "mvfr0"},
|
||||
{ ARM_REG_MVFR1, "mvfr1"},
|
||||
{ ARM_REG_MVFR2, "mvfr2"},
|
||||
{ ARM_REG_Q0, "q0"},
|
||||
{ ARM_REG_Q1, "q1"},
|
||||
{ ARM_REG_Q2, "q2"},
|
||||
{ ARM_REG_Q3, "q3"},
|
||||
{ ARM_REG_Q4, "q4"},
|
||||
{ ARM_REG_Q5, "q5"},
|
||||
{ ARM_REG_Q6, "q6"},
|
||||
{ ARM_REG_Q7, "q7"},
|
||||
{ ARM_REG_Q8, "q8"},
|
||||
{ ARM_REG_Q9, "q9"},
|
||||
{ ARM_REG_Q10, "q10"},
|
||||
{ ARM_REG_Q11, "q11"},
|
||||
{ ARM_REG_Q12, "q12"},
|
||||
{ ARM_REG_Q13, "q13"},
|
||||
{ ARM_REG_Q14, "q14"},
|
||||
{ ARM_REG_Q15, "q15"},
|
||||
{ ARM_REG_R0, "r0"},
|
||||
{ ARM_REG_R1, "r1"},
|
||||
{ ARM_REG_R2, "r2"},
|
||||
{ ARM_REG_R3, "r3"},
|
||||
{ ARM_REG_R4, "r4"},
|
||||
{ ARM_REG_R5, "r5"},
|
||||
{ ARM_REG_R6, "r6"},
|
||||
{ ARM_REG_R7, "r7"},
|
||||
{ ARM_REG_R8, "r8"},
|
||||
{ ARM_REG_R9, "r9"},
|
||||
{ ARM_REG_R10, "r10"},
|
||||
{ ARM_REG_R11, "r11"},
|
||||
{ ARM_REG_R12, "r12"},
|
||||
{ ARM_REG_S0, "s0"},
|
||||
{ ARM_REG_S1, "s1"},
|
||||
{ ARM_REG_S2, "s2"},
|
||||
{ ARM_REG_S3, "s3"},
|
||||
{ ARM_REG_S4, "s4"},
|
||||
{ ARM_REG_S5, "s5"},
|
||||
{ ARM_REG_S6, "s6"},
|
||||
{ ARM_REG_S7, "s7"},
|
||||
{ ARM_REG_S8, "s8"},
|
||||
{ ARM_REG_S9, "s9"},
|
||||
{ ARM_REG_S10, "s10"},
|
||||
{ ARM_REG_S11, "s11"},
|
||||
{ ARM_REG_S12, "s12"},
|
||||
{ ARM_REG_S13, "s13"},
|
||||
{ ARM_REG_S14, "s14"},
|
||||
{ ARM_REG_S15, "s15"},
|
||||
{ ARM_REG_S16, "s16"},
|
||||
{ ARM_REG_S17, "s17"},
|
||||
{ ARM_REG_S18, "s18"},
|
||||
{ ARM_REG_S19, "s19"},
|
||||
{ ARM_REG_S20, "s20"},
|
||||
{ ARM_REG_S21, "s21"},
|
||||
{ ARM_REG_S22, "s22"},
|
||||
{ ARM_REG_S23, "s23"},
|
||||
{ ARM_REG_S24, "s24"},
|
||||
{ ARM_REG_S25, "s25"},
|
||||
{ ARM_REG_S26, "s26"},
|
||||
{ ARM_REG_S27, "s27"},
|
||||
{ ARM_REG_S28, "s28"},
|
||||
{ ARM_REG_S29, "s29"},
|
||||
{ ARM_REG_S30, "s30"},
|
||||
{ ARM_REG_S31, "s31"},
|
||||
};
|
||||
#endif
|
||||
|
||||
const char *ARM_reg_name(csh handle, unsigned int reg)
|
||||
{
|
||||
#ifndef CAPSTONE_DIET
|
||||
if (reg >= ARR_SIZE(reg_name_maps))
|
||||
return NULL;
|
||||
|
||||
return reg_name_maps[reg].name;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
const char *ARM_reg_name2(csh handle, unsigned int reg)
|
||||
{
|
||||
#ifndef CAPSTONE_DIET
|
||||
if (reg >= ARR_SIZE(reg_name_maps2))
|
||||
return NULL;
|
||||
|
||||
return reg_name_maps2[reg].name;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
static const insn_map insns[] = {
|
||||
// dummy item
|
||||
{
|
||||
0, 0,
|
||||
#ifndef CAPSTONE_DIET
|
||||
{ 0 }, { 0 }, { 0 }, 0, 0
|
||||
#endif
|
||||
},
|
||||
#include "ARMMappingInsn.inc"
|
||||
};
|
||||
|
||||
// look for @id in @insns
|
||||
// return -1 if not found
|
||||
static unsigned int find_insn(unsigned int id)
|
||||
{
|
||||
// binary searching since the IDs are sorted in order
|
||||
unsigned int left, right, m;
|
||||
unsigned int max = ARR_SIZE(insns);
|
||||
|
||||
right = max - 1;
|
||||
|
||||
if (id < insns[0].id || id > insns[right].id)
|
||||
// not found
|
||||
return -1;
|
||||
|
||||
left = 0;
|
||||
|
||||
while(left <= right) {
|
||||
m = (left + right) / 2;
|
||||
if (id == insns[m].id) {
|
||||
return m;
|
||||
}
|
||||
|
||||
if (id < insns[m].id)
|
||||
right = m - 1;
|
||||
else
|
||||
left = m + 1;
|
||||
}
|
||||
|
||||
// not found
|
||||
// printf("NOT FOUNDDDDDDDDDDDDDDD id = %u\n", id);
|
||||
return -1;
|
||||
}
|
||||
|
||||
void ARM_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id)
|
||||
{
|
||||
unsigned int i = find_insn(id);
|
||||
if (i != -1) {
|
||||
insn->id = insns[i].mapid;
|
||||
|
||||
// printf("id = %u, mapid = %u\n", id, insn->id);
|
||||
|
||||
if (h->detail) {
|
||||
#ifndef CAPSTONE_DIET
|
||||
cs_struct handle;
|
||||
handle.detail = h->detail;
|
||||
|
||||
memcpy(insn->detail->regs_read, insns[i].regs_use, sizeof(insns[i].regs_use));
|
||||
insn->detail->regs_read_count = (uint8_t)count_positive(insns[i].regs_use);
|
||||
|
||||
memcpy(insn->detail->regs_write, insns[i].regs_mod, sizeof(insns[i].regs_mod));
|
||||
insn->detail->regs_write_count = (uint8_t)count_positive(insns[i].regs_mod);
|
||||
|
||||
memcpy(insn->detail->groups, insns[i].groups, sizeof(insns[i].groups));
|
||||
insn->detail->groups_count = (uint8_t)count_positive8(insns[i].groups);
|
||||
|
||||
insn->detail->arm.update_flags = cs_reg_write((csh)&handle, insn, ARM_REG_CPSR);
|
||||
|
||||
if (insns[i].branch || insns[i].indirect_branch) {
|
||||
// this insn also belongs to JUMP group. add JUMP group
|
||||
insn->detail->groups[insn->detail->groups_count] = ARM_GRP_JUMP;
|
||||
insn->detail->groups_count++;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef CAPSTONE_DIET
|
||||
static const char * const insn_name_maps[] = {
|
||||
NULL, // ARM_INS_INVALID
|
||||
#include "ARMMappingInsnName.inc"
|
||||
};
|
||||
#endif
|
||||
|
||||
const char *ARM_insn_name(csh handle, unsigned int id)
|
||||
{
|
||||
#ifndef CAPSTONE_DIET
|
||||
if (id >= ARM_INS_ENDING)
|
||||
return NULL;
|
||||
|
||||
return insn_name_maps[id];
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef CAPSTONE_DIET
|
||||
static const name_map group_name_maps[] = {
|
||||
// generic groups
|
||||
{ ARM_GRP_INVALID, NULL },
|
||||
{ ARM_GRP_JUMP, "jump" },
|
||||
{ ARM_GRP_CALL, "call" },
|
||||
{ ARM_GRP_INT, "int" },
|
||||
{ ARM_GRP_PRIVILEGE, "privilege" },
|
||||
{ ARM_GRP_BRANCH_RELATIVE, "branch_relative" },
|
||||
|
||||
// architecture-specific groups
|
||||
{ ARM_GRP_CRYPTO, "crypto" },
|
||||
{ ARM_GRP_DATABARRIER, "databarrier" },
|
||||
{ ARM_GRP_DIVIDE, "divide" },
|
||||
{ ARM_GRP_FPARMV8, "fparmv8" },
|
||||
{ ARM_GRP_MULTPRO, "multpro" },
|
||||
{ ARM_GRP_NEON, "neon" },
|
||||
{ ARM_GRP_T2EXTRACTPACK, "T2EXTRACTPACK" },
|
||||
{ ARM_GRP_THUMB2DSP, "THUMB2DSP" },
|
||||
{ ARM_GRP_TRUSTZONE, "TRUSTZONE" },
|
||||
{ ARM_GRP_V4T, "v4t" },
|
||||
{ ARM_GRP_V5T, "v5t" },
|
||||
{ ARM_GRP_V5TE, "v5te" },
|
||||
{ ARM_GRP_V6, "v6" },
|
||||
{ ARM_GRP_V6T2, "v6t2" },
|
||||
{ ARM_GRP_V7, "v7" },
|
||||
{ ARM_GRP_V8, "v8" },
|
||||
{ ARM_GRP_VFP2, "vfp2" },
|
||||
{ ARM_GRP_VFP3, "vfp3" },
|
||||
{ ARM_GRP_VFP4, "vfp4" },
|
||||
{ ARM_GRP_ARM, "arm" },
|
||||
{ ARM_GRP_MCLASS, "mclass" },
|
||||
{ ARM_GRP_NOTMCLASS, "notmclass" },
|
||||
{ ARM_GRP_THUMB, "thumb" },
|
||||
{ ARM_GRP_THUMB1ONLY, "thumb1only" },
|
||||
{ ARM_GRP_THUMB2, "thumb2" },
|
||||
{ ARM_GRP_PREV8, "prev8" },
|
||||
{ ARM_GRP_FPVMLX, "fpvmlx" },
|
||||
{ ARM_GRP_MULOPS, "mulops" },
|
||||
{ ARM_GRP_CRC, "crc" },
|
||||
{ ARM_GRP_DPVFP, "dpvfp" },
|
||||
{ ARM_GRP_V6M, "v6m" },
|
||||
{ ARM_GRP_VIRTUALIZATION, "virtualization" },
|
||||
};
|
||||
#endif
|
||||
|
||||
const char *ARM_group_name(csh handle, unsigned int id)
|
||||
{
|
||||
#ifndef CAPSTONE_DIET
|
||||
return id2name(group_name_maps, ARR_SIZE(group_name_maps), id);
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
// list all relative branch instructions
|
||||
// ie: insns[i].branch && !insns[i].indirect_branch
|
||||
static const unsigned int insn_rel[] = {
|
||||
ARM_BL,
|
||||
ARM_BLX_pred,
|
||||
ARM_Bcc,
|
||||
ARM_t2B,
|
||||
ARM_t2Bcc,
|
||||
ARM_tB,
|
||||
ARM_tBcc,
|
||||
ARM_tCBNZ,
|
||||
ARM_tCBZ,
|
||||
ARM_BL_pred,
|
||||
ARM_BLXi,
|
||||
ARM_tBL,
|
||||
ARM_tBLXi,
|
||||
0
|
||||
};
|
||||
|
||||
static const unsigned int insn_blx_rel_to_arm[] = {
|
||||
ARM_tBLXi,
|
||||
0
|
||||
};
|
||||
|
||||
// check if this insn is relative branch
|
||||
bool ARM_rel_branch(cs_struct *h, unsigned int id)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; insn_rel[i]; i++) {
|
||||
if (id == insn_rel[i]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// not found
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ARM_blx_to_arm_mode(cs_struct *h, unsigned int id) {
|
||||
int i;
|
||||
|
||||
for (i = 0; insn_blx_rel_to_arm[i]; i++)
|
||||
if (id == insn_blx_rel_to_arm[i])
|
||||
return true;
|
||||
|
||||
// not found
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
#ifndef CAPSTONE_DIET
|
||||
// map instruction to its characteristics
|
||||
typedef struct insn_op {
|
||||
uint8_t access[7];
|
||||
} insn_op;
|
||||
|
||||
static const insn_op insn_ops[] = {
|
||||
{
|
||||
// NULL item
|
||||
{ 0 }
|
||||
},
|
||||
|
||||
#include "ARMMappingInsnOp.inc"
|
||||
};
|
||||
|
||||
// given internal insn id, return operand access info
|
||||
const uint8_t *ARM_get_op_access(cs_struct *h, unsigned int id)
|
||||
{
|
||||
int i = insn_find(insns, ARR_SIZE(insns), id, &h->insn_cache);
|
||||
if (i != 0) {
|
||||
return insn_ops[i].access;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void ARM_reg_access(const cs_insn *insn,
|
||||
cs_regs regs_read, uint8_t *regs_read_count,
|
||||
cs_regs regs_write, uint8_t *regs_write_count)
|
||||
{
|
||||
uint8_t i;
|
||||
uint8_t read_count, write_count;
|
||||
cs_arm *arm = &(insn->detail->arm);
|
||||
|
||||
read_count = insn->detail->regs_read_count;
|
||||
write_count = insn->detail->regs_write_count;
|
||||
|
||||
// implicit registers
|
||||
memcpy(regs_read, insn->detail->regs_read, read_count * sizeof(insn->detail->regs_read[0]));
|
||||
memcpy(regs_write, insn->detail->regs_write, write_count * sizeof(insn->detail->regs_write[0]));
|
||||
|
||||
// explicit registers
|
||||
for (i = 0; i < arm->op_count; i++) {
|
||||
cs_arm_op *op = &(arm->operands[i]);
|
||||
switch((int)op->type) {
|
||||
case ARM_OP_REG:
|
||||
if ((op->access & CS_AC_READ) && !arr_exist(regs_read, read_count, op->reg)) {
|
||||
regs_read[read_count] = (uint16_t)op->reg;
|
||||
read_count++;
|
||||
}
|
||||
if ((op->access & CS_AC_WRITE) && !arr_exist(regs_write, write_count, op->reg)) {
|
||||
regs_write[write_count] = (uint16_t)op->reg;
|
||||
write_count++;
|
||||
}
|
||||
break;
|
||||
case ARM_OP_MEM:
|
||||
// registers appeared in memory references always being read
|
||||
if ((op->mem.base != ARM_REG_INVALID) && !arr_exist(regs_read, read_count, op->mem.base)) {
|
||||
regs_read[read_count] = (uint16_t)op->mem.base;
|
||||
read_count++;
|
||||
}
|
||||
if ((op->mem.index != ARM_REG_INVALID) && !arr_exist(regs_read, read_count, op->mem.index)) {
|
||||
regs_read[read_count] = (uint16_t)op->mem.index;
|
||||
read_count++;
|
||||
}
|
||||
if ((arm->writeback) && (op->mem.base != ARM_REG_INVALID) && !arr_exist(regs_write, write_count, op->mem.base)) {
|
||||
regs_write[write_count] = (uint16_t)op->mem.base;
|
||||
write_count++;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
*regs_read_count = read_count;
|
||||
*regs_write_count = write_count;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,40 @@
|
||||
/* Capstone Disassembly Engine */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
|
||||
|
||||
#ifndef CS_ARM_MAP_H
|
||||
#define CS_ARM_MAP_H
|
||||
|
||||
#include "../../include/capstone/capstone.h"
|
||||
#include "../../utils.h"
|
||||
|
||||
// return name of regiser in friendly string
|
||||
const char *ARM_reg_name(csh handle, unsigned int reg);
|
||||
const char *ARM_reg_name2(csh handle, unsigned int reg);
|
||||
|
||||
// given internal insn id, return public instruction ID
|
||||
void ARM_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id);
|
||||
|
||||
const char *ARM_insn_name(csh handle, unsigned int id);
|
||||
|
||||
const char *ARM_group_name(csh handle, unsigned int id);
|
||||
|
||||
// check if this insn is relative branch
|
||||
bool ARM_rel_branch(cs_struct *h, unsigned int insn_id);
|
||||
|
||||
bool ARM_blx_to_arm_mode(cs_struct *h, unsigned int insn_id);
|
||||
|
||||
const uint8_t *ARM_get_op_access(cs_struct *h, unsigned int id);
|
||||
|
||||
void ARM_reg_access(const cs_insn *insn,
|
||||
cs_regs regs_read, uint8_t *regs_read_count,
|
||||
cs_regs regs_write, uint8_t *regs_write_count);
|
||||
|
||||
typedef struct BankedReg {
|
||||
const char *Name;
|
||||
arm_sysreg sysreg;
|
||||
uint16_t Encoding;
|
||||
} BankedReg;
|
||||
|
||||
const BankedReg *lookupBankedRegByEncoding(uint8_t encoding);
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,475 @@
|
||||
/* Capstone Disassembly Engine, http://www.capstone-engine.org */
|
||||
/* This is auto-gen data for Capstone disassembly engine (www.capstone-engine.org) */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
|
||||
|
||||
"adc", // ARM_INS_ADC,
|
||||
"add", // ARM_INS_ADD,
|
||||
"addw", // ARM_INS_ADDW,
|
||||
"adr", // ARM_INS_ADR,
|
||||
"aesd", // ARM_INS_AESD,
|
||||
"aese", // ARM_INS_AESE,
|
||||
"aesimc", // ARM_INS_AESIMC,
|
||||
"aesmc", // ARM_INS_AESMC,
|
||||
"and", // ARM_INS_AND,
|
||||
"asr", // ARM_INS_ASR,
|
||||
"b", // ARM_INS_B,
|
||||
"bfc", // ARM_INS_BFC,
|
||||
"bfi", // ARM_INS_BFI,
|
||||
"bic", // ARM_INS_BIC,
|
||||
"bkpt", // ARM_INS_BKPT,
|
||||
"bl", // ARM_INS_BL,
|
||||
"blx", // ARM_INS_BLX,
|
||||
"blxns", // ARM_INS_BLXNS,
|
||||
"bx", // ARM_INS_BX,
|
||||
"bxj", // ARM_INS_BXJ,
|
||||
"bxns", // ARM_INS_BXNS,
|
||||
"cbnz", // ARM_INS_CBNZ,
|
||||
"cbz", // ARM_INS_CBZ,
|
||||
"cdp", // ARM_INS_CDP,
|
||||
"cdp2", // ARM_INS_CDP2,
|
||||
"clrex", // ARM_INS_CLREX,
|
||||
"clz", // ARM_INS_CLZ,
|
||||
"cmn", // ARM_INS_CMN,
|
||||
"cmp", // ARM_INS_CMP,
|
||||
"cps", // ARM_INS_CPS,
|
||||
"crc32b", // ARM_INS_CRC32B,
|
||||
"crc32cb", // ARM_INS_CRC32CB,
|
||||
"crc32ch", // ARM_INS_CRC32CH,
|
||||
"crc32cw", // ARM_INS_CRC32CW,
|
||||
"crc32h", // ARM_INS_CRC32H,
|
||||
"crc32w", // ARM_INS_CRC32W,
|
||||
"csdb", // ARM_INS_CSDB,
|
||||
"dbg", // ARM_INS_DBG,
|
||||
"dcps1", // ARM_INS_DCPS1,
|
||||
"dcps2", // ARM_INS_DCPS2,
|
||||
"dcps3", // ARM_INS_DCPS3,
|
||||
"dfb", // ARM_INS_DFB,
|
||||
"dmb", // ARM_INS_DMB,
|
||||
"dsb", // ARM_INS_DSB,
|
||||
"eor", // ARM_INS_EOR,
|
||||
"eret", // ARM_INS_ERET,
|
||||
"esb", // ARM_INS_ESB,
|
||||
"faddd", // ARM_INS_FADDD,
|
||||
"fadds", // ARM_INS_FADDS,
|
||||
"fcmpzd", // ARM_INS_FCMPZD,
|
||||
"fcmpzs", // ARM_INS_FCMPZS,
|
||||
"fconstd", // ARM_INS_FCONSTD,
|
||||
"fconsts", // ARM_INS_FCONSTS,
|
||||
"fldmdbx", // ARM_INS_FLDMDBX,
|
||||
"fldmiax", // ARM_INS_FLDMIAX,
|
||||
"fmdhr", // ARM_INS_FMDHR,
|
||||
"fmdlr", // ARM_INS_FMDLR,
|
||||
"fmstat", // ARM_INS_FMSTAT,
|
||||
"fstmdbx", // ARM_INS_FSTMDBX,
|
||||
"fstmiax", // ARM_INS_FSTMIAX,
|
||||
"fsubd", // ARM_INS_FSUBD,
|
||||
"fsubs", // ARM_INS_FSUBS,
|
||||
"hint", // ARM_INS_HINT,
|
||||
"hlt", // ARM_INS_HLT,
|
||||
"hvc", // ARM_INS_HVC,
|
||||
"isb", // ARM_INS_ISB,
|
||||
"it", // ARM_INS_IT,
|
||||
"lda", // ARM_INS_LDA,
|
||||
"ldab", // ARM_INS_LDAB,
|
||||
"ldaex", // ARM_INS_LDAEX,
|
||||
"ldaexb", // ARM_INS_LDAEXB,
|
||||
"ldaexd", // ARM_INS_LDAEXD,
|
||||
"ldaexh", // ARM_INS_LDAEXH,
|
||||
"ldah", // ARM_INS_LDAH,
|
||||
"ldc", // ARM_INS_LDC,
|
||||
"ldc2", // ARM_INS_LDC2,
|
||||
"ldc2l", // ARM_INS_LDC2L,
|
||||
"ldcl", // ARM_INS_LDCL,
|
||||
"ldm", // ARM_INS_LDM,
|
||||
"ldmda", // ARM_INS_LDMDA,
|
||||
"ldmdb", // ARM_INS_LDMDB,
|
||||
"ldmib", // ARM_INS_LDMIB,
|
||||
"ldr", // ARM_INS_LDR,
|
||||
"ldrb", // ARM_INS_LDRB,
|
||||
"ldrbt", // ARM_INS_LDRBT,
|
||||
"ldrd", // ARM_INS_LDRD,
|
||||
"ldrex", // ARM_INS_LDREX,
|
||||
"ldrexb", // ARM_INS_LDREXB,
|
||||
"ldrexd", // ARM_INS_LDREXD,
|
||||
"ldrexh", // ARM_INS_LDREXH,
|
||||
"ldrh", // ARM_INS_LDRH,
|
||||
"ldrht", // ARM_INS_LDRHT,
|
||||
"ldrsb", // ARM_INS_LDRSB,
|
||||
"ldrsbt", // ARM_INS_LDRSBT,
|
||||
"ldrsh", // ARM_INS_LDRSH,
|
||||
"ldrsht", // ARM_INS_LDRSHT,
|
||||
"ldrt", // ARM_INS_LDRT,
|
||||
"lsl", // ARM_INS_LSL,
|
||||
"lsr", // ARM_INS_LSR,
|
||||
"mcr", // ARM_INS_MCR,
|
||||
"mcr2", // ARM_INS_MCR2,
|
||||
"mcrr", // ARM_INS_MCRR,
|
||||
"mcrr2", // ARM_INS_MCRR2,
|
||||
"mla", // ARM_INS_MLA,
|
||||
"mls", // ARM_INS_MLS,
|
||||
"mov", // ARM_INS_MOV,
|
||||
"movs", // ARM_INS_MOVS,
|
||||
"movt", // ARM_INS_MOVT,
|
||||
"movw", // ARM_INS_MOVW,
|
||||
"mrc", // ARM_INS_MRC,
|
||||
"mrc2", // ARM_INS_MRC2,
|
||||
"mrrc", // ARM_INS_MRRC,
|
||||
"mrrc2", // ARM_INS_MRRC2,
|
||||
"mrs", // ARM_INS_MRS,
|
||||
"msr", // ARM_INS_MSR,
|
||||
"mul", // ARM_INS_MUL,
|
||||
"mvn", // ARM_INS_MVN,
|
||||
"neg", // ARM_INS_NEG,
|
||||
"nop", // ARM_INS_NOP,
|
||||
"orn", // ARM_INS_ORN,
|
||||
"orr", // ARM_INS_ORR,
|
||||
"pkhbt", // ARM_INS_PKHBT,
|
||||
"pkhtb", // ARM_INS_PKHTB,
|
||||
"pld", // ARM_INS_PLD,
|
||||
"pldw", // ARM_INS_PLDW,
|
||||
"pli", // ARM_INS_PLI,
|
||||
"pop", // ARM_INS_POP,
|
||||
"push", // ARM_INS_PUSH,
|
||||
"qadd", // ARM_INS_QADD,
|
||||
"qadd16", // ARM_INS_QADD16,
|
||||
"qadd8", // ARM_INS_QADD8,
|
||||
"qasx", // ARM_INS_QASX,
|
||||
"qdadd", // ARM_INS_QDADD,
|
||||
"qdsub", // ARM_INS_QDSUB,
|
||||
"qsax", // ARM_INS_QSAX,
|
||||
"qsub", // ARM_INS_QSUB,
|
||||
"qsub16", // ARM_INS_QSUB16,
|
||||
"qsub8", // ARM_INS_QSUB8,
|
||||
"rbit", // ARM_INS_RBIT,
|
||||
"rev", // ARM_INS_REV,
|
||||
"rev16", // ARM_INS_REV16,
|
||||
"revsh", // ARM_INS_REVSH,
|
||||
"rfeda", // ARM_INS_RFEDA,
|
||||
"rfedb", // ARM_INS_RFEDB,
|
||||
"rfeia", // ARM_INS_RFEIA,
|
||||
"rfeib", // ARM_INS_RFEIB,
|
||||
"ror", // ARM_INS_ROR,
|
||||
"rrx", // ARM_INS_RRX,
|
||||
"rsb", // ARM_INS_RSB,
|
||||
"rsc", // ARM_INS_RSC,
|
||||
"sadd16", // ARM_INS_SADD16,
|
||||
"sadd8", // ARM_INS_SADD8,
|
||||
"sasx", // ARM_INS_SASX,
|
||||
"sbc", // ARM_INS_SBC,
|
||||
"sbfx", // ARM_INS_SBFX,
|
||||
"sdiv", // ARM_INS_SDIV,
|
||||
"sel", // ARM_INS_SEL,
|
||||
"setend", // ARM_INS_SETEND,
|
||||
"setpan", // ARM_INS_SETPAN,
|
||||
"sev", // ARM_INS_SEV,
|
||||
"sevl", // ARM_INS_SEVL,
|
||||
"sg", // ARM_INS_SG,
|
||||
"sha1c", // ARM_INS_SHA1C,
|
||||
"sha1h", // ARM_INS_SHA1H,
|
||||
"sha1m", // ARM_INS_SHA1M,
|
||||
"sha1p", // ARM_INS_SHA1P,
|
||||
"sha1su0", // ARM_INS_SHA1SU0,
|
||||
"sha1su1", // ARM_INS_SHA1SU1,
|
||||
"sha256h", // ARM_INS_SHA256H,
|
||||
"sha256h2", // ARM_INS_SHA256H2,
|
||||
"sha256su0", // ARM_INS_SHA256SU0,
|
||||
"sha256su1", // ARM_INS_SHA256SU1,
|
||||
"shadd16", // ARM_INS_SHADD16,
|
||||
"shadd8", // ARM_INS_SHADD8,
|
||||
"shasx", // ARM_INS_SHASX,
|
||||
"shsax", // ARM_INS_SHSAX,
|
||||
"shsub16", // ARM_INS_SHSUB16,
|
||||
"shsub8", // ARM_INS_SHSUB8,
|
||||
"smc", // ARM_INS_SMC,
|
||||
"smlabb", // ARM_INS_SMLABB,
|
||||
"smlabt", // ARM_INS_SMLABT,
|
||||
"smlad", // ARM_INS_SMLAD,
|
||||
"smladx", // ARM_INS_SMLADX,
|
||||
"smlal", // ARM_INS_SMLAL,
|
||||
"smlalbb", // ARM_INS_SMLALBB,
|
||||
"smlalbt", // ARM_INS_SMLALBT,
|
||||
"smlald", // ARM_INS_SMLALD,
|
||||
"smlaldx", // ARM_INS_SMLALDX,
|
||||
"smlaltb", // ARM_INS_SMLALTB,
|
||||
"smlaltt", // ARM_INS_SMLALTT,
|
||||
"smlatb", // ARM_INS_SMLATB,
|
||||
"smlatt", // ARM_INS_SMLATT,
|
||||
"smlawb", // ARM_INS_SMLAWB,
|
||||
"smlawt", // ARM_INS_SMLAWT,
|
||||
"smlsd", // ARM_INS_SMLSD,
|
||||
"smlsdx", // ARM_INS_SMLSDX,
|
||||
"smlsld", // ARM_INS_SMLSLD,
|
||||
"smlsldx", // ARM_INS_SMLSLDX,
|
||||
"smmla", // ARM_INS_SMMLA,
|
||||
"smmlar", // ARM_INS_SMMLAR,
|
||||
"smmls", // ARM_INS_SMMLS,
|
||||
"smmlsr", // ARM_INS_SMMLSR,
|
||||
"smmul", // ARM_INS_SMMUL,
|
||||
"smmulr", // ARM_INS_SMMULR,
|
||||
"smuad", // ARM_INS_SMUAD,
|
||||
"smuadx", // ARM_INS_SMUADX,
|
||||
"smulbb", // ARM_INS_SMULBB,
|
||||
"smulbt", // ARM_INS_SMULBT,
|
||||
"smull", // ARM_INS_SMULL,
|
||||
"smultb", // ARM_INS_SMULTB,
|
||||
"smultt", // ARM_INS_SMULTT,
|
||||
"smulwb", // ARM_INS_SMULWB,
|
||||
"smulwt", // ARM_INS_SMULWT,
|
||||
"smusd", // ARM_INS_SMUSD,
|
||||
"smusdx", // ARM_INS_SMUSDX,
|
||||
"srsda", // ARM_INS_SRSDA,
|
||||
"srsdb", // ARM_INS_SRSDB,
|
||||
"srsia", // ARM_INS_SRSIA,
|
||||
"srsib", // ARM_INS_SRSIB,
|
||||
"ssat", // ARM_INS_SSAT,
|
||||
"ssat16", // ARM_INS_SSAT16,
|
||||
"ssax", // ARM_INS_SSAX,
|
||||
"ssub16", // ARM_INS_SSUB16,
|
||||
"ssub8", // ARM_INS_SSUB8,
|
||||
"stc", // ARM_INS_STC,
|
||||
"stc2", // ARM_INS_STC2,
|
||||
"stc2l", // ARM_INS_STC2L,
|
||||
"stcl", // ARM_INS_STCL,
|
||||
"stl", // ARM_INS_STL,
|
||||
"stlb", // ARM_INS_STLB,
|
||||
"stlex", // ARM_INS_STLEX,
|
||||
"stlexb", // ARM_INS_STLEXB,
|
||||
"stlexd", // ARM_INS_STLEXD,
|
||||
"stlexh", // ARM_INS_STLEXH,
|
||||
"stlh", // ARM_INS_STLH,
|
||||
"stm", // ARM_INS_STM,
|
||||
"stmda", // ARM_INS_STMDA,
|
||||
"stmdb", // ARM_INS_STMDB,
|
||||
"stmib", // ARM_INS_STMIB,
|
||||
"str", // ARM_INS_STR,
|
||||
"strb", // ARM_INS_STRB,
|
||||
"strbt", // ARM_INS_STRBT,
|
||||
"strd", // ARM_INS_STRD,
|
||||
"strex", // ARM_INS_STREX,
|
||||
"strexb", // ARM_INS_STREXB,
|
||||
"strexd", // ARM_INS_STREXD,
|
||||
"strexh", // ARM_INS_STREXH,
|
||||
"strh", // ARM_INS_STRH,
|
||||
"strht", // ARM_INS_STRHT,
|
||||
"strt", // ARM_INS_STRT,
|
||||
"sub", // ARM_INS_SUB,
|
||||
"subs", // ARM_INS_SUBS,
|
||||
"subw", // ARM_INS_SUBW,
|
||||
"svc", // ARM_INS_SVC,
|
||||
"swp", // ARM_INS_SWP,
|
||||
"swpb", // ARM_INS_SWPB,
|
||||
"sxtab", // ARM_INS_SXTAB,
|
||||
"sxtab16", // ARM_INS_SXTAB16,
|
||||
"sxtah", // ARM_INS_SXTAH,
|
||||
"sxtb", // ARM_INS_SXTB,
|
||||
"sxtb16", // ARM_INS_SXTB16,
|
||||
"sxth", // ARM_INS_SXTH,
|
||||
"tbb", // ARM_INS_TBB,
|
||||
"tbh", // ARM_INS_TBH,
|
||||
"teq", // ARM_INS_TEQ,
|
||||
"trap", // ARM_INS_TRAP,
|
||||
"tsb", // ARM_INS_TSB,
|
||||
"tst", // ARM_INS_TST,
|
||||
"tt", // ARM_INS_TT,
|
||||
"tta", // ARM_INS_TTA,
|
||||
"ttat", // ARM_INS_TTAT,
|
||||
"ttt", // ARM_INS_TTT,
|
||||
"uadd16", // ARM_INS_UADD16,
|
||||
"uadd8", // ARM_INS_UADD8,
|
||||
"uasx", // ARM_INS_UASX,
|
||||
"ubfx", // ARM_INS_UBFX,
|
||||
"udf", // ARM_INS_UDF,
|
||||
"udiv", // ARM_INS_UDIV,
|
||||
"uhadd16", // ARM_INS_UHADD16,
|
||||
"uhadd8", // ARM_INS_UHADD8,
|
||||
"uhasx", // ARM_INS_UHASX,
|
||||
"uhsax", // ARM_INS_UHSAX,
|
||||
"uhsub16", // ARM_INS_UHSUB16,
|
||||
"uhsub8", // ARM_INS_UHSUB8,
|
||||
"umaal", // ARM_INS_UMAAL,
|
||||
"umlal", // ARM_INS_UMLAL,
|
||||
"umull", // ARM_INS_UMULL,
|
||||
"uqadd16", // ARM_INS_UQADD16,
|
||||
"uqadd8", // ARM_INS_UQADD8,
|
||||
"uqasx", // ARM_INS_UQASX,
|
||||
"uqsax", // ARM_INS_UQSAX,
|
||||
"uqsub16", // ARM_INS_UQSUB16,
|
||||
"uqsub8", // ARM_INS_UQSUB8,
|
||||
"usad8", // ARM_INS_USAD8,
|
||||
"usada8", // ARM_INS_USADA8,
|
||||
"usat", // ARM_INS_USAT,
|
||||
"usat16", // ARM_INS_USAT16,
|
||||
"usax", // ARM_INS_USAX,
|
||||
"usub16", // ARM_INS_USUB16,
|
||||
"usub8", // ARM_INS_USUB8,
|
||||
"uxtab", // ARM_INS_UXTAB,
|
||||
"uxtab16", // ARM_INS_UXTAB16,
|
||||
"uxtah", // ARM_INS_UXTAH,
|
||||
"uxtb", // ARM_INS_UXTB,
|
||||
"uxtb16", // ARM_INS_UXTB16,
|
||||
"uxth", // ARM_INS_UXTH,
|
||||
"vaba", // ARM_INS_VABA,
|
||||
"vabal", // ARM_INS_VABAL,
|
||||
"vabd", // ARM_INS_VABD,
|
||||
"vabdl", // ARM_INS_VABDL,
|
||||
"vabs", // ARM_INS_VABS,
|
||||
"vacge", // ARM_INS_VACGE,
|
||||
"vacgt", // ARM_INS_VACGT,
|
||||
"vacle", // ARM_INS_VACLE,
|
||||
"vaclt", // ARM_INS_VACLT,
|
||||
"vadd", // ARM_INS_VADD,
|
||||
"vaddhn", // ARM_INS_VADDHN,
|
||||
"vaddl", // ARM_INS_VADDL,
|
||||
"vaddw", // ARM_INS_VADDW,
|
||||
"vand", // ARM_INS_VAND,
|
||||
"vbic", // ARM_INS_VBIC,
|
||||
"vbif", // ARM_INS_VBIF,
|
||||
"vbit", // ARM_INS_VBIT,
|
||||
"vbsl", // ARM_INS_VBSL,
|
||||
"vcadd", // ARM_INS_VCADD,
|
||||
"vceq", // ARM_INS_VCEQ,
|
||||
"vcge", // ARM_INS_VCGE,
|
||||
"vcgt", // ARM_INS_VCGT,
|
||||
"vcle", // ARM_INS_VCLE,
|
||||
"vcls", // ARM_INS_VCLS,
|
||||
"vclt", // ARM_INS_VCLT,
|
||||
"vclz", // ARM_INS_VCLZ,
|
||||
"vcmla", // ARM_INS_VCMLA,
|
||||
"vcmp", // ARM_INS_VCMP,
|
||||
"vcmpe", // ARM_INS_VCMPE,
|
||||
"vcnt", // ARM_INS_VCNT,
|
||||
"vcvt", // ARM_INS_VCVT,
|
||||
"vcvta", // ARM_INS_VCVTA,
|
||||
"vcvtb", // ARM_INS_VCVTB,
|
||||
"vcvtm", // ARM_INS_VCVTM,
|
||||
"vcvtn", // ARM_INS_VCVTN,
|
||||
"vcvtp", // ARM_INS_VCVTP,
|
||||
"vcvtr", // ARM_INS_VCVTR,
|
||||
"vcvtt", // ARM_INS_VCVTT,
|
||||
"vdiv", // ARM_INS_VDIV,
|
||||
"vdup", // ARM_INS_VDUP,
|
||||
"veor", // ARM_INS_VEOR,
|
||||
"vext", // ARM_INS_VEXT,
|
||||
"vfma", // ARM_INS_VFMA,
|
||||
"vfms", // ARM_INS_VFMS,
|
||||
"vfnma", // ARM_INS_VFNMA,
|
||||
"vfnms", // ARM_INS_VFNMS,
|
||||
"vhadd", // ARM_INS_VHADD,
|
||||
"vhsub", // ARM_INS_VHSUB,
|
||||
"vins", // ARM_INS_VINS,
|
||||
"vjcvt", // ARM_INS_VJCVT,
|
||||
"vld1", // ARM_INS_VLD1,
|
||||
"vld2", // ARM_INS_VLD2,
|
||||
"vld3", // ARM_INS_VLD3,
|
||||
"vld4", // ARM_INS_VLD4,
|
||||
"vldmdb", // ARM_INS_VLDMDB,
|
||||
"vldmia", // ARM_INS_VLDMIA,
|
||||
"vldr", // ARM_INS_VLDR,
|
||||
"vlldm", // ARM_INS_VLLDM,
|
||||
"vlstm", // ARM_INS_VLSTM,
|
||||
"vmax", // ARM_INS_VMAX,
|
||||
"vmaxnm", // ARM_INS_VMAXNM,
|
||||
"vmin", // ARM_INS_VMIN,
|
||||
"vminnm", // ARM_INS_VMINNM,
|
||||
"vmla", // ARM_INS_VMLA,
|
||||
"vmlal", // ARM_INS_VMLAL,
|
||||
"vmls", // ARM_INS_VMLS,
|
||||
"vmlsl", // ARM_INS_VMLSL,
|
||||
"vmov", // ARM_INS_VMOV,
|
||||
"vmovl", // ARM_INS_VMOVL,
|
||||
"vmovn", // ARM_INS_VMOVN,
|
||||
"vmovx", // ARM_INS_VMOVX,
|
||||
"vmrs", // ARM_INS_VMRS,
|
||||
"vmsr", // ARM_INS_VMSR,
|
||||
"vmul", // ARM_INS_VMUL,
|
||||
"vmull", // ARM_INS_VMULL,
|
||||
"vmvn", // ARM_INS_VMVN,
|
||||
"vneg", // ARM_INS_VNEG,
|
||||
"vnmla", // ARM_INS_VNMLA,
|
||||
"vnmls", // ARM_INS_VNMLS,
|
||||
"vnmul", // ARM_INS_VNMUL,
|
||||
"vorn", // ARM_INS_VORN,
|
||||
"vorr", // ARM_INS_VORR,
|
||||
"vpadal", // ARM_INS_VPADAL,
|
||||
"vpadd", // ARM_INS_VPADD,
|
||||
"vpaddl", // ARM_INS_VPADDL,
|
||||
"vpmax", // ARM_INS_VPMAX,
|
||||
"vpmin", // ARM_INS_VPMIN,
|
||||
"vpop", // ARM_INS_VPOP,
|
||||
"vpush", // ARM_INS_VPUSH,
|
||||
"vqabs", // ARM_INS_VQABS,
|
||||
"vqadd", // ARM_INS_VQADD,
|
||||
"vqdmlal", // ARM_INS_VQDMLAL,
|
||||
"vqdmlsl", // ARM_INS_VQDMLSL,
|
||||
"vqdmulh", // ARM_INS_VQDMULH,
|
||||
"vqdmull", // ARM_INS_VQDMULL,
|
||||
"vqmovn", // ARM_INS_VQMOVN,
|
||||
"vqmovun", // ARM_INS_VQMOVUN,
|
||||
"vqneg", // ARM_INS_VQNEG,
|
||||
"vqrdmlah", // ARM_INS_VQRDMLAH,
|
||||
"vqrdmlsh", // ARM_INS_VQRDMLSH,
|
||||
"vqrdmulh", // ARM_INS_VQRDMULH,
|
||||
"vqrshl", // ARM_INS_VQRSHL,
|
||||
"vqrshrn", // ARM_INS_VQRSHRN,
|
||||
"vqrshrun", // ARM_INS_VQRSHRUN,
|
||||
"vqshl", // ARM_INS_VQSHL,
|
||||
"vqshlu", // ARM_INS_VQSHLU,
|
||||
"vqshrn", // ARM_INS_VQSHRN,
|
||||
"vqshrun", // ARM_INS_VQSHRUN,
|
||||
"vqsub", // ARM_INS_VQSUB,
|
||||
"vraddhn", // ARM_INS_VRADDHN,
|
||||
"vrecpe", // ARM_INS_VRECPE,
|
||||
"vrecps", // ARM_INS_VRECPS,
|
||||
"vrev16", // ARM_INS_VREV16,
|
||||
"vrev32", // ARM_INS_VREV32,
|
||||
"vrev64", // ARM_INS_VREV64,
|
||||
"vrhadd", // ARM_INS_VRHADD,
|
||||
"vrinta", // ARM_INS_VRINTA,
|
||||
"vrintm", // ARM_INS_VRINTM,
|
||||
"vrintn", // ARM_INS_VRINTN,
|
||||
"vrintp", // ARM_INS_VRINTP,
|
||||
"vrintr", // ARM_INS_VRINTR,
|
||||
"vrintx", // ARM_INS_VRINTX,
|
||||
"vrintz", // ARM_INS_VRINTZ,
|
||||
"vrshl", // ARM_INS_VRSHL,
|
||||
"vrshr", // ARM_INS_VRSHR,
|
||||
"vrshrn", // ARM_INS_VRSHRN,
|
||||
"vrsqrte", // ARM_INS_VRSQRTE,
|
||||
"vrsqrts", // ARM_INS_VRSQRTS,
|
||||
"vrsra", // ARM_INS_VRSRA,
|
||||
"vrsubhn", // ARM_INS_VRSUBHN,
|
||||
"vsdot", // ARM_INS_VSDOT,
|
||||
"vseleq", // ARM_INS_VSELEQ,
|
||||
"vselge", // ARM_INS_VSELGE,
|
||||
"vselgt", // ARM_INS_VSELGT,
|
||||
"vselvs", // ARM_INS_VSELVS,
|
||||
"vshl", // ARM_INS_VSHL,
|
||||
"vshll", // ARM_INS_VSHLL,
|
||||
"vshr", // ARM_INS_VSHR,
|
||||
"vshrn", // ARM_INS_VSHRN,
|
||||
"vsli", // ARM_INS_VSLI,
|
||||
"vsqrt", // ARM_INS_VSQRT,
|
||||
"vsra", // ARM_INS_VSRA,
|
||||
"vsri", // ARM_INS_VSRI,
|
||||
"vst1", // ARM_INS_VST1,
|
||||
"vst2", // ARM_INS_VST2,
|
||||
"vst3", // ARM_INS_VST3,
|
||||
"vst4", // ARM_INS_VST4,
|
||||
"vstmdb", // ARM_INS_VSTMDB,
|
||||
"vstmia", // ARM_INS_VSTMIA,
|
||||
"vstr", // ARM_INS_VSTR,
|
||||
"vsub", // ARM_INS_VSUB,
|
||||
"vsubhn", // ARM_INS_VSUBHN,
|
||||
"vsubl", // ARM_INS_VSUBL,
|
||||
"vsubw", // ARM_INS_VSUBW,
|
||||
"vswp", // ARM_INS_VSWP,
|
||||
"vtbl", // ARM_INS_VTBL,
|
||||
"vtbx", // ARM_INS_VTBX,
|
||||
"vtrn", // ARM_INS_VTRN,
|
||||
"vtst", // ARM_INS_VTST,
|
||||
"vudot", // ARM_INS_VUDOT,
|
||||
"vuzp", // ARM_INS_VUZP,
|
||||
"vzip", // ARM_INS_VZIP,
|
||||
"wfe", // ARM_INS_WFE,
|
||||
"wfi", // ARM_INS_WFI,
|
||||
"yield", // ARM_INS_YIELD,
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,63 @@
|
||||
/* Capstone Disassembly Engine */
|
||||
/* By Dang Hoang Vu <danghvu@gmail.com> 2013 */
|
||||
|
||||
#ifdef CAPSTONE_HAS_ARM
|
||||
|
||||
#include "../../cs_priv.h"
|
||||
#include "../../MCRegisterInfo.h"
|
||||
#include "ARMDisassembler.h"
|
||||
#include "ARMInstPrinter.h"
|
||||
#include "ARMMapping.h"
|
||||
#include "ARMModule.h"
|
||||
|
||||
cs_err ARM_global_init(cs_struct *ud)
|
||||
{
|
||||
MCRegisterInfo *mri;
|
||||
mri = cs_mem_malloc(sizeof(*mri));
|
||||
|
||||
ARM_init(mri);
|
||||
ARM_getRegName(ud, 0); // use default get_regname
|
||||
|
||||
ud->printer = ARM_printInst;
|
||||
ud->printer_info = mri;
|
||||
ud->reg_name = ARM_reg_name;
|
||||
ud->insn_id = ARM_get_insn_id;
|
||||
ud->insn_name = ARM_insn_name;
|
||||
ud->group_name = ARM_group_name;
|
||||
ud->post_printer = ARM_post_printer;
|
||||
#ifndef CAPSTONE_DIET
|
||||
ud->reg_access = ARM_reg_access;
|
||||
#endif
|
||||
|
||||
if (ud->mode & CS_MODE_THUMB)
|
||||
ud->disasm = Thumb_getInstruction;
|
||||
else
|
||||
ud->disasm = ARM_getInstruction;
|
||||
|
||||
return CS_ERR_OK;
|
||||
}
|
||||
|
||||
cs_err ARM_option(cs_struct *handle, cs_opt_type type, size_t value)
|
||||
{
|
||||
switch(type) {
|
||||
case CS_OPT_MODE:
|
||||
if (value & CS_MODE_THUMB)
|
||||
handle->disasm = Thumb_getInstruction;
|
||||
else
|
||||
handle->disasm = ARM_getInstruction;
|
||||
|
||||
handle->mode = (cs_mode)value;
|
||||
|
||||
break;
|
||||
case CS_OPT_SYNTAX:
|
||||
ARM_getRegName(handle, (int)value);
|
||||
handle->syntax = (int)value;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return CS_ERR_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -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
|
||||
@@ -0,0 +1,88 @@
|
||||
/* Capstone Disassembly Engine */
|
||||
/* BPF Backend by david942j <david942j@gmail.com>, 2019 */
|
||||
|
||||
/* This file defines constants and macros used for parsing a BPF instruction */
|
||||
|
||||
#ifndef CS_BPF_CONSTANTS_H
|
||||
#define CS_BPF_CONSTANTS_H
|
||||
|
||||
#define BPF_CLASS(code) ((code) & 0x7)
|
||||
|
||||
///< Instruction classes
|
||||
#define BPF_CLASS_LD 0x00
|
||||
#define BPF_CLASS_LDX 0x01
|
||||
#define BPF_CLASS_ST 0x02
|
||||
#define BPF_CLASS_STX 0x03
|
||||
#define BPF_CLASS_ALU 0x04
|
||||
#define BPF_CLASS_JMP 0x05
|
||||
#define BPF_CLASS_RET 0x06 ///< cBPF only
|
||||
#define BPF_CLASS_MISC 0x07 ///< cBPF only
|
||||
#define BPF_CLASS_ALU64 0x07 ///< eBPF only
|
||||
|
||||
#define BPF_OP(code) ((code) & 0xf0)
|
||||
|
||||
///< Types of ALU instruction
|
||||
#define BPF_ALU_ADD 0x00
|
||||
#define BPF_ALU_SUB 0x10
|
||||
#define BPF_ALU_MUL 0x20
|
||||
#define BPF_ALU_DIV 0x30
|
||||
#define BPF_ALU_OR 0x40
|
||||
#define BPF_ALU_AND 0x50
|
||||
#define BPF_ALU_LSH 0x60
|
||||
#define BPF_ALU_RSH 0x70
|
||||
#define BPF_ALU_NEG 0x80
|
||||
#define BPF_ALU_MOD 0x90
|
||||
#define BPF_ALU_XOR 0xa0
|
||||
#define BPF_ALU_MOV 0xb0 ///< eBPF only: mov reg to reg
|
||||
#define BPF_ALU_ARSH 0xc0 ///< eBPF only: sign extending shift right
|
||||
#define BPF_ALU_END 0xd0 ///< eBPF only: endianness conversion
|
||||
|
||||
///< Types of jmp instruction
|
||||
#define BPF_JUMP_JA 0x00 ///< goto
|
||||
#define BPF_JUMP_JEQ 0x10 ///< '=='
|
||||
#define BPF_JUMP_JGT 0x20 ///< unsigned '>'
|
||||
#define BPF_JUMP_JGE 0x30 ///< unsigned '>='
|
||||
#define BPF_JUMP_JSET 0x40 ///< '&'
|
||||
#define BPF_JUMP_JNE 0x50 ///< eBPF only: '!=' */
|
||||
#define BPF_JUMP_JSGT 0x60 ///< eBPF only: signed '>'
|
||||
#define BPF_JUMP_JSGE 0x70 ///< eBPF only: signed '>='
|
||||
#define BPF_JUMP_CALL 0x80 ///< eBPF only: function call
|
||||
#define BPF_JUMP_EXIT 0x90 ///< eBPF only: exit
|
||||
#define BPF_JUMP_JLT 0xa0 ///< eBPF only: unsigned '<'
|
||||
#define BPF_JUMP_JLE 0xb0 ///< eBPF only: unsigned '<='
|
||||
#define BPF_JUMP_JSLT 0xc0 ///< eBPF only: signed '<'
|
||||
#define BPF_JUMP_JSLE 0xd0 ///< eBPF only: signed '<='
|
||||
|
||||
#define BPF_SRC(code) ((code) & 0x08)
|
||||
#define BPF_RVAL(code) ((code) & 0x18) /* cBPF only: for return types */
|
||||
///< Source operand
|
||||
#define BPF_SRC_K 0x00
|
||||
#define BPF_SRC_X 0x08
|
||||
#define BPF_SRC_A 0x10 /* cBPF only */
|
||||
|
||||
#define BPF_SRC_LITTLE BPF_SRC_K
|
||||
#define BPF_SRC_BIG BPF_SRC_X
|
||||
|
||||
#define BPF_SIZE(code) ((code) & 0x18)
|
||||
///< Size modifier
|
||||
#define BPF_SIZE_W 0x00 ///< word
|
||||
#define BPF_SIZE_H 0x08 ///< half word
|
||||
#define BPF_SIZE_B 0x10 ///< byte
|
||||
#define BPF_SIZE_DW 0x18 ///< eBPF only: double word
|
||||
|
||||
#define BPF_MODE(code) ((code) & 0xe0)
|
||||
///< Mode modifier
|
||||
#define BPF_MODE_IMM 0x00 ///< used for 32-bit mov in cBPF and 64-bit in eBPF
|
||||
#define BPF_MODE_ABS 0x20
|
||||
#define BPF_MODE_IND 0x40
|
||||
#define BPF_MODE_MEM 0x60
|
||||
#define BPF_MODE_LEN 0x80 ///< cBPF only, reserved in eBPF
|
||||
#define BPF_MODE_MSH 0xa0 ///< cBPF only, reserved in eBPF
|
||||
#define BPF_MODE_XADD 0xc0 ///< eBPF only: exclusive add
|
||||
|
||||
#define BPF_MISCOP(code) ((code) & 0x80)
|
||||
///< Operation of misc
|
||||
#define BPF_MISCOP_TAX 0x00
|
||||
#define BPF_MISCOP_TXA 0x80
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,464 @@
|
||||
/* Capstone Disassembly Engine */
|
||||
/* BPF Backend by david942j <david942j@gmail.com>, 2019 */
|
||||
|
||||
#ifdef CAPSTONE_HAS_BPF
|
||||
|
||||
#include <string.h>
|
||||
#include <stddef.h> // offsetof macro
|
||||
|
||||
#include "BPFConstants.h"
|
||||
#include "BPFDisassembler.h"
|
||||
#include "BPFMapping.h"
|
||||
#include "../../cs_priv.h"
|
||||
|
||||
static uint16_t read_u16(cs_struct *ud, const uint8_t *code)
|
||||
{
|
||||
if (MODE_IS_BIG_ENDIAN(ud->mode))
|
||||
return (((uint16_t)code[0] << 8) | code[1]);
|
||||
else
|
||||
return (((uint16_t)code[1] << 8) | code[0]);
|
||||
}
|
||||
|
||||
static uint32_t read_u32(cs_struct *ud, const uint8_t *code)
|
||||
{
|
||||
if (MODE_IS_BIG_ENDIAN(ud->mode))
|
||||
return ((uint32_t)read_u16(ud, code) << 16) | read_u16(ud, code + 2);
|
||||
else
|
||||
return ((uint32_t)read_u16(ud, code + 2) << 16) | read_u16(ud, code);
|
||||
}
|
||||
|
||||
///< Malloc bpf_internal, also checks if code_len is large enough.
|
||||
static bpf_internal *alloc_bpf_internal(size_t code_len)
|
||||
{
|
||||
bpf_internal *bpf;
|
||||
|
||||
if (code_len < 8)
|
||||
return NULL;
|
||||
bpf = cs_mem_malloc(sizeof(bpf_internal));
|
||||
if (bpf == NULL)
|
||||
return NULL;
|
||||
/* default value */
|
||||
bpf->insn_size = 8;
|
||||
return bpf;
|
||||
}
|
||||
|
||||
///< Fetch a cBPF structure from code
|
||||
static bpf_internal* fetch_cbpf(cs_struct *ud, const uint8_t *code,
|
||||
size_t code_len)
|
||||
{
|
||||
bpf_internal *bpf;
|
||||
|
||||
bpf = alloc_bpf_internal(code_len);
|
||||
if (bpf == NULL)
|
||||
return NULL;
|
||||
|
||||
bpf->op = read_u16(ud, code);
|
||||
bpf->jt = code[2];
|
||||
bpf->jf = code[3];
|
||||
bpf->k = read_u32(ud, code + 4);
|
||||
return bpf;
|
||||
}
|
||||
|
||||
///< Fetch an eBPF structure from code
|
||||
static bpf_internal* fetch_ebpf(cs_struct *ud, const uint8_t *code,
|
||||
size_t code_len)
|
||||
{
|
||||
bpf_internal *bpf;
|
||||
|
||||
bpf = alloc_bpf_internal(code_len);
|
||||
if (bpf == NULL)
|
||||
return NULL;
|
||||
|
||||
bpf->op = (uint16_t)code[0];
|
||||
bpf->dst = code[1] & 0xf;
|
||||
bpf->src = (code[1] & 0xf0) >> 4;
|
||||
|
||||
// eBPF has one 16-byte instruction: BPF_LD | BPF_DW | BPF_IMM,
|
||||
// in this case imm is combined with the next block's imm.
|
||||
if (bpf->op == (BPF_CLASS_LD | BPF_SIZE_DW | BPF_MODE_IMM)) {
|
||||
if (code_len < 16) {
|
||||
cs_mem_free(bpf);
|
||||
return NULL;
|
||||
}
|
||||
bpf->k = read_u32(ud, code + 4) | (((uint64_t)read_u32(ud, code + 12)) << 32);
|
||||
bpf->insn_size = 16;
|
||||
}
|
||||
else {
|
||||
bpf->offset = read_u16(ud, code + 2);
|
||||
bpf->k = read_u32(ud, code + 4);
|
||||
}
|
||||
return bpf;
|
||||
}
|
||||
|
||||
#define CHECK_READABLE_REG(ud, reg) do { \
|
||||
if (! ((reg) >= BPF_REG_R0 && (reg) <= BPF_REG_R10)) \
|
||||
return false; \
|
||||
} while (0)
|
||||
|
||||
#define CHECK_WRITABLE_REG(ud, reg) do { \
|
||||
if (! ((reg) >= BPF_REG_R0 && (reg) < BPF_REG_R10)) \
|
||||
return false; \
|
||||
} while (0)
|
||||
|
||||
#define CHECK_READABLE_AND_PUSH(ud, MI, r) do { \
|
||||
CHECK_READABLE_REG(ud, r + BPF_REG_R0); \
|
||||
MCOperand_CreateReg0(MI, r + BPF_REG_R0); \
|
||||
} while (0)
|
||||
|
||||
#define CHECK_WRITABLE_AND_PUSH(ud, MI, r) do { \
|
||||
CHECK_WRITABLE_REG(ud, r + BPF_REG_R0); \
|
||||
MCOperand_CreateReg0(MI, r + BPF_REG_R0); \
|
||||
} while (0)
|
||||
|
||||
static bool decodeLoad(cs_struct *ud, MCInst *MI, bpf_internal *bpf)
|
||||
{
|
||||
if (!EBPF_MODE(ud)) {
|
||||
/*
|
||||
* +-----+-----------+--------------------+
|
||||
* | ldb | [k] | [x+k] |
|
||||
* | ldh | [k] | [x+k] |
|
||||
* +-----+-----------+--------------------+
|
||||
*/
|
||||
if (BPF_SIZE(bpf->op) == BPF_SIZE_DW)
|
||||
return false;
|
||||
if (BPF_SIZE(bpf->op) == BPF_SIZE_B || BPF_SIZE(bpf->op) == BPF_SIZE_H) {
|
||||
/* no ldx */
|
||||
if (BPF_CLASS(bpf->op) != BPF_CLASS_LD)
|
||||
return false;
|
||||
/* can only be BPF_ABS and BPF_IND */
|
||||
if (BPF_MODE(bpf->op) == BPF_MODE_ABS) {
|
||||
MCOperand_CreateImm0(MI, bpf->k);
|
||||
return true;
|
||||
}
|
||||
else if (BPF_MODE(bpf->op) == BPF_MODE_IND) {
|
||||
MCOperand_CreateReg0(MI, BPF_REG_X);
|
||||
MCOperand_CreateImm0(MI, bpf->k);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/*
|
||||
* +-----+----+------+------+-----+-------+
|
||||
* | ld | #k | #len | M[k] | [k] | [x+k] |
|
||||
* +-----+----+------+------+-----+-------+
|
||||
* | ldx | #k | #len | M[k] | 4*([k]&0xf) |
|
||||
* +-----+----+------+------+-------------+
|
||||
*/
|
||||
switch (BPF_MODE(bpf->op)) {
|
||||
default:
|
||||
break;
|
||||
case BPF_MODE_IMM:
|
||||
MCOperand_CreateImm0(MI, bpf->k);
|
||||
return true;
|
||||
case BPF_MODE_LEN:
|
||||
return true;
|
||||
case BPF_MODE_MEM:
|
||||
MCOperand_CreateImm0(MI, bpf->k);
|
||||
return true;
|
||||
}
|
||||
if (BPF_CLASS(bpf->op) == BPF_CLASS_LD) {
|
||||
if (BPF_MODE(bpf->op) == BPF_MODE_ABS) {
|
||||
MCOperand_CreateImm0(MI, bpf->k);
|
||||
return true;
|
||||
}
|
||||
else if (BPF_MODE(bpf->op) == BPF_MODE_IND) {
|
||||
MCOperand_CreateReg0(MI, BPF_REG_X);
|
||||
MCOperand_CreateImm0(MI, bpf->k);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else { /* LDX */
|
||||
if (BPF_MODE(bpf->op) == BPF_MODE_MSH) {
|
||||
MCOperand_CreateImm0(MI, bpf->k);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* eBPF mode */
|
||||
/*
|
||||
* - IMM: lddw dst, imm64
|
||||
* - ABS: ld{w,h,b,dw} [k]
|
||||
* - IND: ld{w,h,b,dw} [src+k]
|
||||
* - MEM: ldx{w,h,b,dw} dst, [src+off]
|
||||
*/
|
||||
if (BPF_CLASS(bpf->op) == BPF_CLASS_LD) {
|
||||
switch (BPF_MODE(bpf->op)) {
|
||||
case BPF_MODE_IMM:
|
||||
if (bpf->op != (BPF_CLASS_LD | BPF_SIZE_DW | BPF_MODE_IMM))
|
||||
return false;
|
||||
CHECK_WRITABLE_AND_PUSH(ud, MI, bpf->dst);
|
||||
MCOperand_CreateImm0(MI, bpf->k);
|
||||
return true;
|
||||
case BPF_MODE_ABS:
|
||||
MCOperand_CreateImm0(MI, bpf->k);
|
||||
return true;
|
||||
case BPF_MODE_IND:
|
||||
CHECK_READABLE_AND_PUSH(ud, MI, bpf->src);
|
||||
MCOperand_CreateImm0(MI, bpf->k);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
/* LDX */
|
||||
if (BPF_MODE(bpf->op) == BPF_MODE_MEM) {
|
||||
CHECK_WRITABLE_AND_PUSH(ud, MI, bpf->dst);
|
||||
CHECK_READABLE_AND_PUSH(ud, MI, bpf->src);
|
||||
MCOperand_CreateImm0(MI, bpf->offset);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool decodeStore(cs_struct *ud, MCInst *MI, bpf_internal *bpf)
|
||||
{
|
||||
/* in cBPF, only BPF_ST* | BPF_MEM | BPF_W is valid
|
||||
* while in eBPF:
|
||||
* - BPF_STX | BPF_XADD | BPF_{W,DW}
|
||||
* - BPF_ST* | BPF_MEM | BPF_{W,H,B,DW}
|
||||
* are valid
|
||||
*/
|
||||
if (!EBPF_MODE(ud)) {
|
||||
/* can only store to M[] */
|
||||
if (bpf->op != (BPF_CLASS(bpf->op) | BPF_MODE_MEM | BPF_SIZE_W))
|
||||
return false;
|
||||
MCOperand_CreateImm0(MI, bpf->k);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* eBPF */
|
||||
|
||||
if (BPF_MODE(bpf->op) == BPF_MODE_XADD) {
|
||||
if (BPF_CLASS(bpf->op) != BPF_CLASS_STX)
|
||||
return false;
|
||||
if (BPF_SIZE(bpf->op) != BPF_SIZE_W && BPF_SIZE(bpf->op) != BPF_SIZE_DW)
|
||||
return false;
|
||||
/* xadd [dst + off], src */
|
||||
CHECK_READABLE_AND_PUSH(ud, MI, bpf->dst);
|
||||
MCOperand_CreateImm0(MI, bpf->offset);
|
||||
CHECK_READABLE_AND_PUSH(ud, MI, bpf->src);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (BPF_MODE(bpf->op) != BPF_MODE_MEM)
|
||||
return false;
|
||||
|
||||
/* st [dst + off], src */
|
||||
CHECK_READABLE_AND_PUSH(ud, MI, bpf->dst);
|
||||
MCOperand_CreateImm0(MI, bpf->offset);
|
||||
if (BPF_CLASS(bpf->op) == BPF_CLASS_ST)
|
||||
MCOperand_CreateImm0(MI, bpf->k);
|
||||
else
|
||||
CHECK_READABLE_AND_PUSH(ud, MI, bpf->src);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool decodeALU(cs_struct *ud, MCInst *MI, bpf_internal *bpf)
|
||||
{
|
||||
/* Set MI->Operands */
|
||||
|
||||
/* cBPF */
|
||||
if (!EBPF_MODE(ud)) {
|
||||
if (BPF_OP(bpf->op) > BPF_ALU_XOR)
|
||||
return false;
|
||||
/* cBPF's NEG has no operands */
|
||||
if (BPF_OP(bpf->op) == BPF_ALU_NEG)
|
||||
return true;
|
||||
if (BPF_SRC(bpf->op) == BPF_SRC_K)
|
||||
MCOperand_CreateImm0(MI, bpf->k);
|
||||
else /* BPF_SRC_X */
|
||||
MCOperand_CreateReg0(MI, BPF_REG_X);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* eBPF */
|
||||
|
||||
if (BPF_OP(bpf->op) > BPF_ALU_END)
|
||||
return false;
|
||||
/* ALU64 class doesn't have ENDian */
|
||||
/* ENDian's imm must be one of 16, 32, 64 */
|
||||
if (BPF_OP(bpf->op) == BPF_ALU_END) {
|
||||
if (BPF_CLASS(bpf->op) == BPF_CLASS_ALU64)
|
||||
return false;
|
||||
if (bpf->k != 16 && bpf->k != 32 && bpf->k != 64)
|
||||
return false;
|
||||
}
|
||||
|
||||
/* - op dst, imm
|
||||
* - op dst, src
|
||||
* - neg dst
|
||||
* - le<imm> dst
|
||||
*/
|
||||
/* every ALU instructions have dst op */
|
||||
CHECK_WRITABLE_AND_PUSH(ud, MI, bpf->dst);
|
||||
|
||||
/* special cases */
|
||||
if (BPF_OP(bpf->op) == BPF_ALU_NEG)
|
||||
return true;
|
||||
if (BPF_OP(bpf->op) == BPF_ALU_END) {
|
||||
/* bpf->k must be one of 16, 32, 64 */
|
||||
MCInst_setOpcode(MI, MCInst_getOpcode(MI) | ((uint32_t)bpf->k << 4));
|
||||
return true;
|
||||
}
|
||||
|
||||
/* normal cases */
|
||||
if (BPF_SRC(bpf->op) == BPF_SRC_K) {
|
||||
MCOperand_CreateImm0(MI, bpf->k);
|
||||
}
|
||||
else { /* BPF_SRC_X */
|
||||
CHECK_READABLE_AND_PUSH(ud, MI, bpf->src);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool decodeJump(cs_struct *ud, MCInst *MI, bpf_internal *bpf)
|
||||
{
|
||||
/* cBPF and eBPF are very different in class jump */
|
||||
if (!EBPF_MODE(ud)) {
|
||||
if (BPF_OP(bpf->op) > BPF_JUMP_JSET)
|
||||
return false;
|
||||
|
||||
/* ja is a special case of jumps */
|
||||
if (BPF_OP(bpf->op) == BPF_JUMP_JA) {
|
||||
MCOperand_CreateImm0(MI, bpf->k);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (BPF_SRC(bpf->op) == BPF_SRC_K)
|
||||
MCOperand_CreateImm0(MI, bpf->k);
|
||||
else /* BPF_SRC_X */
|
||||
MCOperand_CreateReg0(MI, BPF_REG_X);
|
||||
MCOperand_CreateImm0(MI, bpf->jt);
|
||||
MCOperand_CreateImm0(MI, bpf->jf);
|
||||
}
|
||||
else {
|
||||
if (BPF_OP(bpf->op) > BPF_JUMP_JSLE)
|
||||
return false;
|
||||
|
||||
/* No operands for exit */
|
||||
if (BPF_OP(bpf->op) == BPF_JUMP_EXIT)
|
||||
return bpf->op == (BPF_CLASS_JMP | BPF_JUMP_EXIT);
|
||||
if (BPF_OP(bpf->op) == BPF_JUMP_CALL) {
|
||||
if (bpf->op == (BPF_CLASS_JMP | BPF_JUMP_CALL)) {
|
||||
MCOperand_CreateImm0(MI, bpf->k);
|
||||
return true;
|
||||
}
|
||||
if (bpf->op == (BPF_CLASS_JMP | BPF_JUMP_CALL | BPF_SRC_X)) {
|
||||
CHECK_READABLE_AND_PUSH(ud, MI, bpf->k);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* ja is a special case of jumps */
|
||||
if (BPF_OP(bpf->op) == BPF_JUMP_JA) {
|
||||
if (BPF_SRC(bpf->op) != BPF_SRC_K)
|
||||
return false;
|
||||
MCOperand_CreateImm0(MI, bpf->offset);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* <j> dst, src, +off */
|
||||
CHECK_READABLE_AND_PUSH(ud, MI, bpf->dst);
|
||||
if (BPF_SRC(bpf->op) == BPF_SRC_K)
|
||||
MCOperand_CreateImm0(MI, bpf->k);
|
||||
else
|
||||
CHECK_READABLE_AND_PUSH(ud, MI, bpf->src);
|
||||
MCOperand_CreateImm0(MI, bpf->offset);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool decodeReturn(cs_struct *ud, MCInst *MI, bpf_internal *bpf)
|
||||
{
|
||||
/* Here only handles the BPF_RET class in cBPF */
|
||||
switch (BPF_RVAL(bpf->op)) {
|
||||
case BPF_SRC_K:
|
||||
MCOperand_CreateImm0(MI, bpf->k);
|
||||
return true;
|
||||
case BPF_SRC_X:
|
||||
MCOperand_CreateReg0(MI, BPF_REG_X);
|
||||
return true;
|
||||
case BPF_SRC_A:
|
||||
MCOperand_CreateReg0(MI, BPF_REG_A);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool decodeMISC(cs_struct *ud, MCInst *MI, bpf_internal *bpf)
|
||||
{
|
||||
uint16_t op = bpf->op ^ BPF_CLASS_MISC;
|
||||
return op == BPF_MISCOP_TAX || op == BPF_MISCOP_TXA;
|
||||
}
|
||||
|
||||
///< 1. Check if the instruction is valid
|
||||
///< 2. Set MI->opcode
|
||||
///< 3. Set MI->Operands
|
||||
static bool getInstruction(cs_struct *ud, MCInst *MI, bpf_internal *bpf)
|
||||
{
|
||||
cs_detail *detail;
|
||||
|
||||
detail = MI->flat_insn->detail;
|
||||
// initialize detail
|
||||
if (detail) {
|
||||
memset(detail, 0, offsetof(cs_detail, bpf) + sizeof(cs_bpf));
|
||||
}
|
||||
|
||||
MCInst_clear(MI);
|
||||
MCInst_setOpcode(MI, bpf->op);
|
||||
|
||||
switch (BPF_CLASS(bpf->op)) {
|
||||
default: /* should never happen */
|
||||
return false;
|
||||
case BPF_CLASS_LD:
|
||||
case BPF_CLASS_LDX:
|
||||
return decodeLoad(ud, MI, bpf);
|
||||
case BPF_CLASS_ST:
|
||||
case BPF_CLASS_STX:
|
||||
return decodeStore(ud, MI, bpf);
|
||||
case BPF_CLASS_ALU:
|
||||
return decodeALU(ud, MI, bpf);
|
||||
case BPF_CLASS_JMP:
|
||||
return decodeJump(ud, MI, bpf);
|
||||
case BPF_CLASS_RET:
|
||||
/* eBPF doesn't have this class */
|
||||
if (EBPF_MODE(ud))
|
||||
return false;
|
||||
return decodeReturn(ud, MI, bpf);
|
||||
case BPF_CLASS_MISC:
|
||||
/* case BPF_CLASS_ALU64: */
|
||||
if (EBPF_MODE(ud))
|
||||
return decodeALU(ud, MI, bpf);
|
||||
else
|
||||
return decodeMISC(ud, MI, bpf);
|
||||
}
|
||||
}
|
||||
|
||||
bool BPF_getInstruction(csh ud, const uint8_t *code, size_t code_len,
|
||||
MCInst *instr, uint16_t *size, uint64_t address, void *info)
|
||||
{
|
||||
cs_struct *cs;
|
||||
bpf_internal *bpf;
|
||||
|
||||
cs = (cs_struct*)ud;
|
||||
if (EBPF_MODE(cs))
|
||||
bpf = fetch_ebpf(cs, code, code_len);
|
||||
else
|
||||
bpf = fetch_cbpf(cs, code, code_len);
|
||||
if (bpf == NULL)
|
||||
return false;
|
||||
if (!getInstruction(cs, instr, bpf)) {
|
||||
cs_mem_free(bpf);
|
||||
return false;
|
||||
}
|
||||
|
||||
*size = bpf->insn_size;
|
||||
cs_mem_free(bpf);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,27 @@
|
||||
/* Capstone Disassembly Engine */
|
||||
/* BPF Backend by david942j <david942j@gmail.com>, 2019 */
|
||||
|
||||
#ifndef CS_BPF_DISASSEMBLER_H
|
||||
#define CS_BPF_DISASSEMBLER_H
|
||||
|
||||
#include "../../MCInst.h"
|
||||
|
||||
typedef struct bpf_internal {
|
||||
uint16_t op;
|
||||
uint64_t k;
|
||||
/* for cBPF */
|
||||
uint8_t jt;
|
||||
uint8_t jf;
|
||||
/* for eBPF */
|
||||
uint8_t dst;
|
||||
uint8_t src;
|
||||
uint16_t offset;
|
||||
|
||||
/* length of this bpf instruction */
|
||||
uint8_t insn_size;
|
||||
} bpf_internal;
|
||||
|
||||
bool BPF_getInstruction(csh ud, const uint8_t *code, size_t code_len,
|
||||
MCInst *instr, uint16_t *size, uint64_t address, void *info);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,285 @@
|
||||
/* Capstone Disassembly Engine */
|
||||
/* BPF Backend by david942j <david942j@gmail.com>, 2019 */
|
||||
|
||||
#include <capstone/platform.h>
|
||||
|
||||
#include "BPFConstants.h"
|
||||
#include "BPFInstPrinter.h"
|
||||
#include "BPFMapping.h"
|
||||
|
||||
static cs_bpf_op *expand_bpf_operands(cs_bpf *bpf)
|
||||
{
|
||||
/* assert(bpf->op_count < 3); */
|
||||
return &bpf->operands[bpf->op_count++];
|
||||
}
|
||||
|
||||
static void push_op_reg(cs_bpf *bpf, bpf_op_type val, uint8_t ac_mode)
|
||||
{
|
||||
cs_bpf_op *op = expand_bpf_operands(bpf);
|
||||
|
||||
op->type = BPF_OP_REG;
|
||||
op->reg = val;
|
||||
op->access = ac_mode;
|
||||
}
|
||||
|
||||
static void push_op_imm(cs_bpf *bpf, uint64_t val)
|
||||
{
|
||||
cs_bpf_op *op = expand_bpf_operands(bpf);
|
||||
|
||||
op->type = BPF_OP_IMM;
|
||||
op->imm = val;
|
||||
}
|
||||
|
||||
static void push_op_off(cs_bpf *bpf, uint32_t val)
|
||||
{
|
||||
cs_bpf_op *op = expand_bpf_operands(bpf);
|
||||
|
||||
op->type = BPF_OP_OFF;
|
||||
op->off = val;
|
||||
}
|
||||
|
||||
static void push_op_mem(cs_bpf *bpf, bpf_reg reg, uint32_t val)
|
||||
{
|
||||
cs_bpf_op *op = expand_bpf_operands(bpf);
|
||||
|
||||
op->type = BPF_OP_MEM;
|
||||
op->mem.base = reg;
|
||||
op->mem.disp = val;
|
||||
}
|
||||
|
||||
static void push_op_mmem(cs_bpf *bpf, uint32_t val)
|
||||
{
|
||||
cs_bpf_op *op = expand_bpf_operands(bpf);
|
||||
|
||||
op->type = BPF_OP_MMEM;
|
||||
op->mmem = val;
|
||||
}
|
||||
|
||||
static void push_op_msh(cs_bpf *bpf, uint32_t val)
|
||||
{
|
||||
cs_bpf_op *op = expand_bpf_operands(bpf);
|
||||
|
||||
op->type = BPF_OP_MSH;
|
||||
op->msh = val;
|
||||
}
|
||||
|
||||
static void push_op_ext(cs_bpf *bpf, bpf_ext_type val)
|
||||
{
|
||||
cs_bpf_op *op = expand_bpf_operands(bpf);
|
||||
|
||||
op->type = BPF_OP_EXT;
|
||||
op->ext = val;
|
||||
}
|
||||
|
||||
static void convert_operands(MCInst *MI, cs_bpf *bpf)
|
||||
{
|
||||
unsigned opcode = MCInst_getOpcode(MI);
|
||||
unsigned mc_op_count = MCInst_getNumOperands(MI);
|
||||
MCOperand *op;
|
||||
MCOperand *op2;
|
||||
unsigned i;
|
||||
|
||||
bpf->op_count = 0;
|
||||
if (BPF_CLASS(opcode) == BPF_CLASS_LD || BPF_CLASS(opcode) == BPF_CLASS_LDX) {
|
||||
switch (BPF_MODE(opcode)) {
|
||||
case BPF_MODE_IMM:
|
||||
if (EBPF_MODE(MI->csh)) {
|
||||
push_op_reg(bpf, MCOperand_getReg(MCInst_getOperand(MI, 0)), CS_AC_WRITE);
|
||||
push_op_imm(bpf, MCOperand_getImm(MCInst_getOperand(MI, 1)));
|
||||
} else {
|
||||
push_op_imm(bpf, MCOperand_getImm(MCInst_getOperand(MI, 0)));
|
||||
}
|
||||
break;
|
||||
case BPF_MODE_ABS:
|
||||
op = MCInst_getOperand(MI, 0);
|
||||
push_op_mem(bpf, BPF_REG_INVALID, (uint32_t)MCOperand_getImm(op));
|
||||
break;
|
||||
case BPF_MODE_IND:
|
||||
op = MCInst_getOperand(MI, 0);
|
||||
op2 = MCInst_getOperand(MI, 1);
|
||||
push_op_mem(bpf, MCOperand_getReg(op), (uint32_t)MCOperand_getImm(op2));
|
||||
break;
|
||||
case BPF_MODE_MEM:
|
||||
if (EBPF_MODE(MI->csh)) {
|
||||
/* ldx{w,h,b,dw} dst, [src+off] */
|
||||
push_op_reg(bpf, MCOperand_getReg(MCInst_getOperand(MI, 0)), CS_AC_WRITE);
|
||||
op = MCInst_getOperand(MI, 1);
|
||||
op2 = MCInst_getOperand(MI, 2);
|
||||
push_op_mem(bpf, MCOperand_getReg(op), (uint32_t)MCOperand_getImm(op2));
|
||||
}
|
||||
else {
|
||||
push_op_mmem(bpf, (uint32_t)MCOperand_getImm(MCInst_getOperand(MI, 0)));
|
||||
}
|
||||
break;
|
||||
case BPF_MODE_LEN:
|
||||
push_op_ext(bpf, BPF_EXT_LEN);
|
||||
break;
|
||||
case BPF_MODE_MSH:
|
||||
op = MCInst_getOperand(MI, 0);
|
||||
push_op_msh(bpf, (uint32_t)MCOperand_getImm(op));
|
||||
break;
|
||||
/* case BPF_MODE_XADD: // not exists */
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (BPF_CLASS(opcode) == BPF_CLASS_ST || BPF_CLASS(opcode) == BPF_CLASS_STX) {
|
||||
if (!EBPF_MODE(MI->csh)) {
|
||||
// cBPF has only one case - st* M[k]
|
||||
push_op_mmem(bpf, (uint32_t)MCOperand_getImm(MCInst_getOperand(MI, 0)));
|
||||
return;
|
||||
}
|
||||
/* eBPF has two cases:
|
||||
* - st [dst + off], src
|
||||
* - xadd [dst + off], src
|
||||
* they have same form of operands.
|
||||
*/
|
||||
op = MCInst_getOperand(MI, 0);
|
||||
op2 = MCInst_getOperand(MI, 1);
|
||||
push_op_mem(bpf, MCOperand_getReg(op), (uint32_t)MCOperand_getImm(op2));
|
||||
op = MCInst_getOperand(MI, 2);
|
||||
if (MCOperand_isImm(op))
|
||||
push_op_imm(bpf, MCOperand_getImm(op));
|
||||
else if (MCOperand_isReg(op))
|
||||
push_op_reg(bpf, MCOperand_getReg(op), CS_AC_READ);
|
||||
return;
|
||||
}
|
||||
|
||||
if (BPF_CLASS(opcode) == BPF_CLASS_JMP) {
|
||||
for (i = 0; i < mc_op_count; i++) {
|
||||
op = MCInst_getOperand(MI, i);
|
||||
if (MCOperand_isImm(op)) {
|
||||
/* decide the imm is BPF_OP_IMM or BPF_OP_OFF type here */
|
||||
/*
|
||||
* 1. ja +off
|
||||
* 2. j {x,k}, +jt, +jf // cBPF
|
||||
* 3. j dst_reg, {src_reg, k}, +off // eBPF
|
||||
*/
|
||||
if (BPF_OP(opcode) == BPF_JUMP_JA ||
|
||||
(!EBPF_MODE(MI->csh) && i >= 1) ||
|
||||
(EBPF_MODE(MI->csh) && i == 2))
|
||||
push_op_off(bpf, (uint32_t)MCOperand_getImm(op));
|
||||
else
|
||||
push_op_imm(bpf, MCOperand_getImm(op));
|
||||
}
|
||||
else if (MCOperand_isReg(op)) {
|
||||
push_op_reg(bpf, MCOperand_getReg(op), CS_AC_READ);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!EBPF_MODE(MI->csh)) {
|
||||
/* In cBPF mode, all registers in operands are accessed as read */
|
||||
for (i = 0; i < mc_op_count; i++) {
|
||||
op = MCInst_getOperand(MI, i);
|
||||
if (MCOperand_isImm(op))
|
||||
push_op_imm(bpf, MCOperand_getImm(op));
|
||||
else if (MCOperand_isReg(op))
|
||||
push_op_reg(bpf, MCOperand_getReg(op), CS_AC_READ);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* remain cases are: eBPF mode && ALU */
|
||||
/* if (BPF_CLASS(opcode) == BPF_CLASS_ALU || BPF_CLASS(opcode) == BPF_CLASS_ALU64) */
|
||||
|
||||
/* We have three types:
|
||||
* 1. {l,b}e dst // dst = byteswap(dst)
|
||||
* 2. neg dst // dst = -dst
|
||||
* 3. <op> dst, {src_reg, imm} // dst = dst <op> src
|
||||
* so we can simply check the number of operands,
|
||||
* exactly one operand means we are in case 1. and 2.,
|
||||
* otherwise in case 3.
|
||||
*/
|
||||
if (mc_op_count == 1) {
|
||||
op = MCInst_getOperand(MI, 0);
|
||||
push_op_reg(bpf, MCOperand_getReg(op), CS_AC_READ | CS_AC_WRITE);
|
||||
}
|
||||
else { // if (mc_op_count == 2)
|
||||
op = MCInst_getOperand(MI, 0);
|
||||
push_op_reg(bpf, MCOperand_getReg(op), CS_AC_READ | CS_AC_WRITE);
|
||||
|
||||
op = MCInst_getOperand(MI, 1);
|
||||
if (MCOperand_isImm(op))
|
||||
push_op_imm(bpf, MCOperand_getImm(op));
|
||||
else if (MCOperand_isReg(op))
|
||||
push_op_reg(bpf, MCOperand_getReg(op), CS_AC_READ);
|
||||
}
|
||||
}
|
||||
|
||||
static void print_operand(MCInst *MI, struct SStream *O, const cs_bpf_op *op)
|
||||
{
|
||||
switch (op->type) {
|
||||
case BPF_OP_INVALID:
|
||||
SStream_concat(O, "invalid");
|
||||
break;
|
||||
case BPF_OP_REG:
|
||||
SStream_concat(O, BPF_reg_name((csh)MI->csh, op->reg));
|
||||
break;
|
||||
case BPF_OP_IMM:
|
||||
SStream_concat(O, "0x%" PRIx64, op->imm);
|
||||
break;
|
||||
case BPF_OP_OFF:
|
||||
SStream_concat(O, "+0x%x", op->off);
|
||||
break;
|
||||
case BPF_OP_MEM:
|
||||
SStream_concat(O, "[");
|
||||
if (op->mem.base != BPF_REG_INVALID)
|
||||
SStream_concat(O, BPF_reg_name((csh)MI->csh, op->mem.base));
|
||||
if (op->mem.disp != 0) {
|
||||
if (op->mem.base != BPF_REG_INVALID)
|
||||
SStream_concat(O, "+");
|
||||
SStream_concat(O, "0x%x", op->mem.disp);
|
||||
}
|
||||
if (op->mem.base == BPF_REG_INVALID && op->mem.disp == 0) // special case
|
||||
SStream_concat(O, "0x0");
|
||||
SStream_concat(O, "]");
|
||||
break;
|
||||
case BPF_OP_MMEM:
|
||||
SStream_concat(O, "m[0x%x]", op->mmem);
|
||||
break;
|
||||
case BPF_OP_MSH:
|
||||
SStream_concat(O, "4*([0x%x]&0xf)", op->msh);
|
||||
break;
|
||||
case BPF_OP_EXT:
|
||||
switch (op->ext) {
|
||||
case BPF_EXT_LEN:
|
||||
SStream_concat(O, "#len");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 1. human readable mnemonic
|
||||
* 2. set pubOpcode (BPF_INSN_*)
|
||||
* 3. set detail->bpf.operands
|
||||
* */
|
||||
void BPF_printInst(MCInst *MI, struct SStream *O, void *PrinterInfo)
|
||||
{
|
||||
int i;
|
||||
cs_insn insn;
|
||||
cs_bpf bpf;
|
||||
|
||||
insn.detail = NULL;
|
||||
/* set pubOpcode as instruction id */
|
||||
BPF_get_insn_id((cs_struct*)MI->csh, &insn, MCInst_getOpcode(MI));
|
||||
MCInst_setOpcodePub(MI, insn.id);
|
||||
|
||||
SStream_concat(O, BPF_insn_name((csh)MI->csh, insn.id));
|
||||
convert_operands(MI, &bpf);
|
||||
for (i = 0; i < bpf.op_count; i++) {
|
||||
if (i == 0)
|
||||
SStream_concat(O, "\t");
|
||||
else
|
||||
SStream_concat(O, ", ");
|
||||
print_operand(MI, O, &bpf.operands[i]);
|
||||
}
|
||||
|
||||
#ifndef CAPSTONE_DIET
|
||||
if (MI->flat_insn->detail) {
|
||||
MI->flat_insn->detail->bpf = bpf;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
/* Capstone Disassembly Engine */
|
||||
/* BPF Backend by david942j <david942j@gmail.com>, 2019 */
|
||||
|
||||
#ifndef CS_BPFINSTPRINTER_H
|
||||
#define CS_BPFINSTPRINTER_H
|
||||
|
||||
#include <capstone/capstone.h>
|
||||
|
||||
#include "../../MCInst.h"
|
||||
#include "../../SStream.h"
|
||||
|
||||
struct SStream;
|
||||
|
||||
void BPF_printInst(MCInst *MI, struct SStream *O, void *Info);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,513 @@
|
||||
/* Capstone Disassembly Engine */
|
||||
/* BPF Backend by david942j <david942j@gmail.com>, 2019 */
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "BPFConstants.h"
|
||||
#include "BPFMapping.h"
|
||||
#include "../../utils.h"
|
||||
|
||||
#ifndef CAPSTONE_DIET
|
||||
static const name_map group_name_maps[] = {
|
||||
{ BPF_GRP_INVALID, NULL },
|
||||
|
||||
{ BPF_GRP_LOAD, "load" },
|
||||
{ BPF_GRP_STORE, "store" },
|
||||
{ BPF_GRP_ALU, "alu" },
|
||||
{ BPF_GRP_JUMP, "jump" },
|
||||
{ BPF_GRP_CALL, "call" },
|
||||
{ BPF_GRP_RETURN, "return" },
|
||||
{ BPF_GRP_MISC, "misc" },
|
||||
};
|
||||
#endif
|
||||
|
||||
const char *BPF_group_name(csh handle, unsigned int id)
|
||||
{
|
||||
#ifndef CAPSTONE_DIET
|
||||
return id2name(group_name_maps, ARR_SIZE(group_name_maps), id);
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef CAPSTONE_DIET
|
||||
static const name_map insn_name_maps[BPF_INS_ENDING] = {
|
||||
{ BPF_INS_INVALID, NULL },
|
||||
|
||||
{ BPF_INS_ADD, "add" },
|
||||
{ BPF_INS_SUB, "sub" },
|
||||
{ BPF_INS_MUL, "mul" },
|
||||
{ BPF_INS_DIV, "div" },
|
||||
{ BPF_INS_OR, "or" },
|
||||
{ BPF_INS_AND, "and" },
|
||||
{ BPF_INS_LSH, "lsh" },
|
||||
{ BPF_INS_RSH, "rsh" },
|
||||
{ BPF_INS_NEG, "neg" },
|
||||
{ BPF_INS_MOD, "mod" },
|
||||
{ BPF_INS_XOR, "xor" },
|
||||
{ BPF_INS_MOV, "mov" },
|
||||
{ BPF_INS_ARSH, "arsh" },
|
||||
|
||||
{ BPF_INS_ADD64, "add64" },
|
||||
{ BPF_INS_SUB64, "sub64" },
|
||||
{ BPF_INS_MUL64, "mul64" },
|
||||
{ BPF_INS_DIV64, "div64" },
|
||||
{ BPF_INS_OR64, "or64" },
|
||||
{ BPF_INS_AND64, "and64" },
|
||||
{ BPF_INS_LSH64, "lsh64" },
|
||||
{ BPF_INS_RSH64, "rsh64" },
|
||||
{ BPF_INS_NEG64, "neg64" },
|
||||
{ BPF_INS_MOD64, "mod64" },
|
||||
{ BPF_INS_XOR64, "xor64" },
|
||||
{ BPF_INS_MOV64, "mov64" },
|
||||
{ BPF_INS_ARSH64, "arsh64" },
|
||||
|
||||
{ BPF_INS_LE16, "le16" },
|
||||
{ BPF_INS_LE32, "le32" },
|
||||
{ BPF_INS_LE64, "le64" },
|
||||
{ BPF_INS_BE16, "be16" },
|
||||
{ BPF_INS_BE32, "be32" },
|
||||
{ BPF_INS_BE64, "be64" },
|
||||
|
||||
{ BPF_INS_LDW, "ldw" },
|
||||
{ BPF_INS_LDH, "ldh" },
|
||||
{ BPF_INS_LDB, "ldb" },
|
||||
{ BPF_INS_LDDW, "lddw" },
|
||||
{ BPF_INS_LDXW, "ldxw" },
|
||||
{ BPF_INS_LDXH, "ldxh" },
|
||||
{ BPF_INS_LDXB, "ldxb" },
|
||||
{ BPF_INS_LDXDW, "ldxdw" },
|
||||
|
||||
{ BPF_INS_STW, "stw" },
|
||||
{ BPF_INS_STH, "sth" },
|
||||
{ BPF_INS_STB, "stb" },
|
||||
{ BPF_INS_STDW, "stdw" },
|
||||
{ BPF_INS_STXW, "stxw" },
|
||||
{ BPF_INS_STXH, "stxh" },
|
||||
{ BPF_INS_STXB, "stxb" },
|
||||
{ BPF_INS_STXDW, "stxdw" },
|
||||
{ BPF_INS_XADDW, "xaddw" },
|
||||
{ BPF_INS_XADDDW, "xadddw" },
|
||||
|
||||
{ BPF_INS_JMP, "jmp" },
|
||||
{ BPF_INS_JEQ, "jeq" },
|
||||
{ BPF_INS_JGT, "jgt" },
|
||||
{ BPF_INS_JGE, "jge" },
|
||||
{ BPF_INS_JSET, "jset" },
|
||||
{ BPF_INS_JNE, "jne" },
|
||||
{ BPF_INS_JSGT, "jsgt" },
|
||||
{ BPF_INS_JSGE, "jsge" },
|
||||
{ BPF_INS_CALL, "call" },
|
||||
{ BPF_INS_CALLX, "callx" },
|
||||
{ BPF_INS_EXIT, "exit" },
|
||||
{ BPF_INS_JLT, "jlt" },
|
||||
{ BPF_INS_JLE, "jle" },
|
||||
{ BPF_INS_JSLT, "jslt" },
|
||||
{ BPF_INS_JSLE, "jsle" },
|
||||
|
||||
{ BPF_INS_RET, "ret" },
|
||||
|
||||
{ BPF_INS_TAX, "tax" },
|
||||
{ BPF_INS_TXA, "txa" },
|
||||
};
|
||||
#endif
|
||||
|
||||
const char *BPF_insn_name(csh handle, unsigned int id)
|
||||
{
|
||||
#ifndef CAPSTONE_DIET
|
||||
/* We have some special cases because 'ld' in cBPF is equivalent to 'ldw'
|
||||
* in eBPF, and we don't want to see 'ldw' appears in cBPF mode.
|
||||
*/
|
||||
if (!EBPF_MODE(handle)) {
|
||||
switch (id) {
|
||||
case BPF_INS_LD: return "ld";
|
||||
case BPF_INS_LDX: return "ldx";
|
||||
case BPF_INS_ST: return "st";
|
||||
case BPF_INS_STX: return "stx";
|
||||
}
|
||||
}
|
||||
return id2name(insn_name_maps, ARR_SIZE(insn_name_maps), id);
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
const char *BPF_reg_name(csh handle, unsigned int reg)
|
||||
{
|
||||
#ifndef CAPSTONE_DIET
|
||||
if (EBPF_MODE(handle)) {
|
||||
if (reg < BPF_REG_R0 || reg > BPF_REG_R10)
|
||||
return NULL;
|
||||
static const char reg_names[11][4] = {
|
||||
"r0", "r1", "r2", "r3", "r4",
|
||||
"r5", "r6", "r7", "r8", "r9",
|
||||
"r10"
|
||||
};
|
||||
return reg_names[reg - BPF_REG_R0];
|
||||
}
|
||||
|
||||
/* cBPF mode */
|
||||
if (reg == BPF_REG_A)
|
||||
return "a";
|
||||
else if (reg == BPF_REG_X)
|
||||
return "x";
|
||||
else
|
||||
return NULL;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
static bpf_insn op2insn_ld(unsigned opcode)
|
||||
{
|
||||
#define CASE(c) case BPF_SIZE_##c: \
|
||||
if (BPF_CLASS(opcode) == BPF_CLASS_LD) \
|
||||
return BPF_INS_LD##c; \
|
||||
else \
|
||||
return BPF_INS_LDX##c;
|
||||
|
||||
switch (BPF_SIZE(opcode)) {
|
||||
CASE(W);
|
||||
CASE(H);
|
||||
CASE(B);
|
||||
CASE(DW);
|
||||
}
|
||||
#undef CASE
|
||||
|
||||
return BPF_INS_INVALID;
|
||||
}
|
||||
|
||||
static bpf_insn op2insn_st(unsigned opcode)
|
||||
{
|
||||
/*
|
||||
* - BPF_STX | BPF_XADD | BPF_{W,DW}
|
||||
* - BPF_ST* | BPF_MEM | BPF_{W,H,B,DW}
|
||||
*/
|
||||
|
||||
if (opcode == (BPF_CLASS_STX | BPF_MODE_XADD | BPF_SIZE_W))
|
||||
return BPF_INS_XADDW;
|
||||
if (opcode == (BPF_CLASS_STX | BPF_MODE_XADD | BPF_SIZE_DW))
|
||||
return BPF_INS_XADDDW;
|
||||
|
||||
/* should be BPF_MEM */
|
||||
#define CASE(c) case BPF_SIZE_##c: \
|
||||
if (BPF_CLASS(opcode) == BPF_CLASS_ST) \
|
||||
return BPF_INS_ST##c; \
|
||||
else \
|
||||
return BPF_INS_STX##c;
|
||||
switch (BPF_SIZE(opcode)) {
|
||||
CASE(W);
|
||||
CASE(H);
|
||||
CASE(B);
|
||||
CASE(DW);
|
||||
}
|
||||
#undef CASE
|
||||
|
||||
return BPF_INS_INVALID;
|
||||
}
|
||||
|
||||
static bpf_insn op2insn_alu(unsigned opcode)
|
||||
{
|
||||
/* Endian is a special case */
|
||||
if (BPF_OP(opcode) == BPF_ALU_END) {
|
||||
switch (opcode ^ BPF_CLASS_ALU ^ BPF_ALU_END) {
|
||||
case BPF_SRC_LITTLE | (16 << 4):
|
||||
return BPF_INS_LE16;
|
||||
case BPF_SRC_LITTLE | (32 << 4):
|
||||
return BPF_INS_LE32;
|
||||
case BPF_SRC_LITTLE | (64 << 4):
|
||||
return BPF_INS_LE64;
|
||||
case BPF_SRC_BIG | (16 << 4):
|
||||
return BPF_INS_BE16;
|
||||
case BPF_SRC_BIG | (32 << 4):
|
||||
return BPF_INS_BE32;
|
||||
case BPF_SRC_BIG | (64 << 4):
|
||||
return BPF_INS_BE64;
|
||||
}
|
||||
return BPF_INS_INVALID;
|
||||
}
|
||||
|
||||
#define CASE(c) case BPF_ALU_##c: \
|
||||
if (BPF_CLASS(opcode) == BPF_CLASS_ALU) \
|
||||
return BPF_INS_##c; \
|
||||
else \
|
||||
return BPF_INS_##c##64;
|
||||
|
||||
switch (BPF_OP(opcode)) {
|
||||
CASE(ADD);
|
||||
CASE(SUB);
|
||||
CASE(MUL);
|
||||
CASE(DIV);
|
||||
CASE(OR);
|
||||
CASE(AND);
|
||||
CASE(LSH);
|
||||
CASE(RSH);
|
||||
CASE(NEG);
|
||||
CASE(MOD);
|
||||
CASE(XOR);
|
||||
CASE(MOV);
|
||||
CASE(ARSH);
|
||||
}
|
||||
#undef CASE
|
||||
|
||||
return BPF_INS_INVALID;
|
||||
}
|
||||
|
||||
static bpf_insn op2insn_jmp(unsigned opcode)
|
||||
{
|
||||
if (opcode == (BPF_CLASS_JMP | BPF_JUMP_CALL | BPF_SRC_X)) {
|
||||
return BPF_INS_CALLX;
|
||||
}
|
||||
|
||||
#define CASE(c) case BPF_JUMP_##c: return BPF_INS_##c
|
||||
switch (BPF_OP(opcode)) {
|
||||
case BPF_JUMP_JA:
|
||||
return BPF_INS_JMP;
|
||||
CASE(JEQ);
|
||||
CASE(JGT);
|
||||
CASE(JGE);
|
||||
CASE(JSET);
|
||||
CASE(JNE);
|
||||
CASE(JSGT);
|
||||
CASE(JSGE);
|
||||
CASE(CALL);
|
||||
CASE(EXIT);
|
||||
CASE(JLT);
|
||||
CASE(JLE);
|
||||
CASE(JSLT);
|
||||
CASE(JSLE);
|
||||
}
|
||||
#undef CASE
|
||||
|
||||
return BPF_INS_INVALID;
|
||||
}
|
||||
|
||||
static void update_regs_access(cs_struct *ud, cs_detail *detail,
|
||||
bpf_insn insn_id, unsigned int opcode)
|
||||
{
|
||||
if (insn_id == BPF_INS_INVALID)
|
||||
return;
|
||||
#define PUSH_READ(r) do { \
|
||||
detail->regs_read[detail->regs_read_count] = r; \
|
||||
detail->regs_read_count++; \
|
||||
} while (0)
|
||||
#define PUSH_WRITE(r) do { \
|
||||
detail->regs_write[detail->regs_write_count] = r; \
|
||||
detail->regs_write_count++; \
|
||||
} while (0)
|
||||
/*
|
||||
* In eBPF mode, only these instructions have implicit registers access:
|
||||
* - legacy ld{w,h,b,dw} * // w: r0
|
||||
* - exit // r: r0
|
||||
*/
|
||||
if (EBPF_MODE(ud)) {
|
||||
switch (insn_id) {
|
||||
default:
|
||||
break;
|
||||
case BPF_INS_LDW:
|
||||
case BPF_INS_LDH:
|
||||
case BPF_INS_LDB:
|
||||
case BPF_INS_LDDW:
|
||||
if (BPF_MODE(opcode) == BPF_MODE_ABS || BPF_MODE(opcode) == BPF_MODE_IND) {
|
||||
PUSH_WRITE(BPF_REG_R0);
|
||||
}
|
||||
break;
|
||||
case BPF_INS_EXIT:
|
||||
PUSH_READ(BPF_REG_R0);
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* cBPF mode */
|
||||
switch (BPF_CLASS(opcode)) {
|
||||
default:
|
||||
break;
|
||||
case BPF_CLASS_LD:
|
||||
PUSH_WRITE(BPF_REG_A);
|
||||
break;
|
||||
case BPF_CLASS_LDX:
|
||||
PUSH_WRITE(BPF_REG_X);
|
||||
break;
|
||||
case BPF_CLASS_ST:
|
||||
PUSH_READ(BPF_REG_A);
|
||||
break;
|
||||
case BPF_CLASS_STX:
|
||||
PUSH_READ(BPF_REG_X);
|
||||
break;
|
||||
case BPF_CLASS_ALU:
|
||||
PUSH_READ(BPF_REG_A);
|
||||
PUSH_WRITE(BPF_REG_A);
|
||||
break;
|
||||
case BPF_CLASS_JMP:
|
||||
if (insn_id != BPF_INS_JMP) // except the unconditional jump
|
||||
PUSH_READ(BPF_REG_A);
|
||||
break;
|
||||
/* case BPF_CLASS_RET: */
|
||||
case BPF_CLASS_MISC:
|
||||
if (insn_id == BPF_INS_TAX) {
|
||||
PUSH_READ(BPF_REG_A);
|
||||
PUSH_WRITE(BPF_REG_X);
|
||||
}
|
||||
else {
|
||||
PUSH_READ(BPF_REG_X);
|
||||
PUSH_WRITE(BPF_REG_A);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 1. Convert opcode(id) to BPF_INS_*
|
||||
* 2. Set regs_read/regs_write/groups
|
||||
*/
|
||||
void BPF_get_insn_id(cs_struct *ud, cs_insn *insn, unsigned int opcode)
|
||||
{
|
||||
// No need to care the mode (cBPF or eBPF) since all checks has be done in
|
||||
// BPF_getInstruction, we can simply map opcode to BPF_INS_*.
|
||||
cs_detail *detail;
|
||||
bpf_insn id = BPF_INS_INVALID;
|
||||
bpf_insn_group grp;
|
||||
|
||||
detail = insn->detail;
|
||||
#ifndef CAPSTONE_DIET
|
||||
#define PUSH_GROUP(grp) do { \
|
||||
if (detail) { \
|
||||
detail->groups[detail->groups_count] = grp; \
|
||||
detail->groups_count++; \
|
||||
} \
|
||||
} while(0)
|
||||
#else
|
||||
#define PUSH_GROUP
|
||||
#endif
|
||||
|
||||
switch (BPF_CLASS(opcode)) {
|
||||
default: // will never happen
|
||||
break;
|
||||
case BPF_CLASS_LD:
|
||||
case BPF_CLASS_LDX:
|
||||
id = op2insn_ld(opcode);
|
||||
PUSH_GROUP(BPF_GRP_LOAD);
|
||||
break;
|
||||
case BPF_CLASS_ST:
|
||||
case BPF_CLASS_STX:
|
||||
id = op2insn_st(opcode);
|
||||
PUSH_GROUP(BPF_GRP_STORE);
|
||||
break;
|
||||
case BPF_CLASS_ALU:
|
||||
id = op2insn_alu(opcode);
|
||||
PUSH_GROUP(BPF_GRP_ALU);
|
||||
break;
|
||||
case BPF_CLASS_JMP:
|
||||
grp = BPF_GRP_JUMP;
|
||||
id = op2insn_jmp(opcode);
|
||||
if (id == BPF_INS_CALL || id == BPF_INS_CALLX)
|
||||
grp = BPF_GRP_CALL;
|
||||
else if (id == BPF_INS_EXIT)
|
||||
grp = BPF_GRP_RETURN;
|
||||
PUSH_GROUP(grp);
|
||||
break;
|
||||
case BPF_CLASS_RET:
|
||||
id = BPF_INS_RET;
|
||||
PUSH_GROUP(BPF_GRP_RETURN);
|
||||
break;
|
||||
// BPF_CLASS_MISC and BPF_CLASS_ALU64 have exactly same value
|
||||
case BPF_CLASS_MISC:
|
||||
/* case BPF_CLASS_ALU64: */
|
||||
if (EBPF_MODE(ud)) {
|
||||
// ALU64 in eBPF
|
||||
id = op2insn_alu(opcode);
|
||||
PUSH_GROUP(BPF_GRP_ALU);
|
||||
}
|
||||
else {
|
||||
if (BPF_MISCOP(opcode) == BPF_MISCOP_TXA)
|
||||
id = BPF_INS_TXA;
|
||||
else
|
||||
id = BPF_INS_TAX;
|
||||
PUSH_GROUP(BPF_GRP_MISC);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
insn->id = id;
|
||||
#undef PUSH_GROUP
|
||||
|
||||
#ifndef CAPSTONE_DIET
|
||||
if (detail) {
|
||||
update_regs_access(ud, detail, id, opcode);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void sort_and_uniq(cs_regs arr, uint8_t n, uint8_t *new_n)
|
||||
{
|
||||
/* arr is always a tiny (usually n < 3) array,
|
||||
* a simple O(n^2) sort is efficient enough. */
|
||||
int i;
|
||||
int j;
|
||||
int iMin;
|
||||
int tmp;
|
||||
|
||||
/* a modified selection sort for sorting and making unique */
|
||||
for (j = 0; j < n; j++) {
|
||||
/* arr[iMin] will be min(arr[j .. n-1]) */
|
||||
iMin = j;
|
||||
for (i = j + 1; i < n; i++) {
|
||||
if (arr[i] < arr[iMin])
|
||||
iMin = i;
|
||||
}
|
||||
if (j != 0 && arr[iMin] == arr[j - 1]) { // duplicate ele found
|
||||
arr[iMin] = arr[n - 1];
|
||||
--n;
|
||||
}
|
||||
else {
|
||||
tmp = arr[iMin];
|
||||
arr[iMin] = arr[j];
|
||||
arr[j] = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
*new_n = n;
|
||||
}
|
||||
void BPF_reg_access(const cs_insn *insn,
|
||||
cs_regs regs_read, uint8_t *regs_read_count,
|
||||
cs_regs regs_write, uint8_t *regs_write_count)
|
||||
{
|
||||
unsigned i;
|
||||
uint8_t read_count, write_count;
|
||||
const cs_bpf *bpf = &(insn->detail->bpf);
|
||||
|
||||
read_count = insn->detail->regs_read_count;
|
||||
write_count = insn->detail->regs_write_count;
|
||||
|
||||
// implicit registers
|
||||
memcpy(regs_read, insn->detail->regs_read, read_count * sizeof(insn->detail->regs_read[0]));
|
||||
memcpy(regs_write, insn->detail->regs_write, write_count * sizeof(insn->detail->regs_write[0]));
|
||||
|
||||
for (i = 0; i < bpf->op_count; i++) {
|
||||
const cs_bpf_op *op = &(bpf->operands[i]);
|
||||
switch (op->type) {
|
||||
default:
|
||||
break;
|
||||
case BPF_OP_REG:
|
||||
if (op->access & CS_AC_READ) {
|
||||
regs_read[read_count] = op->reg;
|
||||
read_count++;
|
||||
}
|
||||
if (op->access & CS_AC_WRITE) {
|
||||
regs_write[write_count] = op->reg;
|
||||
write_count++;
|
||||
}
|
||||
break;
|
||||
case BPF_OP_MEM:
|
||||
if (op->mem.base != BPF_REG_INVALID) {
|
||||
regs_read[read_count] = op->mem.base;
|
||||
read_count++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
sort_and_uniq(regs_read, read_count, regs_read_count);
|
||||
sort_and_uniq(regs_write, write_count, regs_write_count);
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user