aboutsummaryrefslogtreecommitdiffstats
path: root/capstone/arch/WASM
diff options
context:
space:
mode:
authorAngelos Mouzakitis <a.mouzakitis@virtualopensystems.com>2023-10-10 14:33:42 +0000
committerAngelos Mouzakitis <a.mouzakitis@virtualopensystems.com>2023-10-10 14:33:42 +0000
commitaf1a266670d040d2f4083ff309d732d648afba2a (patch)
tree2fc46203448ddcc6f81546d379abfaeb323575e9 /capstone/arch/WASM
parente02cda008591317b1625707ff8e115a4841aa889 (diff)
Add submodule dependency filesHEADmaster
Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec
Diffstat (limited to 'capstone/arch/WASM')
-rw-r--r--capstone/arch/WASM/WASMDisassembler.c1009
-rw-r--r--capstone/arch/WASM/WASMDisassembler.h12
-rw-r--r--capstone/arch/WASM/WASMInstPrinter.c47
-rw-r--r--capstone/arch/WASM/WASMInstPrinter.h18
-rw-r--r--capstone/arch/WASM/WASMMapping.c333
-rw-r--r--capstone/arch/WASM/WASMMapping.h9
-rw-r--r--capstone/arch/WASM/WASMModule.c33
-rw-r--r--capstone/arch/WASM/WASMModule.h12
8 files changed, 1473 insertions, 0 deletions
diff --git a/capstone/arch/WASM/WASMDisassembler.c b/capstone/arch/WASM/WASMDisassembler.c
new file mode 100644
index 000000000..a05ee0c75
--- /dev/null
+++ b/capstone/arch/WASM/WASMDisassembler.c
@@ -0,0 +1,1009 @@
+/* Capstone Disassembly Engine */
+/* By Spike, xwings 2019 */
+
+#include <string.h>
+#include <stddef.h> // offsetof macro
+// alternatively #include "../../utils.h" like everyone else
+
+#include "WASMDisassembler.h"
+#include "WASMMapping.h"
+#include "../../cs_priv.h"
+
+static const short opcodes[256] = {
+ WASM_INS_UNREACHABLE,
+ WASM_INS_NOP,
+ WASM_INS_BLOCK,
+ WASM_INS_LOOP,
+ WASM_INS_IF,
+ WASM_INS_ELSE,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ WASM_INS_END,
+ WASM_INS_BR,
+ WASM_INS_BR_IF,
+ WASM_INS_BR_TABLE,
+ WASM_INS_RETURN,
+ WASM_INS_CALL,
+ WASM_INS_CALL_INDIRECT,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ WASM_INS_DROP,
+ WASM_INS_SELECT,
+ -1,
+ -1,
+ -1,
+ -1,
+ WASM_INS_GET_LOCAL,
+ WASM_INS_SET_LOCAL,
+ WASM_INS_TEE_LOCAL,
+ WASM_INS_GET_GLOBAL,
+ WASM_INS_SET_GLOBAL,
+ -1,
+ -1,
+ -1,
+ WASM_INS_I32_LOAD,
+ WASM_INS_I64_LOAD,
+ WASM_INS_F32_LOAD,
+ WASM_INS_F64_LOAD,
+ WASM_INS_I32_LOAD8_S,
+ WASM_INS_I32_LOAD8_U,
+ WASM_INS_I32_LOAD16_S,
+ WASM_INS_I32_LOAD16_U,
+ WASM_INS_I64_LOAD8_S,
+ WASM_INS_I64_LOAD8_U,
+ WASM_INS_I64_LOAD16_S,
+ WASM_INS_I64_LOAD16_U,
+ WASM_INS_I64_LOAD32_S,
+ WASM_INS_I64_LOAD32_U,
+ WASM_INS_I32_STORE,
+ WASM_INS_I64_STORE,
+ WASM_INS_F32_STORE,
+ WASM_INS_F64_STORE,
+ WASM_INS_I32_STORE8,
+ WASM_INS_I32_STORE16,
+ WASM_INS_I64_STORE8,
+ WASM_INS_I64_STORE16,
+ WASM_INS_I64_STORE32,
+ WASM_INS_CURRENT_MEMORY,
+ WASM_INS_GROW_MEMORY,
+ WASM_INS_I32_CONST,
+ WASM_INS_I64_CONST,
+ WASM_INS_F32_CONST,
+ WASM_INS_F64_CONST,
+ WASM_INS_I32_EQZ,
+ WASM_INS_I32_EQ,
+ WASM_INS_I32_NE,
+ WASM_INS_I32_LT_S,
+ WASM_INS_I32_LT_U,
+ WASM_INS_I32_GT_S,
+ WASM_INS_I32_GT_U,
+ WASM_INS_I32_LE_S,
+ WASM_INS_I32_LE_U,
+ WASM_INS_I32_GE_S,
+ WASM_INS_I32_GE_U,
+ WASM_INS_I64_EQZ,
+ WASM_INS_I64_EQ,
+ WASM_INS_I64_NE,
+ WASM_INS_I64_LT_S,
+ WASM_INS_I64_LT_U,
+ WASN_INS_I64_GT_S,
+ WASM_INS_I64_GT_U,
+ WASM_INS_I64_LE_S,
+ WASM_INS_I64_LE_U,
+ WASM_INS_I64_GE_S,
+ WASM_INS_I64_GE_U,
+ WASM_INS_F32_EQ,
+ WASM_INS_F32_NE,
+ WASM_INS_F32_LT,
+ WASM_INS_F32_GT,
+ WASM_INS_F32_LE,
+ WASM_INS_F32_GE,
+ WASM_INS_F64_EQ,
+ WASM_INS_F64_NE,
+ WASM_INS_F64_LT,
+ WASM_INS_F64_GT,
+ WASM_INS_F64_LE,
+ WASM_INS_F64_GE,
+ WASM_INS_I32_CLZ,
+ WASM_INS_I32_CTZ,
+ WASM_INS_I32_POPCNT,
+ WASM_INS_I32_ADD,
+ WASM_INS_I32_SUB,
+ WASM_INS_I32_MUL,
+ WASM_INS_I32_DIV_S,
+ WASM_INS_I32_DIV_U,
+ WASM_INS_I32_REM_S,
+ WASM_INS_I32_REM_U,
+ WASM_INS_I32_AND,
+ WASM_INS_I32_OR,
+ WASM_INS_I32_XOR,
+ WASM_INS_I32_SHL,
+ WASM_INS_I32_SHR_S,
+ WASM_INS_I32_SHR_U,
+ WASM_INS_I32_ROTL,
+ WASM_INS_I32_ROTR,
+ WASM_INS_I64_CLZ,
+ WASM_INS_I64_CTZ,
+ WASM_INS_I64_POPCNT,
+ WASM_INS_I64_ADD,
+ WASM_INS_I64_SUB,
+ WASM_INS_I64_MUL,
+ WASM_INS_I64_DIV_S,
+ WASM_INS_I64_DIV_U,
+ WASM_INS_I64_REM_S,
+ WASM_INS_I64_REM_U,
+ WASM_INS_I64_AND,
+ WASM_INS_I64_OR,
+ WASM_INS_I64_XOR,
+ WASM_INS_I64_SHL,
+ WASM_INS_I64_SHR_S,
+ WASM_INS_I64_SHR_U,
+ WASM_INS_I64_ROTL,
+ WASM_INS_I64_ROTR,
+ WASM_INS_F32_ABS,
+ WASM_INS_F32_NEG,
+ WASM_INS_F32_CEIL,
+ WASM_INS_F32_FLOOR,
+ WASM_INS_F32_TRUNC,
+ WASM_INS_F32_NEAREST,
+ WASM_INS_F32_SQRT,
+ WASM_INS_F32_ADD,
+ WASM_INS_F32_SUB,
+ WASM_INS_F32_MUL,
+ WASM_INS_F32_DIV,
+ WASM_INS_F32_MIN,
+ WASM_INS_F32_MAX,
+ WASM_INS_F32_COPYSIGN,
+ WASM_INS_F64_ABS,
+ WASM_INS_F64_NEG,
+ WASM_INS_F64_CEIL,
+ WASM_INS_F64_FLOOR,
+ WASM_INS_F64_TRUNC,
+ WASM_INS_F64_NEAREST,
+ WASM_INS_F64_SQRT,
+ WASM_INS_F64_ADD,
+ WASM_INS_F64_SUB,
+ WASM_INS_F64_MUL,
+ WASM_INS_F64_DIV,
+ WASM_INS_F64_MIN,
+ WASM_INS_F64_MAX,
+ WASM_INS_F64_COPYSIGN,
+ WASM_INS_I32_WARP_I64,
+ WASP_INS_I32_TRUNC_S_F32,
+ WASM_INS_I32_TRUNC_U_F32,
+ WASM_INS_I32_TRUNC_S_F64,
+ WASM_INS_I32_TRUNC_U_F64,
+ WASM_INS_I64_EXTEND_S_I32,
+ WASM_INS_I64_EXTEND_U_I32,
+ WASM_INS_I64_TRUNC_S_F32,
+ WASM_INS_I64_TRUNC_U_F32,
+ WASM_INS_I64_TRUNC_S_F64,
+ WASM_INS_I64_TRUNC_U_F64,
+ WASM_INS_F32_CONVERT_S_I32,
+ WASM_INS_F32_CONVERT_U_I32,
+ WASM_INS_F32_CONVERT_S_I64,
+ WASM_INS_F32_CONVERT_U_I64,
+ WASM_INS_F32_DEMOTE_F64,
+ WASM_INS_F64_CONVERT_S_I32,
+ WASM_INS_F64_CONVERT_U_I32,
+ WASM_INS_F64_CONVERT_S_I64,
+ WASM_INS_F64_CONVERT_U_I64,
+ WASM_INS_F64_PROMOTE_F32,
+ WASM_INS_I32_REINTERPRET_F32,
+ WASM_INS_I64_REINTERPRET_F64,
+ WASM_INS_F32_REINTERPRET_I32,
+ WASM_INS_F64_REINTERPRET_I64,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+};
+
+// input | code: code pointer start from varuint32
+// | code_len: real code len count from varint
+// | leng: return value, means length of varint. -1 means error
+// return | varint
+static uint32_t get_varuint32(const uint8_t *code, size_t code_len, size_t *leng)
+{
+ uint32_t data = 0;
+ int i;
+
+ for(i = 0;; i++) {
+ if (code_len < i + 1) {
+ *leng = -1;
+ return 0;
+ }
+
+
+ if (i > 4 || (i == 4 && (code[i] & 0x7f) > 0x0f)) {
+ *leng = -1;
+ return 0;
+ }
+
+ data = data + (((uint32_t) code[i] & 0x7f) << (i * 7));
+ if (code[i] >> 7 == 0) {
+ break;
+ }
+ }
+
+ *leng = i + 1;
+
+ return data;
+}
+
+// input | code : code pointer start from varuint64
+// | code_len : real code len count from varint
+// | leng: return value, means length of varint. -1 means error
+// return | varint
+static uint64_t get_varuint64(const uint8_t *code, size_t code_len, size_t *leng)
+{
+ uint64_t data;
+ int i;
+
+ data = 0;
+ for(i = 0;; i++){
+ if (code_len < i + 1) {
+ *leng = -1;
+ return 0;
+ }
+
+ if (i > 9 || (i == 9 && (code[i] & 0x7f) > 0x01)) {
+ *leng = -1;
+ return 0;
+ }
+
+ data = data + (((uint64_t) code[i] & 0x7f) << (i * 7));
+ if (code[i] >> 7 == 0) {
+ break;
+ }
+ }
+
+ *leng = i + 1;
+
+ return data;
+}
+
+// input | code : code pointer start from uint32
+// | dest : the pointer where we store the uint32
+// return | None
+static void get_uint32(const uint8_t *code, uint32_t *dest)
+{
+ memcpy(dest, code, 4);
+}
+
+// input | code : code pointer start from uint32
+// | dest : the pointer where we store the uint64
+// return | None
+static void get_uint64(const uint8_t *code, uint64_t *dest)
+{
+ memcpy(dest, code, 8);
+}
+
+// input | code : code pointer start from varint7
+// | code_len : start from the code pointer to the end, how long is it
+// | leng : length of the param , -1 means error
+// return | data of varint7
+static int8_t get_varint7(const uint8_t *code, size_t code_len, size_t *leng)
+{
+ int8_t data;
+
+ if (code_len < 1) {
+ *leng = -1;
+ return -1;
+ }
+
+ *leng = 1;
+
+ if (code[0] == 0x40) {
+ return -1;
+ }
+
+ data = code[0] & 0x7f;
+
+ return data;
+}
+
+// input | code : code pointer start from varuint32
+// | code_len : start from the code pointer to the end, how long is it
+// | param_size : pointer of the param size
+// | MI : Mcinst handler in this round of disasm
+// return | true/false if the function successfully finished
+static bool read_varuint32(const uint8_t *code, size_t code_len, uint16_t *param_size, MCInst *MI)
+{
+ size_t len = 0;
+ uint32_t data;
+
+ data = get_varuint32(code, code_len, &len);
+ if (len == -1) {
+ return false;
+ }
+
+ if (MI->flat_insn->detail) {
+ MI->flat_insn->detail->wasm.op_count = 1;
+ MI->flat_insn->detail->wasm.operands[0].type = WASM_OP_VARUINT32;
+ MI->flat_insn->detail->wasm.operands[0].size= len;
+ MI->flat_insn->detail->wasm.operands[0].varuint32= data;
+ }
+
+ MI->wasm_data.size = len;
+ MI->wasm_data.type = WASM_OP_VARUINT32;
+ MI->wasm_data.uint32 = data;
+ *param_size = len;
+
+ return true;
+}
+
+// input | code : code pointer start from varuint64
+// | code_len : start from the code pointer to the end, how long is it
+// | param_size : pointer of the param size
+// | MI : Mcinst handler in this round of disasm
+// return | true/false if the function successfully finished
+static bool read_varuint64(const uint8_t *code, size_t code_len, uint16_t *param_size, MCInst *MI)
+{
+ size_t len = 0;
+ uint64_t data;
+
+ data = get_varuint64(code, code_len, &len);
+ if (len == -1) {
+ return false;
+ }
+
+ if (MI->flat_insn->detail) {
+ MI->flat_insn->detail->wasm.op_count = 1;
+ MI->flat_insn->detail->wasm.operands[0].type = WASM_OP_VARUINT64;
+ MI->flat_insn->detail->wasm.operands[0].size = len;
+ MI->flat_insn->detail->wasm.operands[0].varuint64 = data;
+ }
+
+ MI->wasm_data.size = len;
+ MI->wasm_data.type = WASM_OP_VARUINT64;
+ MI->wasm_data.uint64 = data;
+ *param_size = len;
+
+ return true;
+}
+
+// input | code : code pointer start from memoryimmediate
+// | code_len : start from the code pointer to the end, how long is it
+// | param_size : pointer of the param size (sum of two params)
+// | MI : Mcinst handler in this round of disasm
+// return | true/false if the function successfully finished
+static bool read_memoryimmediate(const uint8_t *code, size_t code_len, uint16_t *param_size, MCInst *MI)
+{
+ size_t tmp, len = 0;
+ uint32_t data[2];
+
+ if (MI->flat_insn->detail) {
+ MI->flat_insn->detail->wasm.op_count = 2;
+ }
+
+ data[0] = get_varuint32(code, code_len, &tmp);
+ if (tmp == -1) {
+ return false;
+ }
+
+ if (MI->flat_insn->detail) {
+ MI->flat_insn->detail->wasm.operands[0].type = WASM_OP_VARUINT32;
+ MI->flat_insn->detail->wasm.operands[0].size = tmp;
+ MI->flat_insn->detail->wasm.operands[0].varuint32 = data[0];
+ }
+
+ len = tmp;
+ data[1] = get_varuint32(&code[len], code_len - len, &tmp);
+ if (len == -1) {
+ return false;
+ }
+
+ if (MI->flat_insn->detail) {
+ MI->flat_insn->detail->wasm.operands[1].type = WASM_OP_VARUINT32;
+ MI->flat_insn->detail->wasm.operands[1].size = tmp;
+ MI->flat_insn->detail->wasm.operands[1].varuint32 = data[1];
+ }
+
+ len += tmp;
+ MI->wasm_data.size = len;
+ MI->wasm_data.type = WASM_OP_IMM;
+ MI->wasm_data.immediate[0] = data[0];
+ MI->wasm_data.immediate[1] = data[1];
+ *param_size = len;
+
+ return true;
+}
+
+// input | code : code pointer start from uint32
+// | code_len : start from the code pointer to the end, how long is it
+// | param_size : pointer of the param size
+// | MI : Mcinst handler in this round of disasm
+// return | true/false if the function successfully finished
+static bool read_uint32(const uint8_t *code, size_t code_len, uint16_t *param_size, MCInst *MI)
+{
+ if (code_len < 4) {
+ return false;
+ }
+
+ get_uint32(code, &(MI->wasm_data.uint32));
+
+ if (MI->flat_insn->detail) {
+ MI->flat_insn->detail->wasm.op_count = 1;
+ MI->flat_insn->detail->wasm.operands[0].type = WASM_OP_UINT32;
+ MI->flat_insn->detail->wasm.operands[0].size = 4;
+ get_uint32(code, &(MI->flat_insn->detail->wasm.operands[0].uint32));
+ }
+
+ MI->wasm_data.size = 4;
+ MI->wasm_data.type = WASM_OP_UINT32;
+ *param_size = 4;
+
+ return true;
+}
+
+// input | code : code pointer start from uint64
+// | code_len : start from the code pointer to the end, how long is it
+// | param_size : pointer of the param size
+// | MI : Mcinst handler in this round of disasm
+// return | true/false if the function successfully finished
+static bool read_uint64(const uint8_t *code, size_t code_len, uint16_t *param_size, MCInst *MI)
+{
+ if (code_len < 8) {
+ return false;
+ }
+
+ get_uint64(code, &(MI->wasm_data.uint64));
+
+ if (MI->flat_insn->detail) {
+ MI->flat_insn->detail->wasm.op_count = 1;
+ MI->flat_insn->detail->wasm.operands[0].type = WASM_OP_UINT64;
+ MI->flat_insn->detail->wasm.operands[0].size = 8;
+ get_uint64(code, &(MI->flat_insn->detail->wasm.operands[0].uint64));
+ }
+
+ MI->wasm_data.size = 8;
+ MI->wasm_data.type = WASM_OP_UINT64;
+ *param_size = 8;
+
+ return true;
+}
+
+// input | code : code pointer start from brtable
+// | code_len : start from the code pointer to the end, how long is it
+// | param_size : pointer of the param size (sum of all param)
+// | MI : Mcinst handler in this round of disasm
+// return | true/false if the function successfully finished
+static bool read_brtable(const uint8_t *code, size_t code_len, uint16_t *param_size, MCInst *MI)
+{
+ uint32_t length, default_target;
+ int tmp_len = 0, i;
+ size_t var_len;
+
+ // read length
+ length = get_varuint32(code, code_len, &var_len);
+ if (var_len == -1) {
+ return false;
+ }
+
+ tmp_len += var_len;
+ MI->wasm_data.brtable.length = length;
+ if (length >= UINT32_MAX - tmp_len) {
+ // integer overflow check
+ return false;
+ }
+ if (code_len < tmp_len + length) {
+ // safety check that we have minimum enough data to read
+ return false;
+ }
+ // base address + 1 byte opcode + tmp_len for number of cases = start of targets
+ MI->wasm_data.brtable.address = MI->address + 1 + tmp_len;
+
+ if (MI->flat_insn->detail) {
+ MI->flat_insn->detail->wasm.op_count = 1;
+ MI->flat_insn->detail->wasm.operands[0].type = WASM_OP_BRTABLE;
+ MI->flat_insn->detail->wasm.operands[0].brtable.length = MI->wasm_data.brtable.length;
+ MI->flat_insn->detail->wasm.operands[0].brtable.address = MI->wasm_data.brtable.address;
+ }
+
+ // read data
+ for(i = 0; i < length; i++){
+ if (code_len < tmp_len) {
+ return false;
+ }
+
+ get_varuint32(code + tmp_len, code_len - tmp_len, &var_len);
+ if (var_len == -1) {
+ return false;
+ }
+
+ tmp_len += var_len;
+ }
+
+ // read default target
+ default_target = get_varuint32(code + tmp_len, code_len - tmp_len, &var_len);
+ if (var_len == -1) {
+ return false;
+ }
+
+ MI->wasm_data.brtable.default_target = default_target;
+ MI->wasm_data.type = WASM_OP_BRTABLE;
+ *param_size = tmp_len + var_len;
+
+ if (MI->flat_insn->detail) {
+ MI->flat_insn->detail->wasm.operands[0].size = *param_size;
+ MI->flat_insn->detail->wasm.operands[0].brtable.default_target = MI->wasm_data.brtable.default_target;
+ }
+
+ return true;
+}
+
+// input | code : code pointer start from varint7
+// | code_len : start from the code pointer to the end, how long is it
+// | param_size : pointer of the param size
+// | MI : Mcinst handler in this round of disasm
+// return | true/false if the function successfully finished
+static bool read_varint7(const uint8_t *code, size_t code_len, uint16_t *param_size, MCInst *MI)
+{
+ size_t len = 0;
+
+ MI->wasm_data.type = WASM_OP_INT7;
+ MI->wasm_data.int7 = get_varint7(code, code_len, &len);
+ if (len == -1) {
+ return false;
+ }
+
+ if (MI->flat_insn->detail) {
+ MI->flat_insn->detail->wasm.op_count = 1;
+ MI->flat_insn->detail->wasm.operands[0].type = WASM_OP_INT7;
+ MI->flat_insn->detail->wasm.operands[0].size = 1;
+ MI->flat_insn->detail->wasm.operands[0].int7 = MI->wasm_data.int7;
+ }
+
+ *param_size = len;
+
+ return true;
+}
+
+bool WASM_getInstruction(csh ud, const uint8_t *code, size_t code_len,
+ MCInst *MI, uint16_t *size, uint64_t address, void *inst_info)
+{
+ unsigned char opcode;
+ uint16_t param_size;
+
+ if (code_len == 0)
+ return false;
+
+ opcode = code[0];
+ if (opcodes[opcode] == -1) {
+ // invalid opcode
+ return false;
+ }
+
+ // valid opcode
+ MI->address = address;
+ MI->OpcodePub = MI->Opcode = opcode;
+
+ if (MI->flat_insn->detail) {
+ memset(MI->flat_insn->detail, 0, offsetof(cs_detail, wasm)+sizeof(cs_wasm));
+ WASM_get_insn_id((cs_struct *)ud, MI->flat_insn, opcode);
+ }
+
+ // setup groups
+ switch(opcode) {
+ default:
+ return false;
+
+ case WASM_INS_I32_CONST:
+ if (code_len == 1 || !read_varuint32(&code[1], code_len - 1, &param_size, MI)) {
+ return false;
+ }
+
+ if (MI->flat_insn->detail) {
+ MI->flat_insn->detail->wasm.op_count = 1;
+ MI->flat_insn->detail->groups[MI->flat_insn->detail->groups_count] = WASM_GRP_NUMBERIC;
+ MI->flat_insn->detail->groups_count++;
+ }
+
+ *size = param_size + 1;
+
+ break;
+
+ case WASM_INS_I64_CONST:
+ if (code_len == 1 || !read_varuint64(&code[1], code_len - 1, &param_size, MI)) {
+ return false;
+ }
+
+ if (MI->flat_insn->detail) {
+ MI->flat_insn->detail->wasm.op_count = 1;
+ MI->flat_insn->detail->groups[MI->flat_insn->detail->groups_count] = WASM_GRP_NUMBERIC;
+ MI->flat_insn->detail->groups_count++;
+ }
+
+ *size = param_size + 1;
+
+ break;
+
+ case WASM_INS_F32_CONST:
+ if (code_len == 1 || !read_uint32(&code[1], code_len - 1, &param_size, MI)) {
+ return false;
+ }
+
+ if (MI->flat_insn->detail) {
+ MI->flat_insn->detail->wasm.op_count = 1;
+ MI->flat_insn->detail->groups[MI->flat_insn->detail->groups_count] = WASM_GRP_NUMBERIC;
+ MI->flat_insn->detail->groups_count++;
+ }
+
+ *size = param_size + 1;
+
+ break;
+
+ case WASM_INS_F64_CONST:
+ if (code_len == 1 || !read_uint64(&code[1], code_len - 1, &param_size, MI)) {
+ return false;
+ }
+
+ if (MI->flat_insn->detail) {
+ MI->flat_insn->detail->wasm.op_count = 1;
+ MI->flat_insn->detail->groups[MI->flat_insn->detail->groups_count] = WASM_GRP_NUMBERIC;
+ MI->flat_insn->detail->groups_count++;
+ }
+
+ *size = param_size + 1;
+
+ break;
+
+ case WASM_INS_I32_EQZ:
+ case WASM_INS_I32_EQ:
+ case WASM_INS_I32_NE:
+ case WASM_INS_I32_LT_S:
+ case WASM_INS_I32_LT_U:
+ case WASM_INS_I32_GT_S:
+ case WASM_INS_I32_GT_U:
+ case WASM_INS_I32_LE_S:
+ case WASM_INS_I32_LE_U:
+ case WASM_INS_I32_GE_S:
+ case WASM_INS_I32_GE_U:
+ case WASM_INS_I64_EQZ:
+ case WASM_INS_I64_EQ:
+ case WASM_INS_I64_NE:
+ case WASM_INS_I64_LT_S:
+ case WASM_INS_I64_LT_U:
+ case WASN_INS_I64_GT_S:
+ case WASM_INS_I64_GT_U:
+ case WASM_INS_I64_LE_S:
+ case WASM_INS_I64_LE_U:
+ case WASM_INS_I64_GE_S:
+ case WASM_INS_I64_GE_U:
+ case WASM_INS_F32_EQ:
+ case WASM_INS_F32_NE:
+ case WASM_INS_F32_LT:
+ case WASM_INS_F32_GT:
+ case WASM_INS_F32_LE:
+ case WASM_INS_F32_GE:
+ case WASM_INS_F64_EQ:
+ case WASM_INS_F64_NE:
+ case WASM_INS_F64_LT:
+ case WASM_INS_F64_GT:
+ case WASM_INS_F64_LE:
+ case WASM_INS_F64_GE:
+ case WASM_INS_I32_CLZ:
+ case WASM_INS_I32_CTZ:
+ case WASM_INS_I32_POPCNT:
+ case WASM_INS_I32_ADD:
+ case WASM_INS_I32_SUB:
+ case WASM_INS_I32_MUL:
+ case WASM_INS_I32_DIV_S:
+ case WASM_INS_I32_DIV_U:
+ case WASM_INS_I32_REM_S:
+ case WASM_INS_I32_REM_U:
+ case WASM_INS_I32_AND:
+ case WASM_INS_I32_OR:
+ case WASM_INS_I32_XOR:
+ case WASM_INS_I32_SHL:
+ case WASM_INS_I32_SHR_S:
+ case WASM_INS_I32_SHR_U:
+ case WASM_INS_I32_ROTL:
+ case WASM_INS_I32_ROTR:
+ case WASM_INS_I64_CLZ:
+ case WASM_INS_I64_CTZ:
+ case WASM_INS_I64_POPCNT:
+ case WASM_INS_I64_ADD:
+ case WASM_INS_I64_SUB:
+ case WASM_INS_I64_MUL:
+ case WASM_INS_I64_DIV_S:
+ case WASM_INS_I64_DIV_U:
+ case WASM_INS_I64_REM_S:
+ case WASM_INS_I64_REM_U:
+ case WASM_INS_I64_AND:
+ case WASM_INS_I64_OR:
+ case WASM_INS_I64_XOR:
+ case WASM_INS_I64_SHL:
+ case WASM_INS_I64_SHR_S:
+ case WASM_INS_I64_SHR_U:
+ case WASM_INS_I64_ROTL:
+ case WASM_INS_I64_ROTR:
+ case WASM_INS_F32_ABS:
+ case WASM_INS_F32_NEG:
+ case WASM_INS_F32_CEIL:
+ case WASM_INS_F32_FLOOR:
+ case WASM_INS_F32_TRUNC:
+ case WASM_INS_F32_NEAREST:
+ case WASM_INS_F32_SQRT:
+ case WASM_INS_F32_ADD:
+ case WASM_INS_F32_SUB:
+ case WASM_INS_F32_MUL:
+ case WASM_INS_F32_DIV:
+ case WASM_INS_F32_MIN:
+ case WASM_INS_F32_MAX:
+ case WASM_INS_F32_COPYSIGN:
+ case WASM_INS_F64_ABS:
+ case WASM_INS_F64_NEG:
+ case WASM_INS_F64_CEIL:
+ case WASM_INS_F64_FLOOR:
+ case WASM_INS_F64_TRUNC:
+ case WASM_INS_F64_NEAREST:
+ case WASM_INS_F64_SQRT:
+ case WASM_INS_F64_ADD:
+ case WASM_INS_F64_SUB:
+ case WASM_INS_F64_MUL:
+ case WASM_INS_F64_DIV:
+ case WASM_INS_F64_MIN:
+ case WASM_INS_F64_MAX:
+ case WASM_INS_F64_COPYSIGN:
+ case WASM_INS_I32_WARP_I64:
+ case WASP_INS_I32_TRUNC_S_F32:
+ case WASM_INS_I32_TRUNC_U_F32:
+ case WASM_INS_I32_TRUNC_S_F64:
+ case WASM_INS_I32_TRUNC_U_F64:
+ case WASM_INS_I64_EXTEND_S_I32:
+ case WASM_INS_I64_EXTEND_U_I32:
+ case WASM_INS_I64_TRUNC_S_F32:
+ case WASM_INS_I64_TRUNC_U_F32:
+ case WASM_INS_I64_TRUNC_S_F64:
+ case WASM_INS_I64_TRUNC_U_F64:
+ case WASM_INS_F32_CONVERT_S_I32:
+ case WASM_INS_F32_CONVERT_U_I32:
+ case WASM_INS_F32_CONVERT_S_I64:
+ case WASM_INS_F32_CONVERT_U_I64:
+ case WASM_INS_F32_DEMOTE_F64:
+ case WASM_INS_F64_CONVERT_S_I32:
+ case WASM_INS_F64_CONVERT_U_I32:
+ case WASM_INS_F64_CONVERT_S_I64:
+ case WASM_INS_F64_CONVERT_U_I64:
+ case WASM_INS_F64_PROMOTE_F32:
+ case WASM_INS_I32_REINTERPRET_F32:
+ case WASM_INS_I64_REINTERPRET_F64:
+ case WASM_INS_F32_REINTERPRET_I32:
+ case WASM_INS_F64_REINTERPRET_I64:
+ MI->wasm_data.type = WASM_OP_NONE;
+
+ if (MI->flat_insn->detail) {
+ MI->flat_insn->detail->wasm.op_count = 0;
+ MI->flat_insn->detail->groups[MI->flat_insn->detail->groups_count] = WASM_GRP_NUMBERIC;
+ MI->flat_insn->detail->groups_count++;
+ }
+
+ *size = 1;
+
+ break;
+
+ case WASM_INS_DROP:
+ case WASM_INS_SELECT:
+ MI->wasm_data.type = WASM_OP_NONE;
+
+ if (MI->flat_insn->detail) {
+ MI->flat_insn->detail->wasm.op_count = 0;
+ MI->flat_insn->detail->groups[MI->flat_insn->detail->groups_count] = WASM_GRP_PARAMETRIC;
+ MI->flat_insn->detail->groups_count++;
+ }
+
+ *size = 1;
+
+ break;
+
+ case WASM_INS_GET_LOCAL:
+ case WASM_INS_SET_LOCAL:
+ case WASM_INS_TEE_LOCAL:
+ case WASM_INS_GET_GLOBAL:
+ case WASM_INS_SET_GLOBAL:
+ if (code_len == 1 || !read_varuint32(&code[1], code_len - 1, &param_size, MI)) {
+ return false;
+ }
+
+ if (MI->flat_insn->detail) {
+ MI->flat_insn->detail->wasm.op_count = 1;
+ MI->flat_insn->detail->groups[MI->flat_insn->detail->groups_count] = WASM_GRP_VARIABLE;
+ MI->flat_insn->detail->groups_count++;
+ }
+
+ *size = param_size + 1;
+
+ break;
+
+ case WASM_INS_I32_LOAD:
+ case WASM_INS_I64_LOAD:
+ case WASM_INS_F32_LOAD:
+ case WASM_INS_F64_LOAD:
+ case WASM_INS_I32_LOAD8_S:
+ case WASM_INS_I32_LOAD8_U:
+ case WASM_INS_I32_LOAD16_S:
+ case WASM_INS_I32_LOAD16_U:
+ case WASM_INS_I64_LOAD8_S:
+ case WASM_INS_I64_LOAD8_U:
+ case WASM_INS_I64_LOAD16_S:
+ case WASM_INS_I64_LOAD16_U:
+ case WASM_INS_I64_LOAD32_S:
+ case WASM_INS_I64_LOAD32_U:
+ case WASM_INS_I32_STORE:
+ case WASM_INS_I64_STORE:
+ case WASM_INS_F32_STORE:
+ case WASM_INS_F64_STORE:
+ case WASM_INS_I32_STORE8:
+ case WASM_INS_I32_STORE16:
+ case WASM_INS_I64_STORE8:
+ case WASM_INS_I64_STORE16:
+ case WASM_INS_I64_STORE32:
+ if (code_len == 1 || !read_memoryimmediate(&code[1], code_len - 1, &param_size, MI)) {
+ return false;
+ }
+
+ if (MI->flat_insn->detail) {
+ MI->flat_insn->detail->wasm.op_count = 2;
+ MI->flat_insn->detail->groups[MI->flat_insn->detail->groups_count] = WASM_GRP_MEMORY;
+ MI->flat_insn->detail->groups_count++;
+ }
+
+ *size = param_size + 1;
+
+ break;
+
+ case WASM_INS_CURRENT_MEMORY:
+ case WASM_INS_GROW_MEMORY:
+ MI->wasm_data.type = WASM_OP_NONE;
+
+ if (MI->flat_insn->detail) {
+ MI->flat_insn->detail->wasm.op_count = 0;
+ MI->flat_insn->detail->groups[MI->flat_insn->detail->groups_count] = WASM_GRP_MEMORY;
+ MI->flat_insn->detail->groups_count++;
+ }
+
+ *size = 1;
+
+ break;
+
+ case WASM_INS_UNREACHABLE:
+ case WASM_INS_NOP:
+ case WASM_INS_ELSE:
+ case WASM_INS_END:
+ case WASM_INS_RETURN:
+ MI->wasm_data.type = WASM_OP_NONE;
+
+ if (MI->flat_insn->detail) {
+ MI->flat_insn->detail->wasm.op_count = 0;
+ MI->flat_insn->detail->groups[MI->flat_insn->detail->groups_count] = WASM_GRP_CONTROL;
+ MI->flat_insn->detail->groups_count++;
+ }
+
+ *size = 1;
+
+ break;
+
+ case WASM_INS_BLOCK:
+ case WASM_INS_LOOP:
+ case WASM_INS_IF:
+ if (code_len == 1 || !read_varint7(&code[1], code_len - 1, &param_size, MI)) {
+ return false;
+ }
+
+ if (MI->flat_insn->detail) {
+ MI->flat_insn->detail->wasm.op_count = 1;
+ MI->flat_insn->detail->groups[MI->flat_insn->detail->groups_count] = WASM_GRP_CONTROL;
+ MI->flat_insn->detail->groups_count++;
+ }
+
+ *size = param_size + 1;
+
+ break;
+
+ case WASM_INS_BR:
+ case WASM_INS_BR_IF:
+ case WASM_INS_CALL:
+ case WASM_INS_CALL_INDIRECT:
+ if (code_len == 1 || !read_varuint32(&code[1], code_len - 1, &param_size, MI)) {
+ return false;
+ }
+
+ if (MI->flat_insn->detail) {
+ MI->flat_insn->detail->wasm.op_count = 1;
+ MI->flat_insn->detail->groups[MI->flat_insn->detail->groups_count] = WASM_GRP_CONTROL;
+ MI->flat_insn->detail->groups_count++;
+ }
+
+ *size = param_size + 1;
+
+ break;
+
+ case WASM_INS_BR_TABLE:
+ if (code_len == 1 || !read_brtable(&code[1], code_len - 1, &param_size, MI)) {
+ return false;
+ }
+
+ if (MI->flat_insn->detail) {
+ MI->flat_insn->detail->wasm.op_count = 1;
+ MI->flat_insn->detail->groups[MI->flat_insn->detail->groups_count] = WASM_GRP_CONTROL;
+ MI->flat_insn->detail->groups_count++;
+ }
+
+ *size = param_size + 1;
+
+ break;
+ }
+
+ return true;
+}
diff --git a/capstone/arch/WASM/WASMDisassembler.h b/capstone/arch/WASM/WASMDisassembler.h
new file mode 100644
index 000000000..ca79a7ffd
--- /dev/null
+++ b/capstone/arch/WASM/WASMDisassembler.h
@@ -0,0 +1,12 @@
+/* Capstone Disassembly Engine */
+/* By Spike, xwings 2019 */
+
+#ifndef CS_WASMDISASSEMBLER_H
+#define CS_WASMDISASSEMBLER_H
+
+#include "../../MCInst.h"
+
+bool WASM_getInstruction(csh ud, const uint8_t *code, size_t code_len,
+ MCInst *instr, uint16_t *size, uint64_t address, void *info);
+
+#endif
diff --git a/capstone/arch/WASM/WASMInstPrinter.c b/capstone/arch/WASM/WASMInstPrinter.c
new file mode 100644
index 000000000..6cd76fa3f
--- /dev/null
+++ b/capstone/arch/WASM/WASMInstPrinter.c
@@ -0,0 +1,47 @@
+/* Capstone Disassembly Engine */
+/* By Spike, xwings 2019 */
+
+#include "WASMInstPrinter.h"
+#include "WASMMapping.h"
+
+
+void WASM_printInst(MCInst *MI, struct SStream *O, void *PrinterInfo)
+{
+ SStream_concat(O, WASM_insn_name((csh)MI->csh, MI->Opcode));
+
+ switch (MI->wasm_data.type) {
+ default:
+ break;
+
+ case WASM_OP_VARUINT32:
+ SStream_concat(O, "\t0x%x", MI->wasm_data.varuint32);
+ break;
+
+ case WASM_OP_VARUINT64:
+ SStream_concat(O, "\t0x%lx", MI->wasm_data.varuint64);
+ break;
+
+ case WASM_OP_UINT32:
+ SStream_concat(O, "\t0x%2" PRIx32, MI->wasm_data.uint32);
+ break;
+
+ case WASM_OP_UINT64:
+ SStream_concat(O, "\t0x%2" PRIx64, MI->wasm_data.uint64);
+ break;
+
+ case WASM_OP_IMM:
+ SStream_concat(O, "\t0x%x, 0x%x", MI->wasm_data.immediate[0], MI->wasm_data.immediate[1]);
+ break;
+
+ case WASM_OP_INT7:
+ SStream_concat(O, "\t%d", MI->wasm_data.int7);
+ break;
+
+ case WASM_OP_BRTABLE:
+ SStream_concat(O, "\t0x%x, [", MI->wasm_data.brtable.length);
+ SStream_concat(O, "0x%x", MI->wasm_data.brtable.address);
+ SStream_concat(O, "], 0x%x", MI->wasm_data.brtable.default_target);
+
+ break;
+ }
+}
diff --git a/capstone/arch/WASM/WASMInstPrinter.h b/capstone/arch/WASM/WASMInstPrinter.h
new file mode 100644
index 000000000..eaaaaf719
--- /dev/null
+++ b/capstone/arch/WASM/WASMInstPrinter.h
@@ -0,0 +1,18 @@
+/* Capstone Disassembly Engine */
+/* By Spike, xwings 2019 */
+
+#ifndef CS_WASMINSTPRINTER_H
+#define CS_WASMINSTPRINTER_H
+
+
+#include "capstone/capstone.h"
+#include "../../MCInst.h"
+#include "../../SStream.h"
+#include "../../cs_priv.h"
+
+struct SStream;
+
+void WASM_printInst(MCInst *MI, struct SStream *O, void *Info);
+void printOperand(MCInst *MI, unsigned OpNo, SStream *O);
+
+#endif
diff --git a/capstone/arch/WASM/WASMMapping.c b/capstone/arch/WASM/WASMMapping.c
new file mode 100644
index 000000000..88a6f513b
--- /dev/null
+++ b/capstone/arch/WASM/WASMMapping.c
@@ -0,0 +1,333 @@
+/* Capstone Disassembly Engine */
+/* By Spike, xwings 2019 */
+
+#ifdef CAPSTONE_HAS_WASM
+
+#include <string.h>
+
+#include "../../cs_priv.h"
+#include "../../utils.h"
+
+#include "WASMMapping.h"
+
+// fill in details
+void WASM_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id)
+{
+ insn->id = id;
+}
+
+#ifndef CAPSTONE_DIET
+static const name_map insn_name_maps[256] = {
+ { WASM_INS_UNREACHABLE, "unreachable" },
+ { WASM_INS_NOP, "nop" },
+ { WASM_INS_BLOCK, "block" },
+ { WASM_INS_LOOP, "loop" },
+ { WASM_INS_IF, "if" },
+ { WASM_INS_ELSE, "else" },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_END, "end" },
+ { WASM_INS_BR, "br" },
+ { WASM_INS_BR_IF, "br_if" },
+ { WASM_INS_BR_TABLE, "br_table" },
+ { WASM_INS_RETURN, "return" },
+ { WASM_INS_CALL, "call" },
+ { WASM_INS_CALL_INDIRECT, "call_indirect" },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_DROP, "drop" },
+ { WASM_INS_SELECT, "select" },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_GET_LOCAL, "get_local" },
+ { WASM_INS_SET_LOCAL, "set_local" },
+ { WASM_INS_TEE_LOCAL, "tee_local" },
+ { WASM_INS_GET_GLOBAL, "get_global" },
+ { WASM_INS_SET_GLOBAL, "set_global" },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_I32_LOAD, "i32.load" },
+ { WASM_INS_I64_LOAD, "i64.load" },
+ { WASM_INS_F32_LOAD, "f32.load" },
+ { WASM_INS_F64_LOAD, "f64.load" },
+ { WASM_INS_I32_LOAD8_S, "i32.load8_s" },
+ { WASM_INS_I32_LOAD8_U, "i32.load8_u" },
+ { WASM_INS_I32_LOAD16_S, "i32.load16_s" },
+ { WASM_INS_I32_LOAD16_U, "i32.load16_u" },
+ { WASM_INS_I64_LOAD8_S, "i64.load8_s" },
+ { WASM_INS_I64_LOAD8_U, "i64.load8_u" },
+ { WASM_INS_I64_LOAD16_S, "i64.load16_s" },
+ { WASM_INS_I64_LOAD16_U, "i64.load16_u"},
+ { WASM_INS_I64_LOAD32_S, "i64.load32_s"},
+ { WASM_INS_I64_LOAD32_U, "i64.load32_u" },
+ { WASM_INS_I32_STORE, "i32.store" },
+ { WASM_INS_I64_STORE, "i64.store" },
+ { WASM_INS_F32_STORE, "f32.store" },
+ { WASM_INS_F64_STORE, "f64.store" },
+ { WASM_INS_I32_STORE8, "i32.store8" },
+ { WASM_INS_I32_STORE16, "i32.store16" },
+ { WASM_INS_I64_STORE8, "i64.store8" },
+ { WASM_INS_I64_STORE16, "i64.store16" },
+ { WASM_INS_I64_STORE32, "i64.store32" },
+ { WASM_INS_CURRENT_MEMORY, "current_memory" },
+ { WASM_INS_GROW_MEMORY, "grow_memory" },
+ { WASM_INS_I32_CONST, "i32.const" },
+ { WASM_INS_I64_CONST, "i64.const" },
+ { WASM_INS_F32_CONST, "f32.const" },
+ { WASM_INS_F64_CONST, "f64.const" },
+ { WASM_INS_I32_EQZ, "i32.eqz" },
+ { WASM_INS_I32_EQ, "i32.eq" },
+ { WASM_INS_I32_NE, "i32.ne" },
+ { WASM_INS_I32_LT_S, "i32.lt_s" },
+ { WASM_INS_I32_LT_U, "i32.lt_u" },
+ { WASM_INS_I32_GT_S, "i32.gt_s" },
+ { WASM_INS_I32_GT_U, "i32.gt_u" },
+ { WASM_INS_I32_LE_S, "i32.le_s" },
+ { WASM_INS_I32_LE_U, "i32.le_u" },
+ { WASM_INS_I32_GE_S, "i32.ge_s" },
+ { WASM_INS_I32_GE_U, "i32.ge_u" },
+ { WASM_INS_I64_EQZ, "i64.eqz" },
+ { WASM_INS_I64_EQ, "i64.eq" },
+ { WASM_INS_I64_NE, "i64.ne" },
+ { WASM_INS_I64_LT_S, "i64.lt_s" },
+ { WASM_INS_I64_LT_U, "i64.lt_u" },
+ { WASN_INS_I64_GT_S, "i64.gt_s" },
+ { WASM_INS_I64_GT_U, "i64.gt_u" },
+ { WASM_INS_I64_LE_S, "i64.le_s" },
+ { WASM_INS_I64_LE_U, "i64.le_u" },
+ { WASM_INS_I64_GE_S, "i64.ge_s" },
+ { WASM_INS_I64_GE_U, "i64.ge_u" },
+ { WASM_INS_F32_EQ, "f32.eq" },
+ { WASM_INS_F32_NE, "f32.ne" },
+ { WASM_INS_F32_LT, "f32.lt" },
+ { WASM_INS_F32_GT, "f32.gt" },
+ { WASM_INS_F32_LE, "f32.le" },
+ { WASM_INS_F32_GE, "f32.ge" },
+ { WASM_INS_F64_EQ, "f64.eq" },
+ { WASM_INS_F64_NE, "f64.ne" },
+ { WASM_INS_F64_LT, "f64.lt" },
+ { WASM_INS_F64_GT, "f64.gt" },
+ { WASM_INS_F64_LE, "f64.le" },
+ { WASM_INS_F64_GE, "f64.ge" },
+ { WASM_INS_I32_CLZ, "i32.clz" },
+ { WASM_INS_I32_CTZ, "i32.ctz" },
+ { WASM_INS_I32_POPCNT, "i32.popcnt" },
+ { WASM_INS_I32_ADD, "i32.add" },
+ { WASM_INS_I32_SUB, "i32.sub" },
+ { WASM_INS_I32_MUL, "i32.mul" },
+ { WASM_INS_I32_DIV_S, "i32.div_s" },
+ { WASM_INS_I32_DIV_U, "i32.div_u" },
+ { WASM_INS_I32_REM_S, "i32.rem_s" },
+ { WASM_INS_I32_REM_U, "i32.rem_u" },
+ { WASM_INS_I32_AND, "i32.and" },
+ { WASM_INS_I32_OR, "i32.or" },
+ { WASM_INS_I32_XOR, "i32.xor" },
+ { WASM_INS_I32_SHL, "i32.shl" },
+ { WASM_INS_I32_SHR_S, "i32.shr_s" },
+ { WASM_INS_I32_SHR_U, "i32.shr_u" },
+ { WASM_INS_I32_ROTL, "i32.rotl" },
+ { WASM_INS_I32_ROTR, "i32.rotr" },
+ { WASM_INS_I64_CLZ, "i64.clz" },
+ { WASM_INS_I64_CTZ, "i64.ctz" },
+ { WASM_INS_I64_POPCNT, "i64.popcnt" },
+ { WASM_INS_I64_ADD, "i64.add" },
+ { WASM_INS_I64_SUB, "i64.sub" },
+ { WASM_INS_I64_MUL, "i64.mul" },
+ { WASM_INS_I64_DIV_S, "i64.div_s" },
+ { WASM_INS_I64_DIV_U, "i64.div_u" },
+ { WASM_INS_I64_REM_S, "i64.rem_s" },
+ { WASM_INS_I64_REM_U, "i64.rem_u" },
+ { WASM_INS_I64_AND, "i64.and" },
+ { WASM_INS_I64_OR, "i64.or" },
+ { WASM_INS_I64_XOR, "i64.xor" },
+ { WASM_INS_I64_SHL, "i64.shl" },
+ { WASM_INS_I64_SHR_S, "i64.shr_s" },
+ { WASM_INS_I64_SHR_U, "i64.shr_u" },
+ { WASM_INS_I64_ROTL, "i64.rotl" },
+ { WASM_INS_I64_ROTR, "i64.rotr" },
+ { WASM_INS_F32_ABS, "f32.abs" },
+ { WASM_INS_F32_NEG, "f32.neg" },
+ { WASM_INS_F32_CEIL, "f32.ceil" },
+ { WASM_INS_F32_FLOOR, "f32.floor" },
+ { WASM_INS_F32_TRUNC, "f32.trunc" },
+ { WASM_INS_F32_NEAREST, "f32.nearest" },
+ { WASM_INS_F32_SQRT, "f32.sqrt" },
+ { WASM_INS_F32_ADD, "f32.add" },
+ { WASM_INS_F32_SUB, "f32.sub" },
+ { WASM_INS_F32_MUL, "f32.mul" },
+ { WASM_INS_F32_DIV, "f32.div" },
+ { WASM_INS_F32_MIN, "f32.min" },
+ { WASM_INS_F32_MAX, "f32.max" },
+ { WASM_INS_F32_COPYSIGN, "f32.copysign" },
+ { WASM_INS_F64_ABS, "f64.abs" },
+ { WASM_INS_F64_NEG, "f64.neg" },
+ { WASM_INS_F64_CEIL, "f64.ceil" },
+ { WASM_INS_F64_FLOOR, "f64.floor" },
+ { WASM_INS_F64_TRUNC, "f64.trunc" },
+ { WASM_INS_F64_NEAREST, "f64.nearest" },
+ { WASM_INS_F64_SQRT, "f64.sqrt" },
+ { WASM_INS_F64_ADD, "f64.add" },
+ { WASM_INS_F64_SUB, "f64.sub" },
+ { WASM_INS_F64_MUL, "f64.mul" },
+ { WASM_INS_F64_DIV, "f64.div" },
+ { WASM_INS_F64_MIN, "f64.min" },
+ { WASM_INS_F64_MAX, "f64.max" },
+ { WASM_INS_F64_COPYSIGN, "f64.copysign" },
+ { WASM_INS_I32_WARP_I64, "i32.warp/i64" },
+ { WASP_INS_I32_TRUNC_S_F32, "i32.trunc_s/f32" },
+ { WASM_INS_I32_TRUNC_U_F32, "i32.trunc_u/f32" },
+ { WASM_INS_I32_TRUNC_S_F64, "i32/trunc_s/f64" },
+ { WASM_INS_I32_TRUNC_U_F64, "i32/trunc_u/f64" },
+ { WASM_INS_I64_EXTEND_S_I32, "i64/extend_s/i32" },
+ { WASM_INS_I64_EXTEND_U_I32, "i64/extend_u/i32" },
+ { WASM_INS_I64_TRUNC_S_F32, "i64.trunc_s/f32" },
+ { WASM_INS_I64_TRUNC_U_F32, "i64.trunc_u/f32" },
+ { WASM_INS_I64_TRUNC_S_F64, "f64.trunc_s/f64" },
+ { WASM_INS_I64_TRUNC_U_F64, "f64.trunc_u/f64" },
+ { WASM_INS_F32_CONVERT_S_I32, "f32.convert_s/i32" },
+ { WASM_INS_F32_CONVERT_U_I32, "f32.convert_u/i32" },
+ { WASM_INS_F32_CONVERT_S_I64, "f32.convert_s/i64" },
+ { WASM_INS_F32_CONVERT_U_I64, "f32.convert_u/i64" },
+ { WASM_INS_F32_DEMOTE_F64, "f32.demote/f64" },
+ { WASM_INS_F64_CONVERT_S_I32, "f64.convert_s/i32" },
+ { WASM_INS_F64_CONVERT_U_I32, "f64.convert_u/i32" },
+ { WASM_INS_F64_CONVERT_S_I64, "f64.convert_s/i64" },
+ { WASM_INS_F64_CONVERT_U_I64, "f64.convert_u/i64" },
+ { WASM_INS_F64_PROMOTE_F32, "f64.promote/f32" },
+ { WASM_INS_I32_REINTERPRET_F32, "i32.reinterpret/f32" },
+ { WASM_INS_I64_REINTERPRET_F64, "i64.reinterpret/f64" },
+ { WASM_INS_F32_REINTERPRET_I32, "f32.reinterpret/i32" },
+ { WASM_INS_F64_REINTERPRET_I64, "f64.reinterpret/i64" },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+ { WASM_INS_INVALID, NULL },
+};
+#endif
+
+const char *WASM_insn_name(csh handle, unsigned int id)
+{
+#ifndef CAPSTONE_DIET
+ if (id >= ARR_SIZE(insn_name_maps))
+ return NULL;
+ else
+ return insn_name_maps[id].name;
+#else
+ return NULL;
+#endif
+}
+
+#ifndef CAPSTONE_DIET
+static const name_map group_name_maps[] = {
+ // generic groups
+ { WASM_GRP_INVALID, NULL },
+ // special groups
+ { WASM_GRP_NUMBERIC, "numberic"},
+ { WASM_GRP_PARAMETRIC, "parametric"},
+ { WASM_GRP_VARIABLE, "variable"},
+ { WASM_GRP_MEMORY, "memory"},
+ { WASM_GRP_CONTROL, "control"},
+};
+#endif
+
+#ifndef CAPSTONE_DIET
+static const name_map kind_name_maps[] = {
+ { WASM_OP_INVALID, "Invalid" },
+ { WASM_OP_NONE, "None" },
+ { WASM_OP_INT7, "uint7" },
+ { WASM_OP_VARUINT32, "varuint32" },
+ { WASM_OP_VARUINT64, "varuint64" },
+ { WASM_OP_UINT32, "uint32" },
+ { WASM_OP_UINT64, "uint64" },
+};
+#endif
+
+const char *WASM_kind_name(unsigned int id){
+#ifndef CAPSTONE_DIET
+ return id2name(kind_name_maps, ARR_SIZE(kind_name_maps), id);
+#else
+ return NULL;
+#endif
+}
+
+const char *WASM_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
+}
+#endif
diff --git a/capstone/arch/WASM/WASMMapping.h b/capstone/arch/WASM/WASMMapping.h
new file mode 100644
index 000000000..f00f5afa5
--- /dev/null
+++ b/capstone/arch/WASM/WASMMapping.h
@@ -0,0 +1,9 @@
+/* Capstone Disassembly Engine */
+/* By Spike, xwings 2019 */
+
+#include <capstone/capstone.h>
+
+void WASM_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id);
+const char *WASM_insn_name(csh handle, unsigned int id);
+const char *WASM_group_name(csh handle, unsigned int id);
+const char *WASM_kind_name(unsigned int id);
diff --git a/capstone/arch/WASM/WASMModule.c b/capstone/arch/WASM/WASMModule.c
new file mode 100644
index 000000000..277bd4249
--- /dev/null
+++ b/capstone/arch/WASM/WASMModule.c
@@ -0,0 +1,33 @@
+/* Capstone Disassembly Engine */
+/* By Spike, xwings 2019 */
+
+#ifdef CAPSTONE_HAS_WASM
+
+#include "../../cs_priv.h"
+#include "WASMDisassembler.h"
+#include "WASMInstPrinter.h"
+#include "WASMMapping.h"
+#include "WASMModule.h"
+
+cs_err WASM_global_init(cs_struct *ud)
+{
+ // verify if requested mode is valid
+ if (ud->mode)
+ return CS_ERR_MODE;
+
+ ud->printer = WASM_printInst;
+ ud->printer_info = NULL;
+ ud->insn_id = WASM_get_insn_id;
+ ud->insn_name = WASM_insn_name;
+ ud->group_name = WASM_group_name;
+ ud->disasm = WASM_getInstruction;
+
+ return CS_ERR_OK;
+}
+
+cs_err WASM_option(cs_struct *handle, cs_opt_type type, size_t value)
+{
+ return CS_ERR_OPTION;
+}
+
+#endif
diff --git a/capstone/arch/WASM/WASMModule.h b/capstone/arch/WASM/WASMModule.h
new file mode 100644
index 000000000..e6201c866
--- /dev/null
+++ b/capstone/arch/WASM/WASMModule.h
@@ -0,0 +1,12 @@
+/* Capstone Disassembly Engine */
+/* By Spike, xwings 2019 */
+
+#ifndef CS_WASM_MODULE_H
+#define CS_WASM_MODULE_H
+
+#include "../../utils.h"
+
+cs_err WASM_global_init(cs_struct *ud);
+cs_err WASM_option(cs_struct *handle, cs_opt_type type, size_t value);
+
+#endif