From 8e867df7c12d7ce03b452e83fd9a8778f1a604c1 Mon Sep 17 00:00:00 2001 From: pancake Date: Tue, 11 Jun 2024 22:54:03 +0200 Subject: [PATCH] Initial support for stm8 pseudo ##decompilation --- dist/plugins-cfg/plugins.def.cfg | 1 + libr/arch/p/arm/pseudo.c | 12 +- libr/arch/p/stm8.mk | 1 + libr/arch/p/stm8/gmtdisas/asm.c | 48 +++--- libr/arch/p/stm8/pseudo.c | 274 +++++++++++++++++++++++++++++++ libr/asm/p/Makefile | 2 +- libr/asm/p/stm8_pseudo.mk | 18 ++ libr/core/canal.c | 2 +- libr/core/pseudo.c | 22 ++- libr/include/r_parse.h | 1 + 10 files changed, 343 insertions(+), 38 deletions(-) create mode 100644 libr/arch/p/stm8/pseudo.c create mode 100644 libr/asm/p/stm8_pseudo.mk diff --git a/dist/plugins-cfg/plugins.def.cfg b/dist/plugins-cfg/plugins.def.cfg index 43aff02c5d47f..829ab87b4f933 100644 --- a/dist/plugins-cfg/plugins.def.cfg +++ b/dist/plugins-cfg/plugins.def.cfg @@ -275,6 +275,7 @@ lang.v lang.vala lang.zig parse.6502_pseudo +parse.stm8_pseudo parse.arm_pseudo parse.att2intel parse.avr_pseudo diff --git a/libr/arch/p/arm/pseudo.c b/libr/arch/p/arm/pseudo.c index 665d3a34d4215..e4450564dabb9 100644 --- a/libr/arch/p/arm/pseudo.c +++ b/libr/arch/p/arm/pseudo.c @@ -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 } }, diff --git a/libr/arch/p/stm8.mk b/libr/arch/p/stm8.mk index a4e0d1d33fff1..945a2382e75ab 100644 --- a/libr/arch/p/stm8.mk +++ b/libr/arch/p/stm8.mk @@ -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) diff --git a/libr/arch/p/stm8/gmtdisas/asm.c b/libr/arch/p/stm8/gmtdisas/asm.c index 9cb836cdc8f9c..a0163c9faa92b 100644 --- a/libr/arch/p/stm8/gmtdisas/asm.c +++ b/libr/arch/p/stm8/gmtdisas/asm.c @@ -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: @@ -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]); @@ -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]); @@ -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 @@ -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]); @@ -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]); diff --git a/libr/arch/p/stm8/pseudo.c b/libr/arch/p/stm8/pseudo.c new file mode 100644 index 0000000000000..4c0352fab15e2 --- /dev/null +++ b/libr/arch/p/stm8/pseudo.c @@ -0,0 +1,274 @@ +/* radare - LGPL - Copyright 2024 - pancake */ + +#include +#include +#include +#include +#include + +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; +} + +static char *subs_var_string(RParse *p, RAnalVarField *var, char *tstr, const char *oldstr, const char *reg, int delta) { + char *newstr = p->localvar_only + ? r_str_newf ("%s", var->name) + : r_str_newf ("%s %c %s", reg, delta > 0 ? '+' : '-', var->name); + if (IS_UPPER (*tstr)) { + char *space = strrchr (newstr, ' '); + if (space) { + *space = 0; + r_str_case (newstr, true); + *space = ' '; + } + } + char *ret = r_str_replace (tstr, oldstr, newstr, 1); + free (newstr); + return ret; +} + +static bool subvar(RParse *p, RAnalFunction *f, ut64 addr, int oplen, char *data, char *str, int len) { + r_return_val_if_fail (p, false); + RList *spargs = NULL; + RList *bpargs = NULL; + RListIter *iter; + RAnal *anal = p->analb.anal; + char *oldstr; + bool newstack = anal->opt.var_newstack; + char *tstr = strdup (data); + if (!tstr) { + return false; + } + + if (p->subrel) { + char *rip; + if (p->pseudo) { + rip = (char *)r_str_casestr (tstr, "[pc +"); + if (!rip) { + rip = (char *)r_str_casestr (tstr, "[pc -"); + } + } else { + rip = (char *)r_str_casestr (tstr, "[pc, "); + } + + if (rip && !strchr (rip + 4, ',')) { + rip += 4; + char *tstr_new, *ripend = strchr (rip, ']'); + const char *neg = strchr (rip, '-'); + ut64 off = (oplen == 2 || strstr (tstr, ".w") || strstr (tstr, ".W")) ? 4 : 8; + ut64 repl_num = (addr + off) & ~3; + if (!ripend) { + ripend = "]"; + } + if (neg) { + repl_num -= r_num_get (NULL, neg + 1); + } else { + repl_num += r_num_get (NULL, rip); + } + rip -= 3; + *rip = 0; + tstr_new = r_str_newf ("%s0x%08"PFMT64x"%s", tstr, repl_num, ripend); + free (tstr); + tstr = tstr_new; + } + } + if (len > strlen (tstr)) { + strcpy (str, tstr); + } else { + // TOO BIG STRING CANNOT REPLACE HERE + free (tstr); + return false; + } + free (tstr); + return true; +} + +RParsePlugin r_parse_plugin_stm8_pseudo = { + .name = "stm8.pseudo", + .desc = "STM8 pseudo syntax", + .parse = parse, +// .subvar = &subvar, +}; + +#ifndef R2_PLUGIN_INCORE +R_API RLibStruct radare_plugin = { + .type = R_LIB_TYPE_PARSE, + .data = &r_parse_plugin_stm8_pseudo, + .version = R2_VERSION +}; +#endif diff --git a/libr/asm/p/Makefile b/libr/asm/p/Makefile index 718363af616c9..0919cf88dddab 100644 --- a/libr/asm/p/Makefile +++ b/libr/asm/p/Makefile @@ -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) diff --git a/libr/asm/p/stm8_pseudo.mk b/libr/asm/p/stm8_pseudo.mk new file mode 100644 index 0000000000000..6a7e5eebc5505 --- /dev/null +++ b/libr/asm/p/stm8_pseudo.mk @@ -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 diff --git a/libr/core/canal.c b/libr/core/canal.c index 75c524288daed..8faff15abd5c1 100644 --- a/libr/core/canal.c +++ b/libr/core/canal.c @@ -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"; } diff --git a/libr/core/pseudo.c b/libr/core/pseudo.c index aab699ab05f3e..865f23f1d8d2e 100644 --- a/libr/core/pseudo.c +++ b/libr/core/pseudo.c @@ -222,7 +222,7 @@ R_API int r_core_pseudo_code(RCore *core, const char *input) { if (show_addr) r_strbuf_appendf (out, " 0x%08"PFMT64x" | %s", a, indentstr);\ else r_strbuf_append (out, indentstr); }\ } -#define PRINTGOTO(y, x) if (x != UT64_MAX && y != x) { NEWLINE (x, indent); PRINTF (" goto loc_0x%"PFMT64x, x); } +#define PRINTGOTO(y, x) if (x != UT64_MAX && y != x) { NEWLINE (x, indent); PRINTF (" goto loc_0x%08"PFMT64x, x); } const char *cmdPdc = r_config_get (core->config, "cmd.pdc"); if (cmdPdc && *cmdPdc && !strstr (cmdPdc, "pdc")) { if (strstr (cmdPdc, "!*") || strstr (cmdPdc, "#!")) { @@ -356,7 +356,7 @@ R_API int r_core_pseudo_code(RCore *core, const char *input) { queuegoto = 0LL; } NEWLINE (bb->addr, indent - 1); - PRINTF ("loc_0x%"PFMT64x":", bb->addr); + PRINTF ("loc_0x%08"PFMT64x":", bb->addr); // foreach lines RList *lines = r_str_split_list (code, "\n", 0); RListIter *iter; @@ -410,7 +410,7 @@ R_API int r_core_pseudo_code(RCore *core, const char *input) { } } else { NEWLINE (bb->addr, indent); - PRINTF ("goto loc_0x%"PFMT64x";", bb->fail); + PRINTF ("goto loc_0x%08"PFMT64x";", bb->fail); } if (sdb_const_get (db, K_INDENT (bb->addr), 0)) { // already analyzed, go pop and continue @@ -430,10 +430,14 @@ R_API int r_core_pseudo_code(RCore *core, const char *input) { #endif if (closed) { NEWLINE (bb->addr, indent); - PRINTF ("return %s;", r0); + if (r0) { + PRINTF ("return %s;", r0); + } else { + PRINTF ("return;"); + } } else if (bb->fail != UT64_MAX) { NEWLINE (bb->addr, indent); - PRINTF ("goto loc_0x%"PFMT64x";", bb->fail); + PRINTF ("goto loc_0x%08"PFMT64x";", bb->fail); } RAnalBlock *nbb = r_anal_bb_from_offset (core->anal, bb->fail); if (r_list_contains (visited, nbb)) { @@ -548,7 +552,7 @@ R_API int r_core_pseudo_code(RCore *core, const char *input) { PRINTF ("}"); } } - PRINTF ("goto loc_0x%"PFMT64x";", bb->fail); + PRINTF ("goto loc_0x%08"PFMT64x";", bb->fail); #if 0 if (nindent != indent) { NEWLINE (bb->addr, indent); @@ -642,7 +646,11 @@ R_API int r_core_pseudo_code(RCore *core, const char *input) { } if (bb->jump == UT64_MAX) { NEWLINE (bb->addr, indent); - PRINTF ("return %s;", r0); + if (r0) { + PRINTF ("return %s;", r0); + } else { + PRINTF ("return;"); + } } else { PRINTGOTO (nbbaddr, bb->jump); } diff --git a/libr/include/r_parse.h b/libr/include/r_parse.h index 10396291de23e..56d5466af7654 100644 --- a/libr/include/r_parse.h +++ b/libr/include/r_parse.h @@ -94,6 +94,7 @@ extern RParsePlugin r_parse_plugin_z80_pseudo; extern RParsePlugin r_parse_plugin_tms320_pseudo; extern RParsePlugin r_parse_plugin_v850_pseudo; extern RParsePlugin r_parse_plugin_bpf_pseudo; +extern RParsePlugin r_parse_plugin_stm8_pseudo; extern RParsePlugin r_parse_plugin_evm_pseudo; #endif