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