From 9da26fa636730e43b4c36dec213f33d5885ecb81 Mon Sep 17 00:00:00 2001 From: Humberto Date: Thu, 7 May 2009 03:18:09 -0300 Subject: [PATCH] Liveness funcionando --- abi.c | 6 +++++ analyser.c | 46 ++++++++++++++++++++++++++------- code.h | 28 ++++++++++++-------- liveness.c | 61 +++++++++++++++++++++++++++++++++++++++++++ module.c | 2 ++ nids.c | 4 +-- operations.c | 35 ++++++++++++++++++++++--- outcode.c | 7 ++++- ssa.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++------ subroutines.c | 15 ++++++----- 10 files changed, 246 insertions(+), 41 deletions(-) diff --git a/abi.c b/abi.c index ff1bee3..223fbb5 100644 --- a/abi.c +++ b/abi.c @@ -1,3 +1,9 @@ #include "code.h" #include "utils.h" + + +void abi_check (struct subroutine *sub) +{ + +} diff --git a/analyser.c b/analyser.c index b34e3c7..8f27c7c 100644 --- a/analyser.c +++ b/analyser.c @@ -13,15 +13,15 @@ struct code *code_alloc (void) memset (c, 0, sizeof (struct code)); c->lstpool = listpool_create (8192, 4096); - c->switchpool = fixedpool_create (sizeof (struct codeswitch), 64, 1); - c->subspool = fixedpool_create (sizeof (struct subroutine), 1024, 1); - c->blockspool = fixedpool_create (sizeof (struct basicblock), 4096, 1); - c->edgespool = fixedpool_create (sizeof (struct basicedge), 8192, 1); - c->varspool = fixedpool_create (sizeof (struct variable), 4096, 1); - c->opspool = fixedpool_create (sizeof (struct operation), 8192, 1); - c->valspool = fixedpool_create (sizeof (struct value), 8192, 1); - c->loopspool = fixedpool_create (sizeof (struct loopstructure), 256, 1); - c->ifspool = fixedpool_create (sizeof (struct ifstructure), 1024, 1); + c->switchpool = fixedpool_create (sizeof (struct codeswitch), 64, TRUE); + c->subspool = fixedpool_create (sizeof (struct subroutine), 1024, TRUE); + c->blockspool = fixedpool_create (sizeof (struct basicblock), 4096, TRUE); + c->edgespool = fixedpool_create (sizeof (struct basicedge), 8192, TRUE); + c->varspool = fixedpool_create (sizeof (struct variable), 4096, TRUE); + c->opspool = fixedpool_create (sizeof (struct operation), 8192, TRUE); + c->valspool = fixedpool_create (sizeof (struct value), 8192, TRUE); + c->loopspool = fixedpool_create (sizeof (struct loopstructure), 256, TRUE); + c->ifspool = fixedpool_create (sizeof (struct ifstructure), 1024, TRUE); return c; } @@ -41,6 +41,7 @@ struct code* code_analyse (struct prx *p) extract_switches (c); extract_subroutines (c); + live_registers (c); el = list_head (c->subroutines); @@ -55,12 +56,37 @@ struct code* code_analyse (struct prx *p) if (!sub->haserror) { sub->status |= SUBROUTINE_CFG_TRAVERSE_REV; - fix_call_operations (sub); + fixup_call_arguments (sub); + } + + if (!sub->haserror) { + sub->status |= SUBROUTINE_FIXUP_CALL_ARGS; build_ssa (sub); } if (!sub->haserror) { sub->status |= SUBROUTINE_SSA; + } + } + el = element_next (el); + } + + live_registers_imports (c); + + el = list_head (c->subroutines); + while (el) { + sub = element_getvalue (el); + if (!sub->import && !sub->haserror) { + if (!(sub->status & SUBROUTINE_FIXUP_CALL_ARGS)) { + fixup_call_arguments (sub); + if (!sub->haserror) { + sub->status |= SUBROUTINE_FIXUP_CALL_ARGS; + build_ssa (sub); + } + } + + if (!sub->haserror) { + sub->status |= SUBROUTINE_SSA; propagate_constants (sub); } diff --git a/code.h b/code.h index 1318911..1ad5b7c 100644 --- a/code.h +++ b/code.h @@ -16,16 +16,17 @@ #define IMMU(op) ((unsigned short) (op & 0xFFFF)) /* Subroutine decompilation status */ -#define SUBROUTINE_EXTRACTED 1 -#define SUBROUTINE_CFG_EXTRACTED 2 -#define SUBROUTINE_OPERATIONS_EXTRACTED 4 -#define SUBROUTINE_LIVE_REGISTERS 8 -#define SUBROUTINE_CFG_TRAVERSE 16 -#define SUBROUTINE_CFG_TRAVERSE_REV 32 -#define SUBROUTINE_SSA 64 -#define SUBROUTINE_CONSTANTS_EXTRACTED 128 -#define SUBROUTINE_VARIABLES_EXTRACTED 256 -#define SUBROUTINE_STRUCTURES_EXTRACTED 512 +#define SUBROUTINE_EXTRACTED 1 +#define SUBROUTINE_CFG_EXTRACTED 2 +#define SUBROUTINE_OPERATIONS_EXTRACTED 4 +#define SUBROUTINE_LIVE_REGISTERS 8 +#define SUBROUTINE_CFG_TRAVERSE 16 +#define SUBROUTINE_CFG_TRAVERSE_REV 32 +#define SUBROUTINE_FIXUP_CALL_ARGS 64 +#define SUBROUTINE_SSA 128 +#define SUBROUTINE_CONSTANTS_EXTRACTED 256 +#define SUBROUTINE_VARIABLES_EXTRACTED 512 +#define SUBROUTINE_STRUCTURES_EXTRACTED 1024 /* Register values */ #define REGISTER_GPR_ZERO 0 @@ -357,13 +358,18 @@ void extract_structures (struct subroutine *sub); struct operation *operation_alloc (struct basicblock *block); struct value *value_append (struct subroutine *sub, list l, enum valuetype type, uint32 value); void extract_operations (struct subroutine *sub); +void fixup_call_arguments (struct subroutine *sub); +void remove_call_arguments (struct subroutine *sub); void live_registers (struct code *c); +void live_registers_imports (struct code *c); -void fix_call_operations (struct subroutine *sub); void build_ssa (struct subroutine *sub); +void unbuild_ssa (struct subroutine *sub); + void propagate_constants (struct subroutine *sub); void extract_variables (struct subroutine *sub); +void abi_check (struct subroutine *sub); #endif /* __CODE_H */ diff --git a/liveness.c b/liveness.c index a22b175..f223f7c 100644 --- a/liveness.c +++ b/liveness.c @@ -110,3 +110,64 @@ void live_registers (struct code *c) live_analysis (worklist); list_free (worklist); } + +void live_registers_imports (struct code *c) +{ + element el = list_head (c->subroutines); + + while (el) { + struct subroutine *sub = element_getvalue (el); + if (sub->import && sub->numregargs == -1) { + element ref; + + ref = list_head (sub->whereused); + while (ref) { + struct basicblock *block = element_getvalue (ref); + struct operation *op = list_tailvalue (block->operations); + int count = 0, maxcount = 0; + element opel; + + opel = list_head (op->info.callop.arguments); + while (opel) { + struct value *val = element_getvalue (opel); + count++; + + if (list_size (val->val.variable->uses) == 1 && + val->val.variable->def->type != OP_START && + val->val.variable->def->type != OP_CALL) { + if (maxcount < count) maxcount = count; + } + opel = element_next (opel); + } + + if (sub->numregargs < maxcount) + sub->numregargs = maxcount; + + ref = element_next (ref); + } + + ref = list_head (sub->whereused); + while (ref) { + struct basicblock *block = element_getvalue (ref); + struct subroutine *target = block->sub; + + target->status &= ~(SUBROUTINE_SSA | SUBROUTINE_FIXUP_CALL_ARGS); + ref = element_next (ref); + } + } + el = element_next (el); + } + + el = list_head (c->subroutines); + + while (el) { + struct subroutine *sub = element_getvalue (el); + if (!sub->import && !sub->haserror && + !(sub->status & SUBROUTINE_SSA)) { + unbuild_ssa (sub); + remove_call_arguments (sub); + } + el = element_next (el); + } + +} diff --git a/module.c b/module.c index 4236705..43d04fe 100644 --- a/module.c +++ b/module.c @@ -152,6 +152,7 @@ int load_module_import (struct prx *p, struct prx_import *imp) f->vaddr = imp->funcsvaddr + 8 * i; f->libname = imp->name; f->name = NULL; + f->numargs = -1; } } @@ -234,6 +235,7 @@ int load_module_export (struct prx *p, struct prx_export *exp) f->nid = read_uint32_le (&p->data[offset]); f->name = NULL; f->libname = exp->name; + f->numargs = -1; offset += 4; if (exp->namevaddr == 0) { f->name = resolve_syslib_nid (f->nid); diff --git a/nids.c b/nids.c index a0dbe62..dd67bc6 100644 --- a/nids.c +++ b/nids.c @@ -112,7 +112,7 @@ void end_hndl (void *data, const char *el) } d->currnid.name = NULL; d->currnid.nid = 0; - d->currnid.numargs = 0; + d->currnid.numargs = -1; } } @@ -161,7 +161,7 @@ void char_hndl (void *data, const char *txt, int txtlen) sscanf (buffer, "0x%X", &d->currnid.nid); } } else { - d->currnid.numargs = 0; + d->currnid.numargs = -1; sscanf (buffer, "%d", &d->currnid.numargs); } } diff --git a/operations.c b/operations.c index 4ce408e..7a00d81 100644 --- a/operations.c +++ b/operations.c @@ -497,7 +497,7 @@ void extract_operations (struct subroutine *sub) } } -void fix_call_operations (struct subroutine *sub) +void fixup_call_arguments (struct subroutine *sub) { struct operation *op; struct basicblock *block; @@ -513,8 +513,10 @@ void fix_call_operations (struct subroutine *sub) op = list_tailvalue (block->operations); target = block->info.call.calltarget; - if (target) regend = REGISTER_GPR_A0 + target->numregargs; - else regend = REGISTER_GPR_T4; + regend = REGISTER_GPR_T4; + if (target) + if (target->numregargs != -1) + regend = REGISTER_GPR_A0 + target->numregargs; for (regno = REGISTER_GPR_A0; regno < regend; regno++) { val = value_append (sub, op->operands, VAL_REGISTER, regno); @@ -532,3 +534,30 @@ void fix_call_operations (struct subroutine *sub) el = element_next (el); } } + +void remove_call_arguments (struct subroutine *sub) +{ + struct operation *op; + struct basicblock *block; + struct value *val; + element el; + + el = list_head (sub->blocks); + while (el) { + block = element_getvalue (el); + if (block->type == BLOCK_CALL) { + op = list_tailvalue (block->operations); + while (list_size (op->info.callop.arguments) != 0) { + val = list_removetail (op->info.callop.arguments); + list_removetail (op->operands); + fixedpool_free (sub->code->valspool, val); + } + while (list_size (op->info.callop.retvalues) != 0) { + val = list_removetail (op->info.callop.retvalues); + list_removetail (op->results); + fixedpool_free (sub->code->valspool, val); + } + } + el = element_next (el); + } +} diff --git a/outcode.c b/outcode.c index e55b30e..56ad6a7 100644 --- a/outcode.c +++ b/outcode.c @@ -153,7 +153,12 @@ void print_block_recursive (FILE *out, struct basicblock *block, int verbosity) static void print_subroutine (FILE *out, struct subroutine *sub, int verbosity) { - if (sub->import) return; + if (sub->import) { + fprintf (out, "/* "); + print_subroutine_name (out, sub); + fprintf (out, " num args %d out %d */\n", sub->numregargs, sub->numregout); + return; + } fprintf (out, "/**\n * Subroutine at address 0x%08X\n", sub->begin->address); fprintf (out, " * Numargs: %d Numout: %d\n", sub->numregargs, sub->numregout); diff --git a/ssa.c b/ssa.c index 4e0b3e5..e721215 100644 --- a/ssa.c +++ b/ssa.c @@ -169,11 +169,11 @@ void build_ssa (struct subroutine *sub) { list reglist[NUM_REGISTERS]; element blockel; - int i; + int regno; reglist[0] = NULL; - for (i = 1; i < NUM_REGISTERS; i++) { - reglist[i] = list_alloc (sub->code->lstpool); + for (regno = 1; regno < NUM_REGISTERS; regno++) { + reglist[regno] = list_alloc (sub->code->lstpool); } sub->variables = list_alloc (sub->code->lstpool); @@ -181,9 +181,9 @@ void build_ssa (struct subroutine *sub) blockel = list_head (sub->blocks); while (blockel) { struct basicblock *block = element_getvalue (blockel); - for (i = 0; i < NUM_REGISTERS; i++) { - if (IS_BIT_SET (block->reg_kill, i)) - list_inserttail (reglist[i], block); + for (regno = 0; regno < NUM_REGISTERS; regno++) { + if (IS_BIT_SET (block->reg_kill, regno)) + list_inserttail (reglist[regno], block); } blockel = element_next (blockel); } @@ -191,9 +191,76 @@ void build_ssa (struct subroutine *sub) ssa_place_phis (sub, reglist); ssa_search (sub->startblock, reglist); - for (i = 1; i < NUM_REGISTERS; i++) { - list_free (reglist[i]); + for (regno = 1; regno < NUM_REGISTERS; regno++) { + list_free (reglist[regno]); } } +void unbuild_ssa (struct subroutine *sub) +{ + element varel, valel, blockel, opel; + + blockel = list_head (sub->blocks); + while (blockel) { + struct basicblock *block = element_getvalue (blockel); + opel = list_head (block->operations); + while (opel) { + struct operation *op = element_getvalue (opel); + element nextopel; + + nextopel = element_next (opel); + if (op->type == OP_PHI) { + element_remove (opel); + + valel = list_head (op->operands); + while (valel) { + struct value *val = element_getvalue (valel); + fixedpool_free (sub->code->valspool, val); + valel = element_next (valel); + } + list_free (op->operands); + + fixedpool_free (sub->code->valspool, list_headvalue (op->results)); + list_free (op->results); + } else { + valel = list_head (op->operands); + while (valel) { + struct value *val = element_getvalue (valel); + if (val->type == VAL_VARIABLE) { + val->type = VAL_REGISTER; + val->val.intval = val->val.variable->name.val.intval; + } + valel = element_next (valel); + } + + valel = list_head (op->results); + while (valel) { + struct value *val = element_getvalue (valel); + if (val->type == VAL_VARIABLE) { + val->type = VAL_REGISTER; + val->val.intval = val->val.variable->name.val.intval; + } + valel = element_next (valel); + } + + } + opel = nextopel; + } + blockel = element_next (blockel); + } + + varel = list_head (sub->variables); + while (varel) { + struct variable *var = element_getvalue (varel); + list_free (var->uses); + fixedpool_free (sub->code->varspool, var); + varel = element_next (varel); + } + list_free (sub->variables); + + sub->variables = NULL; +} + + + diff --git a/subroutines.c b/subroutines.c index eb926c1..f08a421 100644 --- a/subroutines.c +++ b/subroutines.c @@ -146,17 +146,18 @@ void extract_from_exports (struct code *c) exp = &c->file->modinfo->exports[i]; for (j = 0; j < exp->nfuncs; j++) { + struct prx_function *func = &exp->funcs[j]; struct location *loc; - tgt = (exp->funcs[j].vaddr - c->baddr) >> 2; - if (exp->funcs[j].vaddr < c->baddr || + tgt = (func->vaddr - c->baddr) >> 2; + if (func->vaddr < c->baddr || tgt >= c->numopc) { error (__FILE__ ": invalid exported function"); continue; } loc = &c->base[tgt]; - new_subroutine (c, loc, NULL, &exp->funcs[j]); + new_subroutine (c, loc, NULL, func); } } } @@ -171,17 +172,19 @@ void extract_from_imports (struct code *c) imp = &c->file->modinfo->imports[i]; for (j = 0; j < imp->nfuncs; j++) { + struct prx_function *func = &imp->funcs[j]; struct location *loc; - tgt = (imp->funcs[j].vaddr - c->baddr) >> 2; - if (imp->funcs[j].vaddr < c->baddr || + tgt = (func->vaddr - c->baddr) >> 2; + if (func->vaddr < c->baddr || tgt >= c->numopc) { error (__FILE__ ": invalid imported function"); continue; } loc = &c->base[tgt]; - new_subroutine (c, loc, &imp->funcs[j], NULL); + new_subroutine (c, loc, func, NULL); + loc->sub->numregargs = func->numargs; } } } -- 2.11.4.GIT