git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@246 379699f6-c40d-0410-875b-85095c16579estable
parent
9ce9535622
commit
a38890be6a
@ -0,0 +1,40 @@ |
|||||||
|
/* |
||||||
|
* ClassFieldOperator (c) 1998 Jochen Hoenicke |
||||||
|
* |
||||||
|
* You may distribute under the terms of the GNU General Public License. |
||||||
|
* |
||||||
|
* IN NO EVENT SHALL JOCHEN HOENICKE BE LIABLE TO ANY PARTY FOR DIRECT, |
||||||
|
* INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF |
||||||
|
* THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF JOCHEN HOENICKE |
||||||
|
* HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
* |
||||||
|
* JOCHEN HOENICKE SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT |
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A |
||||||
|
* PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" |
||||||
|
* BASIS, AND JOCHEN HOENICKE HAS NO OBLIGATION TO PROVIDE MAINTENANCE, |
||||||
|
* SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. |
||||||
|
* |
||||||
|
* $Id$ |
||||||
|
*/ |
||||||
|
|
||||||
|
package jode.decompiler; |
||||||
|
import jode.Type; |
||||||
|
import jode.CodeAnalyzer; |
||||||
|
|
||||||
|
public class ClassFieldOperator extends NoArgOperator { |
||||||
|
Type classType; |
||||||
|
|
||||||
|
public ClassFieldOperator(Type classType) { |
||||||
|
super(Type.tJavaLangClass); |
||||||
|
this.classType = classType; |
||||||
|
classType.useType(); |
||||||
|
} |
||||||
|
|
||||||
|
public int getPriority() { |
||||||
|
return 950; |
||||||
|
} |
||||||
|
|
||||||
|
public String toString(String[] operands) { |
||||||
|
return classType.toString() + ".class"; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,391 @@ |
|||||||
|
/* |
||||||
|
* ClassIdentifier (c) 1998 Jochen Hoenicke |
||||||
|
* |
||||||
|
* You may distribute under the terms of the GNU General Public License. |
||||||
|
* |
||||||
|
* IN NO EVENT SHALL JOCHEN HOENICKE BE LIABLE TO ANY PARTY FOR DIRECT, |
||||||
|
* INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF |
||||||
|
* THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF JOCHEN HOENICKE |
||||||
|
* HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
* |
||||||
|
* JOCHEN HOENICKE SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT |
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A |
||||||
|
* PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" |
||||||
|
* BASIS, AND JOCHEN HOENICKE HAS NO OBLIGATION TO PROVIDE MAINTENANCE, |
||||||
|
* SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. |
||||||
|
* |
||||||
|
* $Id$ |
||||||
|
*/ |
||||||
|
|
||||||
|
package jode.obfuscator; |
||||||
|
import jode.Obfuscator; |
||||||
|
import jode.bytecode.ClassInfo; |
||||||
|
import jode.bytecode.FieldInfo; |
||||||
|
import jode.bytecode.MethodInfo; |
||||||
|
import java.lang.reflect.Modifier; |
||||||
|
import java.util.*; |
||||||
|
import java.io.*; |
||||||
|
|
||||||
|
public class ClassIdentifier extends Identifier { |
||||||
|
ClassBundle bundle; |
||||||
|
PackageIdentifier pack; |
||||||
|
String name; |
||||||
|
ClassInfo info; |
||||||
|
|
||||||
|
int preserveRule; |
||||||
|
Identifier[] identifiers; |
||||||
|
Vector knownSubClasses = new Vector(); |
||||||
|
Vector virtualReachables = new Vector(); |
||||||
|
|
||||||
|
public ClassIdentifier(ClassBundle bundle, PackageIdentifier pack, |
||||||
|
String name, ClassInfo info) { |
||||||
|
super(name); |
||||||
|
this.bundle = bundle; |
||||||
|
this.pack = pack; |
||||||
|
this.name = name; |
||||||
|
this.info = info; |
||||||
|
|
||||||
|
preserveRule = bundle.preserveRule; |
||||||
|
if ((preserveRule & (info.getModifiers() ^ Modifier.PRIVATE)) != 0) { |
||||||
|
setReachable(); |
||||||
|
setPreserved(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void addSubClass(ClassIdentifier ci) { |
||||||
|
knownSubClasses.addElement(ci); |
||||||
|
Enumeration enum = virtualReachables.elements(); |
||||||
|
while (enum.hasMoreElements()) { |
||||||
|
String[] method = (String[]) enum.nextElement(); |
||||||
|
ci.reachableIdentifier(method[0], method[1], true); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void preserveIdentifier(String name, String typeSig) { |
||||||
|
for (int i=0; i< identifiers.length; i++) { |
||||||
|
if (identifiers[i].getName().equals(name) |
||||||
|
&& (typeSig == null |
||||||
|
|| identifiers[i] .getType().equals(typeSig))) |
||||||
|
identifiers[i].setPreserved(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void reachableIdentifier(String name, String typeSig, |
||||||
|
boolean isVirtual) { |
||||||
|
for (int i=0; i < identifiers.length; i++) { |
||||||
|
if (identifiers[i].getName().equals(name) |
||||||
|
&& (typeSig == null |
||||||
|
|| identifiers[i] .getType().equals(typeSig))) |
||||||
|
identifiers[i].setReachable(); |
||||||
|
} |
||||||
|
if (isVirtual) { |
||||||
|
Enumeration enum = knownSubClasses.elements(); |
||||||
|
while (enum.hasMoreElements()) |
||||||
|
((ClassIdentifier)enum.nextElement()) |
||||||
|
.reachableIdentifier(name, typeSig, isVirtual); |
||||||
|
virtualReachables.addElement |
||||||
|
(new String[] { name, typeSig }); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void chainIdentifier(Identifier ident) { |
||||||
|
String name = ident.getName(); |
||||||
|
String typeSig = ident.getType(); |
||||||
|
for (int i=0; i< identifiers.length; i++) { |
||||||
|
if (identifiers[i].getName().equals(ident.getName()) |
||||||
|
&& (identifiers[i].getType().equals(typeSig))) |
||||||
|
ident.addShadow(identifiers[i]); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Preserve all fields, that are necessary, to serialize |
||||||
|
* a compatible class. |
||||||
|
*/ |
||||||
|
public void preserveSerializable() { |
||||||
|
/*XXX*/ |
||||||
|
/* add a field serializableVersionUID if not existent */ |
||||||
|
} |
||||||
|
|
||||||
|
public void initSuperClasses(ClassInfo superclass) { |
||||||
|
while (superclass != null) { |
||||||
|
if (superclass.getName().equals("java.lang.Serializable")) |
||||||
|
preserveSerializable(); |
||||||
|
|
||||||
|
ClassIdentifier superident = (ClassIdentifier) |
||||||
|
bundle.getIdentifier(superclass.getName()); |
||||||
|
if (superident != null) { |
||||||
|
for (int i=0; i < superident.identifiers.length; i++) |
||||||
|
if (superident.identifiers[i] |
||||||
|
instanceof MethodIdentifier) { |
||||||
|
MethodIdentifier mid = (MethodIdentifier) |
||||||
|
superident.identifiers[i]; |
||||||
|
// all virtual methods in superclass must be chained.
|
||||||
|
int modif = mid.info.getModifiers(); |
||||||
|
if (((Modifier.PRIVATE |
||||||
|
| Modifier.STATIC |
||||||
|
| Modifier.FINAL) & modif) == 0 |
||||||
|
&& !(mid.getName().equals("<init>"))) { |
||||||
|
// chain the preserved/same name lists.
|
||||||
|
chainIdentifier(superident.identifiers[i]); |
||||||
|
} |
||||||
|
} |
||||||
|
} else { |
||||||
|
// all methods and fields in superclass are preserved!
|
||||||
|
MethodInfo[] topmethods = superclass.getMethods(); |
||||||
|
FieldInfo[] topfields = superclass.getFields(); |
||||||
|
for (int i=0; i< topmethods.length; i++) { |
||||||
|
// all virtual methods in superclass may be
|
||||||
|
// virtually reachable
|
||||||
|
int modif = topmethods[i].getModifiers(); |
||||||
|
if (((Modifier.PRIVATE | Modifier.STATIC | Modifier.FINAL) |
||||||
|
& modif) == 0 |
||||||
|
&& !topmethods[i].getName().equals("<init>")) { |
||||||
|
reachableIdentifier |
||||||
|
(topmethods[i].getName(), |
||||||
|
topmethods[i].getType().getTypeSignature(), |
||||||
|
true); |
||||||
|
preserveIdentifier |
||||||
|
(topmethods[i].getName(), |
||||||
|
topmethods[i].getType().getTypeSignature()); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
ClassInfo[] ifaces = superclass.getInterfaces(); |
||||||
|
for (int i=0; i < ifaces.length; i++) |
||||||
|
initSuperClasses(ifaces[i]); |
||||||
|
superclass = superclass.getSuperclass(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void setSingleReachable() { |
||||||
|
info.loadInfo(info.FULLINFO); |
||||||
|
|
||||||
|
if (Obfuscator.isVerbose) |
||||||
|
Obfuscator.err.println(this); |
||||||
|
|
||||||
|
FieldInfo[] finfos = info.getFields(); |
||||||
|
MethodInfo[] minfos = info.getMethods(); |
||||||
|
identifiers = new Identifier[finfos.length + minfos.length]; |
||||||
|
for (int i=0; i< finfos.length; i++) { |
||||||
|
identifiers[i] = new FieldIdentifier(this, finfos[i]); |
||||||
|
if ((preserveRule & (finfos[i].getModifiers() ^ Modifier.PRIVATE)) |
||||||
|
!= 0) { |
||||||
|
identifiers[i].setReachable(); |
||||||
|
identifiers[i].setPreserved(); |
||||||
|
} |
||||||
|
} |
||||||
|
for (int i=0; i< minfos.length; i++) { |
||||||
|
identifiers[finfos.length + i] |
||||||
|
= new MethodIdentifier(this, minfos[i]); |
||||||
|
if ((preserveRule & (minfos[i].getModifiers() ^ Modifier.PRIVATE)) |
||||||
|
!= 0) { |
||||||
|
identifiers[i].setReachable(); |
||||||
|
identifiers[i].setPreserved(); |
||||||
|
} |
||||||
|
if (identifiers[i].getName().equals("<init>")) |
||||||
|
identifiers[i].setPreserved(); |
||||||
|
} |
||||||
|
|
||||||
|
ClassInfo[] ifaces = info.getInterfaces(); |
||||||
|
for (int i=0; i < ifaces.length; i++) { |
||||||
|
ClassIdentifier ifaceident = (ClassIdentifier) |
||||||
|
bundle.getIdentifier(ifaces[i].getName()); |
||||||
|
if (ifaceident != null) { |
||||||
|
ifaceident.setReachable(); |
||||||
|
ifaceident.addSubClass(this); |
||||||
|
} |
||||||
|
initSuperClasses(ifaces[i]); |
||||||
|
} |
||||||
|
|
||||||
|
if (info.getSuperclass() != null) { |
||||||
|
ClassIdentifier superident = (ClassIdentifier) |
||||||
|
bundle.getIdentifier(info.getSuperclass().getName()); |
||||||
|
if (superident != null) { |
||||||
|
superident.setReachable(); |
||||||
|
superident.addSubClass(this); |
||||||
|
} |
||||||
|
initSuperClasses(info.getSuperclass()); |
||||||
|
} |
||||||
|
preserveIdentifier("<clinit>", "()V"); |
||||||
|
} |
||||||
|
|
||||||
|
public void strip() { |
||||||
|
int newLength = 0; |
||||||
|
for (int i=0; i < identifiers.length; i++) { |
||||||
|
if (identifiers[i].isReachable()) |
||||||
|
newLength++; |
||||||
|
else { |
||||||
|
if (Obfuscator.isDebugging) |
||||||
|
Obfuscator.err.println(identifiers[i].toString() |
||||||
|
+ " is stripped"); |
||||||
|
} |
||||||
|
} |
||||||
|
Identifier[] newIdents = new Identifier[newLength]; |
||||||
|
int index = 0; |
||||||
|
for (int i=0; i < identifiers.length; i++) { |
||||||
|
if (identifiers[i].isReachable()) |
||||||
|
newIdents[index++] = identifiers[i]; |
||||||
|
} |
||||||
|
identifiers = newIdents; |
||||||
|
} |
||||||
|
|
||||||
|
public void buildTable(int renameRule) { |
||||||
|
super.buildTable(renameRule); |
||||||
|
for (int i=0; i < identifiers.length; i++) |
||||||
|
identifiers[i].buildTable(renameRule); |
||||||
|
} |
||||||
|
|
||||||
|
public void writeTable(PrintWriter out) throws IOException { |
||||||
|
if (getName() != getAlias()) |
||||||
|
out.println("" + getFullAlias() + " = " + getName()); |
||||||
|
for (int i=0; i < identifiers.length; i++) |
||||||
|
identifiers[i].writeTable(out); |
||||||
|
} |
||||||
|
|
||||||
|
public void storeClass(OutputStream out) throws IOException { |
||||||
|
/*XXX*/ |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @return the full qualified name, excluding trailing dot. |
||||||
|
*/ |
||||||
|
public String getFullName() { |
||||||
|
return pack.getFullName() + getName(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @return the full qualified alias, excluding trailing dot. |
||||||
|
*/ |
||||||
|
public String getFullAlias() { |
||||||
|
return pack.getFullAlias() + getAlias(); |
||||||
|
} |
||||||
|
|
||||||
|
public String getName() { |
||||||
|
return name; |
||||||
|
} |
||||||
|
|
||||||
|
public String getType() { |
||||||
|
return "Ljava/lang/Class;"; |
||||||
|
} |
||||||
|
|
||||||
|
public String toString() { |
||||||
|
return "ClassIdentifier "+getFullName(); |
||||||
|
} |
||||||
|
|
||||||
|
public static boolean containsField(ClassInfo clazz, String newAlias) { |
||||||
|
FieldInfo[] finfos = clazz.getFields(); |
||||||
|
for (int i=0; i< finfos.length; i++) { |
||||||
|
if (finfos[i].getName().equals(newAlias)) |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
ClassInfo[] ifaces = clazz.getInterfaces(); |
||||||
|
for (int i=0; i < ifaces.length; i++) { |
||||||
|
if (containsField(ifaces[i], newAlias)) |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
if (clazz.getSuperclass() != null) { |
||||||
|
if (containsField(clazz.getSuperclass(), newAlias)) |
||||||
|
return true; |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
public boolean containsField(String newAlias) { |
||||||
|
for (int i=0; i< identifiers.length; i++) { |
||||||
|
if (identifiers[i] instanceof FieldIdentifier |
||||||
|
&& identifiers[i].getAlias().equals(newAlias)) |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
ClassInfo[] ifaces = info.getInterfaces(); |
||||||
|
for (int i=0; i < ifaces.length; i++) { |
||||||
|
ClassIdentifier ifaceident = (ClassIdentifier) |
||||||
|
bundle.getIdentifier(ifaces[i].getName()); |
||||||
|
if (ifaceident != null) { |
||||||
|
if (ifaceident.containsField(newAlias)) |
||||||
|
return true; |
||||||
|
} else { |
||||||
|
if (containsField(ifaces[i], newAlias)) |
||||||
|
return true; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if (info.getSuperclass() != null) { |
||||||
|
ClassIdentifier superident = (ClassIdentifier) |
||||||
|
bundle.getIdentifier(info.getSuperclass().getName()); |
||||||
|
if (superident != null) { |
||||||
|
if (superident.containsField(newAlias)) |
||||||
|
return true; |
||||||
|
} else { |
||||||
|
if (containsField(info.getSuperclass(), newAlias)) |
||||||
|
return true; |
||||||
|
} |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
public static boolean containsMethod(ClassInfo clazz, |
||||||
|
String newAlias, String paramType) { |
||||||
|
MethodInfo[] minfos = clazz.getMethods(); |
||||||
|
for (int i=0; i< minfos.length; i++) { |
||||||
|
if (minfos[i].getName().equals(newAlias) |
||||||
|
&& minfos[i].getType().getTypeSignature() |
||||||
|
.startsWith(paramType)) |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
ClassInfo[] ifaces = clazz.getInterfaces(); |
||||||
|
for (int i=0; i < ifaces.length; i++) { |
||||||
|
if (containsMethod(ifaces[i], newAlias, paramType)) |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
if (clazz.getSuperclass() != null) { |
||||||
|
if (containsMethod(clazz.getSuperclass(), newAlias, paramType)) |
||||||
|
return true; |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
public boolean containsMethod(String newAlias, String paramType) { |
||||||
|
for (int i=0; i< identifiers.length; i++) { |
||||||
|
if (identifiers[i] instanceof MethodIdentifier |
||||||
|
&& identifiers[i].getAlias().equals(newAlias) |
||||||
|
&& identifiers[i].getType().startsWith(paramType)) |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
ClassInfo[] ifaces = info.getInterfaces(); |
||||||
|
for (int i=0; i < ifaces.length; i++) { |
||||||
|
ClassIdentifier ifaceident = (ClassIdentifier) |
||||||
|
bundle.getIdentifier(ifaces[i].getName()); |
||||||
|
if (ifaceident != null) { |
||||||
|
if (ifaceident.containsMethod(newAlias, paramType)) |
||||||
|
return true; |
||||||
|
} else { |
||||||
|
if (containsMethod(ifaces[i], newAlias, paramType)) |
||||||
|
return true; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if (info.getSuperclass() != null) { |
||||||
|
ClassIdentifier superident = (ClassIdentifier) |
||||||
|
bundle.getIdentifier(info.getSuperclass().getName()); |
||||||
|
if (superident != null) { |
||||||
|
if (superident.containsMethod(newAlias, paramType)) |
||||||
|
return true; |
||||||
|
} else { |
||||||
|
if (containsMethod(info.getSuperclass(), newAlias, paramType)) |
||||||
|
return true; |
||||||
|
} |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
public boolean conflicting(String newAlias) { |
||||||
|
return pack.contains(newAlias); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,56 @@ |
|||||||
|
/* |
||||||
|
* jode.obfuscator.FieldIdentifier (c) 1998 Jochen Hoenicke |
||||||
|
* |
||||||
|
* You may distribute under the terms of the GNU General Public License. |
||||||
|
* |
||||||
|
* IN NO EVENT SHALL JOCHEN HOENICKE BE LIABLE TO ANY PARTY FOR DIRECT, |
||||||
|
* INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF |
||||||
|
* THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF JOCHEN HOENICKE |
||||||
|
* HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
* |
||||||
|
* JOCHEN HOENICKE SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT |
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A |
||||||
|
* PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" |
||||||
|
* BASIS, AND JOCHEN HOENICKE HAS NO OBLIGATION TO PROVIDE MAINTENANCE, |
||||||
|
* SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. |
||||||
|
* |
||||||
|
* $Id$ |
||||||
|
*/ |
||||||
|
package jode.obfuscator; |
||||||
|
import jode.bytecode.FieldInfo; |
||||||
|
|
||||||
|
public class FieldIdentifier extends Identifier{ |
||||||
|
FieldInfo info; |
||||||
|
ClassIdentifier clazz; |
||||||
|
|
||||||
|
public FieldIdentifier(ClassIdentifier clazz, FieldInfo info) { |
||||||
|
super(info.getName()); |
||||||
|
this.info = info; |
||||||
|
this.clazz = clazz; |
||||||
|
} |
||||||
|
|
||||||
|
public String getFullName() { |
||||||
|
return clazz.getFullName() + "." + getName(); |
||||||
|
} |
||||||
|
|
||||||
|
public String getFullAlias() { |
||||||
|
return clazz.getFullAlias() + "." + getAlias(); |
||||||
|
} |
||||||
|
|
||||||
|
public String getName() { |
||||||
|
return info.getName(); |
||||||
|
} |
||||||
|
|
||||||
|
public String getType() { |
||||||
|
return info.getType().getTypeSignature(); |
||||||
|
} |
||||||
|
|
||||||
|
public String toString() { |
||||||
|
return "MethodIdentifier "+getFullName()+"."+getType(); |
||||||
|
} |
||||||
|
|
||||||
|
public boolean conflicting(String newAlias) { |
||||||
|
return clazz.containsField(newAlias) |
||||||
|
|| clazz.containsMethod(newAlias, ""); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,28 @@ |
|||||||
|
/* |
||||||
|
* LoadedClassIdentifier (c) 1998 Jochen Hoenicke |
||||||
|
* |
||||||
|
* You may distribute under the terms of the GNU General Public License. |
||||||
|
* |
||||||
|
* IN NO EVENT SHALL JOCHEN HOENICKE BE LIABLE TO ANY PARTY FOR DIRECT, |
||||||
|
* INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF |
||||||
|
* THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF JOCHEN HOENICKE |
||||||
|
* HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
* |
||||||
|
* JOCHEN HOENICKE SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT |
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A |
||||||
|
* PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" |
||||||
|
* BASIS, AND JOCHEN HOENICKE HAS NO OBLIGATION TO PROVIDE MAINTENANCE, |
||||||
|
* SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. |
||||||
|
* |
||||||
|
* $Id$ |
||||||
|
*/ |
||||||
|
|
||||||
|
package jode.obfuscator; |
||||||
|
import jode.Obfuscator; |
||||||
|
import jode.bytecode.ClassInfo; |
||||||
|
import jode.bytecode.FieldInfo; |
||||||
|
import jode.bytecode.MethodInfo; |
||||||
|
import java.lang.reflect.Modifier; |
||||||
|
import java.util.*; |
||||||
|
import java.io.*; |
||||||
|
|
@ -0,0 +1,141 @@ |
|||||||
|
/* |
||||||
|
* MethodIdentifier (c) 1998 Jochen Hoenicke |
||||||
|
* |
||||||
|
* You may distribute under the terms of the GNU General Public License. |
||||||
|
* |
||||||
|
* IN NO EVENT SHALL JOCHEN HOENICKE BE LIABLE TO ANY PARTY FOR DIRECT, |
||||||
|
* INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF |
||||||
|
* THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF JOCHEN HOENICKE |
||||||
|
* HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
* |
||||||
|
* JOCHEN HOENICKE SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT |
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A |
||||||
|
* PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" |
||||||
|
* BASIS, AND JOCHEN HOENICKE HAS NO OBLIGATION TO PROVIDE MAINTENANCE, |
||||||
|
* SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. |
||||||
|
* |
||||||
|
* $Id$ |
||||||
|
*/ |
||||||
|
package jode.obfuscator; |
||||||
|
import jode.Obfuscator; |
||||||
|
import jode.bytecode.*; |
||||||
|
import java.io.*; |
||||||
|
import java.util.Vector; |
||||||
|
import java.util.Enumeration; |
||||||
|
|
||||||
|
public class MethodIdentifier extends Identifier { |
||||||
|
ClassIdentifier clazz; |
||||||
|
MethodInfo info; |
||||||
|
|
||||||
|
public MethodIdentifier(ClassIdentifier clazz, MethodInfo info) { |
||||||
|
super(info.getName()); |
||||||
|
this.clazz = clazz; |
||||||
|
this.info = info; |
||||||
|
} |
||||||
|
|
||||||
|
public Vector analyzeCode(CodeInfo codeinfo) { |
||||||
|
Vector references = new Vector(); |
||||||
|
byte[] code = codeinfo.getCode(); |
||||||
|
try { |
||||||
|
DataInputStream stream = |
||||||
|
new DataInputStream(new ByteArrayInputStream(code)); |
||||||
|
Opcodes.getReferences(stream, references); |
||||||
|
} catch (IOException ex) { |
||||||
|
ex.printStackTrace(); |
||||||
|
throw new ClassFormatError(ex.getMessage()); |
||||||
|
} |
||||||
|
return references; |
||||||
|
} |
||||||
|
|
||||||
|
public void setSingleReachable() { |
||||||
|
super.setSingleReachable(); |
||||||
|
|
||||||
|
if (Obfuscator.isDebugging) |
||||||
|
Obfuscator.err.println("Reachable: "+this); |
||||||
|
|
||||||
|
ConstantPool cp = clazz.info.getConstantPool(); |
||||||
|
AttributeInfo codeattr = info.findAttribute("Code"); |
||||||
|
if (codeattr == null) |
||||||
|
return; |
||||||
|
|
||||||
|
DataInputStream stream = new DataInputStream |
||||||
|
(new ByteArrayInputStream(codeattr.getContents())); |
||||||
|
CodeInfo codeinfo = new CodeInfo(); |
||||||
|
try { |
||||||
|
codeinfo.read(clazz.info.getConstantPool(), stream); |
||||||
|
Vector references = analyzeCode(codeinfo); |
||||||
|
Enumeration enum = references.elements(); |
||||||
|
while (enum.hasMoreElements()) { |
||||||
|
int[] ref = (int[]) enum.nextElement(); |
||||||
|
int tag = cp.getTag(ref[0]); |
||||||
|
switch (tag) { |
||||||
|
case ConstantPool.FIELDREF: |
||||||
|
case ConstantPool.METHODREF: |
||||||
|
case ConstantPool.INTERFACEMETHODREF: { |
||||||
|
String[] names = cp.getRef(ref[0]); |
||||||
|
clazz.bundle.reachableIdentifier |
||||||
|
(names[0].replace('/','.')+"."+names[1]+"."+names[2], |
||||||
|
ref[1] == 1); |
||||||
|
break; |
||||||
|
} |
||||||
|
case ConstantPool.CLASS: { |
||||||
|
String clName = cp.getClassName(ref[0]).replace('/','.'); |
||||||
|
if (clName.charAt(0) == '[') { |
||||||
|
int i; |
||||||
|
for (i=0; i< clName.length(); i++) |
||||||
|
if (clName.charAt(i) != '[') |
||||||
|
break; |
||||||
|
if (i >= clName.length() || clName.charAt(i) != 'L') |
||||||
|
break; |
||||||
|
int index = clName.indexOf(';', i); |
||||||
|
if (index != clName.length()-1) |
||||||
|
break; |
||||||
|
clName = clName.substring(i+1, index); |
||||||
|
} |
||||||
|
clazz.bundle.reachableIdentifier(clName, false); |
||||||
|
break; |
||||||
|
} |
||||||
|
default: |
||||||
|
throw new jode.AssertError |
||||||
|
("Unknown reference: "+ref+" tag: "+tag); |
||||||
|
} |
||||||
|
} |
||||||
|
} catch (IOException ex) { |
||||||
|
ex.printStackTrace(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void writeTable(PrintWriter out) throws IOException { |
||||||
|
if (getName() != getAlias()) |
||||||
|
out.println("" + getFullAlias() |
||||||
|
+ "." + clazz.bundle.getTypeAlias(getType()) |
||||||
|
+ " = " + getName()); |
||||||
|
} |
||||||
|
|
||||||
|
public String getFullName() { |
||||||
|
return clazz.getFullName() + "." + getName(); |
||||||
|
} |
||||||
|
|
||||||
|
public String getFullAlias() { |
||||||
|
return clazz.getFullAlias() + "." + getAlias(); |
||||||
|
} |
||||||
|
|
||||||
|
public String getName() { |
||||||
|
return info.getName(); |
||||||
|
} |
||||||
|
|
||||||
|
public String getType() { |
||||||
|
return info.getType().getTypeSignature(); |
||||||
|
} |
||||||
|
|
||||||
|
public boolean conflicting(String newAlias) { |
||||||
|
String type = getType(); |
||||||
|
String paramType = type.substring(0, type.indexOf(')')+1); |
||||||
|
return clazz.containsMethod(newAlias, paramType) |
||||||
|
|| clazz.containsField(newAlias); |
||||||
|
} |
||||||
|
|
||||||
|
public String toString() { |
||||||
|
return "MethodIdentifier "+getFullName()+"."+getType(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,301 @@ |
|||||||
|
/* |
||||||
|
* PackageIdentifier (c) 1998 Jochen Hoenicke |
||||||
|
* |
||||||
|
* You may distribute under the terms of the GNU General Public License. |
||||||
|
* |
||||||
|
* IN NO EVENT SHALL JOCHEN HOENICKE BE LIABLE TO ANY PARTY FOR DIRECT, |
||||||
|
* INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF |
||||||
|
* THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF JOCHEN HOENICKE |
||||||
|
* HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
* |
||||||
|
* JOCHEN HOENICKE SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT |
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A |
||||||
|
* PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" |
||||||
|
* BASIS, AND JOCHEN HOENICKE HAS NO OBLIGATION TO PROVIDE MAINTENANCE, |
||||||
|
* SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. |
||||||
|
* |
||||||
|
* $Id$ |
||||||
|
*/ |
||||||
|
|
||||||
|
package jode.obfuscator; |
||||||
|
import jode.Obfuscator; |
||||||
|
import jode.bytecode.ClassInfo; |
||||||
|
import jode.bytecode.FieldInfo; |
||||||
|
import jode.bytecode.MethodInfo; |
||||||
|
import java.lang.reflect.Modifier; |
||||||
|
import java.util.*; |
||||||
|
import java.io.*; |
||||||
|
|
||||||
|
public class PackageIdentifier extends Identifier { |
||||||
|
ClassBundle bundle; |
||||||
|
PackageIdentifier parent; |
||||||
|
String name; |
||||||
|
|
||||||
|
boolean loadOnDemand; |
||||||
|
Hashtable loadedClasses; |
||||||
|
|
||||||
|
public PackageIdentifier(ClassBundle bundle, |
||||||
|
PackageIdentifier parent, |
||||||
|
String name, boolean loadOnDemand) { |
||||||
|
super(name); |
||||||
|
this.bundle = bundle; |
||||||
|
this.parent = parent; |
||||||
|
this.name = name; |
||||||
|
this.loadOnDemand = loadOnDemand; |
||||||
|
this.loadedClasses = new Hashtable(); |
||||||
|
} |
||||||
|
|
||||||
|
public Identifier getIdentifier(String name) { |
||||||
|
if (loadOnDemand) |
||||||
|
return loadClass(name); |
||||||
|
|
||||||
|
int index = name.indexOf('.'); |
||||||
|
if (index == -1) |
||||||
|
return (Identifier) loadedClasses.get(name); |
||||||
|
else { |
||||||
|
PackageIdentifier pack = (PackageIdentifier) |
||||||
|
loadedClasses.get(name.substring(0, index)); |
||||||
|
if (pack != null) |
||||||
|
return pack.getIdentifier(name.substring(index+1)); |
||||||
|
else |
||||||
|
return null; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public Identifier loadClass(String name) { |
||||||
|
int index = name.indexOf('.'); |
||||||
|
if (index == -1) { |
||||||
|
Identifier ident = (Identifier) loadedClasses.get(name); |
||||||
|
if (ident == null) { |
||||||
|
String fullname = getFullName() + name; |
||||||
|
if (ClassInfo.isPackage(fullname)) { |
||||||
|
ident = new PackageIdentifier(bundle, this, name, true); |
||||||
|
} else if (!ClassInfo.exists(fullname)) { |
||||||
|
throw new IllegalArgumentException |
||||||
|
("Can't find class"+fullname); |
||||||
|
} else { |
||||||
|
ident = new ClassIdentifier(bundle, this, name, |
||||||
|
ClassInfo.forName(fullname)); |
||||||
|
} |
||||||
|
loadedClasses.put(name, ident); |
||||||
|
} |
||||||
|
return ident; |
||||||
|
} else { |
||||||
|
String subpack = name.substring(0, index); |
||||||
|
PackageIdentifier pack = |
||||||
|
(PackageIdentifier) loadedClasses.get(subpack); |
||||||
|
if (pack == null) { |
||||||
|
pack = new PackageIdentifier(bundle, this, |
||||||
|
subpack, loadOnDemand); |
||||||
|
loadedClasses.put(subpack, pack); |
||||||
|
} |
||||||
|
|
||||||
|
if (pack != null) |
||||||
|
return pack.getIdentifier(name.substring(index+1)); |
||||||
|
else |
||||||
|
return null; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public Identifier loadClasses(String packageOrClass) { |
||||||
|
int index = packageOrClass.indexOf('.'); |
||||||
|
if (index == -1) { |
||||||
|
return loadClass(packageOrClass); |
||||||
|
} else { |
||||||
|
String subpack = packageOrClass.substring(0, index); |
||||||
|
PackageIdentifier pack = (PackageIdentifier) |
||||||
|
loadedClasses.get(subpack); |
||||||
|
if (pack == null) { |
||||||
|
pack = new PackageIdentifier(bundle, this, |
||||||
|
subpack, loadOnDemand); |
||||||
|
loadedClasses.put(subpack, pack); |
||||||
|
} |
||||||
|
return pack.loadClasses(packageOrClass.substring(index+1)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void reachableIdentifier(String fqn, boolean isVirtual) { |
||||||
|
int index = fqn.indexOf('.'); |
||||||
|
String component = index == -1 ? fqn : fqn.substring(0, index); |
||||||
|
Identifier ident = getIdentifier(component); |
||||||
|
if (ident == null) |
||||||
|
return; |
||||||
|
|
||||||
|
ident.setReachable(); |
||||||
|
if (index == -1) |
||||||
|
return; |
||||||
|
|
||||||
|
if (ident instanceof PackageIdentifier) |
||||||
|
((PackageIdentifier) ident).reachableIdentifier |
||||||
|
(fqn.substring(index+1), isVirtual); |
||||||
|
else { |
||||||
|
String method = fqn.substring(index+1); |
||||||
|
index = method.indexOf('.'); |
||||||
|
if (index == -1) { |
||||||
|
((ClassIdentifier) ident).reachableIdentifier |
||||||
|
(method, null, isVirtual); |
||||||
|
} else { |
||||||
|
((ClassIdentifier) ident).reachableIdentifier |
||||||
|
(method.substring(0, index), method.substring(index+1), |
||||||
|
isVirtual); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void preserveIdentifier(String fqn) { |
||||||
|
int index = fqn.indexOf('.'); |
||||||
|
String component = index == -1 ? fqn : fqn.substring(0, index); |
||||||
|
Identifier ident = getIdentifier(component); |
||||||
|
if (ident == null) |
||||||
|
return; |
||||||
|
ident.setReachable(); |
||||||
|
ident.setPreserved(); |
||||||
|
if (index == -1) |
||||||
|
return; |
||||||
|
|
||||||
|
if (ident instanceof PackageIdentifier) |
||||||
|
((PackageIdentifier) ident).preserveIdentifier |
||||||
|
(fqn.substring(index+1)); |
||||||
|
else { |
||||||
|
String method = fqn.substring(index+1); |
||||||
|
index = method.indexOf('.'); |
||||||
|
if (index == -1) { |
||||||
|
((ClassIdentifier) ident).reachableIdentifier |
||||||
|
(method, null, false); |
||||||
|
((ClassIdentifier) ident).preserveIdentifier |
||||||
|
(method, null); |
||||||
|
} else { |
||||||
|
((ClassIdentifier) ident).reachableIdentifier |
||||||
|
(method.substring(0, index), method.substring(index+1), |
||||||
|
false); |
||||||
|
((ClassIdentifier) ident).preserveIdentifier |
||||||
|
(method.substring(0, index), method.substring(index+1)); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @return the full qualified name, including trailing dot. |
||||||
|
*/ |
||||||
|
public String getFullName() { |
||||||
|
if (parent != null) |
||||||
|
return parent.getFullName() + getName() + "."; |
||||||
|
else |
||||||
|
return ""; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @return the full qualified alias, including trailing dot. |
||||||
|
*/ |
||||||
|
public String getFullAlias() { |
||||||
|
if (parent != null) |
||||||
|
return parent.getFullAlias() + getAlias() + "."; |
||||||
|
else |
||||||
|
return ""; |
||||||
|
} |
||||||
|
|
||||||
|
public String findAlias(String className) { |
||||||
|
int index = className.indexOf('.'); |
||||||
|
if (index == -1) { |
||||||
|
Identifier ident = getIdentifier(className); |
||||||
|
if (ident != null) |
||||||
|
return ident.getFullAlias(); |
||||||
|
} else { |
||||||
|
Identifier pack = getIdentifier(className.substring(0, index)); |
||||||
|
if (pack != null) |
||||||
|
return ((PackageIdentifier)pack) |
||||||
|
.findAlias(className.substring(index+1)); |
||||||
|
} |
||||||
|
return className; |
||||||
|
} |
||||||
|
|
||||||
|
public void strip() { |
||||||
|
Hashtable ht = new Hashtable(); |
||||||
|
Enumeration enum = loadedClasses.elements(); |
||||||
|
while (enum.hasMoreElements()) { |
||||||
|
Identifier ident = (Identifier) enum.nextElement(); |
||||||
|
if (ident.isReachable()) { |
||||||
|
ht.put(ident.getName(), ident); |
||||||
|
if (ident instanceof ClassIdentifier) { |
||||||
|
((ClassIdentifier) ident).strip(); |
||||||
|
} else |
||||||
|
((PackageIdentifier) ident).strip(); |
||||||
|
} else { |
||||||
|
if (Obfuscator.isDebugging) |
||||||
|
Obfuscator.err.println("Class/Package " |
||||||
|
+ ident.getFullName() |
||||||
|
+ " is not reachable"); |
||||||
|
} |
||||||
|
} |
||||||
|
loadedClasses = ht; |
||||||
|
} |
||||||
|
|
||||||
|
public void buildTable(int renameRule) { |
||||||
|
super.buildTable(renameRule); |
||||||
|
Enumeration enum = loadedClasses.elements(); |
||||||
|
while (enum.hasMoreElements()) { |
||||||
|
Identifier ident = (Identifier) enum.nextElement(); |
||||||
|
if (ident instanceof ClassIdentifier) { |
||||||
|
((ClassIdentifier) ident).buildTable(renameRule); |
||||||
|
} else |
||||||
|
((PackageIdentifier) ident).buildTable(renameRule); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void writeTable(PrintWriter out) throws IOException { |
||||||
|
if (parent != null && getName() != getAlias()) |
||||||
|
out.println("" + parent.getFullAlias() + getAlias() |
||||||
|
+ " = " + getName()); |
||||||
|
Enumeration enum = loadedClasses.elements(); |
||||||
|
while (enum.hasMoreElements()) { |
||||||
|
((Identifier)enum.nextElement()).writeTable(out); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public String getName() { |
||||||
|
return name; |
||||||
|
} |
||||||
|
|
||||||
|
public String getType() { |
||||||
|
return "package"; |
||||||
|
} |
||||||
|
|
||||||
|
public void storeClasses(File destination) { |
||||||
|
File newDest = (parent == null) ? destination |
||||||
|
: new File(destination, getName()); |
||||||
|
Enumeration enum = loadedClasses.elements(); |
||||||
|
while (enum.hasMoreElements()) { |
||||||
|
Identifier ident = (Identifier) enum.nextElement(); |
||||||
|
if (ident instanceof PackageIdentifier) |
||||||
|
((PackageIdentifier) ident) |
||||||
|
.storeClasses(newDest); |
||||||
|
else { |
||||||
|
try { |
||||||
|
((ClassIdentifier) ident).storeClass(null); |
||||||
|
} catch (java.io.IOException ex) { |
||||||
|
Obfuscator.err.println("Can't write Class " |
||||||
|
+ ident.getName()); |
||||||
|
ex.printStackTrace(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public String toString() { |
||||||
|
return (parent == null) ? "base package" |
||||||
|
: parent.getFullName()+getName(); |
||||||
|
} |
||||||
|
|
||||||
|
public boolean contains(String newAlias) { |
||||||
|
Enumeration enum = loadedClasses.elements(); |
||||||
|
while (enum.hasMoreElements()) { |
||||||
|
if (((Identifier)enum.nextElement()).getAlias().equals(newAlias)) |
||||||
|
return true; |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
public boolean conflicting(String newAlias) { |
||||||
|
return parent.contains(newAlias); |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue