Skip to content

Commit

Permalink
Initial support for stm8 pseudo ##decompilation
Browse files Browse the repository at this point in the history
  • Loading branch information
trufae authored Jun 12, 2024
1 parent 32565da commit 631223c
Show file tree
Hide file tree
Showing 13 changed files with 278 additions and 46 deletions.
1 change: 1 addition & 0 deletions dist/plugins-cfg/plugins.def.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,7 @@ lang.v
lang.vala
lang.zig
parse.6502_pseudo
parse.stm8_pseudo
parse.arm_pseudo
parse.att2intel
parse.avr_pseudo
Expand Down
12 changes: 6 additions & 6 deletions libr/arch/p/arm/pseudo.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,13 @@ static int replace(int argc, const char *argv[], char *newstr) {
{ 0, "asrs", "# = # >> #", { 1, 2, 3 } },
{ 0, "asr", "# = # >> #", { 1, 2, 3 } },
{ 0, "b", "goto #", { 1 } },
{ 0, "cbz", "if !# goto #", { 1, 2 } },
{ 0, "cbnz", "if # goto #", { 1, 2 } },
{ 0, "cbz", "if (!#) goto #", { 1, 2 } },
{ 0, "cbnz", "if (#) goto #", { 1, 2 } },
{ 0, "b.w", "goto #", { 1 } },
{ 0, "b.gt", "if (a > b) #", { 1 } },
{ 0, "b.le", "if (a <= b) #", { 1 } },
{ 0, "b.lt", "if (a < b) #", { 1 } },
{ 0, "b.ge", "if (a >= b) #", { 1 } },
{ 0, "b.gt", "if (a > b) goto #", { 1 } },
{ 0, "b.le", "if (a <= b) goto #", { 1 } },
{ 0, "b.lt", "if (a < b) goto #", { 1 } },
{ 0, "b.ge", "if (a >= b) goto #", { 1 } },
{ 0, "beq lr", "ifeq ret", {0} },
{ 0, "beq", "je #", { 1 } },
{ 0, "call", "# ()", { 1 } },
Expand Down
1 change: 1 addition & 0 deletions libr/arch/p/stm8.mk
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
OBJ_STM8=p/stm8/plugin.o
OBJ_STM8+=p/stm8/pseudo.o

STATIC_OBJ+=$(OBJ_STM8)
TARGET_STM8=arch_stm8.$(EXT_SO)
Expand Down
48 changes: 25 additions & 23 deletions libr/arch/p/stm8/gmtdisas/asm.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,13 @@ char *stm8_disasm(ut64 pc, const ut8 *data, int size, unsigned int *type, ut64 *
r_strbuf_appendf (sb, "%s", ins.text);

if (n == 1) {
for (; n < ins.size; n++)
for (; n < ins.size; n++) {
oc[n+1] = *(block->data + cnt + n);
}
} else {
for (; n < ins.size; n++)
for (; n < ins.size; n++) {
oc[n] = *(block->data + cnt + n);
}
}
switch (ins.des) {
case STM8_NONE:
Expand Down Expand Up @@ -128,10 +130,10 @@ char *stm8_disasm(ut64 pc, const ut8 *data, int size, unsigned int *type, ut64 *
r_strbuf_appendf (sb, " 0x%02x%02x", oc[2], oc[3]);
break;
case STM8_PTR_X:
r_strbuf_append (sb, " (x)");
r_strbuf_append (sb, " [x]");
break;
case STM8_PTR_Y:
r_strbuf_append (sb, " (y)");
r_strbuf_append (sb, " [y]");
break;
case SHORTMEM_2:
r_strbuf_appendf (sb, " 0x%02x", oc[2]);
Expand Down Expand Up @@ -181,25 +183,25 @@ char *stm8_disasm(ut64 pc, const ut8 *data, int size, unsigned int *type, ut64 *
*jump = add + ins.size + n;
break;
case SHORTOFF_X_2:
r_strbuf_appendf (sb, " (0x%02x, x)", oc[2]);
r_strbuf_appendf (sb, " [x + 0x%02x]", oc[2]);
break;
case SHORTOFF_Y_2:
r_strbuf_appendf (sb, " (0x%02x, y)", oc[2]);
r_strbuf_appendf (sb, " [y + 0x%02x]", oc[2]);
break;
case SHORTOFF_SP_2:
r_strbuf_appendf (sb, " (0x%02x, sp)", oc[2]);
r_strbuf_appendf (sb, " [sp + 0x%02x]", oc[2]);
break;
case LONGOFF_X_23:
r_strbuf_appendf (sb, " (0x%02x%02x, x)", oc[2], oc[3]);
r_strbuf_appendf (sb, " [x + 0x%02x%02x]", oc[2], oc[3]);
break;
case LONGOFF_Y_23:
r_strbuf_appendf (sb, " (0x%02x%02x, y)", oc[2], oc[3]);
r_strbuf_appendf (sb, " [y + 0x%02x%02x]", oc[2], oc[3]);
break;
case EXTOFF_X_234:
r_strbuf_appendf (sb, " (0x%02x%02x%02x, x)", oc[2], oc[3], oc[4]);
r_strbuf_appendf (sb, " [x + 0x%02x%02x%02x]", oc[2], oc[3], oc[4]);
break;
case EXTOFF_Y_234:
r_strbuf_appendf (sb, " (0x%02x%02x%02x, y)", oc[2], oc[3], oc[4]);
r_strbuf_appendf (sb, " [y + 0x%02x%02x%02x]", oc[2], oc[3], oc[4]);
break;
case SHORTPTR_2:
r_strbuf_appendf (sb, " [0x%02x]", oc[2]);
Expand All @@ -208,16 +210,16 @@ char *stm8_disasm(ut64 pc, const ut8 *data, int size, unsigned int *type, ut64 *
r_strbuf_appendf (sb, " [0x%02x%02x]", oc[2], oc[3]);
break;
case SHORTPTR_OFF_X_2:
r_strbuf_appendf (sb, " ([0x%02x], x)", oc[2]);
r_strbuf_appendf (sb, " x + [0x%02x]", oc[2]);
break;
case SHORTPTR_OFF_Y_2:
r_strbuf_appendf (sb, " ([0x%02x], y)", oc[2]);
r_strbuf_appendf (sb, " y + [0x%02x]", oc[2]);
break;
case LONGPTR_OFF_X_23:
r_strbuf_appendf (sb, " ([0x%02x%02x], x)", oc[2], oc[3]);
r_strbuf_appendf (sb, " x + [0x%02x%02x]", oc[2], oc[3]);
break;
case LONGPTR_OFF_Y_23:
r_strbuf_appendf (sb, " ([0x%02x%02x], y)", oc[2], oc[3]);
r_strbuf_appendf (sb, " y + [0x%02x%02x]", oc[2], oc[3]);
break;
case LONGMEM_BIT_123:
// ioreg
Expand Down Expand Up @@ -310,25 +312,25 @@ char *stm8_disasm(ut64 pc, const ut8 *data, int size, unsigned int *type, ut64 *
*jump = add + ins.size + n;
break;
case SHORTOFF_X_2:
r_strbuf_appendf (sb, ", (0x%02x, x)", oc[2]);
r_strbuf_appendf (sb, ", [x + 0x%02x]", oc[2]);
break;
case SHORTOFF_Y_2:
r_strbuf_appendf (sb, ", (0x%02x, y)", oc[2]);
r_strbuf_appendf (sb, ", [y + 0x%02x]", oc[2]);
break;
case SHORTOFF_SP_2:
r_strbuf_appendf (sb, ", (0x%02x, sp)", oc[2]);
r_strbuf_appendf (sb, ", [sp + 0x%02x]", oc[2]);
break;
case LONGOFF_X_23:
r_strbuf_appendf (sb, ", (0x%02x%02x, x)", oc[2], oc[3]);
r_strbuf_appendf (sb, ", [x + 0x%02x%02x]", oc[2], oc[3]);
break;
case LONGOFF_Y_23:
r_strbuf_appendf (sb, ", (0x%02x%02x, y)", oc[2], oc[3]);
r_strbuf_appendf (sb, ", [y + 0x%02x%02x]", oc[2], oc[3]);
break;
case EXTOFF_X_234:
r_strbuf_appendf (sb, ", (0x%02x%02x%02x, x)", oc[2], oc[3], oc[4]);
r_strbuf_appendf (sb, ", [x + 0x%02x%02x%02x]", oc[2], oc[3], oc[4]);
break;
case EXTOFF_Y_234:
r_strbuf_appendf (sb, ", (0x%02x%02x%02x, y)", oc[2], oc[3], oc[4]);
r_strbuf_appendf (sb, ", [y + 0x%02x%02x%02x]", oc[2], oc[3], oc[4]);
break;
case SHORTPTR_2:
r_strbuf_appendf (sb, ", [0x%02x]", oc[2]);
Expand All @@ -337,7 +339,7 @@ char *stm8_disasm(ut64 pc, const ut8 *data, int size, unsigned int *type, ut64 *
r_strbuf_appendf (sb, ", [0x%02x%02x]", oc[2], oc[3]);
break;
case SHORTPTR_OFF_X_2:
r_strbuf_appendf (sb, ", ([0x%02x], x)", oc[2]);
r_strbuf_appendf (sb, ", [0x%02x] + x", oc[2]);
break;
case SHORTPTR_OFF_Y_2:
r_strbuf_appendf (sb, ", ([0x%02x], y)", oc[2]);
Expand Down
200 changes: 200 additions & 0 deletions libr/arch/p/stm8/pseudo.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
/* radare - LGPL - Copyright 2024 - pancake */

#include <r_lib.h>
#include <r_util.h>
#include <r_flag.h>
#include <r_anal.h>
#include <r_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;
const char *op;
const char *str;
int args[MAXPSEUDOOPS];
} ops[] = {
// { 0, "ldw", "# = [#]", { 1, 2 } },
{ 0, "ldf", "# = #", { 1, 2 } },
{ 0, "ldw", "# = [#]", { 1, 2 } },
{ 3, "ld", "# = [# + #]", { 3, 2, 1 } },
{ 2, "ld", "# = #", { 2, 1 } },
{ 0, "dec", "# --", { 1 } },
// { 2, "dec", "# -= #", { 1, 2 } },
{ 0, "inc", "# ++", { 1 } },
{ 0, "subw", "# -= #", { 1, 2 } },
{ 0, "addw", "# += #", { 1, 2 } },
{ 0, "jrne", "if (!zero) goto #", { 1 } },
{ 0, "jra", "goto #", { 1 } },
{ 0, "clrw", "# = 0", { 1 } },
{ 0, "sllw", "# <<= 1", { 1 } },
{ 0, "slaw", "# <<= 1", { 1 } },
{ 0, "srlw", "# >>= 1", { 1 } },
{ 0, "sraw", "# >>= 1", { 1 } },
{ 0, "add", "# += #", { 1, 2 } },
{ 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';
}
// r_str_replace_char (newstr, '{', '(');
// r_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)? " " : ",");
}
return false;
}

static int parse(RParse *p, const char *data, char *str) {
char w0[256], w1[256], w2[256], w3[256], w4[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 0
buf = r_str_replace (buf, "(0", "0", true);
buf = r_str_replace (buf, "p)", "p", true);
buf = r_str_replace (buf, "x)", "x", true);
#endif
#if 0
r_str_replace_char (buf, '(', '{');
r_str_replace_char (buf, ')', '}');
#endif
if (*buf) {
*w0 = *w1 = *w2 = *w3 = *w4 = '\0';
ptr = strchr (buf, ' ');
if (!ptr) {
ptr = strchr (buf, '\t');
}
if (ptr) {
*ptr = '\0';
ptr = (char *)r_str_trim_head_ro (ptr + 1);
strncpy (w0, buf, sizeof (w0) - 1);
strncpy (w1, ptr, sizeof (w1) - 1);
optr = ptr;
if (ptr && *ptr == '[') {
ptr = strchr (ptr + 1, ']');
}
if (ptr && *ptr == '{') {
ptr = strchr (ptr + 1, '}');
}
if (!ptr) {
R_LOG_ERROR ("Unbalanced bracket");
free (buf);
return false;
}
ptr = strchr (ptr, ',');
if (ptr) {
*ptr = '\0';
ptr = (char *)r_str_trim_head_ro (ptr + 1);
strncpy (w1, optr, sizeof (w1) - 1);
strncpy (w2, ptr, sizeof (w2) - 1);
optr = ptr;
ptr = strchr (ptr, ',');
if (ptr) {
*ptr = '\0';
ptr = (char *)r_str_trim_head_ro (ptr + 1);
strncpy (w2, optr, sizeof (w2) - 1);
strncpy (w3, ptr, sizeof (w3) - 1);
optr = ptr;
ptr = strchr (ptr, ',');
if (ptr) {
*ptr = '\0';
ptr = (char *)r_str_trim_head_ro (ptr + 1);
strncpy (w3, optr, sizeof (w3) - 1);
strncpy (w4, ptr, sizeof (w4) - 1);
}
}
}
}
{
const char *wa[] = { w0, w1, w2, w3, w4 };
int nw = 0;
for (i = 0; i < 5; i++) {
if (wa[i][0]) {
nw++;
}
}
replace (nw, wa, str);
}
}
char *s = strdup (str);
if (s) {
s = r_str_replace (s, "wzr", "0", 1);
s = r_str_replace (s, " lsl ", " << ", 1);
s = r_str_replace (s, " lsr ", " >> ", 1);
s = r_str_replace (s, "+ -", "- ", 1);
s = r_str_replace (s, "- -", "+ ", 1);
strcpy (str, s);
free (s);
}
free (buf);
r_str_fixspaces (str);
return true;
}

RParsePlugin r_parse_plugin_stm8_pseudo = {
.name = "stm8.pseudo",
.desc = "STM8 pseudo syntax",
.parse = parse,
};

#ifndef R2_PLUGIN_INCORE
R_API RLibStruct radare_plugin = {
.type = R_LIB_TYPE_PARSE,
.data = &r_parse_plugin_stm8_pseudo,
.version = R2_VERSION
};
#endif
2 changes: 1 addition & 1 deletion libr/asm/p/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ ARCHS+=x86_as.mk x86_nz.mk cris_gnu.mk arc.mk
ARCHS+=ppc_as.mk x86_nasm.mk avr.mk
ARCHS+=sh.mk tms320.mk ebc.mk
ARCHS+=cr16.mk v850.mk jdh8.mk riscv.mk
ARCHS+=lm32.mk mcore.mk
ARCHS+=lm32.mk mcore.mk stm8.mk
# ARCHS+=loongarch_gnu.mk
include $(ARCHS)

Expand Down
18 changes: 18 additions & 0 deletions libr/asm/p/stm8_pseudo.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
OBJ_STM8PSEUDO+=$(LIBR)/arch/p/stm8/pseudo.o

TARGET_STM8PSEUDO=parse_stm8_pseudo.${EXT_SO}
STATIC_OBJ+=${OBJ_STM8PSEUDO}
ifeq ($(CC),cccl)
LIBDEPS=-L../../util -llibr_util
LIBDEPS+=-L../../flag -llibr_flag
else
LIBDEPS=-L../../util -lr_util
LIBDEPS+=-L../../flag -lr_flag
endif

ifeq ($(WITHPIC),1)
ALL_TARGETS+=${TARGET_STM8PSEUDO}
${TARGET_STM8PSEUDO}: ${OBJ_STM8PSEUDO}
${CC} $(call libname,parse_stm8_pseudo) ${LIBDEPS} $(LDFLAGS) \
$(LDFLAGS_SHARED) ${CFLAGS} -o ${TARGET_STM8PSEUDO} ${OBJ_STM8PSEUDO}
endif
2 changes: 1 addition & 1 deletion libr/core/canal.c
Original file line number Diff line number Diff line change
Expand Up @@ -913,7 +913,7 @@ static bool __core_anal_fcn(RCore *core, ut64 at, ut64 from, int reftype, int de
const char *cc = r_anal_cc_default (core->anal);
if (!cc) {
if (r_anal_cc_once (core->anal)) {
R_LOG_WARN ("set your favourite calling convention in `e anal.cc=?`");
R_LOG_WARN ("select the calling convention with `e anal.cc=?`");
}
cc = "reg";
}
Expand Down
Loading

0 comments on commit 631223c

Please sign in to comment.