/** Returns the ClassMemberSpecification currently represented in this dialog. */
  public ClassMemberSpecification getClassMemberSpecification() {
    String name = nameTextField.getText();
    String type = typeTextField.getText();
    String arguments = argumentsTextField.getText();

    if (name.equals("") || name.equals("*")) {
      name = null;
    }

    if (type.equals("") || type.equals("*")) {
      type = null;
    }

    if (name != null || type != null) {
      if (isField) {
        if (type == null) {
          type = ClassConstants.EXTERNAL_TYPE_INT;
        }

        type = ClassUtil.internalType(type);
      } else {
        if (type == null) {
          type = ClassConstants.EXTERNAL_TYPE_VOID;
        }

        type = ClassUtil.internalMethodDescriptor(type, ListUtil.commaSeparatedList(arguments));
      }
    }

    ClassMemberSpecification classMemberSpecification =
        new ClassMemberSpecification(0, 0, name, type);

    // Also get the access radio button settings.
    getClassMemberSpecificationRadioButtons(
        classMemberSpecification, ClassConstants.INTERNAL_ACC_PUBLIC, publicRadioButtons);
    getClassMemberSpecificationRadioButtons(
        classMemberSpecification, ClassConstants.INTERNAL_ACC_PRIVATE, privateRadioButtons);
    getClassMemberSpecificationRadioButtons(
        classMemberSpecification, ClassConstants.INTERNAL_ACC_PROTECTED, protectedRadioButtons);
    getClassMemberSpecificationRadioButtons(
        classMemberSpecification, ClassConstants.INTERNAL_ACC_STATIC, staticRadioButtons);
    getClassMemberSpecificationRadioButtons(
        classMemberSpecification, ClassConstants.INTERNAL_ACC_FINAL, finalRadioButtons);
    getClassMemberSpecificationRadioButtons(
        classMemberSpecification, ClassConstants.INTERNAL_ACC_VOLATILE, volatileRadioButtons);
    getClassMemberSpecificationRadioButtons(
        classMemberSpecification, ClassConstants.INTERNAL_ACC_TRANSIENT, transientRadioButtons);
    getClassMemberSpecificationRadioButtons(
        classMemberSpecification,
        ClassConstants.INTERNAL_ACC_SYNCHRONIZED,
        synchronizedRadioButtons);
    getClassMemberSpecificationRadioButtons(
        classMemberSpecification, ClassConstants.INTERNAL_ACC_NATIVE, nativeRadioButtons);
    getClassMemberSpecificationRadioButtons(
        classMemberSpecification, ClassConstants.INTERNAL_ACC_ABSTRACT, abstractRadioButtons);
    getClassMemberSpecificationRadioButtons(
        classMemberSpecification, ClassConstants.INTERNAL_ACC_STRICT, strictRadioButtons);

    return classMemberSpecification;
  }
  public void visitProgramClass(ProgramClass programClass) {
    String name = programClass.getName();
    String newName = ClassObfuscator.newClassName(programClass);

    ps.println(
        ClassUtil.externalClassName(name) + " -> " + ClassUtil.externalClassName(newName) + ":");

    // Print out the class members.
    programClass.fieldsAccept(this);
    programClass.methodsAccept(this);
  }
  /** Returns a shrunk descriptor or signature of the given method. */
  private String shrinkDescriptor(Method method, String descriptor) {
    // All parameters of non-static methods are shifted by one in the local
    // variable frame.
    int parameterIndex =
        (method.getAccessFlags() & ClassConstants.INTERNAL_ACC_STATIC) != 0 ? 0 : 1;

    // Go over the parameters.
    InternalTypeEnumeration internalTypeEnumeration = new InternalTypeEnumeration(descriptor);

    StringBuffer newDescriptorBuffer = new StringBuffer();

    newDescriptorBuffer.append(internalTypeEnumeration.formalTypeParameters());
    newDescriptorBuffer.append(ClassConstants.INTERNAL_METHOD_ARGUMENTS_OPEN);

    while (internalTypeEnumeration.hasMoreTypes()) {
      String type = internalTypeEnumeration.nextType();
      if (ParameterUsageMarker.isParameterUsed(method, parameterIndex)) {
        newDescriptorBuffer.append(type);
      } else if (DEBUG) {
        System.out.println("  Deleting parameter #" + parameterIndex + " [" + type + "]");
      }

      parameterIndex += ClassUtil.isInternalCategory2Type(type) ? 2 : 1;
    }

    newDescriptorBuffer.append(ClassConstants.INTERNAL_METHOD_ARGUMENTS_CLOSE);
    newDescriptorBuffer.append(internalTypeEnumeration.returnType());

    return newDescriptorBuffer.toString();
  }
