Skip to content

Commit 36230c7

Browse files
ganyao114ganyao114
authored and
ganyao114
committedSep 18, 2019
Fix: fix case when hook some method in class not inited
1 parent 6b1a533 commit 36230c7

File tree

18 files changed

+376
-136
lines changed

18 files changed

+376
-136
lines changed
 

‎app/build.gradle

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ android {
1212
}
1313
buildTypes {
1414
debug {
15+
debuggable false
1516
minifyEnabled false
1617
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
1718
}

‎app/src/main/java/com/swift/sandhook/MainActivity.java

+4
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
import com.swift.sandhook.test.Inter;
1515
import com.swift.sandhook.test.InterImpl;
16+
import com.swift.sandhook.test.PendingHookTest;
1617
import com.swift.sandhook.test.TestClass;
1718

1819
import java.lang.reflect.Field;
@@ -82,6 +83,9 @@ public void dosth() {
8283
inter.dosth();
8384

8485
testPluginHook(str);
86+
87+
MyApp.initedTest = true;
88+
PendingHookTest.test();
8589
}
8690

8791
public static Field getField(Class topClass, String fieldName) throws NoSuchFieldException {

‎app/src/main/java/com/swift/sandhook/MyApp.java

+14-13
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import android.os.Build;
66
import android.util.Log;
77

8+
import com.swift.sandhook.test.PendingHookTest;
89
import com.swift.sandhook.test.TestClass;
910
import com.swift.sandhook.testHookers.ActivityHooker;
1011
import com.swift.sandhook.testHookers.CtrHook;
@@ -16,14 +17,15 @@
1617
import com.swift.sandhook.wrapper.HookErrorException;
1718
import com.swift.sandhook.xposedcompat.XposedCompat;
1819

19-
import dalvik.system.DexClassLoader;
2020
import de.robv.android.xposed.XC_MethodHook;
2121
import de.robv.android.xposed.XposedHelpers;
2222

2323
public class MyApp extends Application {
2424

2525
//if you want test Android Q, please Set true, because SDK_INT of Android Q is still 28
2626
public final static boolean testAndroidQ = false;
27+
//for test pending hook case
28+
public volatile static boolean initedTest = false;
2729

2830
@Override
2931
public void onCreate() {
@@ -95,18 +97,17 @@ protected void afterHookedMethod(MethodHookParam param) throws Throwable {
9597
}
9698
});
9799

98-
try {
99-
ClassLoader classLoader = getClassLoader();
100-
DexClassLoader dexClassLoader = new DexClassLoader("/sdcard/hookers-debug.apk",
101-
getCacheDir().getAbsolutePath(), null, classLoader);
102-
Class absHookerClass = Class.forName("com.swift.sandhook.hookers.AbsHooker", true, dexClassLoader);
103-
Class pluginHookerClass = Class.forName("com.swift.sandhook.hookers.PluginHooker", true, dexClassLoader);
104-
SandHook.addHookClass(getClassLoader(), absHookerClass, pluginHookerClass);
105-
} catch (ClassNotFoundException e) {
106-
e.printStackTrace();
107-
} catch (HookErrorException e) {
108-
e.printStackTrace();
109-
}
100+
XposedHelpers.findAndHookMethod(PendingHookTest.class, "test", new XC_MethodHook() {
101+
@Override
102+
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
103+
super.beforeHookedMethod(param);
104+
param.returnEarly = true;
105+
}
110106

107+
@Override
108+
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
109+
super.afterHookedMethod(param);
110+
}
111+
});
111112
}
112113
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package com.swift.sandhook.test;
2+
3+
import android.util.Log;
4+
5+
import com.swift.sandhook.MyApp;
6+
7+
public class PendingHookTest {
8+
9+
static {
10+
if (!MyApp.initedTest) {
11+
throw new RuntimeException("PendingHookTest.class may can not init this time!");
12+
}
13+
}
14+
15+
public static void test() {
16+
Log.e("PendingHookTest", "hook failure!");
17+
}
18+
19+
}

