X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=src%2Forg%2Fibex%2Futil%2FBytecodePruner.java;h=f9a3b644721c252fe45a3e76f7f822bc3df08e0a;hb=c8f04834582049dce7f80507a1b2b6c6210d5c3f;hp=9dbae7591df5f0e866a29abfc754728fc32f38f8;hpb=2b0def7f037c092c02bce1104dc758cae3da9809;p=org.ibex.core.git diff --git a/src/org/ibex/util/BytecodePruner.java b/src/org/ibex/util/BytecodePruner.java index 9dbae75..f9a3b64 100644 --- a/src/org/ibex/util/BytecodePruner.java +++ b/src/org/ibex/util/BytecodePruner.java @@ -7,76 +7,111 @@ import org.apache.bcel.generic.*; import org.apache.bcel.classfile.*; import org.apache.bcel.util.*; - // SecurityManager hacks to avoid java.security? - // URL and all descendents? Probably impossible. - // ObjectInput/ObjectOutput? Serialization? - - // superprune: URLClassLoader, convert.In/Output other than needed, unneeded locales - // reflective metadata is killing us... - -// Reachability rules: - -// - a constructor is reachable iff it is called -// - a static method is reachable iff it is called -// - a nonstatic method is reachable -// - a static field is reachable iff it is referenced -// - a nonstatic field is reachable iff it is referenced -// - is reachable iff any methods, static methods, fields, or constructors are reachable - -// - if a method is reachable, all the methods it overrides are reachable - -// try eliminating instance methods/fields if no ctor is reachable... -// distinguish between overloaded forms of a given method -// slim down the set of loadAllMethod() classes -// field pruning? - -// FIXME: nonstatic method invocation or field access implies that object will be constructed (ie hint) - +// Field pruning public class BytecodePruner { public static final boolean deleteMethods = false; + + // FIXME public static SyntheticRepository repo = null; + public static HashSet dest = new HashSet(); + public static String outdir = "."; public void loadAllMethods(String classname) throws Exception { visitJavaClass(repo.loadClass(classname)); Method[] meths = getMethods(repo.loadClass(classname)); - for(int i=0; i= 3 && s[1].equals("-o")) { outdir = s[2]; start += 2; } repo = SyntheticRepository.getInstance(new ClassPath(s[0])); - for(int i=start; i")) good = true; } else { if (methods[i].getCode() == null) { System.out.println(" empty codeblock: " + clazz.getClassName() + "." + methods[i].getName()); } else { System.out.println(" pruning " + clazz.getClassName() + "." + methods[i].getName()); - if (!deleteMethods) { - MethodGen mg = new MethodGen(methods[i], clazz.getClassName(), newcpg); - mg.removeExceptions(); - InstructionList il = new InstructionList(); - mg.setInstructionList(il); - - InstructionHandle ih_0 = il.append(factory.createNew("java.lang.UnsatisfiedLinkError")); - il.append(InstructionConstants.DUP); - il.append(factory.createInvoke("java.lang.UnsatisfiedLinkError", - "", Type.VOID, Type.NO_ARGS, Constants.INVOKESPECIAL)); - il.append(InstructionConstants.ATHROW); - - mg.setMaxStack(); - mg.setMaxLocals(); - mg.removeExceptions(); - mg.removeLocalVariables(); - mg.removeExceptionHandlers(); - mg.removeLineNumbers(); - - cg.replaceMethod(methods[i], mg.getMethod()); - il.dispose(); - } else { - cg.removeMethod(methods[i]); - } + if (deleteMethods) { cg.removeMethod(methods[i]); continue; } + MethodGen mg = new MethodGen(methods[i], clazz.getClassName(), newcpg); + mg.removeExceptions(); + InstructionList il = new InstructionList(); + mg.setInstructionList(il); + InstructionHandle ih_0 = il.append(factory.createNew("java.lang.UnsatisfiedLinkError")); + il.append(InstructionConstants.DUP); + il.append(factory.createInvoke("java.lang.UnsatisfiedLinkError", + "", Type.VOID, Type.NO_ARGS, Constants.INVOKESPECIAL)); + il.append(InstructionConstants.ATHROW); + mg.setMaxStack(); + mg.setMaxLocals(); + mg.removeExceptions(); + mg.removeLocalVariables(); + mg.removeExceptionHandlers(); + mg.removeLineNumbers(); + cg.replaceMethod(methods[i], mg.getMethod()); + il.dispose(); } } - if ((clazz.getClassName().startsWith("gnu.java.locale.LocaleInformation") && - !clazz.getClassName().endsWith("LocaleInformation_en") && - !clazz.getClassName().endsWith("LocaleInformation") && - !clazz.getClassName().endsWith("LocaleInformation_en_US")) - || - ((clazz.getClassName().startsWith("gnu.gcj.convert.Input_") || - clazz.getClassName().startsWith("gnu.gcj.convert.Output_")) && - !(clazz.getClassName().endsWith("ASCII") || - clazz.getClassName().endsWith("UTF8") || - clazz.getClassName().endsWith("iconv") || - clazz.getClassName().endsWith("8859_1"))) - || - (!good && - !clazz.isInterface() && - !clazz.isAbstract() && - !clazz.getClassName().startsWith("java.io.") && - !clazz.getClassName().startsWith("java.lang.") && - !clazz.getClassName().startsWith("gnu.") && - !clazz.getClassName().endsWith("Error") && - !clazz.getClassName().endsWith("Exception") && - !clazz.getClassName().endsWith("Permission"))) { - - //System.out.println("DROPPING " + clazz.getClassName()); - //return; } + new File(outdir + "/" + new File(clazz.getClassName().replace('.', '/')).getParent()).mkdirs(); System.out.println("dumping " + clazz.getClassName()); cg.getJavaClass().dump(outdir + "/" + clazz.getClassName().replace('.', '/') + ".class"); @@ -204,7 +212,6 @@ public class BytecodePruner { } public void load(Type t) throws Exception { if (t == null) return; - //String sig = t.getSignature(); if (t instanceof ArrayType) load(((ArrayType)t).getElementType()); if (!(t instanceof ObjectType)) return; load(((ObjectType)t).getClassName()); @@ -227,16 +234,24 @@ public class BytecodePruner { public static int level = 0; public void visitJavaMethod(JavaClass jc, Method method) throws Exception { visitJavaClass(jc); + /* if (jc.getClassName().equals("java.util.Date") && method.getName().equals("readObject")) return; - //if (jc.getClassName().equals("java.net.URLClassLoader")) return; + */ if (jc.getClassName().indexOf("SharedLib") != -1) return; if (jc.getClassName().indexOf("Datagram") != -1) return; if (dest.contains(method)) return; + + /* + // HACK (okay?) + // not inferrable: CNI call to abstract method + if (jc.getClassName().equals("java.util.TimeZone") && method.getName().equals("getDefaultTimeZoneId")) + loadMethod("java.util.SimpleTimeZone.useDaylightTime"); + */ + dest.add(method); level += 2; for(int i=0; i"); + } + if (instr instanceof org.apache.bcel.generic.FieldOrMethod) + load(((org.apache.bcel.generic.FieldOrMethod)instr).getClassType(cpg)); + if (instr instanceof org.apache.bcel.generic.FieldInstruction) { + load(((org.apache.bcel.generic.FieldInstruction)instr).getFieldType(cpg)); + load(((org.apache.bcel.generic.FieldInstruction)instr).getType(cpg)); + String fieldName = ((org.apache.bcel.generic.FieldInstruction)instr).getFieldName(cpg); + JavaClass jc2 = repo.loadClass(((ObjectType)((org.apache.bcel.generic.FieldInstruction)instr). + getLoadClassType(cpg)).getClassName()); + Field[] fields = jc2.getFields(); + for(int j=0; j")) visitJavaMethod(clazz, methods[i]); - // only if ctor reachable (?) if (methods[i].getName().equals("equals")) visitJavaMethod(clazz, methods[i]); if (methods[i].getName().equals("hashCode")) visitJavaMethod(clazz, methods[i]); @@ -349,8 +368,7 @@ public class BytecodePruner { String sig = getMethodSignature(m, cpg); Method[] submethods = getMethods(subclass); for(int j=0; j