TODO list updated

jcpp javaDeps moved to scripts


git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@1249 379699f6-c40d-0410-875b-85095c16579e
master
hoenicke 25 years ago
parent 39d1fbb31b
commit f85c46fd44
  1. 41
      jode/TODO
  2. 70
      jode/configure.in
  3. 184
      jode/javaDependencies.pl.in
  4. 173
      jode/jcpp

@ -1,6 +1,7 @@
This is a list of features, that would be nice to have: This is a list of features, that would be nice to have:
Decompiler: Decompiler:
- BUG: public final static null fields aren't initialized (leads to compile error)
- outline inlined methods. - outline inlined methods.
- remove string decrypt method. - remove string decrypt method.
- remove synthetic methods if and only if all calls to them are resolved. - remove synthetic methods if and only if all calls to them are resolved.
@ -8,15 +9,39 @@ Decompiler:
~ decompile jode.jvm.Interpreter (hand optimized bytecode) ~ decompile jode.jvm.Interpreter (hand optimized bytecode)
Obfuscator: Obfuscator:
- flow obfuscation/optimization. - Detect Class.forName() calls with constant parameters and rename
- warn about Class.forName and list occurences. these constants. Detect class$ methods with constant parameters.
Warn about all other occurences of Class.forName()
This should be put into the constant analyzer. The simple
analyzer should only do the warnings.
- Transforming the class hierarchy, e.g. combining two totally
unrelated classes together into one class or make some class
to implement some interfaces, that it previously didn't.
- Doing flow obfuscation, i.e. do some tests, that one knows to
succeed always, and jump to funny position if the test fails.
The tests should use undecidable properties, so that a
deobfuscator cannot remove them again.
DeObfuscator: DeObfuscator:
- generate nice names: - Deobfuscator should detect inner/anonymous classes and mark them
- classes: derive name from super. as such. It should be possible with the renaming table to mark
- fields: derive name from type. inner classes as well. Inner classes are easy to detect; there
- give synthetic methods the right attribute and name (e.g. class$) constructor has a special form. And the information is very
- detect inner classes and give suitable names. useful for the decompiler.
This should be done with some generalize interface similar to (or
instead of) Transformer
- Deobfuscator should generate nicer names. This should be a
special Renamer. The renamer should analyze short methods and
call them getXXX, isXXX, setXXX if apropriate, detect synthetic
methods and similar. Class names should be derived from super
class or interface (e.g. Enumeration), fields should be derived
from their type, maybe also from their assignments.
One can build more renamer, each handles some special cases and
calls the next one, if it can't handle an identifier.
User Interface: User Interface:
- make a nice user interface: - make a nice user interface:
@ -29,4 +54,4 @@ User Interface:
- visual obfuscation/deobfuscation (like klassmaster?, better?) - visual obfuscation/deobfuscation (like klassmaster?, better?)
Internal: Internal:
- clean up package hierarchy, esp. expr, flow and decompiler. - clean up package hierarchy, esp. expr, flow and decompiler.

