下面列出了怎么用org.objectweb.asm.tree.LabelNode的API类实例代码及写法,或者点击链接到github查看源代码。
private static InsnListSection insnListMatchesL(InsnList haystack, InsnList needle, int start, HashSet<LabelNode> controlFlowLabels) {
int h = start, n = 0;
for (; h < haystack.size() && n < needle.size(); h++) {
AbstractInsnNode insn = haystack.get(h);
if (insn.getType() == 15) {
continue;
}
if (insn.getType() == 8 && !controlFlowLabels.contains(insn)) {
continue;
}
if (!insnEqual(haystack.get(h), needle.get(n))) {
return null;
}
n++;
}
if (n != needle.size()) {
return null;
}
return new InsnListSection(haystack, start, h - 1);
}
@Override
public void write(DoStmtToken token) {
expr.writeDefineVariables(token.getLocal());
LabelNode start = expr.writeLabel(node, token.getMeta().getStartLine());
LabelNode end = new LabelNode();
method.pushJump(end, start);
expr.write(token.getBody());
method.popJump();
expr.writeConditional(token.getCondition(), end);
add(new JumpInsnNode(GOTO, start));
add(end);
add(new LineNumberNode(token.getMeta().getEndLine(), end));
expr.writeUndefineVariables(token.getLocal());
}
public void initLocalVariables(final InsnList instructions) {
// find enter & exit instruction.
final LabelNode variableStartLabelNode = new LabelNode();
final LabelNode variableEndLabelNode = new LabelNode();
if(instructions.getFirst() != null) {
instructions.insertBefore(instructions.getFirst(), variableStartLabelNode);
} else {
instructions.insert(variableStartLabelNode);
}
instructions.insert(instructions.getLast(), variableEndLabelNode);
if (!isStatic()) {
addLocalVariable("this", Type.getObjectType(this.declaringClassInternalName).getDescriptor(), variableStartLabelNode, variableEndLabelNode);
}
for (Type type : this.argumentTypes) {
addLocalVariable(JavaAssistUtils.javaClassNameToVariableName(type.getClassName()), type.getDescriptor(), variableStartLabelNode, variableEndLabelNode);
}
}
@Override
public void transform(ClassNode cnode) {
Game.logger().info("Transforming IForgeRegistryEntry class for correct NOVA mod id mapping.");
ObfMapping mapping = new ObfMapping("net/minecraftforge/fml/common/registry/IForgeRegistryEntry$Impl", "setRegistryName", "(Ljava/lang/String;)Lnet/minecraftforge/fml/common/registry/IForgeRegistryEntry;");
MethodNode method = ASMHelper.findMethod(mapping, cnode);
if (method == null) {
throw new IllegalStateException("[NOVA] Lookup " + mapping + " failed!");
}
Game.logger().info("Transforming method {}", method.name);
InsnList list = new InsnList();
list.add(new VarInsnNode(ALOAD, 5));
list.add(new MethodInsnNode(INVOKESTATIC, "nova/core/wrapper/mc/forge/v1_11_2/asm/StaticForwarder", "isNovaPrefix", "(Ljava/lang/String;)Z", false));
list.add(new JumpInsnNode(IFNE, (LabelNode) method.instructions.get(120)));
method.instructions.insert(method.instructions.get(101), list);
Game.logger().info("Injected instruction to method: {}", method.name);
}
@Inject(description = "Add hook to disable boat gravity")
public void inject(MethodNode main) {
AbstractInsnNode gravityNode =
ASMHelper.findPattern(
main.instructions.getFirst(),
new int[]{ALOAD, DUP, GETFIELD, DLOAD, DADD, PUTFIELD},
"xxxxxx");
Objects.requireNonNull(gravityNode, "Find pattern failed for gravityNode");
AbstractInsnNode putFieldNode = gravityNode;
for (int i = 0; i < 5; i++) {
putFieldNode = putFieldNode.getNext();
}
LabelNode newLabelNode = new LabelNode();
InsnList insnList = new InsnList();
insnList.add(
ASMHelper.call(GETSTATIC, TypesHook.Fields.ForgeHaxHooks_isNoBoatGravityActivated));
insnList.add(new JumpInsnNode(IFNE, newLabelNode)); // if nogravity is enabled
main.instructions.insertBefore(gravityNode, insnList); // insert if
main.instructions.insert(putFieldNode, newLabelNode); // end if
}
private static SequenceQuery<AbstractInsnNode> conditionalAtStart() {
final Slot<LabelNode> loopStart = Slot.create(LabelNode.class);
final Slot<LabelNode> loopEnd = Slot.create(LabelNode.class);
return QueryStart
.any(AbstractInsnNode.class)
.zeroOrMore(QueryStart.match(anyInstruction()))
.then(aMethodCallReturningAnIterator().and(mutationPoint()))
.then(opCode(Opcodes.ASTORE))
.then(aLabelNode(loopStart.write()))
.then(opCode(Opcodes.ALOAD))
.then(methodCallTo(ClassName.fromString("java/util/Iterator"), "hasNext").and(mutationPoint()))
.then(aConditionalJump().and(jumpsTo(loopEnd.write())).and(mutationPoint()))
.then(opCode(Opcodes.ALOAD))
.then(methodCallTo(ClassName.fromString("java/util/Iterator"), "next").and(mutationPoint()))
.zeroOrMore(QueryStart.match(anyInstruction()))
.then(opCode(Opcodes.GOTO).and(jumpsTo(loopStart.read())))
.then(labelNode(loopEnd.read()))
.zeroOrMore(QueryStart.match(anyInstruction()));
}
private static InsnListSection insnListMatchesL(InsnList haystack, InsnList needle, int start, HashSet<LabelNode> controlFlowLabels) {
int h = start, n = 0;
for (; h < haystack.size() && n < needle.size(); h++) {
AbstractInsnNode insn = haystack.get(h);
if (insn.getType() == 15) {
continue;
}
if (insn.getType() == 8 && !controlFlowLabels.contains(insn)) {
continue;
}
if (!insnEqual(haystack.get(h), needle.get(n))) {
return null;
}
n++;
}
if (n != needle.size()) {
return null;
}
return new InsnListSection(haystack, start, h - 1);
}
@Override
public LookupSwitchInsnNode deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
JsonObject jsonObject = (JsonObject) json;
LabelNode dflt = context.deserialize(jsonObject.get("dflt"), LabelNode.class);
List<Integer> keysList = context.deserialize(jsonObject.get("keys"), List.class);
List<LabelNode> labelsList = context.deserialize(jsonObject.get("labels"), List.class);
int[] keys = new int[keysList.size()];
for(int i=0; i < keys.length; i++){
keys[i] = keysList.get(i);
}
LabelNode[] labels = new LabelNode[labelsList.size()];
for(int i=0; i < labels.length; i++){
labels[i] = labelsList.get(i);
}
return new LookupSwitchInsnNode(dflt, keys, labels);
}
public static InsnList getImportantList(InsnList list) {
if (list.size() == 0) {
return list;
}
HashMap<LabelNode, LabelNode> labels = new HashMap<LabelNode, LabelNode>();
for (AbstractInsnNode insn = list.getFirst(); insn != null; insn = insn.getNext()) {
if (insn instanceof LabelNode) {
labels.put((LabelNode) insn, (LabelNode) insn);
}
}
InsnList importantNodeList = new InsnList();
for (AbstractInsnNode insn = list.getFirst(); insn != null; insn = insn.getNext()) {
if (insn instanceof LabelNode || insn instanceof LineNumberNode) {
continue;
}
importantNodeList.add(insn.clone(labels));
}
return importantNodeList;
}
private void check(ClassNode cn, MethodNode mn, TryCatchBlockNode tcb, LabelNode handler) {
AbstractInsnNode ain = handler;
while (ain.getOpcode() == -1) { // skip labels and frames
ain = ain.getNext();
}
if (ain.getOpcode() == ATHROW) {
removeTCB(mn, tcb);
} else if (ain instanceof MethodInsnNode && ain.getNext().getOpcode() == ATHROW) {
MethodInsnNode min = (MethodInsnNode) ain;
if (min.owner.equals(cn.name)) {
MethodNode getter = ClassUtils.getMethod(cn, min.name, min.desc);
AbstractInsnNode getterFirst = getter.instructions.getFirst();
while (getterFirst.getOpcode() == -1) {
getterFirst = ain.getNext();
}
if (getterFirst instanceof VarInsnNode && getterFirst.getNext().getOpcode() == ARETURN) {
if (((VarInsnNode) getterFirst).var == 0) {
removeTCB(mn, tcb);
}
}
}
}
}
public static InsnList getImportantList(InsnList list) {
if (list.size() == 0) {
return list;
}
HashMap<LabelNode, LabelNode> labels = new HashMap<LabelNode, LabelNode>();
for (AbstractInsnNode insn = list.getFirst(); insn != null; insn = insn.getNext()) {
if (insn instanceof LabelNode) {
labels.put((LabelNode) insn, (LabelNode) insn);
}
}
InsnList importantNodeList = new InsnList();
for (AbstractInsnNode insn = list.getFirst(); insn != null; insn = insn.getNext()) {
if (insn instanceof LabelNode || insn instanceof LineNumberNode) {
continue;
}
importantNodeList.add(insn.clone(labels));
}
return importantNodeList;
}
public static void tableswitch(final Frame frame) {
TableSwitchInsnNode table = frame.tableSwitchInsnNode();
LabelNode labelNode = table.dflt;
int index = frame.operandStack.popInt();
int min = table.min;
int max = table.max;
int size = max - min + 1;
for (int i = 0; i < size; i++) {
if (index == (i + min)) {
labelNode = table.labels.get(i);
break;
}
}
frame.jump(labelNode);
//Log.opcode(frame.getCurrentOpCode());
}
/**
* <p>
* This method Handled the Switch block of TableSwitchInsnNode type in a
* method
* </p>.
*
* @param currentTableSwithInsn Type of switch block
*/
private void processTableSwitchBlock(
TableSwitchInsnNode currentTableSwithInsn) {
LabelNode currentLabel = currentTableSwithInsn.dflt;
int switchStartIndex = CollectionUtil.getObjectIndexInArray(insnArr,
currentTableSwithInsn);
int switchTargetIndex = CollectionUtil.getObjectIndexInArray(insnArr,
currentLabel);
if (switchTargetIndex > switchStartIndex) {
LOGGER.debug("switch block ended at: " + switchTargetIndex);
switchCount++;
AbstractInsnNode[] ainSwitchBlock = new AbstractInsnNode[] {
currentTableSwithInsn.getPrevious(), currentLabel };
Integer[] lineNumbers = getLineNumbersForSwitchBlock(ainSwitchBlock);
InsnList[] il = getInsnForswitchBlock(switchCount, lineNumbers);
addInsnForswitchBlock(il, ainSwitchBlock);
scanIndexForswitch = switchTargetIndex;
handleTableSwitchCases(currentTableSwithInsn);
}
}
private void patchMenu(ClassNode node) {
Logger.Info("Patching menu (" + node.name + ".class)");
Iterator<MethodNode> methodNodeList = node.methods.iterator();
while (methodNodeList.hasNext()) {
MethodNode methodNode = methodNodeList.next();
// Menu swap hook
if (methodNode.name.equals("e") && methodNode.desc.equals("(II)V")) {
AbstractInsnNode first = methodNode.instructions.getFirst();
LabelNode label = new LabelNode();
methodNode.instructions.insertBefore(first, new VarInsnNode(Opcodes.ALOAD, 0));
methodNode.instructions.insertBefore(
first,
new MethodInsnNode(
Opcodes.INVOKESTATIC, "Game/Menu", "switchList", "(Ljava/lang/Object;)Z"));
methodNode.instructions.insertBefore(first, new JumpInsnNode(Opcodes.IFGT, label));
methodNode.instructions.insertBefore(first, new InsnNode(Opcodes.RETURN));
methodNode.instructions.insertBefore(first, label);
}
}
}
@Override
public void initJumpTarget(int opcode, LabelNode target) {
if (target != null) {
switch (opcode) {
case IFEQ:
case IFNE:
case IFLT:
case IFGE:
case IFGT:
case IFLE:
case IF_ICMPEQ:
case IF_ICMPNE:
case IF_ICMPLT:
case IF_ICMPGE:
case IF_ICMPGT:
case IF_ICMPLE:
case IF_ACMPEQ:
case IF_ACMPNE:
case IFNONNULL:
// for the case when conditional block is handled, creates new variables set
// to store local variables declared inside current conditional block and
// stores its target LabelNode to restore previous variables set after conditional block is ended
localVariablesSet.push(new HashSet<>());
labelsStack.push(target);
}
}
}
@Override
public void visitJumpInsn(final int opcode, final Label label) {
super.visitJumpInsn(opcode, label);
LabelNode labelNode = ((JumpInsnNode) instructions.getLast()).label;
if (opcode == JSR && !subroutinesInsns.containsKey(labelNode)) {
subroutinesInsns.put(labelNode, new BitSet());
}
}
/**
* Generates instructions for an unconditional jump to a label.
* @param labelNode label to jump to
* @throws NullPointerException if any argument is {@code null}
* @return instructions for an unconditional jump to {@code labelNode}
*/
public static InsnList jumpTo(LabelNode labelNode) {
Validate.notNull(labelNode);
InsnList ret = new InsnList();
ret.add(new JumpInsnNode(Opcodes.GOTO, labelNode));
return ret;
}
public CodeBlock visitTableSwitchInsn(final int min, final int max,
final LabelNode defaultHandler, final LabelNode[] handlers)
{
instructionList.add(new TableSwitchInsnNode(min, max, defaultHandler,
handlers));
return this;
}
public static LabelNode getLabelByIndex(InsnList instructions, int index) {
int i = 0;
for (AbstractInsnNode ain : instructions.toArray()) {
if (ain instanceof LabelNode) {
if(i == index) {
return (LabelNode) ain;
}
i++;
}
}
return null;
}
private static SequenceQuery<AbstractInsnNode> infiniteIteratorLoopJavac() {
final Slot<LabelNode> loopStart = Slot.create(LabelNode.class);
return QueryStart
.any(AbstractInsnNode.class)
.then(methodCallThatReturns(ClassName.fromString("java/util/Iterator")))
.then(opCode(Opcodes.ASTORE))
.then(aLabelNode(loopStart.write()))
.oneOrMore(doesNotBreakIteratorLoop())
.then(jumpsTo(loopStart.read()))
// can't currently deal with loops with conditionals that cause additional jumps back
.zeroOrMore(QueryStart.match(jumpsTo(loopStart.read()).negate()));
}
/**
* <p>
* This method provides instructions to add method call to modify output
* path
* </p>.
*
* @param jobVariableIndex Index of job variable
* @param type the type
* @return Instructions
*/
private InsnList modifyOutputPath(int jobVariableIndex, Type type) {
LOGGER.debug("passed class name in modifyOutputPath is "
+ type.getInternalName());
InsnList il = new InsnList();
il.add(new LabelNode());
il.add(new VarInsnNode(Opcodes.ALOAD, jobVariableIndex));
il.add(new MethodInsnNode(Opcodes.INVOKESTATIC, CLASSNAME_JOB_UTIL,
"modifyOutputPath", Type.getMethodDescriptor(Type.VOID_TYPE,
type)));
return il;
}
public static String toString(AbstractInsnNode ain) {
String s = getOpcodeText(ain.getOpcode());
switch (ain.getType()) {
case AbstractInsnNode.FIELD_INSN:
FieldInsnNode fin = (FieldInsnNode) ain;
return s + " " + fin.owner + "#" + fin.name + " " + fin.desc;
case AbstractInsnNode.METHOD_INSN:
MethodInsnNode min = (MethodInsnNode) ain;
return s + " " + min.owner + "#" + min.name + min.desc;
case AbstractInsnNode.VAR_INSN:
VarInsnNode vin = (VarInsnNode) ain;
return s + " " + vin.var;
case AbstractInsnNode.TYPE_INSN:
TypeInsnNode tin = (TypeInsnNode) ain;
return s + " " + tin.desc;
case AbstractInsnNode.MULTIANEWARRAY_INSN:
MultiANewArrayInsnNode mnin = (MultiANewArrayInsnNode) ain;
return s + " " + mnin.dims + " " + mnin.desc;
case AbstractInsnNode.JUMP_INSN:
JumpInsnNode jin = (JumpInsnNode) ain;
return s + " " + getIndex(jin.label);
case AbstractInsnNode.LDC_INSN:
LdcInsnNode ldc = (LdcInsnNode) ain;
return s + " " + ldc.cst.toString();
case AbstractInsnNode.INT_INSN:
return s + " " + getIntValue(ain);
case AbstractInsnNode.IINC_INSN:
IincInsnNode iinc = (IincInsnNode) ain;
return s + " " + iinc.var + " +" + iinc.incr;
case AbstractInsnNode.FRAME:
FrameNode fn = (FrameNode) ain;
return s + " " + getOpcodeText(fn.type) + " " + fn.local.size() + " " + fn.stack.size();
case AbstractInsnNode.LABEL:
LabelNode ln = (LabelNode) ain;
return s + " " + getIndex(ln);
}
return s;
}
private boolean isFirst(Block to) {
LabelNode ln = to.getLabel();
if (ln != null && OpcodeFormatting.getLabelIndex(ln) == 0) {
return true;
}
return false;
}
public static InsnList cloneInsnList(Map<LabelNode, LabelNode> labelMap, InsnList insns) {
InsnList clone = new InsnList();
for (AbstractInsnNode insn = insns.getFirst(); insn != null; insn = insn.getNext()) {
clone.add(insn.clone(labelMap));
}
return clone;
}
public BlockVertex(MethodNode mn, Block block, ArrayList<AbstractInsnNode> nodes, LabelNode label, int listIndex) {
super();
this.mn = mn;
this.block = block;
this.nodes = nodes;
this.label = label;
this.listIndex = listIndex;
}
@Override
public void accept(MethodContext context, LabelNode node) {
Util.reverse(context.method.tryCatchBlocks.stream().filter(x -> x.start.equals(node)))
.forEachOrdered(context.tryCatches::add);
context.method.tryCatchBlocks.stream().filter(x -> x.end.equals(node))
.forEachOrdered(context.tryCatches::remove);
try {
super.accept(context, node);
} catch (UnsupportedOperationException ex) {
// ignored
}
context.output.append(String.format("%s: %s\n", node.getLabel(), trimmedTryCatchBlock));
}
public MethodFlow(
ClassFlow classFlow,
final int access,
final String name,
final String desc,
final String signature,
final String[] exceptions,
final Detector detector) {
super(Opcodes.ASM7, access, name, desc, signature, exceptions);
this.classFlow = classFlow;
this.detector = detector;
posToLabelList = new ArrayList<LabelNode>();
labelToPosMap = new HashMap<LabelNode, Integer>();
labelToBBMap = new HashMap<LabelNode, BasicBlock>();
/*if (exceptions != null && exceptions.length > 0) {
for (String e: exceptions) {
if (e.equals(PAUSABLE_CLASS)) {
hasPausableAnnotation = true;
break;
} else if (e.equals(NOT_PAUSABLE_CLASS)) {
suppressPausableCheck = true;
}
}
}*/
hasPausableAnnotation = true;
}
private void convertLookupSwitchInsn(LookupSwitchInsnNode insn) {
StackFrame frame = getFrame(insn);
if (units.containsKey(insn)) {
frame.mergeIn(pop());
return;
}
Operand key = popImmediate();
UnitBox dflt = Jimple.v().newStmtBox(null);
List<UnitBox> targets = new ArrayList<UnitBox>(insn.labels.size());
labels.put(insn.dflt, dflt);
for (LabelNode ln : insn.labels) {
UnitBox box = Jimple.v().newStmtBox(null);
targets.add(box);
labels.put(ln, box);
}
List<IntConstant> keys = new ArrayList<IntConstant>(insn.keys.size());
for (Integer i : insn.keys)
keys.add(IntConstant.v(i));
LookupSwitchStmt lss = Jimple.v().newLookupSwitchStmt(key.stackOrValue(),
keys, targets, dflt);
key.addBox(lss.getKeyBox());
frame.in(key);
frame.boxes(lss.getKeyBox());
setUnit(insn, lss);
}
/**
* <p>
* This method provides instructions to add Pattern.compile() call for regex
* values
* </p>
*
* @return Instructions
*/
private InsnList addPatternCompiler() {
JobConfig jobConfig = (JobConfig)getConfig();
String keyRegex = jobConfig.getMapReduceKeyRegex(getClassName());
String valueRegex = jobConfig.getMapReduceValueRegex(getClassName());
InsnList il = new InsnList();
LOGGER.debug(MessageFormat.format(InstrumentationMessageLoader
.getMessage(MessageConstants.LOG_ADD_PATTERN_COMPILE),
getClassName()));
// regex values
String[] regexes = new String[] { keyRegex, valueRegex };
// class fields
String[] filedNames = new String[] { KEY_PATTERN, VALUE_PATTERN };
for (int i = 0; i < regexes.length; i++) {
il.add(new LabelNode());
il.add(new VarInsnNode(Opcodes.ALOAD, 0));
// if regex is not null
if (regexes[i] != null) {
il.add(new LdcInsnNode(regexes[i]));
il.add(new MethodInsnNode(Opcodes.INVOKESTATIC,
CLASSNAME_PATTERN, "compile", Type.getMethodDescriptor(
Type.getType(Pattern.class), TYPE_STRING)));
il.add(new FieldInsnNode(
Opcodes.PUTFIELD,
ConfigurationUtil.convertQualifiedClassNameToInternalName(getClassName()),
filedNames[i], DESCRIPTOR_PATTERN));
}
}
return il;
}
@Override
public void process(@Nonnull final ParserClassNode classNode,
@Nonnull final RuleMethod method)
throws Exception
{
Objects.requireNonNull(classNode, "classNode");
Objects.requireNonNull(method, "method");
AbstractInsnNode current = method.instructions.getLast();
// find last return
while (current.getOpcode() != ARETURN)
current = current.getPrevious();
final LabelNode lastReturnLabel = new LabelNode();
method.instructions.insertBefore(current, lastReturnLabel);
// iterate backwards up to first instructions
while ((current = current.getPrevious()) != null) {
// replace returns with gotos
if (current.getOpcode() != ARETURN)
continue;
final JumpInsnNode insn = new JumpInsnNode(GOTO, lastReturnLabel);
method.instructions.set(current, insn);
current = insn;
}
}