Exemple #1
0
  /**
   * Given an abstract dispatch to an object of type c and a method m, gives a list of possible
   * receiver methods.
   */
  public List resolveAbstractDispatch(SootClass c, SootMethod m) {
    c.checkLevel(SootClass.HIERARCHY);
    m.getDeclaringClass().checkLevel(SootClass.HIERARCHY);
    checkState();

    Iterator<SootClass> classesIt = null;

    if (c.isInterface()) {
      classesIt = getImplementersOf(c).iterator();
      HashSet<SootClass> classes = new HashSet<SootClass>();
      while (classesIt.hasNext()) classes.addAll(getSubclassesOfIncluding(classesIt.next()));
      classesIt = classes.iterator();
    } else classesIt = getSubclassesOfIncluding(c).iterator();

    ArraySet s = new ArraySet();

    while (classesIt.hasNext()) {
      SootClass cl = classesIt.next();
      if (Modifier.isAbstract(cl.getModifiers())) continue;
      s.add(resolveConcreteDispatch(cl, m));
    }

    List l = new ArrayList();
    l.addAll(s);
    return Collections.unmodifiableList(l);
  }
  public void staticBlockInlining(SootClass sootClass) {
    this.sootClass = sootClass;
    // retrieve the clinit method if any for sootClass
    if (!sootClass.declaresMethod("void <clinit>()")) {
      System.out.println("no clinit");
      return;
    }

    SootMethod clinit = sootClass.getMethod("void <clinit>()");
    // System.out.println(clinit);

    // retireve the active body
    if (!clinit.hasActiveBody())
      throw new RuntimeException("method " + clinit.getName() + " has no active body!");

    Body clinitBody = clinit.getActiveBody();

    Chain units = ((DavaBody) clinitBody).getUnits();

    if (units.size() != 1) {
      throw new RuntimeException("DavaBody AST doesn't have single root.");
    }

    ASTNode AST = (ASTNode) units.getFirst();
    if (!(AST instanceof ASTMethodNode))
      throw new RuntimeException("Starting node of DavaBody AST is not an ASTMethodNode");

    AST.apply(new MethodCallFinder(this));
  }
Exemple #3
0
  /** Returns a list of direct subinterfaces of c. */
  public List getDirectSubinterfacesOf(SootClass c) {
    c.checkLevel(SootClass.HIERARCHY);
    if (!c.isInterface()) throw new RuntimeException("interface needed!");

    checkState();

    return interfaceToDirSubinterfaces.get(c);
  }
Exemple #4
0
  /** Returns a list of direct implementers of c, excluding itself. */
  public List getDirectImplementersOf(SootClass i) {
    i.checkLevel(SootClass.HIERARCHY);
    if (!i.isInterface()) throw new RuntimeException("interface needed; got " + i);

    checkState();

    return Collections.unmodifiableList(interfaceToDirImplementers.get(i));
  }
Exemple #5
0
  /** Returns a list of direct subclasses of c, excluding c. */
  public List getDirectSubclassesOf(SootClass c) {
    c.checkLevel(SootClass.HIERARCHY);
    if (c.isInterface()) throw new RuntimeException("class needed!");

    checkState();

    return Collections.unmodifiableList(classToDirSubclasses.get(c));
  }
Exemple #6
0
  /** Returns a list of subinterfaces of c, including itself. */
  public List<SootClass> getSubinterfacesOfIncluding(SootClass c) {
    c.checkLevel(SootClass.HIERARCHY);
    if (!c.isInterface()) throw new RuntimeException("interface needed!");

    List<SootClass> l = new ArrayList<SootClass>();
    l.addAll(getSubinterfacesOf(c));
    l.add(c);

    return Collections.unmodifiableList(l);
  }
Exemple #7
0
  /** Returns a list of direct subclasses of c, including c. */
  public List<SootClass> getDirectSubclassesOfIncluding(SootClass c) {
    c.checkLevel(SootClass.HIERARCHY);
    if (c.isInterface()) throw new RuntimeException("class needed!");

    checkState();

    List<SootClass> l = new ArrayList<SootClass>();
    l.addAll(classToDirSubclasses.get(c));
    l.add(c);

    return Collections.unmodifiableList(l);
  }