@ -157,9 +157,9 @@ AC_SUBST(SWINGUI)
AC_SUBST(CLASSPATH) AC_SUBST(CLASSPATH)
AC_SUBST(JAVAC) AC_SUBST(JAVAC)
AC_SUBST(JAR)
AC_OUTPUT(Makefile AC_OUTPUT(Makefile
javaDependencies.pl
jode/Makefile jode/Makefile
jode/bytecode/Makefile jode/bytecode/Makefile
jode/decompiler/Makefile jode/decompiler/Makefile
@ -171,75 +171,9 @@ jode/obfuscator/modules/Makefile
jode/swingui/Makefile jode/swingui/Makefile
jode/type/Makefile jode/type/Makefile
jode/util/Makefile jode/util/Makefile
jode/bytecode/BinaryInfo.java
jode/bytecode/BytecodeInfo.java
jode/bytecode/ClassInfo.java
jode/bytecode/Reference.java
jode/decompiler/ImportHandler.java
jode/decompiler/ClassAnalyzer.java
jode/decompiler/FieldAnalyzer.java
jode/decompiler/MethodAnalyzer.java
jode/decompiler/DeadCodeAnalysis.java
jode/expr/Expression.java
jode/expr/FieldOperator.java
jode/expr/InvokeOperator.java
jode/expr/LocalVarOperator.java
jode/expr/Operator.java
jode/expr/CheckNullOperator.java
jode/flow/RetBlock.java
jode/flow/InstructionContainer.java
jode/flow/LoopBlock.java
jode/flow/SequentialBlock.java
jode/flow/SlotSet.java
jode/flow/StructuredBlock.java
jode/flow/SynchronizedBlock.java
jode/flow/VariableSet.java
jode/flow/CatchBlock.java
jode/flow/IfThenElseBlock.java
jode/flow/InstructionBlock.java
jode/flow/FlowBlock.java
jode/flow/TransformExceptionHandlers.java
jode/jvm/CodeVerifier.java
jode/jvm/Interpreter.java
jode/jvm/SyntheticAnalyzer.java
jode/obfuscator/ClassBundle.java
jode/obfuscator/ClassIdentifier.java
jode/obfuscator/ConstantRuntimeEnvironment.java
jode/obfuscator/FieldIdentifier.java
jode/obfuscator/Identifier.java
jode/obfuscator/LocalIdentifier.java
jode/obfuscator/Main.java
jode/obfuscator/MethodIdentifier.java
jode/obfuscator/OptionHandler.java
jode/obfuscator/PackageIdentifier.java
jode/obfuscator/Renamer.java
jode/obfuscator/ScriptParser.java
jode/obfuscator/TranslationTable.java
jode/obfuscator/modules/ConstantAnalyzer.java
jode/obfuscator/modules/KeywordRenamer.java
jode/obfuscator/modules/LocalOptimizer.java
jode/obfuscator/modules/LocalizeFieldTransformer.java
jode/obfuscator/modules/ModifierMatcher.java
jode/obfuscator/modules/MultiIdentifierMatcher.java
jode/obfuscator/modules/NameSwapper.java
jode/obfuscator/modules/RemovePopAnalyzer.java
jode/obfuscator/modules/SerializePreserver.java
jode/obfuscator/modules/SimpleAnalyzer.java
jode/obfuscator/modules/StrongRenamer.java
jode/obfuscator/modules/UniqueRenamer.java
jode/obfuscator/modules/WildCard.java
jode/swingui/Main.java
jode/swingui/PackagesTreeModel.java
jode/swingui/HierarchyTreeModel.java
jode/type/Type.java
jode/util/SimpleSet.java
jode/util/SimpleMap.java
jode/util/UnifyHash.java
jode/GlobalOptions.java
bin/Makefile bin/Makefile
bin/jode bin/jode
bin/jode.bat bin/jode.bat
doc/Makefile doc/Makefile
doc/download.html
test/Makefile, test/Makefile,
[chmod 755 javaDependencies.pl bin/jode]) [chmod 755 bin/jode])

