use of org.objectweb.asm.tree.JumpInsnNode in project evosuite by EvoSuite.
the class Instrumenter method wrapMethod.
/**
* public int myMethod(int i)
* {
* try
* {
* return _sw_prototype_original_myMethod(i)
* }
* finally
* {
* Capturer.enable();
* }
* }
*
* @param classNode
* @param className
* @param methodNode
*/
@SuppressWarnings("unchecked")
private MethodNode wrapMethod(final ClassNode classNode, final String className, final MethodNode methodNode) {
methodNode.maxStack += 4;
// create wrapper for original method
final MethodNode wrappingMethodNode = new MethodNode(methodNode.access, methodNode.name, methodNode.desc, methodNode.signature, (String[]) methodNode.exceptions.toArray(new String[methodNode.exceptions.size()]));
wrappingMethodNode.maxStack = methodNode.maxStack;
// assign annotations to wrapping method
wrappingMethodNode.visibleAnnotations = methodNode.visibleAnnotations;
wrappingMethodNode.visibleParameterAnnotations = methodNode.visibleParameterAnnotations;
// remove annotations from wrapped method to avoid wrong behavior controlled by annotations
methodNode.visibleAnnotations = null;
methodNode.visibleParameterAnnotations = null;
// rename original method
methodNode.access = TransformerUtil.modifyVisibility(methodNode.access, Opcodes.ACC_PRIVATE);
final LabelNode l0 = new LabelNode();
final LabelNode l1 = new LabelNode();
final LabelNode l2 = new LabelNode();
final InsnList wInstructions = wrappingMethodNode.instructions;
if ("<init>".equals(methodNode.name)) {
// wrap a constructor
methodNode.name = WRAP_NAME_PREFIX + "init" + WRAP_NAME_PREFIX;
// move call to other constructors to new method
AbstractInsnNode ins = null;
ListIterator<AbstractInsnNode> iter = methodNode.instructions.iterator();
// number of invokespecial calls before actual constructor call
int numInvokeSpecials = 0;
while (iter.hasNext()) {
ins = iter.next();
iter.remove();
wInstructions.add(ins);
if (ins instanceof MethodInsnNode) {
MethodInsnNode mins = (MethodInsnNode) ins;
if (ins.getOpcode() == Opcodes.INVOKESPECIAL) {
if (mins.name.startsWith("<init>")) {
if (numInvokeSpecials == 0) {
break;
} else {
numInvokeSpecials--;
}
}
}
} else if (ins instanceof TypeInsnNode) {
TypeInsnNode typeIns = (TypeInsnNode) ins;
if (typeIns.getOpcode() == Opcodes.NEW || typeIns.getOpcode() == Opcodes.NEWARRAY) {
numInvokeSpecials++;
}
}
}
} else {
methodNode.name = WRAP_NAME_PREFIX + methodNode.name;
}
int varReturnValue = 0;
final Type returnType = Type.getReturnType(methodNode.desc);
if (returnType.equals(Type.VOID_TYPE)) {
wrappingMethodNode.tryCatchBlocks.add(new TryCatchBlockNode(l0, l1, l1, "java/lang/Throwable"));
} else {
wrappingMethodNode.tryCatchBlocks.add(new TryCatchBlockNode(l0, l1, l2, "java/lang/Throwable"));
if (!TransformerUtil.isStatic(methodNode.access)) {
// load "this"
varReturnValue++;
}
// consider method arguments to find right variable index
final Type[] argTypes = Type.getArgumentTypes(methodNode.desc);
for (int i = 0; i < argTypes.length; i++) {
varReturnValue++;
// long/double take two registers
if (argTypes[i].equals(Type.LONG_TYPE) || argTypes[i].equals(Type.DOUBLE_TYPE)) {
varReturnValue++;
}
}
// push NULL on the stack and initialize variable for return value for it
wInstructions.add(new InsnNode(Opcodes.ACONST_NULL));
wInstructions.add(new VarInsnNode(Opcodes.ASTORE, varReturnValue));
}
int var = 0;
// --- L0
wInstructions.add(l0);
wInstructions.add(this.addCaptureCall(TransformerUtil.isStatic(methodNode.access), className, wrappingMethodNode.name, wrappingMethodNode.desc, Type.getArgumentTypes(methodNode.desc)));
if (!TransformerUtil.isStatic(methodNode.access)) {
// load "this" to call method
wInstructions.add(new VarInsnNode(Opcodes.ALOAD, 0));
var++;
}
final Type[] argTypes = Type.getArgumentTypes(methodNode.desc);
for (int i = 0; i < argTypes.length; i++) {
this.addLoadInsn(wInstructions, argTypes[i], var++);
// long/double take two registers
if (argTypes[i].equals(Type.LONG_TYPE) || argTypes[i].equals(Type.DOUBLE_TYPE)) {
var++;
}
}
if (TransformerUtil.isStatic(methodNode.access)) {
wInstructions.add(new MethodInsnNode(Opcodes.INVOKESTATIC, classNode.name, methodNode.name, methodNode.desc));
} else {
wInstructions.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, classNode.name, methodNode.name, methodNode.desc));
}
var++;
if (returnType.equals(Type.VOID_TYPE)) {
wInstructions.add(new JumpInsnNode(Opcodes.GOTO, l2));
// --- L1
wInstructions.add(l1);
wInstructions.add(new FrameNode(Opcodes.F_SAME1, 0, null, 1, new Object[] { "java/lang/Throwable" }));
wInstructions.add(new VarInsnNode(Opcodes.ASTORE, --var));
this.addCaptureEnableStatement(className, methodNode, wInstructions, -1);
wInstructions.add(new VarInsnNode(Opcodes.ALOAD, var));
wInstructions.add(new InsnNode(Opcodes.ATHROW));
// FIXME <--- DUPLICATE CODE
// --- L2
wInstructions.add(l2);
wInstructions.add(new FrameNode(Opcodes.F_SAME, 0, null, 0, null));
this.addCaptureEnableStatement(className, methodNode, wInstructions, -1);
wInstructions.add(new InsnNode(Opcodes.RETURN));
} else {
// construct store of the wrapped method call's result
this.addBoxingStmt(wInstructions, returnType);
wInstructions.add(new VarInsnNode(Opcodes.ASTORE, varReturnValue));
wInstructions.add(new VarInsnNode(Opcodes.ALOAD, varReturnValue));
this.addUnBoxingStmt(wInstructions, returnType);
final int storeOpcode = returnType.getOpcode(Opcodes.ISTORE);
// might be only var
wInstructions.add(new VarInsnNode(storeOpcode, ++var));
// --- L1
wInstructions.add(l1);
this.addCaptureEnableStatement(className, methodNode, wInstructions, varReturnValue);
// construct load of the wrapped method call's result
int loadOpcode = returnType.getOpcode(Opcodes.ILOAD);
wInstructions.add(new VarInsnNode(loadOpcode, var));
// construct return of the wrapped method call's result
this.addReturnInsn(wInstructions, returnType);
// ---- L2
wInstructions.add(l2);
wInstructions.add(new FrameNode(Opcodes.F_FULL, 2, new Object[] { className, this.getInternalName(returnType) }, 1, new Object[] { "java/lang/Throwable" }));
wInstructions.add(new VarInsnNode(Opcodes.ASTORE, --var));
this.addCaptureEnableStatement(className, methodNode, wInstructions, varReturnValue);
wInstructions.add(new VarInsnNode(Opcodes.ALOAD, var));
wInstructions.add(new InsnNode(Opcodes.ATHROW));
}
transformWrapperCalls(methodNode);
return wrappingMethodNode;
}
use of org.objectweb.asm.tree.JumpInsnNode in project evosuite by EvoSuite.
the class LCSAJsInstrumentation method analyze.
/* (non-Javadoc)
* @see org.evosuite.cfg.MethodInstrumentation#analyze(org.objectweb.asm.tree.MethodNode, org.jgrapht.Graph, java.lang.String, java.lang.String)
*/
/**
* {@inheritDoc}
*/
@SuppressWarnings("unchecked")
// using external lib
@Override
public void analyze(ClassLoader classLoader, MethodNode mn, String className, String methodName, int access) {
Queue<LCSAJ> lcsaj_queue = new LinkedList<LCSAJ>();
HashSet<Integer> targets_reached = new HashSet<Integer>();
AbstractInsnNode start = mn.instructions.getFirst();
int startID = 0;
// TODO: This should replace the hack below
if (methodName.startsWith("<init>")) {
Iterator<AbstractInsnNode> j = mn.instructions.iterator();
boolean constructorInvoked = false;
while (j.hasNext()) {
AbstractInsnNode in = j.next();
startID++;
if (!constructorInvoked) {
if (in.getOpcode() == Opcodes.INVOKESPECIAL) {
MethodInsnNode cn = (MethodInsnNode) in;
Collection<String> superClasses = DependencyAnalysis.getInheritanceTree().getSuperclasses(className);
superClasses.add(className);
String classNameWithDots = ResourceList.getClassNameFromResourcePath(cn.owner);
if (superClasses.contains(classNameWithDots)) {
constructorInvoked = true;
break;
}
} else {
continue;
}
}
}
}
/*
if (methodName.startsWith("<init>")) {
if (mn.instructions.size() >= 4) {
start = mn.instructions.get(4);
startID = 4;
}
}
*/
LCSAJ a = new LCSAJ(className, methodName, BytecodeInstructionPool.getInstance(classLoader).getInstruction(className, methodName, startID, start));
lcsaj_queue.add(a);
targets_reached.add(0);
ArrayList<TryCatchBlockNode> tc_blocks = (ArrayList<TryCatchBlockNode>) mn.tryCatchBlocks;
for (TryCatchBlockNode t : tc_blocks) {
LCSAJ b = new LCSAJ(className, methodName, BytecodeInstructionPool.getInstance(classLoader).getInstruction(className, methodName, mn.instructions.indexOf(t.handler), t.handler));
lcsaj_queue.add(b);
}
while (!lcsaj_queue.isEmpty()) {
LCSAJ currentLCSAJ = lcsaj_queue.poll();
int position = mn.instructions.indexOf(currentLCSAJ.getLastNodeAccessed());
// go to next bytecode instruction
position++;
if (position >= mn.instructions.size()) {
// New LCSAJ for current + return
LCSAJPool.add_lcsaj(className, methodName, currentLCSAJ);
continue;
}
AbstractInsnNode next = mn.instructions.get(position);
currentLCSAJ.lookupInstruction(position, BytecodeInstructionPool.getInstance(classLoader).getInstruction(className, methodName, position, next));
if (next instanceof JumpInsnNode) {
JumpInsnNode jump = (JumpInsnNode) next;
// New LCSAJ for current + jump to target
LCSAJPool.add_lcsaj(className, methodName, currentLCSAJ);
LabelNode target = jump.label;
int targetPosition = mn.instructions.indexOf(target);
if (jump.getOpcode() != Opcodes.GOTO) {
LCSAJ copy = new LCSAJ(currentLCSAJ);
lcsaj_queue.add(copy);
}
if (!targets_reached.contains(targetPosition)) {
LCSAJ c = new LCSAJ(className, methodName, BytecodeInstructionPool.getInstance(classLoader).getInstruction(className, methodName, targetPosition, target));
lcsaj_queue.add(c);
targets_reached.add(targetPosition);
}
} else if (next instanceof TableSwitchInsnNode) {
TableSwitchInsnNode tswitch = (TableSwitchInsnNode) next;
List<LabelNode> allTargets = tswitch.labels;
for (LabelNode target : allTargets) {
int targetPosition = mn.instructions.indexOf(target);
if (!targets_reached.contains(targetPosition)) {
LCSAJ b = new LCSAJ(className, methodName, BytecodeInstructionPool.getInstance(classLoader).getInstruction(className, methodName, targetPosition, target));
lcsaj_queue.add(b);
targets_reached.add(targetPosition);
}
}
} else if (next instanceof InsnNode) {
InsnNode insn = (InsnNode) next;
// New LCSAJ for current + throw / return
if (insn.getOpcode() == Opcodes.ATHROW || insn.getOpcode() == Opcodes.RETURN || insn.getOpcode() == Opcodes.ARETURN || insn.getOpcode() == Opcodes.IRETURN || insn.getOpcode() == Opcodes.DRETURN || insn.getOpcode() == Opcodes.LRETURN || insn.getOpcode() == Opcodes.FRETURN) {
LCSAJPool.add_lcsaj(className, methodName, currentLCSAJ);
} else
lcsaj_queue.add(currentLCSAJ);
} else
lcsaj_queue.add(currentLCSAJ);
}
if (Properties.STRATEGY != Strategy.EVOSUITE)
addInstrumentation(classLoader, mn, className, methodName);
// if (Properties.WRITE_CFG)
// for (LCSAJ l : LCSAJPool.getLCSAJs(className, methodName)) {
// LCSAJGraph graph = new LCSAJGraph(l, false);
// String graphDestination = "evosuite-graphs/LCSAJGraphs/" + className
// + "/" + methodName;
// File dir = new File(graphDestination);
// if (dir.mkdirs())
// graph.generate(new File(graphDestination + "/LCSAJGraph no: "
// + l.getID() + ".dot"));
// else if (dir.exists())
// graph.generate(new File(graphDestination + "/LCSAJGraph no: "
// + l.getID() + ".dot"));
// }
}
use of org.objectweb.asm.tree.JumpInsnNode in project Random-Things by lumien231.
the class ClassTransformer method patchWorldClass.
private byte[] patchWorldClass(byte[] basicClass) {
ClassNode classNode = new ClassNode();
ClassReader classReader = new ClassReader(basicClass);
classReader.accept(classNode, 0);
logger.log(Level.DEBUG, "Found World Class: " + classNode.name);
MethodNode getRedstonePower = null;
MethodNode getStrongPower = null;
MethodNode isRainingAt = null;
MethodNode canSnowAt = null;
for (MethodNode mn : classNode.methods) {
if (mn.name.equals(MCPNames.method("func_175651_c"))) {
getRedstonePower = mn;
} else if (mn.name.equals(MCPNames.method("func_175627_a")) && mn.desc.equals("(Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/util/EnumFacing;)I")) {
getStrongPower = mn;
} else if (mn.name.equals(MCPNames.method("func_175727_C"))) {
isRainingAt = mn;
} else if (mn.name.equals(MCPNames.method("func_175708_f"))) {
canSnowAt = mn;
}
}
if (getRedstonePower != null) {
logger.log(Level.DEBUG, "- Found getRedstonePower (1/4)");
InsnList toInsert = new InsnList();
LabelNode l1 = new LabelNode(new Label());
toInsert.add(new VarInsnNode(ALOAD, 0));
toInsert.add(new VarInsnNode(ALOAD, 1));
toInsert.add(new VarInsnNode(ALOAD, 2));
toInsert.add(new MethodInsnNode(INVOKESTATIC, asmHandler, "getRedstonePower", "(Lnet/minecraft/world/World;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/util/EnumFacing;)I", false));
toInsert.add(new InsnNode(DUP));
toInsert.add(new JumpInsnNode(IFEQ, l1));
toInsert.add(new InsnNode(IRETURN));
toInsert.add(l1);
toInsert.add(new InsnNode(POP));
getRedstonePower.instructions.insert(toInsert);
}
if (getStrongPower != null) {
logger.log(Level.DEBUG, "- Found getStrongPower (2/4)");
InsnList toInsert = new InsnList();
LabelNode l1 = new LabelNode(new Label());
toInsert.add(new VarInsnNode(ALOAD, 0));
toInsert.add(new VarInsnNode(ALOAD, 1));
toInsert.add(new VarInsnNode(ALOAD, 2));
toInsert.add(new MethodInsnNode(INVOKESTATIC, asmHandler, "getStrongPower", "(Lnet/minecraft/world/World;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/util/EnumFacing;)I", false));
toInsert.add(new InsnNode(DUP));
toInsert.add(new JumpInsnNode(IFEQ, l1));
toInsert.add(new InsnNode(IRETURN));
toInsert.add(l1);
toInsert.add(new InsnNode(POP));
getStrongPower.instructions.insert(toInsert);
}
if (isRainingAt != null) {
logger.log(Level.DEBUG, "- Found isRainingAt (3/4)");
AbstractInsnNode returnNode = null;
for (int i = 0; i < isRainingAt.instructions.size(); i++) {
AbstractInsnNode ain = isRainingAt.instructions.get(i);
if (ain.getOpcode() == Opcodes.IRETURN) {
returnNode = ain;
}
}
InsnList toInsert = new InsnList();
LabelNode returnLabel = new LabelNode(new Label());
toInsert.add(new InsnNode(Opcodes.DUP));
toInsert.add(new JumpInsnNode(IFEQ, returnLabel));
toInsert.add(new InsnNode(POP));
toInsert.add(new VarInsnNode(ALOAD, 0));
toInsert.add(new VarInsnNode(ALOAD, 1));
toInsert.add(new MethodInsnNode(INVOKESTATIC, asmHandler, "shouldRain", "(Lnet/minecraft/world/World;Lnet/minecraft/util/math/BlockPos;)Z", false));
toInsert.add(returnLabel);
isRainingAt.instructions.insertBefore(returnNode, toInsert);
}
if (canSnowAt != null) {
logger.log(Level.DEBUG, "- Found canSnowAt (4/4)");
AbstractInsnNode returnNode = null;
for (int i = 0; i < canSnowAt.instructions.size(); i++) {
AbstractInsnNode ain = canSnowAt.instructions.get(i);
if (ain.getOpcode() == Opcodes.IRETURN) {
returnNode = ain;
}
}
InsnList toInsert = new InsnList();
LabelNode returnLabel = new LabelNode(new Label());
toInsert.add(new InsnNode(Opcodes.DUP));
toInsert.add(new JumpInsnNode(IFEQ, returnLabel));
toInsert.add(new InsnNode(POP));
toInsert.add(new VarInsnNode(ALOAD, 0));
toInsert.add(new VarInsnNode(ALOAD, 1));
toInsert.add(new MethodInsnNode(INVOKESTATIC, asmHandler, "canSnowAt", "(Lnet/minecraft/world/World;Lnet/minecraft/util/math/BlockPos;)Z", false));
toInsert.add(returnLabel);
canSnowAt.instructions.insertBefore(returnNode, toInsert);
}
CustomClassWriter writer = new CustomClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
classNode.accept(writer);
return writer.toByteArray();
}
use of org.objectweb.asm.tree.JumpInsnNode in project Random-Things by lumien231.
the class ClassTransformer method patchBlockRendererDispatcher.
private byte[] patchBlockRendererDispatcher(byte[] basicClass) {
ClassNode classNode = new ClassNode();
ClassReader classReader = new ClassReader(basicClass);
classReader.accept(classNode, 0);
logger.log(Level.DEBUG, "Found BlockRendererDispatcher Class: " + classNode.name);
MethodNode renderBlock = null;
for (MethodNode mn : classNode.methods) {
if (mn.name.equals(MCPNames.method("func_175018_a"))) {
renderBlock = mn;
}
}
if (renderBlock != null) {
logger.log(Level.DEBUG, "- Found renderBlock (1/1)");
InsnList toInsert = new InsnList();
LabelNode l1 = new LabelNode(new Label());
toInsert.add(new VarInsnNode(ALOAD, 0));
toInsert.add(new VarInsnNode(ALOAD, 1));
toInsert.add(new VarInsnNode(ALOAD, 2));
toInsert.add(new VarInsnNode(ALOAD, 3));
toInsert.add(new VarInsnNode(ALOAD, 4));
toInsert.add(new MethodInsnNode(INVOKESTATIC, asmHandler, "renderBlock", "(Lnet/minecraft/client/renderer/BlockRendererDispatcher;Lnet/minecraft/block/state/IBlockState;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/world/IBlockAccess;Lnet/minecraft/client/renderer/BufferBuilder;)I", false));
toInsert.add(new InsnNode(DUP));
toInsert.add(new InsnNode(ICONST_2));
toInsert.add(new JumpInsnNode(IF_ICMPEQ, l1));
toInsert.add(new InsnNode(IRETURN));
toInsert.add(l1);
toInsert.add(new InsnNode(POP));
renderBlock.instructions.insert(toInsert);
}
CustomClassWriter writer = new CustomClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
classNode.accept(writer);
return writer.toByteArray();
}
use of org.objectweb.asm.tree.JumpInsnNode in project Random-Things by lumien231.
the class ClassTransformer method patchEntityRenderer.
private byte[] patchEntityRenderer(byte[] basicClass) {
ClassNode classNode = new ClassNode();
ClassReader classReader = new ClassReader(basicClass);
classReader.accept(classNode, 0);
logger.log(Level.DEBUG, "Found EntityRenderer Class: " + classNode.name);
MethodNode renderRainSnow = null;
MethodNode addRainParticles = null;
for (MethodNode mn : classNode.methods) {
if (mn.name.equals(MCPNames.method("func_78474_d"))) {
renderRainSnow = mn;
} else if (mn.name.equals(MCPNames.method("func_78484_h"))) {
addRainParticles = mn;
}
}
if (renderRainSnow != null) {
logger.log(Level.DEBUG, "- Found renderRainSnow");
VarInsnNode insnPoint = null;
for (int i = 0; i < renderRainSnow.instructions.size(); i++) {
AbstractInsnNode ain = renderRainSnow.instructions.get(i);
if (ain instanceof MethodInsnNode) {
MethodInsnNode min = (MethodInsnNode) ain;
if (min.name.equals(MCPNames.method("func_76738_d"))) {
logger.log(Level.DEBUG, "- Found canRain");
insnPoint = (VarInsnNode) renderRainSnow.instructions.get(i - 1);
}
if (min.name.equals(MCPNames.method("func_76746_c"))) {
logger.log(Level.DEBUG, "- Found getEnableSnow");
int jumpCounter = i + 1;
int worldIndex = 5;
int blockPosIndex = 21;
// Optifine Why :'(
for (LocalVariableNode lv : renderRainSnow.localVariables) {
if (lv.desc.equals("Lnet/minecraft/client/multiplayer/WorldClient;") || lv.desc.equals("Lnet/minecraft/world/World;")) {
worldIndex = lv.index;
} else if (lv.desc.equals("Lnet/minecraft/util/math/BlockPos$MutableBlockPos;")) {
blockPosIndex = lv.index;
}
}
AbstractInsnNode jumpNode;
while (!((jumpNode = renderRainSnow.instructions.get(jumpCounter)) instanceof JumpInsnNode)) {
jumpCounter++;
}
JumpInsnNode jin = (JumpInsnNode) jumpNode;
LabelNode labelNode = jin.label;
InsnList toInsert = new InsnList();
toInsert.add(new VarInsnNode(ALOAD, worldIndex));
toInsert.add(new VarInsnNode(ALOAD, blockPosIndex));
toInsert.add(new MethodInsnNode(INVOKESTATIC, asmHandler, "shouldRain", "(Lnet/minecraft/world/World;Lnet/minecraft/util/math/BlockPos;)Z", false));
toInsert.add(new JumpInsnNode(IFEQ, labelNode));
renderRainSnow.instructions.insertBefore(insnPoint, toInsert);
i += 4;
}
}
}
}
if (addRainParticles != null) {
logger.log(Level.DEBUG, "- Found addRainParticles");
for (int i = 0; i < addRainParticles.instructions.size(); i++) {
AbstractInsnNode ain = addRainParticles.instructions.get(i);
if (ain instanceof JumpInsnNode) {
JumpInsnNode jin = (JumpInsnNode) ain;
if (jin.getOpcode() == Opcodes.IF_ICMPGT) {
LabelNode jumpTarget = jin.label;
InsnList toInsert = new InsnList();
toInsert.add(new VarInsnNode(ALOAD, 3));
toInsert.add(new VarInsnNode(ALOAD, 15));
toInsert.add(new MethodInsnNode(INVOKESTATIC, asmHandler, "shouldRain", "(Lnet/minecraft/world/World;Lnet/minecraft/util/math/BlockPos;)Z", false));
toInsert.add(new JumpInsnNode(IFEQ, jumpTarget));
addRainParticles.instructions.insert(jin, toInsert);
break;
}
}
}
}
CustomClassWriter writer = new CustomClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
classNode.accept(writer);
return writer.toByteArray();
}
Aggregations