Pseudo refactoring (#1308)

* License fix
* Implemented common pseudo
* Refactored MIPS pseudo
* Refactored ARM pseudo
* Refactored AVR pseudo
* Refactored 6502 pseudo
* Refactored dalvik pseudo
* Refactored arm64 pseudo
* Refactored z80 pseudo
* Refactored TMS320 pseudo
* Refactored v850 pseudo
* Refactored SuperH pseudo
* Refactored Motorola 68K pseudo
* Avoid selecting a pseudo plugin when the arch is not found.
* rz_parse_parse -> rz_parse_pseudocode
This commit is contained in:
Giovanni 2021-07-22 11:55:05 +02:00 committed by GitHub
parent ebd7b7b06b
commit 35558f4180
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
33 changed files with 1834 additions and 2139 deletions

View file

@ -23,13 +23,8 @@ static RzAsmPlugin *asm_static_plugins[] = { RZ_ASM_STATIC_PLUGINS };
static void parseHeap(RzParse *p, RzStrBuf *s) {
char *op_buf_asm = rz_strbuf_get(s);
size_t len = rz_strbuf_length(s);
char *out = malloc(64 + (len * 2));
char *out = rz_parse_pseudocode(p, op_buf_asm);
if (out) {
*out = 0;
strcpy(out, op_buf_asm);
// XXX we shouldn't pad here because we have t orefactor the RzParse API to handle boundaries and chunks properly
rz_parse_parse(p, op_buf_asm, out);
rz_strbuf_set(s, out);
free(out);
}
@ -575,7 +570,11 @@ RZ_API int rz_asm_assemble(RzAsm *a, RzAsmOp *op, const char *buf) {
return 0;
}
if (a->ifilter) {
rz_parse_parse(a->ifilter, buf, b);
char *tmp = rz_parse_pseudocode(a->ifilter, buf);
if (tmp) {
free(b);
b = tmp;
}
}
rz_str_case(b, 0); // to-lower
memset(op, 0, sizeof(RzAsmOp));
@ -659,8 +658,11 @@ RZ_API RzAsmCode *rz_asm_mdisassemble_hexstr(RzAsm *a, RzParse *p, const char *h
}
RzAsmCode *ret = rz_asm_mdisassemble(a, buf, (ut64)len);
if (ret && p) {
// XXX this can crash
rz_parse_parse(p, ret->assembly, ret->assembly);
char *tmp = rz_parse_pseudocode(p, ret->assembly);
if (tmp) {
free(ret->assembly);
ret->assembly = tmp;
}
}
free(buf);
return ret;
@ -987,9 +989,6 @@ RZ_API RzAsmCode *rz_asm_massemble(RzAsm *a, const char *assembly) {
} else { /* Instruction */
char *str = ptr_start;
rz_str_trim(str);
if (a->ifilter) {
rz_parse_parse(a->ifilter, ptr_start, ptr_start);
}
if (acode->equs) {
if (!*ptr_start) {
continue;

View file

@ -43,7 +43,9 @@ static void loadGP(RzCore *core) {
ut64 gp = rz_num_math(core->num, "loc._gp");
if (!gp || gp == UT64_MAX) {
rz_config_set(core->config, "analysis.roregs", "zero");
rz_core_cmd0(core, "10aes@entry0");
ut64 addr = rz_num_math(core->num, "entry");
rz_core_seek_opt(core, addr, true, false);
rz_core_debug_step_one(core, 10);
rz_config_set(core->config, "analysis.roregs", "zero,gp");
gp = rz_reg_getv(core->analysis->reg, "gp");
}

View file

@ -1637,9 +1637,8 @@ static void core_analysis_bytes(RzCore *core, const ut8 *buf, int len, int nops,
pj_ks(pj, "disasm", strsub);
// apply pseudo if needed
{
char *pseudo = calloc(128 + strlen(strsub), 3);
rz_parse_parse(core->parser, strsub, pseudo);
if (pseudo && *pseudo) {
char *pseudo = rz_parse_pseudocode(core->parser, strsub);
if (RZ_STR_ISNOTEMPTY(pseudo)) {
pj_ks(pj, "pseudo", pseudo);
}
free(pseudo);
@ -1798,9 +1797,8 @@ static void core_analysis_bytes(RzCore *core, const ut8 *buf, int len, int nops,
}
printline("disasm", "%s\n", disasm);
{
char *pseudo = calloc(128 + strlen(disasm), 3);
rz_parse_parse(core->parser, disasm, pseudo);
if (pseudo && *pseudo) {
char *pseudo = rz_parse_pseudocode(core->parser, disasm);
if (RZ_STR_ISNOTEMPTY(pseudo)) {
printline("pseudo", "%s\n", pseudo);
}
free(pseudo);

View file

@ -1051,7 +1051,19 @@ static void ds_build_op_str(RDisasmState *ds, bool print_color) {
return;
}
if (!ds->opstr) {
ds->opstr = strdup(rz_asm_op_get_asm(&ds->asmop));
const char *assembly = rz_asm_op_get_asm(&ds->asmop);
if (ds->pseudo) {
char *tmp = rz_parse_pseudocode(core->parser, assembly);
if (tmp) {
snprintf(ds->str, sizeof(ds->str), "%s", tmp);
ds->opstr = tmp;
} else {
ds->opstr = strdup("");
ds->str[0] = 0;
}
} else {
ds->opstr = strdup(assembly);
}
}
if (ds->opstr && core->bin && core->bin->cur) {
RzBinPlugin *plugin = rz_bin_file_cur_plugin(core->bin->cur);
@ -1095,12 +1107,6 @@ static void ds_build_op_str(RDisasmState *ds, bool print_color) {
}
}
if (ds->pseudo) {
const char *opstr = ds->opstr ? ds->opstr : rz_asm_op_get_asm(&ds->asmop);
rz_parse_parse(core->parser, opstr, ds->str);
free(ds->opstr);
ds->opstr = strdup(ds->str);
}
ds->opstr = ds_sub_jumps(ds, ds->opstr);
if (ds->immtrim) {
char *res = rz_parse_immtrim(ds->opstr);
@ -2585,10 +2591,16 @@ static int ds_disassemble(RDisasmState *ds, ut8 *buf, int len) {
ds->oplen = ds->asmop.size;
}
if (ds->pseudo) {
rz_parse_parse(core->parser, ds->opstr ? ds->opstr : rz_asm_op_get_asm(&ds->asmop),
ds->str);
const char *opstr = rz_asm_op_get_asm(&ds->asmop);
char *tmp = rz_parse_pseudocode(core->parser, opstr);
free(ds->opstr);
ds->opstr = strdup(ds->str);
if (tmp) {
snprintf(ds->str, sizeof(ds->str), "%s", tmp);
ds->opstr = tmp;
} else {
ds->opstr = strdup("");
ds->str[0] = 0;
}
}
if (ds->acase) {
rz_str_case(rz_asm_op_get_asm(&ds->asmop), 1);
@ -5997,7 +6009,11 @@ RZ_API int rz_core_print_disasm_json(RzCore *core, ut64 addr, ut8 *buf, int nb_b
rz_analysis_op(core->analysis, &ds->analop, at, buf + i, nb_bytes - i, RZ_ANALYSIS_OP_MASK_ALL);
if (ds->pseudo) {
rz_parse_parse(core->parser, opstr, opstr);
char *tmp = rz_parse_pseudocode(core->parser, opstr);
if (tmp) {
snprintf(opstr, sizeof(opstr), "%s", tmp);
}
free(tmp);
}
// f = rz_analysis_get_fcn_in (core->analysis, at,

View file

@ -454,7 +454,7 @@ RZ_API bool rz_core_run_script(RzCore *core, const char *file);
RZ_API void rz_core_seek_item_free(RzCoreSeekItem *item);
RZ_API bool rz_core_seek(RzCore *core, ut64 addr, bool rb);
RZ_API bool rz_core_seek_and_save(RzCore *core, ut64 addr, bool rb);
RZ_API bool rz_core_seek_opt(RzCore *core, ut64 addr, bool rb, bool save);
RZ_API bool rz_core_seek_opt(RzCore *core, ut64 addr, bool read_block, bool save);
RZ_API bool rz_core_seek_mark(RzCore *core);
RZ_API bool rz_core_seek_save(RzCore *core);
RZ_API bool rz_core_seek_undo(RzCore *core);

View file

@ -47,7 +47,7 @@ typedef struct rz_parse_plugin_t {
char *desc;
bool (*init)(RzParse *p, void *user);
int (*fini)(RzParse *p, void *user);
int (*parse)(RzParse *p, const char *data, char *str);
bool (*parse)(RzParse *p, const char *data, RzStrBuf *sb);
bool (*assemble)(RzParse *p, char *data, char *str);
int (*filter)(RzParse *p, ut64 addr, RzFlag *f, char *data, char *str, int len, bool big_endian);
bool (*subvar)(RzParse *p, RzAnalysisFunction *f, ut64 addr, int oplen, char *data, char *str, int len);
@ -66,7 +66,7 @@ RZ_API bool rz_parse_add(RzParse *p, RzParsePlugin *foo);
RZ_API bool rz_parse_use(RzParse *p, const char *name);
/* action */
RZ_API bool rz_parse_parse(RzParse *p, const char *data, char *str);
RZ_API char *rz_parse_pseudocode(RzParse *p, const char *data);
RZ_API bool rz_parse_assemble(RzParse *p, char *data, char *str); // XXX deprecate, unused and probably useless, related to write-hack
RZ_API bool rz_parse_filter(RzParse *p, ut64 addr, RzFlag *f, RzAnalysisHint *hint, char *data, char *str, int len, bool big_endian);
RZ_API bool rz_parse_subvar(RzParse *p, RzAnalysisFunction *f, ut64 addr, int oplen, char *data, char *str, int len);

View file

@ -1,5 +1,4 @@
// SPDX-FileCopyrightText: 2015 pancake <pancake@nopcode.org>
// SPDX-FileCopyrightText: 2015 qnix <qnix@0x80.org>
// SPDX-FileCopyrightText: 2021 deroad <wargio@libero.it>
// SPDX-License-Identifier: LGPL-3.0-only
#include <stdio.h>
@ -12,177 +11,111 @@
#include <rz_analysis.h>
#include <rz_parse.h>
typedef enum {
IND_IDX = 0,
IDX_IND = 1,
NORM = 2,
} ADDR_TYPE;
#include "parse_common.c"
static int replace(int argc, const char *argv[], char *newstr, ADDR_TYPE type) {
int i, j, k;
struct {
int narg;
char *op;
char *str;
} ops[] = {
{ 1, "lda", "a = 1" },
{ 2, "lda", "a = (1+2)" },
{ 1, "ldx", "x = 1" },
{ 2, "ldx", "x = (1+2)" },
{ 1, "ldy", "y = 1" },
{ 2, "ldy", "y = (1+2)" },
{ 1, "sta", "[1] = a" },
{ 2, "sta", "[1+2 ] = a" },
{ 1, "stx", "[1] = x" },
{ 2, "stx", "[1+2] = x" },
{ 1, "sty", "[1] = y" },
{ 2, "sty", "[1+2] = y" },
{ 1, "dec", "1--" },
{ 2, "dec", "(1+2)--" },
{ 0, "dcx", "x--" },
{ 0, "dcy", "y--" },
{ 1, "inc", "1++" },
{ 2, "inc", "(1+2)++" },
{ 0, "inx", "x++" },
{ 0, "iny", "y++" },
{ 1, "adc", "a += 1" },
{ 2, "adc", "a += (1+2)" },
{ 1, "sbc", "a -= 1" },
{ 2, "sbc", "a -= (1+2)" },
{ 0, "pha", "push a" },
{ 1, "and", "a &= 1" },
{ 2, "and", "a &= (1+2)" },
{ 1, "eor", "a ^= 1" },
{ 2, "eor", "a ^= (1+2)" },
{ 1, "ora", "a |= 1" },
{ 2, "ora", "a |= (1+2)" },
{ 0, "tax", "x = a" },
{ 0, "tay", "y = a" },
{ 0, "txa", "a = x" },
{ 0, "tya", "a = y" },
{ 0, "tsx", "x = s" },
{ 0, "txs", "s = x" },
{ 0, "brk", "break" },
{ 0, "clc", "clear_carry" },
{ 0, "cld", "clear_decimal" },
{ 0, "cli", "clear_interrupt" },
{ 0, "clv", "clear_overflow" },
{ 0, "sec", "set_carry" },
{ 0, "sed", "set_decimal" },
{ 0, "sei", "set_interrupt" },
{ 1, "jsr", "1()" },
{ 0, NULL }
};
if (!newstr) {
return false;
static RzList *_6502_tokenize(const char *assembly, size_t length);
static const RzPseudoGrammar _6502_lexicon[] = {
RZ_PSEUDO_DEFINE_GRAMMAR("adc", "a += (1 + 2)"),
RZ_PSEUDO_DEFINE_GRAMMAR("and", "a &= (1 + 2)"),
RZ_PSEUDO_DEFINE_GRAMMAR("asl", "a = 1 << #1"),
RZ_PSEUDO_DEFINE_GRAMMAR("bcc", "if (carry == 0) goto 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("bcs", "if (carry != 0) goto 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("beq", "if (eq) goto 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("bmi", "if (lt) goto 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("bne", "if (ne) goto 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("bpl", "if (gt) goto 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("brk", "break"),
RZ_PSEUDO_DEFINE_GRAMMAR("clc", "carry = 0"),
RZ_PSEUDO_DEFINE_GRAMMAR("cld", "decimal = 0"),
RZ_PSEUDO_DEFINE_GRAMMAR("cli", "interrupt = 0"),
RZ_PSEUDO_DEFINE_GRAMMAR("clv", "overflow = 0"),
RZ_PSEUDO_DEFINE_GRAMMAR("cmp", "cmp (1, 2)"),
RZ_PSEUDO_DEFINE_GRAMMAR("cpx", "cmp (x, 1)"),
RZ_PSEUDO_DEFINE_GRAMMAR("cpy", "cmp (y, 1)"),
RZ_PSEUDO_DEFINE_GRAMMAR("dcx", "x--"),
RZ_PSEUDO_DEFINE_GRAMMAR("dcy", "y--"),
RZ_PSEUDO_DEFINE_GRAMMAR("dec", "(1 + 2)--"),
RZ_PSEUDO_DEFINE_GRAMMAR("dex", "x--"),
RZ_PSEUDO_DEFINE_GRAMMAR("dey", "y--"),
RZ_PSEUDO_DEFINE_GRAMMAR("eor", "a ^= (1 + 2)"),
RZ_PSEUDO_DEFINE_GRAMMAR("inc", "(1 + 2)++"),
RZ_PSEUDO_DEFINE_GRAMMAR("inc", "1++"),
RZ_PSEUDO_DEFINE_GRAMMAR("inx", "x++"),
RZ_PSEUDO_DEFINE_GRAMMAR("iny", "y++"),
RZ_PSEUDO_DEFINE_GRAMMAR("jmp", "goto 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("jsr", "1 ()"),
RZ_PSEUDO_DEFINE_GRAMMAR("lda", "a = (1 + 2)"),
RZ_PSEUDO_DEFINE_GRAMMAR("ldx", "x = (1 + 2)"),
RZ_PSEUDO_DEFINE_GRAMMAR("ldy", "y = (1 + 2)"),
RZ_PSEUDO_DEFINE_GRAMMAR("nop", ""),
RZ_PSEUDO_DEFINE_GRAMMAR("ora", "a |= (1 + 2)"),
RZ_PSEUDO_DEFINE_GRAMMAR("pha", "push a"),
RZ_PSEUDO_DEFINE_GRAMMAR("rti", "return"),
RZ_PSEUDO_DEFINE_GRAMMAR("rts", "return"),
RZ_PSEUDO_DEFINE_GRAMMAR("sbc", "a -= (1 + 2)"),
RZ_PSEUDO_DEFINE_GRAMMAR("sec", "carry = #1"),
RZ_PSEUDO_DEFINE_GRAMMAR("sed", "decimal = #1"),
RZ_PSEUDO_DEFINE_GRAMMAR("sei", "interrupt = #1"),
RZ_PSEUDO_DEFINE_GRAMMAR("sta", "[1 + 2] = a"),
RZ_PSEUDO_DEFINE_GRAMMAR("stx", "[1 + 2] = x"),
RZ_PSEUDO_DEFINE_GRAMMAR("sty", "[1 + 2] = y"),
RZ_PSEUDO_DEFINE_GRAMMAR("tax", "x = a"),
RZ_PSEUDO_DEFINE_GRAMMAR("tay", "y = a"),
RZ_PSEUDO_DEFINE_GRAMMAR("tsx", "x = s"),
RZ_PSEUDO_DEFINE_GRAMMAR("txa", "a = x"),
RZ_PSEUDO_DEFINE_GRAMMAR("txs", "s = x"),
RZ_PSEUDO_DEFINE_GRAMMAR("tya", "a = y"),
};
static const RzPseudoConfig _6502_config = RZ_PSEUDO_DEFINE_CONFIG_ONLY_LEXICON(_6502_lexicon, 3, _6502_tokenize);
RzList *_6502_tokenize(const char *assembly, size_t length) {
size_t i, p;
char *buf = NULL;
bool insert_zero = false;
RzList *tokens = NULL;
buf = rz_str_ndup(assembly, length);
if (!buf) {
return NULL;
}
for (i = 0; ops[i].op != NULL; i++) {
if (ops[i].narg) {
if (argc - 1 != ops[i].narg) {
continue;
for (i = 0, p = 0; p < length; ++i, ++p) {
if (buf[p] == ',') {
buf[p] = ' ';
} else if (buf[p] == '#') {
p++;
} else if (buf[p] == '(') {
buf[p] = ' ';
if (!IS_HEXCHAR(buf[p - 1])) {
p++;
insert_zero = true;
}
} else if (buf[p] == ')') {
buf[p] = 0;
}
if (!strcmp(ops[i].op, argv[0])) {
for (j = k = 0; ops[i].str[j] != '\0'; j++, k++) {
if (IS_DIGIT(ops[i].str[j])) {
const char *w = argv[ops[i].str[j] - '0'];
if (w != NULL) {
strcpy(newstr + k, w);
k += strlen(w) - 1;
}
} else {
newstr[k] = ops[i].str[j];
}
}
newstr[k] = '\0';
if (argc == 4 && argv[2][0] == '[') {
strcat(newstr + k, "+");
strcat(newstr + k + 3, argv[2]);
}
return true;
if (p > i) {
buf[i] = buf[p];
}
}
buf[i] = 0;
/* TODO: this is slow */
newstr[0] = '\0';
for (i = 0; i < argc; i++) {
strcat(newstr, argv[i]);
strcat(newstr, (i == 0 || i == argc - 1) ? " " : ",");
}
return false;
}
static ADDR_TYPE addr_type(const char *str) {
if (strchr(str, '(')) {
char *e = strchr(str, ')');
if (!e) {
return NORM;
}
char *o = strchr(e, ',');
return (o) ? IND_IDX : IDX_IND;
}
return NORM;
}
static int parse(RzParse *p, const char *data, char *str) {
char w0[256], w1[256], w2[256];
int i, len = strlen(data);
char *buf, *ptr, *optr;
ADDR_TYPE atype;
if (len >= sizeof(w0)) {
return false;
}
// malloc can be slow here :?
if (!(buf = malloc(len + 1))) {
return false;
}
memcpy(buf, data, len + 1);
if (*buf) {
atype = addr_type(buf);
rz_str_replace_char(buf, '(', ' ');
rz_str_replace_char(buf, ')', ' ');
*w0 = *w1 = *w2 = '\0';
ptr = strchr(buf, ' ');
if (!ptr) {
ptr = strchr(buf, '\t');
}
if (ptr) {
*ptr = '\0';
for (++ptr; *ptr == ' '; ptr++) {
;
}
strncpy(w0, buf, sizeof(w0) - 1);
strncpy(w1, ptr, sizeof(w1) - 1);
optr = ptr;
ptr = strchr(ptr, ',');
if (ptr) {
*ptr = '\0';
for (++ptr; *ptr == ' '; ptr++) {
;
}
strncpy(w1, optr, sizeof(w1) - 1);
strncpy(w2, ptr, sizeof(w2) - 1);
}
} else {
strncpy(w0, buf, sizeof(w0) - 1);
}
const char *wa[] = { w0, w1, w2 };
int nw = 0;
for (i = 0; i < 3; i++) {
if (wa[i][0]) {
nw++;
}
}
replace(nw, wa, str, atype);
}
tokens = rz_str_split_duplist(buf, " ", true);
free(buf);
if (!tokens) {
return NULL;
}
return true;
if (insert_zero) {
rz_list_insert(tokens, rz_list_length(tokens) - 1, strdup("0"));
}
return tokens;
}
static bool parse(RzParse *parse, const char *assembly, RzStrBuf *sb) {
return rz_pseudo_convert(&_6502_config, assembly, sb);
}
RzParsePlugin rz_parse_plugin_6502_pseudo = {

View file

@ -1,4 +1,5 @@
// SPDX-FileCopyrightText: 2015-2018 pancake <pancake@nopcode.org>
// SPDX-FileCopyrightText: 2021 deroad <wargio@libero.it>
// SPDX-License-Identifier: LGPL-3.0-only
#include <stdio.h>
@ -10,272 +11,198 @@
#include <rz_analysis.h>
#include <rz_parse.h>
static int replace(int argc, const char *argv[], char *newstr) {
#define MAXPSEUDOOPS 10
int i, j, k, d;
char ch;
struct {
int narg;
char *op;
char *str;
int args[MAXPSEUDOOPS];
} ops[] = {
{ 0, "abs", "# = abs(#)", { 1, 1 } },
{ 0, "adc", "# = # + #", { 1, 2, 3 } },
{ 3, "add", "# = # + #", { 1, 2, 3 } },
{ 2, "add", "# += #", { 1, 2 } },
{ 2, "adds", "# += #", { 1, 2 } },
{ 3, "adds", "# = # + #", { 1, 2, 3 } },
{ 3, "addw", "# = # + #", { 1, 2, 3 } },
{ 3, "add.w", "# = # + #", { 1, 2, 3 } },
{ 0, "adf", "# = # + #", { 1, 2, 3 } },
{ 0, "adrp", "# = #", { 1, 2 } },
{ 0, "adr", "# = #", { 1, 2 } },
{ 0, "and", "# = # & #", { 1, 2, 3 } },
{ 0, "ands", "# &= #", { 1, 2 } },
{ 0, "asls", "# = # << #", { 1, 2, 3 } },
{ 0, "asl", "# = # << #", { 1, 2, 3 } },
{ 0, "asrs", "# = # >> #", { 1, 2, 3 } },
{ 0, "asr", "# = # >> #", { 1, 2, 3 } },
{ 0, "b", "jmp #", { 1 } },
{ 0, "cbz", "if !# jmp #", { 1, 2 } },
{ 0, "cbnz", "if # jmp #", { 1, 2 } },
{ 0, "b.w", "jmp #", { 1 } },
{ 0, "b.gt", "jmp ifgt #", { 1 } },
{ 0, "b.le", "jmp ifle #", { 1 } },
{ 0, "beq lr", "ifeq ret", { 0 } },
{ 0, "beq", "je #", { 1 } },
{ 0, "call", "# ()", { 1 } },
{ 0, "bl", "# ()", { 1 } },
{ 0, "blx", "# ()", { 1 } },
{ 0, "bx lr", "ret", { 0 } },
{ 0, "bxeq", "je #", { 1 } },
{ 0, "cmf", "if (# == #)", { 1, 2 } },
{ 0, "cmn", "if (# != #)", { 1, 2 } },
{ 0, "cmp", "if (# == #)", { 1, 2 } },
{ 0, "fcmp", "if (# == #)", { 1, 2 } },
{ 0, "tst", "if ((# & #) == 0)", { 1, 2 } },
{ 0, "dvf", "# = # / #", { 1, 2, 3 } },
{ 0, "eor", "# = # ^ #", { 1, 2, 3 } },
{ 1, "bkpt", "breakpoint #", { 1 } },
{ 1, "udf", "undefined #", { 1 } },
{ 2, "sxtb", "# = (char) #", { 1, 2 } },
{ 2, "sxth", "# = (short) #", { 1, 2 } },
{ 0, "fdv", "# = # / #", { 1, 2, 3 } },
{ 0, "fml", "# = # * #", { 1, 2, 3 } },
{ 2, "ldr", "# = #", { 1, 2 } },
{ 2, "ldrh", "# = (word) #", { 1, 2 } },
{ 3, "ldrh", "# = (word) # + #", { 1, 2, 3 } },
{ 2, "ldrb", "# = (byte) #", { 1, 2 } },
{ 3, "ldrb", "# = (byte) # + #", { 1, 2, 3 } },
{ 2, "ldrsb", "# = (byte) #", { 1, 2 } },
{ 2, "ldr.w", "# = #", { 1, 2 } },
{ 2, "ldrsw", "# = #", { 1, 2 } },
{ 3, "ldr", "# = # + #", { 1, 2, 3 } },
{ 3, "ldrb", "# = (byte) # + #", { 1, 2, 3 } },
{ 3, "ldrsb", "# = (byte) # + #", { 1, 2, 3 } },
{ 3, "ldr.w", "# = # + #", { 1, 2, 3 } },
{ 3, "ldrsw", "# = # + #", { 1, 2, 3 } },
{ 0, "lsl", "# = # << #", { 1, 2, 3 } },
{ 0, "lsr", "# = # >> #", { 1, 2, 3 } },
{ 0, "mov", "# = #", { 1, 2 } },
{ 0, "fmov", "# = #", { 1, 2 } },
{ 0, "mvn", "# = ~#", { 1, 2 } },
{ 0, "movz", "# = #", { 1, 2 } },
{ 0, "movk", "# = #", { 1, 2 } },
{ 0, "movn", "# = ~#", { 1, 2 } },
{ 0, "neg", "# = !#", { 1, 2 } },
{ 0, "sxtw", "# = #", { 1, 2 } },
{ 0, "stur", "# = #", { 2, 1 } },
{ 0, "stp", "# = (#, 2)", { 3, 1 } },
{ 0, "ldp", "(#, 2) = 3", { 1 } },
{ 0, "vmov.i32", "# = #", { 1, 2 } },
{ 0, "muf", "# = # * #", { 1, 2, 3 } },
{ 0, "mul", "# = # * #", { 1, 2, 3 } },
{ 0, "fmul", "# = # * #", { 1, 2, 3 } },
{ 0, "muls", "# = # * #", { 1, 2, 3 } },
{ 0, "div", "# = # / #", { 1, 2, 3 } },
{ 0, "fdiv", "# = # / #", { 1, 2, 3 } },
{ 0, "udiv", "# = (unsigned) # / #", { 1, 2, 3 } },
{ 0, "orr", "# = # | #", { 1, 2, 3 } },
{ 0, "rmf", "# = # % #", { 1, 2, 3 } },
{ 0, "bge", "(>=) goto #", { 1 } },
{ 0, "sbc", "# = # - #", { 1, 2, 3 } },
{ 0, "sqt", "# = sqrt(#)", { 1, 2 } },
{ 0, "lsrs", "# = # >> #", { 1, 2, 3 } },
{ 0, "lsls", "# = # << #", { 1, 2, 3 } },
{ 0, "lsr", "# = # >> #", { 1, 2, 3 } },
{ 0, "lsl", "# = # << #", { 1, 2, 3 } },
{ 2, "str", "# = #", { 2, 1 } },
{ 2, "strb", "# = (byte) #", { 2, 1 } },
{ 2, "strh", "# = (half) #", { 2, 1 } },
{ 2, "strh.w", "# = (half) #", { 2, 1 } },
{ 3, "str", "# + # = #", { 2, 3, 1 } },
{ 3, "strb", "# + # = (byte) #", { 2, 3, 1 } },
{ 3, "strh", "# + # = (half) #", { 2, 3, 1 } },
{ 3, "strh.w", "# + # = (half) #", { 2, 3, 1 } },
{ 3, "sub", "# = # - #", { 1, 2, 3 } },
{ 3, "subs", "# = # - #", { 1, 2, 3 } },
{ 3, "fsub", "# = # - #", { 1, 2, 3 } },
{ 2, "sub", "# -= #", { 1, 2 } }, // THUMB
{ 2, "subs", "# -= #", { 1, 2 } }, // THUMB
{ 0, "swp", "swap(#, 2)", { 1 } },
/* arm thumb */
{ 0, "movs", "# = #", { 1, 2 } },
{ 0, "movw", "# = #", { 1, 2 } },
{ 0, "movt", "# |= # << 16", { 1, 2 } },
{ 0, "vmov", "# = (float) # . #", { 1, 2, 3 } },
{ 0, "vdiv.f64", "# = (float) # / #", { 1, 2, 3 } },
{ 0, "addw", "# = # + #", { 1, 2, 3 } },
{ 0, "sub.w", "# = # - #", { 1, 2, 3 } },
{ 0, "tst.w", "if ((# & #) == 0)", { 1, 2 } },
{ 0, "lsr.w", "# = # >> #", { 1, 2, 3 } },
{ 0, "lsl.w", "# = # << #", { 1, 2, 3 } },
{ 0, "pop.w", "pop #", { 1 } },
{ 0, "vpop", "pop #", { 1 } },
{ 0, "vpush", "push #", { 1 } },
{ 0, "push.w", "push #", { 1 } },
{ 0, NULL }
};
if (!newstr) {
return false;
#include "parse_common.c"
static RzList *arm_tokenize(const char *assembly, size_t length);
static const RzPseudoGrammar arm_lexicon[] = {
RZ_PSEUDO_DEFINE_GRAMMAR("abs", "1 = abs(1)"),
RZ_PSEUDO_DEFINE_GRAMMAR("adc", "1 = 2 + 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("add", "1 = 2 + 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("add.w", "1 = 2 + 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("adds", "1 = 2 + 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("addw", "1 = 2 + 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("adf", "1 = 2 + 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("adr", "1 = 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("adrp", "1 = 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("and", "1 = 2 & 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("ands", "1 &= 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("asl", "1 = 2 << 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("asls", "1 = 2 << 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("asr", "1 = 2 >> 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("asrs", "1 = 2 >> 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("b", "goto 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("b.gt", "if (? > ?) goto 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("b.le", "if (? < ?) goto 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("b.w", "goto 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("beq", "if (? == ?) goto 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("bge", "if (? >= ?) goto 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("bkpt", "breakpoint 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("bl", "1 ()"),
RZ_PSEUDO_DEFINE_GRAMMAR("blx", "1 ()"),
RZ_PSEUDO_DEFINE_GRAMMAR("bxeq", "if (? == ?) goto 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("call", "1 ()"),
RZ_PSEUDO_DEFINE_GRAMMAR("cbnz", "if (1) goto 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("cbz", "if (!1) goto 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("cmf", "if (1 == 2)"),
RZ_PSEUDO_DEFINE_GRAMMAR("cmn", "if (1 != 2)"),
RZ_PSEUDO_DEFINE_GRAMMAR("cmp", "if (1 == 2)"),
RZ_PSEUDO_DEFINE_GRAMMAR("div", "1 = 2 / 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("dvf", "1 = 2 / 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("eor", "1 = 2 ^ 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("fcmp", "if (1 == 2)"),
RZ_PSEUDO_DEFINE_GRAMMAR("fdiv", "1 = 2 / 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("fdv", "1 = 2 / 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("fml", "1 = 2 * 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("fmov", "1 = 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("fmul", "1 = 2 * 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("fsub", "1 = 2 - 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("ldp", "(1, 2) = 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("ldr", "1 = 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("ldr.w", "1 = 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("ldrb", "1 = (byte) 2 + 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("ldrh", "1 = (word) 2 + 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("ldrsb", "1 = (byte) 2 + 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("ldrsw", "1 = 2 + 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("ldrsw", "1 = 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("lsl", "1 = 2 << 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("lsls", "1 = 2 << 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("lsr", "1 = 2 >> 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("lsrs", "1 = 2 >> 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("mov", "1 = 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("movk", "1 = 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("movn", "1 = ~2"),
RZ_PSEUDO_DEFINE_GRAMMAR("movz", "1 = 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("muf", "1 = 2 * 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("mul", "1 = 2 * 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("muls", "1 = 2 * 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("mvn", "1 = ~2"),
RZ_PSEUDO_DEFINE_GRAMMAR("neg", "1 = !2"),
RZ_PSEUDO_DEFINE_GRAMMAR("orr", "1 = 2 | 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("rmf", "1 = 2 % 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("sbc", "1 = 2 - 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("sqt", "1 = sqrt(2)"),
RZ_PSEUDO_DEFINE_GRAMMAR("stp", "3 = (1, 2)"),
RZ_PSEUDO_DEFINE_GRAMMAR("str", "2 = 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("strb", "2 = (byte) 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("strh", "2 = (half) 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("strh.w", "2 = (half) 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("stur", "2 = 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("sub", "1 = 2 - 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("subs", "1 = 2 - 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("swp", "swap(1, 2)"),
RZ_PSEUDO_DEFINE_GRAMMAR("sxtb", "1 = (char) 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("sxth", "1 = (short) 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("sxtw", "1 = 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("tst", "if ((1 & 2) == 0)"),
RZ_PSEUDO_DEFINE_GRAMMAR("udf", "undefined 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("udiv", "1 = (unsigned) 2 / 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("vmov.i32", "1 = 2"),
/* arm thumb */
RZ_PSEUDO_DEFINE_GRAMMAR("lsl.w", "1 = 2 << 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("lsr.w", "1 = 2 >> 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("movs", "1 = 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("movt", "1 |= 2 << #16"),
RZ_PSEUDO_DEFINE_GRAMMAR("movw", "1 = 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("pop", "pop 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("pop.w", "pop 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("push", "push 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("push.w", "push 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("sub", "1 -= 2"), // THUMB
RZ_PSEUDO_DEFINE_GRAMMAR("sub.w", "1 = 2 - 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("subs", "1 -= 2"), // THUMB
RZ_PSEUDO_DEFINE_GRAMMAR("tst.w", "if ((1 & 2) == 0)"),
RZ_PSEUDO_DEFINE_GRAMMAR("vdiv.f64", "1 = (float) 2 / 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("vmov", "1 = (float) 2 . 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("vpop", "pop(1)"),
RZ_PSEUDO_DEFINE_GRAMMAR("vpush", "push(1)"),
};
static const RzPseudoDirect arm_direct[] = {
RZ_PSEUDO_DEFINE_DIRECT("beq lr", "if (? == ?) return"),
RZ_PSEUDO_DEFINE_DIRECT("bx lr", "return"),
};
static const RzPseudoReplace arm_replace[] = {
RZ_PSEUDO_DEFINE_REPLACE(" + 0]", "]", 0),
RZ_PSEUDO_DEFINE_REPLACE("+ -", "- ", 1),
RZ_PSEUDO_DEFINE_REPLACE("0 << 16", "0", 1),
RZ_PSEUDO_DEFINE_REPLACE("{", "(", 1),
RZ_PSEUDO_DEFINE_REPLACE("}", ")", 1),
};
static const RzPseudoConfig arm_config = RZ_PSEUDO_DEFINE_CONFIG(arm_direct, arm_lexicon, arm_replace, 5, arm_tokenize);
RzList *arm_tokenize(const char *assembly, size_t length) {
size_t i, p;
char *buf = NULL;
const char *comma_replace = NULL;
bool keep = false;
RzList *tokens = NULL;
buf = rz_str_ndup(assembly, length);
if (!buf) {
return NULL;
}
for (i = 0; ops[i].op; i++) {
if (ops[i].narg) {
if (argc - 1 != ops[i].narg) {
for (i = 0, p = 0; p < length; ++i, ++p) {
if (buf[p] == ',') {
if (!keep) {
p++;
} else if (buf[p + 1] == ' ') {
buf[i] = buf[p];
p++;
continue;
}
}
if (!strcmp(ops[i].op, argv[0])) {
if (newstr) {
d = 0;
j = 0;
ch = ops[i].str[j];
for (j = 0, k = 0; ch != '\0'; j++, k++) {
ch = ops[i].str[j];
if (ch == '#') {
if (d >= MAXPSEUDOOPS) {
// XXX Shouldn't ever happen...
continue;
}
int idx = ops[i].args[d];
d++;
if (idx <= 0) {
// XXX Shouldn't ever happen...
continue;
}
const char *w = argv[idx];
if (w) {
strcpy(newstr + k, w);
k += strlen(w) - 1;
}
} else {
newstr[k] = ch;
}
}
newstr[k] = '\0';
} else if (buf[p] == '(') {
buf[p] = ' ';
} else if (buf[p] == ')') {
buf[p] = ' ';
} else if (buf[p] == '[') {
keep = true;
comma_replace = " + ";
} else if (buf[p] == ']') {
keep = false;
} else if (buf[p] == '{') {
if (strchr(buf + p + 1, ',') < strchr(buf + p + 1, '}')) {
keep = true;
comma_replace = ", ";
} else {
p++;
}
} else if (buf[p] == '}') {
if (!comma_replace) {
p++;
}
keep = false;
} else if ((buf[p] == 'w' || buf[p] == 'x') && buf[p + 1] == 'z' && buf[p + 2] == 'r') {
p += 2;
buf[p] = '0';
}
if (p > i) {
buf[i] = buf[p];
}
}
buf[i] = 0;
rz_str_replace_char(newstr, '{', '(');
rz_str_replace_char(newstr, '}', ')');
return true;
tokens = rz_str_split_duplist(buf, " ", true);
free(buf);
if (!tokens) {
return NULL;
}
if (comma_replace) {
RzListIter *it;
rz_list_foreach (tokens, it, buf) {
it->data = rz_str_replace(buf, ",", comma_replace, 1);
}
}
/* TODO: this is slow */
newstr[0] = '\0';
for (i = 0; i < argc; i++) {
strcat(newstr, argv[i]);
strcat(newstr, (!i || i == argc - 1) ? " " : ",");
}
rz_str_replace_char(newstr, '{', '(');
rz_str_replace_char(newstr, '}', ')');
return false;
return tokens;
}
static int parse(RzParse *p, const char *data, char *str) {
char w0[256], w1[256], w2[256], w3[256];
int i, len = strlen(data);
char *buf, *ptr, *optr;
if (len >= sizeof(w0)) {
return false;
}
// malloc can be slow here :?
if (!(buf = malloc(len + 1))) {
return false;
}
memcpy(buf, data, len + 1);
if (*buf) {
*w0 = *w1 = *w2 = *w3 = '\0';
ptr = strchr(buf, ' ');
if (!ptr) {
ptr = strchr(buf, '\t');
}
if (ptr) {
*ptr = '\0';
for (++ptr; *ptr == ' '; ptr++) {
;
}
strncpy(w0, buf, sizeof(w0) - 1);
strncpy(w1, ptr, sizeof(w1) - 1);
optr = ptr;
if (*ptr == '(') {
ptr = strchr(ptr + 1, ')');
}
if (ptr && *ptr == '[') {
ptr = strchr(ptr + 1, ']');
}
if (ptr && *ptr == '{') {
ptr = strchr(ptr + 1, '}');
}
if (!ptr) {
eprintf("Unbalanced bracket\n");
free(buf);
return false;
}
ptr = strchr(ptr, ',');
if (ptr) {
*ptr = '\0';
for (++ptr; *ptr == ' '; ptr++) {
;
}
strncpy(w1, optr, sizeof(w1) - 1);
strncpy(w2, ptr, sizeof(w2) - 1);
optr = ptr;
ptr = strchr(ptr, ',');
if (ptr) {
*ptr = '\0';
for (++ptr; *ptr == ' '; ptr++) {
;
}
strncpy(w2, optr, sizeof(w2) - 1);
strncpy(w3, ptr, sizeof(w3) - 1);
}
}
}
{
const char *wa[] = { w0, w1, w2, w3 };
int nw = 0;
for (i = 0; i < 4; i++) {
if (wa[i][0]) {
nw++;
}
}
replace(nw, wa, str);
}
}
{
char *s = strdup(str);
s = rz_str_replace(s, "+ -", "- ", 1);
s = rz_str_replace(s, "- -", "+ ", 1);
strcpy(str, s);
free(s);
}
free(buf);
return true;
static bool parse(RzParse *p, const char *assembly, RzStrBuf *sb) {
return rz_pseudo_convert(&arm_config, assembly, sb);
}
static char *subs_var_string(RzParse *p, RzAnalysisVarField *var, char *tstr, const char *oldstr, const char *reg, int delta) {
@ -352,7 +279,7 @@ static bool subvar(RzParse *p, RzAnalysisFunction *f, ut64 addr, int oplen, char
rip = (char *)rz_str_casestr(tstr, "[pc, ");
}
if (rip && !strchr(rip + 4, ',')) {
if (rip) {
rip += 4;
char *tstr_new, *ripend = strchr(rip, ']');
const char *neg = strchr(rip, '-');

View file

@ -68,12 +68,13 @@ static int replace(int argc, const char *argv[], char *newstr) {
return false;
}
static int parse(RzParse *p, const char *data, char *str) {
static bool parse(RzParse *p, const char *data, RzStrBuf *sb) {
int i, n;
char w0[32];
char w1[32];
char w2[32];
char w3[32];
char str[1024] = { 0 };
char *buf, *ptr, *optr, *num;
// malloc can be slow here :?
@ -167,6 +168,7 @@ static int parse(RzParse *p, const char *data, char *str) {
}
}
free(buf);
rz_strbuf_set(sb, str);
return true;
}

View file

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2017-2019 deroad <wargio@libero.it>
// SPDX-FileCopyrightText: 2021 deroad <wargio@libero.it>
// SPDX-License-Identifier: LGPL-3.0-only
#include <stdio.h>
@ -11,210 +11,143 @@
#include <rz_analysis.h>
#include <rz_parse.h>
static bool replace(int argc, const char *argv[], char *newstr) {
int i, j, k;
struct {
char *op;
char *str;
} ops[] = {
{ "add", "A += B" },
{ "adc", "A += B + carry" },
{ "adiw", "A+1:A += B" },
{ "sub", "A -= B" },
{ "subi", "A -= B" },
{ "sbc", "A -= (B + carry)" },
{ "sbci", "A -= (B + carry)" },
{ "sbiw", "A+1:A -= B" },
{ "and", "A &= B" },
{ "andi", "A &= B" },
{ "or", "A |= B" },
{ "ori", "A |= B" },
{ "eor", "A ^= B" },
{ "com", "A = 0xff - A" },
{ "neg", "A = -A" },
{ "sbr", "A |= B" },
{ "cbr", "A &= (0xff - B)" },
{ "inc", "A++" },
{ "dec", "A--" },
{ "tst", "A &= A" },
{ "clr", "A ^= A" },
{ "ser", "A = 0xff" },
{ "mul", "r1:r0 = A * B" },
{ "rjmp", "goto A" },
{ "ijmp", "goto z" },
{ "jmp", "goto A" },
{ "rcall", "goto A" },
{ "icall", "goto z" },
{ "call", "goto A" },
{ "ret", "return" },
{ "iret", "return_interrupt()" },
{ "cp", "var = A - B" },
{ "cpc", "var = A - B - carry" },
{ "cpi", "var = A - B" },
{ "breq", "if(!var) goto A" },
{ "brne", "if(var) goto A" },
{ "brsh", "if(var >= 0) goto A" },
{ "brlo", "if(var < 0) goto A" },
{ "brmi", "if(var < 0) goto A" },
{ "brpl", "if(var > 0) goto A" },
{ "brge", "if(var >= 0) goto A" },
{ "brlt", "if(var < 0) goto A" },
{ "mov", "A = B" },
{ "movw", "A+1:A = B+1:B" },
{ "ldi", "A = B" },
{ "lds", "A = *(B)" },
{ "ld", "A = *(B)" },
{ "ldd", "A = *(B)" },
{ "lpm", "r0 = z" },
{ "in", "A = B" },
{ "out", "A = B" },
{ "push", "push(A)" },
{ "pop", "A = pop()" },
{ "lsl", "A <<= 1" },
{ "lsr", "A >>= 1" },
{ "rol", "A = (A << 1) | (A >> 7)" },
{ "ror", "A = (A << 7) | (A >> 1)" },
{ "asr", "A >>= 1" },
{ "swap", "A = ((A & 0xf0) >> 4) | ((A & 0x0f) << 4)" },
{ "sec", "c = 1" },
{ "clc", "c = 0" },
{ "sen", "n = 1" },
{ "cln", "n = 0" },
{ "sez", "z = 1" },
{ "clz", "z = 0" },
{ "sei", "i = 1" },
{ "cli", "i = 0" },
{ "ses", "s = 1" },
{ "cls", "s = 0" },
{ "sev", "v = 1" },
{ "clv", "v = 0" },
{ "set", "t = 1" },
{ "clt", "t = 0" },
{ "seh", "h = 1" },
{ "clh", "h = 0" },
{ "nop", "" },
{ "halt", "_halt()" },
{ "wdr", "_watchdog_reset()" },
{ "std", "*(A) = B" },
{ "st", "*(A) = B" },
{ "sts", "*(A) = B" },
{ NULL }
};
#include "parse_common.c"
for (i = 0; ops[i].op != NULL; i++) {
if (!strcmp(ops[i].op, argv[0])) {
if (newstr != NULL) {
for (j = k = 0; ops[i].str[j] != '\0'; j++, k++) {
if (ops[i].str[j] >= 'A' && ops[i].str[j] <= 'J') {
const char *w = argv[ops[i].str[j] - '@'];
if (w != NULL) {
strcpy(newstr + k, w);
k += strlen(w) - 1;
}
} else {
newstr[k] = ops[i].str[j];
}
}
newstr[k] = '\0';
static RzList *avr_tokenize(const char *assembly, size_t length);
static const RzPseudoGrammar avr_lexicon[] = {
RZ_PSEUDO_DEFINE_GRAMMAR("adc", "1 += 2 + carry"),
RZ_PSEUDO_DEFINE_GRAMMAR("add", "1 += 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("adiw", "1+#1:1 += 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("and", "1 &= 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("andi", "1 &= 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("asr", "1 >>= 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("breq", "if(!var) goto 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("brge", "if(var >= 0) goto 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("brlo", "if(var < 0) goto 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("brlt", "if(var < 0) goto 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("brmi", "if(var < 0) goto 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("brne", "if(var) goto 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("brpl", "if(var > 0) goto 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("brsh", "if(var >= 0) goto 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("call", "goto 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("cbr", "1 &= (#0xff - 2)"),
RZ_PSEUDO_DEFINE_GRAMMAR("clc", "c = #0"),
RZ_PSEUDO_DEFINE_GRAMMAR("clh", "h = #0"),
RZ_PSEUDO_DEFINE_GRAMMAR("cli", "i = #0"),
RZ_PSEUDO_DEFINE_GRAMMAR("cln", "n = #0"),
RZ_PSEUDO_DEFINE_GRAMMAR("clr", "1 ^= 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("cls", "s = #0"),
RZ_PSEUDO_DEFINE_GRAMMAR("clt", "t = #0"),
RZ_PSEUDO_DEFINE_GRAMMAR("clv", "v = #0"),
RZ_PSEUDO_DEFINE_GRAMMAR("clz", "z = #0"),
RZ_PSEUDO_DEFINE_GRAMMAR("com", "1 = #0xff - 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("cp", "var = 1 - 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("cpc", "var = 1 - 2 - carry"),
RZ_PSEUDO_DEFINE_GRAMMAR("cpi", "var = 1 - 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("cpse", "if(1 == 2)"),
RZ_PSEUDO_DEFINE_GRAMMAR("dec", "1--"),
RZ_PSEUDO_DEFINE_GRAMMAR("eor", "1 ^= 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("halt", "_halt()"),
RZ_PSEUDO_DEFINE_GRAMMAR("icall", "goto z"),
RZ_PSEUDO_DEFINE_GRAMMAR("ijmp", "goto z"),
RZ_PSEUDO_DEFINE_GRAMMAR("in", "1 = 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("inc", "1++"),
RZ_PSEUDO_DEFINE_GRAMMAR("iret", "return_interrupt()"),
RZ_PSEUDO_DEFINE_GRAMMAR("jmp", "goto 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("ld", "1 = *(2)"),
RZ_PSEUDO_DEFINE_GRAMMAR("ldd", "1 = *(2)"),
RZ_PSEUDO_DEFINE_GRAMMAR("ldi", "1 = 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("lds", "1 = *(2)"),
RZ_PSEUDO_DEFINE_GRAMMAR("lpm", "r0 = z"),
RZ_PSEUDO_DEFINE_GRAMMAR("lsl", "1 <<= #1"),
RZ_PSEUDO_DEFINE_GRAMMAR("lsr", "1 >>= #1"),
RZ_PSEUDO_DEFINE_GRAMMAR("mov", "1 = 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("movw", "1+#1:1 = 2+#1:2"),
RZ_PSEUDO_DEFINE_GRAMMAR("mul", "#r1:r0 = 1 * 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("neg", "1 = -1"),
RZ_PSEUDO_DEFINE_GRAMMAR("nop", ""),
RZ_PSEUDO_DEFINE_GRAMMAR("or", "1 |= 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("ori", "1 |= 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("out", "1 = 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("pop", "1 = pop()"),
RZ_PSEUDO_DEFINE_GRAMMAR("push", "push(1)"),
RZ_PSEUDO_DEFINE_GRAMMAR("rcall", "goto 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("ret", "return"),
RZ_PSEUDO_DEFINE_GRAMMAR("rjmp", "goto 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("rol", "1 = (1 << #1) | (1 >> #7)"),
RZ_PSEUDO_DEFINE_GRAMMAR("ror", "1 = (1 << #7) | (1 >> #1)"),
RZ_PSEUDO_DEFINE_GRAMMAR("sbc", "1 -= (2 + carry)"),
RZ_PSEUDO_DEFINE_GRAMMAR("sbci", "1 -= (2 + carry)"),
RZ_PSEUDO_DEFINE_GRAMMAR("sbiw", "1+#1:1 -= 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("sbrc", "if((1 & (#1 << 2)) != #0)"),
RZ_PSEUDO_DEFINE_GRAMMAR("sbrs", "if((1 & (#1 << 2)) != #1)"),
RZ_PSEUDO_DEFINE_GRAMMAR("sbr", "1 |= 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("sec", "c = #1"),
RZ_PSEUDO_DEFINE_GRAMMAR("seh", "h = #1"),
RZ_PSEUDO_DEFINE_GRAMMAR("sei", "i = #1"),
RZ_PSEUDO_DEFINE_GRAMMAR("sen", "n = #1"),
RZ_PSEUDO_DEFINE_GRAMMAR("ser", "1 = #0xff"),
RZ_PSEUDO_DEFINE_GRAMMAR("ses", "s = #1"),
RZ_PSEUDO_DEFINE_GRAMMAR("set", "t = #1"),
RZ_PSEUDO_DEFINE_GRAMMAR("sev", "v = #1"),
RZ_PSEUDO_DEFINE_GRAMMAR("sez", "z = #1"),
RZ_PSEUDO_DEFINE_GRAMMAR("st", "*(1) = 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("std", "*(1) = 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("sts", "*(1) = 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("sub", "1 -= 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("subi", "1 -= 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("swap", "1 = ((1 & #0xf0) >> #4) | ((1 & #0x0f) << #4)"),
RZ_PSEUDO_DEFINE_GRAMMAR("tst", "1 &= 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("wdr", "_watchdog_reset()"),
};
static const RzPseudoConfig avr_config = RZ_PSEUDO_DEFINE_CONFIG_ONLY_LEXICON(avr_lexicon, 3, avr_tokenize);
RzList *avr_tokenize(const char *assembly, size_t length) {
size_t i, p;
char *buf = NULL;
bool insert_zero = false;
RzList *tokens = NULL;
buf = rz_str_ndup(assembly, length);
if (!buf) {
return NULL;
}
for (i = 0, p = 0; p < length; ++i, ++p) {
if (buf[p] == ',') {
p++;
} else if (buf[p] == '(') {
buf[p] = ' ';
if (!IS_HEXCHAR(buf[p - 1])) {
p++;
insert_zero = true;
}
return true;
} else if (buf[p] == ')') {
buf[p] = 0;
}
if (p > i) {
buf[i] = buf[p];
}
}
buf[i] = 0;
/* TODO: this is slow */
if (newstr != NULL) {
newstr[0] = '\0';
for (i = 0; i < argc; i++) {
strcat(newstr, argv[i]);
strcat(newstr, (i == 0 || i == argc - 1) ? " " : ", ");
}
tokens = rz_str_split_duplist(buf, " ", true);
free(buf);
if (!tokens) {
return NULL;
}
return false;
if (insert_zero) {
rz_list_insert(tokens, rz_list_length(tokens) - 1, strdup("0"));
}
return tokens;
}
#define WSZ 128
static int parse(RzParse *p, const char *data, char *str) {
int i, len = strlen(data);
char w0[WSZ];
char w1[WSZ];
char w2[WSZ];
char w3[WSZ];
char w4[WSZ];
char *buf, *ptr, *optr;
// malloc can be slow here :?
if (!(buf = malloc(len + 1))) {
return false;
}
memcpy(buf, data, len + 1);
rz_str_trim(buf);
if (*buf) {
w0[0] = '\0';
w1[0] = '\0';
w2[0] = '\0';
w3[0] = '\0';
w4[0] = '\0';
ptr = strchr(buf, ' ');
if (!ptr) {
ptr = strchr(buf, '\t');
}
if (ptr) {
*ptr = '\0';
for (++ptr; *ptr == ' '; ptr++) {
//nothing to see here
}
strncpy(w0, buf, WSZ - 1);
strncpy(w1, ptr, WSZ - 1);
optr = ptr;
ptr = strchr(ptr, ',');
if (ptr) {
*ptr = '\0';
for (++ptr; *ptr == ' '; ptr++) {
//nothing to see here
}
strncpy(w1, optr, WSZ - 1);
strncpy(w2, ptr, WSZ - 1);
optr = ptr;
ptr = strchr(ptr, ',');
if (ptr) {
*ptr = '\0';
for (++ptr; *ptr == ' '; ptr++) {
//nothing to see here
}
strncpy(w2, optr, WSZ - 1);
strncpy(w3, ptr, WSZ - 1);
optr = ptr;
// bonus
ptr = strchr(ptr, ',');
if (ptr) {
*ptr = '\0';
for (++ptr; *ptr == ' '; ptr++) {
//nothing to see here
}
strncpy(w3, optr, WSZ - 1);
strncpy(w4, ptr, WSZ - 1);
}
}
}
} else {
strncpy(w0, buf, WSZ - 1);
}
{
const char *wa[] = { w0, w1, w2, w3, w4 };
int nw = 0;
for (i = 0; i < 5; i++) {
if (wa[i][0] != '\0') {
nw++;
}
}
(void)replace(nw, wa, str);
}
}
free(buf);
return true;
static bool parse(RzParse *parse, const char *assembly, RzStrBuf *sb) {
return rz_pseudo_convert(&avr_config, assembly, sb);
}
RzParsePlugin rz_parse_plugin_avr_pseudo = {

View file

@ -89,8 +89,9 @@ static int tokenize(const char *in, char *out[]) {
return count;
}
static int parse(RzParse *p, const char *data, char *str) {
static bool parse(RzParse *p, const char *data, RzStrBuf *sb) {
int i;
char str[1024] = { 0 };
char *argv[MAXARGS] = { NULL, NULL, NULL, NULL };
int argc = tokenize(data, argv);
@ -101,6 +102,7 @@ static int parse(RzParse *p, const char *data, char *str) {
for (i = 0; i < MAXARGS; i++) {
free(argv[i]);
}
rz_strbuf_set(sb, str);
return true;
}

View file

@ -0,0 +1,182 @@
// SPDX-FileCopyrightText: 2018-2021 deroad <wargio@libero.it>
// SPDX-License-Identifier: LGPL-3.0-only
/** \file parse_common.c
* This file contains a common code that can be used to convert any asm code
* into a pseudo code, via a generic grammar.
*
* The grammar is quite simple; Let's take a simple example
*
* Let's take the following assembly
* ; intel x86 asm
* ; rax = rax + 10
* add rax, 10
*
* The associated grammar will be "1 += 2" the number 1 will be changed to "rax" and 2 with "10"
*
* another example:
*
* ; mips asm
* ; t0 = 4097 << 16
* lui t0, 4097
*
* The associated grammar will be "1 = 2 << #16" to notice the `#` symbol.
* The `#` symbol is used to ignore any set of chars after this till next whitespace/end of the line
*
* the developer has to provide a tokenize method to split the assembly in various token strings
* and
*/
typedef struct {
const char *mnemonic;
size_t mnemonic_length;
const char *grammar;
} RzPseudoGrammar;
typedef struct {
const char *expected;
const char *pseudo;
} RzPseudoDirect;
typedef struct {
const char *expected;
const char *replace;
int flag; // 0 for first match, 1 for all matches
} RzPseudoReplace;
typedef struct {
const RzPseudoDirect *direct;
size_t direct_length;
const RzPseudoReplace *replace;
size_t replace_length;
const RzPseudoGrammar *lexicon;
size_t lexicon_length;
int max_args;
RzList *(*tokenize)(const char *assembly, size_t length);
} RzPseudoConfig;
#define RZ_PSEUDO_DEFINE_GRAMMAR(x, y) \
{ .mnemonic = x, .mnemonic_length = sizeof(x) - 1, .grammar = y }
#define RZ_PSEUDO_DEFINE_DIRECT(x, y) \
{ .expected = x, .pseudo = y }
#define RZ_PSEUDO_DEFINE_REPLACE(x, y, f) \
{ .expected = x, .replace = y, .flag = f }
#define RZ_PSEUDO_DEFINE_CONFIG(d, l, r, m, t) \
{ \
.direct = d, \
.direct_length = RZ_ARRAY_SIZE(d), \
.replace = r, \
.replace_length = RZ_ARRAY_SIZE(r), \
.lexicon = l, \
.lexicon_length = RZ_ARRAY_SIZE(l), \
.max_args = m, \
.tokenize = t, \
}
#define RZ_PSEUDO_DEFINE_CONFIG_NO_DIRECT(l, r, m, t) \
{ \
.direct = NULL, \
.direct_length = 0, \
.replace = r, \
.replace_length = RZ_ARRAY_SIZE(r), \
.lexicon = l, \
.lexicon_length = RZ_ARRAY_SIZE(l), \
.max_args = m, \
.tokenize = t, \
}
#define RZ_PSEUDO_DEFINE_CONFIG_ONLY_LEXICON(l, m, t) \
{ \
.direct = NULL, \
.direct_length = 0, \
.replace = NULL, \
.replace_length = 0, \
.lexicon = l, \
.lexicon_length = RZ_ARRAY_SIZE(l), \
.max_args = m, \
.tokenize = t, \
}
static bool rz_pseudo_convert(const RzPseudoConfig *config, const char *assembly, RzStrBuf *sb) {
rz_return_val_if_fail(config && config->tokenize && config->lexicon, false);
size_t i, p;
const char *tmp = NULL;
const RzPseudoGrammar *gr = NULL;
const RzPseudoReplace *rp = NULL;
if (!strcmp(assembly, "invalid")) {
return true;
} else if (!strncmp(assembly, "trunc", 5)) {
return true;
} else if (!strcmp(assembly, "nop")) {
return true;
}
size_t length = strlen(assembly);
for (i = 0; i < config->direct_length; ++i) {
tmp = config->direct[i].expected;
if (!strcmp(assembly, tmp)) {
rz_strbuf_set(sb, config->direct[i].pseudo);
return true;
}
}
size_t mnemonic_length = length;
if ((tmp = strchr(assembly, ' '))) {
mnemonic_length = tmp - assembly;
}
for (i = 0; i < config->lexicon_length; ++i) {
gr = &config->lexicon[i];
if (gr->mnemonic_length == mnemonic_length && !strncmp(gr->mnemonic, assembly, mnemonic_length)) {
break;
}
gr = NULL;
}
if (!gr) {
rz_strbuf_setf(sb, "asm(\"%s\")", assembly);
return true;
}
RzList *tokens = config->tokenize(assembly, length);
if (!tokens) {
rz_strbuf_setf(sb, "asm(\"%s\")", assembly);
return true;
}
for (i = 0, p = 0; gr->grammar[p]; ++p) {
int index = gr->grammar[p] - '0';
if (index > 0 && index < config->max_args) {
tmp = (const char *)rz_list_get_n(tokens, index);
if (!tmp) {
tmp = "?";
}
rz_strbuf_append_n(sb, gr->grammar + i, p - i);
i = p + 1;
rz_strbuf_append(sb, tmp);
} else if (gr->grammar[p] == '#') {
rz_strbuf_append_n(sb, gr->grammar + i, p - i);
i = p + 1;
p++;
while (gr->grammar[p] && !IS_WHITESPACE(gr->grammar[p])) {
++p;
}
}
}
if (i < p) {
rz_strbuf_append_n(sb, gr->grammar + i, p - i);
}
char *result = rz_strbuf_get(sb);
for (int i = 0; i < config->replace_length; ++i) {
rp = &config->replace[i];
rz_str_replace(result, rp->expected, rp->replace, rp->flag);
}
rz_list_free(tokens);
return true;
}

View file

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2012-2017 pancake <pancake@nopcode.org>
// SPDX-FileCopyrightText: 2021 deroad <wargio@libero.it>
// SPDX-License-Identifier: LGPL-3.0-only
#include <stdio.h>
@ -11,350 +11,249 @@
#include <rz_analysis.h>
#include <rz_parse.h>
static int replace(int argc, const char *argv[], char *newstr) {
int i, j, k;
struct {
char *op;
char *str;
} ops[] = {
{ "rsub-int", "1 = 2 - 3" },
{ "float-to-double", "1 = (double)(float) 2" },
{ "float-to-long", "1 = (long)(float) 2" },
{ "float-to-int", "1 = (int)(float) 2" },
{ "long-to-float", "1 = (float)(long) 2" },
{ "long-to-int", "1 = (int)(long) 2" },
{ "long-to-double", "1 = (double) 2" },
{ "double-to-long", "1 = (long) 2" },
{ "double-to-int", "1 = (int) 2" },
{ "int-to-double", "1 = (double) 2" },
{ "int-to-long", "1 = (long) 2" },
{ "int-to-byte", "1 = (byte) 2" },
{ "aget-byte", "1 = (byte) 2[3]" },
{ "aget-short", "1 = (short) 2[3]" },
{ "aget-object", "1 = (object) 2[3]" },
{ "sput-wide", "1 = 2" },
{ "sput-object", "1 = 2" },
{ "add-long", "1 = 2 + 3" },
{ "add-double", "1 = 2 + 3" },
{ "mul-long", "1 = 2 * 3" },
{ "const-string/jumbo", "1 = (jumbo-string) 2" },
{ "const-string", "1 = (string) 2" },
{ "const-wide", "1 = (wide) 2" },
{ "const/4", "1 = (wide) 2" },
{ "cmp-int", "1 = (2 == 3)" },
{ "cmp-long", "1 = (2 == 3)" },
{ "cmpl-double", "1 = (double)(2 == 3)" },
{ "cmpl-float", "1 = (float)(2 == 3)" },
{ "cmpl-int", "1 = (int)(2 == 3)" },
{ "cmpg-double", "1 = (2 == 3)" },
{ "cmpg-float", "1 = (2 == 3)" },
{ "or-int/2addr", "1 |= 2" },
{ "or-long", "1 |= 2" },
{ "and-long/2addr", "1 &= (long) 2" },
{ "and-int", "1 &= (int) 2" },
{ "and-byte", "1 &= (byte) 2" },
{ "sub-float/2addr", "1 -= 2" },
{ "sub-float", "1 = 2 - 3" },
{ "sub-int", "1 = (int) 2 - 3" },
{ "sub-long", "1 = (long) 2 - 3" },
{ "sub-long/2addr", "1 -= (long) 2" },
{ "sub-int/2addr", "1 -= 2" },
{ "move", "1 = 2" },
{ "move/16", "1 = 2" },
{ "move-object", "1 = (object) 2" },
{ "move-object/16", "1 = (object) 2" },
{ "move-object/from16", "1 = (object) 2" },
{ "move-wide/from16", "1 = (wide) 2" },
{ "array-length", "1 = Array.length (2)" },
{ "new-array", "1 = new array (2, 3)" },
{ "new-instance", "1 = new 2" },
{ "shr-long/2addr", "1 >>= 2" },
{ "shr-long", "1 = (long) 2 >> 3" },
{ "shr-int", "1 = (int) 2 >> 3" },
{ "ushr-int", "1 = (int) 2 >>> 3" },
{ "ushr-int/2addr", "1 >>>= 2" },
{ "ushr-long", "1 = (long) 2 >>> 3" },
{ "ushl-int/2addr", "1 <<<= 2" },
{ "shl-int/2addr", "1 <<<= 2" },
{ "shl-int", "1 = (int) 2 << 3" },
{ "shl-long", "1 = (long) 2 << 3" },
{ "move/from16", "1 = 2" },
{ "move-exception", "1 = exception" },
{ "move-result", "1 = result" },
{ "move-result-wide", "1 = (wide) result" },
{ "move-result-object", "1 = (object) result" },
{ "const-wide/high16", "1 = 2" },
{ "const/16", "1 = 2" },
{ "const-wide/16", "1 = 2" },
{ "const-wide/32", "1 = 2" },
{ "const-class", "1 = (class) 2" },
{ "const/high16", "1 = 2" },
{ "const", "1 = 2" },
{ "rem-long", "1 = (long) 2 % 3" },
{ "rem-double", "1 = (double) 2 % 3" },
{ "rem-float", "1 = (float) 2 % 3" },
{ "rem-long/2addr", "1 %= 2" },
{ "rem-float/2addr", "1 %= (float) 2" },
{ "rem-double/2addr", "1 %= (double) 2" },
{ "instance-of", "1 = insteanceof (2) == 3" },
{ "aput", "2[3] = 1" },
{ "aput-byte", "2[3] = (byte) 1" },
{ "aput-short", "2[3] = (short) 1" },
{ "aput-object", "2[3] = (object) 1" },
{ "aput-wide", "2[3] = (wide) 1" },
{ "aput-char", "2[3] = (char) 1" },
{ "aput-boolean", "2[3] = (bool) 1" },
{ "aget", "1 = 2[3]" },
{ "aget-wide", "1 = (wide) 2[3]" },
{ "aget-char", "1 = (char) 2[3]" },
{ "aget-boolean", "1 = (boolean) 2[3]" },
{ "sget", "1 = 2" },
{ "sget-char", "1 = (char) 2" },
{ "sget-short", "1 = (short) 2" },
{ "sget-boolean", "1 = (bool) 2" },
{ "sget-object", "1 = (object) 2" },
{ "iput", "2[3] = 1" },
{ "iput-object", "2[3] = (object) 1" },
{ "iput-byte", "2[3] = (byte) 1" },
{ "iput-char", "2[3] = (char) 1" },
{ "iput-boolean", "2[3] = (bool) 1" },
{ "sput-boolean", "2[3] = (bool) 1" },
{ "sput-char", "2[3] = (char) 1" },
{ "iput-int", "2[3] = (int) 1" },
{ "iget", "1 = 2[3]" },
{ "sget-byte", "1 = (byte) 2 [3]" },
{ "iget-byte", "1 = (byte) 2 [3]" },
{ "iget-char", "1 = (char) 2 [3]" },
{ "iget-short", "1 = (short) 2 [3]" },
{ "iget-wide", "1 = (wide) 2 [3]" },
{ "iget-object", "1 = (2) 3" },
{ "iget-boolean", "1 = (bool) 2 [3]" },
{ "+iget-wide-volatile", "1 = (wide-volatile) 2 [3]" },
{ "if-eq", "if (1 == 2) goto 3" },
{ "if-lt", "if (1 < 2) goto 3" },
{ "if-ne", "if (1 != 2) goto 3" },
{ "if-eqz", "if (!1) goto 2" },
{ "if-ge", "if (1 > zero) goto 2" },
{ "if-le", "if (1 <= 2) goto 3" },
{ "if-gtz", "if (1 > 0) goto 2" },
{ "filled-new-array", "1 = new Array(2)" },
{ "neg-long", "1 = -2" },
{ "neg-double", "1 = -2" },
{ "neg-float", "1 = -2" },
{ "not-int", "1 = !2" },
{ "packed-switch", "switch 2" },
{ "sparse-switch", "switch 2" },
{ "invoke-direct", "call 2 1" },
{ "invoke-direct/range", "call 2 1" },
{ "invoke-interface", "call 2 1" },
{ "invoke-static", "call 2 1" },
{ "invoke-super", "call super 2 1" },
{ "invoke-super/range", "call super 2 1" },
{ "invoke-polymorphic", "call polymorphic 2 1" },
{ "invoke-virtual/range", "call 2 1" },
{ "invoke-virtual", "call 2 1" },
{ "+invoke-virtual-quick", "call 2 1" },
{ "+invoke-interface/range", "call 2 1" },
{ "invoke-interface/range", "call 2 1" },
{ "div-float/2addr", "1 /= (float) 2" },
{ "div-double/2addr", "1 /= (double) 2" },
{ "div-double", "1 = (double) 2 / 3" },
{ "div-float", "1 = 2 / 3" },
{ "div-int/lit8", "1 = 2 / 3" },
{ "div-int/lit16", "1 = 2 / 3" },
{ "div-int/2addr", "1 /= 2" },
{ "div-int", "1 = (int)(2 / 3)" },
{ "goto/16", "goto 1" },
{ "goto/32", "goto 1" },
{ "or-int", "1 = (int)(2 | 3)" },
{ "xor-int", "1 = (int)(2 ^ 3)" },
{ "xor-int/2addr", "1 ^= 2" },
{ "xor-byte", "1 = (byte)(2 ^ 3)" },
{ "xor-short", "1 = (short)(2 ^ 3)" },
{ "sub-int", "1 = (int)(2 - 3)" },
{ "if-nez", "if (1) goto 2" },
{ "if-ltz", "if (1 <=) goto 2" },
{ "mul-int", "1 = (int)(2 * 3)" },
{ "mul-int/lit8", "1 = (2 * 3)" },
{ "check-cast", "if (1 instanceof 2)" },
{ "add-int", "1 = (int)(2 + 3)" },
{ "add-int/lit8", "1 = 2 + 3" },
{ "add-int/lit16", "1 = 2 + 3" },
{ "add-int/2addr", "1 += 2" },
{ "add-double", "1 = (double)(2 + 3)" },
{ "add-double/2addr", "1 += (double)2" },
{ "mul-float/2addr", "1 *= 2" },
{ "mul-float", "1 = 2 * 3" },
{ "xor-long", "1 = (long)(2 ^ 3)" },
{ "mul-double", "1 = 2 * 3" },
{ "move-wide", "1 = 2" },
{ "move-wide/16", "1 = 2" },
{ "return-wide", "return (wide) 1" },
{ "return-object", "return (object) 1" },
// { "sget", "1 = 2[3]"},
{ NULL }
};
#include "parse_common.c"
for (i = 0; ops[i].op != NULL; i++) {
if (!strcmp(ops[i].op, argv[0])) {
if (newstr != NULL) {
for (j = k = 0; ops[i].str[j] != '\0'; j++, k++) {
if (ops[i].str[j] >= '1' && ops[i].str[j] <= '9') {
const char *w = argv[ops[i].str[j] - '0'];
if (w != NULL) {
strcpy(newstr + k, w);
k += strlen(w) - 1;
}
} else {
newstr[k] = ops[i].str[j];
}
}
newstr[k] = '\0';
static RzList *dalvik_tokenize(const char *assembly, size_t length);
static const RzPseudoGrammar dalvik_lexicon[] = {
RZ_PSEUDO_DEFINE_GRAMMAR("+iget-wide-volatile", "1 = (wide-volatile) 2 [3]"),
RZ_PSEUDO_DEFINE_GRAMMAR("+invoke-interface/range", "call 2 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("+invoke-virtual-quick", "call 2 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("add-double", "1 = (double)(2 + 3)"),
RZ_PSEUDO_DEFINE_GRAMMAR("add-double", "1 = 2 + 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("add-double/2addr", "1 += (double)2"),
RZ_PSEUDO_DEFINE_GRAMMAR("add-int", "1 = (int)(2 + 3)"),
RZ_PSEUDO_DEFINE_GRAMMAR("add-int/2addr", "1 += 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("add-int/lit16", "1 = 2 + 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("add-int/lit8", "1 = 2 + 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("add-long", "1 = 2 + 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("aget", "1 = 2[3]"),
RZ_PSEUDO_DEFINE_GRAMMAR("aget-boolean", "1 = (boolean) 2[3]"),
RZ_PSEUDO_DEFINE_GRAMMAR("aget-byte", "1 = (byte) 2[3]"),
RZ_PSEUDO_DEFINE_GRAMMAR("aget-char", "1 = (char) 2[3]"),
RZ_PSEUDO_DEFINE_GRAMMAR("aget-object", "1 = (object) 2[3]"),
RZ_PSEUDO_DEFINE_GRAMMAR("aget-short", "1 = (short) 2[3]"),
RZ_PSEUDO_DEFINE_GRAMMAR("aget-wide", "1 = (wide) 2[3]"),
RZ_PSEUDO_DEFINE_GRAMMAR("and-byte", "1 &= (byte) 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("and-int", "1 &= (int) 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("and-long/2addr", "1 &= (long) 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("aput", "2[3] = 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("aput-boolean", "2[3] = (bool) 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("aput-byte", "2[3] = (byte) 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("aput-char", "2[3] = (char) 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("aput-object", "2[3] = (object) 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("aput-short", "2[3] = (short) 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("aput-wide", "2[3] = (wide) 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("array-length", "1 = Array.length (2)"),
RZ_PSEUDO_DEFINE_GRAMMAR("check-cast", "if (1 instanceof 2)"),
RZ_PSEUDO_DEFINE_GRAMMAR("cmp-int", "1 = (2 == 3)"),
RZ_PSEUDO_DEFINE_GRAMMAR("cmp-long", "1 = (2 == 3)"),
RZ_PSEUDO_DEFINE_GRAMMAR("cmpg-double", "1 = (2 == 3)"),
RZ_PSEUDO_DEFINE_GRAMMAR("cmpg-float", "1 = (2 == 3)"),
RZ_PSEUDO_DEFINE_GRAMMAR("cmpl-double", "1 = (double)(2 == 3)"),
RZ_PSEUDO_DEFINE_GRAMMAR("cmpl-float", "1 = (float)(2 == 3)"),
RZ_PSEUDO_DEFINE_GRAMMAR("cmpl-int", "1 = (int)(2 == 3)"),
RZ_PSEUDO_DEFINE_GRAMMAR("const", "1 = 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("const-class", "1 = (class) 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("const-string", "1 = (string) 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("const-string/jumbo", "1 = (jumbo-string) 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("const-wide", "1 = (wide) 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("const-wide/16", "1 = 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("const-wide/32", "1 = 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("const-wide/high16", "1 = 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("const/16", "1 = 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("const/4", "1 = (wide) 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("const/high16", "1 = 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("div-double", "1 = (double) 2 / 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("div-double/2addr", "1 /= (double) 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("div-float", "1 = 2 / 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("div-float/2addr", "1 /= (float) 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("div-int", "1 = (int)(2 / 3)"),
RZ_PSEUDO_DEFINE_GRAMMAR("div-int/2addr", "1 /= 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("div-int/lit16", "1 = 2 / 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("div-int/lit8", "1 = 2 / 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("double-to-int", "1 = (int) 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("double-to-long", "1 = (long) 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("filled-new-array", "1 = new Array(2)"),
RZ_PSEUDO_DEFINE_GRAMMAR("float-to-double", "1 = (double)(float) 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("float-to-int", "1 = (int)(float) 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("float-to-long", "1 = (long)(float) 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("goto/16", "goto 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("goto/32", "goto 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("if-eq", "if (1 == 2) goto 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("if-eqz", "if (!1) goto 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("if-ge", "if (1 > zero) goto 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("if-gtz", "if (1 > 0) goto 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("if-le", "if (1 <= 2) goto 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("if-lt", "if (1 < 2) goto 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("if-ltz", "if (1 <=) goto 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("if-ne", "if (1 != 2) goto 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("if-nez", "if (1) goto 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("iget", "1 = 2[3]"),
RZ_PSEUDO_DEFINE_GRAMMAR("iget-boolean", "1 = (bool) 2 [3]"),
RZ_PSEUDO_DEFINE_GRAMMAR("iget-byte", "1 = (byte) 2 [3]"),
RZ_PSEUDO_DEFINE_GRAMMAR("iget-char", "1 = (char) 2 [3]"),
RZ_PSEUDO_DEFINE_GRAMMAR("iget-object", "1 = (2) 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("iget-short", "1 = (short) 2 [3]"),
RZ_PSEUDO_DEFINE_GRAMMAR("iget-wide", "1 = (wide) 2 [3]"),
RZ_PSEUDO_DEFINE_GRAMMAR("instance-of", "1 = insteanceof (2) == 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("int-to-byte", "1 = (byte) 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("int-to-double", "1 = (double) 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("int-to-long", "1 = (long) 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("invoke-direct", "call 2 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("invoke-direct/range", "call 2 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("invoke-interface", "call 2 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("invoke-interface/range", "call 2 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("invoke-polymorphic", "call polymorphic 2 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("invoke-static", "call 2 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("invoke-super", "call super 2 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("invoke-super/range", "call super 2 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("invoke-virtual", "call 2 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("invoke-virtual/range", "call 2 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("iput", "2[3] = 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("iput-boolean", "2[3] = (bool) 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("iput-byte", "2[3] = (byte) 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("iput-char", "2[3] = (char) 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("iput-int", "2[3] = (int) 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("iput-object", "2[3] = (object) 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("long-to-double", "1 = (double) 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("long-to-float", "1 = (float)(long) 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("long-to-int", "1 = (int)(long) 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("move", "1 = 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("move-exception", "1 = exception"),
RZ_PSEUDO_DEFINE_GRAMMAR("move-object", "1 = (object) 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("move-object/16", "1 = (object) 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("move-object/from16", "1 = (object) 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("move-result", "1 = result"),
RZ_PSEUDO_DEFINE_GRAMMAR("move-result-object", "1 = (object) result"),
RZ_PSEUDO_DEFINE_GRAMMAR("move-result-wide", "1 = (wide) result"),
RZ_PSEUDO_DEFINE_GRAMMAR("move-wide", "1 = 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("move-wide/16", "1 = 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("move-wide/from16", "1 = (wide) 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("move/16", "1 = 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("move/from16", "1 = 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("mul-double", "1 = 2 * 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("mul-float", "1 = 2 * 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("mul-float/2addr", "1 *= 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("mul-int", "1 = (int)(2 * 3)"),
RZ_PSEUDO_DEFINE_GRAMMAR("mul-int/lit8", "1 = (2 * 3)"),
RZ_PSEUDO_DEFINE_GRAMMAR("mul-long", "1 = 2 * 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("neg-double", "1 = -2"),
RZ_PSEUDO_DEFINE_GRAMMAR("neg-float", "1 = -2"),
RZ_PSEUDO_DEFINE_GRAMMAR("neg-long", "1 = -2"),
RZ_PSEUDO_DEFINE_GRAMMAR("new-array", "1 = new array (2, 3)"),
RZ_PSEUDO_DEFINE_GRAMMAR("new-instance", "1 = 2.new"),
RZ_PSEUDO_DEFINE_GRAMMAR("nop", ""),
RZ_PSEUDO_DEFINE_GRAMMAR("not-int", "1 = !2"),
RZ_PSEUDO_DEFINE_GRAMMAR("or-int", "1 = (int)(2 | 3)"),
RZ_PSEUDO_DEFINE_GRAMMAR("or-int/2addr", "1 |= 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("or-long", "1 |= 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("packed-switch", "switch 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("rem-double", "1 = (double) 2 % 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("rem-double/2addr", "1 %= (double) 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("rem-float", "1 = (float) 2 % 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("rem-float/2addr", "1 %= (float) 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("rem-long", "1 = (long) 2 % 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("rem-long/2addr", "1 %= 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("return-object", "return (object) 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("return-void", "return"),
RZ_PSEUDO_DEFINE_GRAMMAR("return-wide", "return (wide) 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("rsub-int", "1 = 2 - 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("sget", "1 = 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("sget-boolean", "1 = (bool) 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("sget-byte", "1 = (byte) 2 [3]"),
RZ_PSEUDO_DEFINE_GRAMMAR("sget-char", "1 = (char) 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("sget-object", "1 = (object) 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("sget-short", "1 = (short) 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("shl-int", "1 = (int) 2 << 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("shl-int/2addr", "1 <<<= 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("shl-long", "1 = (long) 2 << 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("shr-int", "1 = (int) 2 >> 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("shr-long", "1 = (long) 2 >> 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("shr-long/2addr", "1 >>= 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("sparse-switch", "switch 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("sput", "1 = 2 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("sput-boolean", "2[3] = (bool) 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("sput-char", "2[3] = (char) 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("sput-object", "1 = 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("sput-wide", "1 = 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("sub-float", "1 = 2 - 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("sub-float/2addr", "1 -= 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("sub-int", "1 = (int) 2 - 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("sub-int", "1 = (int)(2 - 3)"),
RZ_PSEUDO_DEFINE_GRAMMAR("sub-int/2addr", "1 -= 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("sub-long", "1 = (long) 2 - 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("sub-long/2addr", "1 -= (long) 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("ushl-int/2addr", "1 <<<= 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("ushr-int", "1 = (int) 2 >>> 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("ushr-int/2addr", "1 >>>= 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("ushr-long", "1 = (long) 2 >>> 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("xor-byte", "1 = (byte)(2 ^ 3)"),
RZ_PSEUDO_DEFINE_GRAMMAR("xor-int", "1 = (int)(2 ^ 3)"),
RZ_PSEUDO_DEFINE_GRAMMAR("xor-int/2addr", "1 ^= 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("xor-long", "1 = (long)(2 ^ 3)"),
RZ_PSEUDO_DEFINE_GRAMMAR("xor-short", "1 = (short)(2 ^ 3)"),
};
static const RzPseudoReplace dalvik_replace[] = {
RZ_PSEUDO_DEFINE_REPLACE("{", "(", 1),
RZ_PSEUDO_DEFINE_REPLACE("}", ")", 1),
RZ_PSEUDO_DEFINE_REPLACE(";", "", 1),
};
static const RzPseudoConfig dalvik_config = RZ_PSEUDO_DEFINE_CONFIG_NO_DIRECT(dalvik_lexicon, dalvik_replace, 4, dalvik_tokenize);
RzList *dalvik_tokenize(const char *assembly, size_t length) {
size_t i, p;
char *buf = NULL;
RzList *tokens = NULL;
const char *comma_replace = NULL;
bool keep = false;
buf = rz_str_ndup(assembly, length);
if (!buf) {
return NULL;
}
for (i = 0, p = 0; p < length; ++i, ++p) {
if (buf[p] == ',') {
if (!keep) {
p++;
} else if (buf[p + 1] == ' ') {
buf[i] = buf[p];
p++;
continue;
}
return true;
} else if (buf[p] == '{') {
keep = true;
comma_replace = ", ";
} else if (buf[p] == '}') {
keep = false;
}
if (p > i) {
buf[i] = buf[p];
}
}
buf[i] = 0;
tokens = rz_str_split_duplist(buf, " ", true);
free(buf);
if (!tokens) {
return NULL;
}
if (comma_replace) {
RzListIter *it;
rz_list_foreach (tokens, it, buf) {
it->data = rz_str_replace(buf, ",", comma_replace, 1);
}
}
/* TODO: this is slow */
if (newstr != NULL) {
newstr[0] = '\0';
for (i = 0; i < argc; i++) {
strcat(newstr, argv[i]);
strcat(newstr, (i == 0 || i == argc - 1) ? " " : ", ");
}
}
return false;
return tokens;
}
static int parse(RzParse *p, const char *data, char *str) {
int i, len = strlen(data);
char *buf, *ptr, *optr, *ptr2;
char w0[64];
char w1[64];
char w2[64];
char w3[64];
char w4[64];
if (!strcmp(data, "invalid") || !strcmp(data, "nop") || !strcmp(data, "DEPRECATED")) {
str[0] = 0;
return true;
}
// malloc can be slow here :?
if (!(buf = malloc(len + 1))) {
return false;
}
memcpy(buf, data, len + 1);
rz_str_trim(buf);
if (*buf) {
w0[0] = '\0';
w1[0] = '\0';
w2[0] = '\0';
w3[0] = '\0';
w4[0] = '\0';
ptr = strchr(buf, ' ');
if (!ptr) {
ptr = strchr(buf, '\t');
}
if (ptr) {
*ptr = '\0';
for (++ptr; *ptr == ' '; ptr++) {
;
}
strncpy(w0, buf, sizeof(w0) - 1);
w0[sizeof(w0) - 1] = '\0';
strncpy(w1, ptr, sizeof(w1) - 1);
w1[sizeof(w1) - 1] = '\0';
optr = ptr;
ptr2 = strchr(ptr, '}');
if (ptr2) {
ptr = ptr2 + 1;
}
ptr = strchr(ptr, ',');
if (ptr) {
*ptr = '\0';
for (++ptr; *ptr == ' '; ptr++) {
;
}
strncpy(w1, optr, sizeof(w1) - 1);
w1[sizeof(w1) - 1] = '\0';
strncpy(w2, ptr, sizeof(w2) - 1);
w2[sizeof(w2) - 1] = '\0';
optr = ptr;
ptr = strchr(ptr, ',');
if (ptr) {
*ptr = '\0';
for (++ptr; *ptr == ' '; ptr++) {
;
}
strncpy(w2, optr, sizeof(w2) - 1);
w2[sizeof(w2) - 1] = '\0';
strncpy(w3, ptr, sizeof(w3) - 1);
w3[sizeof(w3) - 1] = '\0';
optr = ptr;
// bonus
ptr = strchr(ptr, ',');
if (ptr) {
*ptr = '\0';
for (++ptr; *ptr == ' '; ptr++) {
;
}
strncpy(w3, optr, sizeof(w3) - 1);
w3[sizeof(w3) - 1] = '\0';
strncpy(w4, ptr, sizeof(w4) - 1);
w4[sizeof(w4) - 1] = '\0';
}
}
}
}
{
const char *wa[] = { w0, w1, w2, w3, w4 };
int nw = 0;
for (i = 0; i < 4; i++) {
if (wa[i][0] != '\0') {
nw++;
}
}
replace(nw, wa, str);
{
char *p = strdup(str);
p = rz_str_replace(p, "+ -", "- ", 0);
#if EXPERIMENTAL_ZERO
p = rz_str_replace(p, "zero", "0", 0);
if (!memcmp(p, "0 = ", 4))
*p = 0; // nop
#endif
if (!strcmp(w1, w2)) {
char a[32], b[32];
#define REPLACE(x, y) \
do { \
int snprintf_len1_ = snprintf(a, 32, x, w1, w1); \
int snprintf_len2_ = snprintf(b, 32, y, w1); \
if (snprintf_len1_ < 32 && snprintf_len2_ < 32) { \
p = rz_str_replace(p, a, b, 0); \
} \
} while (0)
// TODO: optimize
REPLACE("%s = %s +", "%s +=");
REPLACE("%s = %s -", "%s -=");
REPLACE("%s = %s &", "%s &=");
REPLACE("%s = %s |", "%s |=");
REPLACE("%s = %s ^", "%s ^=");
REPLACE("%s = %s >>", "%s >>=");
REPLACE("%s = %s <<", "%s <<=");
}
strcpy(str, p);
free(p);
}
}
}
free(buf);
return true;
static bool parse(RzParse *parse, const char *assembly, RzStrBuf *sb) {
return rz_pseudo_convert(&dalvik_config, assembly, sb);
}
RzParsePlugin rz_parse_plugin_dalvik_pseudo = {

View file

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2016 pancake <pancake@nopcode.org>
// SPDX-FileCopyrightText: 2021 deroad <wargio@libero.it>
// SPDX-License-Identifier: LGPL-3.0-only
#include <stdio.h>
@ -11,190 +11,92 @@
#include <rz_analysis.h>
#include <rz_parse.h>
static bool can_replace(const char *str, int idx, int max_operands) {
if (str[idx] > '9' || str[idx] < '1') {
return false;
}
if (str[idx + 1] != '\x00' && str[idx + 1] <= '9' && str[idx + 1] >= '1') {
return false;
}
if ((int)((int)str[idx] - 0x30) > max_operands) {
return false;
}
return true;
}
#include "parse_common.c"
static int replace(int argc, const char *argv[], char *newstr) {
int i, j, k;
struct {
char *op;
char *str;
int max_operands;
} ops[] = {
{ "move", "2 = 1", 2 },
{ "movea", "2 = 1", 2 },
{ "moveq", "2 = 1", 2 },
{ "movem", "2 = 1", 2 },
{ "lea", "2 = 1", 2 },
{ "bsr", "1()", 1 },
{ "jsr", "1()", 1 },
{ "beq", "if (==) jmp 1", 1 },
{ "blt", "if (<) jmp 1", 1 },
{ "ble", "if (<=) jmp 1", 1 },
{ "bgt", "if (>) jmp 1", 1 },
{ "bge", "if (>=) jmp 1", 1 },
{ "bcs", "if (cs) jmp 1", 1 },
{ "bcc", "if (cc) jmp 1", 1 },
{ "bra", "jmp 1", 1 },
{ "jmp", "jmp 1", 1 },
{ "rts", "ret", 2 },
{ "btst", "1 == 2", 2 },
{ "cmp", "1 == 2", 2 },
{ "cmpi", "2 == 1", 2 },
{ "add", "1 += 2", 2 },
{ "addi", "1 += 2", 2 },
{ "adda", "1 += 2", 2 },
{ "sub", "1 += 2", 2 },
{ "subq", "1 += 2", 2 },
{ "tst", "1 == 2", 2 },
{ "ori", "2 |= 1", 2 },
{ "or", "2 |= 1", 2 },
{ "lsr", "2 >>= 1", 2 },
{ "lsl", "2 <<= 1", 2 },
{ "andi", "2 &= 1", 2 },
{ "nop", "" },
//
{ NULL }
};
static RzList *m68k_tokenize(const char *assembly, size_t length);
for (i = 0; ops[i].op != NULL; i++) {
if (!strcmp(ops[i].op, argv[0])) {
if (newstr != NULL) {
for (j = k = 0; ops[i].str[j] != '\0'; j++, k++) {
if (can_replace(ops[i].str, j, ops[i].max_operands)) {
const char *w = argv[ops[i].str[j] - '0'];
if (w != NULL) {
strcpy(newstr + k, w);
k += strlen(w) - 1;
}
} else {
newstr[k] = ops[i].str[j];
}
}
newstr[k] = '\0';
}
return true;
static const RzPseudoGrammar m68k_lexicon[] = {
RZ_PSEUDO_DEFINE_GRAMMAR("add", "1 += 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("adda", "1 += 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("addi", "1 += 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("addq", "1 += 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("andi", "2 &= 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("bcc", "if (cc) goto 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("bcs", "if (cs) goto 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("bne", "if (!=) goto 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("beq", "if (==) goto 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("bge", "if (>=) goto 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("bgt", "if (>) goto 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("ble", "if (<=) goto 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("blt", "if (<) goto 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("bra", "goto 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("bsr", "call 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("btst", "1 == 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("cmp", "1 == 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("cmpi", "2 == 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("jmp", "goto 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("jsr", "call 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("lea", "2 = 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("lsl", "2 <<= 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("lsr", "2 >>= 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("move", "2 = 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("movea", "2 = 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("movem", "2 = 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("moveq", "2 = 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("nop", ""),
RZ_PSEUDO_DEFINE_GRAMMAR("or", "2 |= 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("ori", "2 |= 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("rts", "ret"),
RZ_PSEUDO_DEFINE_GRAMMAR("sub", "1 += 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("subq", "1 += 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("tst", "1 == 0"),
RZ_PSEUDO_DEFINE_GRAMMAR("clr", "1 = 0"),
};
static const RzPseudoReplace m68k_replace[] = {
RZ_PSEUDO_DEFINE_REPLACE("+ -", "- ", 1),
};
static const RzPseudoConfig m68k_config = RZ_PSEUDO_DEFINE_CONFIG_NO_DIRECT(m68k_lexicon, m68k_replace, 4, m68k_tokenize);
RzList *m68k_tokenize(const char *assembly, size_t length) {
size_t i, p;
char *buf = NULL;
RzList *tokens = NULL;
buf = rz_str_ndup(assembly, length);
if (!buf) {
return NULL;
}
for (i = 0, p = 0; p < length; ++i, ++p) {
if (buf[p] == ',') {
p++;
}
if (p > i) {
buf[i] = buf[p];
}
}
buf[i] = 0;
/* TODO: this is slow */
if (newstr != NULL) {
newstr[0] = '\0';
for (i = 0; i < argc; i++) {
strcat(newstr, argv[i]);
strcat(newstr, (i == 0 || i == argc - 1) ? " " : ", ");
}
}
return false;
tokens = rz_str_split_duplist(buf, " ", true);
free(buf);
return tokens;
}
#define WSZ 64
static int parse(RzParse *p, const char *data, char *str) {
int i, len = strlen(data);
char w0[WSZ];
char w1[WSZ];
char w2[WSZ];
char w3[WSZ];
char w4[WSZ];
char *buf, *ptr, *optr;
if (!strcmp(data, "jr ra")) {
strcpy(str, "ret");
static bool parse(RzParse *parse, const char *assembly, RzStrBuf *sb) {
char *copy = strdup(assembly);
if (!copy) {
rz_strbuf_setf(sb, "asm(\"%s\")", assembly);
return true;
}
// malloc can be slow here :?
if (!(buf = malloc(len + 1))) {
return false;
}
memcpy(buf, data, len + 1);
rz_str_replace_in(buf, len + 1, ".l", "", 1);
rz_str_replace_in(buf, len + 1, ".w", "", 1);
rz_str_replace_in(buf, len + 1, ".d", "", 1);
rz_str_replace_in(buf, len + 1, ".b", "", 1);
rz_str_trim(buf);
if (*buf) {
w0[0] = '\0';
w1[0] = '\0';
w2[0] = '\0';
w3[0] = '\0';
w4[0] = '\0';
ptr = strchr(buf, ' ');
if (!ptr) {
ptr = strchr(buf, '\t');
}
if (ptr) {
*ptr = '\0';
for (++ptr; *ptr == ' '; ptr++) {
;
}
strncpy(w0, buf, WSZ - 1);
strncpy(w1, ptr, WSZ - 1);
optr = ptr;
ptr = strchr(ptr, ',');
if (ptr) {
*ptr = '\0';
for (++ptr; *ptr == ' '; ptr++) {
;
}
strncpy(w1, optr, WSZ - 1);
strncpy(w2, ptr, WSZ - 1);
optr = ptr;
ptr = strchr(ptr, ',');
if (ptr) {
*ptr = '\0';
for (++ptr; *ptr == ' '; ptr++) {
;
}
strncpy(w2, optr, WSZ - 1);
strncpy(w3, ptr, WSZ - 1);
optr = ptr;
// bonus
ptr = strchr(ptr, ',');
if (ptr) {
*ptr = '\0';
for (++ptr; *ptr == ' '; ptr++) {
;
}
strncpy(w3, optr, WSZ - 1);
strncpy(w4, ptr, WSZ - 1);
}
}
}
}
{
const char *wa[] = { w0, w1, w2, w3, w4 };
int nw = 0;
for (i = 0; i < 5; i++) {
if (wa[i][0] != '\0') {
nw++;
}
}
replace(nw, wa, str);
{
char *pluseq = strstr(str, "+ =");
if (pluseq) {
memcpy(pluseq, " +=", 3);
}
}
}
}
free(buf);
return true;
rz_str_replace(copy, ".l", "", 0);
rz_str_replace(copy, ".w", "", 0);
rz_str_replace(copy, ".d", "", 0);
rz_str_replace(copy, ".b", "", 0);
bool res = rz_pseudo_convert(&m68k_config, copy, sb);
free(copy);
return res;
}
RzParsePlugin rz_parse_plugin_m68k_pseudo = {

View file

@ -1,4 +1,5 @@
// SPDX-FileCopyrightText: 2012-2017 pancake <pancake@nopcode.org>
// SPDX-FileCopyrightText: 2018-2021 deroad <wargio@libero.it>
// SPDX-License-Identifier: LGPL-3.0-only
#include <stdio.h>
@ -11,245 +12,133 @@
#include <rz_analysis.h>
#include <rz_parse.h>
static int can_replace(const char *str, int idx, int max_operands) {
if (str[idx] > '9' || str[idx] < '1') {
return false;
}
if (str[idx + 1] != '\x00' && str[idx + 1] <= '9' && str[idx + 1] >= '1') {
return false;
}
if ((int)((int)str[idx] - 0x30) > max_operands) {
return false;
}
return true;
}
#include "parse_common.c"
static int replace(int argc, const char *argv[], char *newstr) {
int i, j, k;
struct {
char *op;
char *str;
int max_operands;
} ops[] = {
{ "add", "1 = 2 + 3", 3 },
{ "addi", "1 = 2 + 3", 3 },
{ "addiu", "1 = 2 + 3", 3 },
{ "addu", "1 = 2 + 3", 3 },
{ "and", "1 = 2 & 3", 3 },
{ "andi", "1 = 2 & 3", 3 },
{ "b", "goto 1", 1 },
{ "bal", "call 1", 1 },
{ "begzal", "if (1 >= 0) call 2", 2 },
{ "beq", "if (1 == 2) goto 3", 3 },
{ "beqz", "if (!1) goto 2", 2 },
{ "bgez", "if (1 >= 0) goto 2", 2 },
{ "bgtz", "if (1 > 0) goto 2", 2 },
{ "blez", "if (1 <= 0) goto 2", 2 },
{ "bltz", "if (1 < 0) goto 2", 2 },
{ "bltzal", "if (1 < 0) call 2", 2 },
{ "bne", "if (1 != 2) goto 3", 3 },
{ "bnez", "if (1) goto 2", 2 },
{ "j", "goto 1", 1 },
{ "jal", "call 1", 1 },
{ "jalr", "call 1", 1 },
{ "jr", "goto 1", 1 },
{ "lb", "1 = byte [3 + 2]", 3 },
{ "lbu", "1 = (unsigned) byte [3 + 2]", 3 },
{ "lh", "1 = halfword [3 + 2]", 3 },
{ "lhu", "1 = (unsigned) halfword [3 + 2]", 3 },
{ "li", "1 = 2", 2 },
{ "lui", "1 = 2 << 16", 2 },
{ "lw", "1 = [3 + 2]", 3 },
{ "mfhi", "1 = hi", 1 },
{ "mflo", "1 = lo", 1 },
{ "move", "1 = 2", 2 },
{ "movn", "if (3) 1 = 2", 3 },
{ "movz", "if (!3) 1 = 2", 3 },
{ "mult", "(hi,lo) = 1 * 2", 2 },
{ "multu", "unsigned (hi,lo) = 1 * 2", 2 },
{ "mul", "1 = 2 * 3", 3 },
{ "mulu", "1 = 2 * 3", 3 },
{ "negu", "1 = ~2", 2 },
{ "nop", "", 0 },
{ "nor", "1 = ~(2 | 3)", 3 },
{ "or", "1 = 2 | 3", 3 },
{ "ori", "1 = 2 | 3", 3 },
{ "sb", "byte [3 + 2] = 1", 3 },
{ "sh", "halfword [3 + 2] = 1", 3 },
{ "sll", "1 = 2 << 3", 3 },
{ "sllv", "1 = 2 << 3", 3 },
{ "slr", "1 = 2 >> 3", 3 }, // logic
{ "slt", "1 = (2 < 3)", 3 },
{ "slti", "1 = (2 < 3)", 3 },
{ "sltiu", "1 = (unsigned) (2 < 3)", 3 },
{ "sltu", "1 = (unsigned) (2 < 3)", 3 },
{ "sra", "1 = (signed) 2 >> 3", 3 }, // arithmetic
{ "srl", "1 = 2 >> 3", 3 },
{ "srlv", "1 = 2 >> 3", 3 },
{ "subu", "1 = 2 - 3", 3 },
{ "sub", "1 = 2 - 3", 3 },
{ "sw", "[3 + 2] = 1", 3 },
{ "syscall", "syscall", 0 },
{ "xor", "1 = 2 ^ 3", 3 },
{ "xori", "1 = 2 ^ 3", 3 },
{ NULL }
};
static RzList *mips_tokenize(const char *assembly, size_t length);
for (i = 0; ops[i].op != NULL; i++) {
if (!strcmp(ops[i].op, argv[0])) {
if (newstr != NULL) {
for (j = k = 0; ops[i].str[j] != '\0'; j++, k++) {
if (can_replace(ops[i].str, j, ops[i].max_operands)) {
const char *w = argv[ops[i].str[j] - '0'];
if (w != NULL) {
strcpy(newstr + k, w);
k += strlen(w) - 1;
}
} else {
newstr[k] = ops[i].str[j];
}
}
newstr[k] = '\0';
static const RzPseudoGrammar mips_lexicon[] = {
RZ_PSEUDO_DEFINE_GRAMMAR("add", "1 = 2 + 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("addi", "1 = 2 + 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("addiu", "1 = 2 + 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("addu", "1 = 2 + 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("and", "1 = 2 & 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("andi", "1 = 2 & 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("b", "goto 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("bal", "call 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("begzal", "if (1 >= 0) call 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("beq", "if (1 == 2) goto 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("beqz", "if (!1) goto 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("bgez", "if (1 >= 0) goto 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("bgtz", "if (1 > 0) goto 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("blez", "if (1 <= 0) goto 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("bltz", "if (1 < 0) goto 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("bltzal", "if (1 < 0) call 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("bne", "if (1 != 2) goto 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("bnez", "if (1) goto 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("j", "goto 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("jal", "call 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("jalr", "call 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("jr", "goto 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("lb", "1 = byte [3 + 2]"),
RZ_PSEUDO_DEFINE_GRAMMAR("lbu", "1 = (unsigned) byte [3 + 2]"),
RZ_PSEUDO_DEFINE_GRAMMAR("lh", "1 = halfword [3 + 2]"),
RZ_PSEUDO_DEFINE_GRAMMAR("lhu", "1 = (unsigned) halfword [3 + 2]"),
RZ_PSEUDO_DEFINE_GRAMMAR("li", "1 = 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("lui", "1 = 2 << #16"),
RZ_PSEUDO_DEFINE_GRAMMAR("lw", "1 = word [3 + 2]"),
RZ_PSEUDO_DEFINE_GRAMMAR("mfhi", "1 = hi"),
RZ_PSEUDO_DEFINE_GRAMMAR("mflo", "1 = lo"),
RZ_PSEUDO_DEFINE_GRAMMAR("move", "1 = 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("movn", "if (3) 1 = 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("movz", "if (!3) 1 = 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("mult", "(hi,lo) = 1 * 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("multu", "unsigned (hi,lo) = 1 * 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("mul", "1 = 2 * 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("mulu", "1 = 2 * 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("negu", "1 = ~2"),
RZ_PSEUDO_DEFINE_GRAMMAR("nop", ""),
RZ_PSEUDO_DEFINE_GRAMMAR("nor", "1 = ~(2 | 3)"),
RZ_PSEUDO_DEFINE_GRAMMAR("or", "1 = 2 | 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("ori", "1 = 2 | 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("sb", "byte [3 + 2] = 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("sh", "halfword [3 + 2] = 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("sll", "1 = 2 << 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("sllv", "1 = 2 << 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("slr", "1 = 2 >> 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("slt", "1 = (2 < 3)"),
RZ_PSEUDO_DEFINE_GRAMMAR("slti", "1 = (2 < 3)"),
RZ_PSEUDO_DEFINE_GRAMMAR("sltiu", "1 = (unsigned) (2 < 3)"),
RZ_PSEUDO_DEFINE_GRAMMAR("sltu", "1 = (unsigned) (2 < 3)"),
RZ_PSEUDO_DEFINE_GRAMMAR("sra", "1 = (signed) 2 >> 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("srl", "1 = 2 >> 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("srlv", "1 = 2 >> 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("subu", "1 = 2 - 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("sub", "1 = 2 - 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("sw", "word [3 + 2] = 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("syscall", "syscall"),
RZ_PSEUDO_DEFINE_GRAMMAR("xor", "1 = 2 ^ 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("xori", "1 = 2 ^ 3"),
};
static const RzPseudoDirect mips_direct[] = {
RZ_PSEUDO_DEFINE_DIRECT("jr ra", "return"),
};
static const RzPseudoReplace mips_replace[] = {
RZ_PSEUDO_DEFINE_REPLACE(" + 0]", "]", 0),
RZ_PSEUDO_DEFINE_REPLACE("+ -", "- ", 1),
RZ_PSEUDO_DEFINE_REPLACE("0 << 16", "0", 1),
};
static const RzPseudoConfig mips_config = RZ_PSEUDO_DEFINE_CONFIG(mips_direct, mips_lexicon, mips_replace, 4, mips_tokenize);
RzList *mips_tokenize(const char *assembly, size_t length) {
size_t i, p;
char *buf = NULL;
bool insert_zero = false;
RzList *tokens = NULL;
buf = rz_str_ndup(assembly, length);
if (!buf) {
return NULL;
}
for (i = 0, p = 0; p < length; ++i, ++p) {
if (buf[p] == ',') {
p++;
} else if (buf[p] == '(') {
buf[p] = ' ';
if (!IS_HEXCHAR(buf[p - 1])) {
p++;
insert_zero = true;
}
return true;
} else if (buf[p] == ')') {
buf[p] = 0;
} else if (buf[p] == 'z' && buf[p + 1] == 'e' && buf[p + 2] == 'r' && buf[p + 3] == 'o') {
p += 3;
buf[p] = '0';
}
if (p > i) {
buf[i] = buf[p];
}
}
buf[i] = 0;
/* TODO: this is slow */
if (newstr != NULL) {
newstr[0] = '\0';
for (i = 0; i < argc; i++) {
strcat(newstr, argv[i]);
strcat(newstr, (i == 0 || i == argc - 1) ? " " : ", ");
}
}
return false;
}
#define WSZ 64
static int parse(RzParse *p, const char *data, char *str) {
int i, len = strlen(data);
char w0[WSZ];
char w1[WSZ];
char w2[WSZ];
char w3[WSZ];
char w4[WSZ];
char *buf, *ptr, *optr;
if (!strcmp(data, "jr ra")) {
strcpy(str, "ret");
return true;
}
// malloc can be slow here :?
if (!(buf = malloc(len + 1))) {
return false;
}
memcpy(buf, data, len + 1);
rz_str_replace_char(buf, '(', ',');
rz_str_replace_char(buf, ')', ' ');
rz_str_trim(buf);
if (*buf) {
w0[0] = '\0';
w1[0] = '\0';
w2[0] = '\0';
w3[0] = '\0';
w4[0] = '\0';
ptr = strchr(buf, ' ');
if (!ptr) {
ptr = strchr(buf, '\t');
}
if (ptr) {
*ptr = '\0';
for (++ptr; *ptr == ' '; ptr++) {
;
}
strncpy(w0, buf, WSZ - 1);
strncpy(w1, ptr, WSZ - 1);
optr = ptr;
ptr = strchr(ptr, ',');
if (ptr) {
*ptr = '\0';
for (++ptr; *ptr == ' '; ptr++) {
;
}
strncpy(w1, optr, WSZ - 1);
strncpy(w2, ptr, WSZ - 1);
optr = ptr;
ptr = strchr(ptr, ',');
if (ptr) {
*ptr = '\0';
for (++ptr; *ptr == ' '; ptr++) {
;
}
strncpy(w2, optr, WSZ - 1);
strncpy(w3, ptr, WSZ - 1);
optr = ptr;
// bonus
ptr = strchr(ptr, ',');
if (ptr) {
*ptr = '\0';
for (++ptr; *ptr == ' '; ptr++) {
;
}
strncpy(w3, optr, WSZ - 1);
strncpy(w4, ptr, WSZ - 1);
}
}
}
} else {
strncpy(w0, buf, WSZ - 1);
}
{
const char *wa[] = { w0, w1, w2, w3, w4 };
int nw = 0;
for (i = 0; i < 4; i++) {
if (wa[i][0] != '\0') {
nw++;
}
}
replace(nw, wa, str);
{
char *p = strdup(str);
p = rz_str_replace(p, "+ -", "- ", 0);
p = rz_str_replace(p, " + ]", " + 0]", 0);
p = rz_str_replace(p, "zero", "0", 1);
if (!strncmp(p, "0 = ", 4)) {
*p = 0; // nop
}
if (!strcmp(w1, w2)) {
char a[32], b[32];
#define REPLACE(x, y) \
do { \
int snprintf_len1_ = snprintf(a, 32, x, w1, w1); \
int snprintf_len2_ = snprintf(b, 32, y, w1); \
if (snprintf_len1_ < 32 && snprintf_len2_ < 32) { \
p = rz_str_replace(p, a, b, 0); \
} \
} while (0)
// TODO: optimize
REPLACE("%s = %s +", "%s +=");
REPLACE("%s = %s -", "%s -=");
REPLACE("%s = %s &", "%s &=");
REPLACE("%s = %s |", "%s |=");
REPLACE("%s = %s ^", "%s ^=");
REPLACE("%s = %s >>", "%s >>=");
REPLACE("%s = %s <<", "%s <<=");
}
p = rz_str_replace(p, ":", "0000", 0);
strcpy(str, p);
free(p);
}
}
}
tokens = rz_str_split_duplist(buf, " ", true);
free(buf);
return true;
if (!tokens) {
return NULL;
}
if (insert_zero) {
rz_list_insert(tokens, rz_list_length(tokens) - 1, strdup("0"));
}
return tokens;
}
static bool parse(RzParse *parse, const char *assembly, RzStrBuf *sb) {
return rz_pseudo_convert(&mips_config, assembly, sb);
}
static bool subvar(RzParse *p, RzAnalysisFunction *f, ut64 addr, int oplen, char *data, char *str, int len) {

View file

@ -1,4 +1,5 @@
// SPDX-FileCopyrightText: 2015-2017 pancake <pancake@nopcode.org>
// SPDX-FileCopyrightText: 2018-2021 deroad <wargio@libero.it>
// SPDX-License-Identifier: LGPL-3.0-only
#include <stdio.h>
@ -1615,7 +1616,7 @@ static int replace(int argc, const char *argv[], char *newstr) {
}
#define WSZ 128
static int parse(RzParse *p, const char *data, char *str) {
static bool parse(RzParse *p, const char *data, RzStrBuf *sb) {
int i, len = strlen(data);
char w0[WSZ];
char w1[WSZ];
@ -1623,10 +1624,11 @@ static int parse(RzParse *p, const char *data, char *str) {
char w3[WSZ];
char w4[WSZ];
char w5[WSZ];
char str[1024] = { 0 };
char *buf, *ptr, *optr;
if (!strcmp(data, "jr ra")) {
strcpy(str, "return");
rz_strbuf_set(sb, "return");
return true;
}
@ -1748,6 +1750,7 @@ static int parse(RzParse *p, const char *data, char *str) {
}
}
free(buf);
rz_strbuf_set(sb, str);
return true;
}

View file

@ -107,8 +107,9 @@ static int replace(int argc, const char *argv[], char *newstr) {
return false;
}
static int parse(RzParse *p, const char *data, char *str) {
static bool parse(RzParse *p, const char *data, RzStrBuf *sb) {
char w0[256], w1[256], w2[256], w3[256];
char str[1024] = { 0 };
int i, len = strlen(data), n;
char *buf, *ptr, *optr, *num;
@ -214,6 +215,7 @@ static int parse(RzParse *p, const char *data, char *str) {
free(s);
}
free(buf);
rz_strbuf_set(sb, str);
return true;
}

View file

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2017 deroad <wargio@libero.it>
// SPDX-FileCopyrightText: 2017-2021 deroad <wargio@libero.it>
// SPDX-License-Identifier: LGPL-3.0-only
#include <stdio.h>
@ -11,258 +11,165 @@
#include <rz_analysis.h>
#include <rz_parse.h>
static int replace(int argc, const char *argv[], char *newstr) {
int i, j, k;
struct {
char *op;
char *str;
} ops[] = {
{ "add", "B += A" },
{ "addc", "B += A + t" },
{ "addv", "B += A; t = int_overflow (B)" },
{ "and", "B &= A" },
{ "and.b", "B &= A" },
{ "bf", "if (!t) goto A" },
{ "bf.s", "if (!t) goto A" },
{ "bra", "goto A" },
{ "brk", "_break_exception ()" },
{ "bsr", "A ()" },
{ "bsrf", "A ()" },
{ "bt", "if (t) goto A" },
{ "bt.s", "if (t) goto A" },
{ "clrmac", "_clrmac ()" },
{ "clrs", "_clrs ()" },
{ "clrt", "_clrt ()" },
{ "cmp/eq", "t = B == A ? 1 : 0" },
{ "cmp/ge", "t = B >= A ? 1 : 0" },
{ "cmp/gt", "t = B > A ? 1 : 0" },
{ "cmp/hi", "t = (unsigned) B > (unsigned) A ? 1 : 0" },
{ "cmp/hs", "t = (unsigned) B >= (unsigned) A ? 1 : 0" },
{ "cmp/pl", "t = A > 0 ? 1 : 0" },
{ "cmp/pz", "t = A >= 0 ? 1 : 0" },
{ "cmp/str", "t = A ^ B ? 1 : 0" },
{ "div1", "B /= A" },
{ "dmuls.l", "mac = B * A" },
{ "dmulu.l", "mac = (unsigned) B * (unsigned) A" },
{ "dt", "A--; t = !A ? 1 : 0" },
{ "exts.b", "B = (int) A" },
{ "extu.b", "B = (unsigned int) A" },
{ "exts.w", "B = (int) A" },
{ "extu.w", "B = (unsigned int) A" },
{ "fabs", "A = abs (A)" },
{ "fadd", "B += A" },
{ "fcmp/eq", "t = B == A ? 1 : 0" },
{ "fcmp/gt", "t = B > A ? 1 : 0" },
{ "fcnvds", "B = A" },
{ "fdiv", "B /= A" },
{ "flds", "B = A" },
{ "fldi0", "A = 0.0f" },
{ "fldi1", "A = 1.0f" },
{ "float", "B = A" },
{ "fmac", "C += A * B" },
{ "fmov", "B = A" },
{ "fmov.s", "B = A" },
{ "fmul", "B *= A" },
{ "fneg", "A = -A" },
{ "fsqrt", "A = sqrt (A)" },
{ "fsts", "B = A" },
{ "fsub", "B -= A" },
{ "ftrc", "B = trunc (A)" },
{ "ftrv", "B *= A" },
{ "jmp", "goto A" },
{ "jsr", "A ()" },
{ "ldr", "B = A" },
{ "ldr.l", "B = A" },
{ "lds", "B = A" },
{ "lds.l", "B = A" },
{ "mov", "B = A" },
{ "mov.b", "B = A" },
{ "mov.l", "B = A" },
{ "mov.w", "B = A" },
{ "movca.l", "B = A" },
{ "movt", "A = t" },
{ "muls.w", "macl = A * B" },
{ "mulu.w", "macl = (unsigned) A * (unsigned) B" },
{ "neg", "A = -A" },
{ "negc", "A = (-A) - t" },
{ "nop", "" },
{ "not", "A = !A" },
{ "or", "B |= A" },
{ "rotcl", "t = A & 0x80000000 ? 0 : 1; A = (A << 1) | t" },
{ "rotl", "A = (A << 1) | (A >> 31)" },
{ "rotr", "A = (A << 31) | (A >> 1)" },
{ "rte", "_rte ()" },
{ "rts", "return" },
{ "sets", "s = 1" },
{ "sett", "t = 1" },
{ "shad", "B = A >= 0 ? B << A : B >> (31 - A)" },
{ "shal", "A <<= 1" },
{ "shar", "A >>= 1" },
{ "shld", "B = A >= 0 ? B << A : B >> (31 - A)" },
{ "shll", "A <<= 1" },
{ "shll2", "A <<= 2" },
{ "shll8", "A <<= 8" },
{ "shll16", "A <<= 16" },
{ "shlr", "A >>= 1" },
{ "shlr2", "A >>= 2" },
{ "shlr8", "A >>= 8" },
{ "shlr16", "A >>= 16" },
{ "sleep", "_halt ()" },
{ "stc", "B = A" },
{ "stc.l", "B = A" },
{ "sts", "B = A" },
{ "sts.l", "B = A" },
{ "sub", "B -= A" },
{ "subc", "B -= A - t" },
{ "subv", "B -= A; t = int_underflow (B)" },
{ "swap.b", "swap_byte (B, A)" },
{ "swap.w", "swap_word (B, A)" },
{ "tas.b", "test_and_set (A)" },
{ "trapa", "trap (A)" },
{ "tst", "t = B & A ? 0 : 1" },
{ "xor", "B ^= A" },
{ "xor.b", "B ^= A" },
{ NULL }
};
#include "parse_common.c"
for (i = 0; ops[i].op != NULL; i++) {
if (!strcmp(ops[i].op, argv[0])) {
if (newstr != NULL) {
for (j = k = 0; ops[i].str[j] != '\0'; j++, k++) {
if (ops[i].str[j] >= 'A' && ops[i].str[j] <= 'J') {
const char *w = argv[ops[i].str[j] - '@'];
if (w != NULL) {
strcpy(newstr + k, w);
k += strlen(w) - 1;
}
} else {
newstr[k] = ops[i].str[j];
}
}
newstr[k] = '\0';
}
return true;
}
static RzList *sh_tokenize(const char *assembly, size_t length);
static const RzPseudoGrammar sh_lexicon[] = {
RZ_PSEUDO_DEFINE_GRAMMAR("add", "2 += 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("addc", "2 += 1 + t"),
RZ_PSEUDO_DEFINE_GRAMMAR("addv", "2 += 1; t = int_overflow (2)"),
RZ_PSEUDO_DEFINE_GRAMMAR("and", "2 &= 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("and.b", "2 &= 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("bf", "if (!t) goto 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("bf.s", "if (!t) goto 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("bra", "goto 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("brk", "_break_exception ()"),
RZ_PSEUDO_DEFINE_GRAMMAR("bsr", "1 ()"),
RZ_PSEUDO_DEFINE_GRAMMAR("bsrf", "1 ()"),
RZ_PSEUDO_DEFINE_GRAMMAR("bt", "if (t) goto 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("bt.s", "if (t) goto 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("clrmac", "_clrmac ()"),
RZ_PSEUDO_DEFINE_GRAMMAR("clrs", "_clrs ()"),
RZ_PSEUDO_DEFINE_GRAMMAR("clrt", "_clrt ()"),
RZ_PSEUDO_DEFINE_GRAMMAR("cmp/eq", "t = 2 == 1 ? #1 : 0"),
RZ_PSEUDO_DEFINE_GRAMMAR("cmp/ge", "t = 2 >= 1 ? #1 : 0"),
RZ_PSEUDO_DEFINE_GRAMMAR("cmp/gt", "t = 2 > 1 ? #1 : 0"),
RZ_PSEUDO_DEFINE_GRAMMAR("cmp/hi", "t = (unsigned) 2 > (unsigned) 1 ? #1 : 0"),
RZ_PSEUDO_DEFINE_GRAMMAR("cmp/hs", "t = (unsigned) 2 >= (unsigned) 1 ? #1 : 0"),
RZ_PSEUDO_DEFINE_GRAMMAR("cmp/pl", "t = 1 > 0 ? #1 : 0"),
RZ_PSEUDO_DEFINE_GRAMMAR("cmp/pz", "t = 1 >= 0 ? #1 : 0"),
RZ_PSEUDO_DEFINE_GRAMMAR("cmp/str", "t = 1 ^ 2 ? #1 : 0"),
RZ_PSEUDO_DEFINE_GRAMMAR("div1", "2 /= 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("dmuls.l", "mac = 2 * 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("dmulu.l", "mac = (unsigned) 2 * (unsigned) 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("dt", "1--; t = !1 ? #1 : 0"),
RZ_PSEUDO_DEFINE_GRAMMAR("exts.b", "2 = (int) 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("exts.w", "2 = (int) 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("extu.b", "2 = (unsigned int) 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("extu.w", "2 = (unsigned int) 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("fabs", "1 = abs (1)"),
RZ_PSEUDO_DEFINE_GRAMMAR("fadd", "2 += 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("fcmp/eq", "t = 2 == 1 ? #1 : 0"),
RZ_PSEUDO_DEFINE_GRAMMAR("fcmp/gt", "t = 2 > 1 ? #1 : 0"),
RZ_PSEUDO_DEFINE_GRAMMAR("fcnvds", "2 = 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("fdiv", "2 /= 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("fldi0", "1 = 0.0f"),
RZ_PSEUDO_DEFINE_GRAMMAR("fldi1", "1 = #1.0f"),
RZ_PSEUDO_DEFINE_GRAMMAR("flds", "2 = 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("float", "2 = 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("fmac", "3 += 1 * 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("fmov", "2 = 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("fmov.s", "2 = 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("fmul", "2 *= 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("fneg", "1 = -1"),
RZ_PSEUDO_DEFINE_GRAMMAR("fsqrt", "1 = sqrt (1)"),
RZ_PSEUDO_DEFINE_GRAMMAR("fsts", "2 = 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("fsub", "2 -= 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("ftrc", "2 = trunc (1)"),
RZ_PSEUDO_DEFINE_GRAMMAR("ftrv", "2 *= 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("jmp", "goto 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("jsr", "1 ()"),
RZ_PSEUDO_DEFINE_GRAMMAR("ldr", "2 = 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("ldr.l", "2 = 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("lds", "2 = 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("lds.l", "2 = 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("mov", "2 = 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("mov.b", "2 = 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("mov.l", "2 = 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("mov.w", "2 = 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("movca.l", "2 = 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("movt", "1 = t"),
RZ_PSEUDO_DEFINE_GRAMMAR("muls.w", "macl = 1 * 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("mulu.w", "macl = (unsigned) 1 * (unsigned) 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("neg", "1 = -1"),
RZ_PSEUDO_DEFINE_GRAMMAR("negc", "1 = (-1) - t"),
RZ_PSEUDO_DEFINE_GRAMMAR("nop", ""),
RZ_PSEUDO_DEFINE_GRAMMAR("not", "1 = !1"),
RZ_PSEUDO_DEFINE_GRAMMAR("or", "2 |= 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("rotcl", "t = 1 & 0x#80000000 ? 0 : #1; 1 = (1 << #1) | t"),
RZ_PSEUDO_DEFINE_GRAMMAR("rotl", "1 = (1 << #1) | (1 >> #31)"),
RZ_PSEUDO_DEFINE_GRAMMAR("rotr", "1 = (1 << #31) | (1 >> #1)"),
RZ_PSEUDO_DEFINE_GRAMMAR("rte", "_rte ()"),
RZ_PSEUDO_DEFINE_GRAMMAR("rts", "return"),
RZ_PSEUDO_DEFINE_GRAMMAR("sets", "s = #1"),
RZ_PSEUDO_DEFINE_GRAMMAR("sett", "t = #1"),
RZ_PSEUDO_DEFINE_GRAMMAR("shad", "2 = 1 >= 0 ? 2 << 1 | 2 >> (#31 - 1)"),
RZ_PSEUDO_DEFINE_GRAMMAR("shal", "1 <<= #1"),
RZ_PSEUDO_DEFINE_GRAMMAR("shar", "1 >>= #1"),
RZ_PSEUDO_DEFINE_GRAMMAR("shld", "2 = 1 >= 0 ? 2 << 1 | 2 >> (#31 - 1)"),
RZ_PSEUDO_DEFINE_GRAMMAR("shll", "1 <<= #1"),
RZ_PSEUDO_DEFINE_GRAMMAR("shll#16", "1 <<= #16"),
RZ_PSEUDO_DEFINE_GRAMMAR("shll2", "1 <<= #2"),
RZ_PSEUDO_DEFINE_GRAMMAR("shll8", "1 <<= #8"),
RZ_PSEUDO_DEFINE_GRAMMAR("shlr", "1 >>= #1"),
RZ_PSEUDO_DEFINE_GRAMMAR("shlr#16", "1 >>= #16"),
RZ_PSEUDO_DEFINE_GRAMMAR("shlr2", "1 >>= #2"),
RZ_PSEUDO_DEFINE_GRAMMAR("shlr8", "1 >>= #8"),
RZ_PSEUDO_DEFINE_GRAMMAR("sleep", "_halt ()"),
RZ_PSEUDO_DEFINE_GRAMMAR("stc", "2 = 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("stc.l", "2 = 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("sts", "2 = 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("sts.l", "2 = 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("sub", "2 -= 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("subc", "2 -= 1 - t"),
RZ_PSEUDO_DEFINE_GRAMMAR("subv", "2 -= 1; t = int_underflow (2)"),
RZ_PSEUDO_DEFINE_GRAMMAR("swap.b", "swap_byte (2, 1)"),
RZ_PSEUDO_DEFINE_GRAMMAR("swap.w", "swap_word (2, 1)"),
RZ_PSEUDO_DEFINE_GRAMMAR("tas.b", "test_and_set (1)"),
RZ_PSEUDO_DEFINE_GRAMMAR("trapa", "trap (1)"),
RZ_PSEUDO_DEFINE_GRAMMAR("tst", "t = 2 & 1 ? 0 : #1"),
RZ_PSEUDO_DEFINE_GRAMMAR("xor", "2 ^= 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("xor.b", "2 ^= 1"),
};
static const RzPseudoReplace sh_replace[] = {
RZ_PSEUDO_DEFINE_REPLACE("+ -", "- ", 1),
};
static const RzPseudoConfig sh_config = RZ_PSEUDO_DEFINE_CONFIG_NO_DIRECT(sh_lexicon, sh_replace, 4, sh_tokenize);
RzList *sh_tokenize(const char *assembly, size_t length) {
size_t i, p;
char *buf = NULL;
bool ignore_comma = false;
RzList *tokens = NULL;
buf = rz_str_ndup(assembly, length);
if (!buf) {
return NULL;
}
/* TODO: this is slow */
if (newstr != NULL) {
newstr[0] = '\0';
for (i = 0; i < argc; i++) {
strcat(newstr, argv[i]);
strcat(newstr, (i == 0 || i == argc - 1) ? " " : ", ");
for (i = 0, p = 0; p < length; ++i, ++p) {
if (buf[p] == ',' && !ignore_comma) {
p++;
} else if (buf[p] == '(') {
ignore_comma = true;
} else if (buf[p] == ')') {
ignore_comma = false;
}
if (p > i) {
buf[i] = buf[p];
}
}
buf[i] = 0;
return false;
tokens = rz_str_split_duplist(buf, " ", true);
free(buf);
if (!tokens) {
return NULL;
}
RzListIter *it;
rz_list_foreach (tokens, it, buf) {
it->data = rz_str_replace(buf, ",", " + ", 1);
}
return tokens;
}
#define WSZ 128
static int parse(RzParse *p, const char *data, char *str) {
int i, len = strlen(data);
char w0[WSZ];
char w1[WSZ];
char w2[WSZ];
char w3[WSZ];
char w4[WSZ];
char *buf, *ptr, *optr, *par;
// malloc can be slow here :?
if (!(buf = malloc(len + 1))) {
return false;
}
memcpy(buf, data, len + 1);
rz_str_trim(buf);
if (*buf) {
w0[0] = '\0';
w1[0] = '\0';
w2[0] = '\0';
w3[0] = '\0';
w4[0] = '\0';
ptr = strchr(buf, ' ');
if (!ptr) {
ptr = strchr(buf, '\t');
}
if (ptr) {
*ptr = '\0';
for (++ptr; *ptr == ' '; ptr++) {
//nothing to see here
}
strncpy(w0, buf, WSZ - 1);
strncpy(w1, ptr, WSZ - 1);
optr = ptr;
par = strchr(ptr, '(');
if (par && strchr(ptr, ',') > par) {
ptr = strchr(ptr, ')');
if (ptr) {
ptr = strchr(ptr, ',');
}
} else {
ptr = strchr(ptr, ',');
}
if (ptr) {
*ptr = '\0';
for (++ptr; *ptr == ' '; ptr++) {
//nothing to see here
}
strncpy(w1, optr, WSZ - 1);
strncpy(w2, ptr, WSZ - 1);
optr = ptr;
par = strchr(ptr, '(');
if (par && strchr(ptr, ',') > par) {
ptr = strchr(ptr, ')');
if (ptr) {
ptr = strchr(ptr, ',');
}
} else {
ptr = strchr(ptr, ',');
}
if (ptr) {
*ptr = '\0';
for (++ptr; *ptr == ' '; ptr++) {
//nothing to see here
}
strncpy(w2, optr, WSZ - 1);
strncpy(w3, ptr, WSZ - 1);
optr = ptr;
// bonus
par = strchr(ptr, '(');
if (par && strchr(ptr, ',') > par) {
ptr = strchr(ptr, ')');
if (ptr) {
ptr = strchr(ptr, ',');
}
} else {
ptr = strchr(ptr, ',');
}
if (ptr) {
*ptr = '\0';
for (++ptr; *ptr == ' '; ptr++) {
//nothing to see here
}
strncpy(w3, optr, WSZ - 1);
strncpy(w4, ptr, WSZ - 1);
}
}
}
} else {
strncpy(w0, buf, WSZ - 1);
}
{
const char *wa[] = { w0, w1, w2, w3, w4 };
int nw = 0;
for (i = 0; i < 5; i++) {
if (wa[i][0] != '\0') {
nw++;
}
}
replace(nw, wa, str);
}
}
free(buf);
return true;
static bool parse(RzParse *parse, const char *assembly, RzStrBuf *sb) {
return rz_pseudo_convert(&sh_config, assembly, sb);
}
RzParsePlugin rz_parse_plugin_sh_pseudo = {

View file

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2020 pancake <pancake@nopcode.org>
// SPDX-FileCopyrightText: 2021 deroad <wargio@libero.it>
// SPDX-License-Identifier: LGPL-3.0-only
#include <rz_lib.h>
@ -7,172 +7,114 @@
#include <rz_parse.h>
// https://www.ti.com/lit/ug/spru732j/spru732j.pdf
#include "parse_common.c"
static int replace(int argc, const char *argv[], char *newstr) {
int i, j, k;
struct {
int narg;
char *op;
char *str;
} ops[] = {
{ 3, "add", "3 = 1 + 2" }, // add b12, b1, b9 -> b9 = b12 + b1
{ 3, "addu", "3 = 1 + 2" },
{ 3, "addw", "3 = 1 + 2" },
{ 3, "addaw", "3 = 1 + 2" },
{ 3, "addab", "3 = 1 + 2" },
{ 3, "addah", "3 = 1 + 2" },
{ 2, "addk", "2 += 1" }, // addk 123, b0 -> b0 += 123
{ 3, "sadd", "3 = 1 + 2" }, // sadd b12, b1, b9 -> b9 = b12 + b1
{ 3, "sadd2", "3 = 1 + 2" }, // sadd2 b12, b1, b9 -> b9 = b12 + b1
{ 3, "sub", "3 = 1 - 2" }, // sub b12, b1, b9 -> b9 = b12 - b1
{ 3, "subu", "3 = 1 - 2" }, // sub b12, b1, b9 -> b9 = b12 - b1
{ 3, "sub2", "3 = 1 - 2" }, // sub b12, b1, b9 -> b9 = b12 - b1
{ 3, "subab", "3 = 1 - 2" }, // sub b12, b1, b9 -> b9 = b12 - b1
{ 3, "ssub", "3 = 1 - 2" }, // ssub b12, b1, b9 -> b9 = b12 - b1
{ 2, "mv", "2 = 1" },
{ 2, "mvk", "2 = 1" }, // mvk 1, a0 -> a0 = 1
{ 2, "mvklh", "2 = (half) 1" }, // mvk 1, a0 -> a0 = 1
{ 3, "band", "3 = 1 & 2" }, //
{ 1, "zero", "1 = zero" },
{ 3, "andn", "4 = 1 ~ 2" }, //
{ 3, "cmpgtu", "3 = 1 cmpgtu 2" }, //
{ 3, "cmpeq", "3 = 1 == 2" }, //
{ 3, "cmpge", "3 = 1 >= 2" }, //
{ 3, "cmplt", "3 = 1 <= 2" }, //
{ 3, "smpylh", "3 = 1 * 2" }, //
{ 3, "smpy", "3 = 1 * 2" }, //
{ 3, "smpyh", "3 = 1 * 2" }, //
{ 3, "mpyu4", "3 = 1 * 2" }, //
{ 3, "avg2", "3 = 1 avg 2" }, //
{ 3, "pack2", "3 = 1 pack 2" }, //
{ 3, "smpy", "3 = 1 * 2" }, //
{ 3, "max2", "3 = max(1, 2)" }, //
{ 3, "mpy", "3 = 1 * 2" }, //
{ 3, "mpy2", "3 = 1 * 2" }, //
{ 3, "mpyu", "3 = 1 * 2" }, //
{ 3, "mpyh", "3 = 1 * 2" }, //
{ 3, "mpyhl", "3 = 1 * 2" }, //
{ 3, "mpyhl", "3 = 1 * 2" }, //
{ 3, "mpylh", "3 = 1 * 2" }, //
{ 3, "mpysu", "3 = 1 * 2" }, //
{ 3, "smpyhl", "3 = 1 * 2" }, //
{ 3, "mpyhlu", "3 = 1 * 2" }, //
{ 3, "mpyhslu", "3 = 1 * 2" }, //
{ 3, "mpyluhs", "3 = 1 * 2" }, //
{ 3, "mpyhi", "3 = 1 * 2" }, //
{ 3, "mpyhu", "3 = 1 * 2" }, //
{ 3, "mpyhus", "3 = 1 * 2" }, //
{ 3, "mpyhsu", "3 = 1 * 2" }, //
{ 3, "mpyhul", "3 = 1 * 2" }, //
{ 3, "mpyhuls", "3 = 1 * 2" }, //
{ 3, "mpyhir", "3 = 1 * 2" }, //
{ 3, "mpyli", "3 = 1 * 2" }, //
{ 3, "mpylir", "3 = 1 * 2" }, //
{ 4, "ext", "4 = 2 ext 1 .. 3" }, //
{ 4, "extu", "4 = 2 ext 1 .. 3" }, //
{ 0, "reti", "ret" }, // reti -> ret
{ 2, "lddw", "2 = (word)1" }, // lddw
{ 2, "ldhu", "2 = (half)1" }, // ldhu
{ 2, "ldb", "2 = (byte)1" }, // ldb
{ 2, "ldbu", "2 = (byte)1" }, // ldbu
{ 2, "ldndw", "2 = 1" }, // ldbu
{ 2, "ldnw", "2 = 1" }, // ldbu
{ 2, "ldw", "2 = (word)1" }, // ldw
{ 2, "ldh", "2 = (half)1" }, // ldw
{ 2, "stb", "2 = (byte)1" }, // stb
{ 2, "stw", "2 = (word)1" }, // stw
{ 2, "sth", "2 = (half)1" }, // stw
{ 2, "stnw", "2 = (word)1" }, // stw
{ 2, "stdw", "2 = (half)1" }, // stw
{ 2, "stndw", "2 = (half)1" }, // stw
{ 3, "or", "3 = 2 | 1" },
{ 3, "shl", "3 = (2 & Oxffffff) << 1" },
{ 3, "shr", "3 = (2 & Oxffffff) << 1" },
{ 3, "shlmb", "3 = << 1" },
{ 4, "set", "4 = 2 .bitset 1 .. 2" }, // set a29,0x1a, 1, a19
{ 4, "clr", "4 = 2 .bitclear 1 .. 2" }, // clr a29,0x1a, 1, a19
{ 0, "invalid", "" },
{ 0, "nop", "" },
{ 0, NULL }
};
if (!newstr) {
return false;
static RzList *tms320_tokenize(const char *assembly, size_t length);
static const RzPseudoGrammar tms320_lexicon[] = {
RZ_PSEUDO_DEFINE_GRAMMAR("add", "3 = 1 + 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("addab", "3 = 1 + 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("addah", "3 = 1 + 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("addaw", "3 = 1 + 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("addk", "2 += 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("addu", "3 = 1 + 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("addw", "3 = 1 + 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("andn", "3 = 1 ~ 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("avg2", "3 = 1 avg 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("b", "goto 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("band", "3 = 1 & 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("clr", "4 = 2 .bitclear 1 .. 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("cmpeq", "3 = 1 == 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("cmpge", "3 = 1 >= 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("cmpgtu", "3 = 1 > 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("cmplt", "3 = 1 < 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("ext", "4 = 2 ext 1 .. 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("extu", "4 = 2 ext 1 .. 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("ldb", "2 = (byte) 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("ldbu", "2 = (byte) 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("lddw", "2 = (word) 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("ldh", "2 = (half) 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("ldhu", "2 = (half) 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("ldndw", "2 = 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("ldnw", "2 = 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("ldw", "2 = (word) 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("max2", "3 = max(1, 2)"),
RZ_PSEUDO_DEFINE_GRAMMAR("mpy", "3 = 1 * 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("mpy2", "3 = 1 * 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("mpyh", "3 = 1 * 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("mpyhi", "3 = 1 * 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("mpyhir", "3 = 1 * 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("mpyhl", "3 = 1 * 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("mpyhl", "3 = 1 * 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("mpyhlu", "3 = 1 * 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("mpyhslu", "3 = 1 * 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("mpyhsu", "3 = 1 * 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("mpyhu", "3 = 1 * 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("mpyhul", "3 = 1 * 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("mpyhuls", "3 = 1 * 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("mpyhus", "3 = 1 * 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("mpylh", "3 = 1 * 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("mpyli", "3 = 1 * 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("mpylir", "3 = 1 * 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("mpyluhs", "3 = 1 * 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("mpysu", "3 = 1 * 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("mpyu", "3 = 1 * 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("mpyu4", "3 = 1 * 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("mv", "2 = 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("mvk", "2 = 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("mvklh", "2 = (half) 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("nop", ""),
RZ_PSEUDO_DEFINE_GRAMMAR("or", "3 = 2 | 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("pack2", "3 = 1 pack 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("reti", "return"),
RZ_PSEUDO_DEFINE_GRAMMAR("sadd", "3 = 1 + 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("sadd2", "3 = 1 + 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("set", "4 = 2 .bitset 1 .. 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("shl", "3 = (2 & #0xffffff) << 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("shlmb", "3 = << 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("shr", "3 = (2 & #0xffffff) << 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("smpy", "3 = 1 * 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("smpy", "3 = 1 * 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("smpyh", "3 = 1 * 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("smpyhl", "3 = 1 * 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("smpylh", "3 = 1 * 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("ssub", "3 = 1 - 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("stb", "2 = (byte) 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("stdw", "2 = (half) 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("sth", "2 = (half) 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("stndw", "2 = (half) 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("stnw", "2 = (word) 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("stw", "2 = (word) 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("sub", "3 = 1 - 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("sub2", "3 = 1 - 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("subab", "3 = 1 - 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("subu", "3 = 1 - 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("zero", "1 = 0"),
};
static const RzPseudoConfig tms320_config = RZ_PSEUDO_DEFINE_CONFIG_ONLY_LEXICON(tms320_lexicon, 5, tms320_tokenize);
RzList *tms320_tokenize(const char *assembly, size_t length) {
char *buf = NULL, *sp = NULL;
RzList *tokens = NULL;
buf = rz_str_ndup(assembly, length);
if (!buf) {
return NULL;
}
for (i = 0; ops[i].op; i++) {
if (ops[i].narg) {
if (argc - 1 != ops[i].narg) {
continue;
}
}
if (!strcmp(ops[i].op, argv[0])) {
for (j = k = 0; ops[i].str[j]; j++, k++) {
if (IS_DIGIT(ops[i].str[j])) {
int index = ops[i].str[j] - '0';
if (index >= 0 && index < argc) {
const char *w = argv[index];
if (!RZ_STR_ISEMPTY(w)) {
rz_str_cpy(newstr + k, w);
k += strlen(w) - 1;
}
}
} else {
newstr[k] = ops[i].str[j];
}
}
newstr[k] = '\0';
if (argc == 4 && argv[2][0] == '[') {
strcat(newstr + k, "+");
strcat(newstr + k + 3, argv[2]);
}
return true;
}
sp = strchr(buf, ' ');
if (sp) {
*sp = ',';
}
/* TODO: this is slow */
newstr[0] = '\0';
for (i = 0; i < argc; i++) {
strcat(newstr, argv[i]);
strcat(newstr, (i == 0 || i == argc - 1) ? " " : ",");
}
return false;
tokens = rz_str_split_duplist(buf, ",", true);
free(buf);
return tokens;
}
static int parse(RzParse *p, const char *data, char *str) {
if (!strncmp(data, "|| ", 3)) {
data += 3;
}
if (RZ_STR_ISEMPTY(data)) {
*str = 0;
return false;
}
char *buf = strdup(data);
RzListIter *iter;
char *sp = strchr(buf, ' ');
size_t nw = 1;
const char *wa[5] = { 0 };
wa[0] = buf;
RzList *list = NULL;
if (sp) {
*sp++ = 0;
list = rz_str_split_list(sp, ",", 0);
char *w;
rz_list_foreach (list, iter, w) {
wa[nw] = w;
nw++;
if (nw == 5) {
break;
}
}
}
replace(nw, wa, str);
free(buf);
rz_list_free(list);
return true;
static bool parse(RzParse *parse, const char *assembly, RzStrBuf *sb) {
return rz_pseudo_convert(&tms320_config, assembly, sb);
}
RzParsePlugin rz_parse_plugin_tms320_pseudo = {

View file

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2020 pancake <pancake@nopcode.org>
// SPDX-FileCopyrightText: 2021 deroad <wargio@libero.it>
// SPDX-License-Identifier: LGPL-3.0-only
#include <rz_lib.h>
@ -8,194 +8,132 @@
// https://www.renesas.com/us/en/doc/products/mpumcu/doc/v850/r01us0037ej0100_v850e2.pdf
static int replace(int argc, const char *argv[], char *newstr) {
int i, j, k;
struct {
int narg;
char *op;
char *str;
} ops[] = {
{ 0, "ei", "enable-interrupts" },
{ 0, "di", "disable-interrupts" },
{ 0, "reti", "ret" },
{ 2, "ld.hu", "2 = 1" },
{ 1, "zxb", "1 = O" },
{ 1, "zxh", "1 = O" },
{ 1, "zxw", "1 = O" },
{ 2, "set1", "2 |= (I << 2)" },
{ 2, "clr1", "2 &= ~(I << 2)" },
{ 2, "sld.w", "2 = (word) 1" },
{ 2, "sld.h", "2 = (half) 1" },
{ 2, "sld.b", "2 = (byte) 1" },
{ 2, "ld.bu", "2 = 1" },
{ 2, "ld.w", "2 = (word) 1" },
{ 2, "ld.h", "2 = (half) 1" },
{ 2, "ld.b", "2 = (byte) 1" },
{ 2, "st.h", "2 = (half) 1" },
{ 2, "st.w", "2 = (word) 1" },
{ 2, "st.b", "2 = (byte) 1" },
{ 2, "sst.w", "2 = (word) 1" },
{ 2, "sst.h", "2 = (half) 1" },
{ 2, "sst.b", "2 = (byte) 1" },
{ 2, "stsr", "2 = 1" },
{ 2, "ldsr", "2 = 1" },
{ 2, "and", "3 = 2 & 1" },
{ 3, "andi", "3 = 2 & 1" },
{ 2, "add", "2 += 1" },
{ 3, "addi", "3 = 2 + 1" },
{ 2, "sub", "2 -= 1" },
{ 2, "divh", "2 /= 1" },
{ 3, "divh", "3 = 2 / 1" },
{ 2, "mulh", "2 *= 1" },
{ 3, "mul", "3 = 2 * 1" },
{ 3, "mulf.s", "3 = 2 * 1" },
{ 2, "shl", "2 <<= 1" },
{ 2, "shr", "2 >>= 1" },
{ 2, "xor", "2 ^= 1" },
{ 3, "xori", "3 = 1 ^ 2" },
{ 2, "tst", "2 == 1" },
{ 2, "tst1", "2 == 1" },
{ 1, "jr", "jmp 1" },
{ 2, "cmp", "2 == 1" },
{ 4, "cmov", "4 == 1 ? 2 : 3" },
{ 2, "mov", "2 = 1" },
{ 3, "movhi", "3 = (1 << XX) + 2" },
{ 3, "movea", "3 = 1 & 2" },
{ 3, "ori", "3 = 1 | 2" },
{ 2, "jarl", "call 1 # 2" },
{ 0, NULL }
};
if (!newstr) {
return false;
#include "parse_common.c"
static RzList *v850_tokenize(const char *assembly, size_t length);
static const RzPseudoGrammar v850_lexicon[] = {
RZ_PSEUDO_DEFINE_GRAMMAR("add", "2 += 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("addi", "3 = 2 + 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("and", "3 = 2 & 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("andi", "3 = 2 & 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("clr1", "2 &= ~(#1 << 2)"),
RZ_PSEUDO_DEFINE_GRAMMAR("cmov", "4 == 1 ? 2 : 3"),
RZ_PSEUDO_DEFINE_GRAMMAR("cmp", "2 == 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("di", "disable-interrupts"),
RZ_PSEUDO_DEFINE_GRAMMAR("divh", "2 /= 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("divh", "3 = 2 / 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("ei", "enable-interrupts"),
RZ_PSEUDO_DEFINE_GRAMMAR("jarl", "call 1 # 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("jmp", "goto 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("jr", "goto 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("ld.b", "3 = (byte) *(2 + 1)"),
RZ_PSEUDO_DEFINE_GRAMMAR("ld.bu", "3 = (unsigned byte) *(2 + 1)"),
RZ_PSEUDO_DEFINE_GRAMMAR("ld.h", "3 = (Zhalf) *(2 + 1)"),
RZ_PSEUDO_DEFINE_GRAMMAR("ld.hu", "3 = (unsigned half) *(2 + 1)"),
RZ_PSEUDO_DEFINE_GRAMMAR("ld.w", "3 = (word) *(2 + 1)"),
RZ_PSEUDO_DEFINE_GRAMMAR("ldsr", "2 = 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("mov", "2 = 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("movea", "3 = 1 & 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("movhi", "3 = (1 << XX) + 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("mul", "3 = 2 * 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("mulf.s", "3 = 2 * 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("mulh", "2 *= 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("not", "2 = ~1"),
RZ_PSEUDO_DEFINE_GRAMMAR("or", "3 = 2 | 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("ori", "3 = 2 | 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("reti", "return"),
RZ_PSEUDO_DEFINE_GRAMMAR("set1", "2 |= (#1 << 2)"),
RZ_PSEUDO_DEFINE_GRAMMAR("shl", "2 <<= 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("shr", "2 >>= 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("sld.b", "2 = (byte) 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("sld.h", "2 = (half) 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("sld.w", "2 = (word) 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("sst.b", "2 = (byte) 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("sst.h", "2 = (half) 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("sst.w", "2 = (word) 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("st.b", "*(3 + 2) = (byte) 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("st.h", "*(3 + 2) = (half) 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("st.w", "*(3 + 2) = (word) 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("stsr", "2 = 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("sub", "2 -= 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("tst", "2 == 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("tst1", "2 == 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("xor", "2 ^= 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("xori", "3 = 1 ^ 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("zxb", "1 = 0"),
RZ_PSEUDO_DEFINE_GRAMMAR("zxh", "1 = 0"),
RZ_PSEUDO_DEFINE_GRAMMAR("zxw", "1 = 0"),
};
static const RzPseudoReplace v850_replace[] = {
RZ_PSEUDO_DEFINE_REPLACE(" + 0)", ")", 0),
RZ_PSEUDO_DEFINE_REPLACE("+ -", "- ", 1),
RZ_PSEUDO_DEFINE_REPLACE(",", "", 1),
};
static const RzPseudoConfig v850_config = RZ_PSEUDO_DEFINE_CONFIG_NO_DIRECT(v850_lexicon, v850_replace, 4, v850_tokenize);
static const char *v850_short_op[] = {
"and",
"or",
};
RzList *v850_tokenize(const char *assembly, size_t length) {
size_t i, p;
char *buf = NULL;
bool insert_zero = false;
RzList *tokens = NULL;
buf = rz_str_ndup(assembly, length);
if (!buf) {
return NULL;
}
for (i = 0; ops[i].op; i++) {
if (ops[i].narg) {
if (argc - 1 != ops[i].narg) {
continue;
for (i = 0, p = 0; p < length; ++i, ++p) {
if (buf[p] == ',') {
p++;
} else if (buf[p] == '[') {
buf[p] = ' ';
if (!IS_HEXCHAR(buf[p - 1])) {
p++;
insert_zero = true;
}
} else if (buf[p] == ']') {
buf[p] = ' ';
if (buf[p + 1] == ',') {
p++;
}
}
if (!strcmp(ops[i].op, argv[0])) {
for (j = k = 0; ops[i].str[j]; j++, k++) {
if (IS_DIGIT(ops[i].str[j])) {
int index = ops[i].str[j] - '0';
if (index >= 0 && index < argc) {
const char *w = argv[index];
if (!RZ_STR_ISEMPTY(w)) {
rz_str_cpy(newstr + k, w);
k += strlen(w) - 1;
}
}
} else if (ops[i].str[j] == 'X') {
newstr[k] = '1';
k++;
j++;
newstr[k] = '6';
} else if (ops[i].str[j] == 'I') {
newstr[k] = '1';
} else if (ops[i].str[j] == 'O') {
newstr[k] = '0';
} else {
newstr[k] = ops[i].str[j];
}
}
newstr[k] = '\0';
if (argc == 4 && argv[2][0] == '[') {
strcat(newstr + k, "+");
strcat(newstr + k + 3, argv[2]);
}
return true;
if (p > i) {
buf[i] = buf[p];
}
}
buf[i] = 0;
/* TODO: this is slow */
newstr[0] = '\0';
for (i = 0; i < argc; i++) {
strcat(newstr, argv[i]);
strcat(newstr, (i == 0 || i == argc - 1) ? " " : ",");
}
rz_str_replace_in(newstr, strlen(newstr), "+= -", "-= ", true);
rz_str_replace_in(newstr, strlen(newstr), " + -", " - ", true);
// strcpy (newstr, a);
return false;
}
static char *reorder(char *buf) {
char *arr = strstr(buf, "-0x");
if (!arr) {
arr = strstr(buf, "0x");
}
if (!arr) {
return buf;
}
char *par = strchr(arr + 2, '[');
if (par) {
char arg[32], reg[32];
char *end = strchr(par + 1, ']');
if (end) {
rz_str_ncpy(reg, par + 1, end - par);
rz_str_ncpy(arg, arr, par - arr + 1);
sprintf(buf, "%s[%s]", reg, arg);
}
}
return buf;
}
static void guard_braces(char *buf) {
bool braces = false;
char *p = buf;
for (; *p; p++) {
switch (*p) {
case '{':
braces = true;
break;
case '}':
braces = false;
break;
case ',':
if (braces) {
*p = ' ';
}
break;
}
}
}
static int parse(RzParse *p, const char *data, char *str) {
if (!strncmp(data, "|| ", 3)) {
data += 3;
}
if (RZ_STR_ISEMPTY(data)) {
*str = 0;
return false;
}
char *buf = strdup(data);
guard_braces(buf);
RzListIter *iter;
char *sp = strchr(buf, ' ');
size_t nw = 1;
const char *wa[5] = { 0 };
wa[0] = buf;
RzList *list = NULL;
if (sp) {
*sp++ = 0;
list = rz_str_split_list(sp, ",", 0);
char *w;
rz_list_foreach (list, iter, w) {
wa[nw] = reorder(w);
nw++;
if (nw == 5) {
break;
}
}
}
replace(nw, wa, str);
tokens = rz_str_split_duplist(buf, " ", true);
free(buf);
rz_list_free(list);
if (!tokens) {
return NULL;
}
return true;
buf = rz_list_first(tokens);
for (i = 0; i < RZ_ARRAY_SIZE(v850_short_op); ++i) {
if (!strcmp(buf, v850_short_op[i])) {
rz_list_insert(tokens, 1, strdup("0"));
break;
}
}
if (insert_zero) {
rz_list_insert(tokens, rz_list_length(tokens) - 1, strdup("0"));
}
return tokens;
}
static bool parse(RzParse *parse, const char *assembly, RzStrBuf *sb) {
return rz_pseudo_convert(&v850_config, assembly, sb);
}
RzParsePlugin rz_parse_plugin_v850_pseudo = {

View file

@ -166,8 +166,9 @@ static int replace(int argc, char *argv[], char *newstr) {
return false;
}
static int parse(RzParse *p, const char *data, char *str) {
static bool parse(RzParse *p, const char *data, RzStrBuf *sb) {
char w0[256], w1[256], w2[256], w3[256];
char str[1024] = { 0 };
int i;
size_t len = strlen(data);
int sz = 32;
@ -285,6 +286,7 @@ static int parse(RzParse *p, const char *data, char *str) {
replace(nw, wa, str);
}
free(buf);
rz_strbuf_set(sb, str);
return true;
}

View file

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2015 julien (jvoisin) voisin <julien.voisin@dustri.org>
// SPDX-FileCopyrightText: 2021 deroad <wargio@libero.it>
// SPDX-License-Identifier: LGPL-3.0-only
#include <stdio.h>
@ -11,68 +11,145 @@
#include <rz_analysis.h>
#include <rz_parse.h>
static int replace(int argc, const char *argv[], char *newstr) {
int i, j, k;
struct {
char *op;
char *str;
} ops[] = {
{ "adc", "1 = 1 + 2" },
{ "add", "1 = 1 + 2" },
{ "and", "1 = 1 & 2" },
{ "cpl", "1 = ~1" },
{ "ex", "swap(1, 2)" },
{ "in", "1 = [2]" },
{ "jp", "goto [1]" },
{ "jp", "goto 1" },
{ "jr", "goto +1" },
{ "ld", "1 = 2" },
{ "ldd", "1 = 2--" },
{ "neg", "1 = -1" },
{ "nop", "" },
{ "or", "1 = 1 | 2" },
{ "pop", "pop 1" },
{ "push", "push 1" },
{ "rr", "1 = 1 << 2" },
{ "sbc", "1 = 1 - 2" },
{ "sla", "1 = 1 << 2" },
{ "sra", "1 = 1 >> 2" },
{ "srl", "1 = 1 >> 2" },
{ "sub", "1 = 1 - 2" },
{ "xor", "1 = 1 ^ 2" },
{ NULL }
};
#include "parse_common.c"
for (i = 0; ops[i].op != NULL; i++) {
if (!strcmp(ops[i].op, argv[0])) {
if (newstr != NULL) {
for (j = k = 0; ops[i].str[j] != '\0'; j++, k++) {
if (ops[i].str[j] >= '1' && ops[i].str[j] <= '9') {
const char *w = argv[ops[i].str[j] - '0'];
if (w != NULL) {
strcpy(newstr + k, w);
k += strlen(w) - 1;
}
} else {
newstr[k] = ops[i].str[j];
}
}
newstr[k] = '\0';
static RzList *z80_tokenize(const char *assembly, size_t length);
// https://wikiti.brandonw.net/index.php?title=Z80_Instruction_Set
static const RzPseudoGrammar z80_lexicon[] = {
RZ_PSEUDO_DEFINE_GRAMMAR("adc", "1 += 2 + cf"),
RZ_PSEUDO_DEFINE_GRAMMAR("add", "1 += 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("and", "1 &= 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("bit", "tmp = 2 & (#1 << 1)"),
RZ_PSEUDO_DEFINE_GRAMMAR("call", "call 1"),
// RZ_PSEUDO_DEFINE_GRAMMAR("ccf", "1 = 1 ? 2"),
// RZ_PSEUDO_DEFINE_GRAMMAR("cp", "1 = 1 ? 2"),
// RZ_PSEUDO_DEFINE_GRAMMAR("cpd", "1 = 1 ? 2"),
// RZ_PSEUDO_DEFINE_GRAMMAR("cpdr", "1 = 1 ? 2"),
// RZ_PSEUDO_DEFINE_GRAMMAR("cpi", "1 = 1 ? 2"),
// RZ_PSEUDO_DEFINE_GRAMMAR("cpir", "1 = 1 ? 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("cpl", "1 = ~1"),
// RZ_PSEUDO_DEFINE_GRAMMAR("daa", "1 = 1 ? 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("dec", "1--"),
// RZ_PSEUDO_DEFINE_GRAMMAR("di", "1 = 1 ? 2"),
// RZ_PSEUDO_DEFINE_GRAMMAR("djnz", "1 = 1 ? 2"),
// RZ_PSEUDO_DEFINE_GRAMMAR("ei", "1 = 1 ? 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("ex", "swap(1, 2)"),
// RZ_PSEUDO_DEFINE_GRAMMAR("exx", "1 = 1 ? 2"),
// RZ_PSEUDO_DEFINE_GRAMMAR("halt", "1 = 1 ? 2"),
// RZ_PSEUDO_DEFINE_GRAMMAR("im", "1 = 1 ? 2"),
// RZ_PSEUDO_DEFINE_GRAMMAR("in", "1 = 1 ? 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("in", "1 = [2]"),
RZ_PSEUDO_DEFINE_GRAMMAR("inc", "1++"),
// RZ_PSEUDO_DEFINE_GRAMMAR("ind", "1 = 1 ? 2"),
// RZ_PSEUDO_DEFINE_GRAMMAR("indr", "1 = 1 ? 2"),
// RZ_PSEUDO_DEFINE_GRAMMAR("ini", "1 = 1 ? 2"),
// RZ_PSEUDO_DEFINE_GRAMMAR("inir", "1 = 1 ? 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("jp", "goto 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("jp", "goto [1]"),
RZ_PSEUDO_DEFINE_GRAMMAR("jr", "goto +1"),
RZ_PSEUDO_DEFINE_GRAMMAR("ld", "1 = 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("ldd", "1 = 2--"),
// RZ_PSEUDO_DEFINE_GRAMMAR("lddr", "1 = 1 ? 2"),
// RZ_PSEUDO_DEFINE_GRAMMAR("ldi", "1 = 1 ? 2"),
// RZ_PSEUDO_DEFINE_GRAMMAR("ldir", "1 = 1 ? 2"),
// RZ_PSEUDO_DEFINE_GRAMMAR("mulub", "1 = 1 ? 2"),
// RZ_PSEUDO_DEFINE_GRAMMAR("muluw", "1 = 1 ? 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("neg", "1 = -1"),
RZ_PSEUDO_DEFINE_GRAMMAR("nop", ""),
RZ_PSEUDO_DEFINE_GRAMMAR("or", "1 |= 2"),
// RZ_PSEUDO_DEFINE_GRAMMAR("otdr", "1 = 1 ? 2"),
// RZ_PSEUDO_DEFINE_GRAMMAR("otir", "1 = 1 ? 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("out", "1 = 2"),
// RZ_PSEUDO_DEFINE_GRAMMAR("outd", "1 = 1 ? 2"),
// RZ_PSEUDO_DEFINE_GRAMMAR("outi", "1 = 1 ? 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("pop", "pop 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("push", "push 1"),
// RZ_PSEUDO_DEFINE_GRAMMAR("res", "1 = 1 ? 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("ret", "return"),
RZ_PSEUDO_DEFINE_GRAMMAR("reti", "return"),
RZ_PSEUDO_DEFINE_GRAMMAR("retn", "return"),
// RZ_PSEUDO_DEFINE_GRAMMAR("rl", "1 = 1 ? 2"),
// RZ_PSEUDO_DEFINE_GRAMMAR("rla", "1 = 1 ? 2"),
// RZ_PSEUDO_DEFINE_GRAMMAR("rlc", "1 = 1 ? 2"),
// RZ_PSEUDO_DEFINE_GRAMMAR("rlca", "1 = 1 ? 2"),
// RZ_PSEUDO_DEFINE_GRAMMAR("rld", "1 = 1 ? 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("rr", "1 <<= 2"),
// RZ_PSEUDO_DEFINE_GRAMMAR("rra", "1 = 1 ? 2"),
// RZ_PSEUDO_DEFINE_GRAMMAR("rrc", "1 = 1 ? 2"),
// RZ_PSEUDO_DEFINE_GRAMMAR("rrca", "1 = 1 ? 2"),
// RZ_PSEUDO_DEFINE_GRAMMAR("rrd", "1 = 1 ? 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("rst", "call 1"),
RZ_PSEUDO_DEFINE_GRAMMAR("sbc", "1 -= 2"),
// RZ_PSEUDO_DEFINE_GRAMMAR("scf", "1 = 1 ? 2"),
// RZ_PSEUDO_DEFINE_GRAMMAR("set", "1 = 1 ? 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("sla", "1 <<= 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("sra", "1 >>= 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("srl", "1 >>= 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("sub", "1 -= 2"),
RZ_PSEUDO_DEFINE_GRAMMAR("xor", "1 ^= 2"),
};
static const RzPseudoConfig z80_config = RZ_PSEUDO_DEFINE_CONFIG_ONLY_LEXICON(z80_lexicon, 3, z80_tokenize);
RzList *z80_tokenize(const char *assembly, size_t length) {
size_t i, p;
char *buf = NULL;
const char *comma_replace = NULL;
bool keep = false;
RzList *tokens = NULL;
buf = rz_str_ndup(assembly, length);
if (!buf) {
return NULL;
}
for (i = 0, p = 0; p < length; ++i, ++p) {
if (buf[p] == ',') {
if (!keep) {
p++;
} else if (buf[p + 1] == ' ') {
buf[i] = buf[p];
p++;
continue;
}
return true;
} else if (buf[p] == '(') {
keep = true;
comma_replace = ", ";
} else if (buf[p] == ')') {
keep = false;
}
if (p > i) {
buf[i] = buf[p];
}
}
buf[i] = 0;
tokens = rz_str_split_duplist(buf, " ", true);
free(buf);
if (!tokens) {
return NULL;
}
if (!strcmp((char *)rz_list_first(tokens), "call") && rz_list_length(tokens) == 3) {
void *arg1 = rz_list_get_n(tokens, 1);
void *arg2 = rz_list_get_n(tokens, 2);
rz_list_set_n(tokens, 1, arg2);
rz_list_set_n(tokens, 2, arg1);
}
if (comma_replace) {
RzListIter *it;
rz_list_foreach (tokens, it, buf) {
it->data = rz_str_replace(buf, ",", comma_replace, 1);
}
}
/* TODO: this is slow */
if (newstr != NULL) {
newstr[0] = '\0';
for (i = 0; i < argc; i++) {
strcat(newstr, argv[i]);
strcat(newstr, (i == 0 || i == argc - 1) ? " " : ", ");
}
}
return tokens;
}
return false;
static bool parse(RzParse *parse, const char *assembly, RzStrBuf *sb) {
return rz_pseudo_convert(&z80_config, assembly, sb);
}
RzParsePlugin rz_parse_plugin_z80_pseudo = {
@ -80,7 +157,7 @@ RzParsePlugin rz_parse_plugin_z80_pseudo = {
.desc = "z80 pseudo syntax",
.init = NULL,
.fini = NULL,
.replace = replace,
.parse = parse,
};
#ifndef RZ_PLUGIN_INCORE

View file

@ -63,6 +63,7 @@ RZ_API bool rz_parse_use(RzParse *p, const char *name) {
return true;
}
}
p->cur = NULL;
return false;
}
@ -98,13 +99,29 @@ RZ_API bool rz_parse_assemble(RzParse *p, char *data, char *str) {
return ret;
}
// data is input disasm, str is output pseudo
// TODO: refactooring, this should return char * instead
RZ_API bool rz_parse_parse(RzParse *p, const char *data, char *str) {
rz_return_val_if_fail(p && data && str, false);
return (p && data && *data && p->cur && p->cur->parse)
? p->cur->parse(p, data, str)
: false;
/**
* \brief Converts the assembly line into pseudocode
*
* Converts the assembly line into pseudocode
* */
RZ_API char *rz_parse_pseudocode(RzParse *p, const char *assembly) {
rz_return_val_if_fail(p, NULL);
if (RZ_STR_ISEMPTY(assembly)) {
return NULL;
}
RzStrBuf *sb = rz_strbuf_new("");
if (!sb) {
return NULL;
}
rz_strbuf_reserve(sb, 128);
if (!p->cur || !p->cur->parse || !p->cur->parse(p, assembly, sb)) {
rz_strbuf_free(sb);
return NULL;
}
return rz_strbuf_drain(sb);
}
RZ_API char *rz_parse_immtrim(char *opstr) {

View file

@ -939,7 +939,7 @@ address: 0x568
opcode: push {r3, lr}
esilcost: 16
disasm: push {r3, lr}
pseudo: push (r3, lr)
pseudo: push (r3, lr)
mnemonic: push
mask: ffffffff
prefix: 0

View file

@ -93,7 +93,7 @@ address: 0x100007f10
opcode: irg x8, sp, x8
esilcost: 0
disasm: irg x8, sp, x8
pseudo: irg x8,sp,x8
pseudo: asm("irg x8, sp, x8")
mnemonic: irg
mask: ffffffff
prefix: 0
@ -110,7 +110,7 @@ address: 0x100007f14
opcode: addg x9, x8, 0x20, 0x0
esilcost: 0
disasm: addg x9, x8, 0x20, 0x0
pseudo: addg x9,x8,0x20, 0x0
pseudo: asm("addg x9, x8, 0x20, 0x0")
mnemonic: addg
mask: ffffffff
prefix: 0
@ -141,7 +141,7 @@ address: 0x0
opcode: addg x12, x8, 0x0, 0x2
esilcost: 0
disasm: addg x12, x8, 0x0, 0x2
pseudo: addg x12,x8,0x0, 0x2
pseudo: asm("addg x12, x8, 0x0, 0x2")
mnemonic: addg
mask: ffffffff
prefix: 0
@ -158,7 +158,7 @@ address: 0x4
opcode: addg x9, x8, 0x20, 0x0
esilcost: 0
disasm: addg x9, x8, 0x20, 0x0
pseudo: addg x9,x8,0x20, 0x0
pseudo: asm("addg x9, x8, 0x20, 0x0")
mnemonic: addg
mask: ffffffff
prefix: 0
@ -175,7 +175,7 @@ address: 0x8
opcode: irg x8, sp, x8
esilcost: 0
disasm: irg x8, sp, x8
pseudo: irg x8,sp,x8
pseudo: asm("irg x8, sp, x8")
mnemonic: irg
mask: ffffffff
prefix: 0

View file

@ -25,3 +25,20 @@ EXPECT=<<EOF
entry0 0x26e [CALL] invoke-direct {v0}, LHello.<init>()V ; 0x0
EOF
RUN
NAME=Dalvik HelloWorld func xref
FILE=bins/dex/HelloWorld.dex
CMDS=<<EOF
aa
e asm.pseudo=true
pif @ sym.LHello.method._init___V
EOF
EXPECT=<<EOF
call Object.<init>V (v1)
v0 = (wide) 0x1
v1[(I)] = v0
v0 = (wide) 0x2
v0 = (I) LHello.localVar2
return
EOF
RUN

View file

@ -5,3 +5,80 @@ EXPECT=<<EOF
0x000009f2
EOF
RUN
NAME=M68k pseudo
FILE=bins/smd/LiquidSpaceDodgerV3.bin
CMDS=<<EOF
e asm.pseudo=true
af
pif
EOF
EXPECT=<<EOF
d0 = 0xa10001
d0 &= 0xf
if (==) goto 0x216
0xa14000 = 0x53454741
sr = 0x2700
0xa11100 = 0x100
0xa11200 = 0x100
a7 = sym.SSP
call 0x9f2
call 0xa72
call 0x9ca
call 0xa86
a5 = 0x2338
d4 = 0xbff
(a3) = 0x40000000
call 0x9ea
a5 = 0x1db6
(a3) = 0xc0000000
d4 = 0x2f
call 0x9ea
call 0xae0
a5 = 0x3b38
(a3) = 0x5c000000
d4 = 0x11ff
call 0x9ea
a5 = 0x5f38
d4 = section.header
(a3) = 0x58000000
call 0x9ea
a5 = 0x6138
d4 = 0x24d0
(a3) = 0x40000001
call 0x9ea
a5 = 0xaad8
d4 = 0x7ff
(a3) = 0x40000003
call 0xa9a
a5 = 0x2276
d4 = 0
(a3) = 0x60000002
call 0x9a2
0xff0022 = 0x1
call 0x1c94
0xff000e = 0x110
0xff002e = 0xee
0xff001e = 0x5
0xff0030 = 0xff
0xff0022 = 0x1
0xff0020 = 0x1
call 0xa2e
sr = 0x2300
0xff0014 = 0x0
call 0x490
call 0x3d0
call 0xdd6
call 0x36c
call 0x4d4
call 0x6d0
call 0x1b8c
0xff000a = 0xff
0x1 += 0xff0014
call 0x472
0xff000a == 0
if (!=) goto 0x33e
goto 0x312
EOF
RUN

View file

@ -161,7 +161,7 @@ pd 1
EOF
EXPECT=<<EOF
0x80100000 0000beaf sw fp, (sp)
0x80100000 0000beaf [sp + 0] = fp
0x80100000 0000beaf word [sp] = fp
EOF
RUN

View file

@ -36,6 +36,31 @@ nop
EOF
RUN
NAME=SuperH pseudo
FILE=bins/sh/loop.elf
CMDS=<<EOF
s sym._called_in_loop
e asm.pseudo=true
af
pif
EOF
EXPECT=<<EOF
@-r15 = r14
r14 = r15
r1 = @(0x14 + pc)
r1 = @r1
r2 = r1
r2 += 0x01
r1 = @(0xc + pc)
@r1 = r2
r15 = r14
r14 = @r15+
return
EOF
RUN
NAME=SuperH af
FILE=--
CMDS=<<EOF

View file

@ -11,7 +11,6 @@ EXPECT=<<EOF
{
"opcode": "la %r4, 8(%r15)",
"disasm": "la %r4, 8(%r15)",
"pseudo": "la %r4,8(%r15) ",
"description": "Load Address",
"mnemonic": "la",
"mask": "ffffffff",

View file

@ -11,7 +11,7 @@ EXPECT=<<EOF
{
"opcode": "b 0x20de8",
"disasm": "b 0x20de8",
"pseudo": "b 0x20de8 ",
"pseudo": "goto 0x20de8",
"mnemonic": "b",
"mask": "ff000000",
"jump": 134632,
@ -54,150 +54,150 @@ EOF
EXPECT=<<EOF
a17 = (half) 0x13cf
a28 = 0 ext a0 .. 0
b23:b22 = (word)*a1++[12]
b23:b22 = (word) *a1++[12]
a4 = 2 ext a0 .. 0x1a
a26 = 0x4988
a4 = 0x12 .bitset a20 .. 0x12
a13:a12 = (word)*-a18[a12]
a13:a12 = (word) *-a18[a12]
a17 = a31 avg a0
b22 = (word)*+b14[0x3da6]
a4 = (half)*+b15[0x49]
b22 = (word) *+b14[0x3da6]
a4 = (half) *+b15[0x49]
a25 = 8 ext a21 .. 0x10
a = a8 ~ a21
a26 = a8 ~ a21
a16 = a23 * a25
b17 = (half)*+b15[0xd15]
a16 = (half)*+b14[0x0]
*+b15[0x6c41] = (word)b19
b8 = (byte)*+b14[0x660f]
b12 = (byte)*+b14[0x2e0f]
b12 = (byte)*+b14[0x2e0f]
b17 = (half) *+b15[0xd15]
a16 = (half) *+b14[0x0]
*+b15[0x6c41] = (word) b19
b8 = (byte) *+b14[0x660f]
b12 = (byte) *+b14[0x2e0f]
b12 = (byte) *+b14[0x2e0f]
a0 = 0x1a .bitset a20 .. 0x1a
a22 = 9 .bitclear a17 .. 9
a10 = 0xe ext a12 .. 0
a7 = 0 ext a27 .. 0x10
a22 = 0x18 ext a29 .. 8
*+b14[0x488b] = (byte)b0
*+b14[0x488b] = (byte) b0
a14 = 1 ext a17 .. 4
a17 = (byte)*a3--[10]
a17 = (byte) *a3--[10]
b16 = (half) -0x2c00
b4 = (half)*+b15[0x488d]
b4 = (half) *+b15[0x488d]
a6 = (half) 1
a30 = 0 ext a0 .. 0
a23:a22 = 1 + a20:a19
a20 = (half)*-a23[a18]
a20 = (half) *-a23[a18]
b8 += 0x2463
*-a1[14] = (word)a17
*-a1[14] = (word) a17
a16 = 0x1a ext a0 .. 0x11
a23 = 0x1c ext a16 .. 0x10
*+b14[0x5b1] = (word)b26
*+b14[0x5b1] = (word) b26
a4 = 2 ext a0 .. 0x13
b19 = 0x1a .bitset b30 .. 0x1a
b9 = (half)*+b15[0xb05]
b9 = (half) *+b15[0xb05]
a10 = 0x10 ext a8 .. 0
a26 = (byte)*-a5[15]
a26 = (byte) *-a5[15]
b0 = 2 .bitset b0 .. 2
a30 = (word)*+b15[0x4883]
*+b15[0x47c1] = (word)b17
*+b15[0x7fff] = (word)b31
a2 = (half)*+b15[0x0]
a30 = (word) *+b15[0x4883]
*+b15[0x47c1] = (word) b17
*+b15[0x7fff] = (word) b31
a2 = (half) *+b15[0x0]
a16 = a17 * a29
b0 = b18 + 4
b16 = 2 == b22
b30 = (word)*-a16[0]
b30 = (word) *-a16[0]
a0 = 0x10 ext a15 .. 0
a2 = 8 ext a29 .. 0x18
a23:a22 = (word)*-a1[12]
a23:a22 = (word) *-a1[12]
b4 = 2 .bitset b0 .. 2
*+b14[0xd05] = (half)b17
*+b14[0xd05] = (half) b17
a14 = 8 ext a0 .. 0
b11 = (half)*+b14[0x4948]
a9 = (half)*+b15[0x4848]
b11 = (half) *+b14[0x4948]
a9 = (half) *+b15[0x4848]
a17 = a24 * a29
a1:a0 = a0 * a0
a26 = a0 * a1
b30 = (word)*-a7[24]
b30 = (word) *-a7[24]
a17 = 0x18 ext a2 .. 5
a10 = 0x10 ext a8 .. 0
a19 = (half)*+b15[0x5048]
a19 = (half) *+b15[0x5048]
a15 = a24 * a29
a17 = 0xf ext a2 .. 0x11
*a13--(a9) = (half)b27:b26
*a13--(a9) = (half) b27:b26
b2 = 5 * b0
a0 = 0 ext a0 .. 0
a22 = (half)*-a0[a2]
a22 = (half) *-a0[a2]
a30 = 6 ext a17 .. 2
a4 = (half) 0x6381
a24 = a0 * a1
b13 = (byte)*+b14[0x1066]
*a16++[10] = (half)a0
b13 = (byte) *+b14[0x1066]
*a16++[10] = (half) a0
b19 += 0x13fc
a17 = 0xe ext a2 .. 0x15
a26 = 0xc * a3
b0 = b2 * b0
a24 = (byte)*+b14[0x508b]
a24 = (byte) *+b14[0x508b]
a28 = 0x10 ext a8 .. 0
a18 = 1 ext a31 .. 4
a17 = (byte)*a2--[9]
a17 = (byte) *a2--[9]
a26 = a1 * a17
a28 = 1 ext a17 .. 4
a17 = (byte)*a3--[10]
a30 = (half)*a3++[24]
a17 = (byte)*a3--[11]
*+b14[0x488d] = (word)a16
b8 = (half)*-a8[a2]
a17 = (byte) *a3--[10]
a30 = (half) *a3++[24]
a17 = (byte) *a3--[11]
*+b14[0x488d] = (word) a16
b8 = (half) *-a8[a2]
a18 = a1 * a17
*+b15[0x63fc] = (word)b16
*+a19[a4] = (half)a31:a30
*-a1[14] = (word)a27
a3 = (byte)*+b14[0x4039]
b26 = (half)*+b14[0x2200]
*+b15[0x63fc] = (word) b16
*+a19[a4] = (half) a31:a30
*-a1[14] = (word) a27
a3 = (byte) *+b14[0x4039]
b26 = (half) *+b14[0x2200]
b11 = b2 * b16
*+b14[0x505b] = (half)a8
b2 = (half)*+b14[0x5ec3]
*+b14[0x505b] = (half) a8
b2 = (half) *+b14[0x5ec3]
a8 = 0 ext a0 .. 0
a14 = 0x10 ext a0 .. 0
a19 = 0xa .bitset a26 .. 0xa
*+b15[0x31c0] = (byte)b4
*+b15[0x31c0] = (byte) b4
a0 = (half) 1
a14 = a24 * a0
a17 += 0x788
*+b14[0x405b] = (half)a3
b3:b2 = (word)*+a23[22]
b0 = (half)*+b14[0x662e]
*+b14[0x405b] = (half) a3
b3:b2 = (word) *+a23[22]
b0 = (half) *+b14[0x662e]
b0 = 0x1a .bitset b20 .. 0x1a
a14 = 2 .bitset a4 .. 2
b22 = b4 - b18
a17 = 0x1b ext a2 .. 0x1f
a3 = a18 * a20
a31 = (half)*+a5[14]
a31 = (half) *+a5[14]
a3 = 9 .bitclear a18 .. 9
a20 = 0 ext a0 .. 0
b18 = max(b24, b16)
*a3++[a24] = (half)a7:a6
*-a0[2] = (word)b0
*-a21[18] = (word)a2
a2 = (half)*+b15[0x544c]
*a3++[a24] = (half) a7:a6
*-a0[2] = (word) b0
*-a21[18] = (word) a2
a2 = (half) *+b15[0x544c]
a26 = a15 * a8
a0 = 0xa ext a21 .. 0x13
a19 = a2 * a31
a0 = 0 ext a0 .. 0
*+b15[0xf48] = (byte)b22
a27 = (half)*+b15[0x4ccc]
a25 = (half)*+b15[0x4ccc]
*+b15[0xf48] = (byte) b22
a27 = (half) *+b15[0x4ccc]
a25 = (half) *+b15[0x4ccc]
a19 = 0xf ext a2 .. 6
a17 = 0xe ext a2 .. 8
a7 = 0x10 ext a27 .. 1
a15 = a25 - a26
a20 = (half)*+b15[0x348]
a20 = (half) *+b15[0x348]
a16 = 0xe ext a0 .. 0
a19 = (half)*-a16[a10]
a2 = (half)*a3++[29]
a19 = (half) *-a16[a10]
a2 = (half) *a3++[29]
a26 = 2 .bitset a0 .. 2
a12 = 0xe ext a29 .. 0x18
a12 = 5 .bitclear a5 .. 5
a0 = (half)*+b14[0x0]
a16 = (half)*+b14[0x29f0]
*+b14[0x7f48] = (byte)a19
a0 = (half) *+b14[0x0]
a16 = (half) *+b14[0x29f0]
*+b14[0x7f48] = (byte) a19
a0 = 0 ext a0 .. 0
b30 = b30 * b17
a16 = 2 .bitset a2 .. 2

View file

@ -360,34 +360,39 @@ RUN
NAME=v850 random pseudo
FILE=bins/elf/ld-2.27.so
BROKEN=1
CMDS=<<EOF
sd +128
e asm.arch=v850
e asm.parser=v850.pseudo
e asm.pseudo=true
b 64
pi~=
EOF
EXPECT=<<EOF
r8[0x1047] = (byte) r24
*(r8 + 0x1047) = (byte) r24
r0 = r0
r0 = r0
r9 = ~r31
r1 = ~r4
r0 = r0
r0 = r0
r0 == 0xa
r17 = 0x388 | r13
r13 = 8
r13 = 0
r9 = r2
r17 = r13 | 0x388
r0 = r0
r9 = r0
r11 = (0x8548 << 16) + r26
r2 == -0xc
r9 = r3
r9 = r3
r3 = ~r4
r11 = (0x8548 << XX) + r26
r6 = r18 | 0
r9 = r16
r10 = r3 | 0
r9 = r8
r2 /= r19
r9 /= r19
r0 = r20
r9 = r16
r22 = r5 | 0
r4 == -1
r17 = r8 & 0
r0 = ~r2
r25 = (byte) *(r8805 + 0x5)
r9 = r0
EOF
RUN

View file

@ -16,7 +16,7 @@ int main(int argc, char **argv) {
printf("%s\n", str);
printf("\n----\n\n");
rz_parse_use(p, "att2intel");
rz_parse_parse(p, "movl $3, %eax", str); //, sizeof (str));
rz_parse_pseudocode(p, "movl $3, %eax", str); //, sizeof (str));
//rz_parse_filter (p, NULL, "movl $3, %eax", str, sizeof (str));
printf("%s\n", str);
} else {
@ -29,7 +29,7 @@ int main(int argc, char **argv) {
break;
buf[strlen(buf) - 1] = 0;
if (*buf) {
rz_parse_parse(p, buf, str); //, sizeof (str));
rz_parse_pseudocode(p, buf, str); //, sizeof (str));
printf("%s\n", str);
}
}