use of net.runelite.asm.attributes.code.Instructions in project runelite by runelite.
the class OpcodeReplacer method run.
public void run(ClassGroup group, Collection<PacketWrite> writes) {
int count = 0;
ClassFile runeliteOpcodes = group.findClass(RUNELITE_OPCODES);
assert runeliteOpcodes != null : "Opcodes class must exist";
for (PacketWrite wp : writes) {
Instructions ins = wp.getInstructions();
Instruction param = wp.getOpcodeIns();
if (!(param instanceof PushConstantInstruction)) {
continue;
}
final String fieldName = "PACKET_CLIENT_" + wp.getOpcode();
net.runelite.asm.pool.Field field = new net.runelite.asm.pool.Field(new net.runelite.asm.pool.Class(RUNELITE_OPCODES), fieldName, Type.INT);
ins.replace(param, new GetStatic(ins, field));
if (runeliteOpcodes.findField(fieldName) == null) {
Field opField = new Field(runeliteOpcodes, fieldName, Type.INT);
// ACC_FINAL causes javac to inline the fields, which prevents
// the mapper from doing field mapping
opField.setAccessFlags(ACC_PUBLIC | ACC_STATIC);
// setting a non-final static field value
// doesn't work with fernflower
opField.setValue(wp.getOpcode());
runeliteOpcodes.addField(opField);
// add initialization
Method clinit = runeliteOpcodes.findMethod("<clinit>");
assert clinit != null;
Instructions instructions = clinit.getCode().getInstructions();
instructions.addInstruction(0, new LDC(instructions, wp.getOpcode()));
instructions.addInstruction(1, new PutStatic(instructions, opField));
}
++count;
}
logger.info("Injected {} packet writes", count);
}
use of net.runelite.asm.attributes.code.Instructions in project runelite by runelite.
the class IfEqTest method testIsSame.
@Test
public void testIsSame() {
Instructions ins = mock(Instructions.class);
Frame originalIfEqFrame = mock(Frame.class);
Stack stack = new Stack(42);
Variables variables = new Variables(42);
when(originalIfEqFrame.getStack()).thenReturn(stack);
when(originalIfEqFrame.getVariables()).thenReturn(variables);
variables.set(9, new VariableContext(INT));
Instruction i = new LDC(ins, 0);
InstructionContext ctx = new InstructionContext(i, originalIfEqFrame);
// ifeq 0
IfEq ifeq = new IfEq(ins, InstructionType.IFEQ);
InstructionContext ifeqCtx = new InstructionContext(ifeq, originalIfEqFrame);
ifeqCtx.pop(new StackContext(ctx, INT, new Value(1)));
//
ins = mock(Instructions.class);
Frame originalIfIcmpNeFrame = mock(Frame.class);
stack = new Stack(42);
variables = new Variables(42);
when(originalIfIcmpNeFrame.getStack()).thenReturn(stack);
when(originalIfIcmpNeFrame.getVariables()).thenReturn(variables);
variables.set(5, new VariableContext(INT));
i = new LDC(ins, 1);
InstructionContext ctx1 = new InstructionContext(i, originalIfIcmpNeFrame);
i = new ILoad(ins, 5);
InstructionContext ctx2 = new InstructionContext(i, originalIfIcmpNeFrame);
// ificmpne 1
IfICmpNe ificmpne = new IfICmpNe(ins, InstructionType.IF_ICMPNE);
InstructionContext ificmpneCtx = new InstructionContext(ificmpne, originalIfIcmpNeFrame);
ificmpneCtx.pop(new StackContext(ctx1, INT, new Value(1)), new StackContext(ctx2, INT, Value.UNKNOWN));
assertEquals(ifeq.isSame(ifeqCtx, ificmpneCtx), ificmpne.isSame(ificmpneCtx, ifeqCtx));
// check that both frames jump the same direction
Frame ifeqBranchFrame = mock(Frame.class);
ifeqCtx.branch(ifeqBranchFrame);
Frame ificmpneBranchFrame = mock(Frame.class);
ificmpneCtx.branch(ificmpneBranchFrame);
// initially originalIfEqFrame.other == originalIfIcmpNeFrame.other
when(originalIfEqFrame.getOther()).thenReturn(originalIfIcmpNeFrame);
when(originalIfIcmpNeFrame.getOther()).thenReturn(originalIfEqFrame);
ParallelExecutorMapping mapping = mock(ParallelExecutorMapping.class);
ifeq.map(mapping, ifeqCtx, ificmpneCtx);
// verify that ifeqBranchFrame.other = ificmpneBranchFrame
ArgumentCaptor<Frame> frameCapture = ArgumentCaptor.forClass(Frame.class);
verify(ifeqBranchFrame).setOther(frameCapture.capture());
assertEquals(ificmpneBranchFrame, frameCapture.getValue());
}
use of net.runelite.asm.attributes.code.Instructions in project runelite by runelite.
the class ClassGroupFactory method generateGroup.
public static ClassGroup generateGroup() {
ClassGroup group = new ClassGroup();
ClassFile cf = new ClassFile(group);
cf.setName("test");
cf.setSuperName("java/lang/Object");
group.addClass(cf);
Field field = new Field(cf, "field", Type.INT);
field.setStatic();
cf.addField(field);
Method method = new Method(cf, "func", new Signature("()V"));
method.setStatic();
cf.addMethod(method);
Code code = new Code(method);
method.setCode(code);
{
method = new Method(cf, "func2", new Signature("(III)V"));
method.setStatic();
cf.addMethod(method);
code = new Code(method);
method.setCode(code);
Instructions ins = code.getInstructions();
ins.addInstruction(new VReturn(ins));
}
addVoidMethod(cf, "void1");
addVoidMethod(cf, "void2");
addVoidMethod(cf, "void3");
addVoidMethod(cf, "void4");
return group;
}
use of net.runelite.asm.attributes.code.Instructions 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;
}
use of net.runelite.asm.attributes.code.Instructions 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");
}
Aggregations