Exemple #8
0
 /** Returns true if the method m is visible from code in the class from. */
 public boolean isVisible(SootClass from, SootMethod m) {
   from.checkLevel(SootClass.HIERARCHY);
   m.getDeclaringClass().checkLevel(SootClass.HIERARCHY);
   if (m.isPublic()) return true;
   if (m.isPrivate()) {
     return from.equals(m.getDeclaringClass());
   }
   if (m.isProtected()) {
     return isClassSubclassOfIncluding(from, m.getDeclaringClass());
   }
   // m is package
   return from.getJavaPackageName().equals(m.getDeclaringClass().getJavaPackageName());
   // || isClassSubclassOfIncluding( from, m.getDeclaringClass() );
 }
Exemple #9
0
 /** Returns a list of superclasses of c, including itself. */
 public List<SootClass> getSuperclassesOfIncluding(SootClass c) {
   c.checkLevel(SootClass.HIERARCHY);
   List<SootClass> l = getSuperclassesOf(c);
   ArrayList<SootClass> al = new ArrayList<SootClass>();
   al.add(c);
   al.addAll(l);
   return Collections.unmodifiableList(al);
 }
Exemple #10
0
  // This method is deprecated. Use soot.util.JasminOutputStream instead.
  public void writeXXXDeprecated(SootClass cl, String outputDir) {
    String outputDirWithSep = "";

    if (!outputDir.equals("")) outputDirWithSep = outputDir + fileSeparator;

    try {
      File tempFile = new File(outputDirWithSep + cl.getName() + ".jasmin");

      FileOutputStream streamOut = new FileOutputStream(tempFile);

      PrintWriter writerOut = new PrintWriter(new EscapedWriter(new OutputStreamWriter(streamOut)));

      if (cl.containsBafBody()) new soot.baf.JasminClass(cl).print(writerOut);
      else new soot.jimple.JasminClass(cl).print(writerOut);

      writerOut.close();

      if (Options.v().time()) Timers.v().assembleJasminTimer.start();

      // Invoke jasmin
      {
        String[] args;

        if (outputDir.equals("")) {
          args = new String[1];

          args[0] = cl.getName() + ".jasmin";
        } else {
          args = new String[3];

          args[0] = "-d";
          args[1] = outputDir;
          args[2] = outputDirWithSep + cl.getName() + ".jasmin";
        }

        jasmin.Main.main(args);
      }

      tempFile.delete();

      if (Options.v().time()) Timers.v().assembleJasminTimer.end();

    } catch (IOException e) {
      throw new RuntimeException("Could not produce new classfile! (" + e + ")");
    }
  }
  public static void main(String args[]) {
    // Set classPath
    String exemplePath = "/Users/gamyot/Documents/workspace/Soot_Exemples/src/";
    String objectPath = "/System/Library/Frameworks/JavaVM.framework/Classes/classes.jar";
    String tracePath = "/Users/gamyot/Documents/workspace/SootInstrumenter/src/";

    Scene.v().setSootClassPath(".:" + objectPath + ":" + exemplePath + ":" + tracePath);

    Scene.v().loadClassAndSupport("java.lang.Object");
    Scene.v().loadClassAndSupport("java.lang.System");

    // Set up the class we’re working with
    SootClass c = Scene.v().loadClassAndSupport("MyExemples.ExempleBasic");
    c.setApplicationClass();

    // Get methods
    Iterator<SootMethod> methodIterator = c.methodIterator();
    while (methodIterator.hasNext()) methodList.add(methodIterator.next());
    // Iterate through the method list
    for (SootMethod m : methodList) {
      Body body = m.retrieveActiveBody();
      PatchingChain<Unit> unitList = body.getUnits();
      // get the all the "if statements" Units
      List<Unit> ifStmtList = searchIfStmts(body);

      // for each "if statement" unit, instrument and add the instrumentation code right after
      for (Unit ifStmtUnit : ifStmtList) {
        // Chain<Unit> instrumentedChain = generateInstrumentationUnits(ifStmtUnit, body);
        // unitList.insertAfter(instrumentedChain, ifStmtUnit);
        Chain<Unit> testChain = generateInstrumentationUnits(ifStmtUnit, body);
        unitList.insertAfter(testChain, ifStmtUnit);
      }
      // Output all the units for this method on terminal
      String methodName = m.getName();
      System.out.println(
          "____Method: \"" + methodName + "\"__________________________________________________");
      LoadAndGenerate.printAllUnits(body);
    }

    try {
      LoadAndGenerate.outputClassToBinary(c);
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
Exemple #12
0
  /**
   * Given an object of actual type C (o = new C()), returns the method which will be called on an
   * o.f() invocation.
   */
  public SootMethod resolveConcreteDispatch(SootClass concreteType, SootMethod m) {
    concreteType.checkLevel(SootClass.HIERARCHY);
    m.getDeclaringClass().checkLevel(SootClass.HIERARCHY);
    checkState();

    if (concreteType.isInterface()) throw new RuntimeException("class needed!");

    Iterator<SootClass> it = getSuperclassesOfIncluding(concreteType).iterator();
    String methodSig = m.getSubSignature();

    while (it.hasNext()) {
      SootClass c = it.next();
      if (c.declaresMethod(methodSig) && isVisible(c, m)) {
        return c.getMethod(methodSig);
      }
    }
    throw new RuntimeException(
        "could not resolve concrete dispatch!\nType: " + concreteType + "\nMethod: " + m);
  }
Exemple #13
0
  /** Returns a list of implementers of c, excluding itself. */
  public List<SootClass> getImplementersOf(SootClass i) {
    i.checkLevel(SootClass.HIERARCHY);
    if (!i.isInterface()) throw new RuntimeException("interface needed; got " + i);

    checkState();

    Iterator<SootClass> it = getSubinterfacesOfIncluding(i).iterator();
    ArraySet set = new ArraySet();

    while (it.hasNext()) {
      SootClass c = it.next();

      set.addAll(getDirectImplementersOf(c));
    }

    ArrayList l = new ArrayList();
    l.addAll(set);

    return Collections.unmodifiableList(l);
  }
Exemple #14
0
  public void caseAFile(AFile node) {
    inAFile(node);
    {
      Object temp[] = node.getModifier().toArray();
      for (int i = 0; i < temp.length; i++) {
        ((PModifier) temp[i]).apply(this);
      }
    }
    if (node.getFileType() != null) {
      node.getFileType().apply(this);
    }
    if (node.getClassName() != null) {
      node.getClassName().apply(this);
    }

    String className = (String) mProductions.removeLast();

    if (mSootClass == null) {
      mSootClass = new SootClass(className);
      mSootClass.setResolvingLevel(SootClass.BODIES);
    } else {
      if (!mSootClass.getName().equals(className))
        throw new RuntimeException(
            "Invalid SootClass for this JimpleAST. The SootClass provided is of type: >"
                + mSootClass.getName()
                + "< whereas this parse tree is for type: >"
                + className
                + "<");
    }

    if (node.getExtendsClause() != null) {
      node.getExtendsClause().apply(this);
    }
    if (node.getImplementsClause() != null) {
      node.getImplementsClause().apply(this);
    }
    if (node.getFileBody() != null) {
      node.getFileBody().apply(this);
    }
    outAFile(node);
  }
Exemple #15
0
  /** Returns a list of subinterfaces of c, excluding itself. */
  public List<SootClass> getSubinterfacesOf(SootClass c) {
    c.checkLevel(SootClass.HIERARCHY);
    if (!c.isInterface()) throw new RuntimeException("interface needed!");

    checkState();

    // If already cached, return the value.
    if (interfaceToSubinterfaces.get(c) != null) return interfaceToSubinterfaces.get(c);

    // Otherwise, build up the hashmap.
    List<SootClass> l = new ArrayList<SootClass>();

    ListIterator it = interfaceToDirSubinterfaces.get(c).listIterator();
    while (it.hasNext()) {
      l.addAll(getSubinterfacesOfIncluding((SootClass) it.next()));
    }

    interfaceToSubinterfaces.put(c, Collections.unmodifiableList(l));

    return Collections.unmodifiableList(l);
  }
Exemple #16
0
  /*
    member =
    {field}  modifier* type name semicolon |
    {method} modifier* type name l_paren parameter_list? r_paren throws_clause? method_body;
  */
  public void outAFieldMember(AFieldMember node) {
    int modifier = 0;
    Type type = null;
    String name = null;

    name = (String) mProductions.removeLast();
    type = (Type) mProductions.removeLast();

    modifier = processModifiers(node.getModifier());

    SootField f = new SootField(name, type, modifier);
    mSootClass.addField(f);
  }
Exemple #17
0
  public void outAFile(AFile node) {
    // not not pop members; they have been taken care of.
    List implementsList = null;
    String superClass = null;

    String classType = null;

    if (node.getImplementsClause() != null) {
      implementsList = (List) mProductions.removeLast();
    }
    if (node.getExtendsClause() != null) {
      superClass = (String) mProductions.removeLast();
    }

    classType = (String) mProductions.removeLast();

    int modifierCount = node.getModifier().size();

    int modifierFlags = processModifiers(node.getModifier());

    if (classType.equals("interface")) modifierFlags |= Modifier.INTERFACE;

    mSootClass.setModifiers(modifierFlags);

    if (superClass != null) {
      mSootClass.setSuperclass(mResolver.makeClassRef(superClass));
    }

    if (implementsList != null) {
      Iterator implIt = implementsList.iterator();
      while (implIt.hasNext()) {
        SootClass interfaceClass = mResolver.makeClassRef((String) implIt.next());
        mSootClass.addInterface(interfaceClass);
      }
    }

    mProductions.addLast(mSootClass);
  }
Exemple #18
0
  /** Returns a list of subclasses of c, excluding itself. */
  public List<SootClass> getSubclassesOf(SootClass c) {
    c.checkLevel(SootClass.HIERARCHY);
    if (c.isInterface()) throw new RuntimeException("class needed!");

    checkState();

    // If already cached, return the value.
    if (classToSubclasses.get(c) != null) return classToSubclasses.get(c);

    // Otherwise, build up the hashmap.
    List<SootClass> l = new ArrayList<SootClass>();

    ListIterator it = classToDirSubclasses.get(c).listIterator();
    while (it.hasNext()) {
      SootClass cls = (SootClass) it.next();
      if (cls.resolvingLevel() < SootClass.HIERARCHY) continue;
      l.addAll(getSubclassesOfIncluding(cls));
    }

    l = Collections.unmodifiableList(l);
    classToSubclasses.put(c, l);

    return l;
  }
  public ASTMethodNode inline(SootMethod maybeInline) {
    // check if this method should be inlined

    if (sootClass != null) {
      // 1, method should belong to the same class as the clinit method
      if (sootClass.declaresMethod(maybeInline.getSubSignature())) {
        // System.out.println("The method invoked is from the same class");
        // 2, method should be static

        if (Modifier.isStatic(maybeInline.getModifiers())) {
          // decided to inline
          // send the ASTMethod node of the TO BE INLINED METHOD

          // retireve the active body
          if (!maybeInline.hasActiveBody())
            throw new RuntimeException("method " + maybeInline.getName() + " has no active body!");

          Body bod = maybeInline.getActiveBody();

          Chain units = ((DavaBody) bod).getUnits();

          if (units.size() != 1) {
            throw new RuntimeException("DavaBody AST doesn't have single root.");
          }

          ASTNode ASTtemp = (ASTNode) units.getFirst();
          if (!(ASTtemp instanceof ASTMethodNode))
            throw new RuntimeException("Starting node of DavaBody AST is not an ASTMethodNode");

          // restricting to methods which do not have any variables declared
          ASTMethodNode toReturn = (ASTMethodNode) ASTtemp;

          ASTStatementSequenceNode declarations = toReturn.getDeclarations();
          if (declarations.getStatements().size() == 0) {
            // inline only if there are no declarations in the method inlined
            System.out.println("No declarations in the method. we can inline this method");
            return toReturn;
          }
        }
      }
    }
    return null; // meaning dont inline
  }
Exemple #20
0
  public void outAMethodMember(AMethodMember node) {
    int modifier = 0;
    Type type;
    String name;
    List parameterList = null;
    List throwsClause = null;
    JimpleBody methodBody = null;

    if (node.getMethodBody() instanceof AFullMethodBody)
      methodBody = (JimpleBody) mProductions.removeLast();

    if (node.getThrowsClause() != null) throwsClause = (List) mProductions.removeLast();

    if (node.getParameterList() != null) {
      parameterList = (List) mProductions.removeLast();
    } else {
      parameterList = new ArrayList();
    }

    Object o = mProductions.removeLast();

    name = (String) o;
    type = (Type) mProductions.removeLast();
    modifier = processModifiers(node.getModifier());

    SootMethod method;

    if (throwsClause != null)
      method = new SootMethod(name, parameterList, type, modifier, throwsClause);
    else method = new SootMethod(name, parameterList, type, modifier);

    mSootClass.addMethod(method);

    if (method.isConcrete()) {
      methodBody.setMethod(method);
      method.setActiveBody(methodBody);

    } else if (node.getMethodBody() instanceof AFullMethodBody)
      throw new RuntimeException("Impossible: !concrete => ! instanceof");
  }
Exemple #21
0
  /** Returns a list of strict superclasses of c, starting with c's parent. */
  public List<SootClass> getSuperclassesOf(SootClass c) {
    c.checkLevel(SootClass.HIERARCHY);
    if (c.isInterface()) throw new RuntimeException("class needed!");

    checkState();

    ArrayList<SootClass> l = new ArrayList<SootClass>();
    SootClass cl = c;

    while (cl.hasSuperclass()) {
      l.add(cl.getSuperclass());
      cl = cl.getSuperclass();
    }

    return Collections.unmodifiableList(l);
  }
Exemple #22
0
  /** Constructs a hierarchy from the current scene. */
  public Hierarchy() {
    this.sc = Scene.v();
    state = sc.getState();

    // Well, this used to be describable by 'Duh'.
    // Construct the subclasses hierarchy and the subinterfaces hierarchy.
    {
      Chain allClasses = sc.getClasses();

      classToSubclasses = new HashMap<SootClass, List<SootClass>>(allClasses.size() * 2 + 1, 0.7f);
      interfaceToSubinterfaces =
          new HashMap<SootClass, List<SootClass>>(allClasses.size() * 2 + 1, 0.7f);

      classToDirSubclasses = new HashMap<SootClass, List>(allClasses.size() * 2 + 1, 0.7f);
      interfaceToDirSubinterfaces = new HashMap<SootClass, List>(allClasses.size() * 2 + 1, 0.7f);
      interfaceToDirImplementers = new HashMap<SootClass, List>(allClasses.size() * 2 + 1, 0.7f);

      Iterator classesIt = allClasses.iterator();
      while (classesIt.hasNext()) {
        SootClass c = (SootClass) classesIt.next();
        if (c.resolvingLevel() < SootClass.HIERARCHY) continue;

        if (c.isInterface()) {
          interfaceToDirSubinterfaces.put(c, new ArrayList());
          interfaceToDirImplementers.put(c, new ArrayList());
        } else classToDirSubclasses.put(c, new ArrayList());
      }

      classesIt = allClasses.iterator();
      while (classesIt.hasNext()) {
        SootClass c = (SootClass) classesIt.next();
        if (c.resolvingLevel() < SootClass.HIERARCHY) continue;

        if (c.hasSuperclass()) {
          if (c.isInterface()) {
            Iterator subIt = c.getInterfaces().iterator();

            while (subIt.hasNext()) {
              SootClass i = (SootClass) subIt.next();
              if (c.resolvingLevel() < SootClass.HIERARCHY) continue;
              List<SootClass> l = interfaceToDirSubinterfaces.get(i);
              l.add(c);
            }
          } else {
            List<SootClass> l = classToDirSubclasses.get(c.getSuperclass());
            l.add(c);

            Iterator subIt = c.getInterfaces().iterator();

            while (subIt.hasNext()) {
              SootClass i = (SootClass) subIt.next();
              if (c.resolvingLevel() < SootClass.HIERARCHY) continue;
              l = interfaceToDirImplementers.get(i);
              l.add(c);
            }
          }
        }
      }

      // Fill the directImplementers lists with subclasses.
      {
        classesIt = allClasses.iterator();
        while (classesIt.hasNext()) {
          SootClass c = (SootClass) classesIt.next();
          if (c.resolvingLevel() < SootClass.HIERARCHY) continue;
          if (c.isInterface()) {
            List<SootClass> imp = interfaceToDirImplementers.get(c);
            Set<SootClass> s = new ArraySet();

            Iterator<SootClass> impIt = imp.iterator();
            while (impIt.hasNext()) {
              SootClass c0 = impIt.next();
              if (c.resolvingLevel() < SootClass.HIERARCHY) continue;
              s.addAll(getSubclassesOfIncluding(c0));
            }

            imp.clear();
            imp.addAll(s);
          }
        }
      }

      classesIt = allClasses.iterator();
      while (classesIt.hasNext()) {
        SootClass c = (SootClass) classesIt.next();
        if (c.resolvingLevel() < SootClass.HIERARCHY) continue;

        if (c.isInterface()) {
          interfaceToDirSubinterfaces.put(
              c, Collections.unmodifiableList(interfaceToDirSubinterfaces.get(c)));
          interfaceToDirImplementers.put(
              c, Collections.unmodifiableList(interfaceToDirImplementers.get(c)));
        } else
          classToDirSubclasses.put(c, Collections.unmodifiableList(classToDirSubclasses.get(c)));
      }
    }
  }
Exemple #23
0
 /** Returns the most specific type which is an ancestor of both c1 and c2. */
 public SootClass getLeastCommonSuperclassOf(SootClass c1, SootClass c2) {
   c1.checkLevel(SootClass.HIERARCHY);
   c2.checkLevel(SootClass.HIERARCHY);
   throw new RuntimeException("Not implemented yet!");
 }
Exemple #24
0
 /** Returns true if child is a direct subinterface of possibleParent. */
 public boolean isInterfaceDirectSubinterfaceOf(SootClass child, SootClass possibleParent) {
   child.checkLevel(SootClass.HIERARCHY);
   possibleParent.checkLevel(SootClass.HIERARCHY);
   return getDirectSubinterfacesOf(possibleParent).contains(child);
 }
Exemple #25
0
 /** Returns true if parent is, or is a superclass of, possibleChild. */
 public boolean isClassSuperclassOfIncluding(SootClass parent, SootClass possibleChild) {
   parent.checkLevel(SootClass.HIERARCHY);
   possibleChild.checkLevel(SootClass.HIERARCHY);
   return getSubclassesOfIncluding(parent).contains(possibleChild);
 }
Exemple #26
0
 /** Returns true if child is a subclass of possibleParent. */
 public boolean isClassSubclassOf(SootClass child, SootClass possibleParent) {
   child.checkLevel(SootClass.HIERARCHY);
   possibleParent.checkLevel(SootClass.HIERARCHY);
   return getSuperclassesOf(child).contains(possibleParent);
 }
Exemple #27
0
  public void printTo(SootClass cl, PrintWriter out) {
    // add jimple line number tags
    setJimpleLnNum(1);

    // Print class name + modifiers
    {
      StringTokenizer st = new StringTokenizer(Modifier.toString(cl.getModifiers()));
      while (st.hasMoreTokens()) {
        String tok = (String) st.nextToken();
        if (cl.isInterface() && tok.equals("abstract")) continue;
        out.print(tok + " ");
      }

      String classPrefix = "";

      if (!cl.isInterface()) {
        classPrefix = classPrefix + " class";
        classPrefix = classPrefix.trim();
      }

      out.print(classPrefix + " " + Scene.v().quotedNameOf(cl.getName()) + "");
    }

    // Print extension
    {
      if (cl.hasSuperclass())
        out.print(" extends " + Scene.v().quotedNameOf(cl.getSuperclass().getName()) + "");
    }

    // Print interfaces
    {
      Iterator interfaceIt = cl.getInterfaces().iterator();

      if (interfaceIt.hasNext()) {
        out.print(" implements ");

        out.print("" + Scene.v().quotedNameOf(((SootClass) interfaceIt.next()).getName()) + "");

        while (interfaceIt.hasNext()) {
          out.print(",");
          out.print(" " + Scene.v().quotedNameOf(((SootClass) interfaceIt.next()).getName()) + "");
        }
      }
    }

    out.println();
    incJimpleLnNum();
    /*        if (!addJimpleLn()) {
        Iterator clTagsIt = cl.getTags().iterator();
        while (clTagsIt.hasNext()) {
            final Tag t = (Tag)clTagsIt.next();
            out.println(t);
        }
    }*/
    out.println("{");
    incJimpleLnNum();
    if (Options.v().print_tags_in_output()) {
      Iterator cTagIterator = cl.getTags().iterator();
      while (cTagIterator.hasNext()) {
        Tag t = (Tag) cTagIterator.next();
        out.print("/*");
        out.print(t.toString());
        out.println("*/");
      }
    }

    // Print fields
    {
      Iterator fieldIt = cl.getFields().iterator();

      if (fieldIt.hasNext()) {
        while (fieldIt.hasNext()) {
          SootField f = (SootField) fieldIt.next();

          if (f.isPhantom()) continue;

          if (Options.v().print_tags_in_output()) {
            Iterator fTagIterator = f.getTags().iterator();
            while (fTagIterator.hasNext()) {
              Tag t = (Tag) fTagIterator.next();
              out.print("/*");
              out.print(t.toString());
              out.println("*/");
            }
          }
          out.println("    " + f.getDeclaration() + ";");
          if (addJimpleLn()) {
            setJimpleLnNum(addJimpleLnTags(getJimpleLnNum(), f));
          }

          // incJimpleLnNum();
        }
      }
    }

    // Print methods
    {
      Iterator methodIt = cl.methodIterator();

      if (methodIt.hasNext()) {
        if (cl.getMethodCount() != 0) {
          out.println();
          incJimpleLnNum();
        }

        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 if (Options.v().print_tags_in_output()) {
              Iterator mTagIterator = method.getTags().iterator();
              while (mTagIterator.hasNext()) {
                Tag t = (Tag) mTagIterator.next();
                out.print("/*");
                out.print(t.toString());
                out.println("*/");
              }
            }
            printTo(method.getActiveBody(), out);

            if (methodIt.hasNext()) {
              out.println();
              incJimpleLnNum();
            }
          } else {

            if (Options.v().print_tags_in_output()) {
              Iterator mTagIterator = method.getTags().iterator();
              while (mTagIterator.hasNext()) {
                Tag t = (Tag) mTagIterator.next();
                out.print("/*");
                out.print(t.toString());
                out.println("*/");
              }
            }

            out.print("    ");
            out.print(method.getDeclaration());
            out.println(";");
            incJimpleLnNum();
            if (methodIt.hasNext()) {
              out.println();
              incJimpleLnNum();
            }
          }
        }
      }
    }
    out.println("}");
    incJimpleLnNum();
  }