https://github.com/TSedlar/Sedlar-Bytecode
http://rs-hacking.com/forum/index.php?/t...-bytecode/
Based on jclasslib
License: GPL v2
Here's a small example to get the revision for OSRS:
Alternatively you could replace result with:
or
Or if you'd like to use the instruction tree:
There's various ways to use this library and it's fairly extensive in terms of features, such as: measuring cyclomatic complexity for FlowGraphs, weighing BasicBlocks, and other unmentioned things; explore for yourself!
You can access a Method's FlowGraph via:
If you've got any questions go ahead and ask.
http://rs-hacking.com/forum/index.php?/t...-bytecode/
Based on jclasslib
License: GPL v2
Here's a small example to get the revision for OSRS:
Code:
JarArchive archive = new JarArchive(new File("./oldschool.jar"));
Map<String, ClassInfo> classes = archive.build();
InstructionFilter[] pattern = InstructionFilter.filtersFor("PIF 765", "PIF 503", "PIF :: rev"); // PIF -> PushInstructionFilter
QueryableInstructionList result = classes.get("client").methodByName("init").instructions().find(pattern);
if (result != null) {
PushInstruction rev = (PushInstruction) result.get("rev");
System.out.println("R" + rev.value());
}
Code:
QueryableInstructionList result = ci.methodByName("init").instructions().find(
PushInstructionFilter.create(765), PushInstructionFilter.create(503),
PushInstructionFilter.create().label("rev"));
Code:
PushInstruction result = (PushInstruction) ci.methodByName("init").instructions().first(
new PushInstructionFilter() {
public boolean accept(PushInstruction pi) {
AbstractInstruction ai = pi.previous(new PushInstructionFilter() {
public boolean accept(PushInstruction pi) {
return pi.value() == 503;
}
});
if (ai != null) {
return ai.previous(new PushInstructionFilter() {
public boolean accept(PushInstruction pi) {
return pi.value() == 765;
}
}) != null;
}
return false;
}
});
Code:
AtomicInteger rev = new AtomicInteger(-1);
ci.methodByName("init").tree().accept(new PushNodeFilter() {
public boolean accept(PushNode pn) {
if (pn.insn().value() == 765) {
pn = pn.nextPush();
if (pn != null && pn.insn().value() == 503) {
pn = pn.nextPush();
if (pn != null) {
rev.set(pn.insn().value());
return true;
}
}
}
return false;
}
});
System.out.println("R" + rev);
You can access a Method's FlowGraph via:
Code:
MethodInfo#graph()
Filtering:
IF -> InstructionFilter
IF x -> checks for opcode of x [Opcode] -- works for all filters as long as the opcode name is at index 1.
BIF -> BranchInstructionFilter
CIF -> ConstantInstructionFilter
CIF x -> checks for constant of x [parsed as int/String/null]
IIF -> IncrementInstructionFilter
IIF x -> checks for increment of x [int]
PIF -> PushInstructionFilter
PIF x -> checks for push value of x [int]
VIF -> VariableInstructionFilter
VIF x -> checks for variable value of x [int]
FIF -> FieldInstructionFilter
FIF STATIC -> checks for static fields also; if using FIF GETSTATIC/PUTSTATIC this will automatically be applied
FIF x x x -> checks for owner, name, descriptor
FIF x x -> checks for owner, descriptor
FIF x -> checks for descriptor
MIF -> MethodInstructionFilter
MIF x x x -> checks for owner, name, descriptor
MIF x x -> checks for owner, descriptor
MIF x -> checks for descriptor
MIF REGEX x -> checks for regex descriptor
{DUMMY} is replaced with regex for trailing I|B|S|D|F|J
i.e MIF REGEX (II{DUMMY})V
TIF -> TypeInstructionFilter
TIF x -> checks for descriptor of x
TIF REGEX x -> checks for regex descriptor
append " :: label" at the end to add a label to access the instruction as while matching the pattern.
i.e "PIF 765", "PIF 503", "PIF :: rev"