1 // Copyright 2021 Code Intelligence GmbH 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package com.code_intelligence.jazzer.api; 16 17 import java.lang.annotation.Documented; 18 import java.lang.annotation.ElementType; 19 import java.lang.annotation.Repeatable; 20 import java.lang.annotation.Retention; 21 import java.lang.annotation.RetentionPolicy; 22 import java.lang.annotation.Target; 23 import java.lang.invoke.MethodType; 24 25 /** 26 * Registers this method as a hook that should run after the method 27 * specified by the annotation parameters has returned. 28 * <p> 29 * This method will be called after every call to the target method and has 30 * access to its return value. The target method is specified by 31 * {@link #targetClassName()} and {@link #targetMethod()}. In case of an 32 * overloaded method, {@link #targetMethodDescriptor()} can be used to restrict 33 * the application of the hook to a particular overload. 34 * <p> 35 * The signature of the annotated method must be as follows (this does not 36 * restrict the method name and parameter names, which are arbitrary), 37 * depending on the value of {@link #type()}: 38 * 39 * <dl> 40 * <dt><span class="strong">{@link HookType#BEFORE}</span> 41 * <dd> 42 * <pre>{@code 43 * public static void hook(MethodHandle method, Object thisObject, Object[] arguments, int hookId) 44 * }</pre> 45 * Arguments: 46 * <p><ul> 47 * <li>{@code method}: A {@link java.lang.invoke.MethodHandle} representing the 48 * original method. The original method can be invoked via 49 * {@link java.lang.invoke.MethodHandle#invokeWithArguments(Object...)}. This 50 * requires passing {@code thisObject} as the first argument if the method is 51 * not static. This argument can be {@code null}. 52 * <li>{@code thisObject}: An {@link Object} containing the implicit 53 * {@code this} argument to the original method. If the original method is 54 * static, this argument will be {@code null}. 55 * <li>{@code arguments}: An array of {@link Object}s containing the arguments 56 * passed to the original method. Primitive types (e.g. {@code boolean}) will be 57 * wrapped into their corresponding wrapper type (e.g. {@link Boolean}). 58 * <li>{@code hookId}: A random {@code int} identifying the particular call 59 * site.This can be used to derive additional coverage information. 60 * </ul> 61 * 62 * <dt><span class="strong">{@link HookType#REPLACE}</span> 63 * <dd> 64 * <pre>{@code 65 * public static Object hook(MethodHandle method, Object thisObject, Object[] arguments, int hookId) 66 * }</pre> 67 * The return type may alternatively be taken to be the exact return type of 68 * target method or a wrapper type thereof. The returned object will be casted 69 * and unwrapped automatically. 70 * <p> 71 * Arguments: 72 * <p><ul> 73 * <li>{@code method}: A {@link java.lang.invoke.MethodHandle} representing the 74 * original method. The original method can be invoked via 75 * {@link java.lang.invoke.MethodHandle#invokeWithArguments(Object...)}. This 76 * requires passing {@code thisObject} as the first argument if the method is 77 * not static. This argument can be {@code null}. 78 * <li>{@code thisObject}: An {@link Object} containing the implicit 79 * {@code this} argument to the original method. If the original method is 80 * static, this argument will be {@code null}. 81 * <li>{@code arguments}: An array of {@link Object}s containing the arguments 82 * passed to the original method. Primitive types (e.g. {@code boolean}) will be 83 * wrapped into their corresponding wrapper type (e.g. {@link Boolean}). 84 * <li>{@code hookId}: A random {@code int} identifying the particular call 85 * site.This can be used to derive additional coverage information. 86 * </ul><p> 87 * <p> 88 * Return value: the value that should take the role of the value the target 89 * method would have returned 90 * 91 * <dt><span class="strong">{@link HookType#AFTER}</span> 92 * <dd> 93 * <pre>{@code 94 * public static void hook(MethodHandle method, Object thisObject, Object[] arguments, int hookId, 95 * Object returnValue) 96 * }</pre> 97 * Arguments: 98 * <p><ul> 99 * <li>{@code method}: A {@link java.lang.invoke.MethodHandle} representing the 100 * original method. The original method can be invoked via 101 * {@link java.lang.invoke.MethodHandle#invokeWithArguments(Object...)}. This 102 * requires passing {@code thisObject} as the first argument if the method is 103 * not static. This argument can be {@code null}. 104 * <li>{@code thisObject}: An {@link Object} containing the implicit 105 * {@code this} argument to the original method. If the original method is 106 * static, this argument will be {@code null}. 107 * <li>{@code arguments}: An array of {@link Object}s containing the arguments 108 * passed to the original method. Primitive types (e.g. {@code boolean}) will be 109 * wrapped into their corresponding wrapper type (e.g. {@link Boolean}). 110 * <li>{@code hookId}: A random {@code int} identifying the particular call 111 * site.This can be used to derive additional coverage information. 112 * <li>{@code returnValue}: An {@link Object} containing the return value of the 113 * invocation of the original method. Primitive types (e.g. {@code boolean}) 114 * will be wrapped into their corresponding wrapper type (e.g. {@link Boolean}). 115 * If the original method has return type {@code void}, this value will be 116 * {@code null}. 117 */ 118 @Retention(RetentionPolicy.RUNTIME) 119 @Target(ElementType.METHOD) 120 @Repeatable(MethodHooks.class) 121 @Documented 122 public @interface MethodHook { 123 /** 124 * The time at which the annotated method should be called. 125 * <p> 126 * If this is {@link HookType#BEFORE}, the annotated method will be called 127 * before the target method and has access to its arguments. 128 * <p> 129 * If this is {@link HookType#REPLACE}, the annotated method will be called 130 * instead of the target method. It has access to its arguments and can 131 * return a value that will replace the target method's return value. 132 * <p> 133 * If this is {@link HookType#AFTER}, the annotated method will be called 134 * after the target method and has access to its arguments and return 135 * value. 136 * 137 * @return when the hook should be called 138 */ type()139 HookType type(); 140 141 /** 142 * The name of the class that contains the method that should be hooked, 143 * as returned by {@link Class#getName()}. 144 * <p> 145 * Examples: 146 * <p><ul> 147 * <li>{@link String}: {@code "java.lang.String"} 148 * <li>{@link java.nio.file.FileSystem}: {@code "java.nio.file.FileSystem"} 149 * </ul><p> 150 * 151 * @return the name of the class containing the method to be hooked 152 */ targetClassName()153 String targetClassName(); 154 155 /** 156 * The name of the method to be hooked. Use {@code "<init>"} for 157 * constructors. 158 * <p> 159 * Examples: 160 * <p><ul> 161 * <li>{@link String#equals(Object)}: {@code "equals"} 162 * <li>{@link String#String()}: {@code "<init>"} 163 * </ul><p> 164 * 165 * @return the name of the method to be hooked 166 */ targetMethod()167 String targetMethod(); 168 169 /** 170 * The descriptor of the method to be hooked. This is only needed if there 171 * are multiple methods with the same name and not all of them should be 172 * hooked. 173 * <p> 174 * The descriptor of a method is an internal representation of the method's 175 * signature, which includes the types of its parameters and its return 176 * value. For more information on descriptors, see the 177 * <a href=https://docs.oracle.com/javase/specs/jvms/se15/html/jvms-4.html#jvms-4.3.3>JVM 178 * Specification, Section 4.3.3</a> and {@link MethodType#toMethodDescriptorString()} 179 * 180 * @return the descriptor of the method to be hooked 181 */ targetMethodDescriptor()182 String targetMethodDescriptor() default ""; 183 } 184