Implement asm.pseudo for RISC-V (#17777)
This commit is contained in:
parent
4b2cc40ead
commit
39296b87f8
10 changed files with 270 additions and 1 deletions
|
|
@ -132,6 +132,7 @@ extern RzParsePlugin rz_parse_plugin_mips_pseudo;
|
|||
extern RzParsePlugin rz_parse_plugin_ppc_pseudo;
|
||||
extern RzParsePlugin rz_parse_plugin_sh_pseudo;
|
||||
extern RzParsePlugin rz_parse_plugin_wasm_pseudo;
|
||||
extern RzParsePlugin rz_parse_plugin_riscv_pseudo;
|
||||
extern RzParsePlugin rz_parse_plugin_x86_pseudo;
|
||||
extern RzParsePlugin rz_parse_plugin_z80_pseudo;
|
||||
extern RzParsePlugin rz_parse_plugin_tms320_pseudo;
|
||||
|
|
|
|||
|
|
@ -306,6 +306,7 @@ parse_plugins = [
|
|||
'mips_pseudo',
|
||||
'ppc_pseudo',
|
||||
'sh_pseudo',
|
||||
'riscv_pseudo',
|
||||
'v850_pseudo',
|
||||
'wasm_pseudo',
|
||||
'x86_pseudo',
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ rz_parse_sources = [
|
|||
'p/parse_v850_pseudo.c',
|
||||
'p/parse_wasm_pseudo.c',
|
||||
'p/parse_x86_pseudo.c',
|
||||
'p/parse_riscv_pseudo.c',
|
||||
'p/parse_z80_pseudo.c'
|
||||
]
|
||||
|
||||
|
|
|
|||
230
librz/parse/p/parse_riscv_pseudo.c
Normal file
230
librz/parse/p/parse_riscv_pseudo.c
Normal file
|
|
@ -0,0 +1,230 @@
|
|||
// SPDX-License-Identifier: LGPL-3.0-only
|
||||
|
||||
#include <rz_lib.h>
|
||||
#include <rz_flag.h>
|
||||
#include <rz_anal.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, "add", "# = # + #", { 1, 2, 3 } },
|
||||
{ 0, "addi", "# = # + #", { 1, 2, 3 } },
|
||||
{ 0, "and", "# = # & #", { 1, 2, 3 } },
|
||||
{ 0, "andi", "# = # & #", { 1, 2, 3 } },
|
||||
{ 0, "beq", "if (# == #) goto #", { 1, 2, 3 } },
|
||||
{ 0, "bleu", "if (unsigned)# <= # goto #", { 1, 2, 3 } },
|
||||
{ 0, "bltu", "if (unsigned)# < # goto #", { 1, 2, 3 } },
|
||||
{ 0, "blt", "if (# < #) goto #", { 1, 2, 3 } },
|
||||
{ 0, "beqz", "if (# == 0) goto #", { 1, 2 } },
|
||||
{ 0, "bne", "if (# != #) goto #", { 1, 2, 3 } },
|
||||
{ 0, "bnez", "if (# != 0) goto #", { 1, 2 } },
|
||||
{ 0, "bgez", "if (# >= 0) goto #", { 1, 2 } },
|
||||
{ 0, "bgtz", "if (# > 0) goto #", { 1, 2 } },
|
||||
{ 0, "fld", "# = #", { 1, 2 } },
|
||||
{ 0, "j", "jmp #", { 1 } },
|
||||
{ 0, "jr", "jmp #", { 1 } },
|
||||
{ 0, "jalr", "jmp #", { 1 } },
|
||||
{ 0, "jal", "jmp #", { 1 } },
|
||||
{ 0, "ld", "# = (double)[#]", { 1, 2 } },
|
||||
{ 0, "li", "# = #", { 1, 2 } },
|
||||
{ 0, "lh", "# = [#]", { 1, 2 } },
|
||||
{ 0, "lui", "# = #", { 1, 2 } },
|
||||
{ 0, "lbu", "# = (unsigned)[#]", { 1, 2 } },
|
||||
{ 0, "lhu", "# = (unsigned)[#]", { 1, 2 } },
|
||||
{ 0, "lw", "# = [#]", { 1, 2 } },
|
||||
{ 0, "mv", "# = #", { 1, 2 } },
|
||||
{ 0, "or", "# = # | #", { 1, 2, 3 } },
|
||||
{ 0, "sd", "[#] = (double)#", { 2, 1 } },
|
||||
{ 0, "sw", "[#] = #", { 2, 1 } },
|
||||
{ 0, "sb", "[#] = #", { 2, 1 } },
|
||||
{ 0, "sh", "[#] = #", { 2, 1 } },
|
||||
{ 0, "sub", "# = # - #", { 1, 2, 3 } },
|
||||
{ 0, NULL }
|
||||
};
|
||||
if (!newstr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
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])) {
|
||||
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';
|
||||
}
|
||||
rz_str_replace_char (newstr, '{', '(');
|
||||
rz_str_replace_char (newstr, '}', ')');
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
static int parse(RzParse *p, const char *data, char *str) {
|
||||
char w0[256], w1[256], w2[256], w3[256];
|
||||
int i, len = strlen (data), n;
|
||||
char *buf, *ptr, *optr, *num;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
ptr = strchr (buf, '(');
|
||||
if (ptr) {
|
||||
*ptr = 0;
|
||||
num = (char*)rz_str_lchr (buf, ' ');
|
||||
if (!num) {
|
||||
num = (char *)rz_str_lchr (buf, ',');
|
||||
}
|
||||
if (num) {
|
||||
n = atoi (num + 1);
|
||||
*ptr = '[';
|
||||
rz_str_cpy (num + 1, ptr);
|
||||
ptr = (char*)rz_str_lchr (buf, ']');
|
||||
if (n && ptr) {
|
||||
char *rest = strdup (ptr + 1);
|
||||
size_t dist = len + 1 - (ptr - buf);
|
||||
if (n > 0) {
|
||||
snprintf (ptr, dist, "+%d]%s", n, rest);
|
||||
} else {
|
||||
snprintf (ptr, dist, "%d]%s", n, rest);
|
||||
}
|
||||
free (rest);
|
||||
}
|
||||
} else {
|
||||
*ptr = '[';
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
RzParsePlugin rz_parse_plugin_riscv_pseudo = {
|
||||
.name = "riscv.pseudo",
|
||||
.desc = "riscv pseudo syntax",
|
||||
.parse = parse,
|
||||
};
|
||||
|
||||
#ifndef RZ_PLUGIN_INCORE
|
||||
RZ_API RzLibStruct radare_plugin = {
|
||||
.type = RZ_LIB_TYPE_PARSE,
|
||||
.data = &rz_parse_plugin_riscv_pseudo,
|
||||
.version = RZ_VERSION};
|
||||
#endif
|
||||
17
librz/parse/p/riscv_pseudo.mk
Normal file
17
librz/parse/p/riscv_pseudo.mk
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
OBJ_RISCVPSEUDO+=parse_riscv_pseudo.o
|
||||
|
||||
TARGET_RISCVPSEUDO=parse_riscv_pseudo.${EXT_SO}
|
||||
ALL_TARGETS+=${TARGET_RISCVPSEUDO}
|
||||
STATIC_OBJ+=${OBJ_RISCVPSEUDO}
|
||||
LIBDEPS=-L../../util -llibrz_util
|
||||
|
||||
ifeq ($(CC),cccl)
|
||||
RISCV_CFLAGS:=${CFLAGS}
|
||||
else
|
||||
RISCV_CFLAGS:=${CFLAGS} ${LINK}
|
||||
endif
|
||||
|
||||
${TARGET_RISCVPSEUDO}: ${OBJ_RISCVPSEUDO}
|
||||
${CC} $(call libname,parse_riscv_pseudo) ${LIBDEPS} ${LDFLAGS} \
|
||||
$(LDFLAGS_SHARED) ${RISCV_CFLAGS} -o ${TARGET_RISCVPSEUDO} ${OBJ_RISCVPSEUDO}
|
||||
|
||||
|
|
@ -253,6 +253,7 @@ parse.att2intel
|
|||
parse.chip8_pseudo
|
||||
parse.dalvik_pseudo
|
||||
parse.m68k_pseudo
|
||||
parse.riscv_pseudo
|
||||
parse.mips_pseudo
|
||||
parse.ppc_pseudo
|
||||
parse.sh_pseudo
|
||||
|
|
|
|||
|
|
@ -207,6 +207,7 @@ parse.mips_pseudo
|
|||
parse.ppc_pseudo
|
||||
parse.sh_pseudo
|
||||
parse.wasm_pseudo
|
||||
parse.riscv_pseudo
|
||||
parse.x86_pseudo
|
||||
parse.z80_pseudo"
|
||||
SHARED="io.shm
|
||||
|
|
|
|||
|
|
@ -41,4 +41,20 @@ EXPECT=<<EOF
|
|||
`==< 0x00000006 f5fe bnez a3, 0x2
|
||||
0x00000008 0000 illegal
|
||||
EOF
|
||||
RUN
|
||||
|
||||
NAME=asm pseudo for riscv
|
||||
FILE=bins/elf/analysis/guess-number-riscv64
|
||||
CMDS=<<EOF
|
||||
s 0x00010178
|
||||
e asm.pseudo = 1
|
||||
pd 5
|
||||
EOF
|
||||
EXPECT=<<EOF
|
||||
0x00010178 ef00c01f jmp ra ; sym.printf
|
||||
0x0001017c 930784fe a5 = s0 - 24
|
||||
0x00010180 93850700 a1 = a5
|
||||
0x00010184 b7170200 a5 = 0x21
|
||||
0x00010188 13850751 a0 = a5 + 1296
|
||||
EOF
|
||||
RUN
|
||||
|
|
@ -13,6 +13,7 @@ dalvik.pseudo
|
|||
m68k.pseudo
|
||||
mips.pseudo
|
||||
ppc.pseudo
|
||||
riscv.pseudo
|
||||
sh.pseudo
|
||||
tms320.pseudo
|
||||
v850.pseudo
|
||||
|
|
|
|||
|
|
@ -525,7 +525,7 @@ EXPECT=<<EOF
|
|||
| :: 0x00010174 1385874f addi a0, a5, 1272 ; const char *format
|
||||
| :: 0x00010178 ef00c01f jal ra, dbg.printf
|
||||
| :: 0x0001017c 930784fe addi a5, s0, -24
|
||||
| :: 0x00010180 93850700 mv a1, var_bp_18h
|
||||
| :: 0x00010180 93850700 mv a1, a5
|
||||
| :: 0x00010184 b7170200 lui a5, 0x21
|
||||
| :: 0x00010188 13850751 addi a0, a5, 1296 ; const char *format
|
||||
| :: 0x0001018c ef00402f jal ra, dbg.scanf
|
||||
|
|
|
|||
Loading…
Reference in a new issue