예제 #4
0
  public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute) {
    //        DEBUG =
    //            clazz.getName().equals("abc/Def") &&
    //            method.getName(clazz).equals("abc");

    // The minimum variable size is determined by the arguments.
    codeAttribute.u2maxLocals =
        ClassUtil.internalMethodParameterSize(method.getDescriptor(clazz), method.getAccessFlags());

    if (DEBUG) {
      System.out.println(
          "VariableSizeUpdater: "
              + clazz.getName()
              + "."
              + method.getName(clazz)
              + method.getDescriptor(clazz));
      System.out.println("  Max locals: " + codeAttribute.u2maxLocals + " <- parameters");
    }

    // Go over all instructions.
    codeAttribute.instructionsAccept(clazz, method, this);

    // Remove the unused variables of the attributes.
    codeAttribute.attributesAccept(clazz, method, variableCleaner);
  }
예제 #5
0
  /**
   * Marks the hierarchy of implementing or overriding methods corresponding to the given method, if
   * any.
   */
  protected void markMethodHierarchy(Clazz clazz, Method method) {
    int accessFlags = method.getAccessFlags();
    if ((accessFlags & (ClassConstants.ACC_PRIVATE | ClassConstants.ACC_STATIC)) == 0
        && !ClassUtil.isInitializer(method.getName(clazz))) {
      // We can skip private and static methods in the hierarchy, and
      // also abstract methods, unless they might widen a current
      // non-public access.
      int requiredUnsetAccessFlags =
          ClassConstants.ACC_PRIVATE
              | ClassConstants.ACC_STATIC
              | ((accessFlags & ClassConstants.ACC_PUBLIC) == 0 ? 0 : ClassConstants.ACC_ABSTRACT);

      clazz.accept(
          new ConcreteClassDownTraveler(
              new ClassHierarchyTraveler(
                  true,
                  true,
                  false,
                  true,
                  new NamedMethodVisitor(
                      method.getName(clazz),
                      method.getDescriptor(clazz),
                      new MemberAccessFilter(0, requiredUnsetAccessFlags, this)))));
    }
  }
 public void visitLibraryClass(LibraryClass libraryClass) {
   notePrinter.print(
       libraryClass.getName(),
       "Note: duplicate definition of library class ["
           + ClassUtil.externalClassName(libraryClass.getName())
           + "]");
 }
 public void visitProgramClass(ProgramClass programClass) {
   notePrinter.print(
       programClass.getName(),
       "Note: duplicate definition of program class ["
           + ClassUtil.externalClassName(programClass.getName())
           + "]");
 }
