notaz.gp2x.de
/
ia32rtools.git
/ commitdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
| commitdiff |
tree
raw
|
patch
|
inline
| side by side (parent:
a3668fe
)
translate: yet more work on sp tracking
author
notaz
<notasas@gmail.com>
Sun, 22 Mar 2015 21:00:18 +0000
(23:00 +0200)
committer
notaz
<notasas@gmail.com>
Sun, 22 Mar 2015 21:00:18 +0000
(23:00 +0200)
tools/translate.c
patch
|
blob
|
blame
|
history
diff --git
a/tools/translate.c
b/tools/translate.c
index
1fa3d95
..
503468d
100644
(file)
--- a/
tools/translate.c
+++ b/
tools/translate.c
@@
-243,8
+243,8
@@
static int g_quiet_pp;
static int g_header_mode;
#define ferr(op_, fmt, ...) do { \
static int g_header_mode;
#define ferr(op_, fmt, ...) do { \
- printf("%s:%d: error
: [%s] '%s': " fmt, asmfn, (op_)->asmln, g_func
, \
- dump_op(op_), ##__VA_ARGS__); \
+ printf("%s:%d: error
%u: [%s] '%s': " fmt, asmfn, (op_)->asmln
, \
+
__LINE__, g_func,
dump_op(op_), ##__VA_ARGS__); \
fcloseall(); \
exit(1); \
} while (0)
fcloseall(); \
exit(1); \
} while (0)
@@
-2607,10
+2607,16
@@
static void patch_esp_adjust(struct parsed_op *po, int adj)
static int scan_for_esp_adjust(int i, int opcnt,
int adj_expect, int *adj, int *is_multipath, int do_update)
{
static int scan_for_esp_adjust(int i, int opcnt,
int adj_expect, int *adj, int *is_multipath, int do_update)
{
+ int adj_expect_unknown = 0;
struct parsed_op *po;
int first_pop = -1;
struct parsed_op *po;
int first_pop = -1;
+ int adj_best = 0;
*adj = *is_multipath = 0;
*adj = *is_multipath = 0;
+ if (adj_expect < 0) {
+ adj_expect_unknown = 1;
+ adj_expect = 32 * 4; // enough?
+ }
for (; i < opcnt && *adj < adj_expect; i++) {
if (g_labels[i] != NULL)
for (; i < opcnt && *adj < adj_expect; i++) {
if (g_labels[i] != NULL)
@@
-2654,6
+2660,8
@@
static int scan_for_esp_adjust(int i, int opcnt,
}
*adj += lmod_bytes(po, po->operand[0].lmod);
}
*adj += lmod_bytes(po, po->operand[0].lmod);
+ if (*adj > adj_best)
+ adj_best = *adj;
}
else if (po->flags & (OPF_JMP|OPF_TAIL)) {
if (po->op == OP_JMP && po->btj == NULL) {
}
else if (po->flags & (OPF_JMP|OPF_TAIL)) {
if (po->op == OP_JMP && po->btj == NULL) {
@@
-2668,12
+2676,15
@@
static int scan_for_esp_adjust(int i, int opcnt,
break;
if (po->pp != NULL && po->pp->is_stdcall)
break;
break;
if (po->pp != NULL && po->pp->is_stdcall)
break;
+ if (adj_expect_unknown && first_pop >= 0)
+ break;
// assume it's another cdecl call
}
}
if (first_pop >= 0) {
// assume it's another cdecl call
}
}
if (first_pop >= 0) {
- // probably 'pop ecx' was used..
+ // probably only 'pop ecx' was used
+ *adj = adj_best;
return first_pop;
}
return first_pop;
}
@@
-3103,22
+3114,25
@@
static void scan_prologue_epilogue(int opcnt)
ferr(&ops[j], "'pop ebp' expected\n");
if (g_stack_fsz != 0) {
ferr(&ops[j], "'pop ebp' expected\n");
if (g_stack_fsz != 0) {
- if (ops[j - 1].op == OP_MOV
+ if (ops[j].op == OP_LEAVE)
+ j--;
+ else if (ops[j].op == OP_POP
+ && ops[j - 1].op == OP_MOV
&& IS(opr_name(&ops[j - 1], 0), "esp")
&& IS(opr_name(&ops[j - 1], 1), "ebp"))
{
ops[j - 1].flags |= OPF_RMD | OPF_DONE;
&& IS(opr_name(&ops[j - 1], 0), "esp")
&& IS(opr_name(&ops[j - 1], 1), "ebp"))
{
ops[j - 1].flags |= OPF_RMD | OPF_DONE;
+ j -= 2;
}
}
- else if (ops[j].op != OP_LEAVE
- && !(g_ida_func_attr & IDAFA_NORETURN))
+ else if (!(g_ida_func_attr & IDAFA_NORETURN))
{
{
- ferr(&ops[j
- 1
], "esp restore expected\n");
+ ferr(&ops[j], "esp restore expected\n");
}
}
- if (ecx_push &&
ops[j - 2
].op == OP_POP
- && IS(opr_name(&ops[j
- 2
], 0), "ecx"))
+ if (ecx_push &&
j >= 0 && ops[j
].op == OP_POP
+ && IS(opr_name(&ops[j], 0), "ecx"))
{
{
- ferr(&ops[j
- 2
], "unexpected ecx pop\n");
+ ferr(&ops[j], "unexpected ecx pop\n");
}
}
}
}
@@
-3456,7
+3470,7
@@
static struct parsed_proto *process_call_early(int i, int opcnt,
struct parsed_proto *pp;
int multipath = 0;
int adj = 0;
struct parsed_proto *pp;
int multipath = 0;
int adj = 0;
- int ret;
+ int
j,
ret;
pp = po->pp;
if (pp == NULL || pp->is_vararg || pp->argc_reg != 0)
pp = po->pp;
if (pp == NULL || pp->is_vararg || pp->argc_reg != 0)
@@
-3473,8
+3487,15
@@
static struct parsed_proto *process_call_early(int i, int opcnt,
return NULL;
if (multipath)
return NULL;
return NULL;
if (multipath)
return NULL;
- if (ops[ret].op == OP_POP && adj != 4)
- return NULL;
+ if (ops[ret].op == OP_POP) {
+ for (j = 1; j < adj / 4; j++) {
+ if (ops[ret + j].op != OP_POP
+ || ops[ret + j].operand[0].reg != xCX)
+ {
+ return NULL;
+ }
+ }
+ }
}
*adj_i = ret;
}
*adj_i = ret;
@@
-3541,7
+3562,7
@@
static struct parsed_proto *process_call(int i, int opcnt)
pp->is_fptr = 1;
ret = scan_for_esp_adjust(i + 1, opcnt,
pp->is_fptr = 1;
ret = scan_for_esp_adjust(i + 1, opcnt,
-
32*4
, &adj, &multipath, 0);
+
-1
, &adj, &multipath, 0);
if (ret < 0 || adj < 0) {
if (!g_allow_regfunc)
ferr(po, "non-__cdecl indirect call unhandled yet\n");
if (ret < 0 || adj < 0) {
if (!g_allow_regfunc)
ferr(po, "non-__cdecl indirect call unhandled yet\n");
@@
-3562,9
+3583,11
@@
static struct parsed_proto *process_call(int i, int opcnt)
// look for and make use of esp adjust
multipath = 0;
ret = -1;
// look for and make use of esp adjust
multipath = 0;
ret = -1;
- if (!pp->is_stdcall && pp->argc_stack > 0)
+ if (!pp->is_stdcall && pp->argc_stack > 0) {
+ int adj_expect = pp->is_vararg ? -1 : pp->argc_stack * 4;
ret = scan_for_esp_adjust(i + 1, opcnt,
ret = scan_for_esp_adjust(i + 1, opcnt,
- pp->argc_stack * 4, &adj, &multipath, 0);
+ adj_expect, &adj, &multipath, 0);
+ }
if (ret >= 0) {
if (pp->is_vararg) {
if (adj / 4 < pp->argc_stack) {
if (ret >= 0) {
if (pp->is_vararg) {
if (adj / 4 < pp->argc_stack) {
@@
-4164,11
+4187,12
@@
static void gen_func(FILE *fout, FILE *fhdr, const char *funcn, int opcnt)
if (pp != NULL) {
if (j >= 0) {
// commit esp adjust
if (pp != NULL) {
if (j >= 0) {
// commit esp adjust
- ops[j].flags |= OPF_RMD;
if (ops[j].op != OP_POP)
patch_esp_adjust(&ops[j], pp->argc_stack * 4);
if (ops[j].op != OP_POP)
patch_esp_adjust(&ops[j], pp->argc_stack * 4);
- else
- ops[j].flags |= OPF_DONE;
+ else {
+ for (l = 0; l < pp->argc_stack; l++)
+ ops[j + l].flags |= OPF_DONE | OPF_RMD;
+ }
}
if (strstr(pp->ret_type.name, "int64"))
}
if (strstr(pp->ret_type.name, "int64"))
@@
-5985,7
+6009,8
@@
static void gen_hdr(const char *funcn, int opcnt)
int regmask_dep;
int max_bp_offset = 0;
int has_ret;
int regmask_dep;
int max_bp_offset = 0;
int has_ret;
- int i, j, ret;
+ int i, j, l;
+ int ret;
pp_c = proto_parse(g_fhdr, funcn, 1);
if (pp_c != NULL)
pp_c = proto_parse(g_fhdr, funcn, 1);
if (pp_c != NULL)
@@
-6067,11
+6092,12
@@
static void gen_hdr(const char *funcn, int opcnt)
if (pp != NULL) {
if (j >= 0) {
// commit esp adjust
if (pp != NULL) {
if (j >= 0) {
// commit esp adjust
- ops[j].flags |= OPF_RMD;
if (ops[j].op != OP_POP)
patch_esp_adjust(&ops[j], pp->argc_stack * 4);
if (ops[j].op != OP_POP)
patch_esp_adjust(&ops[j], pp->argc_stack * 4);
- else
- ops[j].flags |= OPF_DONE;
+ else {
+ for (l = 0; l < pp->argc_stack; l++)
+ ops[j + l].flags |= OPF_DONE | OPF_RMD;
+ }
}
po->flags |= OPF_DONE;
}
po->flags |= OPF_DONE;