use of org.objectweb.asm.tree.FrameNode in project MinecraftForge by MinecraftForge.
the class EventSubscriptionTransformer method buildEvents.
private boolean buildEvents(ClassNode classNode) throws Exception {
// Yes, this recursively loads classes until we get this base class. THIS IS NOT A ISSUE. Coremods should handle re-entry just fine.
// If they do not this a COREMOD issue NOT a Forge/LaunchWrapper issue.
Class<?> parent = this.getClass().getClassLoader().loadClass(classNode.superName.replace('/', '.'));
if (!Event.class.isAssignableFrom(parent)) {
return false;
}
//Class<?> listenerListClazz = Class.forName("net.minecraftforge.fml.common.eventhandler.ListenerList", false, getClass().getClassLoader());
Type tList = Type.getType("Lnet/minecraftforge/fml/common/eventhandler/ListenerList;");
boolean edited = false;
boolean hasSetup = false;
boolean hasGetListenerList = false;
boolean hasDefaultCtr = false;
boolean hasCancelable = false;
boolean hasResult = false;
String voidDesc = Type.getMethodDescriptor(VOID_TYPE);
String boolDesc = Type.getMethodDescriptor(BOOLEAN_TYPE);
String listDesc = tList.getDescriptor();
String listDescM = Type.getMethodDescriptor(tList);
for (MethodNode method : classNode.methods) {
if (method.name.equals("setup") && method.desc.equals(voidDesc) && (method.access & ACC_PROTECTED) == ACC_PROTECTED)
hasSetup = true;
if ((method.access & ACC_PUBLIC) == ACC_PUBLIC) {
if (method.name.equals("getListenerList") && method.desc.equals(listDescM))
hasGetListenerList = true;
if (method.name.equals("isCancelable") && method.desc.equals(boolDesc))
hasCancelable = true;
if (method.name.equals("hasResult") && method.desc.equals(boolDesc))
hasResult = true;
}
if (method.name.equals("<init>") && method.desc.equals(voidDesc))
hasDefaultCtr = true;
}
if (classNode.visibleAnnotations != null) {
for (AnnotationNode node : classNode.visibleAnnotations) {
if (!hasResult && node.desc.equals("Lnet/minecraftforge/fml/common/eventhandler/Event$HasResult;")) {
/* Add:
* public boolean hasResult()
* {
* return true;
* }
*/
MethodNode method = new MethodNode(ACC_PUBLIC, "hasResult", boolDesc, null, null);
method.instructions.add(new InsnNode(ICONST_1));
method.instructions.add(new InsnNode(IRETURN));
classNode.methods.add(method);
edited = true;
} else if (!hasCancelable && node.desc.equals("Lnet/minecraftforge/fml/common/eventhandler/Cancelable;")) {
/* Add:
* public boolean isCancelable()
* {
* return true;
* }
*/
MethodNode method = new MethodNode(ACC_PUBLIC, "isCancelable", boolDesc, null, null);
method.instructions.add(new InsnNode(ICONST_1));
method.instructions.add(new InsnNode(IRETURN));
classNode.methods.add(method);
edited = true;
}
}
}
if (hasSetup) {
if (!hasGetListenerList)
throw new RuntimeException("Event class defines setup() but does not define getListenerList! " + classNode.name);
else
return edited;
}
Type tSuper = Type.getType(classNode.superName);
//Add private static ListenerList LISTENER_LIST
classNode.fields.add(new FieldNode(ACC_PRIVATE | ACC_STATIC, "LISTENER_LIST", listDesc, null, null));
/*Add:
* public <init>()
* {
* super();
* }
*/
if (!hasDefaultCtr) {
MethodNode method = new MethodNode(ACC_PUBLIC, "<init>", voidDesc, null, null);
method.instructions.add(new VarInsnNode(ALOAD, 0));
method.instructions.add(new MethodInsnNode(INVOKESPECIAL, tSuper.getInternalName(), "<init>", voidDesc, false));
method.instructions.add(new InsnNode(RETURN));
classNode.methods.add(method);
}
/*Add:
* protected void setup()
* {
* super.setup();
* if (LISTENER_LIST != NULL)
* {
* return;
* }
* LISTENER_LIST = new ListenerList(super.getListenerList());
* }
*/
MethodNode method = new MethodNode(ACC_PROTECTED, "setup", voidDesc, null, null);
method.instructions.add(new VarInsnNode(ALOAD, 0));
method.instructions.add(new MethodInsnNode(INVOKESPECIAL, tSuper.getInternalName(), "setup", voidDesc, false));
method.instructions.add(new FieldInsnNode(GETSTATIC, classNode.name, "LISTENER_LIST", listDesc));
LabelNode initListener = new LabelNode();
method.instructions.add(new JumpInsnNode(IFNULL, initListener));
method.instructions.add(new InsnNode(RETURN));
method.instructions.add(initListener);
method.instructions.add(new FrameNode(F_SAME, 0, null, 0, null));
method.instructions.add(new TypeInsnNode(NEW, tList.getInternalName()));
method.instructions.add(new InsnNode(DUP));
method.instructions.add(new VarInsnNode(ALOAD, 0));
method.instructions.add(new MethodInsnNode(INVOKESPECIAL, tSuper.getInternalName(), "getListenerList", listDescM, false));
method.instructions.add(new MethodInsnNode(INVOKESPECIAL, tList.getInternalName(), "<init>", getMethodDescriptor(VOID_TYPE, tList), false));
method.instructions.add(new FieldInsnNode(PUTSTATIC, classNode.name, "LISTENER_LIST", listDesc));
method.instructions.add(new InsnNode(RETURN));
classNode.methods.add(method);
/*Add:
* public ListenerList getListenerList()
* {
* return this.LISTENER_LIST;
* }
*/
method = new MethodNode(ACC_PUBLIC, "getListenerList", listDescM, null, null);
method.instructions.add(new FieldInsnNode(GETSTATIC, classNode.name, "LISTENER_LIST", listDesc));
method.instructions.add(new InsnNode(ARETURN));
classNode.methods.add(method);
return true;
}
use of org.objectweb.asm.tree.FrameNode in project MineCamera by PorPit.
the class Transformer method replaceLabelBefore.
public void replaceLabelBefore(InsnList instructions, AbstractInsnNode node, @Nullable ArrayList<AbstractInsnNode> replaceInstructions, int labels, int labelsBefore, boolean keepFirstLabel, boolean deleteFrame) {
ListIterator<AbstractInsnNode> iterator = instructions.iterator();
LabelNode searchedLabel = null;
ArrayList<LabelNode> foundLabels = new ArrayList<LabelNode>();
while (iterator.hasNext()) {
AbstractInsnNode insn = iterator.next();
if (insn instanceof LabelNode)
foundLabels.add((LabelNode) insn);
if (areNodesEqual(insn, node)) {
int index = foundLabels.size() - 1;
index -= labelsBefore;
if (index >= 0)
searchedLabel = foundLabels.get(index);
labels += labelsBefore;
break;
}
}
if (searchedLabel != null) {
boolean found = false;
int labelCounter = 0;
iterator = instructions.iterator();
while (iterator.hasNext()) {
AbstractInsnNode insn = iterator.next();
if (found && insn instanceof LabelNode) {
labelCounter++;
if (labelCounter >= labels) {
if (replaceInstructions != null)
for (int i = 0; i < replaceInstructions.size(); i++) instructions.insertBefore(insn, replaceInstructions.get(i));
break;
}
}
if (insn == searchedLabel) {
found = true;
if (keepFirstLabel)
continue;
}
if (found)
if (deleteFrame || !(insn instanceof FrameNode))
instructions.remove(insn);
}
} else if (node instanceof LineNumberNode)
System.out.println("COULD NOT FIND NODE line=" + ((LineNumberNode) node).line);
}
use of org.objectweb.asm.tree.FrameNode in project evosuite by EvoSuite.
the class BooleanTestabilityTransformation method isBooleanAssignment.
/**
* This helper function determines whether the boolean on the stack at the
* current position will be stored in a Boolean variable
*
* @param position
* @param mn
* @return
*/
public boolean isBooleanAssignment(AbstractInsnNode position, MethodNode mn) {
AbstractInsnNode node = position.getNext();
logger.info("Checking for ISTORE after boolean");
boolean done = false;
while (!done) {
if (node.getOpcode() == Opcodes.PUTFIELD || node.getOpcode() == Opcodes.PUTSTATIC) {
// TODO: Check whether field is static
logger.info("Checking field assignment");
FieldInsnNode fn = (FieldInsnNode) node;
if (Type.getType(DescriptorMapping.getInstance().getFieldDesc(fn.owner, fn.name, fn.desc)) == Type.BOOLEAN_TYPE) {
return true;
} else {
return false;
}
} else if (node.getOpcode() == Opcodes.ISTORE) {
logger.info("Found ISTORE after boolean");
VarInsnNode vn = (VarInsnNode) node;
// TODO: Check whether variable at this position is a boolean
if (isBooleanVariable(vn.var, mn)) {
logger.info("Assigning boolean to variable ");
return true;
} else {
logger.info("Variable is not a bool");
return false;
}
} else if (node.getOpcode() == Opcodes.IRETURN) {
logger.info("Checking return value of method " + cn.name + "." + mn.name);
if (DescriptorMapping.getInstance().isTransformedOrBooleanMethod(cn.name, mn.name, mn.desc)) {
logger.info("Method returns a bool");
return true;
} else {
logger.info("Method does not return a bool");
return false;
}
} else if (node.getOpcode() == Opcodes.BASTORE) {
// We remove all bytes, so BASTORE is only used for booleans
AbstractInsnNode start = position.getNext();
boolean reassignment = false;
while (start != node) {
if (node instanceof InsnNode) {
reassignment = true;
}
start = start.getNext();
}
logger.info("Possible assignment to array?");
if (reassignment)
return false;
else
return true;
} else if (node instanceof MethodInsnNode) {
// if it is a boolean parameter of a converted method, then it needs to be converted
// Problem: How do we know which parameter it represents?
MethodInsnNode methodNode = (MethodInsnNode) node;
String desc = DescriptorMapping.getInstance().getMethodDesc(methodNode.owner, methodNode.name, methodNode.desc);
Type[] types = Type.getArgumentTypes(desc);
if (types.length > 0 && types[types.length - 1] == Type.BOOLEAN_TYPE) {
return true;
} else {
return false;
}
} else if (node.getOpcode() == Opcodes.GOTO || node.getOpcode() == Opcodes.ICONST_0 || node.getOpcode() == Opcodes.ICONST_1 || node.getOpcode() == -1) {
logger.info("Continuing search");
// continue search
} else if (!(node instanceof LineNumberNode || node instanceof FrameNode)) {
logger.info("Search ended with opcode " + node.getOpcode());
return false;
}
if (node != mn.instructions.getLast())
node = node.getNext();
else
done = true;
}
return false;
}
use of org.objectweb.asm.tree.FrameNode in project evosuite by EvoSuite.
the class ImplicitElseTransformer method transformFieldInsnNode.
/* (non-Javadoc)
* @see org.evosuite.instrumentation.MethodNodeTransformer#transformFieldInsnNode(org.objectweb.asm.tree.MethodNode, org.objectweb.asm.tree.FieldInsnNode)
*/
@SuppressWarnings("unchecked")
@Override
protected AbstractInsnNode transformFieldInsnNode(MethodNode mn, FieldInsnNode fieldNode) {
if ((fieldNode.getOpcode() == Opcodes.PUTFIELD || fieldNode.getOpcode() == Opcodes.PUTSTATIC) && DescriptorMapping.getInstance().isTransformedOrBooleanField(fieldNode.owner, fieldNode.name, fieldNode.desc)) {
if (addedInsns.contains(fieldNode))
return fieldNode;
// whether we need to pop one or two words
if (fieldNode.getOpcode() == Opcodes.PUTFIELD) {
AbstractInsnNode previous = fieldNode.getPrevious();
while (previous instanceof LineNumberNode || previous instanceof FrameNode || previous.getOpcode() == Opcodes.ICONST_0 || previous.getOpcode() == Opcodes.ICONST_1) previous = previous.getPrevious();
if (previous.getOpcode() != Opcodes.ALOAD) {
BooleanTestabilityTransformation.logger.info("Can't handle case of " + previous);
return fieldNode;
}
VarInsnNode varNode = (VarInsnNode) previous;
if (varNode.var != 0) {
BooleanTestabilityTransformation.logger.info("Can't handle case of " + previous);
return fieldNode;
}
}
BooleanTestabilityTransformation.logger.info("Handling PUTFIELD case!");
// Check if ICONST_0 or ICONST_1 are on the stack
ControlDependenceGraph cdg = GraphPool.getInstance(this.booleanTestabilityTransformation.classLoader).getCDG(this.booleanTestabilityTransformation.className.replace("/", "."), mn.name + mn.desc);
int index = mn.instructions.indexOf(fieldNode);
BooleanTestabilityTransformation.logger.info("Getting bytecode instruction for " + fieldNode.name + "/" + ((FieldInsnNode) mn.instructions.get(index)).name);
InsnList nodes = mn.instructions;
ListIterator<AbstractInsnNode> it = nodes.iterator();
while (it.hasNext()) {
BytecodeInstruction in = new BytecodeInstruction(this.booleanTestabilityTransformation.classLoader, this.booleanTestabilityTransformation.className, mn.name, 0, 0, it.next());
BooleanTestabilityTransformation.logger.info(in.toString());
}
BytecodeInstruction insn = BytecodeInstructionPool.getInstance(this.booleanTestabilityTransformation.classLoader).getInstruction(this.booleanTestabilityTransformation.className.replace("/", "."), mn.name + mn.desc, index);
if (insn == null)
insn = BytecodeInstructionPool.getInstance(this.booleanTestabilityTransformation.classLoader).getInstruction(this.booleanTestabilityTransformation.className.replace("/", "."), mn.name + mn.desc, fieldNode);
// varNode);
if (insn == null) {
// TODO: Find out why
BooleanTestabilityTransformation.logger.info("ERROR: Could not find node");
return fieldNode;
}
if (insn.getASMNode().getOpcode() != fieldNode.getOpcode()) {
BooleanTestabilityTransformation.logger.info("Found wrong bytecode instruction at this index!");
BytecodeInstructionPool.getInstance(this.booleanTestabilityTransformation.classLoader).getInstruction(this.booleanTestabilityTransformation.className, mn.name + mn.desc, fieldNode);
}
if (insn.getBasicBlock() == null) {
BooleanTestabilityTransformation.logger.info("ERROR: Problematic node found");
return fieldNode;
}
Set<ControlDependency> dependencies = insn.getControlDependencies();
BooleanTestabilityTransformation.logger.info("Found flag assignment: " + insn + ", checking " + dependencies.size() + " control dependencies");
for (ControlDependency dep : dependencies) {
if (!addedNodes.contains(dep))
handleDependency(dep, cdg, mn, fieldNode, insn);
}
}
return fieldNode;
}
use of org.objectweb.asm.tree.FrameNode in project openj9 by eclipse.
the class ClassFileCompare method compareInstructions.
private void compareInstructions(ClassNode clazz1, MethodNode method1, ClassNode clazz2, MethodNode method2) {
if (nullCheck(method1.instructions, method2.instructions, "Instructions (" + method1.name + ")")) {
return;
}
if (method1.instructions.size() != method2.instructions.size()) {
reportDifference("Method " + method1.name + ": instructions differ: " + method1.instructions.size() + ", " + method2.instructions.size());
} else {
@SuppressWarnings("unchecked") Iterator<AbstractInsnNode> iter1 = method1.instructions.iterator();
@SuppressWarnings("unchecked") Iterator<AbstractInsnNode> iter2 = method2.instructions.iterator();
int index = 0;
while (iter1.hasNext()) {
AbstractInsnNode instruction1 = iter1.next();
AbstractInsnNode instruction2 = iter2.next();
if (instruction1.getOpcode() != instruction2.getOpcode()) {
/* Check for J9 opcode mapping */
compareJ9OpcodeMapping(clazz2, method2, instruction1, instruction2, index);
} else {
switch(instruction1.getType()) {
case INSN:
/* Do nothing */
break;
case INT_INSN:
compare(((IntInsnNode) instruction1).operand, ((IntInsnNode) instruction2).operand, "Operands of " + Printer.OPCODES[instruction1.getOpcode()] + " (" + method1.name + ":" + index + ")", false);
break;
case VAR_INSN:
compare(((VarInsnNode) instruction1).var, ((VarInsnNode) instruction2).var, "Operands of " + Printer.OPCODES[instruction1.getOpcode()] + " (" + method1.name + ":" + index + ")", false);
break;
case TYPE_INSN:
compare(((TypeInsnNode) instruction1).desc, ((TypeInsnNode) instruction2).desc, "Operands of " + Printer.OPCODES[instruction1.getOpcode()] + " (" + method1.name + ":" + index + ")");
break;
case FIELD_INSN:
{
FieldInsnNode fieldInsn1 = (FieldInsnNode) instruction1;
FieldInsnNode fieldInsn2 = (FieldInsnNode) instruction2;
compare(fieldInsn1.owner, fieldInsn2.owner, "Owning class name of " + Printer.OPCODES[instruction1.getOpcode()] + " (" + method1.name + ":" + index + ")");
compare(fieldInsn1.name, fieldInsn2.name, "Field name of " + Printer.OPCODES[instruction1.getOpcode()] + " (" + method1.name + ":" + index + ")");
compare(fieldInsn1.desc, fieldInsn2.desc, "Descriptor of " + Printer.OPCODES[instruction1.getOpcode()] + " (" + method1.name + ":" + index + ")");
break;
}
case METHOD_INSN:
{
MethodInsnNode methodInsn1 = (MethodInsnNode) instruction1;
MethodInsnNode methodInsn2 = (MethodInsnNode) instruction2;
compare(methodInsn1.owner, methodInsn2.owner, "Owning class name of " + Printer.OPCODES[instruction1.getOpcode()] + " (" + method1.name + ":" + index + ")");
compare(methodInsn1.name, methodInsn2.name, "Method name of " + Printer.OPCODES[instruction1.getOpcode()] + " (" + method1.name + ":" + index + ")");
compare(methodInsn1.desc, methodInsn2.desc, "Descriptor of " + Printer.OPCODES[instruction1.getOpcode()] + " (" + method1.name + ":" + index + ")");
break;
}
case INVOKE_DYNAMIC_INSN:
compareInvokeDynamic((InvokeDynamicInsnNode) instruction1, (InvokeDynamicInsnNode) instruction2, method1, index);
break;
case JUMP_INSN:
compare(method1, ((JumpInsnNode) instruction1).label, method2, ((JumpInsnNode) instruction2).label, "Operands of " + Printer.OPCODES[instruction1.getOpcode()] + " (" + method1.name + ":" + index + ")");
break;
case LABEL:
/* Do nothing */
break;
case LDC_INSN:
if (!((LdcInsnNode) instruction1).cst.equals(((LdcInsnNode) instruction2).cst)) {
reportDifference("Operands of " + Printer.OPCODES[instruction1.getOpcode()] + " (" + method1.name + ":" + index + ") differ: " + ((LdcInsnNode) instruction1).cst + ", " + ((LdcInsnNode) instruction2).cst);
}
break;
case IINC_INSN:
{
IincInsnNode iincInsn1 = (IincInsnNode) instruction1;
IincInsnNode iincInsn2 = (IincInsnNode) instruction2;
compare(iincInsn1.var, iincInsn2.var, "Variable operands of " + Printer.OPCODES[instruction1.getOpcode()] + " (" + method1.name + ":" + index + ")", false);
compare(iincInsn1.incr, iincInsn2.incr, "Increment operands of " + Printer.OPCODES[instruction1.getOpcode()] + " (" + method1.name + ":" + index + ")", false);
break;
}
case TABLESWITCH_INSN:
{
TableSwitchInsnNode tableSwitchInsn1 = (TableSwitchInsnNode) instruction1;
TableSwitchInsnNode tableSwitchInsn2 = (TableSwitchInsnNode) instruction2;
compare(tableSwitchInsn1.min, tableSwitchInsn2.min, Printer.OPCODES[instruction1.getOpcode()] + " (" + method1.name + ":" + index + ") minimum key value", false);
compare(tableSwitchInsn1.max, tableSwitchInsn2.max, Printer.OPCODES[instruction1.getOpcode()] + " (" + method1.name + ":" + index + ") maximum key value", false);
compare(method1, tableSwitchInsn1.dflt, method2, tableSwitchInsn2.dflt, Printer.OPCODES[instruction1.getOpcode()] + " (" + method1.name + ":" + index + ") default_handler_block");
compareLabels(method1, tableSwitchInsn1.labels, method2, tableSwitchInsn2.labels, Printer.OPCODES[instruction1.getOpcode()] + " (" + method1.name + ":" + index + ") handler_blocks");
break;
}
case LOOKUPSWITCH_INSN:
{
LookupSwitchInsnNode lookupSwitchInsn1 = (LookupSwitchInsnNode) instruction1;
LookupSwitchInsnNode lookupSwitchInsn2 = (LookupSwitchInsnNode) instruction2;
compare(method1, lookupSwitchInsn1.dflt, method2, lookupSwitchInsn2.dflt, Printer.OPCODES[instruction1.getOpcode()] + " (" + method1.name + ":" + index + ") default_handler_block");
compare(lookupSwitchInsn1.keys, lookupSwitchInsn2.keys, Printer.OPCODES[instruction1.getOpcode()] + " (" + method1.name + ":" + index + ") key values");
compareLabels(method1, lookupSwitchInsn1.labels, method2, lookupSwitchInsn2.labels, Printer.OPCODES[instruction1.getOpcode()] + " (" + method1.name + ":" + index + ") handler_blocks");
break;
}
case MULTIANEWARRAY_INSN:
{
MultiANewArrayInsnNode arrayInsn1 = (MultiANewArrayInsnNode) instruction1;
MultiANewArrayInsnNode arrayInsn2 = (MultiANewArrayInsnNode) instruction2;
compare(arrayInsn1.desc, arrayInsn2.desc, "Desc operand of " + Printer.OPCODES[instruction1.getOpcode()] + " (" + method1.name + ":" + index + ")");
compare(arrayInsn1.dims, arrayInsn2.dims, "Dimension operand of " + Printer.OPCODES[instruction1.getOpcode()] + " (" + method1.name + ":" + index + ")", false);
break;
}
case FRAME:
{
FrameNode frameInsn1 = (FrameNode) instruction1;
FrameNode frameInsn2 = (FrameNode) instruction2;
compare(frameInsn1.type, frameInsn2.type, "Stack map frame (" + method1.name + ":" + index + ") frame type", false);
compareFrames(frameInsn1.local, frameInsn2.local, "Stack map frame (" + method1.name + ":" + index + ") types of the local variables");
compareFrames(frameInsn1.stack, frameInsn2.stack, "Stack map frame (" + method1.name + ":" + index + ") types of the operand stack elements");
}
break;
case LINE:
{
assert shouldCompareDebugInfo;
LineNumberNode lineInsn1 = (LineNumberNode) instruction1;
LineNumberNode lineInsn2 = (LineNumberNode) instruction2;
compare(lineInsn1.line, lineInsn2.line, "Line number (" + method1.name + ":" + index + ") line No.", false);
compare(method1, lineInsn1.start, method2, lineInsn2.start, "Line number (" + method1.name + ":" + index + ") offset of the 1st instruction");
break;
}
default:
assert false;
}
}
index++;
}
}
}
Aggregations