예제 #8
0
  public void visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute) {
    // Process the generic definitions, superclass, and implemented
    // interfaces.
    String signature = clazz.getString(signatureAttribute.u2signatureIndex);

    // Count the signature types.
    InternalTypeEnumeration internalTypeEnumeration = new InternalTypeEnumeration(signature);

    int count = 0;
    int interfacesCount = -1;
    while (internalTypeEnumeration.hasMoreTypes()) {
      String internalType = internalTypeEnumeration.nextType();

      count++;

      if (ClassUtil.isInternalClassType(internalType)) {
        interfacesCount++;
      }
    }

    // Put the signature types in an array.
    internalTypeEnumeration = new InternalTypeEnumeration(signature);

    String[] internalTypes = new String[count];

    for (int index = 0; index < count; index++) {
      String internalType = internalTypeEnumeration.nextType();

      internalTypes[index] = internalType;
    }

    // Sort the interface types in the array.
    Arrays.sort(internalTypes, count - interfacesCount, count);

    // Recompose the signature types in a string.
    StringBuffer newSignatureBuffer = new StringBuffer();

    for (int index = 0; index < count; index++) {
      // Is this not an interface type, or an interface type that isn't
      // a duplicate of the previous interface type?
      if (index < count - interfacesCount
          || !internalTypes[index].equals(internalTypes[index - 1])) {
        newSignatureBuffer.append(internalTypes[index]);
      }
    }

    String newSignature = newSignatureBuffer.toString();

    // Did the signature change?
    if (!newSignature.equals(signature)) {
      // Update the signature.
      ((Utf8Constant) ((ProgramClass) clazz).constantPool[signatureAttribute.u2signatureIndex])
          .setString(newSignatureBuffer.toString());

      // Clear the referenced classes.
      // TODO: Properly update the referenced classes.
      signatureAttribute.referencedClasses = null;
    }
  }
  /** Shrinks the array of referenced classes of the given method. */
  private Clazz[] shrinkReferencedClasses(
      Method method, String descriptor, Clazz[] referencedClasses) {
    if (referencedClasses != null) {
      // All parameters of non-static methods are shifted by one in the local
      // variable frame.
      int parameterIndex =
          (method.getAccessFlags() & ClassConstants.INTERNAL_ACC_STATIC) != 0 ? 0 : 1;

      int referencedClassIndex = 0;
      int newReferencedClassIndex = 0;

      // Go over the parameters.
      InternalTypeEnumeration internalTypeEnumeration = new InternalTypeEnumeration(descriptor);

      // Also look at the formal type parameters.
      String type = internalTypeEnumeration.formalTypeParameters();
      int count = new DescriptorClassEnumeration(type).classCount();
      for (int counter = 0; counter < count; counter++) {
        referencedClasses[newReferencedClassIndex++] = referencedClasses[referencedClassIndex++];
      }

      while (internalTypeEnumeration.hasMoreTypes()) {
        // Consider the classes referenced by this parameter type.
        type = internalTypeEnumeration.nextType();
        count = new DescriptorClassEnumeration(type).classCount();

        if (ParameterUsageMarker.isParameterUsed(method, parameterIndex)) {
          // Copy the referenced classes.
          for (int counter = 0; counter < count; counter++) {
            referencedClasses[newReferencedClassIndex++] =
                referencedClasses[referencedClassIndex++];
          }
        } else {
          // Skip the referenced classes.
          referencedClassIndex += count;
        }

        parameterIndex += ClassUtil.isInternalCategory2Type(type) ? 2 : 1;
      }

      // Also look at the return value.
      type = internalTypeEnumeration.returnType();
      count = new DescriptorClassEnumeration(type).classCount();
      for (int counter = 0; counter < count; counter++) {
        referencedClasses[newReferencedClassIndex++] = referencedClasses[referencedClassIndex++];
      }

      // Clear the unused entries.
      while (newReferencedClassIndex < referencedClassIndex) {
        referencedClasses[newReferencedClassIndex++] = null;
      }
    }

    return referencedClasses;
  }
  /** Sets the ClassMemberSpecification to be represented in this dialog. */
  public void setClassMemberSpecification(ClassMemberSpecification classMemberSpecification) {
    String name = classMemberSpecification.name;
    String descriptor = classMemberSpecification.descriptor;

    // Set the access radio buttons.
    setClassMemberSpecificationRadioButtons(
        classMemberSpecification, ClassConstants.INTERNAL_ACC_PUBLIC, publicRadioButtons);
    setClassMemberSpecificationRadioButtons(
        classMemberSpecification, ClassConstants.INTERNAL_ACC_PRIVATE, privateRadioButtons);
    setClassMemberSpecificationRadioButtons(
        classMemberSpecification, ClassConstants.INTERNAL_ACC_PROTECTED, protectedRadioButtons);
    setClassMemberSpecificationRadioButtons(
        classMemberSpecification, ClassConstants.INTERNAL_ACC_STATIC, staticRadioButtons);
    setClassMemberSpecificationRadioButtons(
        classMemberSpecification, ClassConstants.INTERNAL_ACC_FINAL, finalRadioButtons);
    setClassMemberSpecificationRadioButtons(
        classMemberSpecification, ClassConstants.INTERNAL_ACC_VOLATILE, volatileRadioButtons);
    setClassMemberSpecificationRadioButtons(
        classMemberSpecification, ClassConstants.INTERNAL_ACC_TRANSIENT, transientRadioButtons);
    setClassMemberSpecificationRadioButtons(
        classMemberSpecification,
        ClassConstants.INTERNAL_ACC_SYNCHRONIZED,
        synchronizedRadioButtons);
    setClassMemberSpecificationRadioButtons(
        classMemberSpecification, ClassConstants.INTERNAL_ACC_NATIVE, nativeRadioButtons);
    setClassMemberSpecificationRadioButtons(
        classMemberSpecification, ClassConstants.INTERNAL_ACC_ABSTRACT, abstractRadioButtons);
    setClassMemberSpecificationRadioButtons(
        classMemberSpecification, ClassConstants.INTERNAL_ACC_STRICT, strictRadioButtons);

    // Set the class name text fields.
    nameTextField.setText(name == null ? "" : name);

    if (isField) {
      typeTextField.setText(descriptor == null ? "" : ClassUtil.externalType(descriptor));
    } else {
      typeTextField.setText(
          descriptor == null ? "" : ClassUtil.externalMethodReturnType(descriptor));
      argumentsTextField.setText(
          descriptor == null ? "" : ClassUtil.externalMethodArguments(descriptor));
    }
  }
 public void visitProgramField(ProgramClass programClass, ProgramField programField) {
   String newName = MemberObfuscator.newMemberName(programField);
   if (newName != null) {
     ps.println(
         "    "
             +
             // lineNumberRange(programClass, programField) +
             ClassUtil.externalFullFieldDescription(
                 0, programField.getName(programClass), programField.getDescriptor(programClass))
             + " -> "
             + newName);
   }
 }
