Search in sources :

Example 31 with Type

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

the class AnnotationTest method testAnnotation.

@Test
public void testAnnotation() throws IOException {
    InputStream in = this.getClass().getClassLoader().getResourceAsStream("net/runelite/asm/annotations/TestClass.class");
    Assert.assertNotNull(in);
    ClassGroup group = new ClassGroup();
    ClassFile cf = ClassUtil.loadClass(in);
    group.addClass(cf);
    byte[] out = JarUtil.writeClass(group, cf);
    // parse it again
    cf = ClassUtil.loadClass(new ByteArrayInputStream(out));
    Method method = cf.getMethods().get(1);
    Assert.assertEquals("method1", method.getName());
    Annotations annotations = method.getAnnotations();
    Assert.assertNotNull(annotations);
    Optional<Annotation> annotation = annotations.getAnnotations().stream().filter(a -> a.getType().equals(new Type("Lnet/runelite/asm/annotations/MyAnnotation;"))).findFirst();
    Assert.assertTrue(annotation.isPresent());
    Annotation an = annotation.get();
    List<Element> elements = an.getElements();
    Assert.assertEquals(1, elements.size());
    Element element = elements.get(0);
    Assert.assertEquals("value", element.getName());
    Assert.assertEquals("method1", element.getValue());
}
Also used : Annotations(net.runelite.asm.attributes.Annotations) IOException(java.io.IOException) Test(org.junit.Test) Type(net.runelite.asm.Type) ClassGroup(net.runelite.asm.ClassGroup) JarUtil(net.runelite.deob.util.JarUtil) List(java.util.List) ClassFile(net.runelite.asm.ClassFile) Annotation(net.runelite.asm.attributes.annotation.Annotation) ByteArrayInputStream(java.io.ByteArrayInputStream) Method(net.runelite.asm.Method) ClassUtil(net.runelite.asm.ClassUtil) Element(net.runelite.asm.attributes.annotation.Element) Optional(java.util.Optional) Assert(org.junit.Assert) InputStream(java.io.InputStream) ClassFile(net.runelite.asm.ClassFile) ByteArrayInputStream(java.io.ByteArrayInputStream) InputStream(java.io.InputStream) Element(net.runelite.asm.attributes.annotation.Element) Method(net.runelite.asm.Method) Annotation(net.runelite.asm.attributes.annotation.Annotation) Type(net.runelite.asm.Type) Annotations(net.runelite.asm.attributes.Annotations) ByteArrayInputStream(java.io.ByteArrayInputStream) ClassGroup(net.runelite.asm.ClassGroup) Test(org.junit.Test)

Example 32 with Type

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

the class Inject method run.

