forums.ps2dev.org Forum Index forums.ps2dev.org
Homebrew PS2, PSP & PS3 Development Discussions
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

PSP decompiler
Goto page 1, 2  Next
 
Post new topic   Reply to topic    forums.ps2dev.org Forum Index -> PSP Development
View previous topic :: View next topic  
Author Message
hnaves



Joined: 03 Feb 2009
Posts: 30

PostPosted: Tue May 12, 2009 8:43 pm    Post subject: PSP decompiler Reply with quote

While trying to decompile the usb.prx (FW 1.5) by hand, I realized that it was a very long and boring process... So I made this little tool to help us while doing some prx reverse engineering...

http://ifile.it/93pthb0

The instructions to compile and use are in the README file.The output of the program is a low-level "C" program (with a lot of imperfections), but it is almost understandable. There is also a DOT mode, where the output is a collection of graphviz dot files with the control flow graph of the program.

I know that this tool has several bugs and improvements to be made, and I hope that more people contribute to its development. Please use with caution. I would like to thank Tyranid for the development of prxtool.
Back to top
View user's profile Send private message
hlide



Joined: 10 Sep 2006
Posts: 750

PostPosted: Wed May 13, 2009 5:29 am    Post subject: Reply with quote

quite impressive

do you think we can put it through SVN in google code ? so some of use can contribute ?
Back to top
View user's profile Send private message
jimparis



Joined: 10 Jun 2005
Posts: 1179
Location: Boston

PostPosted: Wed May 13, 2009 5:43 am    Post subject: Reply with quote

Agreed, very impressive!
Back to top
View user's profile Send private message
TyRaNiD



Joined: 18 Jan 2004
Posts: 918

PostPosted: Wed May 13, 2009 6:06 am    Post subject: Reply with quote

Nice work :)
Back to top
View user's profile Send private message
hnaves



Joined: 03 Feb 2009
Posts: 30

PostPosted: Wed May 13, 2009 7:31 am    Post subject: Reply with quote

Does anybody here uses GIT? My project is already under version control at http://repo.or.cz/w/pspdecompiler.git. I believe GIT is better and easier than SVN or CVS, and it is used in the Linux Kernel project :-)

I have also another project, that is to build an OPEN EDITION USB driver for PSP. I have already started, and decompiled (by hand :-) about 20% of the original PRX. Using the tool now will greatly improve the speed of the development. Anybody interested?
Back to top
View user's profile Send private message
ghost_gluck



Joined: 04 Apr 2008
Posts: 7

PostPosted: Wed May 13, 2009 9:13 am    Post subject: Reply with quote

hnaves wrote:
I have also another project, that is to build an OPEN EDITION USB driver for PSP. I have already started, and decompiled (by hand :-) about 20% of the original PRX. Using the tool now will greatly improve the speed of the development. Anybody interested?


Nice work!
I find some bugs with firmware prxses decompilation (usb.prx and other) and fix it, see below
Code:
diff -urN pspdecompiler/lists.c pspdecompiler.patched/lists.c
--- pspdecompiler/lists.c   2009-05-12 13:29:26.000000000 +0300
+++ pspdecompiler.patched/lists.c   2009-05-13 11:24:32.812500000 +0300
@@ -85,7 +85,7 @@
 
 element list_head (list l)
 {
-  return l->head;
+  return (l != NULL) ? l->head : NULL;
 }
 
 void *list_headvalue (list l)
@@ -200,22 +200,23 @@
 
 void *element_getvalue (element el)
 {
-  return el->value;
+  return (el != NULL) ? el->value : NULL;
 }
 
 void element_setvalue (element el, void *val)
 {
-  el->value = val;
+  if(el != NULL )
+    el->value = val;
 }
 
 element element_next (element el)
 {
-  return el->next;
+  return (el != NULL) ? el->next : NULL;
 }
 
 element element_previous (element el)
 {
-  return el->prev;
+  return (el != NULL) ? el->prev : NULL;
 }
 
 
diff -urN pspdecompiler/operations.c pspdecompiler.patched/operations.c
--- pspdecompiler/operations.c   2009-05-12 13:29:26.000000000 +0300
+++ pspdecompiler.patched/operations.c   2009-05-13 13:37:12.140625000 +0300
@@ -161,7 +161,7 @@
     }
   case I_MOVN:
     val = element_getvalue (element_next (list_head (op->operands)));