예제 #12
0
  public void read(DataEntry dataEntry) throws IOException {
    try {
      // Get the input stream.
      InputStream inputStream = dataEntry.getInputStream();

      // Wrap it into a data input stream.
      DataInputStream dataInputStream = new DataInputStream(inputStream);

      // Create a Clazz representation.
      Clazz clazz;
      if (isLibrary) {
        clazz = new LibraryClass();
        clazz.accept(
            new LibraryClassReader(
                dataInputStream, skipNonPublicLibraryClasses, skipNonPublicLibraryClassMembers));
      } else {
        clazz = new ProgramClass();
        clazz.accept(new ProgramClassReader(dataInputStream));
      }

      // Apply the visitor, if we have a real class.
      String className = clazz.getName();
      if (className != null) {
        if (!dataEntry
                .getName()
                .replace(File.pathSeparatorChar, ClassConstants.PACKAGE_SEPARATOR)
                .equals(className + ClassConstants.CLASS_FILE_EXTENSION)
            && warningPrinter != null) {
          warningPrinter.print(
              className,
              "Warning: class ["
                  + dataEntry.getName()
                  + "] unexpectedly contains class ["
                  + ClassUtil.externalClassName(className)
                  + "]");
        }

        clazz.accept(classVisitor);
      }

      dataEntry.closeInputStream();
    } catch (Exception ex) {
      throw (IOException)
          new IOException(
                  "Can't process class [" + dataEntry.getName() + "] (" + ex.getMessage() + ")")
              .initCause(ex);
    }
  }
