1 /* 2 * Copyright (C) 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.hoststubgen.visitors 17 18 import com.android.hoststubgen.asm.ClassNodes 19 import com.android.hoststubgen.filters.FilterPolicy 20 import com.android.hoststubgen.filters.FilterPolicyWithReason 21 import com.android.hoststubgen.filters.OutputFilter 22 import com.android.hoststubgen.log 23 import org.objectweb.asm.ClassVisitor 24 import org.objectweb.asm.MethodVisitor 25 import org.objectweb.asm.Opcodes 26 27 /** 28 * An adapter that generates the "impl" class file from an input class file. 29 */ 30 class StubGeneratingAdapter( 31 classes: ClassNodes, 32 nextVisitor: ClassVisitor, 33 filter: OutputFilter, 34 options: Options, 35 ) : BaseAdapter(classes, nextVisitor, filter, options) { 36 shouldEmitnull37 override fun shouldEmit(policy: FilterPolicy): Boolean { 38 return policy.needsInStub 39 } 40 visitMethodInnernull41 override fun visitMethodInner( 42 access: Int, 43 name: String, 44 descriptor: String, 45 signature: String?, 46 exceptions: Array<String>?, 47 policy: FilterPolicyWithReason, 48 substituted: Boolean, 49 superVisitor: MethodVisitor?, 50 ): MethodVisitor? { 51 return StubMethodVisitor(access, name, descriptor, signature, exceptions, superVisitor) 52 } 53 54 private inner class StubMethodVisitor( 55 access: Int, 56 val name: String, 57 descriptor: String, 58 signature: String?, 59 exceptions: Array<String>?, 60 next: MethodVisitor? 61 ) : BodyReplacingMethodVisitor(access, name, descriptor, signature, exceptions, next) { emitNewCodenull62 override fun emitNewCode() { 63 log.d(" Generating stub method for $currentClassName.$name") 64 65 // Inject the following code: 66 // throw new RuntimeException("Stub!"); 67 68 /* 69 NEW java/lang/RuntimeException 70 DUP 71 LDC "not supported on host side" 72 INVOKESPECIAL java/lang/RuntimeException.<init> (Ljava/lang/String;)V 73 ATHROW 74 MAXSTACK = 3 75 MAXLOCALS = 2 <- 1 for this, 1 for return value. 76 */ 77 visitTypeInsn(Opcodes.NEW, "java/lang/RuntimeException") 78 visitInsn(Opcodes.DUP) 79 visitLdcInsn("Stub!") 80 visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/RuntimeException", 81 "<init>", "(Ljava/lang/String;)V", false) 82 visitInsn(Opcodes.ATHROW) 83 visitMaxs(0, 0) // We let ASM figure them out. 84 } 85 } 86 } 87