RehabCZ

JAVA ASM HELPER

Jul 21st, 2025
248
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 7.98 KB | Source Code | 0 0
  1. package com.example.coremod;
  2.  
  3. import org.objectweb.asm.Opcodes;
  4. import org.objectweb.asm.Type;
  5. import org.objectweb.asm.tree.*;
  6.  
  7. import java.lang.reflect.Field;
  8. import java.lang.reflect.Method;
  9. import java.lang.reflect.Modifier;
  10.  
  11. public class ASMHelper {
  12.  
  13.     // ====================================================
  14.     // Reflection Utilities
  15.     // ====================================================
  16.  
  17.     /**
  18.      * Calls a method reflectively (static or instance).
  19.      */
  20.     public static Object callMethod(Object target, String methodName, Class<?>[] paramTypes, Object... args) throws Exception {
  21.         Class<?> clazz = (target instanceof Class) ? (Class<?>) target : target.getClass();
  22.         Method method = clazz.getDeclaredMethod(methodName, paramTypes);
  23.         method.setAccessible(true);
  24.         return method.invoke((target instanceof Class) ? null : target, args);
  25.     }
  26.  
  27.     /**
  28.      * Gets a field value reflectively, bypassing visibility.
  29.      */
  30.     public static Object getField(Object target, String fieldName) throws Exception {
  31.         Field field = target.getClass().getDeclaredField(fieldName);
  32.         field.setAccessible(true);
  33.         return field.get(target);
  34.     }
  35.  
  36.     /**
  37.      * Sets a field value reflectively, bypassing visibility and final modifiers.
  38.      */
  39.     public static void setField(Object target, String fieldName, Object value) throws Exception {
  40.         Field field = target.getClass().getDeclaredField(fieldName);
  41.         field.setAccessible(true);
  42.  
  43.         // Remove final modifier if present
  44.         Field modifiersField = Field.class.getDeclaredField("modifiers");
  45.         modifiersField.setAccessible(true);
  46.         modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
  47.  
  48.         field.set(target, value);
  49.     }
  50.  
  51.     /**
  52.      * Gets modifiers of a field.
  53.      */
  54.     public static int getModifiers(Class<?> clazz, String fieldName) throws Exception {
  55.         Field field = clazz.getDeclaredField(fieldName);
  56.         return field.getModifiers();
  57.     }
  58.  
  59.     // ====================================================
  60.     // Descriptor Utilities
  61.     // ====================================================
  62.  
  63.     /**
  64.      * Generates a JVM method descriptor from return type and parameter types.
  65.      */
  66.     public static String getMethodDescriptor(Class<?> returnType, Class<?>... paramTypes) {
  67.         Type retType = Type.getType(returnType);
  68.         Type[] paramAsmTypes = new Type[paramTypes.length];
  69.         for (int i = 0; i < paramTypes.length; i++) {
  70.             paramAsmTypes[i] = Type.getType(paramTypes[i]);
  71.         }
  72.         return Type.getMethodDescriptor(retType, paramAsmTypes);
  73.     }
  74.  
  75.     /**
  76.      * Generates a JVM method descriptor from a reflection Method.
  77.      */
  78.     public static String getMethodDescriptor(Method method) {
  79.         return Type.getMethodDescriptor(method);
  80.     }
  81.  
  82.     /**
  83.      * Generates a JVM field descriptor from a Class.
  84.      */
  85.     public static String getFieldDescriptor(Class<?> type) {
  86.         return Type.getDescriptor(type);
  87.     }
  88.  
  89.     /**
  90.      * Generates a JVM field descriptor from a reflection Field.
  91.      */
  92.     public static String getFieldDescriptor(Field field) {
  93.         return Type.getDescriptor(field.getType());
  94.     }
  95.  
  96.     // ====================================================
  97.     // ASM Patch Utilities
  98.     // ====================================================
  99.  
  100.     /**
  101.      * Injection points for injectCallback.
  102.      */
  103.     public enum InjectionPoint {
  104.         START, END, BEFORE_CALL, AFTER_CALL
  105.     }
  106.  
  107.     // --------------------------
  108.     // redirectMethodCalls overload #1 (Class owners)
  109.     // --------------------------
  110.     public static void redirectMethodCalls(ClassNode classNode,
  111.                                            Class<?> originalOwner, String originalName,
  112.                                            Class<?> returnType, Class<?>[] paramTypes,
  113.                                            Class<?> newOwner, String newName) {
  114.  
  115.         String descriptor = getMethodDescriptor(returnType, paramTypes);
  116.         String originalOwnerName = Type.getInternalName(originalOwner);
  117.         String newOwnerName = Type.getInternalName(newOwner);
  118.  
  119.         redirectMethodCalls(classNode, originalOwnerName, originalName, descriptor, newOwnerName, newName);
  120.     }
  121.  
  122.     // --------------------------
  123.     // redirectMethodCalls overload #2 (String owners)
  124.     // --------------------------
  125.     public static void redirectMethodCalls(ClassNode classNode,
  126.                                            String originalOwner, String originalName, String descriptor,
  127.                                            String newOwner, String newName) {
  128.  
  129.         for (MethodNode method : classNode.methods) {
  130.             for (AbstractInsnNode insn : method.instructions.toArray()) {
  131.                 if (insn instanceof MethodInsnNode) {
  132.                     MethodInsnNode mInsn = (MethodInsnNode) insn;
  133.                     if (mInsn.owner.equals(originalOwner)
  134.                             && mInsn.name.equals(originalName)
  135.                             && mInsn.desc.equals(descriptor)) {
  136.  
  137.                         mInsn.owner = newOwner;
  138.                         mInsn.name = newName;
  139.                         // descriptor stays the same
  140.                     }
  141.                 }
  142.             }
  143.         }
  144.     }
  145.  
  146.     // --------------------------
  147.     // injectCallback overload #1 (Class owner)
  148.     // --------------------------
  149.     public static void injectCallback(MethodNode targetMethod, InjectionPoint point,
  150.                                       Class<?> callbackOwner, String callbackName,
  151.                                       Class<?> callbackReturnType, Class<?>... callbackParamTypes) {
  152.  
  153.         String callbackOwnerName = Type.getInternalName(callbackOwner);
  154.         String callbackDesc = getMethodDescriptor(callbackReturnType, callbackParamTypes);
  155.  
  156.         injectCallback(targetMethod, point, callbackOwnerName, callbackName, callbackDesc);
  157.     }
  158.  
  159.     // --------------------------
  160.     // injectCallback overload #2 (String owner)
  161.     // --------------------------
  162.     public static void injectCallback(MethodNode targetMethod, InjectionPoint point,
  163.                                       String callbackOwner, String callbackName, String callbackDescriptor) {
  164.  
  165.         InsnList callbackInsn = new InsnList();
  166.         callbackInsn.add(new MethodInsnNode(Opcodes.INVOKESTATIC, callbackOwner, callbackName, callbackDescriptor, false));
  167.  
  168.         switch (point) {
  169.             case START:
  170.                 targetMethod.instructions.insert(callbackInsn);
  171.                 break;
  172.  
  173.             case END:
  174.                 for (AbstractInsnNode insn : targetMethod.instructions.toArray()) {
  175.                     int opcode = insn.getOpcode();
  176.                     if (opcode >= Opcodes.IRETURN && opcode <= Opcodes.RETURN) {
  177.                         targetMethod.instructions.insertBefore(insn, callbackInsn);
  178.                     }
  179.                 }
  180.                 break;
  181.  
  182.             case BEFORE_CALL:
  183.             case AFTER_CALL:
  184.                 for (AbstractInsnNode insn : targetMethod.instructions.toArray()) {
  185.                     if (insn instanceof MethodInsnNode) {
  186.                         if (point == InjectionPoint.BEFORE_CALL) {
  187.                             targetMethod.instructions.insertBefore(insn, callbackInsn);
  188.                         } else {
  189.                             targetMethod.instructions.insert(insn, callbackInsn);
  190.                         }
  191.                     }
  192.                 }
  193.                 break;
  194.         }
  195.     }
  196.  
  197.     /**
  198.      * Prints all instructions of a method to System.out for debugging.
  199.      */
  200.     public static void printInstructions(MethodNode method) {
  201.         System.out.println("Instructions for method: " + method.name + method.desc);
  202.         for (AbstractInsnNode insn : method.instructions.toArray()) {
  203.             System.out.println(insn.getClass().getSimpleName() + ": " + insn);
  204.         }
  205.     }
  206. }
  207.  
Tags: Java asm
Advertisement
Add Comment
Please, Sign In to add comment