use of net.runelite.asm.Field in project runelite by runelite.
the class PacketTypeFinder method run.
private void run(Code code) {
if (code == null) {
return;
}
Instructions instructions = code.getInstructions();
for (int i = 0; i < instructions.getInstructions().size() - 1; ++i) {
Instruction i1 = instructions.getInstructions().get(i), i2 = instructions.getInstructions().get(i + 1);
if (i1 instanceof PushConstantInstruction && i2.getType() == InstructionType.PUTSTATIC) {
PushConstantInstruction pci = (PushConstantInstruction) i1;
SetFieldInstruction sfi = (SetFieldInstruction) i2;
Field field = sfi.getMyField();
if (Objects.equal(-1, pci.getConstant()) && field != null) {
Integer count = sets.get(field);
if (count == null) {
sets.put(field, 1);
} else {
sets.put(field, count + 1);
}
}
}
}
}
use of net.runelite.asm.Field 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.Field in project runelite by runelite.
the class UnusedFields method run.
@Override
public void run(ClassGroup group) {
checkForFieldUsage(group);
int count = 0;
for (ClassFile cf : group.getClasses()) for (Field f : new ArrayList<>(cf.getFields())) if (!used.contains(f)) {
cf.removeField(f);
++count;
}
logger.info("Removed " + count + " unused fields");
}
use of net.runelite.asm.Field 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.Field 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();
}
Aggregations