Honor plugin name in rate matching for RArch.use ##arch

* Fixes amd29k regressions
This commit is contained in:
pancake 2022-11-07 00:28:18 +01:00
parent 7652642373
commit 539c5aee90
29 changed files with 349 additions and 539 deletions

View File

@ -1,4 +1,4 @@
ifeq ($(uname -m),arm64)
ifeq ($(shell uname -m),arm64)
ARCH=arm64
else
ARCH=amd64

View File

@ -10,7 +10,6 @@ anal.avr
anal.lanai_gnu
anal.bpf
anal.lm32
anal.i4004
anal.bf
anal.bpf_cs
anal.chip8

View File

@ -5,7 +5,6 @@ anal.arc
anal.arm_cs
anal.arm_gnu
anal.avr
anal.i4004
anal.bf
anal.chip8
anal.lanai_gnu

View File

@ -3,7 +3,6 @@ anal.arc
anal.arm_gnu
anal.arm_v35
anal.avr
anal.i4004
anal.bf
anal.chip8
anal.cr16

View File

@ -23,7 +23,6 @@ anal.v850
anal.ws
anal.x86_cs
anal.xcore_cs
anal.i4004
arch.null
arch.i4004
esil.dummy

View File

@ -4,7 +4,6 @@ STATIC="anal.8051
anal.arc
anal.arm_cs
anal.arm_gnu
anal.i4004
anal.bf
anal.chip8
anal.cris

View File

@ -1,7 +1,6 @@
STATIC="anal.8051
anal.arc
anal.arm_cs
anal.i4004
anal.bf
anal.chip8
anal.cris

View File

@ -34,7 +34,6 @@ anal.pic
anal.rsp
anal.wasm
anal.pyc
anal.i4004
arch.null
arch.i4004
esil.dummy

View File

