use of org.objectweb.asm.tree.InsnList in project pinpoint by naver.
the class ASMMethodNodeAdapter method addBeforeInterceptor.
public void addBeforeInterceptor(final int interceptorId, final InterceptorDefinition interceptorDefinition, final int apiId) {
initInterceptorLocalVariables(interceptorId, interceptorDefinition, apiId);
final InsnList instructions = new InsnList();
this.methodVariables.loadInterceptorLocalVariables(instructions, interceptorDefinition, false);
final String description = Type.getMethodDescriptor(interceptorDefinition.getBeforeMethod());
instructions.add(new MethodInsnNode(Opcodes.INVOKEINTERFACE, Type.getInternalName(interceptorDefinition.getInterceptorBaseClass()), "before", description, true));
this.methodNode.instructions.insertBefore(this.methodVariables.getEnterInsnNode(), instructions);
}
use of org.objectweb.asm.tree.InsnList in project pinpoint by naver.
the class ASMMethodNodeAdapter method addAfterInterceptor.
public void addAfterInterceptor(final int interceptorId, final InterceptorDefinition interceptorDefinition, final int apiId) {
initInterceptorLocalVariables(interceptorId, interceptorDefinition, apiId);
// add try catch block.
final ASMTryCatch tryCatch = new ASMTryCatch(this.methodNode);
this.methodNode.instructions.insertBefore(this.methodVariables.getEnterInsnNode(), tryCatch.getStartLabelNode());
this.methodNode.instructions.insert(this.methodVariables.getExitInsnNode(), tryCatch.getEndLabelNode());
// find return.
AbstractInsnNode insnNode = this.methodNode.instructions.getFirst();
while (insnNode != null) {
final int opcode = insnNode.getOpcode();
if (this.methodVariables.isReturnCode(opcode)) {
final InsnList instructions = new InsnList();
this.methodVariables.storeResultVar(instructions, opcode);
invokeAfterInterceptor(instructions, interceptorDefinition, false);
this.methodNode.instructions.insertBefore(insnNode, instructions);
}
insnNode = insnNode.getNext();
}
// try catch handler.
InsnList instructions = new InsnList();
this.methodVariables.storeThrowableVar(instructions);
invokeAfterInterceptor(instructions, interceptorDefinition, true);
// throw exception.
this.methodVariables.loadInterceptorThrowVar(instructions);
this.methodNode.instructions.insert(tryCatch.getEndLabelNode(), instructions);
tryCatch.sort();
}
use of org.objectweb.asm.tree.InsnList in project pinpoint by naver.
the class ASMClassNodeAdapter method addSetterMethod.
public void addSetterMethod(final String methodName, final ASMFieldNodeAdapter fieldNode) {
if (methodName == null || fieldNode == null) {
throw new IllegalArgumentException("method name or fieldNode annotation must not be null.");
}
// void is V.
final String desc = "(" + fieldNode.getDesc() + ")V";
final MethodNode methodNode = new MethodNode(Opcodes.ACC_PUBLIC, methodName, desc, null, null);
if (methodNode.instructions == null) {
methodNode.instructions = new InsnList();
}
final InsnList instructions = methodNode.instructions;
// load this.
instructions.add(new VarInsnNode(Opcodes.ALOAD, 0));
final Type type = Type.getType(fieldNode.getDesc());
// put field.
instructions.add(new VarInsnNode(type.getOpcode(Opcodes.ILOAD), 1));
instructions.add(new FieldInsnNode(Opcodes.PUTFIELD, classNode.name, fieldNode.getName(), fieldNode.getDesc()));
// return.
instructions.add(new InsnNode(Opcodes.RETURN));
if (this.classNode.methods == null) {
this.classNode.methods = new ArrayList<MethodNode>();
}
this.classNode.methods.add(methodNode);
}
use of org.objectweb.asm.tree.InsnList in project dex2jar by pxb1988.
the class InvocationWeaver method wrapper.
public ClassVisitor wrapper(final ClassVisitor cv) {
return new RemappingClassAdapter(cv, remapper) {
Map<MtdInfo, MtdInfo> toCreate = new HashMap<MtdInfo, MtdInfo>();
String clzName;
private MtdInfo newMethodA(int opcode, MtdInfo t, MtdInfo mapTo) {
MtdInfo n = toCreate.get(t);
if (n != null) {
return n;
}
n = new MtdInfo();
n.owner = t.owner;
n.name = buildMethodAName(t.name);
boolean hasThis = opcode != INVOKESTATIC;
if (hasThis) {
Type[] args = Type.getArgumentTypes(t.desc);
Type ret = Type.getReturnType(t.desc);
List<Type> ts = new ArrayList<>(args.length + 1);
ts.add(Type.getType(t.owner));
ts.addAll(Arrays.asList(args));
n.desc = Type.getMethodDescriptor(ret, ts.toArray(new Type[ts.size()]));
} else {
n.desc = t.desc;
}
toCreate.put(t, n);
MethodVisitor mv = cv.visitMethod(ACC_SYNTHETIC | ACC_PRIVATE | ACC_STATIC, n.name, n.desc, null, null);
mv.visitCode();
genMethodACode(opcode, t, mapTo, mv, t);
return n;
}
private void genMethodACode(int opcode, MtdInfo t, MtdInfo mapTo, MethodVisitor mv, MtdInfo src) {
boolean hasThis = opcode != INVOKESTATIC;
Type[] args = Type.getArgumentTypes(t.desc);
Type ret = Type.getReturnType(t.desc);
final int start;
mv.visitTypeInsn(NEW, getCurrentInvocationName());
mv.visitInsn(DUP);
if (hasThis) {
mv.visitVarInsn(ALOAD, 0);
start = 1;
} else {
mv.visitInsn(ACONST_NULL);
start = 0;
}
if (args.length == 0) {
mv.visitInsn(ACONST_NULL);
} else {
mv.visitLdcInsn(args.length);
mv.visitTypeInsn(ANEWARRAY, "java/lang/Object");
for (int i = 0; i < args.length; i++) {
mv.visitInsn(DUP);
mv.visitLdcInsn(i);
mv.visitVarInsn(args[i].getOpcode(ILOAD), i + start);
box(args[i], mv);
mv.visitInsn(AASTORE);
}
}
int nextIdx = callbacks.size();
mv.visitLdcInsn(nextIdx);
mv.visitMethodInsn(INVOKESPECIAL, getCurrentInvocationName(), "<init>", "(Ljava/lang/Object;[Ljava/lang/Object;I)V");
mv.visitMethodInsn(INVOKESTATIC, toInternal(mapTo.owner), mapTo.name, mapTo.desc);
unBox(ret, Type.getReturnType(mapTo.desc), mv);
mv.visitInsn(ret.getOpcode(IRETURN));
mv.visitMaxs(-1, -1);
mv.visitEnd();
Callback cb = new Callback();
cb.idx = nextIdx;
cb.callback = newMethodCallback(opcode, t);
cb.target = src;
cb.isSpecial = opcode == INVOKESPECIAL;
cb.isStatic = opcode == INVOKESTATIC;
callbacks.add(cb);
}
private MtdInfo newMethodCallback(int opcode, MtdInfo t) {
MtdInfo n = new MtdInfo();
n.owner = "L" + className + ";";
n.name = buildCallbackMethodName(t.name);
if (opcode == INVOKESPECIAL || opcode == INVOKESTATIC) {
n.desc = "([Ljava/lang/Object;)Ljava/lang/Object;";
} else {
n.desc = "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;";
}
MethodVisitor mv = cv.visitMethod(opcode == INVOKESPECIAL ? ACC_PUBLIC : ACC_PUBLIC | ACC_STATIC, n.name, n.desc, null, null);
mv.visitCode();
int start;
if (opcode != INVOKESTATIC) {
mv.visitVarInsn(ALOAD, 0);
if (opcode != INVOKESPECIAL) {
mv.visitTypeInsn(CHECKCAST, toInternal(t.owner));
}
start = 1;
} else {
start = 0;
}
Type[] args = Type.getArgumentTypes(t.desc);
for (int i = 0; i < args.length; i++) {
mv.visitVarInsn(ALOAD, start);
mv.visitLdcInsn(i);
mv.visitInsn(AALOAD);
unBox(args[i], OBJECT_TYPE, mv);
}
mv.visitMethodInsn(opcode, toInternal(t.owner), t.name, t.desc);
Type ret = Type.getReturnType(t.desc);
box(ret, mv);
mv.visitInsn(ARETURN);
mv.visitMaxs(-1, -1);
mv.visitEnd();
return n;
}
@Override
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
super.visit(version, access, name, signature, superName, interfaces);
clzName = name;
}
public MethodVisitor visitMethod(int access, final String name, String desc, String signature, String[] exceptions) {
final MethodVisitor superMv = superMethodVisitor(access, name, desc, signature, exceptions);
final MtdInfo mapTo = findDefinedTargetMethod("L" + clzName + ";", name, desc);
if (mapTo != null) {
final MtdInfo t1 = new MtdInfo();
t1.owner = "L" + clzName + ";";
t1.name = buildMethodAName(name);
t1.desc = desc;
final MtdInfo t = t1;
final MtdInfo src = new MtdInfo();
src.owner = t.owner;
src.name = name;
src.desc = desc;
return new MethodNode(Opcodes.ASM4, access, name, desc, signature, exceptions) {
@Override
public void visitEnd() {
InsnList instructions = this.instructions;
List<TryCatchBlockNode> tryCatchBlocks = this.tryCatchBlocks;
List<LocalVariableNode> localVariables = this.localVariables;
this.instructions = new InsnList();
this.tryCatchBlocks = new ArrayList<>();
this.localVariables = new ArrayList<>();
this.maxLocals = -1;
this.maxStack = -1;
accept(superMv);
int opcode;
if (Modifier.isStatic(access)) {
opcode = Opcodes.INVOKESTATIC;
} else {
opcode = Opcodes.INVOKEVIRTUAL;
}
genMethodACode(opcode, t, mapTo, superMv, src);
// make sure public
int newAccess = (access & ~(ACC_PRIVATE | ACC_PROTECTED)) | ACC_PUBLIC;
MethodVisitor rmv = wrap(superMethodVisitor(newAccess, t.name, desc, null, null));
if (rmv != null) {
rmv.visitCode();
int n, i;
n = tryCatchBlocks == null ? 0 : tryCatchBlocks.size();
for (i = 0; i < n; ++i) {
tryCatchBlocks.get(i).accept(rmv);
}
instructions.accept(rmv);
n = localVariables == null ? 0 : localVariables.size();
for (i = 0; i < n; ++i) {
localVariables.get(i).accept(rmv);
}
rmv.visitMaxs(-1, -1);
rmv.visitEnd();
}
}
};
} else {
return wrap(superMv);
}
}
private MethodVisitor superMethodVisitor(int access, String name, String desc, String signature, String[] exceptions) {
return super.visitMethod(access, name, desc, signature, exceptions);
}
MethodVisitor wrap(MethodVisitor mv) {
return mv == null ? null : new ReplaceMethodVisitor(mv);
}
class ReplaceMethodVisitor extends MethodVisitor {
public ReplaceMethodVisitor(MethodVisitor mv) {
super(Opcodes.ASM4, mv);
}
@Override
public void visitMethodInsn(int opcode, String owner, String name, String desc) {
MtdInfo mapTo = findTargetMethod("L" + owner + ";", name, desc);
if (mapTo != null) {
boolean isStatic = opcode == INVOKESTATIC;
Type orgRet = Type.getReturnType(desc);
Type[] orgArgs = Type.getArgumentTypes(desc);
Type nRet = Type.getReturnType(mapTo.desc);
Type[] nArgs = Type.getArgumentTypes(mapTo.desc);
if (orgRet.getSort() != Type.VOID && nRet.getSort() == Type.VOID) {
throw new RuntimeException("can't cast " + nRet + " to " + orgRet);
}
if (nArgs.length == 1 && nArgs[0].getDescriptor().equals(invocationInterfaceDesc)) {
MtdInfo t = new MtdInfo();
t.owner = "L" + owner + ";";
t.name = name;
t.desc = desc;
MtdInfo n = newMethodA(opcode, t, mapTo);
super.visitMethodInsn(INVOKESTATIC, clzName, n.name, n.desc);
} else {
// checking for invalid replace
if (isStatic) {
if (!Arrays.deepEquals(orgArgs, nArgs)) {
throw new RuntimeException("arguments not equal: " + owner + "." + name + desc + " <> " + mapTo.owner + "." + mapTo.name + mapTo.desc);
}
} else {
if (nArgs.length != orgArgs.length + 1) {
throw new RuntimeException("arguments not equal: " + owner + "." + name + desc + " <> " + mapTo.owner + "." + mapTo.name + mapTo.desc);
}
if (orgArgs.length > 0) {
for (int i = 0; i < orgArgs.length; i++) {
if (!orgArgs[i].equals(nArgs[i + 1])) {
throw new RuntimeException("arguments not equal: " + owner + "." + name + desc + " <> " + mapTo.owner + "." + mapTo.name + mapTo.desc);
}
}
}
}
// replace it!
super.visitMethodInsn(INVOKESTATIC, toInternal(mapTo.owner), mapTo.name, mapTo.desc);
unBox(orgRet, nRet, this.mv);
}
} else {
super.visitMethodInsn(opcode, owner, name, desc);
}
}
}
};
}
use of org.objectweb.asm.tree.InsnList in project Valkyrien-Warfare-Revamped by ValkyrienWarfare.
the class SpecificMethodNodeTransformer method instructionsInserter.
public static SpecificMethodNodeTransformer instructionsInserter(String target, int priority, Function<AbstractInsnNode, Pair<InsnList, Boolean>> inserter) {
return instructionsTransformer(priority, target, instructions -> {
for (AbstractInsnNode node : instructions.toArray()) {
Pair<InsnList, Boolean> pair = inserter.apply(node);
if (pair != null)
if (pair.getRight())
instructions.insertBefore(node, pair.getLeft());
else
instructions.insert(node, pair.getLeft());
}
});
}
Aggregations