下面列出了org.objectweb.asm.Opcodes# INVOKESTATIC 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
@Override
public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
if (opcode == Opcodes.INVOKESTATIC
&& "$jacocoInit".equals(name)
&& internalName.equals(owner)) {
checkNotNull(factory);
ClassReader bytecode =
checkNotNull(
factory.readIfKnown(internalName),
"Couldn't load interface %s to inline $jacocoInit()",
internalName);
InlineOneMethod copier = new InlineOneMethod("$jacocoInit", this);
bytecode.accept(copier, ClassReader.SKIP_DEBUG /* we're copying generated code anyway */);
} else {
super.visitMethodInsn(opcode, owner, name, desc, itf);
}
}
private void doVisitMethodInsn(
final int opcode,
final String owner,
final String name,
final String descriptor,
final boolean isInterface) {
switch (opcode) {
case Opcodes.INVOKESPECIAL:
invokespecial(owner, name, descriptor, isInterface);
break;
case Opcodes.INVOKEVIRTUAL:
invokevirtual(owner, name, descriptor, isInterface);
break;
case Opcodes.INVOKESTATIC:
invokestatic(owner, name, descriptor, isInterface);
break;
case Opcodes.INVOKEINTERFACE:
invokeinterface(owner, name, descriptor);
break;
default:
throw new IllegalArgumentException();
}
}
/**
* Common state machine advancing call. Called at every instruction to see if we need to inject and/or advance
* the state machine.
*/
private void checkInject() {
if (this.scanningToNewBlockStart) {
// We were waiting for this so make sure that this block has some associated cost.
BasicBlock currentBlock = this.blocks.get(this.nextBlockIndexToWrite);
long currentEnergyCost = currentBlock.getEnergyCost();
// We should never encounter a block with a zero/negative cost.
RuntimeAssertionError.assertTrue(currentEnergyCost > 0L);
// We track this as a long but report it as an int so prove that this can't overflow.
RuntimeAssertionError.assertTrue(currentEnergyCost <= (long)Integer.MAX_VALUE);
// Inject the bytecodes.
super.visitLdcInsn(Integer.valueOf((int)currentEnergyCost));
super.visitMethodInsn(Opcodes.INVOKESTATIC, Helper.RUNTIME_HELPER_NAME, "chargeEnergy", "(I)V", false);
// Reset the state machine for the next block.
this.scanningToNewBlockStart = false;
this.nextBlockIndexToWrite += 1;
}
}
private void invokeRecordAllocation(String typeName) {
Matcher matcher = namePattern.matcher(typeName);
if (matcher.find()) {
typeName = matcher.group(1);
}
// stack: ... count newobj
super.visitInsn(Opcodes.DUP_X1);
// -> stack: ... newobj count newobj
super.visitLdcInsn(typeName);
// -> stack: ... newobj count newobj typename
super.visitInsn(Opcodes.SWAP);
// -> stack: ... newobj count typename newobj
super.visitMethodInsn(
Opcodes.INVOKESTATIC, recorderClass, recorderMethod, RECORDER_SIGNATURE, false);
// -> stack: ... newobj
}
@Override
public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
if (itf && opcode == Opcodes.INVOKESTATIC) {
checkNotNull(bootclasspathReader);
checkState(
bootclasspathReader.isKnown(owner),
"%s contains invocation of static interface method that is "
+ "not in the bootclasspath. Owner: %s, name: %s, desc: %s.",
Java7Compatibility.this.internalName,
owner,
name,
desc);
if (!updated) {
Java7Compatibility.this.cv.visit(
Opcodes.V1_8,
Java7Compatibility.this.access,
Java7Compatibility.this.internalName,
Java7Compatibility.this.signature,
Java7Compatibility.this.superName,
Java7Compatibility.this.interfaces);
updated = true;
}
}
super.visitMethodInsn(opcode, owner, name, desc, itf);
}
@Override
public void transform(ClassNode classNode, String name) {
for (MethodNode methodNode : classNode.methods) {
if (TransformerMethod.ungrabMouseCursor.matches(methodNode)) {
// Objective:
// Find: Mouse.setCursorPosition(MouseHelperHook.ungrabMouseCursor() / 2, Display.getHeight() / 2);
// Replace method with: MouseHelperHook.ungrabMouseCursor(Display.getWidth() / 2, Display.getHeight() / 2);
Iterator<AbstractInsnNode> iterator = methodNode.instructions.iterator();
while (iterator.hasNext()) {
AbstractInsnNode abstractNode = iterator.next();
if (abstractNode instanceof MethodInsnNode && abstractNode.getOpcode() == Opcodes.INVOKESTATIC) {
MethodInsnNode methodInsnNode = (MethodInsnNode)abstractNode;
if (methodInsnNode.owner.equals("org/lwjgl/input/Mouse") && methodInsnNode.name.equals("setCursorPosition")) { // these are not minecraft methods, not obfuscated
methodNode.instructions.insertBefore(abstractNode, new MethodInsnNode(Opcodes.INVOKESTATIC, "codes/biscuit/skyblockaddons/asm/hooks/MouseHelperHook",
"ungrabMouseCursor", "(II)V", false)); // Add the replacement method call.
iterator.remove(); // Remove the old method call.
break;
}
}
}
break;
}
}
}
public static AbstractInsnNode methodCall(ClassNode classNode, MethodNode methodNode) {
int opcode = Opcodes.INVOKEVIRTUAL;
if (Modifier.isInterface(classNode.access)) {
opcode = Opcodes.INVOKEINTERFACE;
}
if (Modifier.isStatic(methodNode.access)) {
opcode = Opcodes.INVOKESTATIC;
}
if (methodNode.name.startsWith("<")) {
opcode = Opcodes.INVOKESPECIAL;
}
return new MethodInsnNode(opcode, classNode.name, methodNode.name, methodNode.desc, false);
}
private boolean needsFrameGuard(int opcode, String owner, String name, String desc) {
if (owner.startsWith("java/") || owner.startsWith("javax/")) {
//System.out.println("SKIP:: " + owner + "." + name + desc);
return false;
}
// Always create save-point before Continuation methods (like suspend)
if (CONTINUATION_CLASS_INTERNAL_NAME.equals(owner)) {
return CONTINUATION_CLASS_CONTINUABLE_METHODS.contains(name);
}
// No need to create save-point before constructors -- it's forbidden to suspend in constructors anyway
if (opcode == Opcodes.INVOKESPECIAL && "<init>".equals(name)) {
return false;
}
if (opcode == Opcodes.INVOKEINTERFACE ||
opcode == Opcodes.INVOKESPECIAL ||
opcode == Opcodes.INVOKESTATIC ||
opcode == Opcodes.INVOKEVIRTUAL) {
ContinuableClassInfo classInfo;
try {
classInfo = cciResolver.resolve(owner);
} catch (IOException ex) {
throw new RuntimeException(ex);
}
return null != classInfo && classInfo.isContinuableMethod(opcode, name, desc, desc);
}
return false;
}
@Override
public void visitMethodInsn(
int opcode, String owner, String name, String descriptor, boolean isInterface) {
if (opcode == Opcodes.INVOKESTATIC && owner.equals(SRC_OWNER)) {
if (REWRITE_MAP.containsKey(Arrays.asList(owner, name, descriptor))) {
matches.add(new StackTraceElement(className, methodName, fileName, lineNumber));
}
}
super.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
}
RedirectedInvokeData(Target target, MethodInsnNode node) {
super(target);
this.node = node;
this.returnType = Type.getReturnType(node.desc);
this.targetArgs = Type.getArgumentTypes(node.desc);
this.handlerArgs = node.getOpcode() == Opcodes.INVOKESTATIC
? this.targetArgs
: ObjectArrays.concat(Type.getObjectType(node.owner), this.targetArgs);
}
private static void insertTextureHandler(ClassNode node, boolean isObfuscated)
{
// We're attempting to turn this line from GlStateManager.bindTexture:
// GL11.glBindTexture(GL11.GL_TEXTURE_2D, texture);
// into this:
// TextureHelper.glBindTexture(GL11.GL_TEXTURE_2D, texture);
// TextureHelpers's method then decides whether or not add a shader to the OpenGL pipeline before
// passing the call on to GL11.glBindTexture.
final String methodName = isObfuscated ? "func_179144_i" : "bindTexture";
final String methodDescriptor = "(I)V"; // Takes one int, returns void.
System.out.println("MALMO: Found GlStateManager, attempting to transform it");
for (MethodNode method : node.methods)
{
if (method.name.equals(methodName) && method.desc.equals(methodDescriptor))
{
System.out.println("MALMO: Found GlStateManager.bindTexture() method, attempting to transform it");
for (AbstractInsnNode instruction : method.instructions.toArray())
{
if (instruction.getOpcode() == Opcodes.INVOKESTATIC)
{
MethodInsnNode visitMethodNode = (MethodInsnNode)instruction;
if (visitMethodNode.name.equals("glBindTexture"))
{
visitMethodNode.owner = "com/microsoft/Malmo/Utils/TextureHelper";
if (isObfuscated)
{
visitMethodNode.name = "bindTexture";
}
System.out.println("MALMO: Hooked into call to GlStateManager.bindTexture()");
}
}
}
}
}
}
private void addLog(boolean dup, int site) {
if (dup)
super.visitInsn(Opcodes.DUP);
super.visitLdcInsn(new Integer(site));
super.visitMethodInsn(Opcodes.INVOKESTATIC, name,
LOG_INTERNAL_ALLOC_REPORT, OBJECT_SITE_SIGNATURE);
if (!constructor)
super.visitMethodInsn(Opcodes.INVOKESTATIC, name,
LOG_INTERNAL_ALLOC_DONE, VOID_SIGNATURE);
}
@Override
public BytecodeExpression getPropertyNameIterable(BytecodeExpression target) {
return new InvokeExpression(MapPropertyAdapter.class,
Opcodes.INVOKESTATIC,
"stringsOnly",
Type.getMethodDescriptor(Type.getType(Iterable.class), Type.getType(Iterable.class)),
new IterableTypeWidget(BaseTypeAdapter.STRING),
null,
ImmutableList.<BytecodeExpression>of(new InvokeExpression(Map.class,
"keySet",
new SetTypeWidget(keyType),
target,
ImmutableList.<BytecodeExpression>of())));
}
public void visitMethodInsn(int opcode, String owner, String methodName, String desc) {
if ((JAVA_LANG_RUNTIME.equals(owner) || (inherit && name.equals(owner))) &&
RUNTIME_METHOD_NAME.equals(methodName) &&
RUNTIME_SIGNATURE.equals(desc)) {
found = true;
super.visitMethodInsn(Opcodes.INVOKESTATIC,name,RUNTIME_INTERNAL_METHOD_NAME,RUNTIME_INTERNAL_SIGNATURE);
} else {
super.visitMethodInsn(opcode,owner,methodName,desc);
}
}
protected void onMethodEnter() {
if (done || ! isSynchronized()) return;
has_monitor_operation = true;
super.visitInsn(Opcodes.ACONST_NULL);
super.pop();
methodStartLabel = super.mark();
super.visitMethodInsn(Opcodes.INVOKESTATIC, className, LOG_INTERNAL_ENTER_METHOD, LOG_CLASS_SIGNATURE);
}
private void doVisitMethodInsn(
final int opcode,
final String owner,
final String name,
final String descriptor,
final boolean isInterface) {
if (mv != null) {
mv.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
}
if (this.locals == null) {
labels = null;
return;
}
pop(descriptor);
if (opcode != Opcodes.INVOKESTATIC) {
Object value = pop();
if (opcode == Opcodes.INVOKESPECIAL && name.equals("<init>")) {
Object initializedValue;
if (value == Opcodes.UNINITIALIZED_THIS) {
initializedValue = this.owner;
} else {
initializedValue = uninitializedTypes.get(value);
}
for (int i = 0; i < locals.size(); ++i) {
if (locals.get(i) == value) {
locals.set(i, initializedValue);
}
}
for (int i = 0; i < stack.size(); ++i) {
if (stack.get(i) == value) {
stack.set(i, initializedValue);
}
}
}
}
pushDescriptor(descriptor);
labels = null;
}
public static boolean isBooleanValueOfZ(final AbstractInsnNode insn)
{
Objects.requireNonNull(insn, "insn");
if (insn.getOpcode() != Opcodes.INVOKESTATIC)
return false;
final MethodInsnNode mi = (MethodInsnNode) insn;
return isBooleanValueOfZ(mi.owner, mi.name, mi.desc);
}
/**
* @param opcode
* @param args
* @param tgt
* @param r
* @param signatureTypes
* @return
*/
private List<Type> setupTainting ( MethodReference call, int opcode, List<BaseType> args, Object tgt, MethodReference r, Type[] signatureTypes ) {
if ( opcode != Opcodes.INVOKESTATIC && opcode != Opcodes.INVOKEDYNAMIC ) {
if ( tgt == null || ! ( tgt instanceof BaseType ) || ( (BaseType) tgt ).isTainted() ) {
r.taintCallee();
}
}
boolean foundTypes = true;
List<Type> actualTypes = new ArrayList<>();
if ( signatureTypes.length != args.size() ) {
return null;
}
for ( int i = 0; i < signatureTypes.length; i++ ) {
Object object = args.get(i);
if ( object instanceof BaseType ) {
if ( object instanceof SimpleType ) {
Type type = ( (SimpleType) object ).getType();
Set<Type> altTypes = ( (BaseType) object ).getAlternativeTypes();
Type sigType = signatureTypes[ i ];
if ( type == null ) {
actualTypes.add(sigType);
}
else if ( altTypes == null || altTypes.isEmpty() ) {
try {
Type moreConcreteType = this.parent.getAnalyzer().getMoreConcreteType(type, sigType);
if ( !moreConcreteType.equals(sigType) ) {
// log.info("Improving type to " + moreConcreteType + " for " + call + " in " +
// this.ref);
}
actualTypes.add(moreConcreteType);
}
catch ( SerianalyzerException e ) {
this.log.error("Failed to determine argument type", e); //$NON-NLS-1$
this.log.warn("Formal arguments are " + Arrays.toString(signatureTypes)); //$NON-NLS-1$
this.log.warn("Known arguments are " + args); //$NON-NLS-1$
this.log.warn("Failing arg " + i + ": " + object); //$NON-NLS-1$ //$NON-NLS-2$
this.log.warn("Failing arg type " + type); //$NON-NLS-1$
this.log.warn("Signature type " + sigType); //$NON-NLS-1$
this.log.warn("In " + this.ref); //$NON-NLS-1$
this.log.warn("Calling " + call); //$NON-NLS-1$
foundTypes = false;
}
}
}
else {
foundTypes = false;
}
if ( ( (BaseType) object ).isTainted() ) {
r.taintParameter(i);
}
if ( object instanceof BasicVariable && ( (BasicVariable) object ).isTaintReturns() ) {
r.taintParameterReturns(i);
}
}
else {
r.taintParameter(i);
foundTypes = false;
}
}
if ( foundTypes ) {
return actualTypes;
}
//
return null;
}
public static MethodInsnNode getWrapperContructionInst(Type type) {
char charType = type.getDescriptor().charAt(0);
String wrapper;
switch (charType) {
case 'B':
wrapper = "java/lang/Byte";
break;
case 'C':
wrapper = "java/lang/Character";
break;
case 'D':
wrapper = "java/lang/Double";
break;
case 'F':
wrapper = "java/lang/Float";
break;
case 'I':
wrapper = "java/lang/Integer";
break;
case 'J':
wrapper = "java/lang/Long";
break;
case 'L':
return null;
case '[':
return null;
case 'Z':
wrapper = "java/lang/Boolean";
break;
case 'S':
wrapper = "java/lang/Short";
break;
default:
throw new ClassFormatError("Invalid method signature: "
+ type.getDescriptor());
}
return new MethodInsnNode(Opcodes.INVOKESTATIC, wrapper, "valueOf",
"(" + charType + ")L" + wrapper + ";", false);
}
public MethodInsnNode() {
super(Opcodes.INVOKESTATIC);
owner = "";
desc = "";
name = "";
}