lots of bugs fixed

git-svn-id: https://svn.code.sf.net/p/jode/code/branches/stable@1052 379699f6-c40d-0410-875b-85095c16579e
stable
jochen 25 years ago
parent 4ae713d9a6
commit 20d93c44fe
  1. 6
      jode/jode/obfuscator/ClassBundle.java
  2. 164
      jode/jode/obfuscator/ClassIdentifier.java
  3. 16
      jode/jode/obfuscator/ConstantAnalyzer.java
  4. 2
      jode/jode/obfuscator/FieldIdentifier.java
  5. 5
      jode/jode/obfuscator/Identifier.java
  6. 2
      jode/jode/obfuscator/Main.java
  7. 19
      jode/jode/obfuscator/ModifierMatcher.java
  8. 106
      jode/jode/obfuscator/SimpleAnalyzer.java

@ -139,8 +139,10 @@ public class ClassBundle {
analyze();
}
public void analyzeIdentifier(Identifier i) {
toAnalyze.add(i);
public void analyzeIdentifier(Identifier ident) {
if (ident == null)
throw new NullPointerException();
toAnalyze.add(ident);
}
public void analyze() {

@ -40,6 +40,7 @@ import jode.util.Iterator;
import jode.util.List;
import jode.util.LinkedList;
import jode.util.Map;
import jode.util.UnsupportedOperationException;
///#endif
import java.lang.reflect.Modifier;
@ -57,7 +58,6 @@ public class ClassIdentifier extends Identifier {
String superName;
String[] ifaceNames;
List identifiers;
List fieldIdents, methodIdents;
List knownSubClasses = new LinkedList();
List virtualReachables = new LinkedList();
@ -82,6 +82,7 @@ public class ClassIdentifier extends Identifier {
String fullName = getFullName() + ".";
for (Iterator i = getChilds(); i.hasNext(); ) {
Identifier ident = (Identifier) i.next();
System.err.println("checking "+ident);
if (wildcard.matches(fullName + ident.getName())
|| wildcard.matches(fullName + ident.getName()
+ "." +ident.getType())) {
@ -94,8 +95,24 @@ public class ClassIdentifier extends Identifier {
}
}
public void preserveIdentifier(String name, String typeSig) {
preserveMatchingIdentifier(new WildCard(name+"."+typeSig));
private FieldIdentifier findField(String name, String typeSig) {
for (Iterator i = fieldIdents.iterator(); i.hasNext(); ) {
FieldIdentifier ident = (FieldIdentifier) i.next();
if (ident.getName().equals(name)
&& ident.getType().equals(typeSig))
return ident;
}
return null;
}
private MethodIdentifier findMethod(String name, String typeSig) {
for (Iterator i = methodIdents.iterator(); i.hasNext(); ) {
MethodIdentifier ident = (MethodIdentifier) i.next();
if (ident.getName().equals(name)
&& ident.getType().equals(typeSig))
return ident;
}
return null;
}
public void reachableIdentifier(String name, String typeSig,
@ -109,6 +126,20 @@ public class ClassIdentifier extends Identifier {
found = true;
}
}
if (!found) {
// This means that the method is inherited from parent and
// must be marked as reachable there, (but not virtual).
// Consider following:
// A method in Collection and AbstractCollection is not reachable
// but it is reachable in Set and not implemented in AbstractSet
// In that case the method must be marked reachable in
// AbstractCollection.
ClassIdentifier superIdent = Main.getClassBundle()
.getClassIdentifier(info.getSuperclass().getName());
if (superIdent != null)
superIdent.reachableIdentifier(name, typeSig, false);
}
if (isVirtual) {
for (Iterator i = knownSubClasses.iterator(); i.hasNext(); )
((ClassIdentifier)i.next())
@ -117,13 +148,13 @@ public class ClassIdentifier extends Identifier {
}
}
public void chainIdentifier(Identifier chainIdent) {
public void chainMethodIdentifier(Identifier chainIdent) {
String name = chainIdent.getName();
String typeSig = chainIdent.getType();
for (Iterator i = getChilds(); i.hasNext(); ) {
for (Iterator i = methodIdents.iterator(); i.hasNext(); ) {
Identifier ident = (Identifier) i.next();
if (ident.getName().equals(ident.getName())
&& (ident.getType().equals(typeSig)))
if (ident.getName().equals(name)
&& ident.getType().equals(typeSig))
chainIdent.addShadow(ident);
}
}
@ -246,33 +277,28 @@ public class ClassIdentifier extends Identifier {
* a compatible class.
*/
public void preserveSerializable() {
preserveIdentifier("writeObject", "(Ljava.io.ObjectOutputStream)V");
preserveIdentifier("readObject", "(Ljava.io.ObjectOutputStream)V");
Identifier method
= findMethod("writeObject", "(Ljava.io.ObjectOutputStream)V");
if (method != null)
method.setPreserved();
method = findMethod("readObject", "(Ljava.io.ObjectInputStream)V");
if (method != null)
method.setPreserved();
if ((Main.options & Main.OPTION_PRESERVESERIAL) != 0) {
setPreserved();
boolean hasSerialUID = false;
for (Iterator i = getFieldIdents().iterator(); i.hasNext(); ) {
Identifier ident = (Identifier) i.next();
if ("serialVersionUID".equals(ident.getName())
&& "J".equals(ident.getType())) {
ident.setReachable();
ident.setPreserved();
hasSerialUID = true;
break;
}
}
if (!hasSerialUID) {
Identifier UIDident = findField("serialVersionUID", "J");
if (UIDident == null) {
/* add a field serializableVersionUID if not existent */
long serialVersion = calcSerialVersionUID();
FieldInfo UIDField = new FieldInfo
(info, "serialVersionUID", "J",
Modifier.PUBLIC | Modifier.STATIC | Modifier.FINAL);
UIDField.setConstant(new Long(serialVersion));
FieldIdentifier fident = new FieldIdentifier(this, UIDField);
fident.setPreserved();
fident.setReachable();
fieldIdents.add(fident);
UIDident = new FieldIdentifier(this, UIDField);
fieldIdents.add(UIDident);
}
UIDident.setReachable();
UIDident.setPreserved();
for (Iterator i=getFieldIdents().iterator(); i.hasNext(); ) {
FieldIdentifier ident = (FieldIdentifier) i.next();
if ((ident.info.getModifiers()
@ -358,7 +384,7 @@ public class ClassIdentifier extends Identifier {
| Modifier.FINAL) & modif) == 0
&& !(mid.getName().equals("<init>"))) {
// chain the preserved/same name lists.
chainIdentifier(mid);
chainMethodIdentifier(mid);
}
}
} else {
@ -371,8 +397,10 @@ public class ClassIdentifier extends Identifier {
if (((Modifier.PRIVATE | Modifier.STATIC | Modifier.FINAL)
& modif) == 0
&& !topmethods[i].getName().equals("<init>")) {
preserveIdentifier
Identifier method = findMethod
(topmethods[i].getName(), topmethods[i].getType());
if (method != null)
method.setPreserved();
}
}
}
@ -393,10 +421,8 @@ public class ClassIdentifier extends Identifier {
Collections.shuffle(Arrays.asList(finfos), rand);
Collections.shuffle(Arrays.asList(minfos), rand);
}
identifiers = new ArrayList(finfos.length + minfos.length);
fieldIdents = identifiers.subList(0, 0);
methodIdents = identifiers.subList(0, 0);
identifiers = Collections.unmodifiableList(identifiers);
fieldIdents = new ArrayList(finfos.length);
methodIdents = new ArrayList(minfos.length);
for (int i=0; i< finfos.length; i++)
fieldIdents.add(new FieldIdentifier(this, finfos[i]));
@ -665,36 +691,30 @@ public class ClassIdentifier extends Identifier {
transformSuperIfaces();
transformInnerClasses();
int newFieldCount = 0, newMethodCount = 0;
if ((Main.stripping & Main.STRIP_UNREACH) != 0) {
for (Iterator i = fieldIdents.iterator(); i.hasNext(); ) {
Identifier ident = (Identifier) i.next();
if (!ident.isReachable())
i.remove();
}
for (Iterator i = methodIdents.iterator(); i.hasNext(); ) {
Identifier ident = (Identifier) i.next();
if (!ident.isReachable())
i.remove();
}
}
FieldInfo[] newFields = new FieldInfo[fieldIdents.size()];
MethodInfo[] newMethods = new MethodInfo[methodIdents.size()];
newFieldCount = newMethodCount = 0;
Collection newFields = new ArrayList(fieldIdents.size());
Collection newMethods = new ArrayList(methodIdents.size());
for (Iterator i = fieldIdents.iterator(); i.hasNext(); ) {
FieldIdentifier ident = (FieldIdentifier)i.next();
ident.doTransformations();
newFields[newFieldCount++] = ident.info;
if ((Main.stripping & Main.STRIP_UNREACH) == 0
|| ident.isReachable()) {
ident.doTransformations();
newFields.add(ident.info);
}
}
for (Iterator i = methodIdents.iterator(); i.hasNext(); ) {
MethodIdentifier ident = (MethodIdentifier)i.next();
ident.doTransformations();
newMethods[newMethodCount++] = ident.info;
if ((Main.stripping & Main.STRIP_UNREACH) == 0
|| ident.isReachable()) {
ident.doTransformations();
newMethods.add(ident.info);
}
}
info.setFields(newFields);
info.setMethods(newMethods);
info.setFields((FieldInfo[]) newFields.toArray
(new FieldInfo[newFields.size()]));
info.setMethods((MethodInfo[]) newMethods.toArray
(new MethodInfo[newMethods.size()]));
}
public void storeClass(DataOutputStream out) throws IOException {
@ -702,7 +722,7 @@ public class ClassIdentifier extends Identifier {
GlobalOptions.err.println("Writing "+this);
info.write(out);
info = null;
identifiers = null;
fieldIdents = methodIdents = null;
}
public Identifier getParent() {
@ -746,7 +766,28 @@ public class ClassIdentifier extends Identifier {
}
public Iterator getChilds() {
return identifiers.iterator();
final Iterator fieldIter = fieldIdents.iterator();
final Iterator methodIter = methodIdents.iterator();
return new Iterator() {
boolean fieldsNext = fieldIter.hasNext();
public boolean hasNext() {
return fieldsNext ? true : methodIter.hasNext();
}
public Object next() {
if (fieldsNext) {
Object result = fieldIter.next();
fieldsNext = fieldIter.hasNext();
return result;
}
return methodIter.next();
}
public void remove() {
throw new UnsupportedOperationException();
}
};
}
public String toString() {
@ -754,24 +795,13 @@ public class ClassIdentifier extends Identifier {
}
public Identifier getIdentifier(String fieldName, String typeSig) {
for (Iterator i = identifiers.iterator(); i.hasNext(); ) {
for (Iterator i = getChilds(); i.hasNext(); ) {
Identifier ident = (Identifier) i.next();
if (ident.getName().equals(fieldName)
&& ident.getType().startsWith(typeSig))
return ident;
}
for (int i=0; i < ifaceNames.length; i++) {
ClassIdentifier ifaceident = Main.getClassBundle()
.getClassIdentifier(ifaceNames[i]);
if (ifaceident != null) {
Identifier ident
= ifaceident.getIdentifier(fieldName, typeSig);
if (ident != null)
return ident;
}
}
if (superName != null) {
ClassIdentifier superident = Main.getClassBundle()
.getClassIdentifier(superName);

@ -448,10 +448,17 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
(clName.substring(1, clName.length()-1)
.replace('/','.'));
}
while (clazz != null
&& clazz.findMethod(ref.getName(),
ref.getType()) == null)
clazz = clazz.getSuperclass();
if (instr.opcode >= opc_invokevirtual) {
while (clazz != null
&& clazz.findMethod(ref.getName(),
ref.getType()) == null)
clazz = clazz.getSuperclass();
} else {
while (clazz != null
&& clazz.findField(ref.getName(),
ref.getType()) == null)
clazz = clazz.getSuperclass();
}
if (clazz == null) {
GlobalOptions.err.println("WARNING: Can't find reference: "
@ -1371,6 +1378,7 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
}
public void analyzeCode(MethodIdentifier listener, BytecodeInfo bytecode) {
this.listener = listener;
this.bytecode = bytecode;
working = true;
if (constInfos == null)

@ -111,6 +111,8 @@ public class FieldIdentifier extends Identifier{
}
public void addFieldListener(Identifier ident) {
if (ident == null)
throw new NullPointerException();
if (!fieldListeners.contains(ident))
fieldListeners.add(ident);
}

@ -179,14 +179,13 @@ public abstract class Identifier {
if (GlobalOptions.verboseLevel > 4)
GlobalOptions.err.println(toString() + " is preserved");
} else {
Identifier rep = getRepresentative();
if (rep.wasAliased)
return;
rep.wasAliased = true;
// set alias to empty string, so it won't conflict!
alias = "";
rep.alias = "";
String newAlias = null;
next_alias:
for (;;) {
@ -198,7 +197,7 @@ public abstract class Identifier {
ptr = ptr.right;
}
setAlias(newAlias.toString());
return;
break;
}
}
for (Iterator i = getChilds(); i.hasNext(); )

@ -184,7 +184,7 @@ public class Main {
}
public static CodeAnalyzer createCodeAnalyzer() {
return new ConstantAnalyzer() /*XXX*/;
return new SimpleAnalyzer() /*XXX*/;
}
static CodeTransformer[] codeTransformers = {

@ -107,7 +107,7 @@ public class ModifierMatcher implements IdentifierMatcher, Cloneable {
if (implies(and, xor, andMasks[i], xorMasks[i]))
continue next_i;
for (int j=0; j<andMasks.length; j++) {
for (int j=0; j < andMasks.length; j++) {
if (j != i
&& implies(and | andMasks[j], xor | xorMasks[j],
andMasks[i], xorMasks[i]))
@ -120,12 +120,21 @@ public class ModifierMatcher implements IdentifierMatcher, Cloneable {
int[] ands = new int[newCount];
int[] xors = new int[newCount];
int index = 0;
next_i:
for (int i=0; i < newCount; i++) {
int bothAnd = andMasks[i] & and;
if ((xorMasks[i] & bothAnd) == (and & bothAnd)) {
ands[index++] = andMasks[i] | and;
xors[index++] = xorMasks[i] | xor;
if (implies(and, xor, andMasks[i], xorMasks[i]))
continue next_i;
for (int j=0; j < andMasks.length; j++) {
if (j != i
&& implies(and | andMasks[j], xor | xorMasks[j],
andMasks[i], xorMasks[i]))
continue next_i;
}
ands[index] = andMasks[i] | and;
xors[index] = xorMasks[i] | xor;
index++;
}
return new ModifierMatcher(ands, xors);
}

@ -18,10 +18,69 @@
*/
package jode.obfuscator;
import jode.bytecode.*;
import jode.bytecode.Handler;
import jode.bytecode.Opcodes;
import jode.bytecode.ClassInfo;
import jode.bytecode.BytecodeInfo;
import jode.bytecode.Instruction;
import jode.bytecode.Reference;
import jode.GlobalOptions;
import jode.type.Type;
public class SimpleAnalyzer implements CodeAnalyzer, Opcodes {
public Identifier canonizeReference(Instruction instr) {
Reference ref = (Reference) instr.objData;
Identifier ident = Main.getClassBundle().getIdentifier(ref);
String clName = ref.getClazz();
String realClazzName;
if (ident != null) {
ClassIdentifier clazz = (ClassIdentifier)ident.getParent();
realClazzName = "L" + (clazz.getFullName()
.replace('.', '/')) + ";";
} else {
/* We have to look at the ClassInfo's instead, to
* point to the right method.
*/
ClassInfo clazz;
if (clName.charAt(0) == '[') {
/* Arrays don't define new methods (well clone(),
* but that can be ignored).
*/
clazz = ClassInfo.javaLangObject;
} else {
clazz = ClassInfo.forName
(clName.substring(1, clName.length()-1)
.replace('/','.'));
}
if (instr.opcode >= opc_invokevirtual) {
while (clazz != null
&& clazz.findMethod(ref.getName(),
ref.getType()) == null)
clazz = clazz.getSuperclass();
} else {
while (clazz != null
&& clazz.findField(ref.getName(),
ref.getType()) == null)
clazz = clazz.getSuperclass();
}
if (clazz == null) {
GlobalOptions.err.println("WARNING: Can't find reference: "
+ref);
realClazzName = clName;
} else
realClazzName = "L" + clazz.getName().replace('.', '/') + ";";
}
if (!realClazzName.equals(ref.getClazz())) {
ref = Reference.getReference(realClazzName,
ref.getName(), ref.getType());
instr.objData = ref;
}
return ident;
}
/**
* Reads the opcodes out of the code info and determine its
* references
@ -54,52 +113,21 @@ public class SimpleAnalyzer implements CodeAnalyzer, Opcodes {
/* fall through */
case opc_getstatic:
case opc_getfield: {
Reference ref = (Reference) instr.objData;
Identifier ident = Main.getClassBundle().getIdentifier(ref);
String clName = ref.getClazz();
String realClazzName;
Identifier ident = canonizeReference(instr);
if (ident != null) {
ClassIdentifier clazz = (ClassIdentifier)ident.getParent();
realClazzName = "L" + (clazz.getFullName()
.replace('.', '/')) + ";";
if (instr.opcode == opc_putstatic
|| instr.opcode == opc_putfield) {
FieldIdentifier fi = (FieldIdentifier) ident;
if (fi != null && !fi.isNotConstant())
fi.setNotConstant();
} else if (instr.opcode == opc_invokevirtual
|| instr.opcode == opc_invokeinterface) {
((ClassIdentifier) ident.getParent())
.reachableIdentifier(ident.getName(),
ident.getType(), true);
} else {
clazz.reachableIdentifier
(ref.getName(), ref.getType(),
instr.opcode == opc_invokevirtual
|| instr.opcode == opc_invokeinterface);
ident.setReachable();
}
} else {
/* We have to look at the ClassInfo's instead, to
* point to the right method.
*/
ClassInfo clazz;
if (clName.charAt(0) == '[') {
/* Arrays don't define new methods (well clone(),
* but that can be ignored).
*/
clazz = ClassInfo.javaLangObject;
} else {
clazz = ClassInfo.forName
(clName.substring(1, clName.length()-1)
.replace('/','.'));
}
while (clazz != null
&& clazz.findMethod(ref.getName(),
ref.getType()) == null)
clazz = clazz.getSuperclass();
realClazzName = (clazz != null) ? clName
: "L" + clazz.getName().replace('.', '/') + ";";
}
if (!realClazzName.equals(ref.getClazz())) {
ref = Reference.getReference(realClazzName,
ref.getName(), ref.getType());
instr.objData = ref;
}
break;
}

Loading…
Cancel
Save