-    if (val->val.intval == 0) {
+    if (val != NULL && val->val.intval == 0) {
       reset_operation (op);
       op->type = OP_NOP;
     }
diff -urN pspdecompiler/output.c pspdecompiler.patched/output.c
--- pspdecompiler/output.c   2009-05-12 13:29:26.000000000 +0300
+++ pspdecompiler.patched/output.c   2009-05-13 13:43:22.296875000 +0300
@@ -462,7 +462,7 @@
   val = list_headvalue (op->operands);
   if (val->type == VAL_SSAVAR) {
     if (val->val.variable->type == SSAVAR_CONSTANT) {
-      address = val->val.variable->type;
+      address = val->val.variable->info;
       val = list_tailvalue (op->operands);
       address += val->val.intval;
       fprintf (out, "*((%s) 0x%08X)", type, address);

Problem with access to the structure member when pointer to val or el struct is NULL.
Mabye you are already fix this problem. I don't check git source.

[offtopic]
About OPEN EDITION USB driver for PSP:
So I started working on USB driver for PSP. I want to add to the driver functionality which allow create more than Block Devices, for example: HID devices (joysticks etc), RNDIS devices and additional host functionality (PSP as USB Host - maybe this is a dream).
I want try to connect my GPS (PSP-290) module to PC for examine communication protocol. If GPS module connected to PC and it is works as device, then PSP works as host when GPS module was connected to PSP.(IMHO) It's correct?
[/offtopic]

EDIT:
I find bug with translation addresses, see below:
lui $t0, 0xbc10
lw $t1, 0x4c($t0)
is interpreted as var = *((int*) 0x00000050, but right translation is var = *((int*) 0x0xbc10004c.

EDIT:
previous bug was fixed. see diff. problem in address = val->val.variable->type, but base address value contains in val->val.variable->info

New problem. Procedure calls through registers (jal rX) doesn't reverses correctly. Maybe its possible because subroutine address calculation mechanism doesn't implemented/works incorrectly.
_________________
Sorry for terrible english. My native language is C++...
Back to top
View user's profile Send private message
sauron_le_noir



Joined: 05 Jul 2008
Posts: 229

PostPosted: Thu May 14, 2009 2:48 am    Post subject: Reply with quote

Great tool Where can we found nidsfiles ? are this files compatible with the nids file found on http://silverspring.lan.st/
Back to top
View user's profile Send private message Send e-mail MSN Messenger
ghost_gluck



Joined: 04 Apr 2008
Posts: 7

PostPosted: Thu May 14, 2009 3:15 am    Post subject: Reply with quote

sauron_le_noir wrote:
Great tool Where can we found nidsfiles ? are this files compatible with the nids file found on http://silverspring.lan.st/


compatible.
_________________
Sorry for terrible english. My native language is C++...
Back to top
View user's profile Send private message
hlide



Joined: 10 Sep 2006
Posts: 750

PostPosted: Thu May 14, 2009 7:19 am    Post subject: Reply with quote

some suggestions :

1) prepend "int " to "varN = ..." :

in "static void print_binaryop (FILE *out, struct operation *op, const char *opsymbol, int options)",
"void print_complexop (FILE *out, struct operation *op, const char *opsymbol, int options)", etc. transform every "print_value (out, list_headvalue (op->results));" into "print_result (out, list_headvalue (op->results));"

and add :

Code:

void print_result(FILE *out, struct value *val)
{
    fprintf(out, "int ");
    print_element (out, value, 0);
}


2) add ';' to each output asm string instruction :

Code:

static
void print_asm (FILE *out, struct operation *op, int identsize, int options)
{
   struct location *loc;

   ident_line (out, identsize);
   fprintf (out, "__asm__ (");
   for (loc = op->info.asmop.begin; ; loc++) {
      if (loc != op->info.asmop.begin) {
         fprintf (out, "\n");
         ident_line (out, identsize);
         fprintf (out, "         ");
      }
      fprintf (out, "\"%s;\"", allegrex_disassemble (loc->opc, loc->address, FALSE));
      if (loc == op->info.asmop.end) break;
   }
   if (list_size (op->results) != 0 || list_size (op->operands) != 0) {
      print_asm_reglist (out, op->results, identsize, options);
      if (list_size (op->operands) != 0) {
         print_asm_reglist (out, op->operands, identsize, options);
      }
   }

   fprintf (out, ");\n");
}


i'm not sure there is a good reason to handle $sp and load/store operations with $sp as base as they are prolog and epilog, so you may probably drop them or rather make them into comment. By the way, having varN in epilog is ackward : wouldn't it better not to ssa them ?.
Back to top
View user's profile Send private message
hnaves



Joined: 03 Feb 2009
Posts: 30

PostPosted: Fri May 15, 2009 8:48 am    Post subject: Reply with quote

Hi,

I have corrected several bugs including those posted by ghost_gluck, and among them are:
- Invalid detection of nested ifs gotos;
- Better detection of constants
- Detection of callbacks

To checkout the lastest snapshot, please refer to
http://repo.or.cz/w/pspdecompiler.git
and click on the first snapshot right below the shortlog (on the very right side of the page)

The next step is to improve the detection of arguments and return values of subroutines
Back to top
View user's profile Send private message
willow :--)



Joined: 13 Jan 2007
Posts: 126

PostPosted: Fri May 15, 2009 10:38 am    Post subject: Reply with quote

This looks great!
You might want to remove the pdf documents from the repository though, I believe you can't freely distribute those ;)

Also, a very minor point, but could it be possible to have the list of options in alphabetical order in the "usage" text? (because there are lots of options)

Code:

    "  -c    output code\n"
    "  -d    print the dominator\n"
    "  -e    print edge types\n"
    "  -f    print the frontier\n"
    "  -g    output graphviz dot\n"
    "  -i    print prx info\n"
    "  -n    specify nids xml file\n"
    "  -q    print code into nodes\n"
    "  -r    print the reverse depth first search number\n"
    "  -s    print structures\n"
    "  -t    print depth first search number\n"
    "  -v    increase verbosity\n"
    "  -x    print the reverse dominator\n"
    "  -z    print the reverse frontier\n",
Back to top
View user's profile Send private message
SilverSpring



Joined: 27 Feb 2007
Posts: 115

PostPosted: Fri May 15, 2009 5:49 pm    Post subject: Reply with quote

Very nice, you worked out the new-style prxs? Good work.
_________________
PSP PRX LibDocs
Back to top
View user's profile Send private message Visit poster's website
hlide



Joined: 10 Sep 2006
Posts: 750

PostPosted: Sat May 16, 2009 4:50 pm    Post subject: Reply with quote

@SilverSpring: correct --> http://forums.ps2dev.org/viewtopic.php?p=80416#80416
Back to top
View user's profile Send private message
hlide



Joined: 10 Sep 2006
Posts: 750

PostPosted: Sat May 16, 2009 7:22 pm    Post subject: Reply with quote

@hnaves
There is a problem : in a loop starting with "while (1)" with a register counter, i have : "varN = varN;" instead of "varJ = varI + CONSTANT;" where varI is containing a constant. It seems the issue is in output.c :
Code:

void print_operation (FILE *out, struct operation *op, int identsize, int options)
{
  ...
  if ((op->status & (OP_STAT_CONSTANT | OP_STAT_DEFERRED)) == OP_STAT_CONSTANT) {
    struct value *val = list_headvalue (op->results);
    if (!(options & OPTS_NORESULT)) {
      print_value (out, val, OPTS_RESULT);
      fprintf (out, " = ");
    }
    print_value (out, val, 0);
  } else {
  ...
}


I may be wrong but it looks as if when an SSA register simplified to a constant" the operation status is erroneously marked as OP_STAT_CONSTANT because it doesn't take into account the fact that this operation is inside a loop and is not invariant.

If not, it means an I_ADDIU is wrongly transformed into a I_MOVE.
Back to top
View user's profile Send private message
D_Street



Joined: 12 Jun 2008
Posts: 22
Location: Berkeley, CA

PostPosted: Sat May 16, 2009 8:40 pm    Post subject: Reply with quote

really nice work!

i remember last year i also did a little decompiler, but that was a bit lame, i just did the decompile thing out of the output from prxtool! i guess that way i can just copy & paste a piece of the disassembly output and decompile it without any problems.
Back to top
View user's profile Send private message
hlide



Joined: 10 Sep 2006
Posts: 750

PostPosted: Sun May 17, 2009 2:18 am    Post subject: Reply with quote

there is a regression on the last version, pspdecompiler crashes on some prx files whereas the first public version did not.
Back to top
View user's profile Send private message
hnaves



Joined: 03 Feb 2009
Posts: 30

PostPosted: Sun May 17, 2009 10:50 am    Post subject: Reply with quote

Could you provide me the prx name (and version)? There were several critical bugs fixed (in the constant propagation algorithm) in the last revision, maybe the incorrect output for loops with constants will not exist anymore.
Back to top
View user's profile Send private message
hlide



Joined: 10 Sep 2006
Posts: 750

PostPosted: Sun May 17, 2009 11:05 am    Post subject: Reply with quote

I tried your last revision : two comile-time errors about value_append function missing the last argument in ssa.c; I appended FALSE as last argument to build pspdecompiler fine.

And yes, I have no crash now with all the prx which crashed.


Last edited by hlide on Sun May 17, 2009 10:04 pm; edited 1 time in total
Back to top
View user's profile Send private message
hlide



Joined: 10 Sep 2006
Posts: 750

PostPosted: Sun May 17, 2009 9:59 pm    Post subject: Reply with quote

do you detect some functions not terminating with a JA $RA but with a J ?

the rule is to check if a subroutine has no forward conditional branch when you meet a J to conclude this is subroutine with a tail call to another subroutine :
Code:

void X() { ...; Y(); } <=> ...; J sub_Y; ...;
void Y() { ... }       <=> ...: JR $RA; ...;

int Z() { ...; return W(); } <=> ...; J sub_Y; ...;
int W() { ... }              <=> ...; JR $RA; ...;
Back to top
View user's profile Send private message
hlide



Joined: 10 Sep 2006
Posts: 750

PostPosted: Sun May 17, 2009 11:18 pm    Post subject: Reply with quote

bug with counters in loops is still unresolved :

Code:

  while (1) {
    var17 = var17; <-- it should be : "var17 = var17 + 0x00000001;"
    InterruptManagerForKernel_7527A9BA (0x00000019, 0x00000000, 0x00000001);
    if (((var17 < 0x00000010)) != 0x00000000)
      continue;
    break;
  }


"var17 = var17;" is output when executing output.c:593 :
Code:

   if ((op->status & (OP_STAT_CONSTANT | OP_STAT_DEFERRED)) == OP_STAT_CONSTANT) {
    struct value *val = list_headvalue (op->results);
    if (!(options & OPTS_NORESULT)) {
      print_value (out, val, OPTS_RESULT);
     fprintf (out, " = ");
    }
    print_value (out, val, 0);
  } else {


first, i think "print_value (out, val, 0);" should be something like : "print_expression (out, <operands_expression>, 0, 0);"

second, i tracked OP_STAT_CONSTANT and found out they are set in constant.c:110 (I_MOV), 118(I_ADDI[U]), 124(I_OR). They are trying to make a constant value having the result. The issue var17 is initially set to 0 and so it is a constant. When it tries to evaluate "var17 = I_ADDIU(var17, 1)" it will set var17 as being a constant 1. So var17 is wrongly set as a constant operation :/ and we get "var17 = var17".

so when I try to remove lines constant.c:83-88, I get :
Code:

  while (1) {
    var17 = 0x00000000 + 0x00000001;
    InterruptManagerForKernel_7527A9BA (0x00000019, 0x00000000, 0x00000001);
    if (0x00000001 != 0x00000000)
      continue;
    break;
  }


as I feared, still not good.
Back to top
View user's profile Send private message
hnaves



Joined: 03 Feb 2009
Posts: 30

PostPosted: Wed May 20, 2009 9:59 am    Post subject: Reply with quote

Hi hlide,

I believe that the problem is fixed now.
Back to top
View user's profile Send private message
hlide



Joined: 10 Sep 2006
Posts: 750

PostPosted: Thu May 21, 2009 3:52 am    Post subject: Reply with quote

ackonwledged. I'll try when i have time and when I'm getting familiar with GIT :/ (which action you should do like a Update SVN ?)
Back to top
View user's profile Send private message
hnaves



Joined: 03 Feb 2009
Posts: 30

PostPosted: Thu May 21, 2009 4:07 am    Post subject: Reply with quote

Some useful links for GIT

http://www.kernel.org/pub/software/scm/git/docs/gittutorial.html

http://www.kernel.org/pub/software/scm/git/docs/everyday.html

http://www.kernel.org/pub/software/scm/git/docs/user-manual.html

To "update" (in the svn sense) you must perform a "git pull"

Hlide, as soon as you get acquainted to GIT, I will give you commit permissions to the repository.
Back to top
View user's profile Send private message
hlide



Joined: 10 Sep 2006
Posts: 750

PostPosted: Thu May 21, 2009 5:22 am    Post subject: Reply with quote

When doinga "pull", I got this :
Code:

git.exe pull "origin"

remote: Compressing objects: 100% (17/17)   
remote: Compressing objects: 100% (17/17), done.
remote: Total 26 (delta 13), reused 22 (delta 9)
From git://repo.or.cz/pspdecompiler
   9857781..52f17f2  master     -> origin/master
Updating 9857781..52f17f2
constants.c: needs update
output.c: needs update
ssa.c: needs update
fatal: Entry 'constants.c' not uptodate. Cannot merge.
Back to top
View user's profile Send private message
hlide



Joined: 10 Sep 2006
Posts: 750

PostPosted: Thu May 21, 2009 5:49 am    Post subject: Reply with quote

hnaves wrote:
I believe that the problem is fixed now.

I think so as I cannot see the bugs I used to see any longer :)
Back to top
View user's profile Send private message
hlide



Joined: 10 Sep 2006
Posts: 750

PostPosted: Mon Jun 01, 2009 4:16 am    Post subject: Reply with quote

pspdecompiler has trouble with tail call.

int f(int a) { return g(a); }

f will call g through a J instead of JAL, and it seems f is not reckoned properly because of this.

J can be considered as a call if it has the same arguments and result registers and the callee is defined as a function. So this J can be handled as a return.
Back to top
View user's profile Send private message
KickinAezz



Joined: 03 Jun 2007
Posts: 328

PostPosted: Mon Jun 01, 2009 6:01 am    Post subject: Reply with quote

Awesome project.

Hopefully once PSP GO! is hacked, we can play with bluetooth protocols unrestrictedly.
_________________
Intrigued by PSP system Since December 2006.
Use it more for Development than for Gaming.
Back to top
View user's profile Send private message
Wally



Joined: 26 Sep 2005
Posts: 672

PostPosted: Mon Jun 01, 2009 8:32 am    Post subject: Reply with quote

KickinAezz wrote:
Awesome project.

Hopefully once PSP GO! is hacked, we can play with bluetooth protocols unrestrictedly.


that is if anyone buys that damn ugly thing
Back to top
View user's profile Send private message AIM Address
hnaves



Joined: 03 Feb 2009
Posts: 30

PostPosted: Tue Jun 09, 2009 12:29 pm    Post subject: Reply with quote

hlide wrote:
pspdecompiler has trouble with tail call.

int f(int a) { return g(a); }

f will call g through a J instead of JAL, and it seems f is not reckoned properly because of this.

J can be considered as a call if it has the same arguments and result registers and the callee is defined as a function. So this J can be handled as a return.


Did you manage to solve the problem?
Back to top
View user's profile Send private message
hlide



Joined: 10 Sep 2006
Posts: 750

PostPosted: Wed Jun 10, 2009 4:00 am    Post subject: Reply with quote

no, i didn't. I don't know all the details about pspdecompiler source enough to solve those problems.

I also noticed that constant return values are not always treated (I was forced to use prxtool to retrieve some return values).

Have you any plan to handle float as well ? their handling is quite similar to int but don't know if it is easily feasible.
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    forums.ps2dev.org Forum Index -> PSP Development All times are GMT + 10 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group