Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
Toggle navigation
S
SandHook
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Administrator
SandHook
Commits
4852ccf9
Commit
4852ccf9
authored
Mar 07, 2019
by
swift_gan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
done new hooker maker
parent
0d617246
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
417 additions
and
6 deletions
+417
-6
SandHook.java
hooklib/src/main/java/com/swift/sandhook/SandHook.java
+3
-2
XposedCompat.java
...in/java/com/swift/sandhook/xposedcompat/XposedCompat.java
+1
-0
HookStubManager.java
...swift/sandhook/xposedcompat/hookstub/HookStubManager.java
+71
-0
DynamicBridge.java
.../swift/sandhook/xposedcompat/methodgen/DynamicBridge.java
+3
-3
HookMaker.java
.../com/swift/sandhook/xposedcompat/methodgen/HookMaker.java
+14
-0
HookerDexMaker.java
...swift/sandhook/xposedcompat/methodgen/HookerDexMaker.java
+1
-1
HookerDexMakerNew.java
...ft/sandhook/xposedcompat/methodgen/HookerDexMakerNew.java
+324
-0
No files found.
hooklib/src/main/java/com/swift/sandhook/SandHook.java
View file @
4852ccf9
...
@@ -102,6 +102,8 @@ public class SandHook {
...
@@ -102,6 +102,8 @@ public class SandHook {
mode
=
hookModeCallBack
.
hookMode
(
target
);
mode
=
hookModeCallBack
.
hookMode
(
target
);
}
}
globalHookEntityMap
.
put
(
entity
.
target
,
entity
);
int
res
;
int
res
;
if
(
mode
!=
HookMode
.
AUTO
)
{
if
(
mode
!=
HookMode
.
AUTO
)
{
res
=
hookMethod
(
target
,
hook
,
backup
,
mode
);
res
=
hookMethod
(
target
,
hook
,
backup
,
mode
);
...
@@ -121,11 +123,10 @@ public class SandHook {
...
@@ -121,11 +123,10 @@ public class SandHook {
}
}
if
(
res
<
0
)
{
if
(
res
<
0
)
{
globalHookEntityMap
.
remove
(
entity
.
target
);
throw
new
HookErrorException
(
"hook method <"
+
entity
.
target
.
toString
()
+
"> error in native!"
);
throw
new
HookErrorException
(
"hook method <"
+
entity
.
target
.
toString
()
+
"> error in native!"
);
}
}
globalHookEntityMap
.
put
(
entity
.
target
,
entity
);
if
(
entity
.
backup
!=
null
)
{
if
(
entity
.
backup
!=
null
)
{
globalBackupMap
.
put
(
entity
.
backup
,
entity
);
globalBackupMap
.
put
(
entity
.
backup
,
entity
);
}
}
...
...
xposedcompat/src/main/java/com/swift/sandhook/xposedcompat/XposedCompat.java
View file @
4852ccf9
...
@@ -27,6 +27,7 @@ public class XposedCompat {
...
@@ -27,6 +27,7 @@ public class XposedCompat {
//try to use internal stub hooker & backup method to speed up hook
//try to use internal stub hooker & backup method to speed up hook
public
static
volatile
boolean
useInternalStub
=
true
;
public
static
volatile
boolean
useInternalStub
=
true
;
public
static
volatile
boolean
useNewDexMaker
=
true
;
public
static
volatile
boolean
retryWhenCallOriginError
=
false
;
public
static
volatile
boolean
retryWhenCallOriginError
=
false
;
private
static
ClassLoader
sandHookXposedClassLoader
;
private
static
ClassLoader
sandHookXposedClassLoader
;
...
...
xposedcompat/src/main/java/com/swift/sandhook/xposedcompat/hookstub/HookStubManager.java
View file @
4852ccf9
...
@@ -322,6 +322,77 @@ public class HookStubManager {
...
@@ -322,6 +322,77 @@ public class HookStubManager {
}
}
}
}
public
static
Object
hookBridge
(
Member
origin
,
Object
thiz
,
Object
...
args
)
throws
Throwable
{
if
(
XposedBridge
.
disableHooks
)
{
return
SandHook
.
callOriginMethod
(
origin
,
thiz
,
args
);
}
DexLog
.
printMethodHookIn
(
origin
);
Object
[]
snapshot
=
hookCallbacks
.
get
(
origin
).
getSnapshot
();
if
(
snapshot
==
null
||
snapshot
.
length
==
0
)
{
return
SandHook
.
callOriginMethod
(
origin
,
thiz
,
args
);
}
XC_MethodHook
.
MethodHookParam
param
=
new
XC_MethodHook
.
MethodHookParam
();
param
.
method
=
origin
;
param
.
thisObject
=
thiz
;
param
.
args
=
args
;
int
beforeIdx
=
0
;
do
{
try
{
((
XC_MethodHook
)
snapshot
[
beforeIdx
]).
callBeforeHookedMethod
(
param
);
}
catch
(
Throwable
t
)
{
// reset result (ignoring what the unexpectedly exiting callback did)
param
.
setResult
(
null
);
param
.
returnEarly
=
false
;
continue
;
}
if
(
param
.
returnEarly
)
{
// skip remaining "before" callbacks and corresponding "after" callbacks
beforeIdx
++;
break
;
}
}
while
(++
beforeIdx
<
snapshot
.
length
);
// call original method if not requested otherwise
if
(!
param
.
returnEarly
)
{
try
{
param
.
setResult
(
SandHook
.
callOriginMethod
(
origin
,
thiz
,
param
.
args
));
}
catch
(
Throwable
e
)
{
XposedBridge
.
log
(
e
);
param
.
setThrowable
(
e
);
}
}
// call "after method" callbacks
int
afterIdx
=
beforeIdx
-
1
;
do
{
Object
lastResult
=
param
.
getResult
();
Throwable
lastThrowable
=
param
.
getThrowable
();
try
{
((
XC_MethodHook
)
snapshot
[
afterIdx
]).
callAfterHookedMethod
(
param
);
}
catch
(
Throwable
t
)
{
XposedBridge
.
log
(
t
);
if
(
lastThrowable
==
null
)
param
.
setResult
(
lastResult
);
else
param
.
setThrowable
(
lastThrowable
);
}
}
while
(--
afterIdx
>=
0
);
if
(!
param
.
hasThrowable
())
{
return
param
.
getResult
();
}
else
{
throw
param
.
getThrowable
();
}
}
public
static
long
callOrigin
(
HookMethodEntity
entity
,
Member
origin
,
Object
thiz
,
Object
[]
args
)
throws
Throwable
{
public
static
long
callOrigin
(
HookMethodEntity
entity
,
Member
origin
,
Object
thiz
,
Object
[]
args
)
throws
Throwable
{
Object
res
=
SandHook
.
callOriginMethod
(
origin
,
thiz
,
args
);
Object
res
=
SandHook
.
callOriginMethod
(
origin
,
thiz
,
args
);
return
entity
.
getResultAddress
(
res
);
return
entity
.
getResultAddress
(
res
);
...
...
xposedcompat/src/main/java/com/swift/sandhook/xposedcompat/methodgen/DynamicBridge.java
View file @
4852ccf9
...
@@ -24,7 +24,7 @@ import de.robv.android.xposed.XposedBridge;
...
@@ -24,7 +24,7 @@ import de.robv.android.xposed.XposedBridge;
public
final
class
DynamicBridge
{
public
final
class
DynamicBridge
{
private
static
final
HashMap
<
Member
,
Method
>
hookedInfo
=
new
HashMap
<>();
private
static
final
HashMap
<
Member
,
Method
>
hookedInfo
=
new
HashMap
<>();
private
static
final
HookerDexMaker
dexMaker
=
new
HookerDexMaker
();
private
static
HookMaker
hookMaker
=
XposedCompat
.
useNewDexMaker
?
new
HookerDexMakerNew
()
:
new
HookerDexMaker
();
private
static
final
AtomicBoolean
dexPathInited
=
new
AtomicBoolean
(
false
);
private
static
final
AtomicBoolean
dexPathInited
=
new
AtomicBoolean
(
false
);
private
static
File
dexDir
;
private
static
File
dexDir
;
...
@@ -66,9 +66,9 @@ public final class DynamicBridge {
...
@@ -66,9 +66,9 @@ public final class DynamicBridge {
SandHook
.
hook
(
new
HookWrapper
.
HookEntity
(
hookMethod
,
stub
.
hook
,
stub
.
backup
,
false
));
SandHook
.
hook
(
new
HookWrapper
.
HookEntity
(
hookMethod
,
stub
.
hook
,
stub
.
backup
,
false
));
entityMap
.
put
(
hookMethod
,
stub
);
entityMap
.
put
(
hookMethod
,
stub
);
}
else
{
}
else
{
dex
Maker
.
start
(
hookMethod
,
additionalHookInfo
,
hook
Maker
.
start
(
hookMethod
,
additionalHookInfo
,
XposedCompat
.
classLoader
,
dexDir
==
null
?
null
:
dexDir
.
getAbsolutePath
());
XposedCompat
.
classLoader
,
dexDir
==
null
?
null
:
dexDir
.
getAbsolutePath
());
hookedInfo
.
put
(
hookMethod
,
dex
Maker
.
getCallBackupMethod
());
hookedInfo
.
put
(
hookMethod
,
hook
Maker
.
getCallBackupMethod
());
}
}
DexLog
.
d
(
"hook method <"
+
hookMethod
.
toString
()
+
"> cost "
+
(
System
.
currentTimeMillis
()
-
timeStart
)
+
" ms, by "
+
(
stub
!=
null
?
"internal stub."
:
"dex maker"
));
DexLog
.
d
(
"hook method <"
+
hookMethod
.
toString
()
+
"> cost "
+
(
System
.
currentTimeMillis
()
-
timeStart
)
+
" ms, by "
+
(
stub
!=
null
?
"internal stub."
:
"dex maker"
));
Trace
.
endSection
();
Trace
.
endSection
();
...
...
xposedcompat/src/main/java/com/swift/sandhook/xposedcompat/methodgen/HookMaker.java
0 → 100644
View file @
4852ccf9
package
com
.
swift
.
sandhook
.
xposedcompat
.
methodgen
;
import
java.lang.reflect.Member
;
import
java.lang.reflect.Method
;
import
de.robv.android.xposed.XposedBridge
;
public
interface
HookMaker
{
void
start
(
Member
member
,
XposedBridge
.
AdditionalHookInfo
hookInfo
,
ClassLoader
appClassLoader
,
String
dexDirPath
)
throws
Exception
;
Method
getHookMethod
();
Method
getBackupMethod
();
Method
getCallBackupMethod
();
}
xposedcompat/src/main/java/com/swift/sandhook/xposedcompat/methodgen/HookerDexMaker.java
View file @
4852ccf9
...
@@ -34,7 +34,7 @@ import static com.swift.sandhook.xposedcompat.utils.DexMakerUtils.autoUnboxIfNec
...
@@ -34,7 +34,7 @@ import static com.swift.sandhook.xposedcompat.utils.DexMakerUtils.autoUnboxIfNec
import
static
com
.
swift
.
sandhook
.
xposedcompat
.
utils
.
DexMakerUtils
.
createResultLocals
;
import
static
com
.
swift
.
sandhook
.
xposedcompat
.
utils
.
DexMakerUtils
.
createResultLocals
;
import
static
com
.
swift
.
sandhook
.
xposedcompat
.
utils
.
DexMakerUtils
.
getObjTypeIdIfPrimitive
;
import
static
com
.
swift
.
sandhook
.
xposedcompat
.
utils
.
DexMakerUtils
.
getObjTypeIdIfPrimitive
;
public
class
HookerDexMaker
{
public
class
HookerDexMaker
implements
HookMaker
{
public
static
final
String
METHOD_NAME_BACKUP
=
"backup"
;
public
static
final
String
METHOD_NAME_BACKUP
=
"backup"
;
public
static
final
String
METHOD_NAME_HOOK
=
"hook"
;
public
static
final
String
METHOD_NAME_HOOK
=
"hook"
;
...
...
xposedcompat/src/main/java/com/swift/sandhook/xposedcompat/methodgen/HookerDexMakerNew.java
0 → 100644
View file @
4852ccf9
package
com
.
swift
.
sandhook
.
xposedcompat
.
methodgen
;
import
android.text.TextUtils
;
import
com.android.dx.Code
;
import
com.android.dx.DexMaker
;
import
com.android.dx.FieldId
;
import
com.android.dx.Label
;
import
com.android.dx.Local
;
import
com.android.dx.MethodId
;
import
com.android.dx.TypeId
;
import
com.swift.sandhook.SandHook
;
import
com.swift.sandhook.wrapper.HookWrapper
;
import
com.swift.sandhook.xposedcompat.hookstub.HookStubManager
;
import
com.swift.sandhook.xposedcompat.utils.DexLog
;
import
java.io.File
;
import
java.lang.reflect.Constructor
;
import
java.lang.reflect.Member
;
import
java.lang.reflect.Method
;
import
java.lang.reflect.Modifier
;
import
java.util.Map
;
import
de.robv.android.xposed.XposedBridge
;
import
de.robv.android.xposed.XposedHelpers
;
import
static
com
.
swift
.
sandhook
.
xposedcompat
.
utils
.
DexMakerUtils
.
MD5
;
import
static
com
.
swift
.
sandhook
.
xposedcompat
.
utils
.
DexMakerUtils
.
autoBoxIfNecessary
;
import
static
com
.
swift
.
sandhook
.
xposedcompat
.
utils
.
DexMakerUtils
.
autoUnboxIfNecessary
;
import
static
com
.
swift
.
sandhook
.
xposedcompat
.
utils
.
DexMakerUtils
.
createResultLocals
;
import
static
com
.
swift
.
sandhook
.
xposedcompat
.
utils
.
DexMakerUtils
.
getObjTypeIdIfPrimitive
;
public
class
HookerDexMakerNew
implements
HookMaker
{
public
static
final
String
METHOD_NAME_BACKUP
=
"backup"
;
public
static
final
String
METHOD_NAME_HOOK
=
"hook"
;
public
static
final
TypeId
<
Object
[]>
objArrayTypeId
=
TypeId
.
get
(
Object
[].
class
);
private
static
final
String
CLASS_DESC_PREFIX
=
"L"
;
private
static
final
String
CLASS_NAME_PREFIX
=
"SandHookerN"
;
private
static
final
String
FIELD_NAME_HOOK_INFO
=
"additionalHookInfo"
;
private
static
final
String
FIELD_NAME_METHOD
=
"method"
;
private
static
final
String
FIELD_NAME_BACKUP_METHOD
=
"backupMethod"
;
private
static
final
TypeId
<
Throwable
>
throwableTypeId
=
TypeId
.
get
(
Throwable
.
class
);
private
static
final
TypeId
<
Member
>
memberTypeId
=
TypeId
.
get
(
Member
.
class
);
private
static
final
TypeId
<
Method
>
methodTypeId
=
TypeId
.
get
(
Method
.
class
);
private
static
final
TypeId
<
XposedBridge
.
AdditionalHookInfo
>
hookInfoTypeId
=
TypeId
.
get
(
XposedBridge
.
AdditionalHookInfo
.
class
);
private
FieldId
<?,
XposedBridge
.
AdditionalHookInfo
>
mHookInfoFieldId
;
private
FieldId
<?,
Member
>
mMethodFieldId
;
private
FieldId
<?,
Method
>
mBackupMethodFieldId
;
private
MethodId
<?,
?>
mHookMethodId
;
private
MethodId
<?,
?>
mBackupMethodId
;
private
MethodId
<?,
?>
mSandHookBridgeMethodId
;
private
TypeId
<?>
mHookerTypeId
;
private
TypeId
<?>[]
mParameterTypeIds
;
private
Class
<?>[]
mActualParameterTypes
;
private
Class
<?>
mReturnType
;
private
TypeId
<?>
mReturnTypeId
;
private
boolean
mIsStatic
;
// TODO use this to generate methods
private
boolean
mHasThrowable
;
private
DexMaker
mDexMaker
;
private
Member
mMember
;
private
XposedBridge
.
AdditionalHookInfo
mHookInfo
;
private
ClassLoader
mAppClassLoader
;
private
Class
<?>
mHookClass
;
private
Method
mHookMethod
;
private
Method
mBackupMethod
;
private
String
mDexDirPath
;
private
static
TypeId
<?>[]
getParameterTypeIds
(
Class
<?>[]
parameterTypes
,
boolean
isStatic
)
{
int
parameterSize
=
parameterTypes
.
length
;
int
targetParameterSize
=
isStatic
?
parameterSize
:
parameterSize
+
1
;
TypeId
<?>[]
parameterTypeIds
=
new
TypeId
<?>[
targetParameterSize
];
int
offset
=
0
;
if
(!
isStatic
)
{
parameterTypeIds
[
0
]
=
TypeId
.
OBJECT
;
offset
=
1
;
}
for
(
int
i
=
0
;
i
<
parameterTypes
.
length
;
i
++)
{
parameterTypeIds
[
i
+
offset
]
=
TypeId
.
get
(
parameterTypes
[
i
]);
}
return
parameterTypeIds
;
}
private
static
Class
<?>[]
getParameterTypes
(
Class
<?>[]
parameterTypes
,
boolean
isStatic
)
{
if
(
isStatic
)
{
return
parameterTypes
;
}
int
parameterSize
=
parameterTypes
.
length
;
int
targetParameterSize
=
parameterSize
+
1
;
Class
<?>[]
newParameterTypes
=
new
Class
<?>[
targetParameterSize
];
int
offset
=
1
;
newParameterTypes
[
0
]
=
Object
.
class
;
System
.
arraycopy
(
parameterTypes
,
0
,
newParameterTypes
,
offset
,
parameterTypes
.
length
);
return
newParameterTypes
;
}
public
void
start
(
Member
member
,
XposedBridge
.
AdditionalHookInfo
hookInfo
,
ClassLoader
appClassLoader
,
String
dexDirPath
)
throws
Exception
{
if
(
member
instanceof
Method
)
{
Method
method
=
(
Method
)
member
;
mIsStatic
=
Modifier
.
isStatic
(
method
.
getModifiers
());
mReturnType
=
method
.
getReturnType
();
if
(
mReturnType
.
equals
(
Void
.
class
)
||
mReturnType
.
equals
(
void
.
class
)
||
mReturnType
.
isPrimitive
())
{
mReturnTypeId
=
TypeId
.
get
(
mReturnType
);
}
else
{
// all others fallback to plain Object for convenience
mReturnType
=
Object
.
class
;
mReturnTypeId
=
TypeId
.
OBJECT
;
}
mParameterTypeIds
=
getParameterTypeIds
(
method
.
getParameterTypes
(),
mIsStatic
);
mActualParameterTypes
=
getParameterTypes
(
method
.
getParameterTypes
(),
mIsStatic
);
mHasThrowable
=
method
.
getExceptionTypes
().
length
>
0
;
}
else
if
(
member
instanceof
Constructor
)
{
Constructor
constructor
=
(
Constructor
)
member
;
mIsStatic
=
false
;
mReturnType
=
void
.
class
;
mReturnTypeId
=
TypeId
.
VOID
;
mParameterTypeIds
=
getParameterTypeIds
(
constructor
.
getParameterTypes
(),
mIsStatic
);
mActualParameterTypes
=
getParameterTypes
(
constructor
.
getParameterTypes
(),
mIsStatic
);
mHasThrowable
=
constructor
.
getExceptionTypes
().
length
>
0
;
}
else
if
(
member
.
getDeclaringClass
().
isInterface
())
{
throw
new
IllegalArgumentException
(
"Cannot hook interfaces: "
+
member
.
toString
());
}
else
if
(
Modifier
.
isAbstract
(
member
.
getModifiers
()))
{
throw
new
IllegalArgumentException
(
"Cannot hook abstract methods: "
+
member
.
toString
());
}
else
{
throw
new
IllegalArgumentException
(
"Only methods and constructors can be hooked: "
+
member
.
toString
());
}
mMember
=
member
;
mHookInfo
=
hookInfo
;
mDexDirPath
=
dexDirPath
;
if
(
appClassLoader
==
null
||
appClassLoader
.
getClass
().
getName
().
equals
(
"java.lang.BootClassLoader"
))
{
mAppClassLoader
=
this
.
getClass
().
getClassLoader
();
}
else
{
mAppClassLoader
=
appClassLoader
;
}
mDexMaker
=
new
DexMaker
();
// Generate a Hooker class.
String
className
=
getClassName
(
mMember
);
String
dexName
=
className
+
".jar"
;
HookWrapper
.
HookEntity
hookEntity
=
null
;
//try load cache first
try
{
ClassLoader
loader
=
mDexMaker
.
loadClassDirect
(
mAppClassLoader
,
new
File
(
mDexDirPath
),
dexName
);
if
(
loader
!=
null
)
{
hookEntity
=
loadHookerClass
(
loader
,
className
);
}
}
catch
(
Throwable
throwable
)
{}
//do generate
if
(
hookEntity
==
null
)
{
hookEntity
=
doMake
(
className
,
dexName
);
}
SandHook
.
hook
(
hookEntity
);
}
private
HookWrapper
.
HookEntity
doMake
(
String
className
,
String
dexName
)
throws
Exception
{
mHookerTypeId
=
TypeId
.
get
(
CLASS_DESC_PREFIX
+
className
+
";"
);
mDexMaker
.
declare
(
mHookerTypeId
,
className
+
".generated"
,
Modifier
.
PUBLIC
,
TypeId
.
OBJECT
);
generateFields
();
generateHookMethod
();
generateBackupMethod
();
ClassLoader
loader
;
if
(
TextUtils
.
isEmpty
(
mDexDirPath
))
{
throw
new
IllegalArgumentException
(
"dexDirPath should not be empty!!!"
);
}
// Create the dex file and load it.
loader
=
mDexMaker
.
generateAndLoad
(
mAppClassLoader
,
new
File
(
mDexDirPath
),
dexName
);
return
loadHookerClass
(
loader
,
className
);
}
private
HookWrapper
.
HookEntity
loadHookerClass
(
ClassLoader
loader
,
String
className
)
throws
Exception
{
mHookClass
=
loader
.
loadClass
(
className
);
// Execute our newly-generated code in-process.
mHookMethod
=
mHookClass
.
getMethod
(
METHOD_NAME_HOOK
,
mActualParameterTypes
);
mBackupMethod
=
mHookClass
.
getMethod
(
METHOD_NAME_BACKUP
,
mActualParameterTypes
);
setup
(
mHookClass
);
return
new
HookWrapper
.
HookEntity
(
mMember
,
mHookMethod
,
mBackupMethod
,
false
);
}
private
void
setup
(
Class
mHookClass
)
{
XposedHelpers
.
setStaticObjectField
(
mHookClass
,
FIELD_NAME_METHOD
,
mMember
);
XposedHelpers
.
setStaticObjectField
(
mHookClass
,
FIELD_NAME_BACKUP_METHOD
,
mBackupMethod
);
XposedHelpers
.
setStaticObjectField
(
mHookClass
,
FIELD_NAME_HOOK_INFO
,
mHookInfo
);
}
private
String
getClassName
(
Member
originMethod
)
{
return
CLASS_NAME_PREFIX
+
"_"
+
MD5
(
originMethod
.
toString
());
}
public
Method
getHookMethod
()
{
return
mHookMethod
;
}
public
Method
getBackupMethod
()
{
return
mBackupMethod
;
}
public
Method
getCallBackupMethod
()
{
return
mBackupMethod
;
}
public
Class
getHookClass
()
{
return
mHookClass
;
}
private
void
generateFields
()
{
mHookInfoFieldId
=
mHookerTypeId
.
getField
(
hookInfoTypeId
,
FIELD_NAME_HOOK_INFO
);
mMethodFieldId
=
mHookerTypeId
.
getField
(
memberTypeId
,
FIELD_NAME_METHOD
);
mBackupMethodFieldId
=
mHookerTypeId
.
getField
(
methodTypeId
,
FIELD_NAME_BACKUP_METHOD
);
mDexMaker
.
declare
(
mHookInfoFieldId
,
Modifier
.
STATIC
,
null
);
mDexMaker
.
declare
(
mMethodFieldId
,
Modifier
.
STATIC
,
null
);
mDexMaker
.
declare
(
mBackupMethodFieldId
,
Modifier
.
STATIC
,
null
);
}
private
void
generateBackupMethod
()
{
mBackupMethodId
=
mHookerTypeId
.
getMethod
(
mReturnTypeId
,
METHOD_NAME_BACKUP
,
mParameterTypeIds
);
Code
code
=
mDexMaker
.
declare
(
mBackupMethodId
,
Modifier
.
PUBLIC
|
Modifier
.
STATIC
);
Local
<
Member
>
method
=
code
.
newLocal
(
memberTypeId
);
Map
<
TypeId
,
Local
>
resultLocals
=
createResultLocals
(
code
);
MethodId
<?,
?>
errLogMethod
=
TypeId
.
get
(
DexLog
.
class
).
getMethod
(
TypeId
.
get
(
Void
.
TYPE
),
"printCallOriginError"
,
memberTypeId
);
//very very important!!!!!!!!!!!
//add a try cache block avoid inline
Label
tryCatchBlock
=
new
Label
();
code
.
addCatchClause
(
throwableTypeId
,
tryCatchBlock
);
code
.
sget
(
mMethodFieldId
,
method
);
code
.
invokeStatic
(
errLogMethod
,
null
,
method
);
// start of try
code
.
mark
(
tryCatchBlock
);
// do nothing
if
(
mReturnTypeId
.
equals
(
TypeId
.
VOID
))
{
code
.
returnVoid
();
}
else
{
// we have limited the returnType to primitives or Object, so this should be safe
code
.
returnValue
(
resultLocals
.
get
(
mReturnTypeId
));
}
}
private
void
generateHookMethod
()
{
mHookMethodId
=
mHookerTypeId
.
getMethod
(
mReturnTypeId
,
METHOD_NAME_HOOK
,
mParameterTypeIds
);
mSandHookBridgeMethodId
=
TypeId
.
get
(
HookStubManager
.
class
).
getMethod
(
TypeId
.
get
(
Object
.
class
),
"hookBridge"
,
memberTypeId
,
TypeId
.
get
(
Object
.
class
),
TypeId
.
get
(
Object
[].
class
));
Code
code
=
mDexMaker
.
declare
(
mHookMethodId
,
Modifier
.
PUBLIC
|
Modifier
.
STATIC
);
Local
<
Member
>
method
=
code
.
newLocal
(
memberTypeId
);
// Local<Method> backupMethod = code.newLocal(methodTypeId);
Local
<
Object
>
thisObject
=
code
.
newLocal
(
TypeId
.
OBJECT
);
Local
<
Object
[]>
args
=
code
.
newLocal
(
objArrayTypeId
);
Local
<
Integer
>
actualParamSize
=
code
.
newLocal
(
TypeId
.
INT
);
Local
<
Integer
>
argIndex
=
code
.
newLocal
(
TypeId
.
INT
);
Local
<
Object
>
resultObj
=
code
.
newLocal
(
TypeId
.
OBJECT
);
Local
[]
allArgsLocals
=
createParameterLocals
(
code
);
Map
<
TypeId
,
Local
>
resultLocals
=
createResultLocals
(
code
);
code
.
sget
(
mMethodFieldId
,
method
);
code
.
loadConstant
(
args
,
null
);
code
.
loadConstant
(
argIndex
,
0
);
// code.sget(mBackupMethodFieldId, backupMethod);
int
paramsSize
=
mParameterTypeIds
.
length
;
int
offset
=
0
;
// thisObject
if
(
mIsStatic
)
{
// thisObject = null
code
.
loadConstant
(
thisObject
,
null
);
}
else
{
// thisObject = args[0]
offset
=
1
;
code
.
move
(
thisObject
,
allArgsLocals
[
0
]);
}
// actual args (exclude thisObject if this is not a static method)
code
.
loadConstant
(
actualParamSize
,
paramsSize
-
offset
);
code
.
newArray
(
args
,
actualParamSize
);
for
(
int
i
=
offset
;
i
<
paramsSize
;
i
++)
{
Local
parameter
=
allArgsLocals
[
i
];
// save parameter to resultObj as Object
autoBoxIfNecessary
(
code
,
resultObj
,
parameter
);
code
.
loadConstant
(
argIndex
,
i
-
offset
);
// save Object to args
code
.
aput
(
args
,
argIndex
,
resultObj
);
}
if
(
mReturnTypeId
.
equals
(
TypeId
.
VOID
))
{
code
.
invokeStatic
(
mSandHookBridgeMethodId
,
null
,
method
,
thisObject
,
args
);
code
.
returnVoid
();
}
else
{
code
.
invokeStatic
(
mSandHookBridgeMethodId
,
resultObj
,
method
,
thisObject
,
args
);
TypeId
objTypeId
=
getObjTypeIdIfPrimitive
(
mReturnTypeId
);
Local
matchObjLocal
=
resultLocals
.
get
(
objTypeId
);
code
.
cast
(
matchObjLocal
,
resultObj
);
// have to use matching typed Object(Integer, Double ...) to do unboxing
Local
toReturn
=
resultLocals
.
get
(
mReturnTypeId
);
autoUnboxIfNecessary
(
code
,
toReturn
,
matchObjLocal
,
resultLocals
,
true
);
code
.
returnValue
(
toReturn
);
}
}
private
Local
[]
createParameterLocals
(
Code
code
)
{
Local
[]
paramLocals
=
new
Local
[
mParameterTypeIds
.
length
];
for
(
int
i
=
0
;
i
<
mParameterTypeIds
.
length
;
i
++)
{
paramLocals
[
i
]
=
code
.
getParameter
(
i
,
mParameterTypeIds
[
i
]);
}
return
paramLocals
;
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment