Improve the pseudo-decompilation output for !x86 and inlined gotos ##print

This commit is contained in:
pancake 2023-03-13 12:41:58 +01:00 committed by pancake
parent f4539cc9e1
commit 90601b14f7
4 changed files with 105 additions and 26 deletions

View File

@ -319,3 +319,4 @@ It's dangerous to go alone, take this.
"If you gotta burn it all to the ground; Then let it burn"
Watch until the end!
Don't forget to subscribe!
Ah shit, here we go again.

View File

@ -125,7 +125,7 @@ R_API char *r_anal_cc_get(RAnal *anal, const char *name) {
int i;
// get cc by name and print the expr
if (r_str_cmp (sdb_const_get (DB, name, 0), "cc", -1)) {
R_LOG_ERROR ("This is not a valid calling convention name (%s)", name);
R_LOG_ERROR ("Invalid calling convention name (%s)", name);
return NULL;
}
r_strf_var (ccret, 128, "cc.%s.ret", name);

View File

@ -1,4 +1,4 @@
/* radare - LGPL - Copyright 2015-2021 - pancake */
/* radare - LGPL - Copyright 2015-2023 - pancake */
#include <r_core.h>
#define TYPE_NONE 0
@ -162,6 +162,15 @@ static void find_and_change(char* in, int len) {
}
}
#if 0
static int cmpnbbs(const void *_a, const void *_b) {
const RAnalBlock *a = _a, *b = _b;
ut64 as = a->addr;
ut64 bs = b->addr;
return (as> bs)? -1: (as< bs)? 1: 0;
}
#endif
static RCoreHelpMessage help_msg_pdc = {
"Usage: pdc[oj]", "", "experimental, unreliable and hacky pseudo-decompiler",
"pdc", "", "pseudo decompile function in current offset",
@ -268,6 +277,8 @@ R_API int r_core_pseudo_code(RCore *core, const char *input) {
char indentstr[1024] = {0};
int indent = 0;
int nindent = 1;
// XXX sorting basic blocks is nice for the reader, but introduces conceptual problems
// when the entrypoint is not starting at the lowest address. // r_list_sort (fcn->bbs, cmpnbbs);
int n_bb = r_list_length (fcn->bbs);
PJ *pj = NULL;
if (show_json) {
@ -275,6 +286,12 @@ R_API int r_core_pseudo_code(RCore *core, const char *input) {
pj_o (pj);
pj_ka (pj, "annotations");
}
const char *cc = fcn->cc ? fcn->cc: "default";
const char *cc_a0 = r_anal_cc_arg (core->anal, cc, 0);
const char *cc_a1 = r_anal_cc_arg (core->anal, cc, 1);
const char *a0 = cc_a0? cc_a0: r_reg_get_name_by_type (core->anal->reg, "A0");
const char *a1 = cc_a1? cc_a1: r_reg_get_name_by_type (core->anal->reg, "A1");
const char *r0 = r_reg_get_name_by_type (core->anal->reg, "R0");
if (show_c_headers) {
// NEWLINE (fcn->addr, indent);
PRINTF ("// global registers\n");
@ -284,23 +301,21 @@ R_API int r_core_pseudo_code(RCore *core, const char *input) {
PRINTF ("unsigned int *dword = &stack;\n");
PRINTF ("unsigned short *word = &stack;\n");
PRINTF ("unsigned char *byte = &stack;\n");
PRINTF ("int eax, ebx, ecx, edx;\n");
PRINTF ("int %s, %s;\n", a0, a1);
PRINTF ("// This function contains %d basic blocks and its %d long.",
n_bb, (int)r_anal_function_realsize (fcn));
NEWLINE (fcn->addr, indent);
const char *S0 = "esp";
PRINTF ("static inline void push (int reg) {%s-=%d;stack[%s]=reg;}\n", S0, (int)sizeof (int), S0);
PRINTF ("static inline int pop() {int r = stack[%s]; %s+=%d; return r;}\n", S0, S0, (int)sizeof (int));
PRINTF ("static inline void push (int reg) {%s -= %d; stack[%s] = reg; }\n", S0, (int)sizeof (int), S0);
PRINTF ("static inline int pop() {int r = stack[%s]; %s += %d; return r; }\n", S0, S0, (int)sizeof (int));
PRINTF ("\n");
}
PRINTF ("int %s (int esi, int edx) {", fcn->name);
PRINTF ("int %s (int %s, int %s) {", fcn->name, a0, a1);
indent++;
RList *visited = r_list_newf (NULL);
ut64 addr = fcn->addr;
do {
if (!bb) {
break;
}
while (bb) {
r_list_append (visited, bb);
r_cons_push ();
bool html = r_config_get_b (core->config, "scr.html");
@ -309,22 +324,22 @@ R_API int r_core_pseudo_code(RCore *core, const char *input) {
r_cons_pop ();
r_config_set_b (core->config, "scr.html", html);
indent = 2;
SET_INDENT (indent);
if (!code) {
R_LOG_ERROR ("No code here");
break;
}
// SET_INDENT (indent);
// PRINTF ("\n---\n");
code = r_str_replace (code, ";", "//", true);
const char *R0 = "eax";
size_t len = strlen (code);
code[len - 1] = 0; // chop last newline
find_and_change (code, len);
if (!sdb_const_get (db, K_MARK (bb->addr), 0)) {
bool mustprint = !queuegoto || queuegoto != bb->addr;
if (mustprint) {
if (queuegoto) {
NEWLINE (bb->addr, indent);
PRINTF ("goto loc_0x%"PFMT64x, queuegoto);
if (queuegoto && queuegoto != UT64_MAX) {
// NEWLINE (bb->addr, indent);
// PRINTF ("3goto loc_0x%"PFMT64x, queuegoto);
queuegoto = 0LL;
}
NEWLINE (bb->addr, indent - 1);
@ -365,6 +380,26 @@ R_API int r_core_pseudo_code(RCore *core, const char *input) {
sdb_num_set (db, K_MARK (bb->addr), 1, 0);
}
}
bool closed = false;
if (bb->fail == UT64_MAX) {
if (bb->jump != UT64_MAX) {
#if 1
if (bb->jump != UT64_MAX) { // nbb->addr) {
NEWLINE (bb->addr, indent);
PRINTF ("goto loc_0x%"PFMT64x, bb->jump);
}
#endif
} else {
closed = true;
#if 0
NEWLINE (bb->addr, indent);
PRINTF ("return; ");
#endif
}
} else {
NEWLINE (bb->addr, indent);
PRINTF ("goto loc_0x%"PFMT64x, bb->fail);
}
if (sdb_const_get (db, K_INDENT (bb->addr), 0)) {
// already analyzed, go pop and continue
// XXX check if can't pop
@ -376,9 +411,15 @@ R_API int r_core_pseudo_code(RCore *core, const char *input) {
for (i = indent; i != nindent && i > 0; i--) {
NEWLINE (bb->addr, i);
PRINTF ("}");
closed = true;
}
if (closed) {
NEWLINE (bb->addr, indent);
PRINTF ("return %s;", r0);
} else if (bb->fail != UT64_MAX) {
NEWLINE (bb->addr, indent);
PRINTF ("goto loc_0x%"PFMT64x";", bb->fail);
}
NEWLINE (bb->addr, indent);
PRINTF ("return %s;", R0);
RAnalBlock *nbb = r_anal_bb_from_offset (core->anal, bb->fail);
if (r_list_contains (visited, nbb)) {
nbb = r_anal_bb_from_offset (core->anal, bb->jump);
@ -400,9 +441,6 @@ R_API int r_core_pseudo_code(RCore *core, const char *input) {
} else {
PRINTF (" // } %s (?);", blocktype);
}
} else {
NEWLINE (addr, indent);
PRINTF (" // }");
}
if (addr != bb->addr) {
queuegoto = addr;
@ -461,7 +499,7 @@ R_API int r_core_pseudo_code(RCore *core, const char *input) {
sdb_array_push_num (db, "indent", fail, 0);
sdb_num_set (db, K_INDENT (fail), indent, 0);
sdb_num_set (db, K_ELSE (fail), 1, 0);
NEWLINE (bb->addr, indent);
// NEWLINE (bb->addr, indent);
}
} else {
sdb_array_push_num (db, "indent", jump, 0);
@ -478,7 +516,7 @@ R_API int r_core_pseudo_code(RCore *core, const char *input) {
indent++;
}
}
} else {
} else if (!closed) {
ut64 addr = sdb_array_pop_num (db, "indent", NULL);
if (addr == UT64_MAX) {
NEWLINE (bb->addr, indent);
@ -494,6 +532,7 @@ R_API int r_core_pseudo_code(RCore *core, const char *input) {
PRINTF ("}");
}
}
PRINTF ("goto loc_0x%"PFMT64x";", bb->fail);
if (nindent != indent) {
NEWLINE (bb->addr, indent);
PRINTF ("} else {");
@ -501,8 +540,7 @@ R_API int r_core_pseudo_code(RCore *core, const char *input) {
indent = nindent;
}
}
//n_bb --;
} while (n_bb > 0);
}
RListIter *iter;
r_list_foreach (fcn->bbs, iter, bb) {
if (!r_list_contains (visited, bb)) {
@ -522,6 +560,7 @@ R_API int r_core_pseudo_code(RCore *core, const char *input) {
pj_end (pj);
} else {
r_strbuf_append (codestr, s);
// PRINTF ("goto loc_0x%"PFMT64x";", bb->fail);
}
if (codelen > 0) {
NEWLINE (bb->addr, 1);

View File

@ -101,10 +101,11 @@ EXPECT=<<EOF
| 0x0040206e ff15b8304000 call dword [MessageBoxA] ; 0x4030b8 ; int MessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType)
| 0x00402074 6a00 push 0
\ 0x00402076 ff1584304000 call dword [ExitProcess] ; 0x403084 ; VOID ExitProcess(UINT uExitCode)
int entry0 (int esi, int edx) {
int entry0 (int stack, int stack) {
loc_0x40200f:
si = 3
fcn.00402000 ()
goto loc_0x402018
do {
loc_0x402018:
push (0)
@ -121,7 +122,9 @@ int entry0 (int esi, int edx) {
si-
var = si - 0
if (var > 0) goto loc_0x402018 // unlikely
goto loc_0x402042
// } while (?);
goto loc_0x402042
}
return eax;
loc_0x402042:
@ -147,7 +150,43 @@ int entry0 (int esi, int edx) {
push (0)
dword [ExitProcess] () // 0x403084 // reloc.kernel32.dll_ExitProcess
// VOID ExitProcess(NULL)
break;
}
return eax;
}
EOF
RUN
NAME=pdc @ main ls-m1
FILE=bins/mach0/ls-m1
ARGS=-a arm -b64
CMDS=<<EOF
s 0x100003a54
af
pdc
EOF
EXPECT=<<EOF
int sym.func.100003a54 (int x0, int x1) {
loc_0x100003a54:
x8 = [x0 + 0x60] // 0xda // 218 // arg1
x8 = [x8 + 0x60] // 0xe2 // 226
x9 = [x1 + 0x60] // 0xdb // 219 // arg2
x9 = [x9 + 0x60] // 0xe3 // 227
if (x8 == x9)
goto ifle 0x100003a74 // likely
goto loc_0x100003a6c
loc_0x100003a74:
b.ge 0x100003a80 // likely
goto loc_0x100003a78
loc_0x100003a80:
x8 = x1 + 0x68 // arg2
x1 = x0 + 0x68 // arg1
x0 = x8
goto sym.imp.strcoll
// int strcoll("", "")
// } else {
}
return x0;
}
EOF