Search in sources :

Example 46 with Signature

use of net.runelite.asm.signature.Signature in project runelite by runelite.

the class InjectGetter method injectGetter.

public void injectGetter(ClassFile clazz, java.lang.reflect.Method method, Field field, Number getter) {
    assert clazz.findMethod(method.getName()) == null;
    assert field.isStatic() || field.getClassFile() == clazz;
    Signature sig = new Signature.Builder().setReturnType(Inject.classToType(method.getReturnType())).build();
    Method getterMethod = new Method(clazz, method.getName(), sig);
    getterMethod.setAccessFlags(ACC_PUBLIC);
    // create code
    Code code = new Code(getterMethod);
    getterMethod.setCode(code);
    Instructions instructions = code.getInstructions();
    List<Instruction> ins = instructions.getInstructions();
    if (field.isStatic()) {
        code.setMaxStack(1);
        ins.add(new GetStatic(instructions, field.getPoolField()));
    } else {
        code.setMaxStack(2);
        ins.add(new ALoad(instructions, 0));
        ins.add(new GetField(instructions, field.getPoolField()));
    }
    if (getter != null) {
        code.setMaxStack(2);
        assert getter instanceof Integer || getter instanceof Long;
        if (getter instanceof Integer) {
            ins.add(new LDC(instructions, (int) getter));
            ins.add(new IMul(instructions));
        } else {
            ins.add(new LDC(instructions, (long) getter));
            ins.add(new LMul(instructions));
        }
    }
    InstructionType returnType;
    if (field.getType().isPrimitive() && field.getType().getDimensions() == 0) {
        switch(field.getType().toString()) {
            case "B":
            case "C":
            case "I":
            case "S":
            case "Z":
                returnType = InstructionType.IRETURN;
                break;
            case "D":
                returnType = InstructionType.DRETURN;
                break;
            case "F":
                returnType = InstructionType.FRETURN;
                break;
            case "J":
                returnType = InstructionType.LRETURN;
                break;
            default:
                throw new RuntimeException("Unknown type");
        }
    } else {
        returnType = InstructionType.ARETURN;
    }
    ins.add(new Return(instructions, returnType));
    clazz.addMethod(getterMethod);
    ++injectedGetters;
}
Also used : GetField(net.runelite.asm.attributes.code.instructions.GetField) Return(net.runelite.asm.attributes.code.instructions.Return) InstructionType(net.runelite.asm.attributes.code.InstructionType) Instructions(net.runelite.asm.attributes.code.Instructions) LDC(net.runelite.asm.attributes.code.instructions.LDC) Method(net.runelite.asm.Method) Instruction(net.runelite.asm.attributes.code.Instruction) Code(net.runelite.asm.attributes.Code) GetStatic(net.runelite.asm.attributes.code.instructions.GetStatic) Signature(net.runelite.asm.signature.Signature) IMul(net.runelite.asm.attributes.code.instructions.IMul) LMul(net.runelite.asm.attributes.code.instructions.LMul) ALoad(net.runelite.asm.attributes.code.instructions.ALoad)

Example 47 with Signature

use of net.runelite.asm.signature.Signature in project runelite by runelite.

the class MixinInjectorTest method testInject.

