-
public final class PineThe bridge class provides main APIs for you.
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description public interfacePine.HookListenerInterface definition for a callback to be invoked when a method is hooked.
public interfacePine.LibLoaderInterface definition for an implementation to be invoked when load our native library (libpine.so)
public interfacePine.HookModeEnum definition for how to hook method.
public interfacePine.HookHandlerInternal API. Implement the hook logic by implementing this interface.
public final classPine.HookRecordInternal API. Record hook info about a method.
public classPine.CallFrameA Holder that holds the method, "this" object, arguments, result or exception of a method call.
-
Field Summary
Fields Modifier and Type Field Description public final static Array<Object>EMPTY_OBJECT_ARRAYprivate static volatile inthookModepublic static longopenElfpublic static longfindElfSymbolpublic static longcloseElfpublic static longgetMethodDeclaringClasspublic static longsyncMethodEntrypublic static longsuspendVMpublic static longresumeVM
-
Method Summary
Modifier and Type Method Description static intgetHookMode()Return the current hook mode. static voidsetHookMode(int newHookMode)Set the way how Pine hook method. static voidensureInitialized()Initialize the Pine library if not initialized. static booleanisInitialized()Check whether Pine library is initialized. static voidsetHookHandler(Pine.HookHandler h)Set a handler that will be used when Pine hooking a method. static Pine.HookHandlergetHookHandler()Get the handler that will be used when Pine hooking a method.Internal API, use the returned handler only when you are implementing your own handlerand want to continue hooking. static voidsetHookListener(Pine.HookListener l)Set a listener that will be called before/after hooking a method. static Pine.HookListenergetHookListener()Get the listener that will be called before/after hooking method. static booleanis64Bit()Return whether the system is 64-bit.Note that this method will initialize Pine library if uninitialized. static MethodHook.Unhookhook(Member method, MethodHook callback)Register a hook that will be invoked when the {@code method}is invoked.Note that this will initialize Pine library if uninitialized.static MethodHook.Unhookhook(Member method, MethodHook callback, boolean canInitDeclaringClass)Register a hook that will be invoked when the {@code method}is invoked.Note that this will initialize Pine library if uninitialized.static MethodhookReplace(Pine.HookRecord hookRecord, Method replacement, Method backup, boolean canInitDeclaringClass)static booleanisHooked(Member method)Return whether the given method has been hooked before. static Pine.HookRecordgetHookRecord(long artMethod)static ObjectgetObject(long thread, long address)static longgetAddress(long thread, Object o)static ObjectinvokeOriginalMethod(Member method, Object thisObject, Array<Object> args)Invoke the original implementation of the given method.If the method is not hooked, the behavior is undefined. static booleancompile(Member method)Compile the given method. static booleandecompile(Member method, boolean disableJit)Decompile the given method. static booleandisableJitInline()Prevent any JIT inlining in the current process. static voidsetJitCompilationAllowed(boolean allowed)Set whether we can manually JIT compile a method. static voidsetJitCompilationAllowed(boolean allowed, boolean autoCompileBridge)Set whether we can manually JIT compile a method. static booleandisableProfileSaver()Prevent art recording our method call profile. static voidsetDebuggable(boolean debuggable)Set whether the current process is debuggable, like {@code PineConfig#debuggable}but allowsyou set the value after Pine library is initialized.static voiddisableHiddenApiPolicy(boolean application, boolean platform)Disable the hidden api restriction policy in the current process. static ObjecthandleCall(Pine.HookRecord hookRecord, Object thisObject, Array<Object> args)static voidlog(String message)Print a log with "Pine" tag if {@code PineConfig#debug}is set, or do nothing.static voidlog(String fmt, Array<Object> args)Print a log with "Pine" tag if {@code PineConfig#debug}is set, or do nothing.static native longgetArtMethod(Member method)static native voidgetArgsArm32(int extras, int sp, Array<int> crOut, Array<int> stack, Array<float> fpOut)static native voidgetArgsArm64(long extras, long sp, Array<boolean> typeWides, Array<long> crOut, Array<long> stack, Array<double> fpOut)static native voidgetArgsX86(int extras, Array<int> out, int ebx)static native longcurrentArtThread0()static native longcloneExtras(long origin)-
-
Method Detail
-
getHookMode
static int getHookMode()
Return the current hook mode.
-
setHookMode
static void setHookMode(int newHookMode)
Set the way how Pine hook method.
- Parameters:
newHookMode- One of{@code Pine.HookMode.AUTO},{@code Pine.HookMode.INLINE},{@code Pine.HookMode.REPLACEMENT}or{@code Pine.HookMode.INLINE_WITHOUT_JIT}.
-
ensureInitialized
static void ensureInitialized()
Initialize the Pine library if not initialized.WARNING: Calling this API will disable hidden api policy when
{@code PineConfig.disableHiddenApiPolicy}or{@code PineConfig.disableHiddenApiPolicyForPlatformDomain}.Due to an ART bug, if a thread changes hidden api policy while another thread is callinga API that lists members of a class, a out-of-bounds write may occur and causes crashes.See ... for more details.
-
isInitialized
static boolean isInitialized()
Check whether Pine library is initialized.
-
setHookHandler
static void setHookHandler(Pine.HookHandler h)
Set a handler that will be used when Pine hooking a method.Internal API, use
{@code HookListener}instead if you just want to be notified when hooking.Note that only one handler can exist at a time, so setting a new handler will overridethe old one. Save the old handler if yours don't know how to properly hook a method!- Parameters:
h- The handler you want to register.
-
getHookHandler
static Pine.HookHandler getHookHandler()
Get the handler that will be used when Pine hooking a method.Internal API, use the returned handler only when you are implementing your own handlerand want to continue hooking. Do NOT use the returned hook handler if you just want to hook.
-
setHookListener
static void setHookListener(Pine.HookListener l)
Set a listener that will be called before/after hooking a method.
- Parameters:
l- The listener you want to set.
-
getHookListener
static Pine.HookListener getHookListener()
Get the listener that will be called before/after hooking method.
-
is64Bit
static boolean is64Bit()
Return whether the system is 64-bit.Note that this method will initialize Pine library if uninitialized.
-
hook
static MethodHook.Unhook hook(Member method, MethodHook callback)
Register a hook that will be invoked when the
{@code method}is invoked.Note that this will initialize Pine library if uninitialized.- Parameters:
method- The method want to control.callback- The callback that will be invoked when the{@code method}is invoked.
-
hook
static MethodHook.Unhook hook(Member method, MethodHook callback, boolean canInitDeclaringClass)
Register a hook that will be invoked when the
{@code method}is invoked.Note that this will initialize Pine library if uninitialized.- Parameters:
method- The method want to control.callback- The callback that will be invoked when the{@code method}is invoked.canInitDeclaringClass-{@code true}if initializing the class is allowed,{@code false}otherwise.
-
hookReplace
static Method hookReplace(Pine.HookRecord hookRecord, Method replacement, Method backup, boolean canInitDeclaringClass)
-
isHooked
static boolean isHooked(Member method)
Return whether the given method has been hooked before.Note that once the method is hooked, this will return
{@code true}, even it has been unhooked.- Parameters:
method- the method you want to check.
-
getHookRecord
static Pine.HookRecord getHookRecord(long artMethod)
-
getAddress
static long getAddress(long thread, Object o)
-
invokeOriginalMethod
static Object invokeOriginalMethod(Member method, Object thisObject, Array<Object> args)
Invoke the original implementation of the given method.If the method is not hooked, the behavior is undefined. Now Pine will try to directly invoke it,but if other threads hooked the given method between we check if the method is hookedand invoke it directly, this call will be intercepted and the registered hooks will betriggered. DO NOT RELY ON THIS UNRELIABLE INTERNAL BEHAVIOR.
- Parameters:
method- The method you want to invoke its original implementation.thisObject- The object the underlying method is invoked fromargs- The arguments used for the method call
-
compile
static boolean compile(Member method)
Compile the given method. Note that this will always do nothing on Android R+,and may crash if JIT compilation is not allowed the current process,like some system process. Make sure you really need this before use!
- Parameters:
method- The method you want to compile.
-
decompile
static boolean decompile(Member method, boolean disableJit)
Decompile the given method. Force the given method executes by interpreter.This may be very useful when hooking a method that is inlined into caller.Note that in that case, you should decompile the caller rather than the callee.
- Parameters:
method- The method you want to decompile.disableJit-{@code true}if you want to prevent the method gets JIT compiled again
-
disableJitInline
@Deprecated() static boolean disableJitInline()
Prevent any JIT inlining in the current process. DOES NOT WORK FOR NOW.
-
setJitCompilationAllowed
static void setJitCompilationAllowed(boolean allowed)
Set whether we can manually JIT compile a method.
- Parameters:
allowed-{@code true}if allowed,{@code false}otherwise.
-
setJitCompilationAllowed
static void setJitCompilationAllowed(boolean allowed, boolean autoCompileBridge)
Set whether we can manually JIT compile a method.
- Parameters:
allowed-{@code true}if allowed,{@code false}otherwise.autoCompileBridge-{@code true}if try to automatically compile bridge methods for better performance
-
disableProfileSaver
static boolean disableProfileSaver()
Prevent art recording our method call profile. This can prevent methods being AOT-compiled,so can avoid some hook invalidation caused by optimization, but will cause performance problems.
-
setDebuggable
static void setDebuggable(boolean debuggable)
Set whether the current process is debuggable, like
{@code PineConfig#debuggable}but allowsyou set the value after Pine library is initialized.- Parameters:
debuggable- whether the current process is debuggable.
-
disableHiddenApiPolicy
static void disableHiddenApiPolicy(boolean application, boolean platform)
Disable the hidden api restriction policy in the current process.
- Parameters:
application- whether the restriction policy for application domain should be disabledplatform- whether the restriction policy for platform domain should be disabled
-
handleCall
static Object handleCall(Pine.HookRecord hookRecord, Object thisObject, Array<Object> args)
-
log
static void log(String message)
Print a log with "Pine" tag if
{@code PineConfig#debug}is set, or do nothing.- Parameters:
message- The message you want print.
-
log
static void log(String fmt, Array<Object> args)
Print a log with "Pine" tag if
{@code PineConfig#debug}is set, or do nothing.- Parameters:
fmt- The message format you want print.args- The args used to format{@code format}.
-
getArtMethod
static native long getArtMethod(Member method)
-
getArgsArm32
static native void getArgsArm32(int extras, int sp, Array<int> crOut, Array<int> stack, Array<float> fpOut)
-
getArgsArm64
static native void getArgsArm64(long extras, long sp, Array<boolean> typeWides, Array<long> crOut, Array<long> stack, Array<double> fpOut)
-
getArgsX86
static native void getArgsX86(int extras, Array<int> out, int ebx)
-
currentArtThread0
static native long currentArtThread0()
-
cloneExtras
static native long cloneExtras(long origin)
-
-
-
-