@ -1,184 +0,0 @@
#!@PERL@ -s -w
#
# javaDependencies 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 scripts create Makefile dependencies out of class files. It
# simply scans the constant pool of the class files, finding all
# references to other classes and adding a dependency to that class.
#
# It doesn't do a perfect job, since it can't handle dependencies to
# constant values in different classes: The compiler inlines the
# constant and thus doesn't include a reference to the class.
#
# Usage:
# javaDependencies.pl -classpath <cp> [-dependdir <depdir> [-subdir <subdir>]]
# [-depfile <depfile>]
# <classfiles>
#
# cp: colon separated paths to the java files we should depend on.
# depdir: if set, use this path as path to the java files when printing
# dependencies, not the path where the java files were found.
# useful, if you want to make use of VPATH settings in Makefile.
# subdir: if set, this is the path from depdir to the current directory.
# Use it to remove unneccessary ../../$subdir/
# depfile: the name of the dependency file, default is "Makefile.dep".
# class: The class files (not inner classes) for which the dependencies
# should be generated. We will also look for inner and anon
# classes.
my $buff;
sub readInBuff ($) {
my $count = $_[0];
my $offset = 0;
while ($count > 0) {
my $result;
$result = read FILE, $buff, $count, $offset or return 0;
$offset += $result;
$count -= $result;
}
$offset;
}
sub readUTF () {
readInBuff 2 or die "Can't read UTF8 length";
my $ulength = unpack("n", $buff) & 0xffff;
return "" if $ulength == 0;
readInBuff $ulength or die "Can't read UTF8 string $ulength";
unpack("a$ulength", $buff);
}
$depfile = "Makefile.dep" if (!defined($depfile));
open DEPFILE, ">$depfile";
print DEPFILE <<EOF;
# This dependency file is automatically created by $0 from class files.
# Do not edit.
EOF
foreach $clazz (@ARGV) {
next if $clazz =~ (/^.*\$.*\.class/);
$clazz =~ /([^\$]*)(\$.*)?\.class/ or die "not a class file";
$base = $1;
my ($filename, %done);
%done=();
for $filename ($clazz, glob("$base\\\$*.class")) {
open FILE, $filename;
binmode FILE;
readInBuff 8 or die "Can't read header";
my ($magic, $minor, $major) = unpack("Nnn", $buff);
die "Wrong magic $magic" if $magic != 0xcafebabe;
die "Wrong minor $minor" if $minor > 3;
die "Wrong minor $major" if $major != 45;
readInBuff 2 or die "Can't read cpool length";
my ($length) = unpack("n", $buff) & 0xffff;
my $number;
my @strings = ();
my @clazzes;
for ($number = 1; $number < $length; $number++) {
readInBuff 1 or die "Can't read constant tag";
my ($tag) = unpack("C", $buff);
#print STDERR "$number/$length: $tag";
tags:
for ($tag) {
/^1$/ && do {
# UTF 8
$strings[$number] = &readUTF();
#print STDERR ": $strings[$number]";
last tags;
};
/^(3|4|9|10|11|12)$/ && do {
# INTEGER, FLOAT, FIELDREF, METHODREF, IFACEREF, NAMEANDTYPE
readInBuff 4;
last tags;
};
/^(5|6)$/ && do {
# LONG, DOUBLE
readInBuff 8;
$number++;
last tags;
};
/^7$/ && do {
# CLASS
readInBuff 2;
push @clazzes, (unpack("n", $buff) & 0xffff);
last tags;
};
/^8$/ && do {
# STRING
readInBuff 2;
last tags;
};
die "Unknown tag: $tag, $number/$length, $filename";
}
#print STDERR "\n";
}
my @deplist = ();
clazz:
for $c (@clazzes) {
$clzz = $strings[$c];
next if $clzz =~ /^\[/;
next if defined $done{"$clzz"};
$done{$clzz} = 1;
my $p;
for $p (split ':', $classpath) {
if (-e "$p/$clzz.java") {
my $path="$p/";
if (defined $dependdir) {
$path = "$dependdir/";
if (defined $subdir) {
my $currsubdir = "$subdir/";
while ($currsubdir =~ m<^([A-Za-z0-9]+)/+(.*)>) {
$currsubdir = $2;
my $firstcomp = $1;
if ($clzz =~ m<$firstcomp/(.*)>) {
my $remain = $1;
if ($path =~ m<^(|.*/)\.\./+$>) {
$path = $1;
$clzz = $remain;
}
}
}
}
}
push @deplist, "$path$clzz.java";
next clazz;
}
}
}
if (@deplist) {
print DEPFILE "$clazz: " . join (" ", @deplist) . "\n";
}
}
}
close DEPFILE;

@ -1,173 +0,0 @@
#!/usr/bin/perl
#
# jcpp 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 is a program to allow conditional compiled code in java files.
# The key idea is, not to run the file always through the
# preprocessor, but to modify the java files directly and make use of
# comments.
#
# The comments all have the form /// to distinguish them from normal
# comments. You should not use such comments yourself.
#
# Usage is simple: jcpp -Ddefine1 -Ddefine2 first.java second.java
# The files should contain comments of the form
#
# ///#ifdef JDK12
# jdk1.2 code
# ///#else
# jdk1.1 code
# ///#endif
#
# After running jcpp the false branch is commented out. If the true
# branch was commented out it will get commented in.
my @files;
my %defs;
for (@ARGV) {
if ($_ =~ /^-D([^=]*)$/) {
$defs{$1} = 1;
} elsif ($_ =~ /^-D([^=]*)=([^=]*)$/) {
$defs{$1} = $2;
} else {
push @files, $_;
}
}
for (@files) {
# Number of nested #if directives. Initially 0, will be increased
# on every #if directive and decreased on every #endif directive.
my $level = 0;
# The number of the outermost level, whose #if directive was
# false. This is 0, if there wasn't an false #if directive, yet.
# As long as it is != 0, we comment every line, and ignore
# directives except for increasing/decreasing $level.
my $falselevel = 0;
# Tells if an error occured and the transformation shouldn't
# be done.
my $error = 0;
my $changes = 0;
my $file = $_;
open OLD, "<$file" or do {
print STDERR "Can't open file $file\n";
next;
};
open NEW, ">$file.tmp" or do {
print STDERR "Can't open tmp file $file.tmp\n";
next;
};
my $linenr = 0;
LINE:
while (<OLD>) {
$linenr++;
if (m'^///#') {
# This is a directive. First we print it out.
print NEW $_;
if (m'^///# *if') {
$level++;
if (m'^///# *ifdef (\S*)$') {
# If there was an outer false #if directive, we ignore the
# condition.
next LINE if ($falselevel);
my $label=$1;
# An ifdef directive, look if -D is defined.
$falselevel = $level
unless (defined $defs{$label});
} elsif (m'^///# *ifndef (\S*)$') {
# If there was an outer false #if directive, we ignore the
# condition.
next LINE if ($falselevel);
my $label=$1;
# An ifndef directive, look if -D is defined
$falselevel = $level
if (defined $defs{$label});
}
} elsif (m'^///# *else') {
# An else directive. We switch from true to false and
# if level is falselevel we switch from false to true
if ($level == 0) {
# An else outside of any directives; warn.
print STDERR "$file: $linenr: unmatched $_";
$error = 1;
} elsif ($falselevel == $level) {
$falselevel = 0;
} elsif ($falselevel == 0) {
$falselevel = $level;
}
} elsif (m'^///# *endif') {
# set $falselevel to 0, if the false branch is over now.
$falselevel = 0 if ($falselevel == $level);
# decrease level.
if ($level == 0) {
print STDERR "$file: $linenr: unmatched $_";
$error = 1;
} else {
$level--;
}
} else {
print STDERR "$file: $linenr: ignoring unknown directive $_";
$error = 1;
}
} elsif (m'^///(.*)') {
$line = $1;
if ($falselevel == 0 && $level > 0) {
# remove comments in true branch, but not in outermost level.
print NEW "$line\n";
$changes = 1;
} else {
# print out the full line with comments:
print NEW $_;
}
} else {
if ($falselevel != 0) {
# add comments in false branch
print NEW "///$_";
$changes = 1;
} else {
print NEW $_;
}
}
}
if ($level != 0 || $falselevel != 0) {
# something got wrong
print STDERR "$file: unmatched directives: level $level, ".
"falselevel $falselevel\n";
$error = 1;
}
if ($error == 0) {
if ($changes == 0) {
unlink "$file.tmp";
} else {
(rename "$file", "$file.orig"
and rename "$file.tmp", "$file")
or print STDERR "$file: Couldn't rename files.\n";
}
} else {
print STDERR "$file: errors occured, file not transformed.\n";
}
}
Loading…
Cancel
Save