예제 #13
0
  /**
   * Marks the hierarchy of implementing or overriding methods corresponding to the given method, if
   * any.
   */
  protected void markMethodHierarchy(Clazz clazz, Method method) {
    int accessFlags = method.getAccessFlags();
    if ((accessFlags & (ClassConstants.ACC_PRIVATE | ClassConstants.ACC_STATIC)) == 0
        && !ClassUtil.isInitializer(method.getName(clazz))) {
      // We can skip private and static methods in the hierarchy, and
      // also abstract methods, unless they might widen a current
      // non-public access.
      int requiredUnsetAccessFlags =
          ClassConstants.ACC_PRIVATE
              | ClassConstants.ACC_STATIC
              | ((accessFlags & ClassConstants.ACC_PUBLIC) == 0 ? 0 : ClassConstants.ACC_ABSTRACT);

      // Mark default implementations in interfaces down the hierarchy.
      // TODO: This may be premature if there aren't any concrete implementing classes.
      clazz.accept(
          new ClassAccessFilter(
              ClassConstants.ACC_ABSTRACT,
              0,
              new ClassHierarchyTraveler(
                  false,
                  false,
                  false,
                  true,
                  new ProgramClassFilter(
                      new ClassAccessFilter(
                          ClassConstants.ACC_ABSTRACT,
                          0,
                          new NamedMethodVisitor(
                              method.getName(clazz),
                              method.getDescriptor(clazz),
                              new MemberAccessFilter(
                                  0, requiredUnsetAccessFlags, defaultMethodUsageMarker)))))));

      // Mark other implementations.
      clazz.accept(
          new ConcreteClassDownTraveler(
              new ClassHierarchyTraveler(
                  true,
                  true,
                  false,
                  true,
                  new NamedMethodVisitor(
                      method.getName(clazz),
                      method.getDescriptor(clazz),
                      new MemberAccessFilter(0, requiredUnsetAccessFlags, this)))));
    }
  }
  public void visitAnyParameterAnnotationsAttribute(
      Clazz clazz, Method method, ParameterAnnotationsAttribute parameterAnnotationsAttribute) {
    int[] annotationsCounts = parameterAnnotationsAttribute.u2parameterAnnotationsCount;
    Annotation[][] annotations = parameterAnnotationsAttribute.parameterAnnotations;

    // All parameters of non-static methods are shifted by one in the local
    // variable frame.
    int parameterIndex =
        (method.getAccessFlags() & ClassConstants.INTERNAL_ACC_STATIC) != 0 ? 0 : 1;

    int annotationIndex = 0;
    int newAnnotationIndex = 0;

    // Go over the parameters.
    String descriptor = method.getDescriptor(clazz);
    InternalTypeEnumeration internalTypeEnumeration = new InternalTypeEnumeration(descriptor);

    while (internalTypeEnumeration.hasMoreTypes()) {
      String type = internalTypeEnumeration.nextType();
      if (ParameterUsageMarker.isParameterUsed(method, parameterIndex)) {
        annotationsCounts[newAnnotationIndex] = annotationsCounts[annotationIndex];
        annotations[newAnnotationIndex++] = annotations[annotationIndex];
      }

      annotationIndex++;

      parameterIndex += ClassUtil.isInternalCategory2Type(type) ? 2 : 1;
    }

    // Update the number of parameters.
    parameterAnnotationsAttribute.u2parametersCount = newAnnotationIndex;

    // Clear the unused entries.
    while (newAnnotationIndex < annotationIndex) {
      annotationsCounts[newAnnotationIndex] = 0;
      annotations[newAnnotationIndex++] = null;
    }
  }
  public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod) {
    // Special cases: <clinit> and <init> are always kept unchanged.
    // We can ignore them here.
    String name = programMethod.getName(programClass);
    if (name.equals(ClassConstants.INTERNAL_METHOD_NAME_CLINIT)
        || name.equals(ClassConstants.INTERNAL_METHOD_NAME_INIT)) {
      return;
    }

    String newName = MemberObfuscator.newMemberName(programMethod);
    if (newName != null) {
      ps.println(
          "    "
              + lineNumberRange(programClass, programMethod)
              + ClassUtil.externalFullMethodDescription(
                  programClass.getName(),
                  0,
                  programMethod.getName(programClass),
                  programMethod.getDescriptor(programClass))
              + " -> "
              + newName);
    }
  }
예제 #16
0
  public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute) {
    // Get the original parameter size that was saved.
    int oldParameterSize = ParameterUsageMarker.getParameterSize(method);

    // Compute the new parameter size from the shrunk descriptor.
    int newParameterSize =
        ClassUtil.internalMethodParameterSize(method.getDescriptor(clazz), method.getAccessFlags());

    if (oldParameterSize > newParameterSize) {
      // Get the total size of the local variable frame.
      int maxLocals = codeAttribute.u2maxLocals;

      if (DEBUG) {
        System.out.println(
            "ParameterShrinker: "
                + clazz.getName()
                + "."
                + method.getName(clazz)
                + method.getDescriptor(clazz));
        System.out.println("  Old parameter size = " + oldParameterSize);
        System.out.println("  New parameter size = " + newParameterSize);
        System.out.println("  Max locals         = " + maxLocals);
      }

      // Create a variable map.
      int[] variableMap = new int[maxLocals];

      // Move unused parameters right after the parameter block.
      int usedParameterIndex = 0;
      int unusedParameterIndex = newParameterSize;
      for (int parameterIndex = 0; parameterIndex < oldParameterSize; parameterIndex++) {
        // Is the variable required as a parameter?
        if (ParameterUsageMarker.isParameterUsed(method, parameterIndex)) {
          // Keep the variable as a parameter.
          variableMap[parameterIndex] = usedParameterIndex++;
        } else {
          if (DEBUG) {
            System.out.println("  Deleting parameter #" + parameterIndex);
          }

          // Shift the variable to the unused parameter block,
          // in case it is still used as a variable.
          variableMap[parameterIndex] = unusedParameterIndex++;

          // Visit the method, if required.
          if (extraVariableMemberVisitor != null) {
            method.accept(clazz, extraVariableMemberVisitor);
          }
        }
      }

      // Fill out the remainder of the map.
      for (int variableIndex = oldParameterSize; variableIndex < maxLocals; variableIndex++) {
        variableMap[variableIndex] = variableIndex;
      }

      // Set the map.
      variableRemapper.setVariableMap(variableMap);

      // Remap the variables.
      variableRemapper.visitCodeAttribute(clazz, method, codeAttribute);
    }
  }