Search in sources :

Example 81 with Method

use of net.runelite.asm.Method 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 82 with Method

use of net.runelite.asm.Method in project runelite by runelite.

the class InjectHookMethod method findHookLocations.

private List<Integer> findHookLocations(Annotation hook, Method vanillaMethod) throws InjectionException {
    Instructions instructions = vanillaMethod.getCode().getInstructions();
    boolean end = hook.getElements().size() == 2 && hook.getElements().get(1).getValue().equals(true);
    if (end) {
        // find return
        List<Instruction> returns = instructions.getInstructions().stream().filter(i -> i instanceof ReturnInstruction).collect(Collectors.toList());
        List<Integer> indexes = new ArrayList<>();
        for (Instruction ret : returns) {
            int idx = instructions.getInstructions().indexOf(ret);
            assert idx != -1;
            indexes.add(idx);
        }
        return indexes;
    }
    if (!vanillaMethod.getName().equals("<init>")) {
        return Arrays.asList(0);
    }
    // Find index after invokespecial
    for (int i = 0; i < instructions.getInstructions().size(); ++i) {
        Instruction in = instructions.getInstructions().get(i);
        if (in.getType() == InstructionType.INVOKESPECIAL) {
            // one after
            return Arrays.asList(i + 1);
        }
    }
    throw new IllegalStateException("constructor with no invokespecial");
}
Also used : Annotations(net.runelite.asm.attributes.Annotations) Arrays(java.util.Arrays) DeobAnnotations(net.runelite.deob.DeobAnnotations) Logger(org.slf4j.Logger) InstructionType(net.runelite.asm.attributes.code.InstructionType) ReturnInstruction(net.runelite.asm.attributes.code.instruction.types.ReturnInstruction) LoggerFactory(org.slf4j.LoggerFactory) Type(net.runelite.asm.Type) ALoad(net.runelite.asm.attributes.code.instructions.ALoad) Collectors(java.util.stream.Collectors) InvokeStatic(net.runelite.asm.attributes.code.instructions.InvokeStatic) ArrayList(java.util.ArrayList) ClassGroup(net.runelite.asm.ClassGroup) List(java.util.List) ClassFile(net.runelite.asm.ClassFile) Annotation(net.runelite.asm.attributes.annotation.Annotation) Method(net.runelite.asm.Method) Instructions(net.runelite.asm.attributes.code.Instructions) Signature(net.runelite.asm.signature.Signature) Instruction(net.runelite.asm.attributes.code.Instruction) ReturnInstruction(net.runelite.asm.attributes.code.instruction.types.ReturnInstruction) ArrayList(java.util.ArrayList) Instructions(net.runelite.asm.attributes.code.Instructions) ReturnInstruction(net.runelite.asm.attributes.code.instruction.types.ReturnInstruction) Instruction(net.runelite.asm.attributes.code.Instruction)

Example 83 with Method

use of net.runelite.asm.Method in project runelite by runelite.

the class InjectSetterTest method testInjectSetterInt.

@Test
public void testInjectSetterInt() throws NoSuchMethodException {
    Inject inject = mock(Inject.class);
    when(inject.findImportMethodOnApi(any(Class.class), anyString(), any(Boolean.class))).thenReturn(APIClass.class.getDeclaredMethod("setTest", int.class));
    when(inject.createLoadForTypeIndex(any(Instructions.class), any(Type.class), anyInt())).thenReturn(mock(Instruction.class));
    InjectSetter instance = new InjectSetter(inject);
    ClassFile targetClass = new ClassFile();
    targetClass.setName("test");
    Field field = new Field(targetClass, "test", Type.INT);
    targetClass.addField(field);
    instance.injectSetter(targetClass, APIClass.class, field, "test", null);
    Method injectedMethod = targetClass.findMethod("setTest");
    assertNotNull(injectedMethod);
    Code code = injectedMethod.getCode();
    Instructions instructions = code.getInstructions();
    assertFalse(instructions.getInstructions().stream().filter(i -> i.getType() == CHECKCAST).findAny().isPresent());
}
Also used : Assert.assertNotNull(org.junit.Assert.assertNotNull) Field(net.runelite.asm.Field) Assert.assertTrue(org.junit.Assert.assertTrue) Code(net.runelite.asm.attributes.Code) Test(org.junit.Test) Mockito.when(org.mockito.Mockito.when) Type(net.runelite.asm.Type) Matchers.anyString(org.mockito.Matchers.anyString) Matchers.any(org.mockito.Matchers.any) ClassFile(net.runelite.asm.ClassFile) CHECKCAST(net.runelite.asm.attributes.code.InstructionType.CHECKCAST) Method(net.runelite.asm.Method) Assert.assertFalse(org.junit.Assert.assertFalse) Instructions(net.runelite.asm.attributes.code.Instructions) Matchers.anyInt(org.mockito.Matchers.anyInt) Instruction(net.runelite.asm.attributes.code.Instruction) Mockito.mock(org.mockito.Mockito.mock) ClassFile(net.runelite.asm.ClassFile) Instructions(net.runelite.asm.attributes.code.Instructions) Method(net.runelite.asm.Method) Instruction(net.runelite.asm.attributes.code.Instruction) Code(net.runelite.asm.attributes.Code) Field(net.runelite.asm.Field) Type(net.runelite.asm.Type) Test(org.junit.Test)

