Class Remapper

java.lang.Object
de.geolykt.starloader.deobf.remapper.Remapper

public final class Remapper extends Object
Simple in-memory remapping engine. Unlike many other remappers it is able to take in already parsed Objectweb ASM Classnodes as input and output them without having to go through an intermediary store-to-file mode. Additionally, this is a no-bullshit remapper. It will only remap, not change your Access flags, LVT entries or anything like that. If you want a deobfuscator, use Oaktree after remapping.
  • Constructor Details

    • Remapper

      public Remapper()
  • Method Details

    • addTarget

      public void addTarget(org.objectweb.asm.tree.ClassNode node)
      Adds a single class node to remap
      Parameters:
      node - The class node
    • addTargets

      public void addTargets(Collection<org.objectweb.asm.tree.ClassNode> nodes)
      Adds multiple class nodes to remap
      Parameters:
      nodes - The class nodes
    • clearTargets

      public void clearTargets()
    • fixICNNames

      public Map<String,String> fixICNNames(StringBuilder sharedBuilder)
      Fixes remapped InnerClassNode by remapping any child classes alongside their parent class, even if only the parent class was remapped. Due to the potentially destructive properties of this action, this method must be explicitly invoked for it to do anything.

      More specifically if the class "OuterClass" is remapped to "RootClass", but "OuterClass$Inner" is not remapped, then after process() the classes "RootClass" and "OuterClass$Inner" will exist. As the names contradict the relation given by their InnerClassNode, most decompilers will discard the InnerClassNode.

      To fix this issue, this method will look for such changes and renames the inner classes accordingly.

      This method will only do anything if it is called before process() and will modify the internal collection of remapped classes.

      The more ClassNodes there are, the more efficient this method is at doing what it should do.

      This method can be destructive as it will not check for collisions.

      Parameters:
      sharedBuilder - A shared StringBuilder to reduce memory consumption created by string operations
      Returns:
      A map that contains ALL additional mappings where as the key is the old name and the value the new name.
    • getOutput

      public List<org.objectweb.asm.tree.ClassNode> getOutput()
      Note: due to the circumstances of how the remapper works, this method call may be not required as the remapper remaps the input ClassNodes without cloning them in any capacity.
      Returns:
      Returns the targets
    • getRemappedClassName

      @NotNull public @NotNull String getRemappedClassName(@NotNull @NotNull String name)
      Remaps a class name.
      Parameters:
      name - The old (unmapped) class name
      Returns:
      The new (remapped) class name
    • getRemappedFieldDescriptor

      @NotNull public @NotNull String getRemappedFieldDescriptor(@NotNull @NotNull String fieldDesc, @NotNull @NotNull StringBuilder sharedBuilder)
      Remaps a field descriptor.
      Parameters:
      fieldDesc - The old (unmapped) field descriptor
      sharedBuilder - A shared cached string builder. The contents of the string builder are wiped and after the invocation the contents are undefined
      Returns:
      The new (remapped) field descriptor. It can be identity identical to the "fieldDesc" if it didn't need to be altered
    • getRemappedFieldName

      @NotNull public @NotNull String getRemappedFieldName(@NotNull @NotNull String owner, @NotNull @NotNull String name, @NotNull @NotNull String desc)
      Remaps a field name.
      Parameters:
      owner - The old (unmapped) class name
      name - The old (unmapped) field name
      desc - The old (unmapped) field descriptor
      Returns:
      The new (remapped) field name
      Since:
      0.1.0
    • getRemappedMethodDescriptor

      @NotNull public @NotNull String getRemappedMethodDescriptor(@NotNull @NotNull String methodDesc, @NotNull @NotNull StringBuilder sharedBuilder)
      Remaps a method descriptor.
      Parameters:
      methodDesc - The old (unmapped) method descriptor
      sharedBuilder - A shared cached string builder. The contents of the string builder are wiped and after the invocation the contents are undefined
      Returns:
      The new (remapped) method descriptor. It can be identity identical to the "methodDesc" if it didn't need to be altered
    • getRemappedMethodName

      @NotNull public @NotNull String getRemappedMethodName(@NotNull @NotNull String owner, @NotNull @NotNull String name, @NotNull @NotNull String desc)
      Remaps a method name.
      Parameters:
      owner - The old (unmapped) class name
      name - The old (unmapped) method name
      desc - The old (unmapped) method descriptor
      Returns:
      The new (remapped) method name
      Since:
      0.1.0
    • process

      public void process()
      Processes all remap orders and clears the remap orders afterwards. The classes that need to be processed remain in the targets list until clearTargets() is invoked. This allows for reusability of the same remapper instance. Class names are remapped last.
    • remapClassName

      public void remapClassName(String oldName, String newName)
      Remaps the name of all target class nodes once process() is called. Class names are remapped alongside method / fields however technically they are remapped last.
      Parameters:
      oldName - The old internal class name of the class to remap
      newName - The new internal class name of the class to remap
    • remapClassNames

      public void remapClassNames(Map<String,String> mappings)
      Remaps the name of all target class nodes once process() is called. Class names are remapped alongside method / fields however technically they are remapped last. This is a bulk method. And is similar to calling remapClassName(String, String).
      Parameters:
      mappings - A map that represents all the class remaps. Keys are old names, values are new names.
    • remapField

      public void remapField(String owner, String desc, String oldName, String newName)
      Inserts a field renaming entry to the remapping list. The owner and desc strings must be valid for the current class names, i. e. without remapClassName(String, String) and process() applied. The fields are not actually renamed until process() is invoked. These tasks are however removed as soon as process() is invoked. Unlike remapMethod(String, String, String, String), this method will do it's best to propagate field renames to child classes. However it may miss a few if not all classes are declared as targets. However one would still be able to explicitly add a remap via this method.
      Parameters:
      owner - The internal name of the current owner of the field
      desc - The descriptor string of the field entry
      oldName - The old name of the field
      newName - The new name of the field
      See Also:
      • Type.getInternalName()
    • remapMethod

      public void remapMethod(String owner, String desc, String oldName, String newName) throws ConflicitingMappingException
      Inserts a method renaming entry to the remapping list. The owner and desc strings must be valid for the current class names, i. e. without remapClassName(String, String) and process() applied. The method are not actually renamed until process() is invoked.

      WARNING: if the method is non-static and non-private and the owning class non-final then it is recommended that the change is propagated through the entire tree. Renaming a method will only affect one class, not multiple - which may void overrides or other similar behaviours.

      Parameters:
      owner - The internal name of the current owner of the method
      desc - The descriptor string of the method entry
      oldName - The old name of the method
      newName - The new name of the method
      Throws:
      ConflicitingMappingException - If a mapping error occurs.
      See Also:
      • Type.getInternalName()
    • removeMethodRemap

      public void removeMethodRemap(String owner, String desc, String name)
      Removes a method remapping entry from the method remapping list. This method practically undoes remapMethod(String, String, String, String). Like it it only affects a SINGLE method in a SINGLE class and it's references. Note that implicitly declared/inherited methods must also be added to the remap list.
      Parameters:
      owner - The class of the method that should not be remapped
      desc - The descriptor of the method to not remap
      name - The name of the method that should not be remapped