private static StructureType getInstanceType0( SootClass clazz, int subClassAlignment, int[] superSize) { List<Type> types = new ArrayList<Type>(); List<SootField> fields = getInstanceFields(clazz); int superAlignment = 1; if (!fields.isEmpty()) { // Pad the super type so that the first field is aligned properly SootField field = fields.get(0); superAlignment = getFieldAlignment(field); } if (clazz.hasSuperclass()) { types.add(getInstanceType0(clazz.getSuperclass(), superAlignment, superSize)); } int offset = superSize[0]; for (SootField field : fields) { int falign = getFieldAlignment(field); int padding = (offset & (falign - 1)) != 0 ? (falign - (offset & (falign - 1))) : 0; types.add(padType(getType(field.getType()), padding)); offset += padding + getFieldSize(field); } int padding = (offset & (subClassAlignment - 1)) != 0 ? (subClassAlignment - (offset & (subClassAlignment - 1))) : 0; for (int i = 0; i < padding; i++) { types.add(I8); offset++; } superSize[0] = offset; return new StructureType(types.toArray(new Type[types.size()])); }
public void transform() { if (clazz.isPhantom()) return; // build ancestor // List<SootClass> ancestors = Scene.v().getActiveHierarchy().getSuperclassesOf(clazz); List<SootClass> ancestors = new LinkedList<SootClass>(); // fill in ancestor list without using Soot.Hierarchy SootClass curAncestor = clazz; while (curAncestor.hasSuperclass()) { ancestors.add(curAncestor.getSuperclass()); curAncestor = curAncestor.getSuperclass(); } for (SootClass ancestor : ancestors) { if (ancestor.isPhantom()) continue; cloneReachableNonHiddenAncestorMethods(ancestor); } // modify ancestors fields for (SootClass ancestor : ancestors) { if (ancestor.isPhantom()) continue; SootUtils.makeFieldsVisible(ancestor); } cloneHiddenAncestorMethodsAndFixInvokeSpecial(); }
/** * Resolve the concrete target of a special invoke using our modified semantics for special invoke * expression. */ private SootMethod resolveSpecialInvokeTarget(SpecialInvokeExpr si) { SootMethod target = null; try { target = SootUtils.resolve(si.getMethodRef()); } catch (CannotFindMethodException e) { logger.error("Cannot find concrete method target for special invoke: {}", si); return null; } String targetSubSig = target.getSubSignature(); SootClass current = target.getDeclaringClass(); while (true) { if (current.declaresMethod(targetSubSig)) { return current.getMethod(targetSubSig); } // not a match in current, try superclass on next loop if (current.hasSuperclass()) current = current.getSuperclass(); else { logger.error("Cannot find concrete method target for special invoke: {}", si); droidsafe.main.Main.exit(1); return null; } } }
public static boolean isSubclass(SootClass sc, String className) { SootClass clazz = sc; while (clazz.hasSuperclass()) { clazz = clazz.getSuperclass(); if (className.equals(clazz.getName())) { return true; } } return false; }
public static boolean isAssignable(SootClass taintType, SootClass declaredType) { if (taintType.equals(declaredType)) return true; if (taintType.hasSuperclass() && isAssignable(taintType.getSuperclass(), declaredType)) { return true; } for (SootClass interf : taintType.getInterfaces()) { if (isAssignable(interf, declaredType)) return true; } return false; }
public ResolvedEntry resolve(SootClass clazz) { while (clazz != null) { for (SootMethod m : clazz.getMethods()) { if (m.getName().equals(name) && desc.equals(Types.getDescriptor(m))) { return new ResolvedEntry(this, m); } } clazz = clazz.hasSuperclass() ? clazz.getSuperclass() : null; } return null; }
public ReverseClassHierarchy(Map<String, OpenCLClass> classes) { m_Hierarchy = new ArrayList<TreeNode>(); m_Classes = classes; addClass("java.lang.String"); Set<String> key_set = classes.keySet(); Set<String> visited = new HashSet<String>(); for (String key : key_set) { OpenCLClass ocl_class = classes.get(key); SootClass soot_class = Scene.v().getSootClass(ocl_class.getJavaName()); if (soot_class.hasSuperclass() == false) continue; SootClass parent = soot_class.getSuperclass(); if (parent.getName().equals("java.lang.Object")) { TreeNode tree = new TreeNode(soot_class, ocl_class); m_Hierarchy.add(tree); visited.add(key); } } boolean modified; do { modified = false; key_set = classes.keySet(); for (String key : key_set) { if (visited.contains(key)) continue; OpenCLClass ocl_class = classes.get(key); SootClass soot_class = Scene.v().getSootClass(ocl_class.getJavaName()); if (soot_class.hasSuperclass() == false) continue; SootClass parent = soot_class.getSuperclass(); TreeNode node = getNode(parent); if (node == null) continue; node.addChild(soot_class, ocl_class); modified = true; visited.add(key); } } while (modified); }
public static HashSet<SootMethod> getAllImplementations(SootMethod method) { Chain appClasses = Scene.v().getApplicationClasses(); HashSet<SootClass> implementingClasses = new HashSet<SootClass>(1); HashSet<SootMethod> overridingMethods = new HashSet<SootMethod>(1); SootClass t = method.getDeclaringClass(); if ( /*t.isAbstract() || */ t.isPhantom() || t.isPhantomClass()) { boolean b1 = t.isAbstract(); boolean be = t.isPhantom(); boolean b3 = t.isPhantomClass(); try { throw new Exception("Need to implement for Plantom Classes"); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } if (t.isAbstract()) { for (Object object : appClasses) { SootClass clazz = (SootClass) object; SootClass superClass = clazz.getSuperclass(); { if (superClass.getName().equals(t.toString())) { implementingClasses.add(clazz); SootMethod m2 = clazz.getMethod( method.getName(), method.getParameterTypes(), method.getReturnType()); overridingMethods.add(m2); } } } } if (t.isInterface()) { for (Object object : appClasses) { SootClass clazz = (SootClass) object; Chain<SootClass> interfaces = clazz.getInterfaces(); for (SootClass sootClass : interfaces) { if (sootClass.getName().equals(t.toString())) { implementingClasses.add(clazz); SootMethod m2 = clazz.getMethod( method.getName(), method.getParameterTypes(), method.getReturnType()); overridingMethods.add(m2); } } } } return overridingMethods; }
/** For instance invokes */ public static ArrayList<SootMethod> resolveAppCall(Type tgtType, SootMethodRef methodRef) { final NumberedString mSubsignature = methodRef.getSubSignature(); if (tgtType instanceof RefType) { // find first class upwards in hierarchy, starting from cls, that implements method (i.e., // *concrete* method) SootClass cls = ((RefType) tgtType).getSootClass(); while (!cls.declaresMethod(mSubsignature)) cls = cls .getSuperclass(); // if method not in this class, it HAS to be in a superclass, so a // superclass must exist if (!cls.hasTag(ClassTag.TAG_NAME)) return null; // not an app method // finally, store resolved app method SootMethod m = cls.getMethod(mSubsignature); assert m.hasTag(MethodTag.TAG_NAME); ArrayList<SootMethod> methods = new ArrayList<SootMethod>(); methods.add(m); // just one element, directly resolved return methods; } if (tgtType instanceof AnySubType) { // return set of all app subtypes that implement referenced method SootClass baseCls = ((AnySubType) tgtType).getBase().getSootClass(); List subClasses = baseCls.isInterface() ? Scene.v().getActiveHierarchy().getImplementersOf(baseCls) : Scene.v().getActiveHierarchy().getSubclassesOf(baseCls); ArrayList<SootMethod> methods = new ArrayList<SootMethod>(); for (Object oSubCls : subClasses) { SootClass subCls = (SootClass) oSubCls; if (subCls.hasTag(ClassTag.TAG_NAME)) { try { SootMethod m = subCls.getMethod(mSubsignature); assert m.hasTag(MethodTag.TAG_NAME); if (!m.isAbstract()) methods.add(m); } catch (RuntimeException e) { } } } return methods; } assert tgtType instanceof ArrayType; // only other case observed so far return new ArrayList(); // no array class/method is in app }
public VTable get(SootClass clazz) { if (clazz.isInterface()) { throw new IllegalArgumentException("Expected a class got an interface: " + clazz.getName()); } VTable vtable = cache.get(clazz.getName()); if (vtable != null) { return vtable; } VTable parent = null; if (clazz.hasSuperclass()) { parent = get(clazz.getSuperclass()); } vtable = new VTable(clazz, parent); cache.put(clazz.getName(), vtable); return vtable; }
/** * Finds in class hierarchy and returns all app and lib concrete methods possibly referenced by * method ref. Method is assumed to be virtual (not special or static). Returns true if there are * library methods among targets found. */ public static boolean getConcreteCallTargets( InvokeExpr instInvExpr, /*OUT*/ Set<SootMethod> appTargets, /*OUT*/ Set<SootMethod> libTargets) { // get class of method ref; we start searching from this class SootMethodRef mref = instInvExpr.getMethodRef(); SootClass cls = mref.declaringClass(); // starting class final NumberedString subsignature = mref.getSubSignature(); // signature to search for // CASE 1: object is of declared class type or inherited from some superclass // find first superclass, starting from current cls, that declares method; there HAS to // be such a class // note that if cls is interface, superclass if java.lang.Object // note that we don't check if there is indeed an interface declaring the method; we assume this // is the case if no superclass declares it while (!cls.declaresMethod(subsignature) && cls.hasSuperclass()) cls = cls.getSuperclass(); // never an interface // now, method might not be in superclass, or might be abstract; in that case, it's not a target SootMethod m; if (cls.declaresMethod(subsignature)) { m = cls.getMethod(subsignature); if (!m.isAbstract()) { if (cls.hasTag(ClassTag.TAG_NAME)) appTargets.add(m); // add app method else libTargets.add(m); // add lib method } } // (only for virtual/interface calls) // CASE 2: object's actual type is a subclass; any subclass declaring the method is a possible // target // we have to check all superclasses of implementers, because starting cls might be // interface if (instInvExpr instanceof VirtualInvokeExpr || instInvExpr instanceof InterfaceInvokeExpr) { cls = mref.declaringClass(); // start again from declaring class List<SootClass> allSubclasses = getAllSubtypes(cls); for (SootClass subCls : allSubclasses) { m = getMethodInClassOrSuperclass(subCls, subsignature); if (m != null && !m.isAbstract()) { if (m.getDeclaringClass().hasTag(ClassTag.TAG_NAME)) appTargets.add(m); // add app method else libTargets.add(m); // add lib method } } } return !libTargets.isEmpty(); }
// TODO: Consider implementing a cached version private static Set<SootMethod> getInitialDeclaration(SootMethod method, SootClass candidate) { Set<SootMethod> result = Sets.newHashSet(); if (candidate.hasSuperclass()) { result.addAll(getInitialDeclaration(method, candidate.getSuperclass())); } for (SootClass intface : candidate.getInterfaces()) { result.addAll(getInitialDeclaration(method, intface)); } if (result.isEmpty()) { for (SootMethod candidateMethod : candidate.getMethods()) { if (compatible(candidateMethod, method)) { result.add(candidateMethod); break; } } } return result; }
// finds the most restrictive form of exception that is also a superclass of exception_class SootClass GetMostRestrictiveFormOfException( List<TwoValuePair<Trap, Set<SootClass>>> tvps, SootClass exception_class) { List<TwoValuePair<SootClass, Integer>> superclass_counters = new ArrayList<TwoValuePair<SootClass, Integer>>(); for (TwoValuePair<Trap, Set<SootClass>> tvp : tvps) { SootClass super_exception_class = exception_class; int i = 0; while (super_exception_class != null) { if (tvp.v.getException() == super_exception_class) { superclass_counters.add( new TwoValuePair<SootClass, Integer>(tvp.v.getException(), new Integer(i))); } i++; try { super_exception_class = super_exception_class.getSuperclass(); } catch ( RuntimeException e) { // unfortunately soot doesn't have a specific exception class for "no // superclass for java.lang.Object" exception super_exception_class = null; } } } assert superclass_counters.size() != 0; TwoValuePair<SootClass, Integer> most_restrictive_form = superclass_counters.get(0); for (TwoValuePair<SootClass, Integer> tvp : superclass_counters) { if (tvp.w < most_restrictive_form.w) { most_restrictive_form = tvp; } } return most_restrictive_form.v; }
public static boolean isEnum(SootClass sc) { return sc.hasSuperclass() && sc.getSuperclass().getName().equals("java.lang.Enum"); }
private StructureConstant createClassInfoStruct() { int flags = 0; if (Modifier.isPublic(sootClass.getModifiers())) { flags |= CI_PUBLIC; } if (Modifier.isFinal(sootClass.getModifiers())) { flags |= CI_FINAL; } if (Modifier.isInterface(sootClass.getModifiers())) { flags |= CI_INTERFACE; } if (Modifier.isAbstract(sootClass.getModifiers())) { flags |= CI_ABSTRACT; } if ((sootClass.getModifiers() & 0x1000) > 0) { flags |= CI_SYNTHETIC; } if (Modifier.isAnnotation(sootClass.getModifiers())) { flags |= CI_ANNOTATION; } if (Modifier.isEnum(sootClass.getModifiers())) { flags |= CI_ENUM; } if (attributesEncoder.classHasAttributes()) { flags |= CI_ATTRIBUTES; } if (hasFinalizer(sootClass)) { flags |= CI_FINALIZABLE; } // Create the ClassInfoHeader structure. StructureConstantBuilder header = new StructureConstantBuilder(); header.add(new NullConstant(I8_PTR)); // Points to the runtime Class struct header.add(new IntegerConstant(flags)); header.add(getString(getInternalName(sootClass))); if (sootClass.declaresMethod("<clinit>", Collections.emptyList(), VoidType.v())) { SootMethod method = sootClass.getMethod("<clinit>", Collections.emptyList(), VoidType.v()); header.add(new FunctionRef(mangleMethod(method), getFunctionType(method))); } else { header.add(new NullConstant(I8_PTR)); } header.add(sizeof(classType)); header.add(sizeof(instanceType)); if (!instanceFields.isEmpty()) { header.add(offsetof(instanceType, 1, 1)); } else { header.add(sizeof(instanceType)); } header.add(new IntegerConstant((short) countReferences(classFields))); header.add(new IntegerConstant((short) countReferences(instanceFields))); PackedStructureConstantBuilder body = new PackedStructureConstantBuilder(); body.add(new IntegerConstant((short) sootClass.getInterfaceCount())); body.add(new IntegerConstant((short) sootClass.getFieldCount())); body.add(new IntegerConstant((short) sootClass.getMethodCount())); if (!sootClass.isInterface()) { body.add( getStringOrNull( sootClass.hasSuperclass() ? getInternalName(sootClass.getSuperclass()) : null)); } if (attributesEncoder.classHasAttributes()) { body.add(new ConstantBitcast(attributesEncoder.getClassAttributes().ref(), I8_PTR)); } for (SootClass s : sootClass.getInterfaces()) { body.add(getString(getInternalName(s))); } for (SootField f : sootClass.getFields()) { flags = 0; soot.Type t = f.getType(); if (t instanceof PrimType) { if (t.equals(BooleanType.v())) { flags |= DESC_Z; } else if (t.equals(ByteType.v())) { flags |= DESC_B; } else if (t.equals(ShortType.v())) { flags |= DESC_S; } else if (t.equals(CharType.v())) { flags |= DESC_C; } else if (t.equals(IntType.v())) { flags |= DESC_I; } else if (t.equals(LongType.v())) { flags |= DESC_J; } else if (t.equals(FloatType.v())) { flags |= DESC_F; } else if (t.equals(DoubleType.v())) { flags |= DESC_D; } flags <<= 12; } if (Modifier.isPublic(f.getModifiers())) { flags |= FI_PUBLIC; } else if (Modifier.isPrivate(f.getModifiers())) { flags |= FI_PRIVATE; } else if (Modifier.isProtected(f.getModifiers())) { flags |= FI_PROTECTED; } if (Modifier.isStatic(f.getModifiers())) { flags |= FI_STATIC; } if (Modifier.isFinal(f.getModifiers())) { flags |= FI_FINAL; } if (Modifier.isVolatile(f.getModifiers())) { flags |= FI_VOLATILE; } if (Modifier.isTransient(f.getModifiers())) { flags |= FI_TRANSIENT; } if ((f.getModifiers() & 0x1000) > 0) { flags |= FI_SYNTHETIC; } if (Modifier.isEnum(f.getModifiers())) { flags |= FI_ENUM; } if (attributesEncoder.fieldHasAttributes(f)) { flags |= FI_ATTRIBUTES; } body.add(new IntegerConstant((short) flags)); body.add(getString(f.getName())); if (!(t instanceof PrimType)) { body.add(getString(getDescriptor(f))); } if (f.isStatic()) { int index = classFields.indexOf(f); body.add(offsetof(classType, 1, index, 1)); } else { int index = instanceFields.indexOf(f); body.add(offsetof(instanceType, 1, 1 + index, 1)); } if (attributesEncoder.fieldHasAttributes(f)) { body.add(new ConstantBitcast(attributesEncoder.getFieldAttributes(f).ref(), I8_PTR)); } } for (SootMethod m : sootClass.getMethods()) { soot.Type t = m.getReturnType(); flags = 0; if (Modifier.isPublic(m.getModifiers())) { flags |= MI_PUBLIC; } else if (Modifier.isPrivate(m.getModifiers())) { flags |= MI_PRIVATE; } else if (Modifier.isProtected(m.getModifiers())) { flags |= MI_PROTECTED; } if (Modifier.isStatic(m.getModifiers())) { flags |= MI_STATIC; } if (Modifier.isFinal(m.getModifiers())) { flags |= MI_FINAL; } if (Modifier.isSynchronized(m.getModifiers())) { flags |= MI_SYNCHRONIZED; } if ((m.getModifiers() & 0x0040) > 0) { flags |= MI_BRIDGE; } if ((m.getModifiers() & 0x0080) > 0) { flags |= MI_VARARGS; } if (Modifier.isNative(m.getModifiers())) { if (!isStruct(sootClass) && !isStructMember(m)) { flags |= MI_NATIVE; } } if (Modifier.isAbstract(m.getModifiers())) { flags |= MI_ABSTRACT; } if (Modifier.isStrictFP(m.getModifiers())) { flags |= MI_STRICT; } if ((m.getModifiers() & 0x1000) > 0) { flags |= MI_SYNTHETIC; } if (attributesEncoder.methodHasAttributes(m)) { flags |= MI_ATTRIBUTES; } if (isBridge(m)) { flags |= MI_BRO_BRIDGE; } if (isCallback(m)) { flags |= MI_BRO_CALLBACK; } if ((t instanceof PrimType || t == VoidType.v()) && m.getParameterCount() == 0) { flags |= MI_COMPACT_DESC; } body.add(new IntegerConstant((short) flags)); body.add(getString(m.getName())); if ((flags & MI_COMPACT_DESC) > 0) { int desc = 0; if (t.equals(BooleanType.v())) { desc = DESC_Z; } else if (t.equals(ByteType.v())) { desc = DESC_B; } else if (t.equals(ShortType.v())) { desc = DESC_S; } else if (t.equals(CharType.v())) { desc = DESC_C; } else if (t.equals(IntType.v())) { desc = DESC_I; } else if (t.equals(LongType.v())) { desc = DESC_J; } else if (t.equals(FloatType.v())) { desc = DESC_F; } else if (t.equals(DoubleType.v())) { desc = DESC_D; } else if (t.equals(VoidType.v())) { desc = DESC_V; } body.add(new IntegerConstant((byte) desc)); } else { body.add(getString(getDescriptor(m))); } if (attributesEncoder.methodHasAttributes(m)) { body.add(new ConstantBitcast(attributesEncoder.getMethodAttributes(m).ref(), I8_PTR)); } if (!m.isAbstract()) { body.add(new ConstantBitcast(new FunctionRef(mangleMethod(m), getFunctionType(m)), I8_PTR)); body.add( new IntegerConstant( DUMMY_METHOD_SIZE)); // Size of function. This value will be modified later by // patching the .s file. if (m.isSynchronized()) { body.add( new ConstantBitcast( new FunctionRef(mangleMethod(m) + "_synchronized", getFunctionType(m)), I8_PTR)); } } if (isBridge(m)) { body.add(new GlobalRef(BridgeMethodCompiler.getTargetFnPtrName(m), I8_PTR)); } if (isCallback(m)) { body.add( new ConstantBitcast( new FunctionRef(mangleMethod(m) + "_callback", getCallbackFunctionType(m)), I8_PTR)); } } // Return the struct {header, body}. To be compatible with the C code in classinfo.c // it is important that the header is padded the same as in C so that the body starts // after sizeof(ClassInfoHeader) bytes. return new StructureConstantBuilder().add(header.build()).add(body.build()).build(); }
private StructureConstant createClassInfoErrorStruct() { /* * Check that clazz can be loaded, i.e. that the superclass * and interfaces of the class exist and are accessible to the * class. Also check that any exception the class uses in catch * clauses exist and is accessible to the class. If the class * cannot be loaded we override the ClassInfoHeader struct * produced by the ClassCompiler for the class with one which * tells the code in bc.c to throw an appropriate exception * whenever clazz is accessed. */ int errorType = ClassCompiler.CI_ERROR_TYPE_NONE; String errorMessage = null; if (!sootClass.isInterface() && sootClass.hasSuperclass()) { // Check superclass SootClass superclazz = sootClass.getSuperclass(); if (superclazz.isPhantom()) { errorType = ClassCompiler.CI_ERROR_TYPE_NO_CLASS_DEF_FOUND; errorMessage = superclazz.getName(); } else if (!checkClassAccessible(superclazz, sootClass)) { errorType = ClassCompiler.CI_ERROR_TYPE_ILLEGAL_ACCESS; errorMessage = String.format(ILLEGAL_ACCESS_ERROR_CLASS, superclazz, sootClass); } else if (superclazz.isInterface()) { errorType = ClassCompiler.CI_ERROR_TYPE_INCOMPATIBLE_CLASS_CHANGE; errorMessage = String.format("class %s has interface %s as super class", sootClass, superclazz); } // No need to check for ClassCircularityError. Soot doesn't handle // such problems so the compilation will fail earlier. } if (errorType == ClassCompiler.CI_ERROR_TYPE_NONE) { // Check interfaces for (SootClass interfaze : sootClass.getInterfaces()) { if (interfaze.isPhantom()) { errorType = ClassCompiler.CI_ERROR_TYPE_NO_CLASS_DEF_FOUND; errorMessage = interfaze.getName(); break; } else if (!checkClassAccessible(interfaze, sootClass)) { errorType = ClassCompiler.CI_ERROR_TYPE_ILLEGAL_ACCESS; errorMessage = String.format(ILLEGAL_ACCESS_ERROR_CLASS, interfaze, sootClass); break; } else if (!interfaze.isInterface()) { errorType = ClassCompiler.CI_ERROR_TYPE_INCOMPATIBLE_CLASS_CHANGE; errorMessage = String.format( "class %s tries to implement class %s as interface", sootClass, interfaze); break; } } } if (errorType == ClassCompiler.CI_ERROR_TYPE_NONE) { // Check exceptions used in catch clauses. I cannot find any info in // the VM spec specifying that this has to be done when the class is loaded. // However, this is how it's done in other VMs so we do it too. for (String exName : catches) { Clazz ex = config.getClazzes().load(exName); if (ex == null || ex.getSootClass().isPhantom()) { errorType = ClassCompiler.CI_ERROR_TYPE_NO_CLASS_DEF_FOUND; errorMessage = exName; break; } else if (!checkClassAccessible(ex.getSootClass(), sootClass)) { errorType = ClassCompiler.CI_ERROR_TYPE_ILLEGAL_ACCESS; errorMessage = String.format(ILLEGAL_ACCESS_ERROR_CLASS, ex, sootClass); break; } } } if (errorType == ClassCompiler.CI_ERROR_TYPE_NONE) { return null; } // Create a ClassInfoError struct StructureConstantBuilder error = new StructureConstantBuilder(); error.add(new NullConstant(I8_PTR)); // Points to the runtime Class struct error.add(new IntegerConstant(ClassCompiler.CI_ERROR)); error.add(getString(getInternalName(sootClass))); error.add(new IntegerConstant(errorType)); error.add(getString(errorMessage)); return error.build(); }
private void compile(Clazz clazz, OutputStream out) throws IOException { sootClass = clazz.getSootClass(); mb = new ModuleBuilder(); trampolines = new HashSet<Trampoline>(); catches = new HashSet<String>(); classFields = getClassFields(sootClass); instanceFields = getInstanceFields(sootClass); classType = getClassType(sootClass); instanceType = getInstanceType(sootClass); attributesEncoder.encode(mb, sootClass); // Add a <clinit> method if the class has ConstantValueTags but no <clinit>. // This has to be done before createInfoStruct() is called otherwise the // ClassInfoHeader->initializer value will become NULL and constant static fields // will never be initialized. if (!sootClass.declaresMethodByName("<clinit>") && hasConstantValueTags(classFields)) { SootMethod clinit = new SootMethod("<clinit>", Collections.EMPTY_LIST, VoidType.v(), Modifier.STATIC); JimpleBody body = Jimple.v().newBody(clinit); clinit.setActiveBody(body); body.getUnits().add(new JReturnVoidStmt()); this.sootClass.addMethod(clinit); } if (isStruct(sootClass)) { if (!Modifier.isFinal(sootClass.getModifiers())) { throw new IllegalArgumentException("Struct class must be final"); } SootMethod _sizeOf = new SootMethod("_sizeOf", Collections.EMPTY_LIST, IntType.v(), Modifier.PROTECTED); sootClass.addMethod(_sizeOf); SootMethod sizeOf = new SootMethod( "sizeOf", Collections.EMPTY_LIST, IntType.v(), Modifier.PUBLIC | Modifier.STATIC); sootClass.addMethod(sizeOf); } mb.addInclude( getClass() .getClassLoader() .getResource( String.format("header-%s-%s.ll", config.getOs().getFamily(), config.getArch()))); mb.addInclude(getClass().getClassLoader().getResource("header.ll")); mb.addFunction(createInstanceof()); mb.addFunction(createCheckcast()); mb.addFunction(createLdcClass()); mb.addFunction(createLdcClassWrapper()); Function allocator = createAllocator(); mb.addFunction(allocator); mb.addFunction(createClassInitWrapperFunction(allocator.ref())); for (SootField f : sootClass.getFields()) { Function getter = createFieldGetter(f); Function setter = createFieldSetter(f); mb.addFunction(getter); mb.addFunction(setter); if (f.isStatic() && !f.isPrivate()) { mb.addFunction(createClassInitWrapperFunction(getter.ref())); if (!f.isFinal()) { mb.addFunction(createClassInitWrapperFunction(setter.ref())); } } } for (SootMethod method : sootClass.getMethods()) { String name = method.getName(); if (isBridge(method)) { bridgeMethod(method); } else if (isStruct(sootClass) && ("_sizeOf".equals(name) || "sizeOf".equals(name) || isStructMember(method))) { structMember(method); } else if (method.isNative()) { nativeMethod(method); } else if (!method.isAbstract()) { method(method); } if (!name.equals("<clinit>") && !name.equals("<init>") && !method.isPrivate() && !method.isStatic() && !Modifier.isFinal(method.getModifiers()) && !Modifier.isFinal(sootClass.getModifiers())) { createLookupFunction(method); } if (method.isStatic()) { String fnName = mangleMethod(method); if (method.isSynchronized()) { fnName += "_synchronized"; } FunctionRef fn = new FunctionRef(fnName, getFunctionType(method)); mb.addFunction(createClassInitWrapperFunction(fn)); } } Set<String> trampolineDependencies = new HashSet<String>(); for (Trampoline trampoline : trampolines) { trampolineResolver.compile(mb, trampoline); trampolineDependencies.addAll(trampolineResolver.getDependencies()); } Global classInfoStruct = null; StructureConstant classInfoErrorStruct = createClassInfoErrorStruct(); if (classInfoErrorStruct != null) { // The class cannot be loaded at runtime. Replace the ClassInfo struct // with a ClassInfoError struct with details of why. classInfoStruct = new Global(mangleClass(sootClass) + "_info_struct", classInfoErrorStruct); } else { classInfoStruct = new Global(mangleClass(sootClass) + "_info_struct", createClassInfoStruct()); } mb.addGlobal(classInfoStruct); Function infoFn = FunctionBuilder.infoStruct(sootClass); infoFn.add(new Ret(new ConstantBitcast(classInfoStruct.ref(), I8_PTR_PTR))); mb.addFunction(infoFn); out.write(mb.build().toString().getBytes("UTF-8")); clazz.clearDependencies(); clazz.addDependency( "java/lang/Object"); // Make sure no class or interface has zero dependencies if (sootClass.hasSuperclass() && !sootClass.isInterface()) { clazz.addDependency(getInternalName(sootClass.getSuperclass())); } for (SootClass iface : sootClass.getInterfaces()) { clazz.addDependency(getInternalName(iface)); } for (SootField f : sootClass.getFields()) { addDependencyIfNeeded(clazz, f.getType()); } for (SootMethod m : sootClass.getMethods()) { addDependencyIfNeeded(clazz, m.getReturnType()); @SuppressWarnings("unchecked") List<soot.Type> paramTypes = (List<soot.Type>) m.getParameterTypes(); for (soot.Type type : paramTypes) { addDependencyIfNeeded(clazz, type); } } clazz.addDependencies(attributesEncoder.getDependencies()); clazz.addDependencies(trampolineDependencies); clazz.addDependencies(catches); for (Trampoline t : trampolines) { if (!(t instanceof LdcString)) { String desc = t.getTarget(); if (desc.charAt(0) == 'L' || desc.charAt(0) == '[') { // Target is a descriptor addDependencyIfNeeded(clazz, desc); } else { clazz.addDependency(t.getTarget()); } } if (t instanceof FieldAccessor) { addDependencyIfNeeded(clazz, ((FieldAccessor) t).getFieldDesc()); } else if (t instanceof Invoke) { String methodDesc = ((Invoke) t).getMethodDesc(); addDependencyIfNeeded(clazz, getReturnTypeDescriptor(methodDesc)); for (String desc : getParameterDescriptors(methodDesc)) { addDependencyIfNeeded(clazz, desc); } } } clazz.saveDependencies(); }
public boolean DoAnalysis(boolean verbose) { Stack<List<Set<SootClass>>> current_exception_sets = new Stack<List<Set<SootClass>>>(); { List<Set<SootClass>> exception_sets = new ArrayList<Set<SootClass>>(); exception_sets.add(method_exception_set); current_exception_sets.push(exception_sets); } PatchingChain<Unit> chain = body.getUnits(); Unit next = chain.getFirst(); int previous_class_count = method_exception_set.size(); for (Map.Entry<Unit, List<TwoValuePair<Trap, Set<SootClass>>>> entry : trap_begin_exception_sets.entrySet()) { for (TwoValuePair<Trap, Set<SootClass>> tvp : entry.getValue()) { previous_class_count += tvp.w.size(); } } do { if (trap_begin_exception_sets.containsKey(next)) { List<TwoValuePair<Trap, Set<SootClass>>> tvps = trap_begin_exception_sets.get(next); List<Set<SootClass>> sets_to_add = new ArrayList<Set<SootClass>>(); for (TwoValuePair<Trap, Set<SootClass>> tvp : tvps) { sets_to_add.add(tvp.w); } current_exception_sets.push(sets_to_add); } if (next instanceof InvokeStmt || next instanceof AssignStmt) { SootMethod callee = null; if (next instanceof AssignStmt) { if (((AssignStmt) next).getRightOp() instanceof InvokeExpr) { callee = ((InvokeExpr) ((AssignStmt) next).getRightOp()).getMethod(); } } else { callee = ((InvokeStmt) next).getInvokeExpr().getMethod(); } if (callee != null) { // invocation only Collection<SootClass> exception_classes; if (class_map.containsKey(callee.getDeclaringClass())) { assert class_map.get(callee.getDeclaringClass()).method_analysis.containsKey(callee); exception_classes = class_map .get(callee.getDeclaringClass()) .method_analysis .get(callee) .method_exception_set; } else { exception_classes = callee.getExceptions(); } for (SootClass exception_class : exception_classes) { for (Set<SootClass> current_exception_set : current_exception_sets.peek()) { current_exception_set.add(exception_class); } } } } else if (next instanceof ThrowStmt) { assert chain.getPredOf(next) instanceof JInvokeStmt; assert ((JInvokeStmt) chain.getPredOf(next)).getInvokeExpr() instanceof SpecialInvokeExpr; assert ((SpecialInvokeExpr) ((JInvokeStmt) chain.getPredOf(next)).getInvokeExpr()).getBase() instanceof JimpleLocal; assert ((JimpleLocal) ((SpecialInvokeExpr) ((JInvokeStmt) chain.getPredOf(next)).getInvokeExpr()) .getBase()) .getType() instanceof RefType; SootClass exception_class = ((RefType) ((JimpleLocal) ((SpecialInvokeExpr) ((JInvokeStmt) chain.getPredOf(next)).getInvokeExpr()) .getBase()) .getType()) .getSootClass(); for (Set<SootClass> current_exception_set : current_exception_sets.peek()) { current_exception_set.add(exception_class); } } if (trap_end_exception_sets.containsKey(next)) { List<TwoValuePair<Trap, Set<SootClass>>> tvps = trap_end_exception_sets.get(next); if (verbose) { for (Set<SootClass> current_exception_set : current_exception_sets.peek()) { if (current_exception_set.size() == 0) { for (TwoValuePair<Trap, Set<SootClass>> tvp : tvps) { if (!tvp.v.getException().getName().equals("java.lang.RuntimeException")) System.out.println( "Warning: In " + method.toString() + ": Unncessary exception handler for catching " + tvp.v.getException().getName()); } } } } for (TwoValuePair<Trap, Set<SootClass>> tvp : tvps) { Iterator<SootClass> i = tvp.w.iterator(); while (i.hasNext()) { SootClass exception_class = i.next(); if (tvp.v.getException() == exception_class) { // getting properly caught by the handler. i.remove(); } else { SootClass super_exception_class = exception_class; while (super_exception_class != null) { if (tvp.v.getException() == super_exception_class) { i.remove(); if (verbose && super_exception_class != exception_class && GetMostRestrictiveFormOfException(tvps, exception_class) == tvp.v.getException() && !super_exception_class.getName().equals("java.lang.RuntimeException")) { System.out.println( "Warning: In " + method.toString() + ": attempting to catch " + exception_class.getName() + " with " + super_exception_class.getName() + " Consider catching the most restrictive exception class"); } break; } try { super_exception_class = super_exception_class.getSuperclass(); } catch ( RuntimeException e) { // unfortunately soot doesn't have a specific exception class for "no // superclass for java.lang.Object" exception super_exception_class = null; } } } } } current_exception_sets.pop(); for (Set<SootClass> current_exception_set : current_exception_sets .peek()) { // This list iteration is not necessary if we are still making the // assumption that there's only one unique set that contains exception // classes if the range for traps are the same for (TwoValuePair<Trap, Set<SootClass>> tvp : tvps) { for (SootClass exception_class : tvp.w) { current_exception_set.add(exception_class); } } } } next = chain.getSuccOf(next); } while (next != null); int new_class_count = method_exception_set.size(); for (Map.Entry<Unit, List<TwoValuePair<Trap, Set<SootClass>>>> entry : trap_begin_exception_sets.entrySet()) { for (TwoValuePair<Trap, Set<SootClass>> tvp : entry.getValue()) { new_class_count += tvp.w.size(); } } return new_class_count != previous_class_count; }
/** * Returns method in given class or first upwards superclass, or null if not found in any class * (no interface checked) */ private static SootMethod getMethodInClassOrSuperclass( SootClass cls, NumberedString subsignature) { if (cls.declaresMethod(subsignature)) return cls.getMethod(subsignature); if (cls.hasSuperclass()) return getMethodInClassOrSuperclass(cls.getSuperclass(), subsignature); return null; }
private StructureType getStructType(SootClass clazz, boolean checkEmpty) { int n = 0; for (SootMethod method : clazz.getMethods()) { n = Math.max(getStructMemberOffset(method) + 1, n); } Type[] result = new Type[n + 1]; StructureType superType = null; if (clazz.hasSuperclass()) { SootClass superclass = clazz.getSuperclass(); if (!superclass.getName().equals("org.robovm.rt.bro.Struct")) { superType = getStructType(superclass, false); } } result[0] = superType != null ? superType : new StructureType(); for (SootMethod method : clazz.getMethods()) { int offset = getStructMemberOffset(method); if (offset != -1) { if (!method.isNative() && !method.isStatic()) { throw new IllegalArgumentException( "@StructMember annotated method " + method + " must be native and not static"); } Type type = null; if (method.getParameterCount() == 0) { soot.Type sootType = method.getReturnType(); // Possibly a getter if (hasPointerAnnotation(method) && !sootType.equals(LongType.v())) { throw new IllegalArgumentException( "@StructMember(" + offset + ") annotated getter " + method + " must be of type long when annotated with @Pointer"); } if (hasMachineSizedFloatAnnotation(method) && !sootType.equals(DoubleType.v()) && !sootType.equals(FloatType.v())) { throw new IllegalArgumentException( "@StructMember(" + offset + ") annotated getter " + method + " must be of type float or double when annotated with @MachineSizedFloat"); } if ((hasMachineSizedSIntAnnotation(method) || hasMachineSizedUIntAnnotation(method)) && !sootType.equals(LongType.v())) { throw new IllegalArgumentException( "@StructMember(" + offset + ") annotated getter " + method + " must be of type long when annotated with @MachineSizedSInt or @MachineSizedUInt"); } if (sootType instanceof soot.ArrayType && !hasArrayAnnotation(method)) { throw new IllegalArgumentException( "@Array annotation expected on struct member getter " + method); } } else if (method.getParameterCount() == 1) { soot.Type sootType = method.getParameterType(0); if (hasPointerAnnotation(method, 0) && !sootType.equals(LongType.v())) { throw new IllegalArgumentException( "@StructMember(" + offset + ") annotated setter " + method + " must be of type long when annotated with @Pointer"); } if (hasMachineSizedFloatAnnotation(method, 0) && !sootType.equals(DoubleType.v()) && !sootType.equals(FloatType.v())) { throw new IllegalArgumentException( "@StructMember(" + offset + ") annotated setter " + method + " must be of type float or double when annotated with @MachineSizedFloat"); } if ((hasMachineSizedSIntAnnotation(method, 0) || hasMachineSizedUIntAnnotation(method)) && !sootType.equals(LongType.v())) { throw new IllegalArgumentException( "@StructMember(" + offset + ") annotated setter " + method + " must be of type long when annotated with @MachineSizedSInt or @MachineSizedUInt"); } if (sootType instanceof soot.ArrayType && !hasArrayAnnotation(method, 0)) { throw new IllegalArgumentException( "@Array annotation expected on first parameter of struct member setter " + method); } soot.Type retType = method.getReturnType(); // The return type of the setter must be void or this if (!retType.equals(VoidType.v()) && !(retType instanceof RefType && ((RefType) retType).getSootClass().equals(clazz))) { throw new IllegalArgumentException( "Setter " + method + " for " + "@StructMember(" + offset + ") " + " must either return nothing or return a " + clazz); } } else { throw new IllegalArgumentException( "@StructMember annotated method " + method + " has too many parameters"); } type = getStructMemberType(method); int index = offset + 1; if (result[index] == null) { result[index] = type; } else if (type != result[index]) { // Two members mapped to the same offset (union). Pick // the type with the largest alignment and pad with bytes // up to the largest size. result[index] = mergeStructMemberTypes(config.getDataLayout(), type, result[index]); } } } for (int i = 1; i < result.length; i++) { if (result[i] == null) { throw new IllegalArgumentException("No @StructMember(" + i + ") defined in class " + clazz); } } if (!clazz.isAbstract() && checkEmpty && n == 0 && superType == null) { throw new IllegalArgumentException( "Struct class " + clazz + " has no @StructMember annotated methods"); } return new StructureType(result); }
public void printTo(SootClass cl, PrintWriter out) { // IterableSet packagesUsed = new IterableSet(); IterableSet importList = new IterableSet(); { String curPackage = cl.getJavaPackageName(); if (!curPackage.equals("")) { out.println("package " + curPackage + ";"); out.println(); } if (cl.hasSuperclass()) { SootClass superClass = cl.getSuperclass(); importList.add(superClass.toString()); // packagesUsed.add(superClass.getJavaPackageName()); } Iterator<SootClass> interfaceIt = cl.getInterfaces().iterator(); while (interfaceIt.hasNext()) { String interfacePackage = ((SootClass) interfaceIt.next()).toString(); if (!importList.contains(interfacePackage)) importList.add(interfacePackage); // if (!packagesUsed.contains(interfacePackage)) // packagesUsed.add(interfacePackage); } Iterator<SootMethod> methodIt = cl.methodIterator(); while (methodIt.hasNext()) { SootMethod dm = (SootMethod) methodIt.next(); if (dm.hasActiveBody()) { // packagesUsed = packagesUsed.union(((DavaBody) dm.getActiveBody()).get_PackagesUsed()); importList = importList.union(((DavaBody) dm.getActiveBody()).getImportList()); } Iterator<SootClass> eit = dm.getExceptions().iterator(); while (eit.hasNext()) { String thrownPackage = eit.next().toString(); if (!importList.contains(thrownPackage)) importList.add(thrownPackage); // if (!packagesUsed.contains(thrownPackage)) // packagesUsed.add(thrownPackage); } Iterator<Type> pit = dm.getParameterTypes().iterator(); while (pit.hasNext()) { Type t = (Type) pit.next(); if (t instanceof RefType) { String paramPackage = ((RefType) t).getSootClass().toString(); if (!importList.contains(paramPackage)) importList.add(paramPackage); // if (packagesUsed.contains(paramPackage) == false) // packagesUsed.add(paramPackage); } } Type t = dm.getReturnType(); if (t instanceof RefType) { String returnPackage = ((RefType) t).getSootClass().toString(); if (!importList.contains(returnPackage)) importList.add(returnPackage); // if (packagesUsed.contains(returnPackage) == false) // packagesUsed.add(returnPackage); } } Iterator<SootField> fieldIt = cl.getFields().iterator(); while (fieldIt.hasNext()) { SootField f = (SootField) fieldIt.next(); if (f.isPhantom()) continue; Type t = f.getType(); if (t instanceof RefType) { String fieldPackage = ((RefType) t).getSootClass().toString(); if (!importList.contains(fieldPackage)) importList.add(fieldPackage); } } Iterator<String> pit = importList.iterator(); List<String> toImport = new ArrayList<String>(); while (pit.hasNext()) { /* * dont import any file which has currentPackage.className * dont import any file which starts with java.lang */ String temp = (String) pit.next(); // System.out.println("temp is "+temp); if (temp.indexOf("java.lang") > -1) { // problem is that we need to import sub packages java.lang.ref // for instance if the type is java.lang.ref.WeakReference String tempClassName = RemoveFullyQualifiedName.getClassName(temp); if (temp.equals("java.lang." + tempClassName)) { // System.out.println("temp was not printed as it belongs to java.lang"); continue; } } if (curPackage.length() > 0 && temp.indexOf(curPackage) > -1) { // System.out.println("here "+temp); continue; } if (cl.toString().equals(temp)) continue; // System.out.println("printing"+); toImport.add(temp); } /* * Check that we are not importing two classes with the same last name * If yes then remove explicit import and import the whole package * else output explicit import statement */ Iterator it = toImport.iterator(); while (it.hasNext()) { String temp = (String) it.next(); if (RemoveFullyQualifiedName.containsMultiple(toImport.iterator(), temp, null)) { // there are atleast two imports with this className // import package add * if (temp.lastIndexOf('.') > -1) { temp = temp.substring(0, temp.lastIndexOf('.')); out.println("import " + temp + ".*;"); } else throw new DecompilationException("Cant find the DOT . for fullyqualified name"); } else { if (temp.lastIndexOf('.') == -1) { // dot not found this is a class belonging to this package so dont add } else out.println("import " + temp + ";"); } } boolean addNewLine = false; addNewLine = true; // out.println("import " + temp + ";"); if (addNewLine) out.println(); /*if (!packagesUsed.isEmpty()) out.println(); packagesUsed.add("java.lang"); packagesUsed.add(curPackage); */ Dava.v().set_CurrentPackageContext(importList); // Dava.v().set_CurrentPackageContext(packagesUsed); Dava.v().set_CurrentPackage(curPackage); } // Print class name + modifiers { String classPrefix = ""; classPrefix = classPrefix + " " + Modifier.toString(cl.getModifiers()); classPrefix = classPrefix.trim(); if (!cl.isInterface()) { classPrefix = classPrefix + " class"; classPrefix = classPrefix.trim(); } out.print(classPrefix + " " + cl.getShortJavaStyleName()); } // Print extension if (cl.hasSuperclass() && !(cl.getSuperclass().getName().equals("java.lang.Object"))) { String superClassName = cl.getSuperclass().getName(); // Nomair Naeem 8th Feb 2006 // also check if the super class name is not a fully qualified // name. in which case if the package is imported no need for // the long name superClassName = RemoveFullyQualifiedName.getReducedName(importList, superClassName, cl.getType()); out.print(" extends " + superClassName + ""); } // Print interfaces { Iterator<SootClass> interfaceIt = cl.getInterfaces().iterator(); if (interfaceIt.hasNext()) { if (cl.isInterface()) out.print(" extends "); else out.print(" implements "); out.print("" + (interfaceIt.next()).getName() + ""); while (interfaceIt.hasNext()) out.print(", " + (interfaceIt.next()).getName() + ""); } } out.println(); out.println("{"); // Print fields { Iterator<SootField> fieldIt = cl.getFields().iterator(); if (fieldIt.hasNext()) { while (fieldIt.hasNext()) { SootField f = fieldIt.next(); if (f.isPhantom()) continue; String declaration = null; Type fieldType = f.getType(); String qualifiers = Modifier.toString(f.getModifiers()) + " "; qualifiers += RemoveFullyQualifiedName.getReducedName(importList, fieldType.toString(), fieldType); qualifiers = qualifiers.trim(); if (qualifiers.equals("")) declaration = Scene.v().quotedNameOf(f.getName()); else declaration = qualifiers + " " + Scene.v().quotedNameOf(f.getName()) + ""; if (f.isFinal() && f.isStatic()) { if (fieldType instanceof DoubleType && f.hasTag("DoubleConstantValueTag")) { double val = ((DoubleConstantValueTag) f.getTag("DoubleConstantValueTag")).getDoubleValue(); out.println(" " + declaration + " = " + val + ";"); } else if (fieldType instanceof FloatType && f.hasTag("FloatConstantValueTag")) { float val = ((FloatConstantValueTag) f.getTag("FloatConstantValueTag")).getFloatValue(); out.println(" " + declaration + " = " + val + "f;"); } else if (fieldType instanceof LongType && f.hasTag("LongConstantValueTag")) { long val = ((LongConstantValueTag) f.getTag("LongConstantValueTag")).getLongValue(); out.println(" " + declaration + " = " + val + "l;"); } else if (fieldType instanceof CharType && f.hasTag("IntegerConstantValueTag")) { int val = ((IntegerConstantValueTag) f.getTag("IntegerConstantValueTag")).getIntValue(); out.println(" " + declaration + " = '" + ((char) val) + "';"); } else if (fieldType instanceof BooleanType && f.hasTag("IntegerConstantValueTag")) { int val = ((IntegerConstantValueTag) f.getTag("IntegerConstantValueTag")).getIntValue(); if (val == 0) out.println(" " + declaration + " = false;"); else out.println(" " + declaration + " = true;"); } else if ((fieldType instanceof IntType || fieldType instanceof ByteType || fieldType instanceof ShortType) && f.hasTag("IntegerConstantValueTag")) { int val = ((IntegerConstantValueTag) f.getTag("IntegerConstantValueTag")).getIntValue(); out.println(" " + declaration + " = " + val + ";"); } else if (f.hasTag("StringConstantValueTag")) { String val = ((StringConstantValueTag) f.getTag("StringConstantValueTag")).getStringValue(); out.println(" " + declaration + " = \"" + val + "\";"); } else { // System.out.println("Couldnt find type of // field"+f.getDeclaration()); out.println(" " + declaration + ";"); } } // field is static final else { out.println(" " + declaration + ";"); } } } } // Print methods { Iterator<SootMethod> methodIt = cl.methodIterator(); if (methodIt.hasNext()) { if (cl.getMethodCount() != 0) out.println(); while (methodIt.hasNext()) { SootMethod method = (SootMethod) methodIt.next(); if (method.isPhantom()) continue; if (!Modifier.isAbstract(method.getModifiers()) && !Modifier.isNative(method.getModifiers())) { if (!method.hasActiveBody()) throw new RuntimeException("method " + method.getName() + " has no active body!"); else printTo(method.getActiveBody(), out); if (methodIt.hasNext()) out.println(); } else { // if method is abstract then print the declaration out.print(" "); out.print(method.getDavaDeclaration()); out.println(";"); if (methodIt.hasNext()) out.println(); } } } } /* * January 23rd, 2006 * In trying to handle the suepr class problem we need to introduce an inner class * Instead of creating a data structure for it we are right now just going to print it in the form * of a string * * It would be interesting to later have an internal inner class structure so that we could * decompile inner classes into inner classes */ if (G.v().SootClassNeedsDavaSuperHandlerClass.contains(cl)) { out.println("\n private static class DavaSuperHandler{"); out.println(" java.util.Vector myVector = new java.util.Vector();"); out.println("\n public Object get(int pos){"); out.println(" return myVector.elementAt(pos);"); out.println(" }"); out.println("\n public void store(Object obj){"); out.println(" myVector.add(obj);"); out.println(" }"); out.println(" }"); } out.println("}"); }