Example 84 with Method

use of net.runelite.asm.Method in project runelite by runelite.

the class InjectSetterTest method testInjectSetterObject.

@Test
public void testInjectSetterObject() throws NoSuchMethodException {
    Inject inject = mock(Inject.class);
    when(inject.findImportMethodOnApi(any(Class.class), anyString(), any(Boolean.class))).thenReturn(APIClass.class.getDeclaredMethod("setTestObject", Object.class));
    when(inject.createLoadForTypeIndex(any(Instructions.class), any(Type.class), anyInt())).thenReturn(mock(Instruction.class));
    InjectSetter instance = new InjectSetter(inject);
    ClassFile targetClass = new ClassFile();
    targetClass.setName("test");
    Field field = new Field(targetClass, "testObject", Type.STRING);
    targetClass.addField(field);
    instance.injectSetter(targetClass, APIClass.class, field, "testObject", null);
    Method injectedMethod = targetClass.findMethod("setTestObject");
    assertNotNull(injectedMethod);
    Code code = injectedMethod.getCode();
    Instructions instructions = code.getInstructions();
    assertTrue(instructions.getInstructions().stream().filter(i -> i.getType() == CHECKCAST).findAny().isPresent());
}
Also used : Assert.assertNotNull(org.junit.Assert.assertNotNull) Field(net.runelite.asm.Field) Assert.assertTrue(org.junit.Assert.assertTrue) Code(net.runelite.asm.attributes.Code) Test(org.junit.Test) Mockito.when(org.mockito.Mockito.when) Type(net.runelite.asm.Type) Matchers.anyString(org.mockito.Matchers.anyString) Matchers.any(org.mockito.Matchers.any) ClassFile(net.runelite.asm.ClassFile) CHECKCAST(net.runelite.asm.attributes.code.InstructionType.CHECKCAST) Method(net.runelite.asm.Method) Assert.assertFalse(org.junit.Assert.assertFalse) Instructions(net.runelite.asm.attributes.code.Instructions) Matchers.anyInt(org.mockito.Matchers.anyInt) Instruction(net.runelite.asm.attributes.code.Instruction) Mockito.mock(org.mockito.Mockito.mock) ClassFile(net.runelite.asm.ClassFile) Instructions(net.runelite.asm.attributes.code.Instructions) Method(net.runelite.asm.Method) Instruction(net.runelite.asm.attributes.code.Instruction) Code(net.runelite.asm.attributes.Code) Field(net.runelite.asm.Field) Type(net.runelite.asm.Type) Test(org.junit.Test)

Example 85 with Method

use of net.runelite.asm.Method 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)

Aggregations

Method (net.runelite.asm.Method)90 ClassFile (net.runelite.asm.ClassFile)64 Field (net.runelite.asm.Field)34 Instruction (net.runelite.asm.attributes.code.Instruction)29 Code (net.runelite.asm.attributes.Code)28 Instructions (net.runelite.asm.attributes.code.Instructions)28 Signature (net.runelite.asm.signature.Signature)28 ClassGroup (net.runelite.asm.ClassGroup)20 ArrayList (java.util.ArrayList)18 Type (net.runelite.asm.Type)18 List (java.util.List)13 Test (org.junit.Test)13 PushConstantInstruction (net.runelite.asm.attributes.code.instruction.types.PushConstantInstruction)12 Logger (org.slf4j.Logger)12 LoggerFactory (org.slf4j.LoggerFactory)12 LDC (net.runelite.asm.attributes.code.instructions.LDC)10 DeobAnnotations (net.runelite.deob.DeobAnnotations)9 Annotation (net.runelite.asm.attributes.annotation.Annotation)8 InstructionType (net.runelite.asm.attributes.code.InstructionType)8 Label (net.runelite.asm.attributes.code.Label)8