Ejemplo n.º 1
0
  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();
  }
Ejemplo n.º 2
0
  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("}");
  }