From 20d93c44fe2291354afe925272ea2e63922ee4c6 Mon Sep 17 00:00:00 2001 From: jochen Date: Thu, 8 Jul 1999 13:53:59 +0000 Subject: [PATCH] lots of bugs fixed git-svn-id: https://svn.code.sf.net/p/jode/code/branches/stable@1052 379699f6-c40d-0410-875b-85095c16579e --- jode/jode/obfuscator/ClassBundle.java | 6 +- jode/jode/obfuscator/ClassIdentifier.java | 164 ++++++++++++--------- jode/jode/obfuscator/ConstantAnalyzer.java | 16 +- jode/jode/obfuscator/FieldIdentifier.java | 2 + jode/jode/obfuscator/Identifier.java | 5 +- jode/jode/obfuscator/Main.java | 2 +- jode/jode/obfuscator/ModifierMatcher.java | 19 ++- jode/jode/obfuscator/SimpleAnalyzer.java | 106 ++++++++----- 8 files changed, 199 insertions(+), 121 deletions(-) diff --git a/jode/jode/obfuscator/ClassBundle.java b/jode/jode/obfuscator/ClassBundle.java index 20c087a..013d19b 100644 --- a/jode/jode/obfuscator/ClassBundle.java +++ b/jode/jode/obfuscator/ClassBundle.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() { diff --git a/jode/jode/obfuscator/ClassIdentifier.java b/jode/jode/obfuscator/ClassIdentifier.java index 0885c80..86f659b 100644 --- a/jode/jode/obfuscator/ClassIdentifier.java +++ b/jode/jode/obfuscator/ClassIdentifier.java @@ -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(""))) { // 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("")) { - 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); diff --git a/jode/jode/obfuscator/ConstantAnalyzer.java b/jode/jode/obfuscator/ConstantAnalyzer.java index 27d5619..9889ed5 100644 --- a/jode/jode/obfuscator/ConstantAnalyzer.java +++ b/jode/jode/obfuscator/ConstantAnalyzer.java @@ -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) diff --git a/jode/jode/obfuscator/FieldIdentifier.java b/jode/jode/obfuscator/FieldIdentifier.java index dd881ae..cae8bfc 100644 --- a/jode/jode/obfuscator/FieldIdentifier.java +++ b/jode/jode/obfuscator/FieldIdentifier.java @@ -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); } diff --git a/jode/jode/obfuscator/Identifier.java b/jode/jode/obfuscator/Identifier.java index c92a6ea..95e58a3 100644 --- a/jode/jode/obfuscator/Identifier.java +++ b/jode/jode/obfuscator/Identifier.java @@ -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(); ) diff --git a/jode/jode/obfuscator/Main.java b/jode/jode/obfuscator/Main.java index 861c19f..a9b88d4 100644 --- a/jode/jode/obfuscator/Main.java +++ b/jode/jode/obfuscator/Main.java @@ -184,7 +184,7 @@ public class Main { } public static CodeAnalyzer createCodeAnalyzer() { - return new ConstantAnalyzer() /*XXX*/; + return new SimpleAnalyzer() /*XXX*/; } static CodeTransformer[] codeTransformers = { diff --git a/jode/jode/obfuscator/ModifierMatcher.java b/jode/jode/obfuscator/ModifierMatcher.java index 1119c09..806b863 100644 --- a/jode/jode/obfuscator/ModifierMatcher.java +++ b/jode/jode/obfuscator/ModifierMatcher.java @@ -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= 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; }