‎build.gradle

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ buildscript {
77
jcenter()
88
}
99
dependencies {
10-
classpath 'com.android.tools.build:gradle:3.1.3'
10+
classpath 'com.android.tools.build:gradle:3.5.0'
1111
classpath 'com.novoda:bintray-release:0.8.1'
1212

1313
// NOTE: Do not place your application dependencies here; they belong

‎gradle/wrapper/gradle-wrapper.properties

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
33
distributionPath=wrapper/dists
44
zipStoreBase=GRADLE_USER_HOME
55
zipStorePath=wrapper/dists
6-
distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip
6+
distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip

‎hooklib/build.gradle

+4-5
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,14 @@ android {
99
versionCode 1
1010
versionName "1.0"
1111

12-
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
13-
1412
externalNativeBuild {
1513
cmake {
16-
arguments '-DBUILD_TESTING=OFF'
17-
cppFlags "-frtti -fexceptions"
18-
abiFilters 'armeabi-v7a', 'arm64-v8a'
14+
arguments "-DCMAKE_BUILD_TYPE=Release"
1915
}
2016
}
17+
ndk {
18+
abiFilters 'armeabi-v7a', "arm64-v8a"
19+
}
2120
}
2221

2322
externalNativeBuild {

‎hooklib/src/main/cpp/CMakeLists.txt

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ project(sandhook)
33

44
ENABLE_LANGUAGE(ASM)
55

6+
add_definitions(-std=c++11)
7+
68
set(${PROJECT_NAME}_SOURCES
79
sandhook.cpp
810
trampoline/trampoline.cpp
@@ -23,8 +25,6 @@ set(${PROJECT_NAME}_SOURCES
2325
nativehook/native_hook.cpp
2426
)
2527

26-
add_definitions(-std=c++11)
27-
2828
add_library(${PROJECT_NAME}
2929
SHARED
3030
${${PROJECT_NAME}_SOURCES})

‎hooklib/src/main/cpp/includes/hide_api.h

+4
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ extern "C" {
3737

3838
bool forceProcessProfiles();
3939

40+
bool hookClassInit(void(*callback)(void*));
41+
42+
JNIEnv *attachAndGetEvn();
43+
4044
}
4145

4246
#endif //SANDHOOK_HIDE_API_H

‎hooklib/src/main/cpp/sandhook.cpp

+23-1
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,7 @@ Java_com_swift_sandhook_SandHook_skipAllSafeCheck(JNIEnv *env, jclass type, jboo
324324
extern "C"
325325
JNIEXPORT jboolean JNICALL
326326
Java_com_swift_sandhook_SandHook_is64Bit(JNIEnv *env, jclass type) {
327-
return BYTE_POINT == 8;
327+
return static_cast<jboolean>(BYTE_POINT == 8);
328328
}
329329

330330
extern "C"
@@ -361,6 +361,23 @@ Java_com_swift_sandhook_SandHook_setNativeEntry(JNIEnv *env, jclass type, jobjec
361361
return JNI_TRUE;
362362
}
363363

364+
365+
static jclass class_pending_hook = nullptr;
366+
static jmethodID method_class_init = nullptr;
367+
368+
extern "C"
369+
JNIEXPORT jboolean JNICALL
370+
Java_com_swift_sandhook_SandHook_initForPendingHook(JNIEnv *env, jclass type) {
371+
class_pending_hook = static_cast<jclass>(env->NewGlobalRef(
372+
env->FindClass("com/swift/sandhook/PendingHookHandler")));
373+
method_class_init = env->GetStaticMethodID(class_pending_hook, "onClassInit", "(J)V");
374+
auto class_init_handler = [](void *clazz_ptr) {
375+
attachAndGetEvn()->CallStaticVoidMethod(class_pending_hook, method_class_init, (jlong) clazz_ptr);
376+
attachAndGetEvn()->ExceptionClear();
377+
};
378+
return static_cast<jboolean>(hookClassInit(class_init_handler));
379+
}
380+
364381
extern "C"
365382
JNIEXPORT void JNICALL
366383
Java_com_swift_sandhook_ClassNeverCall_neverCallNative(JNIEnv *env, jobject instance) {
@@ -477,6 +494,11 @@ static JNINativeMethod jniSandHook[] = {
477494
"setNativeEntry",
478495
"(Ljava/lang/reflect/Member;Ljava/lang/reflect/Member;J)Z",
479496
(void *) Java_com_swift_sandhook_SandHook_setNativeEntry
497+
},
498+
{
499+
"initForPendingHook",
500+
"()Z",
501+
(void *) Java_com_swift_sandhook_SandHook_initForPendingHook
480502
}
481503
};
482504

‎hooklib/src/main/cpp/utils/hide_api.cpp

+50
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,12 @@ extern "C" {
3535

3636
JavaVM* jvm;
3737

38+
void *(*hook_native)(void* origin, void *replace) = nullptr;
39+
40+
void (*class_init_callback)(void*) = nullptr;
41+
42+
void (*backup_fixup_static_trampolines)(void *, void *) = nullptr;
43+
3844
bool fileExits(const char* path) {
3945
int fd = open(path, O_RDONLY);
4046
if (fd < 0) {
@@ -125,6 +131,15 @@ extern "C" {
125131
profileSaver_ForceProcessProfiles = reinterpret_cast<void (*)()>(getSymCompat(art_lib_path, "_ZN3art12ProfileSaver20ForceProcessProfilesEv"));
126132
}
127133

134+
//init native hook lib
135+
void* native_hook_handle = dlopen("libsandhook-native.so", RTLD_LAZY | RTLD_GLOBAL);
136+
if (native_hook_handle) {
137+
hook_native = reinterpret_cast<void *(*)(void *, void *)>(dlsym(native_hook_handle, "SandInlineHook"));
138+
} else {
139+
hook_native = reinterpret_cast<void *(*)(void *, void *)>(getSymCompat(
140+
"libsandhook-native.so", "SandInlineHook"));
141+
}
142+
128143
}
129144

130145
bool canCompile() {
@@ -250,5 +265,40 @@ extern "C" {
250265
return true;
251266
}
252267

268+
void replaceFixupStaticTrampolines(void *thiz, void *clazz_ptr) {
269+
backup_fixup_static_trampolines(thiz, clazz_ptr);
270+
if (class_init_callback) {
271+
class_init_callback(clazz_ptr);
272+
}
273+
}
274+
275+
bool hookClassInit(void(*callback)(void*)) {
276+
void* symFixupStaticTrampolines = getSymCompat(art_lib_path, "_ZN3art11ClassLinker22FixupStaticTrampolinesENS_6ObjPtrINS_6mirror5ClassEEE");
277+
if (symFixupStaticTrampolines == nullptr || hook_native == nullptr)
278+
return false;
279+
backup_fixup_static_trampolines = reinterpret_cast<void (*)(void *, void *)>(hook_native(
280+
symFixupStaticTrampolines, (void *) replaceFixupStaticTrampolines));
281+
if (backup_fixup_static_trampolines) {
282+
class_init_callback = callback;
283+
return true;
284+
} else {
285+
return false;
286+
}
287+
}
288+
289+
JNIEnv *getEnv() {
290+
JNIEnv *env;
291+
jvm->GetEnv(reinterpret_cast<void **>(&env), JNI_VERSION_1_6);
292+
return env;
293+
}
294+
295+
JNIEnv *attachAndGetEvn() {
296+
JNIEnv *env = getEnv();
297+
if (env == nullptr) {
298+
jvm->AttachCurrentThread(&env, nullptr);
299+
}
300+
return env;
301+
}
302+
253303
}
254304

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package com.swift.sandhook;
2+
3+
import android.util.Log;
4+
5+
import com.swift.sandhook.wrapper.HookErrorException;
6+
import com.swift.sandhook.wrapper.HookWrapper;
7+
8+
import java.util.Map;
9+
import java.util.Vector;
10+
import java.util.concurrent.ConcurrentHashMap;
11+
12+
// Pending for hook static method
13+
// When Init class error!
14+
public class PendingHookHandler {
15+
16+
private static Map<Class, Vector<HookWrapper.HookEntity>> pendingHooks = new ConcurrentHashMap<>();
17+
18+
private static boolean canUsePendingHook;
19+
20+
static {
21+
//init native hook
22+
canUsePendingHook = SandHook.initForPendingHook();
23+
}
24+
25+
public static boolean canWork() {
26+
return canUsePendingHook && SandHook.canGetObject() && !SandHookConfig.DEBUG;
27+
}
28+
29+
public static synchronized void addPendingHook(HookWrapper.HookEntity hookEntity) {
30+
Vector<HookWrapper.HookEntity> entities = pendingHooks.get(hookEntity.target.getDeclaringClass());
31+
if (entities == null) {
32+
entities = new Vector<>();
33+
pendingHooks.put(hookEntity.target.getDeclaringClass(), entities);
34+
}
35+
entities.add(hookEntity);
36+
}
37+
38+
public static void onClassInit(long clazz_ptr) {
39+
if (clazz_ptr == 0)
40+
return;
41+
Class clazz = (Class) SandHook.getObject(clazz_ptr);
42+
if (clazz == null)
43+
return;
44+
Vector<HookWrapper.HookEntity> entities = pendingHooks.get(clazz);
45+
if (entities == null)
46+
return;
47+
for (HookWrapper.HookEntity entity:entities) {
48+
HookLog.w("do pending hook for method: " + entity.target.toString());
49+
try {
50+
SandHook.hook(entity);
51+
} catch (HookErrorException e) {
52+
HookLog.e("Pending Hook Error!", e);
53+
}
54+
}
55+
pendingHooks.remove(clazz);
56+
}
57+
58+
}

‎hooklib/src/main/java/com/swift/sandhook/SandHook.java

+18-7
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import com.swift.sandhook.annotation.HookMode;
66
import com.swift.sandhook.blacklist.HookBlackList;
7+
import com.swift.sandhook.utils.ClassStatusUtils;
78
import com.swift.sandhook.utils.FileUtils;
89
import com.swift.sandhook.utils.ReflectionUtils;
910
import com.swift.sandhook.utils.Unsafe;
@@ -68,10 +69,6 @@ public static void addHookClass(Class... hookWrapperClass) throws HookErrorExcep
6869
HookWrapper.addHookClass(hookWrapperClass);
6970
}
7071

71-
public static void addHookClass(ClassLoader classLoader, Class... hookWrapperClass) throws HookErrorException {
72-
HookWrapper.addHookClass(classLoader, hookWrapperClass);
73-
}
74-
7572
public static synchronized void hook(HookWrapper.HookEntity entity) throws HookErrorException {
7673

7774
if (entity == null)
@@ -90,8 +87,16 @@ public static synchronized void hook(HookWrapper.HookEntity entity) throws HookE
9087
if (HookBlackList.canNotHook(target))
9188
throw new HookErrorException("method <" + entity.target.toString() + "> can not hook, because of in blacklist!");
9289

93-
resolveStaticMethod(target);
90+
91+
if (SandHookConfig.delayHook && PendingHookHandler.canWork() && ClassStatusUtils.isStaticAndNoInited(entity.target)) {
92+
PendingHookHandler.addPendingHook(entity);
93+
return;
94+
} else {
95+
resolveStaticMethod(target);
96+
}
97+
9498
resolveStaticMethod(backup);
99+
95100
if (backup != null && entity.resolveDexCache) {
96101
SandHookMethodResolver.resolveMethod(hook, backup);
97102
}
@@ -193,17 +198,21 @@ public final static void ensureBackupMethod(Method backupMethod) {
193198
}
194199
}
195200

196-
public static void resolveStaticMethod(Member method) {
201+
public static boolean resolveStaticMethod(Member method) {
197202
//ignore result, just call to trigger resolve
198203
if (method == null)
199-
return;
204+
return true;
200205
try {
201206
if (method instanceof Method && Modifier.isStatic(method.getModifiers())) {
202207
((Method) method).setAccessible(true);
203208
((Method) method).invoke(new Object(), getFakeArgs((Method) method));
204209
}
210+
} catch (ExceptionInInitializerError classInitError) {
211+
//may need hook later
212+
return false;
205213
} catch (Throwable throwable) {
206214
}
215+
return true;
207216
}
208217

209218
private static Object[] getFakeArgs(Method method) {
@@ -367,6 +376,8 @@ public static boolean tryDisableProfile(String selfPackageName) {
367376

368377
public static native boolean setNativeEntry(Member origin, Member hook, long nativeEntry);
369378

379+
public static native boolean initForPendingHook();
380+
370381
@FunctionalInterface
371382
public interface HookModeCallBack {
372383
int hookMode(Member originMethod);

‎hooklib/src/main/java/com/swift/sandhook/SandHookConfig.java

+4-1
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,13 @@
88
public class SandHookConfig {
99

1010
public volatile static int SDK_INT = Build.VERSION.SDK_INT;
11-
public volatile static boolean DEBUG = BuildConfig.DEBUG;
11+
//Debug status of hook target process
12+
public volatile static boolean DEBUG = true;
13+
//Enable compile with jit
1214
public volatile static boolean compiler = true;
1315
public volatile static ClassLoader initClassLoader;
1416
public volatile static int curUse = 0;
17+
public volatile static boolean delayHook = true;
1518

1619
public volatile static String libSandHookPath;
1720
public volatile static LibLoader libLoader = new LibLoader() {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
package com.swift.sandhook.utils;
2+
3+
import com.swift.sandhook.SandHookConfig;
4+
5+
import java.lang.reflect.Constructor;
6+
import java.lang.reflect.Field;
7+
import java.lang.reflect.Member;
8+
import java.lang.reflect.Modifier;
9+
10+
public class ClassStatusUtils {
11+
12+
static Field fieldStatusOfClass;
13+
14+
static {
15+
try {
16+
fieldStatusOfClass = Class.class.getDeclaredField("status");
17+
fieldStatusOfClass.setAccessible(true);
18+
} catch (NoSuchFieldException e) {
19+
}
20+
}
21+
22+
public static int getClassStatus(Class clazz, boolean isUnsigned) {
23+
if (clazz == null) {
24+
return 0;
25+
}
26+
int status = 0;
27+
try {
28+
status = fieldStatusOfClass.getInt(clazz);
29+
} catch (Throwable e) {
30+
}
31+
if (isUnsigned) {
32+
status = (int) (toUnsignedLong(status) >> (32 - 4));
33+
}
34+
return status;
35+
}
36+
37+
public static long toUnsignedLong(int x) {
38+
return ((long) x) & 0xffffffffL;
39+
}
40+
41+
42+
/**
43+
* 5.0-8.0: kInitialized = 10 int
44+
* 8.1: kInitialized = 11 int
45+
* 9.0: kInitialized = 14 uint8_t
46+
*/
47+
public static boolean isInitialized(Class clazz) {
48+
if (fieldStatusOfClass == null)
49+
return true;
50+
if (SandHookConfig.SDK_INT >= 28) {
51+
return getClassStatus(clazz, true) == 14;
52+
} else if (SandHookConfig.SDK_INT == 27) {
53+
return getClassStatus(clazz, false) == 11;
54+
} else {
55+
return getClassStatus(clazz, false) == 10;
56+
}
57+
}
58+
59+
public static boolean isStaticAndNoInited(Member hookMethod) {
60+
if (hookMethod == null || hookMethod instanceof Constructor) {
61+
return false;
62+
}
63+
Class declaringClass = hookMethod.getDeclaringClass();
64+
return Modifier.isStatic(hookMethod.getModifiers())
65+
&& !ClassStatusUtils.isInitialized(declaringClass);
66+
}
67+
68+
}

‎nativehook/CMakeLists.txt

-104
This file was deleted.

‎nativehook/build.gradle

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ android {
2424

2525
externalNativeBuild {
2626
cmake {
27-
path "CMakeLists.txt"
27+
path "src/main/cpp/CMakeLists.txt"
2828
}
2929
}
3030

+104
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
# For more information about using CMake with Android Studio, read the
2+
# documentation: https://d.android.com/studio/projects/add-native-code.html
3+
4+
# Sets the minimum version of CMake required to build the native library.
5+
6+
cmake_minimum_required(VERSION 3.4.1)
7+
8+
# Creates and names a library, sets it as either STATIC
9+
# or SHARED, and provides the relative paths to its source code.
10+
# You can define multiple libraries, and CMake builds them for you.
11+
# Gradle automatically packages shared libraries with your APK.
12+
if(${CMAKE_ANDROID_ARCH_ABI} STREQUAL "arm64-v8a")
13+
set(OS_DEPENDENDED_SRC
14+
archs/arm/arm64/assembler/assembler_arm64.cpp
15+
archs/arm/arm64/inst/inst_arm64.cpp
16+
archs/arm/arm64/register/register_arm64.cpp
17+
archs/arm/arm64/register/register_list_arm64.cpp
18+
archs/arm/arm64/decoder/decoder_arm64.cpp
19+
archs/arm/arm64/relocate/code_relocate_arm64.cpp
20+
archs/arm/arm64/hook/hook_arm64.cpp)
21+
22+
elseif (${CMAKE_ANDROID_ARCH_ABI} STREQUAL "armeabi-v7a")
23+
set(OS_DEPENDENDED_SRC
24+
archs/arm/arm32/inst/inst_arm32.cpp
25+
archs/arm/arm32/inst/inst_t32.cpp
26+
archs/arm/arm32/inst/inst_t16.cpp
27+
archs/arm/arm32/register/register_arm32.cpp
28+
archs/arm/arm32/register/register_list_arm32.cpp
29+
archs/arm/arm32/assembler/assembler_arm32.cpp
30+
archs/arm/arm32/decoder/decoder_arm32.cpp
31+
archs/arm/arm32/hook/hook_arm32.cpp
32+
archs/arm/arm32/hook/breakpoint_shellcode.S
33+
archs/arm/arm32/relocate/code_relocate_arm32.cpp)
34+
endif()
35+
36+
add_library( # Sets the name of the library.
37+
sandhook-native
38+
39+
# Sets the library as a shared library.
40+
SHARED
41+
42+
# Provides a relative path to your source file(s).
43+
sandhook_native.cpp
44+
decoder/decoder.cpp
45+
relocate/code_relocate.cpp
46+
elf/elf.cpp
47+
assembler/assembler.cpp
48+
buffer/code_buffer.cpp
49+
utils/platform.cpp
50+
hook/hook.cpp
51+
${OS_DEPENDENDED_SRC})
52+
53+
54+
include_directories(
55+
asm
56+
decoder
57+
elf
58+
utils
59+
includes
60+
buffer
61+
archs/arm
62+
archs/arm/arm64/inst
63+
archs/arm/arm64/register
64+
archs/arm/arm64/decoder
65+
archs/arm/arm64/assembler
66+
archs/arm/arm64/relocate
67+
archs/arm/arm64/hook
68+
archs/arm/arm32/inst
69+
archs/arm/arm32/register
70+
archs/arm/arm32/assembler
71+
archs/arm/arm32/decoder
72+
archs/arm/arm32/hook
73+
archs/arm/arm32/relocate
74+
src/main/cpp/antihook
75+
)
76+
77+
# Searches for a specified prebuilt library and stores the path as a
78+
# variable. Because CMake includes system libraries in the search path by
79+
# default, you only need to specify the name of the public NDK library
80+
# you want to add. CMake verifies that the library exists before
81+
# completing its build.
82+
83+
find_library( # Sets the name of the path variable.
84+
log-lib
85+
86+
# Specifies the name of the NDK library that
87+
# you want CMake to locate.
88+
log)
89+
90+
# Specifies libraries CMake should link to your target library. You
91+
# can link multiple libraries, such as libraries you define in this
92+
# build script, prebuilt third-party libraries, or system libraries.
93+
94+
target_link_libraries( # Specifies the target library.
95+
sandhook-native
96+
97+
# Links the target library to the log library
98+
# included in the NDK.
99+
${log-lib})
100+
101+
102+
add_definitions(-std=c++11)
103+
104+
ENABLE_LANGUAGE(ASM)

0 commit comments

Comments
 (0)
Please sign in to comment.