Move anal.evm.cs into arch.evm ##arch

* First capstone plugin to be moved, without globals and such
This commit is contained in:
pancake 2023-01-29 23:53:40 +01:00 committed by pancake
parent 3089ada0b9
commit 516fbc5a94
13 changed files with 671 additions and 100 deletions

View File

@ -16,7 +16,7 @@ anal.cr16
anal.cris
anal.dalvik
anal.ebc
anal.evm_cs
arch.evm
anal.gb
anal.h8300
anal.hppa_gnu

View File

@ -70,7 +70,6 @@ r_anal_sources = [
'../asm/arch/cris/gnu/cris-opc.c',
'p/anal_dalvik.c',
'p/anal_ebc.c',
'p/anal_evm_cs.c',
'p/anal_gb.c',
'p/anal_h8300.c',
'p/anal_i8080.c',

View File

@ -1,12 +0,0 @@
OBJ_EVM_CS=anal_evm_cs.o
include $(CURDIR)capstone.mk
STATIC_OBJ+=$(OBJ_EVM_CS)
TARGET_EVM_CS=anal_evm_cs.${EXT_SO}
ALL_TARGETS+=${TARGET_EVM_CS}
${TARGET_EVM_CS}: ${OBJ_EVM_CS}
${CC} ${CFLAGS} $(call libname,anal_evm_cs) $(CS_CFLAGS) \
-o anal_evm_cs.${EXT_SO} ${OBJ_EVM_CS} $(CS_LDFLAGS)

View File

@ -6,6 +6,7 @@ R2DEPS+=r_util r_reg
CFLAGS+=-DR2_PLUGIN_INCORE
CFLAGS:=-I.. -I$(LTOP)/asm/arch/include -DR2_PLUGIN_INCORE -Iarch -I$(TOP)/shlr $(CFLAGS)
LDFLAGS+=$(CS_LDFLAGS)
.PHONY: pre
pre: p v35pre

View File

@ -1,18 +1,6 @@
/* radare2 - LGPL - Copyright 2022 - pancake */
/* radare2 - LGPL - Copyright 2022-2023 - pancake */
#include <r_arch.h>
#include <r_util.h>
#if 0
// pseudocode
var a = arch.session("x86", {bits: 64});
var op = new RArchOp ();
op.setBytes("\x90");
if (!a.decode(op)) {
println("cannot decode");
}
printfln (a.mnemonic);
#endif
R_API RArchSession *r_arch_session(RArch *arch, RArchConfig *cfg, RArchPlugin *ap) {
RArchSession *ai = R_NEW0 (RArchSession);

View File

@ -7,6 +7,7 @@ r_arch_sources = [
'arch_cond.c',
'arch_value.c',
'p/null/plugin.c',
'p/evm/plugin.c',
'p/propeller/plugin.c',
'p/propeller/propeller_disas.c',
'p/arm/plugin.c',

116
libr/arch/p/capstone.inc Normal file
View File

@ -0,0 +1,116 @@
#ifndef CSINC
#error Undefined CSINC
#endif
#ifndef CSINC_MODE
#define CSINC_MODE 0
#endif
#define TOKEN_PASTE(x, y) x ## y
#define CSINC_INS_ENDING CSINC_INS_ENDING_(CSINC)
#define CSINC_INS_ENDING_(y) TOKEN_PASTE(y, _INS_ENDING)
#define CSINC_ARCH CSINC_ARCH_(CSINC)
#define CSINC_ARCH_(y) TOKEN_PASTE(CS_ARCH_, y)
static void initcs(csh *ud) {
cs_opt_mem mem = {
.malloc = malloc,
.calloc = calloc,
.realloc = realloc,
.free = free,
.vsnprintf = vsnprintf,
};
cs_option (*ud, CS_OPT_MEM, (size_t)&mem);
}
static bool r_arch_cs_init(RArchSession *as, csh *cs_handle) {
int mode = CSINC_MODE;
initcs (cs_handle);
#if 0
if (mode != a->cs_omode || a->config->bits != a->cs_obits) {
if (a->cs_handle != 0) {
cs_close (&a->cs_handle);
a->cs_handle = 0; // unnecessary
}
a->cs_omode = mode;
a->cs_obits = a->config->bits;
}
#endif
int ret = cs_open (CSINC_ARCH, mode, cs_handle);
if (ret != CS_ERR_OK) {
R_LOG_ERROR ("Capstone failed: cs_open(%#x, %#x): %s", CSINC_ARCH, mode, cs_strerror (ret));
*cs_handle = 0;
} else {
cs_option (*cs_handle, CS_OPT_DETAIL, CS_OPT_ON);
#if CS_API_MAJOR >= 4
cs_option (*cs_handle, CS_OPT_UNSIGNED, CS_OPT_ON);
#endif
}
#if 0
if (*cs_handle) {
if (a->config->syntax == R_ARCH_SYNTAX_ATT) {
cs_option (a->cs_handle, CS_OPT_SYNTAX, CS_OPT_SYNTAX_ATT);
#if CS_API_MAJOR >= 4
} else if (a->config->syntax == R_ARCH_SYNTAX_MASM) {
cs_option (a->cs_handle, CS_OPT_SYNTAX, CS_OPT_SYNTAX_MASM);
#endif
} else {
cs_option (a->cs_handle, CS_OPT_SYNTAX, CS_OPT_SYNTAX_INTEL);
}
}
#endif
return true;
}
static char *r_arch_cs_mnemonics(RArchSession *s, csh cs_handle, int id, bool json) {
int i;
#if 0
csh cs_handle = init_capstone (s->arch);
if (cs_handle == 0) {
a->cs_handle = cs_handle;
return NULL;
}
#endif
PJ *pj = NULL;
if (id != -1) {
const char *name = cs_insn_name (cs_handle, id);
if (name) {
if (json) {
pj = pj_new ();
pj_a (pj);
pj_s (pj, name);
pj_end (pj);
return pj_drain (pj);
}
return strdup (name);
}
return NULL;
}
RStrBuf *buf = NULL;
if (json) {
pj = pj_new ();
pj_a (pj);
} else {
buf = r_strbuf_new ("");
}
for (i = 1; i < CSINC_INS_ENDING; i++) {
const char *op = cs_insn_name (cs_handle, i);
if (!op) {
continue;
}
if (pj) {
pj_s (pj, op);
} else {
r_strbuf_append (buf, op);
r_strbuf_append (buf, "\n");
}
}
if (pj) {
pj_end (pj);
}
return pj? pj_drain (pj): r_strbuf_drain (buf);
}

12
libr/arch/p/evm.mk Normal file
View File

@ -0,0 +1,12 @@
OBJ_EVM=p/evm/plugin.o
include $(CURDIR)/p/capstone.mk
STATIC_OBJ+=$(OBJ_EVM)
TARGET_EVM=arch_evm.${EXT_SO}
ALL_TARGETS+=${TARGET_EVM}
${TARGET_EVM}: ${OBJ_EVM}
${CC} ${CFLAGS} $(call libname,arch_evm) $(CS_CFLAGS) \
-o arch_evm.${EXT_SO} ${OBJ_EVM} $(CS_LDFLAGS)

264
libr/arch/p/evm/evm.c Normal file
View File

@ -0,0 +1,264 @@
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <stdarg.h>
#include <sys/types.h>
#include "evm.h"
static const EvmOpDef opcodes[256] = {
[EVM_OP_STOP] = { "stop", 1 },
[EVM_OP_ADD] = { "add", 1 },
[EVM_OP_MUL] = { "mul", 1 },
[EVM_OP_SUB] = { "sub", 1 },
[EVM_OP_DIV] = { "div", 1 },
[EVM_OP_SDIV] = { "sdiv", 1 },
[EVM_OP_MOD] = { "mod", 1 },
[EVM_OP_SMOD] = { "smod", 1 },
[EVM_OP_ADDMOD] = { "addmod", 1 },
[EVM_OP_MULMOD] = { "mulmod", 1 },
[EVM_OP_EXP] = { "exp", 1 },
[EVM_OP_SIGNEXTEND] = { "signextend", 1 },
[EVM_OP_LT] = { "lt", 1 },
[EVM_OP_GT] = { "gt", 1 },
[EVM_OP_SLT] = { "slt", 1 },
[EVM_OP_SGT] = { "sgt", 1 },
[EVM_OP_EQ] = { "eq", 1 },
[EVM_OP_ISZERO] = { "iszero", 1 },
[EVM_OP_AND] = { "and", 1 },
[EVM_OP_OR] = { "or", 1 },
[EVM_OP_XOR] = { "xor", 1 },
[EVM_OP_NOT] = { "not", 1 },
[EVM_OP_BYTE] = { "byte", 1 },
[EVM_OP_SHL] = { "shl", 1 },
[EVM_OP_SHR] = { "shr", 1 },
[EVM_OP_SAR] = { "sar", 1 },
[EVM_OP_SHA3] = { "sha3", 1 },
[EVM_OP_ADDRESS] = { "address", 1 },
[EVM_OP_BALANCE] = { "balance", 1 },
[EVM_OP_ORIGIN] = { "origin", 1 },
[EVM_OP_CALLER] = { "caller", 1 },
[EVM_OP_CALLVALUE] = { "callvalue", 1 },
[EVM_OP_CALLDATALOAD] = { "calldataload", 1 },
[EVM_OP_CALLDATASIZE] = { "calldatasize", 1 },
[EVM_OP_CALLDATACOPY] = { "calldatacopy", 1 },
[EVM_OP_CODESIZE] = { "codesize", 1 },
[EVM_OP_CODECOPY] = { "codecopy", 1 },
[EVM_OP_GASPRICE] = { "gasprice", 1 },
[EVM_OP_EXTCODESIZE] = { "extcodesize", 1 },
[EVM_OP_EXTCODECOPY] = { "extcodecopy", 1 },
[EVM_OP_RETURNDATASIZE] = { "returndatasize", 1},
[EVM_OP_RETURNDATACOPY] = { "returndatacopy", 1},
[EVM_OP_EXTCODEHASH] = { "extcodehash", 1},
[EVM_OP_BLOCKHASH] = { "blockhash", 1 },
[EVM_OP_COINBASE] = { "coinbase", 1 },
[EVM_OP_TIMESTAMP] = { "timestamp", 1 },
[EVM_OP_NUMBER] = { "number", 1 },
[EVM_OP_DIFFICULTY] = { "difficulty", 1 },
[EVM_OP_GASLIMIT] = { "gaslimit", 1 },
[EVM_OP_CHAINID] = { "chainid", 1 },
[EVM_OP_SELFBALANCE] = { "selfbalance", 1 },
[EVM_OP_POP] = { "pop", 1 },
[EVM_OP_MLOAD] = { "mload", 1 },
[EVM_OP_MSTORE] = { "mstore", 1 },
[EVM_OP_MSTORE8] = { "mstore8", 1 },
[EVM_OP_SLOAD] = { "sload", 1 },
[EVM_OP_SSTORE] = { "sstore", 1 },
[EVM_OP_JUMP] = { "jump", 1 },
[EVM_OP_JUMPI] = { "jumpi", 1 },
[EVM_OP_PC] = { "pc", 1 },
[EVM_OP_MSIZE] = { "msize", 1 },
[EVM_OP_GAS] = { "gas", 1 },
[EVM_OP_JUMPDEST] = { "jumpdest", 1 },
// ....
[EVM_OP_CREATE] = { "create", 1 },
[EVM_OP_CALL] = { "call", 1 },
[EVM_OP_CALLCODE] = { "callcode", 1 },
[EVM_OP_RETURN] = { "return", 1 },
[EVM_OP_DELEGATECALL] = { "delegatecall", 1 },
[EVM_OP_CREATE2] = { "create2", 1 },
[EVM_OP_STATICCALL] = { "staticcall", 1 },
[EVM_OP_REVERT] = { "revert", 1 },
[EVM_OP_INVALID] = { "invalid", 1 },
[EVM_OP_SELFDESTRUCT] = { "selfdestruct", 1 },
};
static void settxtf(EvmOp *op, const char *fmt, ...) {
if (strchr (fmt, '%')) {
va_list ap;
va_start (ap, fmt);
op->txt = op->txt_buf;
vsnprintf (op->txt_buf, sizeof (op->txt_buf), fmt, ap);
va_end (ap);
} else {
op->txt = fmt;
}
}
int evm_asm(const char *str, ut8 *buf, int buf_len) {
int i, len = -1;
for (i = 0; i < 0xff; i++) {
const EvmOpDef *opdef = &opcodes[i];
if (opdef->txt) {
if (!strcmp (opdef->txt, str)) {
buf[0] = i;
// r_strbuf_appendf (buf, "%d", i);
return 1;
}
}
}
// TODO: add support for: push, swap, dup, log
return len;
}
int evm_dis(EvmOp *op, const unsigned char *buf, int buf_len) {
op->len = 1;
op->op = buf[0];
const EvmOpDef *opdef = &opcodes[buf[0]];
if (opdef->txt) {
op->txt = opdef->txt;
op->len = opdef->len;
if (op->len < 1) {
op->len = 1;
}
return op->len;
}
switch (op->op) {
case EVM_OP_PUSH1:
case EVM_OP_PUSH2:
case EVM_OP_PUSH3:
case EVM_OP_PUSH4:
case EVM_OP_PUSH5:
case EVM_OP_PUSH6:
case EVM_OP_PUSH7:
case EVM_OP_PUSH8:
case EVM_OP_PUSH9:
case EVM_OP_PUSH10:
case EVM_OP_PUSH11:
case EVM_OP_PUSH12:
case EVM_OP_PUSH13:
case EVM_OP_PUSH14:
case EVM_OP_PUSH15:
case EVM_OP_PUSH16:
case EVM_OP_PUSH17:
case EVM_OP_PUSH18:
case EVM_OP_PUSH19:
case EVM_OP_PUSH20:
case EVM_OP_PUSH21:
case EVM_OP_PUSH22:
case EVM_OP_PUSH23:
case EVM_OP_PUSH24:
case EVM_OP_PUSH25:
case EVM_OP_PUSH26:
case EVM_OP_PUSH27:
case EVM_OP_PUSH28:
case EVM_OP_PUSH29:
case EVM_OP_PUSH30:
case EVM_OP_PUSH31:
case EVM_OP_PUSH32:
{
int pushSize = buf[0] - EVM_OP_PUSH1;
char hexbuf[64] = {0};
int res = r_hex_bin2str (buf + 1, pushSize + 1, hexbuf);
if (res < 1 || !*hexbuf) {
strcpy (hexbuf, "0");
}
settxtf (op, "push%d 0x%s", pushSize + 1, hexbuf);
op->len = 2 + pushSize;
}
break;
case EVM_OP_DUP1:
case EVM_OP_DUP2:
case EVM_OP_DUP3:
case EVM_OP_DUP4:
case EVM_OP_DUP5:
case EVM_OP_DUP6:
case EVM_OP_DUP7:
case EVM_OP_DUP8:
case EVM_OP_DUP9:
case EVM_OP_DUP10:
case EVM_OP_DUP11:
case EVM_OP_DUP12:
case EVM_OP_DUP13:
case EVM_OP_DUP14:
case EVM_OP_DUP15:
case EVM_OP_DUP16:
{
int dupSize = buf[0] - EVM_OP_DUP1 + 1;
settxtf (op, "dup%d", dupSize);
op->len = 1;
}
break;
case EVM_OP_SWAP1:
case EVM_OP_SWAP2:
case EVM_OP_SWAP3:
case EVM_OP_SWAP4:
case EVM_OP_SWAP5:
case EVM_OP_SWAP6:
case EVM_OP_SWAP7:
case EVM_OP_SWAP8:
case EVM_OP_SWAP9:
case EVM_OP_SWAP10:
case EVM_OP_SWAP11:
case EVM_OP_SWAP12:
case EVM_OP_SWAP13:
case EVM_OP_SWAP14:
case EVM_OP_SWAP15:
case EVM_OP_SWAP16:
{
int swapSize = buf[0] - EVM_OP_SWAP1 + 1;
settxtf (op, "swap%d", swapSize);
op->len = 1;
}
break;
case EVM_OP_LOG0:
case EVM_OP_LOG1:
case EVM_OP_LOG2:
case EVM_OP_LOG3:
case EVM_OP_LOG4:
{
int logSize = buf[0] - EVM_OP_LOG0;
settxtf (op, "log%d", logSize);
op->len = 1;
}
break;
default:
settxtf (op, "unassigned");
op->len = 0;
break;
}
return op->len;
}
typedef const unsigned char *buf_t;
#if HAS_MAIN
int main() {
#if 0
[1] 6060 PUSH1 0x60
[3] 6040 PUSH1 0x40
[4] 52 MSTORE
[5] 36 CALLDATASIZE
[6] 15 ISZERO// WRONG ?? should be 11
[9] PUSH2 0x00da
[10] JUMPI
[12] PUSH1 0xe0
[14] PUSH1 0x02
[15] EXP
#endif
int i;
EvmOp op = {
0
};
buf_t b = (buf_t) "\x60\x60\x60\x40\x52\x36\x15\x61\x00\xda\x57\x60\xe0\x60\x02";
for (i = 0; i < sizeof (b); i++) {
evm_dis (&op, b + i, sizeof (b) - i);
printf ("len=%d op=0x%02x %s\n", op.len, op.op, op.txt);
if (op.len < 1) {
break;
}
i += op.len - 1;
}
return 0;
}
#endif

173
libr/arch/p/evm/evm.h Normal file
View File

@ -0,0 +1,173 @@
#ifndef EVM_EVM_H
#define EVM_EVM_H
#include <r_util.h>
typedef enum {
EVM_OP_STOP = 0x00,
EVM_OP_ADD,
EVM_OP_MUL,
EVM_OP_SUB,
EVM_OP_DIV,
EVM_OP_SDIV,
EVM_OP_MOD,
EVM_OP_SMOD,
EVM_OP_ADDMOD,
EVM_OP_MULMOD,
EVM_OP_EXP,
EVM_OP_SIGNEXTEND,
EVM_OP_LT = 0x10,
EVM_OP_GT,
EVM_OP_SLT,
EVM_OP_SGT,
EVM_OP_EQ,
EVM_OP_ISZERO,
EVM_OP_AND,
EVM_OP_OR,
EVM_OP_XOR,
EVM_OP_NOT,
EVM_OP_BYTE,
EVM_OP_SHL,
EVM_OP_SHR,
EVM_OP_SAR,
EVM_OP_SHA3 = 0x20,
EVM_OP_ADDRESS = 0x30,
EVM_OP_BALANCE,
EVM_OP_ORIGIN,
EVM_OP_CALLER,
EVM_OP_CALLVALUE,
EVM_OP_CALLDATALOAD,
EVM_OP_CALLDATASIZE,
EVM_OP_CALLDATACOPY,
EVM_OP_CODESIZE,
EVM_OP_CODECOPY,
EVM_OP_GASPRICE,
EVM_OP_EXTCODESIZE,
EVM_OP_EXTCODECOPY,
EVM_OP_RETURNDATASIZE,
EVM_OP_RETURNDATACOPY,
EVM_OP_EXTCODEHASH,
EVM_OP_BLOCKHASH,
EVM_OP_COINBASE,
EVM_OP_TIMESTAMP,
EVM_OP_NUMBER,
EVM_OP_DIFFICULTY,
EVM_OP_GASLIMIT,
EVM_OP_CHAINID,
EVM_OP_SELFBALANCE,
EVM_OP_POP = 0x50,
EVM_OP_MLOAD,
EVM_OP_MSTORE,
EVM_OP_MSTORE8,
EVM_OP_SLOAD,
EVM_OP_SSTORE,
EVM_OP_JUMP,
EVM_OP_JUMPI,
EVM_OP_PC,
EVM_OP_MSIZE,
EVM_OP_GAS,
EVM_OP_JUMPDEST,
EVM_OP_PUSH1 = 0x60,
EVM_OP_PUSH2,
EVM_OP_PUSH3,
EVM_OP_PUSH4,
EVM_OP_PUSH5,
EVM_OP_PUSH6,
EVM_OP_PUSH7,
EVM_OP_PUSH8,
EVM_OP_PUSH9,
EVM_OP_PUSH10,
EVM_OP_PUSH11,
EVM_OP_PUSH12,
EVM_OP_PUSH13,
EVM_OP_PUSH14,
EVM_OP_PUSH15,
EVM_OP_PUSH16,
EVM_OP_PUSH17,
EVM_OP_PUSH18,
EVM_OP_PUSH19,
EVM_OP_PUSH20,
EVM_OP_PUSH21,
EVM_OP_PUSH22,
EVM_OP_PUSH23,
EVM_OP_PUSH24,
EVM_OP_PUSH25,
EVM_OP_PUSH26,
EVM_OP_PUSH27,
EVM_OP_PUSH28,
EVM_OP_PUSH29,
EVM_OP_PUSH30,
EVM_OP_PUSH31,
EVM_OP_PUSH32,
EVM_OP_DUP1,
EVM_OP_DUP2,
EVM_OP_DUP3,
EVM_OP_DUP4,
EVM_OP_DUP5,
EVM_OP_DUP6,
EVM_OP_DUP7,
EVM_OP_DUP8,
EVM_OP_DUP9,
EVM_OP_DUP10,
EVM_OP_DUP11,
EVM_OP_DUP12,
EVM_OP_DUP13,
EVM_OP_DUP14,
EVM_OP_DUP15,
EVM_OP_DUP16,
EVM_OP_SWAP1,
EVM_OP_SWAP2,
EVM_OP_SWAP3,
EVM_OP_SWAP4,
EVM_OP_SWAP5,
EVM_OP_SWAP6,
EVM_OP_SWAP7,
EVM_OP_SWAP8,
EVM_OP_SWAP9,
EVM_OP_SWAP10,
EVM_OP_SWAP11,
EVM_OP_SWAP12,
EVM_OP_SWAP13,
EVM_OP_SWAP14,
EVM_OP_SWAP15,
EVM_OP_SWAP16,
EVM_OP_LOG0 = 0xa0,
EVM_OP_LOG1,
EVM_OP_LOG2,
EVM_OP_LOG3,
EVM_OP_LOG4,
EVM_OP_CREATE = 0xf0,
EVM_OP_CALL,
EVM_OP_CALLCODE,
EVM_OP_RETURN,
EVM_OP_DELEGATECALL,
EVM_OP_CREATE2,
EVM_OP_STATICCALL = 0xfa,
EVM_OP_REVERT = 0xfd,
EVM_OP_INVALID,
EVM_OP_SELFDESTRUCT
} EvmOpcodes;
typedef struct EvmOp {
EvmOpcodes op;
int len;
const char *txt;
// Largest opcode is "push32 0x" followed by hex value of 32 bytes.
char txt_buf[9+64+1];
} EvmOp;
typedef struct {
const char *txt;
int len;
} EvmOpDef;
// extern const EvmOpDef opcodes[256];
// int evm_dis(EvmOp *op, const unsigned char *buf, int buf_len);
#endif /* EVM_EVM_H */

View File

@ -1,20 +1,24 @@
/* radare2 - LGPL - Copyright 2022 - pancake, Sylvain Pelissier */
/* radare2 - LGPL - Copyright 2022-2023 - pancake, Sylvain Pelissier */
#define R_LOG_ORIGIN "arch.evm"
#include <r_asm.h>
#include <r_lib.h>
#include "./evm.c"
#include <capstone/capstone.h>
#if CS_API_MAJOR >= 5
#include <capstone/evm.h>
// TODO :Rename CSINC to something meaningful
#define CSINC EVM
#include "capstone.inc"
#include "../capstone.inc"
struct evm_anal_info {
typedef struct {
Sdb *pushs_db;
};
static R_TH_LOCAL struct evm_anal_info *evm_ai = NULL;
csh cs_handle;
} EvmPluginData;
static void set_opdir(RAnalOp *op) {
switch (op->type & R_ANAL_OP_TYPE_MASK) {
@ -47,48 +51,58 @@ static void set_opdir(RAnalOp *op) {
* addr of the push instruction, but at the addr of next jumpi instruction.
* So in our example we are inserting (0xf, 0x42)
*/
static int evm_add_push_to_db(RAnalOp *op, ut64 addr, const ut8 *buf, int len) {
ut64 next_cmd_addr = 0;
static int evm_add_push_to_db(RArchSession *s, RAnalOp *op, ut64 addr, const ut8 *buf, int len) {
EvmPluginData *epd = (EvmPluginData*)s->data;
ut64 dst_addr = 0;
size_t i, push_size;
size_t i;
push_size = op->id - EVM_INS_PUSH1;
next_cmd_addr = addr + push_size + 2;
size_t push_size = op->id - EVM_INS_PUSH1;
ut64 next_cmd_addr = addr + push_size + 2;
for (i = 0; i < push_size + 1; i++) {
dst_addr <<= 8;
dst_addr |= buf[i + 1];
}
if (evm_ai) {
sdb_num_nset (evm_ai->pushs_db, next_cmd_addr, dst_addr, 0);
}
sdb_num_nset (epd->pushs_db, next_cmd_addr, dst_addr, 0);
return 0;
}
static ut64 evm_get_jmp_addr(ut64 addr) {
return sdb_num_nget (evm_ai->pushs_db, addr, 0);
static ut64 evm_get_jmp_addr(RArchSession *s, ut64 addr) {
EvmPluginData *epd = (EvmPluginData*)s->data;
return sdb_num_nget (epd->pushs_db, addr, 0);
}
static int analop(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *buf, int len, RAnalOpMask mask) {
csh hndl = init_capstone (anal);
if (hndl == 0) {
return -1;
static bool encode(RArchSession *s, RAnalOp *op, RAnalOpMask mask) {
ut8 buf[64];
int asmlen = evm_asm (op->mnemonic, buf, sizeof (buf));
if (asmlen > 0) {
op->size = asmlen;
r_anal_op_set_bytes (op, op->addr, buf, asmlen);
return true;
}
return false;
}
int n, opsize = -1;
static bool decode(RArchSession *s, RAnalOp *op, RAnalOpMask mask) {
r_return_val_if_fail (s && op && s->data, false);
const ut64 addr = op->addr;
const ut8 *buf = op->bytes;
const int len = op->size;
EvmPluginData *epd = (EvmPluginData*)s->data;
int opsize = -1;
cs_insn *insn;
char *str;
op->addr = addr;
if (len < 1) {
return -1;
return false;
}
op->size = 1;
op->type = R_ANAL_OP_TYPE_UNK;
n = cs_disasm (hndl, (ut8 *)buf, len, addr, 1, &insn);
int n = cs_disasm (epd->cs_handle, (ut8 *)buf, len, addr, 1, &insn);
opsize = 1;
if (n < 1 || insn->size < 1) {
if (mask & R_ARCH_OP_MASK_DISASM) {
@ -97,7 +111,7 @@ static int analop(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *buf, int len,
goto beach;
}
if (mask & R_ARCH_OP_MASK_DISASM) {
if (!r_str_cmp (insn->op_str, "0x", 2)) {
if (r_str_startswith (insn->op_str, "0x")) {
str = r_str_newf ("%s%s%s", insn->mnemonic, insn->op_str[0]? " ": "", insn->op_str);
} else {
str = r_str_newf ("%s%s%s", insn->mnemonic, insn->op_str[0]? " 0x": "", insn->op_str);
@ -117,7 +131,7 @@ static int analop(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *buf, int len,
case EVM_INS_JUMP:
op->type = R_ANAL_OP_TYPE_JMP;
op->fail = op->addr + 1;
op->jump = evm_get_jmp_addr (addr);
op->jump = evm_get_jmp_addr (s, addr);
esilprintf (op, "32,sp,-=,sp,[1],pc,:=");
break;
case EVM_INS_JUMPDEST:
@ -126,7 +140,7 @@ static int analop(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *buf, int len,
case EVM_INS_JUMPI:
op->fail = op->addr + 1;
op->type = R_ANAL_OP_TYPE_CJMP;
op->jump = evm_get_jmp_addr (addr);
op->jump = evm_get_jmp_addr (s, addr);
break;
case EVM_INS_MLOAD:
case EVM_INS_SLOAD:
@ -215,7 +229,7 @@ static int analop(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *buf, int len,
case EVM_INS_PUSH1:
esilprintf (op, "0x%s,sp,=[1],32,sp,+=", insn->op_str);
op->type = R_ANAL_OP_TYPE_PUSH;
evm_add_push_to_db (op, addr, buf, len);
evm_add_push_to_db (s, op, addr, buf, len);
break;
case EVM_INS_PUSH2:
case EVM_INS_PUSH3:
@ -238,7 +252,7 @@ static int analop(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *buf, int len,
case EVM_INS_PUSH22:
case EVM_INS_PUSH23:
op->type = R_ANAL_OP_TYPE_PUSH;
evm_add_push_to_db (op, addr, buf, len);
evm_add_push_to_db (s, op, addr, buf, len);
break;
// Handle https://github.com/capstone-engine/capstone/pull/1231. Can be removed when merged.
case EVM_INS_PUSH24:
@ -302,19 +316,20 @@ beach:
opex (&op->opex, hndl, insn);
}
if (mask & R_ARCH_OP_MASK_ESIL) {
if (analop_esil (anal, op, addr, buf, len, &hndl, insn) != 0) {
if (archop_esil (arch, op, addr, buf, len, &hndl, insn) != 0) {
r_strbuf_fini (&op->esil);
}
}
if (mask & R_ARCH_OP_MASK_VAL) {
op_fillval (anal, op, &hndl, insn);
op_fillval (arch, op, &hndl, insn);
}
#endif
cs_free (insn, n);
return opsize;
op->size = opsize;
return true;
}
static char *get_reg_profile(RAnal *anal) {
static char *regs(RArchSession *as) {
return strdup (
"=PC pc\n"
"=SP sp\n"
@ -329,66 +344,77 @@ static char *get_reg_profile(RAnal *anal) {
);
}
static int evm_anal_init(void *user) {
if (!evm_ai) {
evm_ai = R_NEW0 (struct evm_anal_info);
evm_ai->pushs_db = sdb_new0 ();
if (!evm_ai) {
return false;
}
static bool init(RArchSession *s) {
r_return_val_if_fail (s, false);
if (s->data) {
R_LOG_WARN ("Already initialized");
return false;
}
s->data = R_NEW0 (EvmPluginData);
EvmPluginData *epd = (EvmPluginData*)s->data;
if (!r_arch_cs_init (s, &epd->cs_handle)) {
R_LOG_ERROR ("Cannot initialize capstone");
R_FREE (s->data);
return false;
}
epd->pushs_db = sdb_new0 ();
return true;
}
static int evm_anal_fini(void *user) {
if (evm_ai) {
sdb_free (evm_ai->pushs_db);
R_FREE (evm_ai);
}
static bool fini(RArchSession *s) {
r_return_val_if_fail (s, false);
EvmPluginData *epd = (EvmPluginData*)s->data;
sdb_free (epd->pushs_db);
cs_close (&epd->cs_handle);
R_FREE (s->data);
return true;
}
static int archinfo(RAnal *anal, int q) {
static int archinfo(RArchSession *a, ut32 q) {
switch (q) {
case R_ANAL_ARCHINFO_ALIGN:
case R_ARCH_INFO_ALIGN:
return 0;
case R_ANAL_ARCHINFO_MAX_OP_SIZE:
case R_ARCH_INFO_MAX_OP_SIZE:
return 33;
case R_ANAL_ARCHINFO_MIN_OP_SIZE:
case R_ARCH_INFO_MIN_OP_SIZE:
return 1;
}
return 0;
}
RAnalPlugin r_anal_plugin_evm_cs = {
static char *mnemonics(RArchSession *s, int id, bool json) {
EvmPluginData *epd = (EvmPluginData*)s->data;
return r_arch_cs_mnemonics (s, epd->cs_handle, id, json);
}
RArchPlugin r_arch_plugin_evm = {
.name = "evm",
.desc = "Capstone ETHEREUM VM arch plugin",
.desc = "EthereumVM plugin",
.license = "BSD",
.esil = true,
.arch = "evm",
.get_reg_profile = get_reg_profile,
.archinfo = archinfo,
.bits = 8,
.op = &analop,
.mnemonics = cs_mnemonics,
.init = evm_anal_init,
.fini = evm_anal_fini
.regs = regs,
.info = archinfo,
.bits = 32,
.decode = &decode,
.encode = &encode,
.mnemonics = mnemonics,
.init = init,
.fini = fini
};
#ifndef R2_PLUGIN_INCORE
R_API RLibStruct radare_plugin = {
.type = R_LIB_TYPE_ANAL,
.data = &r_anal_plugin_evm_cs,
.type = R_LIB_TYPE_ARCH,
.data = &r_arch_plugin_evm,
.version = R2_VERSION
};
#endif
#else
RAnalPlugin r_anal_plugin_evm_cs = { 0 };
RArchPlugin r_arch_plugin_evm = { 0 };
#ifndef R2_PLUGIN_INCORE
R_API RLibStruct radare_plugin = {
.type = R_LIB_TYPE_ANAL,
.type = R_LIB_TYPE_ARCH,
.version = R2_VERSION
};
#endif

View File

@ -1,4 +1,4 @@
/* radare2 - LGPL - Copyright 2022 - pancake, condret */
/* radare2 - LGPL - Copyright 2022-2023 - pancake, condret */
#ifndef R2_ARCH_H
#define R2_ARCH_H
@ -105,14 +105,16 @@ typedef enum {
R_ARCH_OP_MASK_ALL = 1 | 2 | 4 | 8 | 16
} RAnalOpMask;
#if 0
// XXX R2_590 - backward compatible, shouldnt be used
#define R_ANAL_OP_MASK_BASIC = 0, // Just fills basic op info , it's fast
#define R_ANAL_OP_MASK_ESIL = 1, // It fills RAnalop->esil info
#define R_ANAL_OP_MASK_VAL = 2, // It fills RAnalop->dst/src info
#define R_ANAL_OP_MASK_HINT = 4, // It calls r_anal_op_hint to override anal options
#define R_ANAL_OP_MASK_OPEX = 8, // It fills RAnalop->opex info
#define R_ANAL_OP_MASK_DISASM = 16, // It fills RAnalop->mnemonic // should be RAnalOp->disasm // only from r_core_anal_op()
#define R_ANAL_OP_MASK_ALL = 1 | 2 | 4 | 8 | 16
#define R_ANAL_OP_MASK_BASIC 0, // Just fills basic op info , it's fast
#define R_ANAL_OP_MASK_ESIL 1, // It fills RAnalop->esil info
#define R_ANAL_OP_MASK_VAL 2, // It fills RAnalop->dst/src info
#define R_ANAL_OP_MASK_HINT 4, // It calls r_anal_op_hint to override anal options
#define R_ANAL_OP_MASK_OPEX 8, // It fills RAnalop->opex info
#define R_ANAL_OP_MASK_DISASM 16, // It fills RAnalop->mnemonic // should be RAnalOp->disasm // only from r_core_anal_op()
#define R_ANAL_OP_MASK_ALL (1 | 2 | 4 | 8 | 16)
#endif
typedef struct r_arch_t {
RList *plugins; // all plugins
@ -268,6 +270,7 @@ extern RArchPlugin r_arch_plugin_v850;
extern RArchPlugin r_arch_plugin_propeller;
extern RArchPlugin r_arch_plugin_mcore;
extern RArchPlugin r_arch_plugin_nios2;
extern RArchPlugin r_arch_plugin_evm;
#ifdef __cplusplus
}

View File

@ -9,6 +9,7 @@ arch_plugins = [ 'null',
'sh',
'arm',
'6502',
'evm',
'nios2',
'snes',
'v850',
@ -147,7 +148,6 @@ anal_plugins += [
'cris',
'dalvik',
'ebc',
'evm_cs',
'gb',
'h8300',
'i8080',