@Test
public void testInject() throws Exception {
    InputStream deobIn = getClass().getResourceAsStream("DeobTarget.class");
    ClassFile deobTarget = ClassUtil.loadClass(deobIn);
    ClassGroup deob = new ClassGroup();
    deob.addClass(deobTarget);
    InputStream vanillaIn = getClass().getResourceAsStream("VanillaTarget.class");
    ClassFile vanillaTarget = ClassUtil.loadClass(vanillaIn);
    ClassGroup vanilla = new ClassGroup();
    vanilla.addClass(vanillaTarget);
    Map<Class<?>, List<ClassFile>> mixinClasses = new HashMap<>();
    mixinClasses.put(Source.class, Collections.singletonList(vanillaTarget));
    mixinClasses.put(Source2.class, Collections.singletonList(vanillaTarget));
    Inject inject = new Inject(deob, vanilla);
    new MixinInjector(inject).inject(mixinClasses);
    // Check if "foo" has been injected
    Field foo = vanillaTarget.findField("foo");
    assertNotNull(foo);
    assertEquals(INT, foo.getType());
    assertEquals(ACC_PUBLIC | ACC_STATIC, foo.getAccessFlags());
    // Check if "foo2()V" has been injected
    Method foo2 = vanillaTarget.findMethod("foo2");
    assertNotNull(foo2);
    assertEquals(new Signature("()V"), foo2.getDescriptor());
    assertEquals(ACC_PUBLIC, foo2.getAccessFlags());
    // Check if "ob_foo3(I)V" was copied
    Method foo3 = vanillaTarget.findMethod("copy$foo3");
    assertNotNull(foo3);
    assertEquals(new Signature("(I)V"), foo3.getDescriptor());
    assertEquals(ACC_PUBLIC, foo3.getAccessFlags());
    // Check if "ob_foo3(I)V" was replaced
    Method ob_foo3 = vanillaTarget.findMethod("ob_foo3");
    assertNotNull(ob_foo3);
    assertEquals(new Signature("(I)V"), ob_foo3.getDescriptor());
    assertEquals(ob_foo3.getCode().getInstructions().getInstructions().stream().filter(i -> i instanceof LDC && ((LDC) i).getConstant().equals("replaced")).count(), 1);
    // Check that the "foo4" field access in the new code body was mapped correctly
    assertEquals(ob_foo3.getCode().getInstructions().getInstructions().stream().filter(i -> {
        if (!(i instanceof GetStatic)) {
            return false;
        }
        net.runelite.asm.pool.Field field = ((GetStatic) i).getField();
        if (!field.getClazz().getName().equals("net/runelite/injector/VanillaTarget")) {
            return false;
        }
        if (!field.getName().equals("ob_foo4")) {
            return false;
        }
        return true;
    }).count(), 1);
    // Check that the "foo3()" call in the new code body was mapped to the copy
    assertEquals(ob_foo3.getCode().getInstructions().getInstructions().stream().filter(i -> {
        if (!(i instanceof InvokeVirtual)) {
            return false;
        }
        net.runelite.asm.pool.Method method = ((InvokeVirtual) i).getMethod();
        if (!method.getClazz().getName().equals("net/runelite/injector/VanillaTarget")) {
            return false;
        }
        if (!method.getName().equals("copy$foo3")) {
            return false;
        }
        return true;
    }).count(), 1);
    // Check if "foo5()V" was injected
    Method foo5 = vanillaTarget.findMethod("foo5");
    assertNotNull(foo5);
    assertEquals(new Signature("()V"), foo5.getDescriptor());
    assertEquals(ACC_PUBLIC, foo5.getAccessFlags());
    // Check that the shadow "foo" field access was mapped correctly
    assertEquals(foo5.getCode().getInstructions().getInstructions().stream().filter(i -> {
        if (!(i instanceof GetStatic)) {
            return false;
        }
        net.runelite.asm.pool.Field field = ((GetStatic) i).getField();
        if (!field.getClazz().getName().equals("net/runelite/injector/VanillaTarget")) {
            return false;
        }
        if (!field.getName().equals("foo")) {
            return false;
        }
        return true;
    }).count(), 1);
}
Also used : ClassFile(net.runelite.asm.ClassFile) HashMap(java.util.HashMap) InputStream(java.io.InputStream) LDC(net.runelite.asm.attributes.code.instructions.LDC) Method(net.runelite.asm.Method) Field(net.runelite.asm.Field) GetStatic(net.runelite.asm.attributes.code.instructions.GetStatic) InvokeVirtual(net.runelite.asm.attributes.code.instructions.InvokeVirtual) ClassGroup(net.runelite.asm.ClassGroup) ObfuscatedSignature(net.runelite.mapping.ObfuscatedSignature) Signature(net.runelite.asm.signature.Signature) List(java.util.List) Test(org.junit.Test)

Example 48 with Signature

use of net.runelite.asm.signature.Signature in project runelite by runelite.

the class DrawAfterWidgets method findStaticMethod.

private Method findStaticMethod(String name) {
    for (ClassFile c : inject.getDeobfuscated().getClasses()) {
        for (Method m : c.getMethods()) {
            if (!m.getName().equals(name)) {
                continue;
            }
            String obfuscatedName = DeobAnnotations.getObfuscatedName(m.getAnnotations());
            Signature obfuscatedSignature = DeobAnnotations.getObfuscatedSignature(m);
            ClassFile c2 = inject.toObClass(c);
            return c2.findMethod(obfuscatedName, (obfuscatedSignature != null) ? obfuscatedSignature : m.getDescriptor());
        }
    }
    return null;
}
Also used : ClassFile(net.runelite.asm.ClassFile) Signature(net.runelite.asm.signature.Signature) Method(net.runelite.asm.Method)

Example 49 with Signature

use of net.runelite.asm.signature.Signature in project runelite by runelite.

the class InjectSetter method injectSetter.

/**
 * inject a setter into the vanilla classgroup
 *
 * @param targetClass Class where to inject the setter (field's class,
 * or client)
 * @param targetApiClass API targetClass implements, which may have the
 * setter declared
 * @param field Field of vanilla that will be set
 * @param exportedName exported name of field
 * @param setter
 */