public void run() throws InjectionException {
    Map<ClassFile, java.lang.Class> implemented = new HashMap<>();
    // check below works
    for (ClassFile cf : deobfuscated.getClasses()) {
        Annotations an = cf.getAnnotations();
        if (an == null || an.size() == 0) {
            continue;
        }
        String obfuscatedName = DeobAnnotations.getObfuscatedName(an);
        if (obfuscatedName == null) {
            obfuscatedName = cf.getName();
        }
        ClassFile other = vanilla.findClass(obfuscatedName);
        assert other != null : "unable to find vanilla class from obfuscated name: " + obfuscatedName;
        java.lang.Class implementingClass = injectInterface(cf, other);
        // it can not implement an interface but still have exported static fields, which are
        // moved to client
        implemented.put(cf, implementingClass);
    }
    // requires interfaces to be injected
    mixinInjector.inject();
    construct.inject(implemented);
    for (ClassFile cf : deobfuscated.getClasses()) {
        java.lang.Class implementingClass = implemented.get(cf);
        Annotations an = cf.getAnnotations();
        if (an == null || an.size() == 0) {
            continue;
        }
        String obfuscatedName = DeobAnnotations.getObfuscatedName(an);
        if (obfuscatedName == null) {
            obfuscatedName = cf.getName();
        }
        ClassFile other = vanilla.findClass(obfuscatedName);
        assert other != null : "unable to find vanilla class from obfuscated name: " + obfuscatedName;
        for (Field f : cf.getFields()) {
            an = f.getAnnotations();
            if (an == null || an.find(DeobAnnotations.EXPORT) == null) {
                // not an exported field
                continue;
            }
            Annotation exportAnnotation = an.find(DeobAnnotations.EXPORT);
            String exportedName = exportAnnotation.getElement().getString();
            obfuscatedName = DeobAnnotations.getObfuscatedName(an);
            Annotation getterAnnotation = an.find(DeobAnnotations.OBFUSCATED_GETTER);
            Number getter = null;
            if (getterAnnotation != null) {
                getter = (Number) getterAnnotation.getElement().getValue();
            }
            // the ob jar is the same as the vanilla so this field must exist in this class.
            Type obType = getFieldType(f);
            Field otherf = other.findField(obfuscatedName, obType);
            assert otherf != null;
            assert f.isStatic() == otherf.isStatic();
            // target class for getter
            ClassFile targetClass = f.isStatic() ? vanilla.findClass("client") : other;
            // target api class for getter
            java.lang.Class targetApiClass = f.isStatic() ? CLIENT_CLASS : implementingClass;
            if (targetApiClass == null) {
                assert !f.isStatic();
                // non static field exported on non exported interface
                logger.debug("Non static exported field {} on non exported interface", exportedName);
                continue;
            }
            java.lang.reflect.Method apiMethod = findImportMethodOnApi(targetApiClass, exportedName, true);
            if (apiMethod != null) {
                Number setter = null;
                if (getter != null) {
                    // inverse getter to get the setter
                    setter = DMath.modInverse(getter);
                }
                setters.injectSetter(targetClass, targetApiClass, otherf, exportedName, setter);
            }
            apiMethod = findImportMethodOnApi(targetApiClass, exportedName, false);
            if (apiMethod == null) {
                logger.debug("Unable to find import method on api class {} with imported name {}, not injecting getter", targetApiClass, exportedName);
                continue;
            }
            // check that otherf is converable to apiMethod's
            // return type
            Type fieldType = otherf.getType();
            Type returnType = classToType(apiMethod.getReturnType());
            if (!validateTypeIsConvertibleTo(fieldType, returnType)) {
                throw new InjectionException("Type " + fieldType + " is not convertable to " + returnType + " for getter " + apiMethod);
            }
            getters.injectGetter(targetClass, apiMethod, otherf, getter);
        }
        for (Method m : cf.getMethods()) {
            hookMethod.process(m);
            invokes.process(m, other, implementingClass);
        }
    }
    logger.info("Injected {} getters, {} settters, {} invokers", getters.getInjectedGetters(), setters.getInjectedSetters(), invokes.getInjectedInvokers());
    drawAfterWidgets.inject();
    scriptVM.inject();
}
Also used : ClassFile(net.runelite.asm.ClassFile) HashMap(java.util.HashMap) Method(net.runelite.asm.Method) Annotation(net.runelite.asm.attributes.annotation.Annotation) Field(net.runelite.asm.Field) Type(net.runelite.asm.Type) Annotations(net.runelite.asm.attributes.Annotations) DeobAnnotations(net.runelite.deob.DeobAnnotations) Class(net.runelite.asm.pool.Class)

Example 33 with Type

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

the class AALoad method execute.

@Override
public InstructionContext execute(Frame frame) {
    InstructionContext ins = new InstructionContext(this, frame);
    Stack stack = frame.getStack();
    StackContext index = stack.pop();
    StackContext array = stack.pop();
    ins.pop(index, array);
    Type subtype;
    if (array.getType().isArray()) {
        subtype = array.getType().getSubtype();
    } else {
        // This will happen from aaloading from a aconst_null
        subtype = array.getType();
    }
    StackContext ctx = new StackContext(ins, subtype, array.getValue().arrayGet(index.getValue()));
    stack.push(ctx);
    ins.push(ctx);
    return ins;
}
Also used : InstructionContext(net.runelite.asm.execution.InstructionContext) InstructionType(net.runelite.asm.attributes.code.InstructionType) Type(net.runelite.asm.Type) StackContext(net.runelite.asm.execution.StackContext) Stack(net.runelite.asm.execution.Stack)

Example 34 with Type

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

Aggregations

Type (net.runelite.asm.Type)34 Signature (net.runelite.asm.signature.Signature)16 Method (net.runelite.asm.Method)15 ClassFile (net.runelite.asm.ClassFile)13 InstructionType (net.runelite.asm.attributes.code.InstructionType)13 Instruction (net.runelite.asm.attributes.code.Instruction)11 Field (net.runelite.asm.Field)10 Code (net.runelite.asm.attributes.Code)9 Instructions (net.runelite.asm.attributes.code.Instructions)9 ClassGroup (net.runelite.asm.ClassGroup)7 LDC (net.runelite.asm.attributes.code.instructions.LDC)7 Test (org.junit.Test)6 ArrayList (java.util.ArrayList)5 List (java.util.List)5 InvokeInstruction (net.runelite.asm.attributes.code.instruction.types.InvokeInstruction)5 PushConstantInstruction (net.runelite.asm.attributes.code.instruction.types.PushConstantInstruction)5 ALoad (net.runelite.asm.attributes.code.instructions.ALoad)5 InstructionContext (net.runelite.asm.execution.InstructionContext)5 Annotation (net.runelite.asm.attributes.annotation.Annotation)4 FieldInstruction (net.runelite.asm.attributes.code.instruction.types.FieldInstruction)4