Initial release

git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@1269 379699f6-c40d-0410-875b-85095c16579e
master
hoenicke 25 years ago
parent 1a0fc97111
commit 571bb071fe
  1. 96
      jode/jode/decompiler/OptionNames.properties
  2. 50
      jode/jode/obfuscator/modules/IdentityRenamer.java
  3. 134
      jode/scripts/createStackDelta.pl
  4. 40
      jode/test/innerclasses/CheckPrivate.java
  5. 28
      jode/test/innerclasses/CheckSuperRemove.java

@ -0,0 +1,96 @@
options = tabwidth,indent,style,linewidth,import,verbose,lvt,inner,anonymous,push,pretty,decrypt,onetime,immediate,verify,contrafo,debug
tabwidth.0=<n>
tabwidth.1=Set tab width to n.
tabwidth.2=This means that Jode uses tabs to replace n spaces. \
Don't confound this with the indent option. Use 0 if you don't want \
tabs. Default is 8.
indent.0=<n>
indent.1=Indent blocks by n spaces.
style.0={sun|gnu}
style.1=Specify indentation style.
linewidth.0=<n>
linewidth.1=Set maximum line width to n.
linewidth.2=Jode breaks lines that are longer than this. It tries it's best \
to make all lines fit in this limit, but sometimes this won't succeed.
import.0=<pkglimit>,<clslimit>
import.1=import classes if they occur more than clslimit times and packages \
with more than pkglimit used classes. Default is 0,1 which means that all \
used classes are imported, but never a whole package.
verbose.0=<n>
verbose.1=Be verbose (higher n means more verbose).
verbose.2=This prints some information about the currently decompiled \
class or method to the console.
debug.0=<flag>,...
debug.1=Enable debugging options. Useful to track errors in the decompiler.
debug.2=Possible flags are: \
"bytecode", to print raw bytecode. \
"lvt", dump LocalVariableTable. \
"verifier", to trace bytecode verification. \
"check", do time consuming sanity checks; useful to spot serious errors. \
"types", to see the type intersections. \
"flow", for a very verbose trace of the decompile process. \
"analyze", briefly inform about "T1/T2" analyzation. \
"inout", to view the in/out local variable analyzation. \
"locals", to see how local variable merging is done. \
"constructors", to trace constructor transformation. \
"interpreter", to follow the execution of the interpreter \
(the interpreter is used for string decryption).
inner.0={yes|no}
inner.1=(Don't) decompiler inner classes.
anonymous.0={yes|no}
anonymous.1=(Don't) decompiler method scoped classes.
contrafo.0={yes|no}
contrafo.1=(Don't) transform constructors.
lvt.0={yes|no}
lvt.1=(Don't) use the local variable table.
lvt.2=Turning it off is useful if an obfuscator filled it with bogus values.
pretty.0={yes|no}
pretty.1=(Don't) use `pretty' names for local variables.
pretty.2=The non pretty names have the advantage, that their names are \
unique. This make search & replace possible.
push.0={yes|no}
push.1=Allow PUSH pseudo instructions in output.
push.2=Sometimes, when methods were inlined, Jode can't reconstruct \
the original expression. It has to split a complex expression into \
several ones, using temporary variables. If this option is on, it won't \
use the temporary variables, but uses pseudo PUSH/POP instructions instead, \
as they are in the bytecode.
decrypt.0={yes|no}
decrypt.1=(Don't) decrypt encrypted strings.
decrypt.2=Some obfuscators encrypt all strings. To decrypt them at runtime \
they add a small decryption routine to the code. If Jode detects such a \
decryption routine it interprets it to decrypt the strings at decompile time.
onetime.0={yes|no}
onetime.1=(Don't) remove locals that written and then immediately read.
onetime.2=When javac inlines a method it uses temporary local variables for \
the parameters. Often these local variables can be removed, which makes \
the code much better to read.
immediate.0={yes|no}
immediate.1=Output the source immediately as it gets decompiled.
immediate.2=This leads to more instant output, but has many disadvantages.\
For one the import statements can't be correct. But it also may lead to \
buggy code. The advantage is, that you can get partial output even if an
exception is thrown.
verify.0={yes|no}
verify.1=(Don't) verify code before decompiling it.
verify.2=Jode assumes at many places that your byte code is legal. To \
be sure it verifies it before decompiling. If verification fails it \
rejects the code. Since verification can fail for legal code if the \
type hierarchy is not known, you can turn this option off.

@ -0,0 +1,50 @@
/* IdentityRenamer Copyright (C) 1999 Jochen Hoenicke.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Id$
*/
package jode.obfuscator.modules;
import jode.obfuscator.Renamer;
import jode.obfuscator.Identifier;
///#def COLLECTIONS java.util
import java.util.Iterator;
///#enddef
///#def COLLECTIONEXTRA java.lang
import java.lang.UnsupportedOperationException;
///#enddef
public class IdentityRenamer implements Renamer {
public Iterator generateNames(Identifier ident) {
final String base = ident.getName();
return new Iterator() {
int last = 0;
public boolean hasNext() {
return true;
}
public Object next() {
return (last++ == 0 ? base : base + last);
}
public void remove() {
throw new UnsupportedOperationException();
}
};
}
}

@ -0,0 +1,134 @@
#!/usr/bin/perl
# createStackDelta.pl Copyright (C) 1999 Jochen Hoenicke.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; see the file COPYING. If not, write to
# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
#
# $Id$
# This perl script creates the stackDelta string needed by
# jode.bytecode.Instruction.
my $OPCODEFILE="jode/bytecode/Opcodes.java";
my @delta;
my $lastOpcode = 0;
my $nr;
open OPCODES, "<$OPCODEFILE";
while (<OPCODES>) {
next unless /opc_([a-z0-9_]+)\s*=\s*(\d+)/;
$_ = $1;
$nr = $2;
if (/^(nop|iinc)$/) {
# no pop, no push
$delta[$nr] = "000";
} elsif (/^([aif](const|load).*|[sb]ipush|ldc(_w)?)$/) {
# no pop, one push
$delta[$nr] = "010";
} elsif (/^([ld](const|load).*|ldc2_w)$/) {
# no pop, two push
$delta[$nr] = "020";
} elsif (/^([aif]store.*|pop)$/) {
# one pop, no push
$delta[$nr] = "001";
} elsif (/^([ld]store.*|pop2)$/) {
# two pop, no push
$delta[$nr] = "002";
} elsif (/^[aifbcs]aload$/) {
# two pop, one push
$delta[$nr] = "012";
} elsif (/^[dl]aload$/) {
# two pop, two push
$delta[$nr] = "022";
} elsif (/^[aifbcs]astore$/) {
# three pop, no push
$delta[$nr] = "003";
} elsif (/^[dl]astore$/) {
# four pop, no push
$delta[$nr] = "004";
} elsif (/^dup(2)?(_x([12]))?$/) {
$count = $1 ? 2 : 1;
$depth = $2 ? $3 : 0;
$pop = $count + $depth;
$push = $pop + $count;
$delta[$nr] = "0".$push.$pop;
} elsif (/^swap$/) {
# two pop, two push
$delta[$nr] = "022";
} elsif (/^[if](add|sub|mul|div|rem|u?sh[lr]|and|or|xor)$/) {
# two pop, one push
$delta[$nr] = "012";
} elsif (/^[ld](add|sub|mul|div|rem|and|or|xor)$/) {
# four pop, two push
$delta[$nr] = "024";
} elsif (/^[if]neg$/) {
# one pop, one push
$delta[$nr] = "011";
} elsif (/^[ld]neg$/) {
# two pop, two push
$delta[$nr] = "022";
} elsif (/^lu?sh[lr]$/) {
# 3 pop, two push
$delta[$nr] = "023";
} elsif (/^[if]2[ifbcs]$/) {
# one pop, one push
$delta[$nr] = "011";
} elsif (/^[if]2[ld]$/) {
# one pop, two push
$delta[$nr] = "021";
} elsif (/^[ld]2[if]$/) {
# two pop, one push
$delta[$nr] = "012";
} elsif (/^[ld]2[ld]$/) {
# two pop, two push
$delta[$nr] = "022";
} elsif (/^fcmp[lg]$/) {
$delta[$nr] = "012";
} elsif (/^[ld]cmp[lg]?$/) {
$delta[$nr] = "014";
} elsif (/^if_[ia]cmp(eq|ne|lt|ge|le|gt)$/) {
$delta[$nr] = "002";
} elsif (/^(if(eq|ne|lt|ge|le|gt|(non)?null)|tableswitch|lookupswitch)$/) {
# order does matter
$delta[$nr] = "001";
} elsif (/^(goto(_w)?|jsr(_w)?|ret|return)$/) {
$delta[$nr] = "000";
} elsif (/^([ifa]return)$/) {
$delta[$nr] = "001";
} elsif (/^([ld]return)$/) {
$delta[$nr] = "002";
} elsif (/^(new)$/) {
$delta[$nr] = "010";
} elsif (/^(multianewarray|(get|put|invoke).*)$/) {
# unknown
$delta[$nr] = "100";
} elsif (/^(athrow|monitor(enter|exit))$/) {
$delta[$nr] = "001";
} elsif (/^(a?newarray|arraylength|checkcast|instanceof)$/) {
$delta[$nr] = "011";
} else {
# illegal
next;
}
$lastOpcode = $nr
if ($nr > $lastOpcode);
}
print " private final static String stackDelta = \n\t\"";
for ($nr = 0; $nr <= $lastOpcode; $nr ++) {
defined $delta[$nr] or $delta[$nr] = "177";
print "\\$delta[$nr]";
}
print "\";\n";

@ -0,0 +1,40 @@
public class CheckPrivate {
private class InnerClass {
private int field;
private InnerClass(int j) {
field = j;
}
private int method(int a) {
int old = field;
field = a;
return old;
}
private void test() {
outerField = 4;
outerMethod();
System.err.println(outerField);
new CheckPrivate();
}
}
private int outerField;
private int outerMethod() {
return outerField;
}
private CheckPrivate() {
InnerClass inner = new InnerClass(1);
inner.field = 3;
inner.method(inner.field);
}
public static void main(String[] test) {
new CheckPrivate();
}
}

@ -0,0 +1,28 @@
public class CheckSuperRemove {
public class Inner {
public void test() {
class MyInner extends Inner {
}
MyInner myInner = new MyInner();
Inner anonInner = new Inner() {
public void test() {}
};
MyInner anonInner2 = new MyInner() {
public void test() {}
};
}
}
public class SubInner extends Inner {
public SubInner(int a) {
}
public SubInner() {
}
}
public static void main(String[] param) {
new CheckSuperRemove().new SubInner();
new CheckSuperRemove().new SubInner(1);
}
}
Loading…
Cancel
Save