@ -23,6 +23,7 @@ R_API void r_anal_set_limits(RAnal *anal, ut64 from, ut64 to) {
}
R_API void r_anal_unset_limits(RAnal *anal) {
r_return_if_fail (anal);
R_FREE (anal->limit);
}
@ -231,9 +232,10 @@ R_API char *r_anal_mnemonics(RAnal *anal, int id, bool json) {
R_API bool r_anal_use(RAnal *anal, const char *name) {
r_return_val_if_fail (anal, false);
if (anal->arch) {
bool res = r_arch_use (anal->arch, anal->config);
bool res = r_arch_use (anal->arch, anal->config, name);
if (res) {
R_LOG_DEBUG ("sing experimental '%s' r_arch plugin", name);
return true;
} else {
anal->arch->current = NULL;
}
@ -456,13 +458,20 @@ R_API void r_anal_purge(RAnal *anal) {
r_anal_purge_imports (anal);
}
R_API int r_anal_archinfo(RAnal *anal, int query) {
// XXX deprecate
R_API R_DEPRECATE int r_anal_archinfo(RAnal *anal, int query) {
r_return_val_if_fail (anal, -1);
switch (query) {
case R_ANAL_ARCHINFO_MIN_OP_SIZE:
case R_ANAL_ARCHINFO_MAX_OP_SIZE:
case R_ANAL_ARCHINFO_INV_OP_SIZE:
case R_ANAL_ARCHINFO_ALIGN:
{
int res = r_arch_info (anal->arch, NULL, query);
if (res != -1) {
return res;
}
}
if (anal->cur && anal->cur->archinfo) {
return anal->cur->archinfo (anal, query);
}
@ -713,8 +722,8 @@ R_API void r_anal_bind(RAnal *anal, RAnalBind *b) {
b->anal = anal;
b->get_fcn_in = r_anal_get_fcn_in;
b->get_hint = r_anal_hint_get;
b->encode = (RAnalEncode)r_anal_opasm;
b->decode = (RAnalDecode)r_anal_op;
b->encode = (RAnalEncode)r_anal_opasm; // TODO rename to encode
b->decode = (RAnalDecode)r_anal_op; // TODO rename to decode
b->opinit = r_anal_op_init;
b->mnemonics = r_anal_mnemonics;
b->opfini = r_anal_op_fini;

View File

@ -77,7 +77,6 @@ r_anal_sources = [
'p/anal_evm_cs.c',
'p/anal_gb.c',
'p/anal_h8300.c',
'p/anal_i4004.c',
'p/anal_i8080.c',
'p/anal_java.c',
'p/anal_kvx.c',

View File

@ -90,14 +90,34 @@ static int defaultCycles(RAnalOp *op) {
}
R_API int r_anal_opasm(RAnal *anal, ut64 addr, const char *s, ut8 *outbuf, int outlen) {
if (anal && outbuf && outlen > 0 && anal->cur && anal->cur->opasm) {
int ret = 0;
if (outlen > 0 && anal->arch->current) {
ret = r_arch_encode (anal->arch, addr, s, outbuf, outlen);
// r_arch_op_to_analop (op, &archop);
// ret = anal->arch->op (anal, op, addr, data, len, mask);
if (ret < 1) {
ret = r_arch_info (anal->arch, NULL, R_ANAL_ARCHINFO_INV_OP_SIZE);
if (ret < 0) {
ret = r_arch_info (anal->arch, NULL, R_ANAL_ARCHINFO_ALIGN);
if (ret < 0) {
ret = 1;
}
}
}
// op->addr = addr;
/* consider at least 1 byte to be part of the opcode */
#if 0
if (op->nopcode < 1) {
op->nopcode = 1;
}
#endif
} else if (anal && outbuf && outlen > 0 && anal->cur && anal->cur->opasm) {
// use core binding to set asm.bits correctly based on the addr
// this is because of the hassle of arm/thumb
int ret = anal->cur->opasm (anal, addr, s, outbuf, outlen);
ret = anal->cur->opasm (anal, addr, s, outbuf, outlen);
/* consider at least 1 byte to be part of the opcode */
return ret;
}
return 0;
return ret;
}
R_API int r_anal_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *data, int len, RAnalOpMask mask) {

View File

@ -1,405 +0,0 @@
/* radare - LGPL - Copyright 2016-2022 - pancake, condret */
#include <string.h>
#include <r_types.h>
#include <r_util.h>
#include <r_lib.h>
#include <r_asm.h>
#include <r_anal.h>
#include "../arch/i4004/i4004.c"
static bool set_reg_profile(RAnal *anal) {
const char *p =
"=PC PC\n"
/* syntax not yet supported */
// "=SP &PC1\n"
"=A0 r0\n"
"=A1 r1\n"
"=A2 r2\n"
"=A3 r3\n"
"=R0 r0\n"
"gpr r0 .4 0 0\n"
"gpr r1 .4 .4 0\n"
"gpr r0r1 1 0 0\n"
"gpr r2 .4 .8 0\n"
"gpr r3 .4 .12 0\n"
"gpr r2r3 1 1 0\n"
"gpr r4 .4 .16 0\n"
"gpr r5 .4 .20 0\n"
"gpr r4r5 1 2 0\n"
"gpr r6 .4 .24 0\n"
"gpr r7 .4 .28 0\n"
"gpr r6r7 1 3 0\n"
"gpr r8 .4 .32 0\n"
"gpr r9 .4 .36 0\n"
"gpr r8r9 1 4 0\n"
"gpr r10 .4 .40 0\n"
"gpr r11 .4 .44 0\n"
"gpr r10r11 1 5 0\n"
"gpr r12 .4 .52 0\n"
"gpr r13 .4 .56 0\n"
"gpr r12r13 1 6 0\n"
"gpr r14 .4 .60 0\n"
"gpr r15 .4 .64 0\n"
"gpr r14r15 1 7 0\n"
"gpr PC .12 .72 0\n"
/* stack */
"gpr PC1 .12 .88 0\n"
"gpr PC2 .12 .104 0\n"
"gpr PC3 .12 .120 0\n"
;
return r_reg_set_profile_string (anal->reg, p);
}
/* That 3 is a hack */
static const int i4004_ins_len[16] = {
1, 2, 3, 1, 2, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1
};
static const char *i4004_e[16] = {
"wrm",
"wmp",
"wrr",
"wpm",
"wr0",
"wr1",
"wr2",
"wr3",
"sbm",
"rdm",
"rdr",
"adm",
"rd0",
"rd1",
"rd2",
"rd3"
};
static const char *i4004_f[16] = {
"clb",
"clc",
"iac",
"cmc",
"cma",
"ral",
"rar",
"tcc",
"dac", // decrement
"tcs",
"stc",
"daa",
"kbp",
"dcl",
"invalid",
"invalid"
};
static int i4004_get_ins_len(ut8 hex) {
ut8 high = (hex & 0xf0)>>4;
int ret = i4004_ins_len[high];
if (ret == 3) {
ret = (hex & 1) ? 1 : 2;
}
return ret;
}
static int i4004_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *buf, int len, RAnalOpMask mask) {
char basm[64];
const size_t basz = sizeof (basm);
int rlen = i4004_get_ins_len (*buf);
if (!op) {
return 2;
}
ut8 high = (*buf & 0xf0)>>4;
ut8 low = (*buf & 0xf);
basm[0] = 0;
if (rlen > len) {
return op->size = 0;
}
switch (high) {
case 0:
if (low) {
op->type = R_ANAL_OP_TYPE_ILL;
if (mask & R_ARCH_OP_MASK_DISASM) {
strcpy (basm, "invalid");
}
} else {
op->type = R_ANAL_OP_TYPE_NOP;
if (mask & R_ARCH_OP_MASK_DISASM) {
strcpy (basm, "nop");
}
}
break;
case 1:
op->type = R_ANAL_OP_TYPE_CJMP;
if (mask & R_ARCH_OP_MASK_DISASM) {
snprintf (basm, basz, "jcn 0x%x 0x%x", low, buf[1]);
}
op->jump = (addr & (~0xFF)) + buf[1];
op->fail = addr + rlen;
break;
case 2:
if (rlen == 1) {
if (mask & R_ARCH_OP_MASK_DISASM) {
snprintf (basm, basz, "src r%d", (low & 0xe) >> 1);
}
} else {
op->type = R_ANAL_OP_TYPE_MOV;
op->val = buf[1];
if (mask & R_ARCH_OP_MASK_DISASM) {
snprintf (basm, basz, "fim r%dr%d, 0x%x", low & 0xe,
(low & 0xe) + 1, buf[1]);
}
}
break;
case 3:
if (low & 1) {
op->type = R_ANAL_OP_TYPE_RJMP;
if (mask & R_ARCH_OP_MASK_DISASM) {
snprintf (basm, basz, "jin r%dr%d", low & 0xe, (low & 0xe) + 1);
}
} else {
op->type = R_ANAL_OP_TYPE_MOV;
if (mask & R_ARCH_OP_MASK_DISASM) {
snprintf (basm, basz, "fin r%dr%d", low & 0xe, (low & 0xe) + 1);
}
}
break;
case 4:
op->type = R_ANAL_OP_TYPE_JMP;
op->jump = (ut16) (low<<8) | buf[1];
if (mask & R_ARCH_OP_MASK_DISASM) {
snprintf (basm, basz, "jun 0x%x", (ut16)op->jump);
}
break;
case 5:
op->type = R_ANAL_OP_TYPE_CALL;
op->jump = (ut16) (low<<8) | buf[1];
op->fail = addr + rlen;
if (mask & R_ARCH_OP_MASK_DISASM) {
snprintf (basm, basz, "jms 0x%x", (ut16)op->jump);
}
break;
case 6:
op->type = R_ANAL_OP_TYPE_ADD;
if (mask & R_ARCH_OP_MASK_DISASM) {
snprintf (basm, basz, "inc r%d", low);
}
break;
case 7:
op->type = R_ANAL_OP_TYPE_CJMP;
op->fail = (addr & (~0xFF)) + buf[1];
op->jump = addr + rlen;
if (mask & R_ARCH_OP_MASK_DISASM) {
snprintf (basm, basz, "isz r%d, 0x%x", low, buf[1]);
}
break;
case 8:
op->type = R_ANAL_OP_TYPE_ADD;
if (mask & R_ARCH_OP_MASK_DISASM) {
snprintf (basm, basz, "add r%d", low);
}
break;
case 9:
op->type = R_ANAL_OP_TYPE_SUB;
if (mask & R_ARCH_OP_MASK_DISASM) {
snprintf (basm, basz, "sub r%d", low);
}
break;
case 10:
op->type = R_ANAL_OP_TYPE_MOV;
if (mask & R_ARCH_OP_MASK_DISASM) {
snprintf (basm, basz, "ld r%d", low);
}
break;
case 11:
op->type = R_ANAL_OP_TYPE_XCHG;
if (mask & R_ARCH_OP_MASK_DISASM) {
snprintf (basm, basz, "xch r%d", low);
}
break;
case 12:
op->type = R_ANAL_OP_TYPE_RET;
if (mask & R_ARCH_OP_MASK_DISASM) {
snprintf (basm, basz, "bbl 0x%x", low);
}
break;
case 13:
op->type = R_ANAL_OP_TYPE_LOAD;
if (mask & R_ARCH_OP_MASK_DISASM) {
snprintf (basm, basz, "ldm 0x%x", low);
}
break;
case 14:
strncpy (basm, i4004_e[low], basz);
basm[basz - 1] = '\0';
break;
case 15:
strncpy (basm, i4004_f[low], basz);
basm[basz - 1] = '\0';
if (!strcmp (basm, "dac")) {
op->type = R_ANAL_OP_TYPE_SUB;
}
break;
}
if (!strcmp (basm, "invalid")) {
op->type = R_ANAL_OP_TYPE_ILL;
} else if (!strcmp (basm, "ral")) {
op->type = R_ANAL_OP_TYPE_SHL;
} else if (!strcmp (basm, "rar")) {
op->type = R_ANAL_OP_TYPE_SHR;
}
if (mask & R_ARCH_OP_MASK_DISASM) {
op->mnemonic = strdup (basm);
}
return op->size = rlen;
}
static int i4004_anal_opasm(RAnal *a, ut64 addr, const char *str, ut8 *outbuf, int outsize) {
char *s = strdup (str);
r_str_case (s, false);
s = r_str_replace (s, "_", "?", false); // mitigate a bug in sdb -C
s = r_str_replace (s, ",", " _ ", false);
int i, nelems;
char **elems = r_str_argv (s, &nelems);
RStrBuf *sbuf = r_strbuf_new (elems[0]);
for (i = 1; i < nelems; i++) {
if (r_is_valid_input_num_value (NULL, elems[i])) {
r_strbuf_appendf (sbuf, " 0x%"PFMT64x, r_num_get (NULL, elems[i]));
} else {
r_strbuf_appendf (sbuf, " %s", elems[i]);
}
}
Sdb *asm_db = sdb_new0 ();
sdb_open_gperf (asm_db, (SdbGperf *)&gperf_i4004);
char *hex_output = sdb_get (asm_db, r_strbuf_get (sbuf), NULL);
sdb_free (asm_db);
r_strbuf_free (sbuf);
if (hex_output) {
r_str_argv_free (elems);
free (s);
r_hex_str2bin (hex_output, outbuf);
free (hex_output);
return 1;
}
if (strlen (elems[0]) != 3) {
r_str_argv_free (elems);
free (s);
return 0;
}
int ret = 0;
switch (elems[0][0] << 16 | elems[0][1] << 8 | elems[0][2]) {
case 0x6a636e: //jcn
if (nelems > 2 && r_is_valid_input_num_value (NULL, elems[1])
&& r_is_valid_input_num_value (NULL, elems[2])) {
ut64 v = r_num_get (NULL, elems[1]);
if (v < 0x10) {
outbuf[0] = 0x10 | (ut8)v;
v = r_num_get (NULL, elems[2]);
if (v < 0x100) {
outbuf[1] = (ut8)v;
ret = 2;
}
}
}
break;
case 0x66696d: //fim
if (nelems > 3 && !strcmp (elems[2], "_") && r_is_valid_input_num_value (NULL, elems[3])) {
const ut64 v = r_num_get (NULL, elems[3]);
if (v < 0x100) {
ret = 2;
if (!strcmp (elems[1], "r0r1")) {
outbuf[0] = 0x20;
outbuf[1] = (ut8)v;
} else if (!strcmp (elems[1], "r2r3")) {
outbuf[0] = 0x22;
outbuf[1] = (ut8)v;
} else if (!strcmp (elems[1], "r4r5")) {
outbuf[0] = 0x24;
outbuf[1] = (ut8)v;
} else if (!strcmp (elems[1], "r6r7")) {
outbuf[0] = 0x26;
outbuf[1] = (ut8)v;
} else if (!strcmp (elems[1], "r8r9")) {
outbuf[0] = 0x28;
outbuf[1] = (ut8)v;
} else if (!strcmp (elems[1], "r10r11")) {
outbuf[0] = 0x2a;
outbuf[1] = (ut8)v;
} else if (!strcmp (elems[1], "r12r14")) {
outbuf[0] = 0x2c;
outbuf[1] = (ut8)v;
} else if (!strcmp (elems[1], "r14r15")) {
outbuf[0] = 0x2e;
outbuf[1] = (ut8)v;
} else {
ret = 0;
}
}
}
break;
case 0x6a756e: //jun
if (nelems > 1 && r_is_valid_input_num_value (NULL, elems[1])) {
const ut64 v = r_num_get (NULL, elems[1]);
if (v < 0x1000) {
outbuf[0] = 0x40 | (v & 0xf00) >> 8;
outbuf[1] = v & 0xff;
ret = 2;
}
}
break;
case 0x6a6d73: //jms
if (nelems > 1 && r_is_valid_input_num_value (NULL, elems[1])) {
const ut64 v = r_num_get (NULL, elems[1]);
if (v < 0x1000) {
outbuf[0] = 0x50 | (v & 0xf00) >> 8;
outbuf[1] = v & 0xff;
ret = 2;
}
}
break;
case 0x69737a: //isz
if (nelems > 3 && elems[1][0] == 'r' && r_is_valid_input_num_value (NULL, &elems[1][1])
&& !strcmp (elems[2], "_") && r_is_valid_input_num_value (NULL, elems[3])) {
ut64 v = r_num_get (NULL, &elems[1][1]);
if (v < 0x10) {
outbuf[0] = 0x70 | (ut8)v;
v = r_num_get (NULL, elems[3]);
if (v < 0x100) {
outbuf[1] = (ut8)v;
ret = 2;
}
}
}
break;
default:
break;
}
r_str_argv_free (elems);
free (s);
return ret;
}
RAnalPlugin r_anal_plugin_i4004 = {
.name = "i4004",
.desc = "i4004 code analysis plugin",
.license = "LGPL3",
.arch = "i4004",
.esil = false,
.bits = 4,
.author = "pancake, condret",
.op = &i4004_op,
.opasm = &i4004_anal_opasm,
.set_reg_profile = &set_reg_profile
};
#ifndef R2_PLUGIN_INCORE
R_API RLibStruct radare_plugin = {
.type = R_LIB_TYPE_ANAL,
.data = &r_anal_plugin_i4004,
.version = R2_VERSION
};
#endif

View File

@ -1,9 +0,0 @@
OBJ_I4004=anal_i4004.o
STATIC_OBJ+=${OBJ_I4004}
TARGET_I4004=anal_i4004.${EXT_SO}
ALL_TARGETS+=${TARGET_I4004}
${TARGET_I4004}: ${OBJ_I4004}
${CC} $(call libname,anal_i4004) ${CFLAGS} -o anal_i4004.${EXT_SO} ${OBJ_I4004}

View File

@ -11,6 +11,8 @@ pre: libr_arch.$(EXT_SO) libr_arch.$(EXT_AR)
include $(STATIC_ARCH_PLUGINS)
STATIC_OBJS=$(subst ..,p/..,$(subst arch_,p/arch_,$(STATIC_OBJ)))
OBJS=arch.o aconfig.o decoder.o switchop.o archop.o archvalue.o archcond.o ${STATIC_OBJS}
OBJS=arch.o aconfig.o switchop.o archop.o archvalue.o archcond.o
OBJS+=${STATIC_OBJS}
OBJS+=encoder.o decoder.o
include ../rules.mk

View File

@ -5,10 +5,10 @@
static const RArchPlugin * const arch_static_plugins[] = { R_ARCH_STATIC_PLUGINS };
static void plugin_free (void *p) {
static void plugin_free(void *p) {
}
static void _decoder_free_cb (HtPPKv *kv) {
static void _decoder_free_cb(HtPPKv *kv) {
free (kv->key);
RArchDecoder *decoder = (RArchDecoder *)kv->value;
if (decoder->p->fini) {
@ -40,7 +40,7 @@ R_API RArch *r_arch_new(void) {
return a;
}
static ut32 _rate_compat(RArchPlugin *p, RArchConfig *cfg) {
static ut32 _rate_compat(RArchPlugin *p, RArchConfig *cfg, const char *name) {
ut32 bits;
switch (cfg->bits) {
case 64:
@ -69,8 +69,11 @@ static ut32 _rate_compat(RArchPlugin *p, RArchConfig *cfg) {
break;
}
ut32 score = 0;
if (name && !strcmp (p->name, name)) {
score += 50;
}
if (!strcmp (p->arch, cfg->arch)) {
score = 50;
score += 50;
}
if (p->bits & bits) {
score += (!!score) * 30;
@ -81,27 +84,27 @@ static ut32 _rate_compat(RArchPlugin *p, RArchConfig *cfg) {
return score;
}
static char *_find_bestmatch(RList *plugins, RArchConfig *cfg) {
static char *_find_bestmatch(RList *plugins, RArchConfig *cfg, const char *name) {
ut8 best_score = 0;
char *name = NULL;
char *rname = NULL;
RListIter *iter;
RArchPlugin *p;
r_list_foreach (plugins, iter, p) {
const ut32 score = _rate_compat (p, cfg);
const ut32 score = _rate_compat (p, cfg, name);
if (score > best_score) {
best_score = score;
name = p->name;
rname = p->name;
}
if (score == 100) {
break;
}
}
return name;
return rname;
}
// use config as new arch config and use matching decoder as current
// must return arch->current, and remove that field. and use refcounting
R_API bool r_arch_use(RArch *arch, RArchConfig *config) {
R_API bool r_arch_use(RArch *arch, RArchConfig *config, const char *name) {
r_return_val_if_fail (arch, false);
if (!config) {
config = arch->cfg;
@ -110,10 +113,10 @@ R_API bool r_arch_use(RArch *arch, RArchConfig *config) {
return true;
}
if (!config) {
return false;
// arch->decoder = NULL;
return false;
}
const char *dname = config->decoder ? config->decoder: _find_bestmatch (arch->plugins, config);
const char *dname = config->decoder ? config->decoder: _find_bestmatch (arch->plugins, config, name);
if (!dname) {
return false;
}
@ -144,7 +147,7 @@ R_API bool r_arch_set_bits(RArch *arch, ut32 bits) {
}
// r_arch_config_set_bits (arch->cfg, bits);
cfg->bits = bits;
if (!r_arch_use (arch, cfg)) {
if (!r_arch_use (arch, cfg, NULL)) {
r_unref (cfg);
arch->cfg = NULL;
return false;
@ -153,17 +156,17 @@ R_API bool r_arch_set_bits(RArch *arch, ut32 bits) {
}
if (arch->autoselect) {
if (arch->current) {
const ut32 score = _rate_compat (arch->current->p, arch->cfg);
const ut32 score = _rate_compat (arch->current->p, arch->cfg, NULL);
arch->cfg->bits = bits;
if (!score || score > _rate_compat (arch->current->p, arch->cfg)) {
if (!score || score > _rate_compat (arch->current->p, arch->cfg, NULL)) {
R_FREE (arch->cfg->decoder);
return r_arch_use (arch, arch->cfg);
return r_arch_use (arch, arch->cfg, NULL);
}
return true;
}
R_FREE (arch->cfg->decoder);
arch->cfg->bits = bits;
return r_arch_use (arch, arch->cfg);
return r_arch_use (arch, arch->cfg, NULL);
}
arch->cfg->bits = bits;
return true;
@ -177,7 +180,7 @@ R_API bool r_arch_set_endian(RArch *arch, ut32 endian) {
return false;
}
cfg->endian = endian;
if (!r_arch_use (arch, cfg)) {
if (!r_arch_use (arch, cfg, NULL)) {
r_unref (cfg);
arch->cfg = NULL;
return false;
@ -186,17 +189,17 @@ R_API bool r_arch_set_endian(RArch *arch, ut32 endian) {
}
if (arch->autoselect) {
if (arch->current) {
const ut32 score = _rate_compat (arch->current->p, arch->cfg);
const ut32 score = _rate_compat (arch->current->p, arch->cfg, NULL);
arch->cfg->endian = endian;
if (!score || score > _rate_compat (arch->current->p, arch->cfg)) {
if (!score || score > _rate_compat (arch->current->p, arch->cfg, NULL)) {
R_FREE (arch->cfg->decoder);
return r_arch_use (arch, arch->cfg);
return r_arch_use (arch, arch->cfg, NULL);
}
return true;
}
R_FREE (arch->cfg->decoder);
arch->cfg->endian = endian;
return r_arch_use (arch, arch->cfg);
return r_arch_use (arch, arch->cfg, NULL);
}
arch->cfg->endian = endian;
return true;
@ -216,7 +219,7 @@ R_API bool r_arch_set_arch(RArch *arch, char *archname) {
}
free (cfg->arch);
cfg->arch =_arch;
if (!r_arch_use (arch, cfg)) {
if (!r_arch_use (arch, cfg, archname)) {
r_unref (cfg);
return false;
}
@ -224,19 +227,19 @@ R_API bool r_arch_set_arch(RArch *arch, char *archname) {
}
if (arch->autoselect) {
if (arch->current) {
const ut32 score = _rate_compat (arch->current->p, arch->cfg);
const ut32 score = _rate_compat (arch->current->p, arch->cfg, archname);
free (arch->cfg->arch);
arch->cfg->arch = _arch;
if (!score || score > _rate_compat (arch->current->p, arch->cfg)) {
if (!score || score > _rate_compat (arch->current->p, arch->cfg, archname)) {
R_FREE (arch->cfg->decoder);
return r_arch_use (arch, arch->cfg);
return r_arch_use (arch, arch->cfg, archname);
}
return true;
}
R_FREE (arch->cfg->decoder);
free (arch->cfg->arch);
arch->cfg->arch = _arch;
return r_arch_use (arch, arch->cfg);
return r_arch_use (arch, arch->cfg, archname);
}
free (arch->cfg->arch);
arch->cfg->arch = _arch;
@ -292,3 +295,20 @@ R_API void r_arch_free(RArch *arch) {
r_unref (arch->cfg);
free (arch);
}
#if 0
R_API int r_arch_info(RArch *a, int query) {
r_return_val_if_fail (a, -1);
switch (query) {
case R_ANAL_ARCHINFO_MIN_OP_SIZE:
case R_ANAL_ARCHINFO_MAX_OP_SIZE:
case R_ANAL_ARCHINFO_INV_OP_SIZE:
case R_ANAL_ARCHINFO_ALIGN:
if (arch->current && anal->arch->current->archinfo) {
return arch->current->archinfo (arch, query);
}
break;
}
return -1;
}
#endif

View File

@ -111,7 +111,7 @@ R_API bool r_arch_unload_decoder(RArch *arch, const char *dname) {
}
R_API int r_arch_info(RArch *arch, const char *dname, ut32 query) {
r_return_val_if_fail (arch && arch->decoders, -1);
r_return_val_if_fail (arch, -1);
RArchDecoder *decoder = NULL;
if (dname) {
decoder = (RArchDecoder *)ht_pp_find (arch->decoders, dname, NULL);

18
libr/arch/encoder.c Normal file
View File

@ -0,0 +1,18 @@
/* radare2 - LGPL - Copyright 2022 - condret */
#include <r_arch.h>
#include <r_util.h>
// plaintext to opcdes bytes, returns length
// why not returning an RBuffer?
// R_API RBuffer *r_arch_encode(RArch *a, ut64 addr, const char *s) { }
R_API int r_arch_encode(RArch *a, ut64 addr, const char *s, ut8 *outbuf, int outlen) {
int res = 0;
RArchOpAsmCallback opasm = R_UNWRAP4 (a, current, p, opasm);
if (opasm) { // a->current && a->current->p && a->current->p->opasm) {
res = opasm (a, addr, s, outbuf, outlen);
}
return res;
}

View File

@ -2,6 +2,7 @@ r_arch_sources = [
'arch.c',
'aconfig.c',
'decoder.c',
'encoder.c',
'switchop.c',
'archop.c',
'archcond.c',

View File

@ -1,6 +1,7 @@
/* radare - LGPL - Copyright 2016-2022 - pancake, condret */
#include <r_arch.h>
#include "../i/i4004/gperfdb.c"
static bool set_reg_profile(RArchConfig *cfg, RReg *reg) {
const char *p =
@ -250,6 +251,135 @@ static int i4004_decode(RArchConfig *cfg, RAnalOp *op, ut64 addr, const ut8 *buf
return op->size = rlen;
}
static int i4004_anal_opasm(RArch *a, ut64 addr, const char *str, ut8 *outbuf, int outsize) {
char *s = strdup (str);
r_str_case (s, false);
s = r_str_replace (s, "_", "?", false); // mitigate a bug in sdb -C
s = r_str_replace (s, ",", " _ ", false);
int i, nelems;
char **elems = r_str_argv (s, &nelems);
RStrBuf *sbuf = r_strbuf_new (elems[0]);
for (i = 1; i < nelems; i++) {
if (r_is_valid_input_num_value (NULL, elems[i])) {
r_strbuf_appendf (sbuf, " 0x%"PFMT64x, r_num_get (NULL, elems[i]));
} else {
r_strbuf_appendf (sbuf, " %s", elems[i]);
}
}
// this db should be instantiated once on plugin session
#if 1
Sdb *asm_db = sdb_new0 ();
sdb_open_gperf (asm_db, (SdbGperf *)&gperf_i4004);
char *hex_output = sdb_get (asm_db, r_strbuf_get (sbuf), NULL);
sdb_free (asm_db);
r_strbuf_free (sbuf);
if (hex_output) {
r_str_argv_free (elems);
free (s);
r_hex_str2bin (hex_output, outbuf);
free (hex_output);
return 1;
}
#endif
if (strlen (elems[0]) != 3) {
r_str_argv_free (elems);
free (s);
return 0;
}
int ret = 0;
switch (elems[0][0] << 16 | elems[0][1] << 8 | elems[0][2]) {
case 0x6a636e: // jcn
if (nelems > 2 && r_is_valid_input_num_value (NULL, elems[1])
&& r_is_valid_input_num_value (NULL, elems[2])) {
ut64 v = r_num_get (NULL, elems[1]);
if (v < 0x10) {
outbuf[0] = 0x10 | (ut8)v;
v = r_num_get (NULL, elems[2]);
if (v < 0x100) {
outbuf[1] = (ut8)v;
ret = 2;
}
}
}
break;
case 0x66696d: // fim
if (nelems > 3 && !strcmp (elems[2], "_") && r_is_valid_input_num_value (NULL, elems[3])) {
const ut64 v = r_num_get (NULL, elems[3]);
if (v < 0x100) {
ret = 2;
if (!strcmp (elems[1], "r0r1")) {
outbuf[0] = 0x20;
outbuf[1] = (ut8)v;
} else if (!strcmp (elems[1], "r2r3")) {
outbuf[0] = 0x22;
outbuf[1] = (ut8)v;
} else if (!strcmp (elems[1], "r4r5")) {
outbuf[0] = 0x24;
outbuf[1] = (ut8)v;
} else if (!strcmp (elems[1], "r6r7")) {
outbuf[0] = 0x26;
outbuf[1] = (ut8)v;
} else if (!strcmp (elems[1], "r8r9")) {
outbuf[0] = 0x28;
outbuf[1] = (ut8)v;
} else if (!strcmp (elems[1], "r10r11")) {
outbuf[0] = 0x2a;
outbuf[1] = (ut8)v;
} else if (!strcmp (elems[1], "r12r14")) {
outbuf[0] = 0x2c;
outbuf[1] = (ut8)v;
} else if (!strcmp (elems[1], "r14r15")) {
outbuf[0] = 0x2e;
outbuf[1] = (ut8)v;
} else {
ret = 0;
}
}
}
break;
case 0x6a756e: // jun
if (nelems > 1 && r_is_valid_input_num_value (NULL, elems[1])) {
const ut64 v = r_num_get (NULL, elems[1]);
if (v < 0x1000) {
outbuf[0] = 0x40 | (v & 0xf00) >> 8;
outbuf[1] = v & 0xff;
ret = 2;
}
}
break;
case 0x6a6d73: // jms
if (nelems > 1 && r_is_valid_input_num_value (NULL, elems[1])) {
const ut64 v = r_num_get (NULL, elems[1]);
if (v < 0x1000) {
outbuf[0] = 0x50 | (v & 0xf00) >> 8;
outbuf[1] = v & 0xff;
ret = 2;
}
}
break;
case 0x69737a: // isz
if (nelems > 3 && elems[1][0] == 'r' && r_is_valid_input_num_value (NULL, &elems[1][1])
&& !strcmp (elems[2], "_") && r_is_valid_input_num_value (NULL, elems[3])) {
ut64 v = r_num_get (NULL, &elems[1][1]);
if (v < 0x10) {
outbuf[0] = 0x70 | (ut8)v;
v = r_num_get (NULL, elems[3]);
if (v < 0x100) {
outbuf[1] = (ut8)v;
ret = 2;
}
}
}
break;
default:
break;
}
r_str_argv_free (elems);
free (s);
return ret;
}
RArchPlugin r_arch_plugin_i4004 = {
.name = "i4004",
.desc = "i4004 decoder plugin",
@ -261,6 +391,7 @@ RArchPlugin r_arch_plugin_i4004 = {
.esil = false,
.author = "pancake, condret",
.decode = &i4004_decode,
.opasm = &i4004_anal_opasm,
.set_reg_profile = &set_reg_profile
};

View File

@ -316,7 +316,7 @@ R_API bool r_asm_use_assembler(RAsm *a, const char *name) {
RAsmPlugin *h;
RListIter *iter;
if (a) {
if (name && *name) {
if (R_STR_ISNOTEMPTY (name)) {
r_list_foreach (a->plugins, iter, h) {
if (h->assemble && !strcmp (h->name, name)) {
a->acur = h;
@ -342,7 +342,7 @@ static void load_asm_descriptions(RAsm *a, RAsmPlugin *p) {
arch = a->config->cpu;
}
#if HAVE_GPERF
SdbGperf *gp = r_asm_get_gperf (arch); // p->name);
SdbGperf *gp = r_asm_get_gperf (arch);
if (gp) {
sdb_free (a->pair);
a->pair = sdb_new0 ();
@ -353,8 +353,12 @@ static void load_asm_descriptions(RAsm *a, RAsmPlugin *p) {
char *r2prefix = r_str_r2_prefix (R2_SDB_OPCODES);
char *file = r_str_newf ("%s/%s.sdb", r_str_getf (r2prefix), arch);
if (file) {
#if 0
sdb_reset (a->pair);
#else
sdb_free (a->pair);
a->pair = sdb_new (NULL, file, 0);
#endif
free (file);
}
free (r2prefix);
@ -369,54 +373,56 @@ R_API bool r_asm_use(RAsm *a, const char *name) {
}
RAsmPlugin *h;
RListIter *iter;
char *dotname = strdup (name);
char *vv = strchr (dotname, '.');
if (vv) {
*vv = 0;
} else {
R_FREE (dotname);
}
r_list_foreach (a->plugins, iter, h) {
if (h->arch) {
if (!strcmp (h->name, name)) {
if (!a->cur || (a->cur && strcmp (a->cur->arch, h->arch))) {
load_asm_descriptions (a, h);
r_asm_set_cpu (a, NULL);
}
if (!strcmp (h->name, name)) {
if (!a->cur || (a->cur && h->arch && strcmp (a->cur->arch, h->arch))) {
load_asm_descriptions (a, h);
r_asm_set_cpu (a, NULL);
}
a->cur = h;
return true;
}
if (dotname && h->arch && !strcmp (dotname, h->arch)) {
char *arch = r_str_ndup (name, vv - name);
#if 0
r_arch_config_set_cpu (a->config, arch);
// r_asm_set_cpu (a, arch);
// h->arch = name;
#else
r_asm_set_cpu (a, arch);
#endif
a->cur = h;
load_asm_descriptions (a, h);
free (arch);
return true;
}
#if 0
} else if (!strcmp (name, h->name)) {
#if 0
r_arch_config_set_cpu (a->config, NULL);
#else
h->arch = name; // leaks wtf is this shit
r_asm_set_cpu (a, NULL);
#endif
a->cur = h;
load_asm_descriptions (a, h);
return true;
}
} else {
// resolve asm plugin by name, support multi-arch assemblers
char *vv = strchr (name, '.');
if (vv) {
if (!strcmp (vv + 1, h->name)) {
char *arch = r_str_ndup (name, vv - name);
#if 0
r_arch_config_set_cpu (a->config, arch);
// r_asm_set_cpu (a, arch);
// h->arch = name;
#else
r_asm_set_cpu (a, arch);
#endif
a->cur = h;
load_asm_descriptions (a, h);
free (arch);
return true;
}
} else {
if (!strcmp (name, h->name)) {
#if 0
r_arch_config_set_cpu (a->config, NULL);
#else
h->arch = name;
r_asm_set_cpu (a, NULL);
#endif
a->cur = h;
load_asm_descriptions (a, h);
return true;
}
}
}
}
if (a->analb.anal) {
if (a->analb.use (a->analb.anal, name)) {
load_asm_descriptions (a, NULL);
// return true;
} else {
R_LOG_ERROR ("Cannot find '%s' asm/arch/anal plugin. See rasm2 -L and rasm2 -LL", name);
R_LOG_ERROR ("Cannot find '%s' asm/arch/anal plugin. See rasm2 -L, -LL or -LLL", name);
}
}
#if 0
@ -425,7 +431,7 @@ R_API bool r_asm_use(RAsm *a, const char *name) {
a->pair = NULL;
#endif
if (strcmp (name, "null")) {
return r_asm_use (a, "null");
return r_asm_use (a, "null"); // x86.nz");
}
return false;
}
@ -581,31 +587,41 @@ R_API int r_asm_disassemble(RAsm *a, RAsmOp *op, const ut8 *buf, int len) {
typedef int (*Ase)(RAsm *a, RAsmOp *op, const char *buf);
static bool assemblerMatches(RAsm *a, RAsmPlugin *h) {
static bool assemblerMatches(RAsm *a, RAsmPlugin *h, const char *ends_with) {
const char *arch = R_UNWRAP3 (a, config, arch);
if (!a || !h->arch || !h->assemble || !has_bits (h, a->config->bits)) {
return false;
}
return (a->cur->arch && !strncmp (a->config->arch, h->arch, strlen (a->cur->arch)));
const char *cur_arch = R_UNWRAP3 (a, cur, arch);
if (!strcmp (h->arch, arch)) {
if (ends_with) {
return r_str_endswith (h->name, ends_with);
}
if ((cur_arch && r_str_startswith (cur_arch, h->arch))) {
return true;
}
}
return false;
}
static Ase findAssembler(RAsm *a, const char *kw) {
RAsmPlugin *h;
RListIter *iter;
if (a->acur && a->acur->assemble) {
return a->acur->assemble;
}
r_list_foreach (a->plugins, iter, h) {
if (assemblerMatches (a, h)) {
if (kw) {
if (strstr (h->name, kw)) {
return h->assemble;
static Ase find_assembler(RAsm *a, const char *kw) {
RAsmAssembleCallback aac = R_UNWRAP3 (a, acur, assemble);
if (!aac) {
RAsmPlugin *h;
RListIter *iter;
r_list_foreach (a->plugins, iter, h) {
if (assemblerMatches (a, h, kw)) {
if (kw) {
if (r_str_endswith (h->name, kw)) {
aac = h->assemble;
break;
}
}
} else {
return h->assemble;
break;
}
}
}
return NULL;
return aac;
}
static char *replace_directives_for(char *str, const char *token) {
@ -620,7 +636,7 @@ static char *replace_directives_for(char *str, const char *token) {
if (p) {
char *nl = strchr (p, '\n');
if (nl) {
*nl ++ = 0;
*nl++ = 0;
}
char _ = *p;
*p = 0;
@ -675,17 +691,17 @@ R_API int r_asm_assemble(RAsm *a, RAsmOp *op, const char *buf) {
if (a->ifilter) {
r_parse_parse (a->ifilter, buf, b);
}
r_str_case (b, 0); // to-lower
memset (op, 0, sizeof (RAsmOp));
r_str_case (b, false); // to-lower
r_asm_op_init (op);
if (a->cur) {
Ase ase = NULL;
if (!a->cur->assemble) {
Ase ase = R_UNWRAP3 (a, cur, assemble);
if (!ase) {
/* find callback if no assembler support in current plugin */
ase = findAssembler (a, ".ks");
ase = find_assembler (a, ".ks");
if (!ase) {
ase = findAssembler (a, ".nz");
ase = find_assembler (a, ".nz");
if (!ase) {
ase = findAssembler (a, NULL);
ase = find_assembler (a, NULL);
}
}
if (!ase && a->analb.anal) {
@ -934,7 +950,7 @@ R_API RAsmCode *r_asm_massemble(RAsm *a, const char *assembly) {
if (cptr && ptr && cptr < ptr) {
likely_comment = false;
for (cptr += 1; cptr < ptr ; cptr += 1) {
if (! isspace ((unsigned char) *cptr)) {
if (! isspace ((int) *cptr)) {
likely_comment = true;
break;
}
@ -955,7 +971,7 @@ R_API RAsmCode *r_asm_massemble(RAsm *a, const char *assembly) {
if (!*ptr_start) {
continue;
}
linenum ++;
linenum++;
/* labels */
if (labels && (ptr = strchr (ptr_start, ':'))) {
bool is_a_label = true;

View File

@ -987,16 +987,18 @@ static cache_imgxtr_t *read_cache_imgextra(RBuffer *cache_buf, cache_hdr_t *hdr,
static char *get_lib_name(RBuffer *cache_buf, cache_img_t *img) {
char file[256];
char *lib_name = file;
const char *lib_name = file;
if (r_buf_read_at (cache_buf, img->pathFileOffset, (ut8*) &file, sizeof (file)) == sizeof (file)) {
file[255] = 0;
/*char * last_slash = strrchr (file, '/');
file[sizeof (file) - 1] = 0; // wtf
#if 0
char * last_slash = strrchr (file, '/');
if (last_slash && *last_slash) {
lib_name = last_slash + 1;
}*/
}
#endif
return strdup (lib_name);
}
return strdup ("FAIL");
return strdup ("FAIL"); /// XXX return NULL instead
}
static int string_contains(const void *a, const void *b) {

View File

@ -154,12 +154,14 @@ static bool nextpal_item(RCore *core, PJ *pj, int mode, const char *file) {
static bool cmd_load_theme(RCore *core, const char *_arg) {
bool failed = false;
char *path;
if (!_arg || !*_arg) {
if (R_STR_ISEMPTY (_arg)) {
return false;
}
if (!strcmp (_arg, "default")) {
free (core->theme);
core->theme = strdup (_arg);
if (_arg != core->theme) {
free (core->theme);
core->theme = strdup (_arg);
}
r_cons_pal_init (core->cons->context);
return true;
}

View File

@ -1885,7 +1885,6 @@ extern RAnalPlugin r_anal_plugin_dalvik;
extern RAnalPlugin r_anal_plugin_ebc;
extern RAnalPlugin r_anal_plugin_gb;
extern RAnalPlugin r_anal_plugin_h8300;
extern RAnalPlugin r_anal_plugin_i4004;
extern RAnalPlugin r_anal_plugin_i8080;
extern RAnalPlugin r_anal_plugin_java;
extern RAnalPlugin r_anal_plugin_kvx;

View File

@ -93,6 +93,8 @@ typedef struct r_arch_t {
bool autoselect;
} RArch;
typedef int (*RArchOpAsmCallback)(RArch *a, ut64 addr, const char *str, ut8 *outbuf, int outlen);
typedef struct r_arch_plugin_t {
char *name;
char *desc;
@ -110,6 +112,7 @@ typedef struct r_arch_plugin_t {
int (*info)(RArchConfig *cfg, ut32 query);
int (*decode)(RArchConfig *cfg, struct r_anal_op_t *op, ut64 addr, const ut8 *data, int len, ut32 mask, void *user);
bool (*set_reg_profile)(RArchConfig *cfg, struct r_reg_t *reg);
RArchOpAsmCallback opasm;
//TODO: reenable this later
// bool (*esil_init)(RAnalEsil *esil);
// void (*esil_fini)(RAnalEsil *esil);
@ -122,13 +125,14 @@ R_API bool r_arch_use_decoder(RArch *arch, const char *dname);
R_API bool r_arch_unload_decoder(RArch *arch, const char *dname);
R_API int r_arch_info(RArch *arch, const char *dname, ut32 query);
R_API int r_arch_decode(RArch *arch, const char *dname, struct r_anal_op_t *op, ut64 addr, const ut8 *data, int len, ut32 mask);
R_API int r_arch_encode(RArch *a, ut64 addr, const char *s, ut8 *outbuf, int outlen);
R_API bool r_arch_set_reg_profile(RArch *arch, const char *dname, struct r_reg_t *reg);
//R_API bool r_arch_esil_init(RArch *arch, const char *dname, RAnalEsil *esil);
//R_API void r_arch_esil_fini(RArch *arch, const char *dname, RAnalEsil *esil);
// arch.c
R_API RArch *r_arch_new(void);
R_API bool r_arch_use(RArch *arch, RArchConfig *config);
R_API bool r_arch_use(RArch *arch, RArchConfig *config, const char *name);
R_API bool r_arch_set_bits(RArch *arch, ut32 bits);
R_API bool r_arch_set_endian(RArch *arch, ut32 endian);
R_API bool r_arch_set_arch(RArch *arch, char *archname);

View File

@ -97,6 +97,7 @@ typedef struct r_asm_t {
} RAsm;
typedef bool (*RAsmModifyCallback)(RAsm *a, ut8 *buf, int field, ut64 val);
typedef int (*RAsmAssembleCallback)(RAsm *a, RAsmOp *op, const char *buf);
typedef struct r_asm_plugin_t {
const char *name;
@ -112,7 +113,8 @@ typedef struct r_asm_plugin_t {
bool (*init)(void *user);
bool (*fini)(void *user);
int (*disassemble)(RAsm *a, RAsmOp *op, const ut8 *buf, int len);
int (*assemble)(RAsm *a, RAsmOp *op, const char *buf);
RAsmAssembleCallback assemble;
RAsmModifyCallback modify;
char *(*mnemonics)(RAsm *a, int id, bool json);
const char *features;
@ -129,12 +131,14 @@ R_API void r_asm_set_user_ptr(RAsm *a, void *user);
R_API bool r_asm_add(RAsm *a, RAsmPlugin *foo);
R_API bool r_asm_setup(RAsm *a, const char *arch, int bits, int big_endian);
R_API bool r_asm_is_valid(RAsm *a, const char *name);
R_API bool r_asm_use(RAsm *a, const char *name);
R_API bool r_asm_use_assembler(RAsm *a, const char *name);
R_API bool r_asm_set_arch(RAsm *a, const char *name, int bits);
R_API int r_asm_set_bits(RAsm *a, int bits);
R_API void r_asm_set_cpu(RAsm *a, const char *cpu);
R_API bool r_asm_set_big_endian(RAsm *a, bool big_endian);
R_API bool r_asm_set_syntax(RAsm *a, int syntax);
R_API int r_asm_syntax_from_string(const char *name);
R_API int r_asm_set_pc(RAsm *a, ut64 pc);

View File

@ -231,6 +231,11 @@ typedef struct _utX {
#define R_PACKED( __Declaration__ ) __Declaration__ __attribute__((__packed__))
#endif
#define R_UNWRAP2(a,b) ((a)? a->b: NULL)
#define R_UNWRAP3(a,b,c) ((a)? a->b? a->b->c: NULL: NULL)
#define R_UNWRAP4(a,b,c,d) ((a)? a->b? a->b->c? a->b->c->d: NULL: NULL: NULL)
#define R_UNWRAP5(a,b,c,d,e) ((a)? a->b? a->b->c? a->b->c->d: a->b->c->d->e: NULL: NULL: NULL: NULL)
#ifdef __GNUC__
#define R_UNUSED __attribute__((__unused__))
#define R_WEAK __attribute__ ((weak))

View File

@ -150,7 +150,6 @@ anal_plugins += [
'evm_cs',
'gb',
'h8300',
'i4004',
'i8080',
'java',
'kvx',