public void injectSetter(ClassFile targetClass, Class<?> targetApiClass, Field field, String exportedName, Number setter) {
    java.lang.reflect.Method method = inject.findImportMethodOnApi(targetApiClass, exportedName, true);
    if (method == null) {
        logger.warn("Setter injection for field {} but an API method was not found on {}", exportedName, targetApiClass);
        return;
    }
    if (method.getParameterCount() != 1) {
        logger.warn("Setter {} with not parameter count != 1?", exportedName);
        return;
    }
    logger.info("Injecting setter for {} on {}", exportedName, targetApiClass);
    assert targetClass.findMethod(method.getName()) == null;
    assert field.isStatic() || field.getClassFile() == targetClass;
    Signature sig = new Signature.Builder().setReturnType(Type.VOID).addArgument(Inject.classToType(method.getParameterTypes()[0])).build();
    Method setterMethod = new Method(targetClass, method.getName(), sig);
    setterMethod.setAccessFlags(ACC_PUBLIC);
    targetClass.addMethod(setterMethod);
    ++injectedSetters;
    Code code = new Code(setterMethod);
    setterMethod.setCode(code);
    Instructions instructions = code.getInstructions();
    List<Instruction> ins = instructions.getInstructions();
    // load this
    if (!field.isStatic()) {
        ins.add(new ALoad(instructions, 0));
    }
    // load argument
    Type argumentType = sig.getTypeOfArg(0);
    ins.add(inject.createLoadForTypeIndex(instructions, argumentType, 1));
    // cast argument to field type
    Type fieldType = field.getType();
    if (!argumentType.equals(fieldType)) {
        CheckCast checkCast = new CheckCast(instructions);
        checkCast.setType(fieldType);
        ins.add(checkCast);
    }
    if (setter != null) {
        assert setter instanceof Integer || setter instanceof Long;
        if (setter instanceof Integer) {
            ins.add(new LDC(instructions, (int) setter));
            ins.add(new IMul(instructions));
        } else {
            ins.add(new LDC(instructions, (long) setter));
            ins.add(new LMul(instructions));
        }
    }
    if (field.isStatic()) {
        ins.add(new PutStatic(instructions, field));
    } else {
        ins.add(new PutField(instructions, field));
    }
    ins.add(new VReturn(instructions));
}
Also used : Instructions(net.runelite.asm.attributes.code.Instructions) LDC(net.runelite.asm.attributes.code.instructions.LDC) Method(net.runelite.asm.Method) CheckCast(net.runelite.asm.attributes.code.instructions.CheckCast) Instruction(net.runelite.asm.attributes.code.Instruction) PutStatic(net.runelite.asm.attributes.code.instructions.PutStatic) Code(net.runelite.asm.attributes.Code) VReturn(net.runelite.asm.attributes.code.instructions.VReturn) Type(net.runelite.asm.Type) Signature(net.runelite.asm.signature.Signature) IMul(net.runelite.asm.attributes.code.instructions.IMul) LMul(net.runelite.asm.attributes.code.instructions.LMul) ALoad(net.runelite.asm.attributes.code.instructions.ALoad) PutField(net.runelite.asm.attributes.code.instructions.PutField)

Example 50 with Signature

use of net.runelite.asm.signature.Signature in project runelite by runelite.

the class InvokeInterface method removeParameter.

@Override
public void removeParameter(int idx) {
    net.runelite.asm.pool.Class clazz = method.getClazz();
    // create new signature
    Signature sig = new Signature(method.getType());
    sig.remove(idx);
    // create new method pool object
    method = new Method(clazz, method.getName(), sig);
}
Also used : Signature(net.runelite.asm.signature.Signature) Method(net.runelite.asm.pool.Method)

Aggregations

Signature (net.runelite.asm.signature.Signature)51 Method (net.runelite.asm.Method)29 ClassFile (net.runelite.asm.ClassFile)17 Type (net.runelite.asm.Type)16 Instruction (net.runelite.asm.attributes.code.Instruction)16 InvokeVirtual (net.runelite.asm.attributes.code.instructions.InvokeVirtual)16 Code (net.runelite.asm.attributes.Code)15 Instructions (net.runelite.asm.attributes.code.Instructions)15 InvokeStatic (net.runelite.asm.attributes.code.instructions.InvokeStatic)14 Field (net.runelite.asm.Field)10 ClassGroup (net.runelite.asm.ClassGroup)8 ALoad (net.runelite.asm.attributes.code.instructions.ALoad)8 LDC (net.runelite.asm.attributes.code.instructions.LDC)8 InstructionType (net.runelite.asm.attributes.code.InstructionType)7 InvokeInstruction (net.runelite.asm.attributes.code.instruction.types.InvokeInstruction)6 LVTInstruction (net.runelite.asm.attributes.code.instruction.types.LVTInstruction)6 GetStatic (net.runelite.asm.attributes.code.instructions.GetStatic)6 ArrayList (java.util.ArrayList)5 List (java.util.List)5 VReturn (net.runelite.asm.attributes.code.instructions.VReturn)5