下面列出了org.objectweb.asm.tree.AbstractInsnNode#getPrevious ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
public static InsnList cutClinit(MethodNode mn) {
InsnList insns = MethodUtils.copy(mn.instructions, null, null);
ArrayList<LabelNode> handlers = new ArrayList<>();
for (TryCatchBlockNode tcbn : mn.tryCatchBlocks) {
handlers.add((LabelNode) insns.get(mn.instructions.indexOf(tcbn.handler)));
}
for(LabelNode ln : handlers) {
findSubroutinesAndDelete(insns, ln);
}
AbstractInsnNode endLabel = findEndLabel(insns);
while (endLabel.getOpcode() == -1) {
endLabel = endLabel.getNext();
}
AbstractInsnNode end = endLabel.getPrevious();
if (endLabel.getOpcode() != RETURN) {
findSubroutinesAndDelete(insns, endLabel);
insns.insert(end, new InsnNode(RETURN));
}
return insns;
}
/**
* Returns the previous instruction prior to the given node, ignoring label
* and line number nodes.
*
* @param node the node to look up the previous instruction for
* @return the previous instruction, or null if no previous node was found
*/
@Nullable
public static AbstractInsnNode getPrevInstruction(@NonNull AbstractInsnNode node) {
AbstractInsnNode prev = node;
while (true) {
prev = prev.getPrevious();
if (prev == null) {
return null;
} else {
int type = prev.getType();
if (type != AbstractInsnNode.LINE && type != AbstractInsnNode.LABEL
&& type != AbstractInsnNode.FRAME) {
return prev;
}
}
}
}
private void removeLastAllocation() {
AbstractInsnNode insn = instructions.getLast();
while (insn != null && insn.getPrevious() != null) {
AbstractInsnNode prev = insn.getPrevious();
if (prev.getOpcode() == Opcodes.NEW
&& insn.getOpcode() == Opcodes.DUP
&& ((TypeInsnNode) prev).desc.equals(lambdaInfo.methodReference().getOwner())) {
instructions.remove(prev);
instructions.remove(insn);
return;
}
insn = prev;
}
throw new IllegalStateException(
"Couldn't find allocation to rewrite ::new reference " + lambdaInfo.methodReference());
}
private boolean isVarBetweenBounds(AbstractInsnNode var, LabelNode lo, LabelNode hi) {
AbstractInsnNode x;
boolean loFound = false;
for (x = var; !(x == null || loFound); x = x.getPrevious()) {
loFound = x == lo;
}
if (!loFound)
return false;
boolean hiFound = false;
for (x = var; !(x == null || hiFound); x = x.getNext()) {
hiFound = x == hi;
}
return hiFound;
}
public static int getLabelIndex(AbstractInsnNode ain) {
int index = 0;
AbstractInsnNode node = ain;
while (node.getPrevious() != null) {
node = node.getPrevious();
if (node instanceof LabelNode) {
index += 1;
}
}
return index;
}
private static int labelIndex(LabelNode label) {
int i = 0;
AbstractInsnNode ain = label.getPrevious();
while (ain != null) {
if (ain.getType() == AbstractInsnNode.LABEL) {
i++;
}
ain = ain.getPrevious();
}
return i;
}
@Override
public void process(@Nonnull final ParserClassNode classNode,
@Nonnull final RuleMethod method)
throws Exception
{
Objects.requireNonNull(classNode, "classNode");
Objects.requireNonNull(method, "method");
// super methods have flag moved to the overriding method
Preconditions.checkState(!method.isSuperMethod());
final InsnList instructions = method.instructions;
AbstractInsnNode retInsn = instructions.getLast();
while (retInsn.getOpcode() != ARETURN)
retInsn = retInsn.getPrevious();
final LabelNode label = new LabelNode();
final CodeBlock block = CodeBlock.newCodeBlock()
.dup()
.ifnull(label)
.ldc(getLabelText(method))
.invokeinterface(CodegenUtils.p(Rule.class), "label",
CodegenUtils.sig(Rule.class, String.class))
.label(label);
instructions.insertBefore(retInsn, block.getInstructionList());
}
public static AbstractInsnNode findLast(InsnList il, int op) {
AbstractInsnNode ain = il.getLast();
while (ain != null) {
if (ain.getOpcode() == op) {
return ain;
}
ain = ain.getPrevious();
}
return null;
}
private static boolean blockContainsSetter(AbstractInsnNode ain) {
if (ain.getOpcode() == PUTSTATIC && ((FieldInsnNode) ain).desc.endsWith("Ljava/lang/String;")) {
return true;
}
AbstractInsnNode ain2 = ain;
while (ain2 != null && !(ain2 instanceof LabelNode)) {
if (ain2.getOpcode() == PUTSTATIC && ain2.getPrevious().getOpcode() == ANEWARRAY) {
FieldInsnNode fin = (FieldInsnNode) ain2;
if (fin.desc.endsWith("[Ljava/lang/String;"))
return true;
}
ain2 = ain2.getPrevious();
}
return false;
}
@Override
public void process(@Nonnull final ParserClassNode classNode,
@Nonnull final RuleMethod method)
throws Exception
{
Objects.requireNonNull(classNode, "classNode");
Objects.requireNonNull(method, "method");
final InsnList instructions = method.instructions;
AbstractInsnNode ret = instructions.getLast();
while (ret.getOpcode() != ARETURN)
ret = ret.getPrevious();
final CodeBlock block = CodeBlock.newCodeBlock();
block.newobj(CodegenUtils.p(VarFramingMatcher.class))
.dup_x1()
.swap();
createVarFieldArray(block, method);
block.invokespecial(CodegenUtils.p(VarFramingMatcher.class), "<init>",
CodegenUtils.sig(void.class, Rule.class, Var[].class));
instructions.insertBefore(ret, block.getInstructionList());
method.setBodyRewritten();
}
/**
* <p>
* This method processes loops and add logging
* </p>
*
* @param firstStmtInLoopIndex
* Index of the first statement in the loop.
* @param loopEndIndex
* Index where loop ends.
* @param nestingLevel
* nesting level
*/
private void processLoop(int firstStmtInLoopIndex, int loopEndIndex,
int nestingLevel) {
logger.debug(firstStmtInLoopIndex + " " + loopEndIndex);
this.currentLoopCount[nestingLevel]++;
AbstractInsnNode abstractInsnNode;
// adding loop entry
abstractInsnNode = this.insnArr[firstStmtInLoopIndex];
AbstractInsnNode gotoNode = abstractInsnNode.getPrevious();
AbstractInsnNode lineNode = abstractInsnNode.getNext();
if ((gotoNode instanceof JumpInsnNode && Opcodes.GOTO == gotoNode
.getOpcode()) || (!(lineNode instanceof LineNumberNode))) {
lineNode = getPreviousLineNode(abstractInsnNode);
}
Integer lineNumber = ((LineNumberNode) lineNode).line;
String cSymbol = env.getClassSymbol(getClassName());
String mSymbol = env.getMethodSymbol(getClassName(), cSymbol, name);
InsnList il1 = InstrumentUtil.addLogMessage(cSymbol,mSymbol,
InstrumentationMessageLoader
.getMessage(MessageConstants.ENTERED_LOOP), lineNumber
.toString(), this.currentLoopCount[nestingLevel]
.toString());
instructions.insertBefore(lineNode.getPrevious(), il1);
// handling map reduce output in the loop
handleCtxWrite(firstStmtInLoopIndex, loopEndIndex);
// adding loop exit
abstractInsnNode = this.insnArr[loopEndIndex];
InsnList il2 = InstrumentUtil.addloopCounterLogging(cSymbol,
mSymbol, InstrumentationMessageLoader
.getMessage(MessageConstants.EXITING_LOOP),
this.localVariableSize, this.currentLoopCount[nestingLevel]
.toString());
// resetting the counter to ZERO
il2.add(new LabelNode());
il2.add(new InsnNode(Opcodes.ICONST_0));
il2.add(new VarInsnNode(Opcodes.ISTORE, this.localVariableSize));
instructions.insert(abstractInsnNode.getNext(), il2);
this.addLocalVariable(this.localVariableSize);
}
@Override
public void visitEnd() {
for (Object o : methods) {
MethodNode mn = (MethodNode) o;
InsnList insnList = mn.instructions;
AbstractInsnNode[] insnArr = insnList.toArray();
/**
* Finding the method instruction nodes whose owner is mapreduce.Job
* and it submits the job
*/
for (AbstractInsnNode abstractInsnNode : insnArr) {
if (abstractInsnNode instanceof MethodInsnNode) {
MethodInsnNode min = (MethodInsnNode) abstractInsnNode;
// finding job submission
if (InstrumentUtil.isJobSubmissionMethod(min)) {
LOGGER.debug(MessageFormat.format(
InstrumentationMessageLoader
.getMessage(MessageConstants.JOB_SUBMISSION_FOUND),
getClassName() + "##" + mn.name));
// validating that the owner of the method call is
if (InstrumentUtil.isOwnerJob(min)) {
LOGGER.debug(MessageFormat.format(
InstrumentationMessageLoader
.getMessage(MessageConstants.LOG_OWNER_IS_JOB),
getClassName() + "##" + mn.name));
AbstractInsnNode ain = min.getPrevious();
while (!(ain instanceof VarInsnNode)) {
ain = ain.getPrevious();
}
/* VarInsnNode vin = (VarInsnNode) ain;
int jobVariableIndex = vin.var;
InsnList il = null;
// old api check
if (getOwnerType(min).getInternalName().equals(
CLASSNAME_JOB_CONF)) {
il = addProfilingForOldAPI(jobVariableIndex);
} else {
il = addProfiling(jobVariableIndex);
}
insnList.insertBefore(vin, il);
*/ }
}
}
}
mn.visitMaxs(0, 0);
}
accept(cv);
}
@Override
public void visitEnd() {
for (Object o : methods) {
MethodNode mn = (MethodNode) o;
InsnList insnList = mn.instructions;
AbstractInsnNode[] insnArr = insnList.toArray();
/**
* Finding the method instruction nodes whose owner is mapreduce.Job
* and it submits the job
*/
for (AbstractInsnNode abstractInsnNode : insnArr) {
if (abstractInsnNode instanceof MethodInsnNode) {
MethodInsnNode min = (MethodInsnNode) abstractInsnNode;
// finding job submission
if (min.name.equals(EnumJobSubmitMethods.JOB_SUBMIT
.toString())) {
LOGGER.debug(MessageFormat.format(
InstrumentationMessageLoader
.getMessage(MessageConstants.JOB_SUBMISSION_FOUND),
getClassName() + "##" + mn.name));
// validating that the owner of the method call is
if (min.owner.equals(EnumJobSubmitMethods.JOB_SUBMIT
.getOwner().getInternalName())) {
LOGGER.debug(MessageFormat.format(
InstrumentationMessageLoader
.getMessage(MessageConstants.LOG_OWNER_IS_JOB),
getClassName() + "##" + mn.name));
AbstractInsnNode ain = min.getPrevious();
while (!(ain instanceof VarInsnNode)) {
ain = ain.getPrevious();
}
VarInsnNode vin = (VarInsnNode) ain;
int jobVariableIndex = vin.var;
InsnList il = null;
il = handleJobSubmitcase(mn, jobVariableIndex);
insnList.insert(min, il);
}
}
}
}
mn.visitMaxs(0, 0);
}
accept(cv);
}
@Override
public void transform(ClassNode cnode) {
Game.logger().info("Transforming Chunk class for chunkModified event.");
ObfMapping obfMap = new ObfMapping("apx", "a", "(IIILaji;I)Z");
ObfMapping deobfMap = new ObfMapping("net/minecraft/world/chunk/Chunk", "func_150807_a", "(IIILnet/minecraft/block/Block;I)Z");
MethodNode method = ASMHelper.findMethod(obfMap, cnode);
if (method == null) {
Game.logger().warn("Lookup {} failed. You are probably in a deobf environment.", obfMap);
method = ASMHelper.findMethod(deobfMap, cnode);
if (method == null) {
throw new IllegalStateException("[NOVA] Lookup " + deobfMap + " failed!");
}
}
Game.logger().info("Found method {}", method.name);
InsnList list = new InsnList();
list.add(new VarInsnNode(ALOAD, 0));
list.add(new VarInsnNode(ILOAD, 1));
list.add(new VarInsnNode(ILOAD, 2));
list.add(new VarInsnNode(ILOAD, 3));
list.add(new VarInsnNode(ALOAD, 8));
list.add(new VarInsnNode(ILOAD, 9));
list.add(new VarInsnNode(ALOAD, 4));
list.add(new VarInsnNode(ILOAD, 5));
list.add(new MethodInsnNode(INVOKESTATIC, "nova/core/wrapper/mc/forge/v17/asm/StaticForwarder", "chunkSetBlockEvent", "(Lnet/minecraft/world/chunk/Chunk;IIILnet/minecraft/block/Block;ILnet/minecraft/block/Block;I)V", false));
AbstractInsnNode lastInsn = method.instructions.getLast();
while (lastInsn instanceof LabelNode || lastInsn instanceof LineNumberNode) {
lastInsn = lastInsn.getPrevious();
}
if (ASMHelper.isReturn(lastInsn)) {
method.instructions.insertBefore(lastInsn, list);
} else {
method.instructions.insert(list);
}
Game.logger().info("Injected instruction to method: {}", method.name);
}
public static <T> T findPattern(
final AbstractInsnNode start,
final int patternSize,
Predicate<AbstractInsnNode>
isValidNode, // if this returns false then dont invoke the predicate and dont update found
BiPredicate<Integer, AbstractInsnNode> nodePredicate,
BiFunction<AbstractInsnNode, AbstractInsnNode, T> outputFunction) {
if (start != null) {
int found = 0;
AbstractInsnNode next = start;
do {
// Check if node matches the predicate.
// If the node is not considered a "valid" node then we'll consider it to match the pattern
// but the predicate will not be invoked for it and found will not be incremented
final boolean validNode = isValidNode.test(next);
if (!validNode || nodePredicate.test(found, next)) {
if (validNode) {
// Increment number of matched opcodes
found++;
}
} else {
// Go back to the starting node
for (int i = 1; i <= (found - 1); i++) {
next = next.getPrevious();
}
// Reset the number of insns matched
found = 0;
}
// Check if found entire pattern
if (found >= patternSize) {
final AbstractInsnNode end = next;
// Go back to top node
for (int i = 1; i <= (found - 1); i++) {
next = next.getPrevious();
}
return outputFunction.apply(next, end);
}
next = next.getNext();
} while (next != null);
}
// failed to find pattern
return null;
}
@Override
public void transform(ClassNode cnode) {
Game.logger().info("Transforming Chunk class for chunkModified event.");
//obf name: func_177436_a
ObfMapping obfMap = new ObfMapping("auo", "a", "(Lco;Latl;)Latl;");
ObfMapping deobfMap = new ObfMapping("net/minecraft/world/chunk/Chunk", "setBlockState", "(Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/state/IBlockState;)Lnet/minecraft/block/state/IBlockState;");
MethodNode method = ASMHelper.findMethod(obfMap, cnode);
if (method == null) {
Game.logger().warn("Lookup {} failed. You are probably in a deobf environment.", obfMap);
method = ASMHelper.findMethod(deobfMap, cnode);
if (method == null) {
throw new IllegalStateException("[NOVA] Lookup " + deobfMap + " failed!");
}
}
Game.logger().info("Found method {}", method.name);
InsnList list = new InsnList();
list.add(new VarInsnNode(ALOAD, 0)); //this
list.add(new VarInsnNode(ALOAD, 1)); //BlockPos
list.add(new VarInsnNode(ALOAD, 8)); //oldBlock IBlockState
list.add(new VarInsnNode(ALOAD, 2)); //newBlock IBlockState
list.add(new MethodInsnNode(INVOKESTATIC, "nova/core/wrapper/mc/forge/v1_11_2/asm/StaticForwarder", "chunkSetBlockEvent", "(Lnet/minecraft/world/chunk/Chunk;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/state/IBlockState;Lnet/minecraft/block/state/IBlockState;)V", false));
AbstractInsnNode lastInsn = method.instructions.getLast();
while (lastInsn instanceof LabelNode || lastInsn instanceof LineNumberNode) {
lastInsn = lastInsn.getPrevious();
}
if (ASMHelper.isReturn(lastInsn)) {
method.instructions.insertBefore(lastInsn, list);
} else {
method.instructions.insert(list);
}
Game.logger().info("Injected instruction to method: {}", method.name);
}
/**
* visit end method for intrumentation
*/
@Override
public void visitEnd() {
for (Object o : methods) {
MethodNode mn = (MethodNode) o;
// filtering the methods
if (!(validateMapReduceClinitMethod(mn.name,MAP_METHOD , REDUCE_METHOD,CLINIT_METHOD)
|| checkMethodNameAndArgumentLength(mn)
|| (mn.access & Opcodes.ACC_SYNTHETIC) == Opcodes.ACC_SYNTHETIC)) {
InsnList insnList = mn.instructions;
AbstractInsnNode[] insnArr = insnList.toArray();
// adding entry logging
logger.debug(MessageFormat.format(InstrumentationMessageLoader
.getMessage(MessageConstants.LOG_METHOD_ENTRY),
getClassName() + "##" + mn.name + "##" + mn.desc));
String logMsg = InstrumentationMessageLoader
.getMessage(MessageConstants.ENTERED_METHOD);
String cSymbol = env.getClassSymbol(getClassName());
String mSymbol = env.getMethodSymbol(getClassName(),cSymbol, mn.name);
InsnList il = InstrumentUtil.addLogMessage(cSymbol,
mSymbol, logMsg);
insnList.insertBefore(insnList.getFirst(), il);
for (AbstractInsnNode abstractInsnNode : insnArr) {
if (Opcodes.RETURN >= abstractInsnNode.getOpcode()
&& Opcodes.IRETURN <= abstractInsnNode.getOpcode()) {
// adding exit logging
logger.debug(MessageFormat.format(
InstrumentationMessageLoader
.getMessage(MessageConstants.LOG_METHOD_EXIT),
getClassName() + "##" + mn.name));
logMsg = InstrumentationMessageLoader
.getMessage(MessageConstants.EXITING_METHOD);
cSymbol = env.getClassSymbol(getClassName());
mSymbol = env.getMethodSymbol(getClassName(),cSymbol,mn.name);
il = InstrumentUtil.addLogMessage(cSymbol,
mSymbol, logMsg);
// inserting the list at the associated label node
AbstractInsnNode prevNode = abstractInsnNode
.getPrevious();
while (!(prevNode instanceof LabelNode)) {
prevNode = prevNode.getPrevious();
}
insnList.insert(prevNode, il);
}
}
}
mn.visitMaxs(0, 0);
}
accept(cv);
}
/**
* Visit end.
*
* @see org.jumbune.debugger.instrumentation.adapter.BaseAdapter#visitEnd()
*/
@Override
public void visitEnd() {
for (Object o : methods) {
MethodNode mn = (MethodNode) o;
InsnList insnList = mn.instructions;
AbstractInsnNode[] insnArr = insnList.toArray();
LOGGER.debug(MessageFormat.format(InstrumentationMessageLoader
.getMessage(MessageConstants.LOG_INSTRUMENTING_METHOD),
getClassName() + "##" + mn.name));
// traversing in reverse order as job submission comes at the end of
// the method
for (AbstractInsnNode abstractInsnNode : insnArr) {
if (abstractInsnNode instanceof MethodInsnNode) {
MethodInsnNode min = (MethodInsnNode) abstractInsnNode;
// finding job submission
if (InstrumentUtil.isJobSubmissionMethod(min)) {
LOGGER.debug(MessageFormat.format(
InstrumentationMessageLoader
.getMessage(MessageConstants.JOB_SUBMISSION_FOUND),
getClassName()));
// validating if the owner is mapreduce.Job or JobClient
if (InstrumentUtil.isOwnerJob(min)) {
LOGGER.debug(MessageFormat.format(
InstrumentationMessageLoader
.getMessage(MessageConstants.LOG_OWNER_IS_JOB),
getClassName()));
// finding index of job variable
AbstractInsnNode ain = min.getPrevious();
while (!(ain instanceof VarInsnNode)) {
ain = ain.getPrevious();
}
VarInsnNode vin = (VarInsnNode) ain;
int jobVariableIndex = vin.var;
InsnList il = new InsnList();
// classpath is to be passed as libjars
il.add(addClasspath(jobVariableIndex,
getOwnerType(min)));
// // output path modification
il.add(modifyOutputPath(jobVariableIndex,
getOwnerType(min)));
insnList.insertBefore(vin, il);
// Disabling the profiling for the pure jar - old
// api
if (getOwnerType(min).getInternalName().equals(
CLASSNAME_JOB_CONF)) {
il.add(new LabelNode());
il.add(new VarInsnNode(Opcodes.ALOAD,
jobVariableIndex));
il.add(new LdcInsnNode(false));
il.add(new MethodInsnNode(
Opcodes.INVOKEVIRTUAL,
CLASSNAME_JOB_CONF,
"setProfileEnabled", Type
.getMethodDescriptor(
Type.VOID_TYPE,
Type.BOOLEAN_TYPE)));
} else {
il.add(new LabelNode());
il.add(new VarInsnNode(Opcodes.ALOAD,
jobVariableIndex));
il.add(new MethodInsnNode(
Opcodes.INVOKEVIRTUAL,
CLASSNAME_MR_JOB, "getConfiguration",
Type.getMethodDescriptor(Type
.getType(Configuration.class))));
il.add(new LdcInsnNode(PROFILE_TASK));
il.add(new LdcInsnNode(Boolean.toString(false)));
il.add(new MethodInsnNode(
Opcodes.INVOKEVIRTUAL,
CLASSNAME_HADOOP_CONFIGURATION, "set",
Type.getMethodDescriptor(
Type.VOID_TYPE, TYPE_STRING,
TYPE_STRING)));
}
insnList.insertBefore(vin, il);
}
}
}
}
mn.visitMaxs(0, 0);
}
accept(cv);
}
/**
* <p>
* Gets the previous line number for the given node
* </p>
*
* @param ain
* node
* @return int line number
*/
public int getPreviousLineNumber(AbstractInsnNode ain) {
AbstractInsnNode lineNode = ain.getPrevious();
while (!(lineNode instanceof LineNumberNode)) {
lineNode = lineNode.getPrevious();
}
return ((LineNumberNode) lineNode).line;
}
/**
* Get the first insn connected to the given one.
*
* @param insn
* instruction
*
* @return First insn in the insn-list.
*/
public static AbstractInsnNode getFirst(AbstractInsnNode insn) {
while(insn.getPrevious() != null)
insn = insn.getPrevious();
return insn;
}