diff --git a/.gitattributes b/.gitattributes
index 12c34eb..1341b04 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,3 +1,2 @@
*.prop text eol=lf
-*.sh text eol=lf
-gradle/wrapper/gradle-4.10.1-all.zip filter=lfs diff=lfs merge=lfs -text
+*.sh text eol=lf
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index e07007a..a750d98 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,7 +9,8 @@
.DS_Store
/build
/captures
-/release
+/out
.externalNativeBuild
elf-cleaner.sh
settings.gradle
+.cxx
\ No newline at end of file
diff --git a/README.md b/README.md
old mode 100644
new mode 100755
index 934e14c..209ef3b
--- a/README.md
+++ b/README.md
@@ -38,8 +38,8 @@ Magisk 版 [Xposed Fingerprint pay](https://github.com/eritpchy/Xposed-Fingerpri
## 编译
-1. 运行./gradlew :riru-module-xfingerprint-pay-taobao:zip
-2. 编译文件位于./release
+1. 运行./gradlew :module:assembleRelease
+2. 编译文件位于./out
## 致谢
diff --git a/app/.gitignore b/app/.gitignore
deleted file mode 100644
index 921d403..0000000
--- a/app/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-/build
-signing.properties
\ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
deleted file mode 100644
index 0cdeb08..0000000
--- a/app/build.gradle
+++ /dev/null
@@ -1,67 +0,0 @@
-apply plugin: 'com.android.application'
-apply plugin: 'kotlin-android-extensions'
-apply plugin: 'kotlin-android'
-
-android {
- compileSdkVersion rootProject.ext.targetSdkVersion
- defaultConfig {
- applicationId "moe.riru.manager"
- minSdkVersion rootProject.ext.minSdkVersion
- targetSdkVersion rootProject.ext.targetSdkVersion
- versionCode 4
- versionName "0.0.4"
- testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
- externalNativeBuild {
- cmake {
- abiFilters "armeabi-v7a", 'arm64-v8a', 'x86', 'x86_64'
- cppFlags "-std=c++11"
- arguments '-DANDROID_TOOLCHAIN=clang', '-DANDROID_STL=c++_static'
- }
- }
- }
- compileOptions {
- sourceCompatibility 1.8
- targetCompatibility 1.8
- }
- signingConfigs {
- sign
- }
- buildTypes {
- debug {
- signingConfig signingConfigs.sign
- }
- release {
- signingConfig signingConfigs.sign
- minifyEnabled true
- shrinkResources true
- proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
- }
- }
- externalNativeBuild {
- cmake {
- path "src/main/cpp/CMakeLists.txt"
- }
- }
- splits {
- abi {
- enable false
- }
- }
-}
-
-dependencies {
- implementation fileTree(dir: 'libs', include: ['*.jar'])
- testImplementation 'junit:junit:4.12'
- androidTestImplementation 'com.android.support.test:runner:1.0.2'
- androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
- implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
- implementation "moe.shizuku.support:recyclerview-utils:3.0.4"
- implementation "moe.shizuku.support:design:3.1.0"
- implementation "moe.shizuku.support:support-utils:3.0.4"
- implementation "moe.shizuku.support:htmlcompat:2.0.0"
-}
-repositories {
- mavenCentral()
-}
-
-apply from: project.file('signing.gradle')
\ No newline at end of file
diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro
deleted file mode 100644
index f1b4245..0000000
--- a/app/proguard-rules.pro
+++ /dev/null
@@ -1,21 +0,0 @@
-# Add project specific ProGuard rules here.
-# You can control the set of applied configuration files using the
-# proguardFiles setting in build.gradle.
-#
-# For more details, see
-# http://developer.android.com/guide/developing/tools/proguard.html
-
-# If your project uses WebView with JS, uncomment the following
-# and specify the fully qualified class name to the JavaScript interface
-# class:
-#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
-# public *;
-#}
-
-# Uncomment this to preserve the line number information for
-# debugging stack traces.
-#-keepattributes SourceFile,LineNumberTable
-
-# If you keep the line number information, uncomment this to
-# hide the original source file name.
-#-renamesourcefileattribute SourceFile
diff --git a/app/signing.gradle b/app/signing.gradle
deleted file mode 100644
index b491fd2..0000000
--- a/app/signing.gradle
+++ /dev/null
@@ -1,17 +0,0 @@
-def ksFile = project.file('signing.properties')
-def props = new Properties()
-if (ksFile.canRead()) {
- props.load(new FileInputStream(ksFile))
-
- if (props != null) {
- android.signingConfigs.sign.storeFile file(props['KEYSTORE_FILE'])
- android.signingConfigs.sign.storePassword props['KEYSTORE_PASSWORD']
- android.signingConfigs.sign.keyAlias props['KEYSTORE_ALIAS']
- android.signingConfigs.sign.keyPassword props['KEYSTORE_ALIAS_PASSWORD']
- } else {
- println 'some entries in \'signing.properties\' not found!'
- }
-} else {
- println '\'signing.properties\' not found!'
-}
-
diff --git a/app/src/androidTest/java/moe/riru/manager/ExampleInstrumentedTest.java b/app/src/androidTest/java/moe/riru/manager/ExampleInstrumentedTest.java
deleted file mode 100644
index ac6e76d..0000000
--- a/app/src/androidTest/java/moe/riru/manager/ExampleInstrumentedTest.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package moe.riru.manager;
-
-import android.content.Context;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import androidx.test.InstrumentationRegistry;
-import androidx.test.runner.AndroidJUnit4;
-
-import static org.junit.Assert.*;
-
-/**
- * Instrumented test, which will execute on an Android device.
- *
- * @see Testing documentation
- */
-@RunWith(AndroidJUnit4.class)
-public class ExampleInstrumentedTest {
- @Test
- public void useAppContext() {
- // Context of the app under test.
- Context appContext = InstrumentationRegistry.getTargetContext();
-
- assertEquals("moe.riru.manager", appContext.getPackageName());
- }
-}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
deleted file mode 100644
index be5faa8..0000000
--- a/app/src/main/AndroidManifest.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/app/src/main/cpp/CMakeLists.txt b/app/src/main/cpp/CMakeLists.txt
deleted file mode 100644
index abdefa7..0000000
--- a/app/src/main/cpp/CMakeLists.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-cmake_minimum_required(VERSION 3.4.1)
-
-set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--hash-style=both")
-
-add_library(helper SHARED
- helper.cpp pmparser.c)
-
-target_link_libraries(helper
- log)
\ No newline at end of file
diff --git a/app/src/main/cpp/helper.cpp b/app/src/main/cpp/helper.cpp
deleted file mode 100644
index c5be2bc..0000000
--- a/app/src/main/cpp/helper.cpp
+++ /dev/null
@@ -1,189 +0,0 @@
-#include
-#include
-#include
-#include
-#include
-#include
-#include "logging.h"
-
-extern "C" {
-#include "pmparser.h"
-}
-
-static jboolean is_path_in_maps(const char *path) {
- procmaps_iterator *maps = pmparser_parse(-1);
- if (maps == nullptr) {
- LOGE("[map]: cannot parse the memory map");
- return JNI_FALSE;
- }
-
- procmaps_struct *maps_tmp = nullptr;
- while ((maps_tmp = pmparser_next(maps)) != nullptr) {
- if (strstr(maps_tmp->pathname, path))
- return JNI_TRUE;
- }
- pmparser_free(maps);
- return JNI_FALSE;
-}
-
-static jboolean init(JNIEnv *env, jobject thiz) {
- procmaps_iterator *maps = pmparser_parse(-1);
- if (maps == nullptr) {
- LOGE("[map]: cannot parse the memory map");
- return JNI_FALSE;
- }
-
- jboolean res = JNI_FALSE;
- procmaps_struct *maps_tmp = nullptr;
- while ((maps_tmp = pmparser_next(maps)) != nullptr) {
- if (strstr(maps_tmp->pathname, "libmemtrack_real.so")) {
- res = JNI_TRUE;
- }
- }
- pmparser_free(maps);
- return res;
-}
-
-static jboolean is_riru_module_exists(JNIEnv *env, jobject thiz, jstring name) {
- // TODO
- return JNI_FALSE;
-}
-
-static void *handle;
-
-static void *get_handle() {
- if (handle == nullptr)
- handle = dlopen(nullptr, 0);
-
- return handle;
-}
-
-static jint get_riru_rersion(JNIEnv *env, jobject thiz) {
- static void *sym;
- void *handle;
- if ((handle = get_handle()) == nullptr) return -1;
- if (sym == nullptr) sym = dlsym(handle, "riru_get_version");
- if (sym) return ((int (*)()) sym)();
- return -1;
-}
-
-static jboolean is_zygote_methods_replaced(JNIEnv *env, jobject thiz) {
- static void *sym;
- void *handle;
- if ((handle = get_handle()) == nullptr) return JNI_FALSE;
- if (sym == nullptr) sym = dlsym(handle, "riru_is_zygote_methods_replaced");
- if (sym) return static_cast(((int (*)()) sym)());
- return JNI_FALSE;
-}
-
-static jint get_nativeForkAndSpecialize_calls_count(JNIEnv *env, jobject thiz) {
- static void *sym;
- void *handle;
- if ((handle = get_handle()) == nullptr) return -1;
- if (sym == nullptr) sym = dlsym(handle, "riru_get_nativeForkAndSpecialize_calls_count");
- if (sym) return static_cast(((int (*)()) sym)());
- return -1;
-}
-
-static jint get_nativeForkSystemServer_calls_count(JNIEnv *env, jobject thiz) {
- static void *sym;
- void *handle;
- if ((handle = get_handle()) == nullptr) return -1;
- if (sym == nullptr) sym = dlsym(handle, "riru_get_nativeForkSystemServer_calls_count");
- if (sym) return static_cast(((int (*)()) sym)());
- return -1;
-}
-
-static jstring get_nativeForkAndSpecialize_signature(JNIEnv *env, jobject thiz) {
- static void *sym;
- void *handle;
- if ((handle = get_handle()) == nullptr) return nullptr;
- if (sym == nullptr) sym = dlsym(handle, "riru_get_original_native_methods");
- if (sym) {
- auto method = ((const JNINativeMethod *(*)(const char *, const char *, const char *)) sym)(
- "com/android/internal/os/Zygote", "nativeForkAndSpecialize", nullptr);
- if (method != nullptr)
- return env->NewStringUTF(method->signature);
- }
- return nullptr;
-}
-
-static jstring get_nativeSpecializeBlastula_signature(JNIEnv *env, jobject thiz) {
- static void *sym;
- void *handle;
- if ((handle = get_handle()) == nullptr) return nullptr;
- if (sym == nullptr) sym = dlsym(handle, "riru_get_original_native_methods");
- if (sym) {
- auto method = ((const JNINativeMethod *(*)(const char *, const char *, const char *)) sym)(
- "com/android/internal/os/Zygote", "nativeSpecializeBlastula", nullptr);
- if (method != nullptr)
- return env->NewStringUTF(method->signature);
- }
- return nullptr;
-}
-
-static jstring get_nativeForkSystemServer_signature(JNIEnv *env, jobject thiz) {
- static void *sym;
- void *handle;
- if ((handle = get_handle()) == nullptr) return nullptr;
- if (sym == nullptr) sym = dlsym(handle, "riru_get_original_native_methods");
- if (sym) {
- auto method = ((const JNINativeMethod *(*)(const char *, const char *, const char *)) sym)(
- "com/android/internal/os/Zygote", "nativeForkSystemServer", nullptr);
- if (method != nullptr)
- return env->NewStringUTF(method->signature);
- }
- return nullptr;
-}
-
-static JNINativeMethod gMethods[] = {
- {"init", "()Z", (void *) init},
- {"isRiruModuleExists", "(Ljava/lang/String;)Z", (void *) is_riru_module_exists},
- {"getRiruVersion", "()I", (void *) get_riru_rersion},
- {"isZygoteMethodsReplaced", "()Z", (void *) is_zygote_methods_replaced},
- {"getNativeForkAndSpecializeCallsCount", "()I", (void *) get_nativeForkAndSpecialize_calls_count},
- {"getNativeForkSystemServerCallsCount", "()I", (void *) get_nativeForkSystemServer_calls_count},
- {"getNativeForkAndSpecializeSignature", "()Ljava/lang/String;", (void *) get_nativeForkAndSpecialize_signature},
- {"getNativeSpecializeBlastulaSignature", "()Ljava/lang/String;", (void *) get_nativeSpecializeBlastula_signature},
- {"getNativeForkSystemServerSignature", "()Ljava/lang/String;", (void *) get_nativeForkSystemServer_signature},
-};
-
-static int registerNativeMethods(JNIEnv *env, const char *className,
- JNINativeMethod *gMethods, int numMethods) {
- jclass clazz;
- clazz = env->FindClass(className);
- if (clazz == nullptr)
- return JNI_FALSE;
-
- if (env->RegisterNatives(clazz, gMethods, numMethods) < 0)
- return JNI_FALSE;
-
- return JNI_TRUE;
-}
-
-static int registerNatives(JNIEnv *env) {
- if (!registerNativeMethods(env, "moe/riru/manager/utils/NativeHelper", gMethods,
- sizeof(gMethods) / sizeof(gMethods[0])))
- return JNI_FALSE;
-
- return JNI_TRUE;
-}
-
-JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
- JNIEnv *env = nullptr;
- jint result;
-
- if (vm->GetEnv((void **) &env, JNI_VERSION_1_6) != JNI_OK)
- return -1;
-
- assert(env != nullptr);
-
- if (!registerNatives(env)) {
- LOGE("registerNatives NativeHelper");
- return -1;
- }
-
- result = JNI_VERSION_1_6;
-
- return result;
-}
diff --git a/app/src/main/cpp/logging.h b/app/src/main/cpp/logging.h
deleted file mode 100644
index e4d2307..0000000
--- a/app/src/main/cpp/logging.h
+++ /dev/null
@@ -1,22 +0,0 @@
-#ifndef _LOGGING_H
-#define _LOGGING_H
-
-#include
-#include "android/log.h"
-
-#ifndef LOG_TAG
-#define LOG_TAG "RiruManager"
-#endif
-
-//#ifdef DEBUG
-#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
-/*#else
-#define LOGD(...)
-#endif*/
-#define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)
-#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
-#define LOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)
-#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
-#define PLOGE(fmt, args...) LOGE(fmt " failed with %d: %s", ##args, errno, strerror(errno))
-
-#endif // _LOGGING_H
diff --git a/app/src/main/cpp/pmparser.c b/app/src/main/cpp/pmparser.c
deleted file mode 100644
index a07bf34..0000000
--- a/app/src/main/cpp/pmparser.c
+++ /dev/null
@@ -1,227 +0,0 @@
-/*
- @Author : ouadimjamal@gmail.com
- @date : December 2015
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation. No representations are made about the suitability of this
-software for any purpose. It is provided "as is" without express or
-implied warranty.
-*/
-
-#include "pmparser.h"
-
-/**
- * gobal variables
- */
-//procmaps_struct* g_last_head=NULL;
-//procmaps_struct* g_current=NULL;
-
-#include "android/log.h"
-
-#define printf(...) __android_log_print(ANDROID_LOG_DEBUG, "TAG", __VA_ARGS__);
-
-procmaps_iterator* pmparser_parse(int pid){
- procmaps_iterator* maps_it = malloc(sizeof(procmaps_iterator));
- char maps_path[500];
- if(pid>=0 ){
- sprintf(maps_path,"/proc/%d/maps",pid);
- }else{
- sprintf(maps_path,"/proc/self/maps");
- }
- FILE* file=fopen(maps_path,"r");
- if(!file){
- fprintf(stderr,"pmparser : cannot open the memory maps, %s\n",strerror(errno));
- return NULL;
- }
- int ind=0;char buf[PROCMAPS_LINE_MAX_LENGTH];
- int c;
- procmaps_struct* list_maps=NULL;
- procmaps_struct* tmp;
- procmaps_struct* current_node=list_maps;
- char addr1[20],addr2[20], perm[8], offset[20], dev[10],inode[30],pathname[PATH_MAX];
- while( !feof(file) ){
- fgets(buf,PROCMAPS_LINE_MAX_LENGTH,file);
- //allocate a node
- tmp=(procmaps_struct*)malloc(sizeof(procmaps_struct));
- //fill the node
- _pmparser_split_line(buf,addr1,addr2,perm,offset, dev,inode,pathname);
- //printf("#%s",buf);
- //printf("%s-%s %s %s %s %s\t%s\n",addr1,addr2,perm,offset,dev,inode,pathname);
- //addr_start & addr_end
- unsigned long l_addr_start;
- sscanf(addr1,"%lx",(long unsigned *)&tmp->addr_start );
- sscanf(addr2,"%lx",(long unsigned *)&tmp->addr_end );
- //size
- tmp->length=(unsigned long)(tmp->addr_end-tmp->addr_start);
- //perm
- strcpy(tmp->perm,perm);
- tmp->is_r=(perm[0]=='r');
- tmp->is_w=(perm[1]=='w');
- tmp->is_x=(perm[2]=='x');
- tmp->is_p=(perm[3]=='p');
-
- //offset
- sscanf(offset,"%lx",&tmp->offset );
- //device
- strcpy(tmp->dev,dev);
- //inode
- tmp->inode=atoi(inode);
- //pathname
- strcpy(tmp->pathname,pathname);
- tmp->next=NULL;
- //attach the node
- if(ind==0){
- list_maps=tmp;
- list_maps->next=NULL;
- current_node=list_maps;
- }
- current_node->next=tmp;
- current_node=tmp;
- ind++;
- //printf("%s",buf);
- }
-
- //close file
- fclose(file);
-
-
- //g_last_head=list_maps;
- maps_it->head = list_maps;
- maps_it->current = list_maps;
- return maps_it;
-}
-
-
-procmaps_struct* pmparser_next(procmaps_iterator* p_procmaps_it){
- if(p_procmaps_it->current == NULL)
- return NULL;
- procmaps_struct* p_current = p_procmaps_it->current;
- p_procmaps_it->current = p_procmaps_it->current->next;
- return p_current;
- /*
- if(g_current==NULL){
- g_current=g_last_head;
- }else
- g_current=g_current->next;
-
- return g_current;
- */
-}
-
-
-
-void pmparser_free(procmaps_iterator* p_procmaps_it){
- procmaps_struct* maps_list = p_procmaps_it->head;
- if(maps_list==NULL) return ;
- procmaps_struct* act=maps_list;
- procmaps_struct* nxt=act->next;
- while(act!=NULL){
- free(act);
- act=nxt;
- if(nxt!=NULL)
- nxt=nxt->next;
- }
-
-}
-
-
-void _pmparser_split_line(
- char*buf,char*addr1,char*addr2,
- char*perm,char* offset,char* device,char*inode,
- char* pathname){
- //
- int orig=0;
- int i=0;
- //addr1
- while(buf[i]!='-'){
- addr1[i-orig]=buf[i];
- i++;
- }
- addr1[i]='\0';
- i++;
- //addr2
- orig=i;
- while(buf[i]!='\t' && buf[i]!=' '){
- addr2[i-orig]=buf[i];
- i++;
- }
- addr2[i-orig]='\0';
-
- //perm
- while(buf[i]=='\t' || buf[i]==' ')
- i++;
- orig=i;
- while(buf[i]!='\t' && buf[i]!=' '){
- perm[i-orig]=buf[i];
- i++;
- }
- perm[i-orig]='\0';
- //offset
- while(buf[i]=='\t' || buf[i]==' ')
- i++;
- orig=i;
- while(buf[i]!='\t' && buf[i]!=' '){
- offset[i-orig]=buf[i];
- i++;
- }
- offset[i-orig]='\0';
- //dev
- while(buf[i]=='\t' || buf[i]==' ')
- i++;
- orig=i;
- while(buf[i]!='\t' && buf[i]!=' '){
- device[i-orig]=buf[i];
- i++;
- }
- device[i-orig]='\0';
- //inode
- while(buf[i]=='\t' || buf[i]==' ')
- i++;
- orig=i;
- while(buf[i]!='\t' && buf[i]!=' '){
- inode[i-orig]=buf[i];
- i++;
- }
- inode[i-orig]='\0';
- //pathname
- pathname[0]='\0';
- while(buf[i]=='\t' || buf[i]==' ')
- i++;
- orig=i;
- while(buf[i]!='\t' && buf[i]!=' ' && buf[i]!='\n'){
- pathname[i-orig]=buf[i];
- i++;
- }
- pathname[i-orig]='\0';
-
-}
-
-void pmparser_print(procmaps_struct* map, int order){
-
- procmaps_struct* tmp=map;
- int id=0;
- if(order<0) order=-1;
- while(tmp!=NULL){
- //(unsigned long) tmp->addr_start;
- if(order==id || order==-1){
- printf("Backed by:\t%s\n",strlen(tmp->pathname)==0?"[anonym*]":tmp->pathname);
- printf("Range:\t\t%p-%p\n",tmp->addr_start,tmp->addr_end);
- printf("Length:\t\t%ld\n",tmp->length);
- printf("Offset:\t\t%ld\n",tmp->offset);
- printf("Permissions:\t%s\n",tmp->perm);
- printf("Inode:\t\t%d\n",tmp->inode);
- printf("Device:\t\t%s\n",tmp->dev);
- }
- if(order!=-1 && id>order)
- tmp=NULL;
- else if(order==-1){
- printf("#################################\n");
- tmp=tmp->next;
- }else tmp=tmp->next;
-
- id++;
- }
-}
diff --git a/app/src/main/cpp/pmparser.h b/app/src/main/cpp/pmparser.h
deleted file mode 100644
index 1162470..0000000
--- a/app/src/main/cpp/pmparser.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- @Author : ouadimjamal@gmail.com
- @date : December 2015
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation. No representations are made about the suitability of this
-software for any purpose. It is provided "as is" without express or
-implied warranty.
-
- */
-
-#ifndef H_PMPARSER
-#define H_PMPARSER
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-//maximum line length in a procmaps file
-#define PROCMAPS_LINE_MAX_LENGTH (PATH_MAX + 100)
-/**
- * procmaps_struct
- * @desc hold all the information about an area in the process's VM
- */
-typedef struct procmaps_struct{
- void* addr_start; //< start address of the area
- void* addr_end; //< end address
- unsigned long length; //< size of the range
-
- char perm[5]; //< permissions rwxp
- short is_r; //< rewrote of perm with short flags
- short is_w;
- short is_x;
- short is_p;
-
- long offset; //< offset
- char dev[12]; //< dev major:minor
- int inode; //< inode of the file that backs the area
-
- char pathname[600]; //< the path of the file that backs the area
- //chained list
- struct procmaps_struct* next; //");
-
- if (isZygoteMethodsReplaced) {
- sb.append("Native methods of Zygote class replaced.").append("
")
- .append("nativeForkAndSpecialize calls count: ").append(nativeForkAndSpecializeCallsCount).append("
")
- .append("nativeForkSystemServer calls count: ").append(nativeForkSystemServerCallsCount).append("
");
-
- if (nativeForkAndSpecializeCallsCount == 0) {
- sb.append("
nativeForkAndSpecialize calls count is 0, Riru is not working correctly.
This may because Riru's hook is overwritten by other things, please check yourself.");
- } else if (nativeForkSystemServerCallsCount != 0) {
- sb.append("
Everything looks fine :D");
- }
- } else {
- sb.append("However, native methods of Zygote class not replaced, please contact developer with the following information.").append("
")
- .append("nativeForkAndSpecializeSignature:
").append(nativeForkAndSpecializeSignature).append("
")
- .append("getNativeForkSystemServerSignature:
").append(nativeForkSystemServerSignature).append("");
- }
- }
- } else {
- sb.append("Riru not found in memory.");
- }
-
- new AlertDialog.Builder(this)
- .setMessage(HtmlCompat.fromHtml(sb.toString()))
- .setPositiveButton(android.R.string.ok, (dialog, which) -> {
- finish();
- })
- .setNeutralButton("Copy", (dialog, which) -> {
- getSystemService(ClipboardManager.class).setPrimaryClip(ClipData.newPlainText("text", HtmlCompat.fromHtml(sb.toString()).toString()));
- finish();
- })
- .setCancelable(false)
- .show();
-
- Log.i("RiruManager", "init: " + NativeHelper.init());
- Log.i("RiruManager", "getRiruVersion: " + NativeHelper.getRiruVersion());
- Log.i("RiruManager", "isZygoteMethodsReplaced: " + NativeHelper.isZygoteMethodsReplaced());
- Log.i("RiruManager", "getNativeForkAndSpecializeCallsCount: " + NativeHelper.getNativeForkAndSpecializeCallsCount());
- Log.i("RiruManager", "getNativeForkSystemServerCallsCount: " + NativeHelper.getNativeForkSystemServerCallsCount());
- Log.i("RiruManager", "getNativeForkAndSpecializeSignature: " + NativeHelper.getNativeForkAndSpecializeSignature());
- Log.i("RiruManager", "getNativeSpecializeBlastulaSignature: " + NativeHelper.getNativeSpecializeBlastulaSignature());
- Log.i("RiruManager", "getNativeForkSystemServerSignature: " + NativeHelper.getNativeForkSystemServerSignature());
- }
-}
diff --git a/app/src/main/java/moe/riru/manager/app/BaseActivity.java b/app/src/main/java/moe/riru/manager/app/BaseActivity.java
deleted file mode 100644
index 3494493..0000000
--- a/app/src/main/java/moe/riru/manager/app/BaseActivity.java
+++ /dev/null
@@ -1,6 +0,0 @@
-package moe.riru.manager.app;
-
-import android.app.Activity;
-
-public abstract class BaseActivity extends Activity {
-}
diff --git a/app/src/main/java/moe/riru/manager/utils/BuildUtils.java b/app/src/main/java/moe/riru/manager/utils/BuildUtils.java
deleted file mode 100644
index 05b4f8a..0000000
--- a/app/src/main/java/moe/riru/manager/utils/BuildUtils.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package moe.riru.manager.utils;
-
-import android.os.Build;
-
-public class BuildUtils {
-
- public static boolean isQ() {
- return "Q".equals(Build.VERSION.RELEASE) || Build.VERSION.SDK_INT >= 29;
- }
-}
diff --git a/app/src/main/java/moe/riru/manager/utils/NativeHelper.java b/app/src/main/java/moe/riru/manager/utils/NativeHelper.java
deleted file mode 100644
index 4d054f5..0000000
--- a/app/src/main/java/moe/riru/manager/utils/NativeHelper.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package moe.riru.manager.utils;
-
-import android.content.Context;
-
-import androidx.annotation.Keep;
-import moe.riru.manager.R;
-
-@Keep
-public class NativeHelper {
-
- private static final int MAX_VERSION = 19;
- private static final int V18 = 19;
- private static final int V17_1 = 18;
-
- static {
- System.loadLibrary("helper");
- }
-
- public static String versionName(Context context, int versionCode) {
- if (versionCode > MAX_VERSION) {
- return context.getString(R.string.riru_unknown_version, versionCode);
- }
-
- if (versionCode <= 0) {
- return context.getString(R.string.riru_not_found);
- }
-
- switch (versionCode) {
- case V18:
- return "v18";
- case V17_1:
- return "v17.1";
- default:
- return "v" + versionCode;
- }
- }
-
- public static native boolean init();
- public static native boolean isRiruModuleExists(String name);
- public static native int getRiruVersion();
- public static native boolean isZygoteMethodsReplaced();
- public static native int getNativeForkAndSpecializeCallsCount();
- public static native int getNativeForkSystemServerCallsCount();
- public static native String getNativeForkAndSpecializeSignature();
- public static native String getNativeSpecializeBlastulaSignature();
- public static native String getNativeForkSystemServerSignature();
-}
diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
deleted file mode 100644
index 1f6bb29..0000000
--- a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml
deleted file mode 100644
index 0d025f9..0000000
--- a/app/src/main/res/drawable/ic_launcher_background.xml
+++ /dev/null
@@ -1,170 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
deleted file mode 100644
index eca70cf..0000000
--- a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
deleted file mode 100644
index eca70cf..0000000
--- a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/src/main/res/mipmap-hdpi/ic_launcher.png
deleted file mode 100644
index 898f3ed..0000000
Binary files a/app/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ
diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
deleted file mode 100644
index dffca36..0000000
Binary files a/app/src/main/res/mipmap-hdpi/ic_launcher_round.png and /dev/null differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.png b/app/src/main/res/mipmap-mdpi/ic_launcher.png
deleted file mode 100644
index 64ba76f..0000000
Binary files a/app/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
deleted file mode 100644
index dae5e08..0000000
Binary files a/app/src/main/res/mipmap-mdpi/ic_launcher_round.png and /dev/null differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/app/src/main/res/mipmap-xhdpi/ic_launcher.png
deleted file mode 100644
index e5ed465..0000000
Binary files a/app/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
deleted file mode 100644
index 14ed0af..0000000
Binary files a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png and /dev/null differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
deleted file mode 100644
index b0907ca..0000000
Binary files a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
deleted file mode 100644
index d8ae031..0000000
Binary files a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
deleted file mode 100644
index 2c18de9..0000000
Binary files a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
deleted file mode 100644
index beed3cd..0000000
Binary files a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ
diff --git a/app/src/main/res/values-night/styles.xml b/app/src/main/res/values-night/styles.xml
deleted file mode 100644
index e0357ab..0000000
--- a/app/src/main/res/values-night/styles.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml
deleted file mode 100644
index 04a8a1b..0000000
--- a/app/src/main/res/values-zh-rCN/strings.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
- 未安装/未被载入
- 未知(版本号 %d)
-
\ No newline at end of file
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
deleted file mode 100644
index 69b2233..0000000
--- a/app/src/main/res/values/colors.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
- #008577
- #00574B
- #D81B60
-
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
deleted file mode 100644
index 8785f8c..0000000
--- a/app/src/main/res/values/strings.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-
- Riru
- Not installed / not loaded
- Unknown (version code %d)
-
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
deleted file mode 100644
index 3844883..0000000
--- a/app/src/main/res/values/styles.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml
deleted file mode 100644
index e019f41..0000000
--- a/app/src/main/res/values/themes.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/test/java/moe/riru/manager/ExampleUnitTest.java b/app/src/test/java/moe/riru/manager/ExampleUnitTest.java
deleted file mode 100644
index d412db0..0000000
--- a/app/src/test/java/moe/riru/manager/ExampleUnitTest.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package moe.riru.manager;
-
-import org.junit.Test;
-
-import static org.junit.Assert.*;
-
-/**
- * Example local unit test, which will execute on the development machine (host).
- *
- * @see Testing documentation
- */
-public class ExampleUnitTest {
- @Test
- public void addition_isCorrect() {
- assertEquals(4, 2 + 2);
- }
-}
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
old mode 100644
new mode 100755
index 2a3d2fa..7cea681
--- a/build.gradle
+++ b/build.gradle
@@ -1,18 +1,18 @@
-// Top-level build file where you can add configuration options common to all sub-projects/modules.
+apply plugin: 'idea'
-buildscript {
- ext.kotlin_version = '1.3.21'
+idea.module {
+ excludeDirs += file('out')
+ resourceDirs += file('template')
+ resourceDirs += file('scripts')
+}
+buildscript {
repositories {
google()
jcenter()
}
dependencies {
- classpath 'com.android.tools.build:gradle:3.3.2'
- classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
-
- // NOTE: Do not place your application dependencies here; they belong
- // in the individual module build.gradle files
+ classpath 'com.android.tools.build:gradle:3.5.3'
}
}
@@ -20,7 +20,6 @@ allprojects {
repositories {
google()
jcenter()
- maven { url 'https://dl.bintray.com/rikkaw/Libraries' }
}
}
@@ -30,5 +29,5 @@ task clean(type: Delete) {
ext {
minSdkVersion = 23
- targetSdkVersion = 28
-}
\ No newline at end of file
+ targetSdkVersion = 29
+}
diff --git a/build.sh b/build.sh
deleted file mode 100644
index a07598a..0000000
--- a/build.sh
+++ /dev/null
@@ -1,62 +0,0 @@
-#!/bin/bash
-MODULE_NAME=$1
-shift
-if [ "$MODULE_NAME" == "" ]; then
- echo "Usage: sh build.sh []"
- exit 1
-fi
-
-if [ ! -d "$MODULE_NAME" ]; then
- echo "$MODULE_NAME not exists"
- exit 1
-fi
-
-VERSION=$1
-shift
-[[ "$VERSION" == "" ]] && VERSION=v1
-
-LIBS_OUTPUT=$MODULE_NAME/build/ndkBuild/libs
-NDK_OUT=$MODULE_NAME/build/ndkBuild/obj
-
-# build
-NDK_BUILD=ndk-build
-[[ "$OSTYPE" == "msys" ]] && NDK_BUILD=ndk-build.cmd
-[[ "$OSTYPE" == "cygwin" ]] && NDK_BUILD=ndk-build.cmd
-
-$NDK_BUILD -C $MODULE_NAME NDK_LIBS_OUT=build/ndkBuild/libs NDK_OUT=build/ndkBuild/obj $@
-
-# create tmp dir
-TMP_DIR=build/zip
-TMP_DIR_MAGISK=$TMP_DIR/magisk
-
-rm -rf $TMP_DIR
-mkdir -p $TMP_DIR
-
-cp -a template/magisk/. $TMP_DIR_MAGISK
-
-# copy files
-mkdir -p $TMP_DIR_MAGISK/system/lib64
-mkdir -p $TMP_DIR_MAGISK/system/lib
-mkdir -p $TMP_DIR_MAGISK/system_x86/lib64
-mkdir -p $TMP_DIR_MAGISK/system_x86/lib
-cp -a $LIBS_OUTPUT/arm64-v8a/. $TMP_DIR_MAGISK/system/lib64
-cp -a $LIBS_OUTPUT/armeabi-v7a/. $TMP_DIR_MAGISK/system/lib
-[[ -d $LIBS_OUTPUT/x86_64 ]] && cp -a $LIBS_OUTPUT/x86_64/. $TMP_DIR_MAGISK/system_x86/lib64
-[[ -d $LIBS_OUTPUT/x86 ]] && cp -a $LIBS_OUTPUT/x86/. $TMP_DIR_MAGISK/system_x86/lib
-
-# run custom script
-if [ -f $MODULE_NAME/build.sh ]; then
- source $MODULE_NAME/build.sh
- copy_files
-fi
-
-# zip
-mkdir -p release
-ZIP_NAME=magisk-$MODULE_NAME-"$VERSION".zip
-rm -f release/$ZIP_NAME
-rm -f $TMP_DIR_MAGISK/$ZIP_NAME
-(cd $TMP_DIR_MAGISK; zip -r $ZIP_NAME * > /dev/null)
-mv $TMP_DIR_MAGISK/$ZIP_NAME release/$ZIP_NAME
-
-# clean tmp dir
-rm -rf $TMP_DIR
diff --git a/gradle.properties b/gradle.properties
old mode 100644
new mode 100755
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
old mode 100644
new mode 100755
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
old mode 100644
new mode 100755
index 1b7ea6b..30b572c
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,5 @@
-#Thu Feb 14 15:40:39 CST 2019
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.1-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.0.1-all.zip
diff --git a/gradlew.bat b/gradlew.bat
old mode 100644
new mode 100755
diff --git a/riru-core/.gitignore b/module/.gitignore
old mode 100644
new mode 100755
similarity index 100%
rename from riru-core/.gitignore
rename to module/.gitignore
diff --git a/module/build.gradle b/module/build.gradle
new file mode 100755
index 0000000..c44eca4
--- /dev/null
+++ b/module/build.gradle
@@ -0,0 +1,123 @@
+apply plugin: 'com.android.library'
+
+android {
+ compileSdkVersion rootProject.ext.targetSdkVersion
+ defaultConfig {
+ minSdkVersion rootProject.ext.minSdkVersion
+ targetSdkVersion rootProject.ext.targetSdkVersion
+ ndk {
+ abiFilters "armeabi-v7a", 'arm64-v8a', 'x86', 'x86_64'
+ }
+ }
+ externalNativeBuild {
+ cmake {
+ path "src/main/cpp/CMakeLists.txt"
+ version "3.9.1"
+ }
+ }
+}
+
+def moduleId = "module_xfingerprint_pay_taobao"
+def moduleProp = [
+ name : "指纹支付 - 淘宝",
+ version : "v3.9.6",
+ versionCode: "1",
+ author : "Jason Eric",
+ description: "让淘宝支持指纹支付 Fingerprint pay for Taobao.",
+ api : 4
+]
+
+def magiskModuleProp = [
+ id : "riru-${moduleId.replace('_', '-')}",
+ name : "Riru - ${moduleProp['name']}",
+ version : moduleProp['version'],
+ versionCode: moduleProp['versionCode'],
+ author : moduleProp['author'],
+ description: moduleProp['description']
+]
+
+def outDir = file("$rootDir/out")
+def magiskDir = file("$outDir/magisk_module")
+def zipName = "magisk-${magiskModuleProp['id']}-${magiskModuleProp['version']}.zip"
+def riruDir = "$magiskDir/data/misc/riru/modules/${moduleId}"
+
+import java.nio.file.Files
+import java.security.MessageDigest
+
+static def calcSha256(file) {
+ def md = MessageDigest.getInstance("SHA-256")
+ file.eachByte 4096, { bytes, size ->
+ md.update(bytes, 0, size);
+ }
+ return md.digest().encodeHex()
+}
+
+static def renameOrFail(File from, File to) {
+ if (!from.renameTo(to)) {
+ throw new IOException("Unable reanme file $from to $to")
+ }
+}
+
+android.libraryVariants.all { variant ->
+ def task = variant.assembleProvider.get()
+ task.doLast {
+ // clear
+ delete { delete magiskDir }
+
+ // copy from template
+ copy {
+ from "$rootDir/template/magisk_module"
+ into magiskDir.path
+ }
+ // copy .git files manually since gradle exclude it by default
+ Files.copy(file("$rootDir/template/magisk_module/.gitattributes").toPath(), file("${magiskDir.path}/.gitattributes").toPath())
+
+ // generate module.prop
+ def modulePropText = ""
+ magiskModuleProp.each { k, v -> modulePropText += "$k=$v\n" }
+ modulePropText = modulePropText.trim()
+ file("$magiskDir/module.prop").text = modulePropText
+
+ // generate module.prop for Riru
+ def riruModulePropText = ""
+ moduleProp.each { k, v -> riruModulePropText += "$k=$v\n" }
+ riruModulePropText = riruModulePropText.trim()
+ file(riruDir).mkdirs()
+
+ // module.prop.new will be renamed to module.prop in post-fs-data.sh
+ file("$riruDir/module.prop.new").text = riruModulePropText
+
+ // copy native files
+ def nativeOutDir = file("build/intermediates/cmake/$variant.name/obj")
+
+ file("$magiskDir/system").mkdirs()
+ file("$magiskDir/system_x86").mkdirs()
+ renameOrFail(file("$nativeOutDir/arm64-v8a"), file("$magiskDir/system/lib64"))
+ renameOrFail(file("$nativeOutDir/armeabi-v7a"), file("$magiskDir/system/lib"))
+ renameOrFail(file("$nativeOutDir/x86_64"), file("$magiskDir/system_x86/lib64"))
+ renameOrFail(file("$nativeOutDir/x86"), file("$magiskDir/system_x86/lib"))
+
+ file("$magiskDir/system/framework").mkdirs()
+ copy {
+ from zipTree('libs/fingerprint-pay-taobao-magisk.apk')
+ rename('classes.dex', 'libxfingerprint_pay_taobao.dex')
+ into file("$magiskDir/system/framework")
+ include 'classes.dex'
+ }
+
+ // generate sha1sum
+ fileTree("$magiskDir").matching {
+ exclude "README.md", "META-INF"
+ }.visit { f ->
+ if (f.directory) return
+ file(f.file.path + ".sha256sum").text = calcSha256(f.file)
+ }
+ }
+ task.finalizedBy zipMagiskMoudle
+}
+
+task zipMagiskMoudle(type: Zip) {
+ from magiskDir
+ archiveName zipName
+ destinationDir outDir
+}
\ No newline at end of file
diff --git a/module/libs/fingerprint-pay-taobao-magisk.apk b/module/libs/fingerprint-pay-taobao-magisk.apk
new file mode 100644
index 0000000..91c48ca
Binary files /dev/null and b/module/libs/fingerprint-pay-taobao-magisk.apk differ
diff --git a/module/src/main/AndroidManifest.xml b/module/src/main/AndroidManifest.xml
new file mode 100755
index 0000000..235c657
--- /dev/null
+++ b/module/src/main/AndroidManifest.xml
@@ -0,0 +1 @@
+
diff --git a/module/src/main/cpp/CMakeLists.txt b/module/src/main/cpp/CMakeLists.txt
new file mode 100755
index 0000000..8930277
--- /dev/null
+++ b/module/src/main/cpp/CMakeLists.txt
@@ -0,0 +1,27 @@
+cmake_minimum_required(VERSION 3.4.1)
+
+set(MODULE_NAME "riru_module_xfingerprint_pay_taobao")
+
+message("Build type: ${CMAKE_BUILD_TYPE}")
+
+set(CMAKE_CXX_STANDARD 11)
+
+set(LINKER_FLAGS "-ffixed-x18 -Wl,--hash-style=both")
+set(C_FLAGS "-Werror=format -fdata-sections -ffunction-sections")
+
+if (CMAKE_BUILD_TYPE STREQUAL "Release")
+ set(C_FLAGS "${C_FLAGS} -O2 -fvisibility=hidden -fvisibility-inlines-hidden")
+ set(LINKER_FLAGS "${LINKER_FLAGS} -Wl,-exclude-libs,ALL -Wl,--gc-sections")
+else ()
+ set(C_FLAGS "${C_FLAGS} -O0")
+endif ()
+
+set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_FLAGS}")
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${C_FLAGS}")
+
+set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${LINKER_FLAGS}")
+set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${LINKER_FLAGS}")
+
+add_library(${MODULE_NAME} SHARED main.cpp)
+target_link_libraries(${MODULE_NAME} log)
+set_target_properties(${MODULE_NAME} PROPERTIES LINK_FLAGS_RELEASE -s)
diff --git a/riru-module-xfingerprint-pay-taobao/jni/main/log.h b/module/src/main/cpp/log.h
similarity index 100%
rename from riru-module-xfingerprint-pay-taobao/jni/main/log.h
rename to module/src/main/cpp/log.h
diff --git a/riru-module-xfingerprint-pay-taobao/jni/main/main.cpp b/module/src/main/cpp/main.cpp
old mode 100644
new mode 100755
similarity index 63%
rename from riru-module-xfingerprint-pay-taobao/jni/main/main.cpp
rename to module/src/main/cpp/main.cpp
index a6977aa..cb05473
--- a/riru-module-xfingerprint-pay-taobao/jni/main/main.cpp
+++ b/module/src/main/cpp/main.cpp
@@ -1,8 +1,8 @@
#include
#include
+#include
#include
#include
-#include
#include "log.h"
@@ -90,43 +90,49 @@ static void loadDex(JNIEnv *env, jstring jdexPath, jstring jodexPath, jstring jc
env->CallStaticVoidMethod(javaClientClass, targetMethod, jarg1);
}
+
+// You can remove functions you don't need
+
extern "C" {
-__attribute__((visibility("default")))
-void nativeForkAndSpecializePre(
- JNIEnv *env, jclass clazz, jint *_uid, jint *gid, jintArray *gids, jint *,
- jobjectArray *rlimits, jint *_mount_external, jstring *se_info, jstring *jse_name,
+#define EXPORT __attribute__((visibility("default"))) __attribute__((used))
+EXPORT void nativeForkAndSpecializePre(
+ JNIEnv *env, jclass clazz, jint *_uid, jint *gid, jintArray *gids, jint *runtimeFlags,
+ jobjectArray *rlimits, jint *mountExternal, jstring *seInfo, jstring *niceName,
jintArray *fdsToClose, jintArray *fdsToIgnore, jboolean *is_child_zygote,
- jstring *instructionSet, jstring *jappDataDir, jstring *packageName,
- jobjectArray *packagesForUID, jobjectArray *visibleVolIDs) {
- // packageName, packagesForUID, visibleVolIDs exists from Android Q
- char *appDataDir = jstringToC(env, *jappDataDir);
- if (appDataDir == NULL) {
+ jstring *instructionSet, jstring *appDataDir, jstring *packageName,
+ jobjectArray *packagesForUID, jstring *sandboxId) {
+ // packageName, packagesForUID, sandboxId are added from Android Q beta 2, removed from beta 5
+ char *cAppDataDir = jstringToC(env, *appDataDir);
+ if (cAppDataDir == NULL) {
LOGD("MEM ERR");
return;
}
- sAppDataDir = strdup(appDataDir);
- free(appDataDir);
+ sAppDataDir = strdup(cAppDataDir);
+ free(cAppDataDir);
if (sAppDataDir == NULL) {
LOGD("MEM ERR");
return;
}
- char *niceName = jstringToC(env, *jse_name);
- sHookEnable = equals(niceName, "com.taobao.taobao");
- if (niceName) {
- free(niceName);
+ char *cNiceName = jstringToC(env, *niceName);
+ sHookEnable = equals(cNiceName, "com.taobao.taobao");
+ if (cNiceName) {
+ free(cNiceName);
}
}
-__attribute__((visibility("default")))
-int nativeForkAndSpecializePost(JNIEnv *env, jclass clazz, jint res) {
+EXPORT int nativeForkAndSpecializePost(JNIEnv *env, jclass clazz, jint res) {
if (res == 0) {
// in app process
if (sHookEnable) {
char appCacheDir[PATH_MAX] = {0};
snprintf(appCacheDir, PATH_MAX - 1, "%s/cache", sAppDataDir);
- loadDex(env,
- env->NewStringUTF("/system/framework/libxfingerprint_pay_taobao.dex"),
+ const char *dexPath = "/data/local/tmp/libxfingerprint_pay_taobao.dex";
+ if (access(dexPath, 0) != 0) {
+ dexPath = "/system/framework/libxfingerprint_pay_taobao.dex";
+ }
+ loadDex(env,
+ env->NewStringUTF(dexPath),
env->NewStringUTF(appCacheDir),
env->NewStringUTF("com.yyxx.wechatfp.xposed.plugin.XposedTaobaoPlugin"),
"main",
@@ -140,15 +146,29 @@ int nativeForkAndSpecializePost(JNIEnv *env, jclass clazz, jint res) {
return 0;
}
-__attribute__((visibility("default")))
-void nativeForkSystemServerPre(
- JNIEnv *env, jclass clazz, uid_t *uid, gid_t *gid, jintArray *gids, jint *debug_flags,
+EXPORT __attribute__((visibility("default"))) void specializeAppProcessPre(
+ JNIEnv *env, jclass clazz, jint *_uid, jint *gid, jintArray *gids, jint *runtimeFlags,
+ jobjectArray *rlimits, jint *mountExternal, jstring *seInfo, jstring *niceName,
+ jboolean *startChildZygote, jstring *instructionSet, jstring *appDataDir,
+ jstring *packageName, jobjectArray *packagesForUID, jstring *sandboxId) {
+ // this is added from Android Q beta, but seems Google disabled this in following updates
+
+ // packageName, packagesForUID, sandboxId are added from Android Q beta 2, removed from beta 5
+}
+
+EXPORT __attribute__((visibility("default"))) int specializeAppProcessPost(
+ JNIEnv *env, jclass clazz) {
+ // this is added from Android Q beta, but seems Google disabled this in following updates
+ return 0;
+}
+
+EXPORT void nativeForkSystemServerPre(
+ JNIEnv *env, jclass clazz, uid_t *uid, gid_t *gid, jintArray *gids, jint *runtimeFlags,
jobjectArray *rlimits, jlong *permittedCapabilities, jlong *effectiveCapabilities) {
}
-__attribute__((visibility("default")))
-int nativeForkSystemServerPost(JNIEnv *env, jclass clazz, jint res) {
+EXPORT int nativeForkSystemServerPost(JNIEnv *env, jclass clazz, jint res) {
if (res == 0) {
// in system server process
} else {
@@ -157,4 +177,14 @@ int nativeForkSystemServerPost(JNIEnv *env, jclass clazz, jint res) {
}
return 0;
}
+
+EXPORT int shouldSkipUid(int uid) {
+ // by default, Riru only call module functions in "normal app processes" (10000 <= uid % 100000 <= 19999)
+ // false = don't skip
+ return false;
+}
+
+EXPORT void onModuleLoaded() {
+ // called when the shared library of Riru core is loaded
}
+}
\ No newline at end of file
diff --git a/riru-core/build.gradle b/riru-core/build.gradle
deleted file mode 100644
index 0626b5f..0000000
--- a/riru-core/build.gradle
+++ /dev/null
@@ -1,26 +0,0 @@
-apply plugin: 'com.android.library'
-
-android {
- compileSdkVersion rootProject.ext.targetSdkVersion
- defaultConfig {
- minSdkVersion rootProject.ext.minSdkVersion
- targetSdkVersion rootProject.ext.targetSdkVersion
-
- externalNativeBuild {
- ndkBuild {
- abiFilters 'arm64-v8a', 'armeabi-v7a'
- arguments "NDK_PROJECT_PATH=jni/"
- }
- }
- }
- externalNativeBuild {
- ndkBuild {
- path 'jni/Android.mk'
- }
- }
-}
-
-task zip(type: Exec) {
- workingDir '..'
- commandLine 'sh', 'build.sh', project.name, 'v18'
-}
\ No newline at end of file
diff --git a/riru-core/build.sh b/riru-core/build.sh
deleted file mode 100644
index 9da4118..0000000
--- a/riru-core/build.sh
+++ /dev/null
@@ -1,12 +0,0 @@
-function copy_files {
- cp $MODULE_NAME/template_override/config.sh $TMP_DIR_MAGISK
- cp $MODULE_NAME/template_override/module.prop $TMP_DIR_MAGISK
-
- mkdir -p $TMP_DIR_MAGISK/common
- cp $MODULE_NAME/template_override/post-fs-data.sh $TMP_DIR_MAGISK/common/post-fs-data.sh
-
- mv $TMP_DIR_MAGISK/system/lib/zygote_restart $TMP_DIR_MAGISK/zygote_restart_arm
- mv $TMP_DIR_MAGISK/system/lib64/zygote_restart $TMP_DIR_MAGISK/zygote_restart_arm64
- mv $TMP_DIR_MAGISK/system_x86/lib/zygote_restart $TMP_DIR_MAGISK/zygote_restart_x86
- mv $TMP_DIR_MAGISK/system_x86/lib64/zygote_restart $TMP_DIR_MAGISK/zygote_restart_x64
-}
\ No newline at end of file
diff --git a/riru-core/jni/.gitattributes b/riru-core/jni/.gitattributes
deleted file mode 100644
index 63f9e34..0000000
--- a/riru-core/jni/.gitattributes
+++ /dev/null
@@ -1 +0,0 @@
-libs/** binary
diff --git a/riru-core/jni/Android.mk b/riru-core/jni/Android.mk
deleted file mode 100644
index 16d6dcf..0000000
--- a/riru-core/jni/Android.mk
+++ /dev/null
@@ -1,3 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-include $(call all-makefiles-under, $(LOCAL_PATH))
\ No newline at end of file
diff --git a/riru-core/jni/Application.mk b/riru-core/jni/Application.mk
deleted file mode 100644
index 8d914af..0000000
--- a/riru-core/jni/Application.mk
+++ /dev/null
@@ -1,21 +0,0 @@
-APP_ABI := arm64-v8a armeabi-v7a x86 x86_64
-APP_PLATFORM := android-23
-APP_CFLAGS := -std=gnu99
-APP_CPPFLAGS := -std=c++11
-APP_STL := c++_static
-APP_SHORT_COMMANDS := true
-
-SCS_FLAGS := -ffixed-x18
-APP_LDFLAGS += $(SCS_FLAGS)
-APP_CFLAGS += $(SCS_FLAGS)
-APP_CPPFLAGS += $(SCS_FLAGS)
-
-ifeq ($(NDK_DEBUG),1)
-$(info building DEBUG version...)
-APP_CFLAGS += -O0
-APP_CPPFLAGS += -O0
-else
-$(info building RELEASE version...)
-APP_CFLAGS += -fvisibility=hidden -fvisibility-inlines-hidden -O2
-APP_CPPFLAGS += -fvisibility=hidden -fvisibility-inlines-hidden -O2
-endif
\ No newline at end of file
diff --git a/riru-core/jni/external/Android.mk b/riru-core/jni/external/Android.mk
deleted file mode 100644
index 04d3e48..0000000
--- a/riru-core/jni/external/Android.mk
+++ /dev/null
@@ -1,15 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := xhook
-LOCAL_SRC_FILES := xhook/xhook.c \
- xhook/xh_core.c \
- xhook/xh_elf.c \
- xhook/xh_jni.c \
- xhook/xh_log.c \
- xhook/xh_util.c \
- xhook/xh_version.c
-LOCAL_C_INCLUDES := $(LOCAL_PATH)
-LOCAL_CFLAGS := -Wall -Wextra -Werror -fvisibility=hidden
-LOCAL_CONLYFLAGS := -std=c11
-include $(BUILD_STATIC_LIBRARY)
\ No newline at end of file
diff --git a/riru-core/jni/external/include/xhook/xhook.h b/riru-core/jni/external/include/xhook/xhook.h
deleted file mode 100644
index 93dd5b4..0000000
--- a/riru-core/jni/external/include/xhook/xhook.h
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright (c) 2018-present, iQIYI, Inc. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
-
-// Created by caikelun on 2018-04-11.
-
-#ifndef XHOOK_H
-#define XHOOK_H 1
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define XHOOK_EXPORT __attribute__((visibility("default")))
-
-int xhook_register(const char *pathname_regex_str, const char *symbol,
- void *new_func, void **old_func) XHOOK_EXPORT;
-
-int xhook_ignore(const char *pathname_regex_str, const char *symbol) XHOOK_EXPORT;
-
-int xhook_refresh(int async) XHOOK_EXPORT;
-
-void xhook_clear() XHOOK_EXPORT;
-
-void xhook_enable_debug(int flag) XHOOK_EXPORT;
-
-void xhook_enable_sigsegv_protection(int flag) XHOOK_EXPORT;
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/riru-core/jni/external/xhook/queue.h b/riru-core/jni/external/xhook/queue.h
deleted file mode 100644
index c2443be..0000000
--- a/riru-core/jni/external/xhook/queue.h
+++ /dev/null
@@ -1,554 +0,0 @@
-/*-
- * Copyright (c) 1991, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)queue.h 8.5 (Berkeley) 8/20/94
- * $FreeBSD: stable/9/sys/sys/queue.h 252365 2013-06-29 04:25:40Z lstewart $
- */
-
-#ifndef QUEUE_H
-#define QUEUE_H
-
-/* #include */
-#define __containerof(ptr, type, field) ((type *)((char *)(ptr) - ((char *)&((type *)0)->field)))
-
-/*
- * This file defines four types of data structures: singly-linked lists,
- * singly-linked tail queues, lists and tail queues.
- *
- * A singly-linked list is headed by a single forward pointer. The elements
- * are singly linked for minimum space and pointer manipulation overhead at
- * the expense of O(n) removal for arbitrary elements. New elements can be
- * added to the list after an existing element or at the head of the list.
- * Elements being removed from the head of the list should use the explicit
- * macro for this purpose for optimum efficiency. A singly-linked list may
- * only be traversed in the forward direction. Singly-linked lists are ideal
- * for applications with large datasets and few or no removals or for
- * implementing a LIFO queue.
- *
- * A singly-linked tail queue is headed by a pair of pointers, one to the
- * head of the list and the other to the tail of the list. The elements are
- * singly linked for minimum space and pointer manipulation overhead at the
- * expense of O(n) removal for arbitrary elements. New elements can be added
- * to the list after an existing element, at the head of the list, or at the
- * end of the list. Elements being removed from the head of the tail queue
- * should use the explicit macro for this purpose for optimum efficiency.
- * A singly-linked tail queue may only be traversed in the forward direction.
- * Singly-linked tail queues are ideal for applications with large datasets
- * and few or no removals or for implementing a FIFO queue.
- *
- * A list is headed by a single forward pointer (or an array of forward
- * pointers for a hash table header). The elements are doubly linked
- * so that an arbitrary element can be removed without a need to
- * traverse the list. New elements can be added to the list before
- * or after an existing element or at the head of the list. A list
- * may be traversed in either direction.
- *
- * A tail queue is headed by a pair of pointers, one to the head of the
- * list and the other to the tail of the list. The elements are doubly
- * linked so that an arbitrary element can be removed without a need to
- * traverse the list. New elements can be added to the list before or
- * after an existing element, at the head of the list, or at the end of
- * the list. A tail queue may be traversed in either direction.
- *
- * For details on the use of these macros, see the queue(3) manual page.
- *
- * SLIST LIST STAILQ TAILQ
- * _HEAD + + + +
- * _HEAD_INITIALIZER + + + +
- * _ENTRY + + + +
- * _INIT + + + +
- * _EMPTY + + + +
- * _FIRST + + + +
- * _NEXT + + + +
- * _PREV - + - +
- * _LAST - - + +
- * _FOREACH + + + +
- * _FOREACH_FROM + + + +
- * _FOREACH_SAFE + + + +
- * _FOREACH_FROM_SAFE + + + +
- * _FOREACH_REVERSE - - - +
- * _FOREACH_REVERSE_FROM - - - +
- * _FOREACH_REVERSE_SAFE - - - +
- * _FOREACH_REVERSE_FROM_SAFE - - - +
- * _INSERT_HEAD + + + +
- * _INSERT_BEFORE - + - +
- * _INSERT_AFTER + + + +
- * _INSERT_TAIL - - + +
- * _CONCAT - - + +
- * _REMOVE_AFTER + - + -
- * _REMOVE_HEAD + - + -
- * _REMOVE + + + +
- * _SWAP + + + +
- *
- */
-
-/*
- * Singly-linked List declarations.
- */
-#define SLIST_HEAD(name, type, qual) \
- struct name { \
- struct type *qual slh_first; /* first element */ \
- }
-
-#define SLIST_HEAD_INITIALIZER(head) \
- { NULL }
-
-#define SLIST_ENTRY(type, qual) \
- struct { \
- struct type *qual sle_next; /* next element */ \
- }
-
-/*
- * Singly-linked List functions.
- */
-#define SLIST_INIT(head) do { \
- SLIST_FIRST((head)) = NULL; \
- } while (0)
-
-#define SLIST_EMPTY(head) ((head)->slh_first == NULL)
-
-#define SLIST_FIRST(head) ((head)->slh_first)
-
-#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
-
-#define SLIST_FOREACH(var, head, field) \
- for ((var) = SLIST_FIRST((head)); \
- (var); \
- (var) = SLIST_NEXT((var), field))
-
-#define SLIST_FOREACH_FROM(var, head, field) \
- for ((var) = ((var) ? (var) : SLIST_FIRST((head))); \
- (var); \
- (var) = SLIST_NEXT((var), field))
-
-#define SLIST_FOREACH_SAFE(var, head, field, tvar) \
- for ((var) = SLIST_FIRST((head)); \
- (var) && ((tvar) = SLIST_NEXT((var), field), 1); \
- (var) = (tvar))
-
-#define SLIST_FOREACH_FROM_SAFE(var, head, field, tvar) \
- for ((var) = ((var) ? (var) : SLIST_FIRST((head))); \
- (var) && ((tvar) = SLIST_NEXT((var), field), 1); \
- (var) = (tvar))
-
-#define SLIST_INSERT_HEAD(head, elm, field) do { \
- SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \
- SLIST_FIRST((head)) = (elm); \
- } while (0)
-
-#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
- SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \
- SLIST_NEXT((slistelm), field) = (elm); \
- } while (0)
-
-#define SLIST_REMOVE_AFTER(elm, field) do { \
- SLIST_NEXT(elm, field) = \
- SLIST_NEXT(SLIST_NEXT(elm, field), field); \
- } while (0)
-
-#define SLIST_REMOVE_HEAD(head, field) do { \
- SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \
- } while (0)
-
-#define SLIST_REMOVE(head, elm, type, field) do { \
- if (SLIST_FIRST((head)) == (elm)) { \
- SLIST_REMOVE_HEAD((head), field); \
- } \
- else { \
- struct type *curelm = SLIST_FIRST((head)); \
- while (SLIST_NEXT(curelm, field) != (elm)) \
- curelm = SLIST_NEXT(curelm, field); \
- SLIST_REMOVE_AFTER(curelm, field); \
- } \
- } while (0)
-
-#define SLIST_SWAP(head1, head2, type) do { \
- struct type *swap_first = SLIST_FIRST(head1); \
- SLIST_FIRST(head1) = SLIST_FIRST(head2); \
- SLIST_FIRST(head2) = swap_first; \
- } while (0)
-
-/*
- * List declarations.
- */
-#define LIST_HEAD(name, type, qual) \
- struct name { \
- struct type *qual lh_first; /* first element */ \
- }
-
-#define LIST_HEAD_INITIALIZER(head) \
- { NULL }
-
-#define LIST_ENTRY(type, qual) \
- struct { \
- struct type *qual le_next; /* next element */ \
- struct type *qual *le_prev; /* address of previous next element */ \
- }
-
-/*
- * List functions.
- */
-#define LIST_INIT(head) do { \
- LIST_FIRST((head)) = NULL; \
- } while (0)
-
-#define LIST_EMPTY(head) ((head)->lh_first == NULL)
-
-#define LIST_FIRST(head) ((head)->lh_first)
-
-#define LIST_NEXT(elm, field) ((elm)->field.le_next)
-
-#define LIST_PREV(elm, head, type, field) \
- ((elm)->field.le_prev == &LIST_FIRST((head)) ? NULL : \
- __containerof((elm)->field.le_prev, struct type, field.le_next))
-
-#define LIST_FOREACH(var, head, field) \
- for ((var) = LIST_FIRST((head)); \
- (var); \
- (var) = LIST_NEXT((var), field))
-
-#define LIST_FOREACH_FROM(var, head, field) \
- for ((var) = ((var) ? (var) : LIST_FIRST((head))); \
- (var); \
- (var) = LIST_NEXT((var), field))
-
-#define LIST_FOREACH_SAFE(var, head, field, tvar) \
- for ((var) = LIST_FIRST((head)); \
- (var) && ((tvar) = LIST_NEXT((var), field), 1); \
- (var) = (tvar))
-
-#define LIST_FOREACH_FROM_SAFE(var, head, field, tvar) \
- for ((var) = ((var) ? (var) : LIST_FIRST((head))); \
- (var) && ((tvar) = LIST_NEXT((var), field), 1); \
- (var) = (tvar))
-
-#define LIST_INSERT_HEAD(head, elm, field) do { \
- if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \
- LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field); \
- LIST_FIRST((head)) = (elm); \
- (elm)->field.le_prev = &LIST_FIRST((head)); \
- } while (0)
-
-#define LIST_INSERT_BEFORE(listelm, elm, field) do { \
- (elm)->field.le_prev = (listelm)->field.le_prev; \
- LIST_NEXT((elm), field) = (listelm); \
- *(listelm)->field.le_prev = (elm); \
- (listelm)->field.le_prev = &LIST_NEXT((elm), field); \
- } while (0)
-
-#define LIST_INSERT_AFTER(listelm, elm, field) do { \
- if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL) \
- LIST_NEXT((listelm), field)->field.le_prev = \
- &LIST_NEXT((elm), field); \
- LIST_NEXT((listelm), field) = (elm); \
- (elm)->field.le_prev = &LIST_NEXT((listelm), field); \
- } while (0)
-
-#define LIST_REMOVE(elm, field) do { \
- if (LIST_NEXT((elm), field) != NULL) \
- LIST_NEXT((elm), field)->field.le_prev = \
- (elm)->field.le_prev; \
- *(elm)->field.le_prev = LIST_NEXT((elm), field); \
- } while (0)
-
-#define LIST_SWAP(head1, head2, type, field) do { \
- struct type *swap_tmp = LIST_FIRST((head1)); \
- LIST_FIRST((head1)) = LIST_FIRST((head2)); \
- LIST_FIRST((head2)) = swap_tmp; \
- if ((swap_tmp = LIST_FIRST((head1))) != NULL) \
- swap_tmp->field.le_prev = &LIST_FIRST((head1)); \
- if ((swap_tmp = LIST_FIRST((head2))) != NULL) \
- swap_tmp->field.le_prev = &LIST_FIRST((head2)); \
- } while (0)
-
-/*
- * Singly-linked Tail queue declarations.
- */
-#define STAILQ_HEAD(name, type, qual) \
- struct name { \
- struct type *qual stqh_first;/* first element */ \
- struct type *qual *stqh_last;/* addr of last next element */ \
- }
-
-#define STAILQ_HEAD_INITIALIZER(head) \
- { NULL, &(head).stqh_first }
-
-#define STAILQ_ENTRY(type, qual) \
- struct { \
- struct type *qual stqe_next; /* next element */ \
- }
-
-/*
- * Singly-linked Tail queue functions.
- */
-#define STAILQ_INIT(head) do { \
- STAILQ_FIRST((head)) = NULL; \
- (head)->stqh_last = &STAILQ_FIRST((head)); \
- } while (0)
-
-#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL)
-
-#define STAILQ_FIRST(head) ((head)->stqh_first)
-
-#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
-
-#define STAILQ_LAST(head, type, field) \
- (STAILQ_EMPTY((head)) ? NULL : \
- __containerof((head)->stqh_last, struct type, field.stqe_next))
-
-#define STAILQ_FOREACH(var, head, field) \
- for((var) = STAILQ_FIRST((head)); \
- (var); \
- (var) = STAILQ_NEXT((var), field))
-
-#define STAILQ_FOREACH_FROM(var, head, field) \
- for ((var) = ((var) ? (var) : STAILQ_FIRST((head))); \
- (var); \
- (var) = STAILQ_NEXT((var), field))
-
-#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \
- for ((var) = STAILQ_FIRST((head)); \
- (var) && ((tvar) = STAILQ_NEXT((var), field), 1); \
- (var) = (tvar))
-
-#define STAILQ_FOREACH_FROM_SAFE(var, head, field, tvar) \
- for ((var) = ((var) ? (var) : STAILQ_FIRST((head))); \
- (var) && ((tvar) = STAILQ_NEXT((var), field), 1); \
- (var) = (tvar))
-
-#define STAILQ_INSERT_HEAD(head, elm, field) do { \
- if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \
- (head)->stqh_last = &STAILQ_NEXT((elm), field); \
- STAILQ_FIRST((head)) = (elm); \
- } while (0)
-
-#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \
- if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL) \
- (head)->stqh_last = &STAILQ_NEXT((elm), field); \
- STAILQ_NEXT((tqelm), field) = (elm); \
- } while (0)
-
-#define STAILQ_INSERT_TAIL(head, elm, field) do { \
- STAILQ_NEXT((elm), field) = NULL; \
- *(head)->stqh_last = (elm); \
- (head)->stqh_last = &STAILQ_NEXT((elm), field); \
- } while (0)
-
-#define STAILQ_CONCAT(head1, head2) do { \
- if (!STAILQ_EMPTY((head2))) { \
- *(head1)->stqh_last = (head2)->stqh_first; \
- (head1)->stqh_last = (head2)->stqh_last; \
- STAILQ_INIT((head2)); \
- } \
- } while (0)
-
-#define STAILQ_REMOVE_AFTER(head, elm, field) do { \
- if ((STAILQ_NEXT(elm, field) = \
- STAILQ_NEXT(STAILQ_NEXT(elm, field), field)) == NULL) \
- (head)->stqh_last = &STAILQ_NEXT((elm), field); \
- } while (0)
-
-#define STAILQ_REMOVE_HEAD(head, field) do { \
- if ((STAILQ_FIRST((head)) = \
- STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \
- (head)->stqh_last = &STAILQ_FIRST((head)); \
- } while (0)
-
-#define STAILQ_REMOVE(head, elm, type, field) do { \
- if (STAILQ_FIRST((head)) == (elm)) { \
- STAILQ_REMOVE_HEAD((head), field); \
- } \
- else { \
- struct type *curelm = STAILQ_FIRST((head)); \
- while (STAILQ_NEXT(curelm, field) != (elm)) \
- curelm = STAILQ_NEXT(curelm, field); \
- STAILQ_REMOVE_AFTER(head, curelm, field); \
- } \
- } while (0)
-
-#define STAILQ_SWAP(head1, head2, type) do { \
- struct type *swap_first = STAILQ_FIRST(head1); \
- struct type **swap_last = (head1)->stqh_last; \
- STAILQ_FIRST(head1) = STAILQ_FIRST(head2); \
- (head1)->stqh_last = (head2)->stqh_last; \
- STAILQ_FIRST(head2) = swap_first; \
- (head2)->stqh_last = swap_last; \
- if (STAILQ_EMPTY(head1)) \
- (head1)->stqh_last = &STAILQ_FIRST(head1); \
- if (STAILQ_EMPTY(head2)) \
- (head2)->stqh_last = &STAILQ_FIRST(head2); \
- } while (0)
-
-/*
- * Tail queue declarations.
- */
-#define TAILQ_HEAD(name, type, qual) \
- struct name { \
- struct type *qual tqh_first; /* first element */ \
- struct type *qual *tqh_last; /* addr of last next element */ \
-}
-
-#define TAILQ_HEAD_INITIALIZER(head) \
- { NULL, &(head).tqh_first }
-
-#define TAILQ_ENTRY(type, qual) \
- struct { \
- struct type *qual tqe_next; /* next element */ \
- struct type *qual *tqe_prev; /* address of previous next element */ \
- }
-
-/*
- * Tail queue functions.
- */
-#define TAILQ_INIT(head) do { \
- TAILQ_FIRST((head)) = NULL; \
- (head)->tqh_last = &TAILQ_FIRST((head)); \
- } while (0)
-
-#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL)
-
-#define TAILQ_FIRST(head) ((head)->tqh_first)
-
-#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
-
-#define TAILQ_PREV(elm, headname, field) \
- (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
-
-#define TAILQ_LAST(head, headname) \
- (*(((struct headname *)((head)->tqh_last))->tqh_last))
-
-#define TAILQ_FOREACH(var, head, field) \
- for ((var) = TAILQ_FIRST((head)); \
- (var); \
- (var) = TAILQ_NEXT((var), field))
-
-#define TAILQ_FOREACH_FROM(var, head, field) \
- for ((var) = ((var) ? (var) : TAILQ_FIRST((head))); \
- (var); \
- (var) = TAILQ_NEXT((var), field))
-
-#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \
- for ((var) = TAILQ_FIRST((head)); \
- (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \
- (var) = (tvar))
-
-#define TAILQ_FOREACH_FROM_SAFE(var, head, field, tvar) \
- for ((var) = ((var) ? (var) : TAILQ_FIRST((head))); \
- (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \
- (var) = (tvar))
-
-#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
- for ((var) = TAILQ_LAST((head), headname); \
- (var); \
- (var) = TAILQ_PREV((var), headname, field))
-
-#define TAILQ_FOREACH_REVERSE_FROM(var, head, headname, field) \
- for ((var) = ((var) ? (var) : TAILQ_LAST((head), headname)); \
- (var); \
- (var) = TAILQ_PREV((var), headname, field))
-
-#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \
- for ((var) = TAILQ_LAST((head), headname); \
- (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \
- (var) = (tvar))
-
-#define TAILQ_FOREACH_REVERSE_FROM_SAFE(var, head, headname, field, tvar) \
- for ((var) = ((var) ? (var) : TAILQ_LAST((head), headname)); \
- (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \
- (var) = (tvar))
-
-#define TAILQ_INSERT_HEAD(head, elm, field) do { \
- if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) \
- TAILQ_FIRST((head))->field.tqe_prev = \
- &TAILQ_NEXT((elm), field); \
- else \
- (head)->tqh_last = &TAILQ_NEXT((elm), field); \
- TAILQ_FIRST((head)) = (elm); \
- (elm)->field.tqe_prev = &TAILQ_FIRST((head)); \
- } while (0)
-
-#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
- (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
- TAILQ_NEXT((elm), field) = (listelm); \
- *(listelm)->field.tqe_prev = (elm); \
- (listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \
- } while (0)
-
-#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
- if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL) \
- TAILQ_NEXT((elm), field)->field.tqe_prev = \
- &TAILQ_NEXT((elm), field); \
- else \
- (head)->tqh_last = &TAILQ_NEXT((elm), field); \
- TAILQ_NEXT((listelm), field) = (elm); \
- (elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \
- } while (0)
-
-#define TAILQ_INSERT_TAIL(head, elm, field) do { \
- TAILQ_NEXT((elm), field) = NULL; \
- (elm)->field.tqe_prev = (head)->tqh_last; \
- *(head)->tqh_last = (elm); \
- (head)->tqh_last = &TAILQ_NEXT((elm), field); \
- } while (0)
-
-#define TAILQ_CONCAT(head1, head2, field) do { \
- if (!TAILQ_EMPTY(head2)) { \
- *(head1)->tqh_last = (head2)->tqh_first; \
- (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \
- (head1)->tqh_last = (head2)->tqh_last; \
- TAILQ_INIT((head2)); \
- } \
- } while (0)
-
-#define TAILQ_REMOVE(head, elm, field) do { \
- if ((TAILQ_NEXT((elm), field)) != NULL) \
- TAILQ_NEXT((elm), field)->field.tqe_prev = \
- (elm)->field.tqe_prev; \
- else \
- (head)->tqh_last = (elm)->field.tqe_prev; \
- *(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \
- } while (0)
-
-#define TAILQ_SWAP(head1, head2, type, field) do { \
- struct type *swap_first = (head1)->tqh_first; \
- struct type **swap_last = (head1)->tqh_last; \
- (head1)->tqh_first = (head2)->tqh_first; \
- (head1)->tqh_last = (head2)->tqh_last; \
- (head2)->tqh_first = swap_first; \
- (head2)->tqh_last = swap_last; \
- if ((swap_first = (head1)->tqh_first) != NULL) \
- swap_first->field.tqe_prev = &(head1)->tqh_first; \
- else \
- (head1)->tqh_last = &(head1)->tqh_first; \
- if ((swap_first = (head2)->tqh_first) != NULL) \
- swap_first->field.tqe_prev = &(head2)->tqh_first; \
- else \
- (head2)->tqh_last = &(head2)->tqh_first; \
- } while (0)
-
-#endif
diff --git a/riru-core/jni/external/xhook/tree.h b/riru-core/jni/external/xhook/tree.h
deleted file mode 100644
index dc938ae..0000000
--- a/riru-core/jni/external/xhook/tree.h
+++ /dev/null
@@ -1,768 +0,0 @@
-/* $NetBSD: tree.h,v 1.8 2004/03/28 19:38:30 provos Exp $ */
-/* $OpenBSD: tree.h,v 1.7 2002/10/17 21:51:54 art Exp $ */
-/* $FreeBSD: stable/9/sys/sys/tree.h 189204 2009-03-01 04:57:23Z bms $ */
-
-/*-
- * Copyright 2002 Niels Provos
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef TREE_H
-#define TREE_H
-
-/* #include */
-#ifndef __unused
-#define __unused __attribute__((__unused__))
-#endif
-
-/*
- * This file defines data structures for different types of trees:
- * splay trees and red-black trees.
- *
- * A splay tree is a self-organizing data structure. Every operation
- * on the tree causes a splay to happen. The splay moves the requested
- * node to the root of the tree and partly rebalances it.
- *
- * This has the benefit that request locality causes faster lookups as
- * the requested nodes move to the top of the tree. On the other hand,
- * every lookup causes memory writes.
- *
- * The Balance Theorem bounds the total access time for m operations
- * and n inserts on an initially empty tree as O((m + n)lg n). The
- * amortized cost for a sequence of m accesses to a splay tree is O(lg n);
- *
- * A red-black tree is a binary search tree with the node color as an
- * extra attribute. It fulfills a set of conditions:
- * - every search path from the root to a leaf consists of the
- * same number of black nodes,
- * - each red node (except for the root) has a black parent,
- * - each leaf node is black.
- *
- * Every operation on a red-black tree is bounded as O(lg n).
- * The maximum height of a red-black tree is 2lg (n+1).
- */
-
-#define SPLAY_HEAD(name, type) \
-struct name { \
- struct type *sph_root; /* root of the tree */ \
-}
-
-#define SPLAY_INITIALIZER(root) \
- { NULL }
-
-#define SPLAY_INIT(root) do { \
- (root)->sph_root = NULL; \
-} while (/*CONSTCOND*/ 0)
-
-#define SPLAY_ENTRY(type) \
-struct { \
- struct type *spe_left; /* left element */ \
- struct type *spe_right; /* right element */ \
-}
-
-#define SPLAY_LEFT(elm, field) (elm)->field.spe_left
-#define SPLAY_RIGHT(elm, field) (elm)->field.spe_right
-#define SPLAY_ROOT(head) (head)->sph_root
-#define SPLAY_EMPTY(head) (SPLAY_ROOT(head) == NULL)
-
-/* SPLAY_ROTATE_{LEFT,RIGHT} expect that tmp hold SPLAY_{RIGHT,LEFT} */
-#define SPLAY_ROTATE_RIGHT(head, tmp, field) do { \
- SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(tmp, field); \
- SPLAY_RIGHT(tmp, field) = (head)->sph_root; \
- (head)->sph_root = tmp; \
-} while (/*CONSTCOND*/ 0)
-
-#define SPLAY_ROTATE_LEFT(head, tmp, field) do { \
- SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(tmp, field); \
- SPLAY_LEFT(tmp, field) = (head)->sph_root; \
- (head)->sph_root = tmp; \
-} while (/*CONSTCOND*/ 0)
-
-#define SPLAY_LINKLEFT(head, tmp, field) do { \
- SPLAY_LEFT(tmp, field) = (head)->sph_root; \
- tmp = (head)->sph_root; \
- (head)->sph_root = SPLAY_LEFT((head)->sph_root, field); \
-} while (/*CONSTCOND*/ 0)
-
-#define SPLAY_LINKRIGHT(head, tmp, field) do { \
- SPLAY_RIGHT(tmp, field) = (head)->sph_root; \
- tmp = (head)->sph_root; \
- (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field); \
-} while (/*CONSTCOND*/ 0)
-
-#define SPLAY_ASSEMBLE(head, node, left, right, field) do { \
- SPLAY_RIGHT(left, field) = SPLAY_LEFT((head)->sph_root, field); \
- SPLAY_LEFT(right, field) = SPLAY_RIGHT((head)->sph_root, field);\
- SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(node, field); \
- SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(node, field); \
-} while (/*CONSTCOND*/ 0)
-
-/* Generates prototypes and inline functions */
-
-#define SPLAY_PROTOTYPE(name, type, field, cmp) \
-void name##_SPLAY(struct name *, struct type *); \
-void name##_SPLAY_MINMAX(struct name *, int); \
-struct type *name##_SPLAY_INSERT(struct name *, struct type *); \
-struct type *name##_SPLAY_REMOVE(struct name *, struct type *); \
- \
-/* Finds the node with the same key as elm */ \
-static __inline struct type * \
-name##_SPLAY_FIND(struct name *head, struct type *elm) \
-{ \
- if (SPLAY_EMPTY(head)) \
- return(NULL); \
- name##_SPLAY(head, elm); \
- if ((cmp)(elm, (head)->sph_root) == 0) \
- return (head->sph_root); \
- return (NULL); \
-} \
- \
-static __inline struct type * \
-name##_SPLAY_NEXT(struct name *head, struct type *elm) \
-{ \
- name##_SPLAY(head, elm); \
- if (SPLAY_RIGHT(elm, field) != NULL) { \
- elm = SPLAY_RIGHT(elm, field); \
- while (SPLAY_LEFT(elm, field) != NULL) { \
- elm = SPLAY_LEFT(elm, field); \
- } \
- } else \
- elm = NULL; \
- return (elm); \
-} \
- \
-static __inline struct type * \
-name##_SPLAY_MIN_MAX(struct name *head, int val) \
-{ \
- name##_SPLAY_MINMAX(head, val); \
- return (SPLAY_ROOT(head)); \
-}
-
-/* Main splay operation.
- * Moves node close to the key of elm to top
- */
-#define SPLAY_GENERATE(name, type, field, cmp) \
-struct type * \
-name##_SPLAY_INSERT(struct name *head, struct type *elm) \
-{ \
- if (SPLAY_EMPTY(head)) { \
- SPLAY_LEFT(elm, field) = SPLAY_RIGHT(elm, field) = NULL; \
- } else { \
- int __comp; \
- name##_SPLAY(head, elm); \
- __comp = (cmp)(elm, (head)->sph_root); \
- if(__comp < 0) { \
- SPLAY_LEFT(elm, field) = SPLAY_LEFT((head)->sph_root, field);\
- SPLAY_RIGHT(elm, field) = (head)->sph_root; \
- SPLAY_LEFT((head)->sph_root, field) = NULL; \
- } else if (__comp > 0) { \
- SPLAY_RIGHT(elm, field) = SPLAY_RIGHT((head)->sph_root, field);\
- SPLAY_LEFT(elm, field) = (head)->sph_root; \
- SPLAY_RIGHT((head)->sph_root, field) = NULL; \
- } else \
- return ((head)->sph_root); \
- } \
- (head)->sph_root = (elm); \
- return (NULL); \
-} \
- \
-struct type * \
-name##_SPLAY_REMOVE(struct name *head, struct type *elm) \
-{ \
- struct type *__tmp; \
- if (SPLAY_EMPTY(head)) \
- return (NULL); \
- name##_SPLAY(head, elm); \
- if ((cmp)(elm, (head)->sph_root) == 0) { \
- if (SPLAY_LEFT((head)->sph_root, field) == NULL) { \
- (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field);\
- } else { \
- __tmp = SPLAY_RIGHT((head)->sph_root, field); \
- (head)->sph_root = SPLAY_LEFT((head)->sph_root, field);\
- name##_SPLAY(head, elm); \
- SPLAY_RIGHT((head)->sph_root, field) = __tmp; \
- } \
- return (elm); \
- } \
- return (NULL); \
-} \
- \
-void \
-name##_SPLAY(struct name *head, struct type *elm) \
-{ \
- struct type __node, *__left, *__right, *__tmp; \
- int __comp; \
-\
- SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\
- __left = __right = &__node; \
-\
- while ((__comp = (cmp)(elm, (head)->sph_root)) != 0) { \
- if (__comp < 0) { \
- __tmp = SPLAY_LEFT((head)->sph_root, field); \
- if (__tmp == NULL) \
- break; \
- if ((cmp)(elm, __tmp) < 0){ \
- SPLAY_ROTATE_RIGHT(head, __tmp, field); \
- if (SPLAY_LEFT((head)->sph_root, field) == NULL)\
- break; \
- } \
- SPLAY_LINKLEFT(head, __right, field); \
- } else if (__comp > 0) { \
- __tmp = SPLAY_RIGHT((head)->sph_root, field); \
- if (__tmp == NULL) \
- break; \
- if ((cmp)(elm, __tmp) > 0){ \
- SPLAY_ROTATE_LEFT(head, __tmp, field); \
- if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\
- break; \
- } \
- SPLAY_LINKRIGHT(head, __left, field); \
- } \
- } \
- SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \
-} \
- \
-/* Splay with either the minimum or the maximum element \
- * Used to find minimum or maximum element in tree. \
- */ \
-void name##_SPLAY_MINMAX(struct name *head, int __comp) \
-{ \
- struct type __node, *__left, *__right, *__tmp; \
-\
- SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\
- __left = __right = &__node; \
-\
- while (1) { \
- if (__comp < 0) { \
- __tmp = SPLAY_LEFT((head)->sph_root, field); \
- if (__tmp == NULL) \
- break; \
- if (__comp < 0){ \
- SPLAY_ROTATE_RIGHT(head, __tmp, field); \
- if (SPLAY_LEFT((head)->sph_root, field) == NULL)\
- break; \
- } \
- SPLAY_LINKLEFT(head, __right, field); \
- } else if (__comp > 0) { \
- __tmp = SPLAY_RIGHT((head)->sph_root, field); \
- if (__tmp == NULL) \
- break; \
- if (__comp > 0) { \
- SPLAY_ROTATE_LEFT(head, __tmp, field); \
- if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\
- break; \
- } \
- SPLAY_LINKRIGHT(head, __left, field); \
- } \
- } \
- SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \
-}
-
-#define SPLAY_NEGINF -1
-#define SPLAY_INF 1
-
-#define SPLAY_INSERT(name, x, y) name##_SPLAY_INSERT(x, y)
-#define SPLAY_REMOVE(name, x, y) name##_SPLAY_REMOVE(x, y)
-#define SPLAY_FIND(name, x, y) name##_SPLAY_FIND(x, y)
-#define SPLAY_NEXT(name, x, y) name##_SPLAY_NEXT(x, y)
-#define SPLAY_MIN(name, x) (SPLAY_EMPTY(x) ? NULL \
- : name##_SPLAY_MIN_MAX(x, SPLAY_NEGINF))
-#define SPLAY_MAX(name, x) (SPLAY_EMPTY(x) ? NULL \
- : name##_SPLAY_MIN_MAX(x, SPLAY_INF))
-
-#define SPLAY_FOREACH(x, name, head) \
- for ((x) = SPLAY_MIN(name, head); \
- (x) != NULL; \
- (x) = SPLAY_NEXT(name, head, x))
-
-/* Macros that define a red-black tree */
-#define RB_HEAD(name, type) \
-struct name { \
- struct type *rbh_root; /* root of the tree */ \
-}
-
-#define RB_INITIALIZER(root) \
- { NULL }
-
-#define RB_INIT(root) do { \
- (root)->rbh_root = NULL; \
-} while (/*CONSTCOND*/ 0)
-
-#define RB_BLACK 0
-#define RB_RED 1
-#define RB_ENTRY(type) \
-struct { \
- struct type *rbe_left; /* left element */ \
- struct type *rbe_right; /* right element */ \
- struct type *rbe_parent; /* parent element */ \
- int rbe_color; /* node color */ \
-}
-
-#define RB_LEFT(elm, field) (elm)->field.rbe_left
-#define RB_RIGHT(elm, field) (elm)->field.rbe_right
-#define RB_PARENT(elm, field) (elm)->field.rbe_parent
-#define RB_COLOR(elm, field) (elm)->field.rbe_color
-#define RB_ROOT(head) (head)->rbh_root
-#define RB_EMPTY(head) (RB_ROOT(head) == NULL)
-
-#define RB_SET(elm, parent, field) do { \
- RB_PARENT(elm, field) = parent; \
- RB_LEFT(elm, field) = RB_RIGHT(elm, field) = NULL; \
- RB_COLOR(elm, field) = RB_RED; \
-} while (/*CONSTCOND*/ 0)
-
-#define RB_SET_BLACKRED(black, red, field) do { \
- RB_COLOR(black, field) = RB_BLACK; \
- RB_COLOR(red, field) = RB_RED; \
-} while (/*CONSTCOND*/ 0)
-
-#ifndef RB_AUGMENT
-#define RB_AUGMENT(x) do {} while (0)
-#endif
-
-#define RB_ROTATE_LEFT(head, elm, tmp, field) do { \
- (tmp) = RB_RIGHT(elm, field); \
- if ((RB_RIGHT(elm, field) = RB_LEFT(tmp, field)) != NULL) { \
- RB_PARENT(RB_LEFT(tmp, field), field) = (elm); \
- } \
- RB_AUGMENT(elm); \
- if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field)) != NULL) { \
- if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \
- RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \
- else \
- RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \
- } else \
- (head)->rbh_root = (tmp); \
- RB_LEFT(tmp, field) = (elm); \
- RB_PARENT(elm, field) = (tmp); \
- RB_AUGMENT(tmp); \
- if ((RB_PARENT(tmp, field))) \
- RB_AUGMENT(RB_PARENT(tmp, field)); \
-} while (/*CONSTCOND*/ 0)
-
-#define RB_ROTATE_RIGHT(head, elm, tmp, field) do { \
- (tmp) = RB_LEFT(elm, field); \
- if ((RB_LEFT(elm, field) = RB_RIGHT(tmp, field)) != NULL) { \
- RB_PARENT(RB_RIGHT(tmp, field), field) = (elm); \
- } \
- RB_AUGMENT(elm); \
- if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field)) != NULL) { \
- if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \
- RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \
- else \
- RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \
- } else \
- (head)->rbh_root = (tmp); \
- RB_RIGHT(tmp, field) = (elm); \
- RB_PARENT(elm, field) = (tmp); \
- RB_AUGMENT(tmp); \
- if ((RB_PARENT(tmp, field))) \
- RB_AUGMENT(RB_PARENT(tmp, field)); \
-} while (/*CONSTCOND*/ 0)
-
-/* Generates prototypes and inline functions */
-#define RB_PROTOTYPE(name, type, field, cmp) \
- RB_PROTOTYPE_INTERNAL(name, type, field, cmp,)
-#define RB_PROTOTYPE_STATIC(name, type, field, cmp) \
- RB_PROTOTYPE_INTERNAL(name, type, field, cmp, __unused static)
-#define RB_PROTOTYPE_INTERNAL(name, type, field, cmp, attr) \
-attr void name##_RB_INSERT_COLOR(struct name *, struct type *); \
-attr void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *);\
-attr struct type *name##_RB_REMOVE(struct name *, struct type *); \
-attr struct type *name##_RB_INSERT(struct name *, struct type *); \
-attr struct type *name##_RB_FIND(struct name *, struct type *); \
-attr struct type *name##_RB_NFIND(struct name *, struct type *); \
-attr struct type *name##_RB_NEXT(struct type *); \
-attr struct type *name##_RB_PREV(struct type *); \
-attr struct type *name##_RB_MINMAX(struct name *, int); \
- \
-
-/* Main rb operation.
- * Moves node close to the key of elm to top
- */
-#define RB_GENERATE(name, type, field, cmp) \
- RB_GENERATE_INTERNAL(name, type, field, cmp,)
-#define RB_GENERATE_STATIC(name, type, field, cmp) \
- RB_GENERATE_INTERNAL(name, type, field, cmp, __unused static)
-#define RB_GENERATE_INTERNAL(name, type, field, cmp, attr) \
-attr void \
-name##_RB_INSERT_COLOR(struct name *head, struct type *elm) \
-{ \
- struct type *parent, *gparent, *tmp; \
- while ((parent = RB_PARENT(elm, field)) != NULL && \
- RB_COLOR(parent, field) == RB_RED) { \
- gparent = RB_PARENT(parent, field); \
- if (parent == RB_LEFT(gparent, field)) { \
- tmp = RB_RIGHT(gparent, field); \
- if (tmp && RB_COLOR(tmp, field) == RB_RED) { \
- RB_COLOR(tmp, field) = RB_BLACK; \
- RB_SET_BLACKRED(parent, gparent, field);\
- elm = gparent; \
- continue; \
- } \
- if (RB_RIGHT(parent, field) == elm) { \
- RB_ROTATE_LEFT(head, parent, tmp, field);\
- tmp = parent; \
- parent = elm; \
- elm = tmp; \
- } \
- RB_SET_BLACKRED(parent, gparent, field); \
- RB_ROTATE_RIGHT(head, gparent, tmp, field); \
- } else { \
- tmp = RB_LEFT(gparent, field); \
- if (tmp && RB_COLOR(tmp, field) == RB_RED) { \
- RB_COLOR(tmp, field) = RB_BLACK; \
- RB_SET_BLACKRED(parent, gparent, field);\
- elm = gparent; \
- continue; \
- } \
- if (RB_LEFT(parent, field) == elm) { \
- RB_ROTATE_RIGHT(head, parent, tmp, field);\
- tmp = parent; \
- parent = elm; \
- elm = tmp; \
- } \
- RB_SET_BLACKRED(parent, gparent, field); \
- RB_ROTATE_LEFT(head, gparent, tmp, field); \
- } \
- } \
- RB_COLOR(head->rbh_root, field) = RB_BLACK; \
-} \
- \
-attr void \
-name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm) \
-{ \
- struct type *tmp; \
- while ((elm == NULL || RB_COLOR(elm, field) == RB_BLACK) && \
- elm != RB_ROOT(head)) { \
- if (RB_LEFT(parent, field) == elm) { \
- tmp = RB_RIGHT(parent, field); \
- if (RB_COLOR(tmp, field) == RB_RED) { \
- RB_SET_BLACKRED(tmp, parent, field); \
- RB_ROTATE_LEFT(head, parent, tmp, field);\
- tmp = RB_RIGHT(parent, field); \
- } \
- if ((RB_LEFT(tmp, field) == NULL || \
- RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\
- (RB_RIGHT(tmp, field) == NULL || \
- RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\
- RB_COLOR(tmp, field) = RB_RED; \
- elm = parent; \
- parent = RB_PARENT(elm, field); \
- } else { \
- if (RB_RIGHT(tmp, field) == NULL || \
- RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK) {\
- struct type *oleft; \
- if ((oleft = RB_LEFT(tmp, field)) \
- != NULL) \
- RB_COLOR(oleft, field) = RB_BLACK;\
- RB_COLOR(tmp, field) = RB_RED; \
- RB_ROTATE_RIGHT(head, tmp, oleft, field);\
- tmp = RB_RIGHT(parent, field); \
- } \
- RB_COLOR(tmp, field) = RB_COLOR(parent, field);\
- RB_COLOR(parent, field) = RB_BLACK; \
- if (RB_RIGHT(tmp, field)) \
- RB_COLOR(RB_RIGHT(tmp, field), field) = RB_BLACK;\
- RB_ROTATE_LEFT(head, parent, tmp, field);\
- elm = RB_ROOT(head); \
- break; \
- } \
- } else { \
- tmp = RB_LEFT(parent, field); \
- if (RB_COLOR(tmp, field) == RB_RED) { \
- RB_SET_BLACKRED(tmp, parent, field); \
- RB_ROTATE_RIGHT(head, parent, tmp, field);\
- tmp = RB_LEFT(parent, field); \
- } \
- if ((RB_LEFT(tmp, field) == NULL || \
- RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\
- (RB_RIGHT(tmp, field) == NULL || \
- RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\
- RB_COLOR(tmp, field) = RB_RED; \
- elm = parent; \
- parent = RB_PARENT(elm, field); \
- } else { \
- if (RB_LEFT(tmp, field) == NULL || \
- RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) {\
- struct type *oright; \
- if ((oright = RB_RIGHT(tmp, field)) \
- != NULL) \
- RB_COLOR(oright, field) = RB_BLACK;\
- RB_COLOR(tmp, field) = RB_RED; \
- RB_ROTATE_LEFT(head, tmp, oright, field);\
- tmp = RB_LEFT(parent, field); \
- } \
- RB_COLOR(tmp, field) = RB_COLOR(parent, field);\
- RB_COLOR(parent, field) = RB_BLACK; \
- if (RB_LEFT(tmp, field)) \
- RB_COLOR(RB_LEFT(tmp, field), field) = RB_BLACK;\
- RB_ROTATE_RIGHT(head, parent, tmp, field);\
- elm = RB_ROOT(head); \
- break; \
- } \
- } \
- } \
- if (elm) \
- RB_COLOR(elm, field) = RB_BLACK; \
-} \
- \
-attr struct type * \
-name##_RB_REMOVE(struct name *head, struct type *elm) \
-{ \
- struct type *child, *parent, *old = elm; \
- int color; \
- if (RB_LEFT(elm, field) == NULL) \
- child = RB_RIGHT(elm, field); \
- else if (RB_RIGHT(elm, field) == NULL) \
- child = RB_LEFT(elm, field); \
- else { \
- struct type *left; \
- elm = RB_RIGHT(elm, field); \
- while ((left = RB_LEFT(elm, field)) != NULL) \
- elm = left; \
- child = RB_RIGHT(elm, field); \
- parent = RB_PARENT(elm, field); \
- color = RB_COLOR(elm, field); \
- if (child) \
- RB_PARENT(child, field) = parent; \
- if (parent) { \
- if (RB_LEFT(parent, field) == elm) \
- RB_LEFT(parent, field) = child; \
- else \
- RB_RIGHT(parent, field) = child; \
- RB_AUGMENT(parent); \
- } else \
- RB_ROOT(head) = child; \
- if (RB_PARENT(elm, field) == old) \
- parent = elm; \
- (elm)->field = (old)->field; \
- if (RB_PARENT(old, field)) { \
- if (RB_LEFT(RB_PARENT(old, field), field) == old)\
- RB_LEFT(RB_PARENT(old, field), field) = elm;\
- else \
- RB_RIGHT(RB_PARENT(old, field), field) = elm;\
- RB_AUGMENT(RB_PARENT(old, field)); \
- } else \
- RB_ROOT(head) = elm; \
- RB_PARENT(RB_LEFT(old, field), field) = elm; \
- if (RB_RIGHT(old, field)) \
- RB_PARENT(RB_RIGHT(old, field), field) = elm; \
- if (parent) { \
- left = parent; \
- do { \
- RB_AUGMENT(left); \
- } while ((left = RB_PARENT(left, field)) != NULL); \
- } \
- goto color; \
- } \
- parent = RB_PARENT(elm, field); \
- color = RB_COLOR(elm, field); \
- if (child) \
- RB_PARENT(child, field) = parent; \
- if (parent) { \
- if (RB_LEFT(parent, field) == elm) \
- RB_LEFT(parent, field) = child; \
- else \
- RB_RIGHT(parent, field) = child; \
- RB_AUGMENT(parent); \
- } else \
- RB_ROOT(head) = child; \
-color: \
- if (color == RB_BLACK) \
- name##_RB_REMOVE_COLOR(head, parent, child); \
- return (old); \
-} \
- \
-/* Inserts a node into the RB tree */ \
-attr struct type * \
-name##_RB_INSERT(struct name *head, struct type *elm) \
-{ \
- struct type *tmp; \
- struct type *parent = NULL; \
- int comp = 0; \
- tmp = RB_ROOT(head); \
- while (tmp) { \
- parent = tmp; \
- comp = (cmp)(elm, parent); \
- if (comp < 0) \
- tmp = RB_LEFT(tmp, field); \
- else if (comp > 0) \
- tmp = RB_RIGHT(tmp, field); \
- else \
- return (tmp); \
- } \
- RB_SET(elm, parent, field); \
- if (parent != NULL) { \
- if (comp < 0) \
- RB_LEFT(parent, field) = elm; \
- else \
- RB_RIGHT(parent, field) = elm; \
- RB_AUGMENT(parent); \
- } else \
- RB_ROOT(head) = elm; \
- name##_RB_INSERT_COLOR(head, elm); \
- return (NULL); \
-} \
- \
-/* Finds the node with the same key as elm */ \
-attr struct type * \
-name##_RB_FIND(struct name *head, struct type *elm) \
-{ \
- struct type *tmp = RB_ROOT(head); \
- int comp; \
- while (tmp) { \
- comp = cmp(elm, tmp); \
- if (comp < 0) \
- tmp = RB_LEFT(tmp, field); \
- else if (comp > 0) \
- tmp = RB_RIGHT(tmp, field); \
- else \
- return (tmp); \
- } \
- return (NULL); \
-} \
- \
-/* Finds the first node greater than or equal to the search key */ \
-attr struct type * \
-name##_RB_NFIND(struct name *head, struct type *elm) \
-{ \
- struct type *tmp = RB_ROOT(head); \
- struct type *res = NULL; \
- int comp; \
- while (tmp) { \
- comp = cmp(elm, tmp); \
- if (comp < 0) { \
- res = tmp; \
- tmp = RB_LEFT(tmp, field); \
- } \
- else if (comp > 0) \
- tmp = RB_RIGHT(tmp, field); \
- else \
- return (tmp); \
- } \
- return (res); \
-} \
- \
-/* ARGSUSED */ \
-attr struct type * \
-name##_RB_NEXT(struct type *elm) \
-{ \
- if (RB_RIGHT(elm, field)) { \
- elm = RB_RIGHT(elm, field); \
- while (RB_LEFT(elm, field)) \
- elm = RB_LEFT(elm, field); \
- } else { \
- if (RB_PARENT(elm, field) && \
- (elm == RB_LEFT(RB_PARENT(elm, field), field))) \
- elm = RB_PARENT(elm, field); \
- else { \
- while (RB_PARENT(elm, field) && \
- (elm == RB_RIGHT(RB_PARENT(elm, field), field)))\
- elm = RB_PARENT(elm, field); \
- elm = RB_PARENT(elm, field); \
- } \
- } \
- return (elm); \
-} \
- \
-/* ARGSUSED */ \
-attr struct type * \
-name##_RB_PREV(struct type *elm) \
-{ \
- if (RB_LEFT(elm, field)) { \
- elm = RB_LEFT(elm, field); \
- while (RB_RIGHT(elm, field)) \
- elm = RB_RIGHT(elm, field); \
- } else { \
- if (RB_PARENT(elm, field) && \
- (elm == RB_RIGHT(RB_PARENT(elm, field), field))) \
- elm = RB_PARENT(elm, field); \
- else { \
- while (RB_PARENT(elm, field) && \
- (elm == RB_LEFT(RB_PARENT(elm, field), field)))\
- elm = RB_PARENT(elm, field); \
- elm = RB_PARENT(elm, field); \
- } \
- } \
- return (elm); \
-} \
- \
-attr struct type * \
-name##_RB_MINMAX(struct name *head, int val) \
-{ \
- struct type *tmp = RB_ROOT(head); \
- struct type *parent = NULL; \
- while (tmp) { \
- parent = tmp; \
- if (val < 0) \
- tmp = RB_LEFT(tmp, field); \
- else \
- tmp = RB_RIGHT(tmp, field); \
- } \
- return (parent); \
-}
-
-#define RB_NEGINF -1
-#define RB_INF 1
-
-#define RB_INSERT(name, x, y) name##_RB_INSERT(x, y)
-#define RB_REMOVE(name, x, y) name##_RB_REMOVE(x, y)
-#define RB_FIND(name, x, y) name##_RB_FIND(x, y)
-#define RB_NFIND(name, x, y) name##_RB_NFIND(x, y)
-#define RB_NEXT(name, x, y) name##_RB_NEXT(y)
-#define RB_PREV(name, x, y) name##_RB_PREV(y)
-#define RB_MIN(name, x) name##_RB_MINMAX(x, RB_NEGINF)
-#define RB_MAX(name, x) name##_RB_MINMAX(x, RB_INF)
-
-#define RB_FOREACH(x, name, head) \
- for ((x) = RB_MIN(name, head); \
- (x) != NULL; \
- (x) = name##_RB_NEXT(x))
-
-#define RB_FOREACH_FROM(x, name, y) \
- for ((x) = (y); \
- ((x) != NULL) && ((y) = name##_RB_NEXT(x), (x) != NULL); \
- (x) = (y))
-
-#define RB_FOREACH_SAFE(x, name, head, y) \
- for ((x) = RB_MIN(name, head); \
- ((x) != NULL) && ((y) = name##_RB_NEXT(x), (x) != NULL); \
- (x) = (y))
-
-#define RB_FOREACH_REVERSE(x, name, head) \
- for ((x) = RB_MAX(name, head); \
- (x) != NULL; \
- (x) = name##_RB_PREV(x))
-
-#define RB_FOREACH_REVERSE_FROM(x, name, y) \
- for ((x) = (y); \
- ((x) != NULL) && ((y) = name##_RB_PREV(x), (x) != NULL); \
- (x) = (y))
-
-#define RB_FOREACH_REVERSE_SAFE(x, name, head, y) \
- for ((x) = RB_MAX(name, head); \
- ((x) != NULL) && ((y) = name##_RB_PREV(x), (x) != NULL); \
- (x) = (y))
-
-#endif
diff --git a/riru-core/jni/external/xhook/xh_core.c b/riru-core/jni/external/xhook/xh_core.c
deleted file mode 100644
index 4d14ba4..0000000
--- a/riru-core/jni/external/xhook/xh_core.c
+++ /dev/null
@@ -1,656 +0,0 @@
-// Copyright (c) 2018-present, iQIYI, Inc. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
-
-// Created by caikelun on 2018-04-11.
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include "queue.h"
-#include "tree.h"
-#include "xh_errno.h"
-#include "xh_log.h"
-#include "xh_elf.h"
-#include "xh_version.h"
-#include "xh_core.h"
-
-#define XH_CORE_DEBUG 0
-
-//registered hook info collection
-typedef struct xh_core_hook_info
-{
-#if XH_CORE_DEBUG
- char *pathname_regex_str;
-#endif
- regex_t pathname_regex;
- char *symbol;
- void *new_func;
- void **old_func;
- TAILQ_ENTRY(xh_core_hook_info,) link;
-} xh_core_hook_info_t;
-typedef TAILQ_HEAD(xh_core_hook_info_queue, xh_core_hook_info,) xh_core_hook_info_queue_t;
-
-//ignored hook info collection
-typedef struct xh_core_ignore_info
-{
-#if XH_CORE_DEBUG
- char *pathname_regex_str;
-#endif
- regex_t pathname_regex;
- char *symbol; //NULL meaning for all symbols
- TAILQ_ENTRY(xh_core_ignore_info,) link;
-} xh_core_ignore_info_t;
-typedef TAILQ_HEAD(xh_core_ignore_info_queue, xh_core_ignore_info,) xh_core_ignore_info_queue_t;
-
-//required info from /proc/self/maps
-typedef struct xh_core_map_info
-{
- char *pathname;
- uintptr_t base_addr;
- xh_elf_t elf;
- RB_ENTRY(xh_core_map_info) link;
-} xh_core_map_info_t;
-static __inline__ int xh_core_map_info_cmp(xh_core_map_info_t *a, xh_core_map_info_t *b)
-{
- return strcmp(a->pathname, b->pathname);
-}
-typedef RB_HEAD(xh_core_map_info_tree, xh_core_map_info) xh_core_map_info_tree_t;
-RB_GENERATE_STATIC(xh_core_map_info_tree, xh_core_map_info, link, xh_core_map_info_cmp)
-
-//signal handler for SIGSEGV
-//for xh_elf_init(), xh_elf_hook(), xh_elf_check_elfheader()
-static int xh_core_sigsegv_enable = 1; //enable by default
-static struct sigaction xh_core_sigsegv_act_old;
-static volatile int xh_core_sigsegv_flag = 0;
-static sigjmp_buf xh_core_sigsegv_env;
-static void xh_core_sigsegv_handler(int sig)
-{
- (void)sig;
-
- if(xh_core_sigsegv_flag)
- siglongjmp(xh_core_sigsegv_env, 1);
- else
- sigaction(SIGSEGV, &xh_core_sigsegv_act_old, NULL);
-}
-static int xh_core_add_sigsegv_handler()
-{
- struct sigaction act;
-
- if(!xh_core_sigsegv_enable) return 0;
-
- if(0 != sigemptyset(&act.sa_mask)) return (0 == errno ? XH_ERRNO_UNKNOWN : errno);
- act.sa_handler = xh_core_sigsegv_handler;
-
- if(0 != sigaction(SIGSEGV, &act, &xh_core_sigsegv_act_old))
- return (0 == errno ? XH_ERRNO_UNKNOWN : errno);
-
- return 0;
-}
-static void xh_core_del_sigsegv_handler()
-{
- if(!xh_core_sigsegv_enable) return;
-
- sigaction(SIGSEGV, &xh_core_sigsegv_act_old, NULL);
-}
-
-
-static xh_core_hook_info_queue_t xh_core_hook_info = TAILQ_HEAD_INITIALIZER(xh_core_hook_info);
-static xh_core_ignore_info_queue_t xh_core_ignore_info = TAILQ_HEAD_INITIALIZER(xh_core_ignore_info);
-static xh_core_map_info_tree_t xh_core_map_info = RB_INITIALIZER(&xh_core_map_info);
-static pthread_mutex_t xh_core_mutex = PTHREAD_MUTEX_INITIALIZER;
-static pthread_cond_t xh_core_cond = PTHREAD_COND_INITIALIZER;
-static volatile int xh_core_inited = 0;
-static volatile int xh_core_init_ok = 0;
-static volatile int xh_core_async_inited = 0;
-static volatile int xh_core_async_init_ok = 0;
-static pthread_mutex_t xh_core_refresh_mutex = PTHREAD_MUTEX_INITIALIZER;
-static pthread_t xh_core_refresh_thread_tid;
-static volatile int xh_core_refresh_thread_running = 0;
-static volatile int xh_core_refresh_thread_do = 0;
-
-
-int xh_core_register(const char *pathname_regex_str, const char *symbol,
- void *new_func, void **old_func)
-{
- xh_core_hook_info_t *hi;
- regex_t regex;
-
- if(NULL == pathname_regex_str || NULL == symbol || NULL == new_func) return XH_ERRNO_INVAL;
-
- if(xh_core_inited)
- {
- XH_LOG_ERROR("do not register hook after refresh(): %s, %s", pathname_regex_str, symbol);
- return XH_ERRNO_INVAL;
- }
-
- if(0 != regcomp(®ex, pathname_regex_str, REG_NOSUB)) return XH_ERRNO_INVAL;
-
- if(NULL == (hi = malloc(sizeof(xh_core_hook_info_t)))) return XH_ERRNO_NOMEM;
- if(NULL == (hi->symbol = strdup(symbol)))
- {
- free(hi);
- return XH_ERRNO_NOMEM;
- }
-#if XH_CORE_DEBUG
- if(NULL == (hi->pathname_regex_str = strdup(pathname_regex_str)))
- {
- free(hi->symbol);
- free(hi);
- return XH_ERRNO_NOMEM;
- }
-#endif
- hi->pathname_regex = regex;
- hi->new_func = new_func;
- hi->old_func = old_func;
-
- pthread_mutex_lock(&xh_core_mutex);
- TAILQ_INSERT_TAIL(&xh_core_hook_info, hi, link);
- pthread_mutex_unlock(&xh_core_mutex);
-
- return 0;
-}
-
-int xh_core_ignore(const char *pathname_regex_str, const char *symbol)
-{
- xh_core_ignore_info_t *ii;
- regex_t regex;
-
- if(NULL == pathname_regex_str) return XH_ERRNO_INVAL;
-
- if(xh_core_inited)
- {
- XH_LOG_ERROR("do not ignore hook after refresh(): %s, %s", pathname_regex_str, symbol ? symbol : "ALL");
- return XH_ERRNO_INVAL;
- }
-
- if(0 != regcomp(®ex, pathname_regex_str, REG_NOSUB)) return XH_ERRNO_INVAL;
-
- if(NULL == (ii = malloc(sizeof(xh_core_ignore_info_t)))) return XH_ERRNO_NOMEM;
- if(NULL != symbol)
- {
- if(NULL == (ii->symbol = strdup(symbol)))
- {
- free(ii);
- return XH_ERRNO_NOMEM;
- }
- }
- else
- {
- ii->symbol = NULL; //ignore all symbols
- }
-#if XH_CORE_DEBUG
- if(NULL == (ii->pathname_regex_str = strdup(pathname_regex_str)))
- {
- free(ii->symbol);
- free(ii);
- return XH_ERRNO_NOMEM;
- }
-#endif
- ii->pathname_regex = regex;
-
- pthread_mutex_lock(&xh_core_mutex);
- TAILQ_INSERT_TAIL(&xh_core_ignore_info, ii, link);
- pthread_mutex_unlock(&xh_core_mutex);
-
- return 0;
-}
-
-static int xh_core_check_elf_header(uintptr_t base_addr, const char *pathname)
-{
- if(!xh_core_sigsegv_enable)
- {
- return xh_elf_check_elfheader(base_addr);
- }
- else
- {
- int ret = XH_ERRNO_UNKNOWN;
-
- xh_core_sigsegv_flag = 1;
- if(0 == sigsetjmp(xh_core_sigsegv_env, 1))
- {
- ret = xh_elf_check_elfheader(base_addr);
- }
- else
- {
- ret = XH_ERRNO_SEGVERR;
- XH_LOG_WARN("catch SIGSEGV when check_elfheader: %s", pathname);
- }
- xh_core_sigsegv_flag = 0;
- return ret;
- }
-}
-
-static void xh_core_hook_impl(xh_core_map_info_t *mi)
-{
- //init
- if(0 != xh_elf_init(&(mi->elf), mi->base_addr, mi->pathname)) return;
-
- //hook
- xh_core_hook_info_t *hi;
- xh_core_ignore_info_t *ii;
- int ignore;
- TAILQ_FOREACH(hi, &xh_core_hook_info, link) //find hook info
- {
- if(0 == regexec(&(hi->pathname_regex), mi->pathname, 0, NULL, 0))
- {
- ignore = 0;
- TAILQ_FOREACH(ii, &xh_core_ignore_info, link) //find ignore info
- {
- if(0 == regexec(&(ii->pathname_regex), mi->pathname, 0, NULL, 0))
- {
- if(NULL == ii->symbol) //ignore all symbols
- return;
-
- if(0 == strcmp(ii->symbol, hi->symbol)) //ignore the current symbol
- {
- ignore = 1;
- break;
- }
- }
- }
-
- if(0 == ignore)
- xh_elf_hook(&(mi->elf), hi->symbol, hi->new_func, hi->old_func);
- }
- }
-}
-
-static void xh_core_hook(xh_core_map_info_t *mi)
-{
- if(!xh_core_sigsegv_enable)
- {
- xh_core_hook_impl(mi);
- }
- else
- {
- xh_core_sigsegv_flag = 1;
- if(0 == sigsetjmp(xh_core_sigsegv_env, 1))
- {
- xh_core_hook_impl(mi);
- }
- else
- {
- XH_LOG_WARN("catch SIGSEGV when init or hook: %s", mi->pathname);
- }
- xh_core_sigsegv_flag = 0;
- }
-}
-
-static void xh_core_refresh_impl()
-{
- char line[512];
- FILE *fp;
- uintptr_t base_addr;
- char perm[5];
- unsigned long offset;
- int pathname_pos;
- char *pathname;
- size_t pathname_len;
- xh_core_map_info_t *mi, *mi_tmp;
- xh_core_map_info_t mi_key;
- xh_core_hook_info_t *hi;
- xh_core_ignore_info_t *ii;
- int match;
- xh_core_map_info_tree_t map_info_refreshed = RB_INITIALIZER(&map_info_refreshed);
-
- if(NULL == (fp = fopen("/proc/self/maps", "r")))
- {
- XH_LOG_ERROR("fopen /proc/self/maps failed");
- return;
- }
-
- while(fgets(line, sizeof(line), fp))
- {
- if(sscanf(line, "%"PRIxPTR"-%*lx %4s %lx %*x:%*x %*d%n", &base_addr, perm, &offset, &pathname_pos) != 3) continue;
-
- //check permission
- if(perm[0] != 'r') continue;
- if(perm[3] != 'p') continue; //do not touch the shared memory
-
- //check offset
- //
- //We are trying to find ELF header in memory.
- //It can only be found at the beginning of a mapped memory regions
- //whose offset is 0.
- if(0 != offset) continue;
-
- //get pathname
- while(isspace(line[pathname_pos]) && pathname_pos < (int)(sizeof(line) - 1))
- pathname_pos += 1;
- if(pathname_pos >= (int)(sizeof(line) - 1)) continue;
- pathname = line + pathname_pos;
- pathname_len = strlen(pathname);
- if(0 == pathname_len) continue;
- if(pathname[pathname_len - 1] == '\n')
- {
- pathname[pathname_len - 1] = '\0';
- pathname_len -= 1;
- }
- if(0 == pathname_len) continue;
- if('[' == pathname[0]) continue;
-
- //check pathname
- //if we need to hook this elf?
- match = 0;
- TAILQ_FOREACH(hi, &xh_core_hook_info, link) //find hook info
- {
- if(0 == regexec(&(hi->pathname_regex), pathname, 0, NULL, 0))
- {
- TAILQ_FOREACH(ii, &xh_core_ignore_info, link) //find ignore info
- {
- if(0 == regexec(&(ii->pathname_regex), pathname, 0, NULL, 0))
- {
- if(NULL == ii->symbol)
- goto check_finished;
-
- if(0 == strcmp(ii->symbol, hi->symbol))
- goto check_continue;
- }
- }
-
- match = 1;
- check_continue:
- break;
- }
- }
- check_finished:
- if(0 == match) continue;
-
- //check elf header format
- //We are trying to do ELF header checking as late as possible.
- if(0 != xh_core_check_elf_header(base_addr, pathname)) continue;
-
- //check existed map item
- mi_key.pathname = pathname;
- if(NULL != (mi = RB_FIND(xh_core_map_info_tree, &xh_core_map_info, &mi_key)))
- {
- //exist
- RB_REMOVE(xh_core_map_info_tree, &xh_core_map_info, mi);
-
- //repeated?
- //We only keep the first one, that is the real base address
- if(NULL != RB_INSERT(xh_core_map_info_tree, &map_info_refreshed, mi))
- {
-#if XH_CORE_DEBUG
- XH_LOG_DEBUG("repeated map info when update: %s", line);
-#endif
- free(mi->pathname);
- free(mi);
- continue;
- }
-
- //re-hook if base_addr changed
- if(mi->base_addr != base_addr)
- {
- mi->base_addr = base_addr;
- xh_core_hook(mi);
- }
- }
- else
- {
- //not exist, create a new map info
- if(NULL == (mi = (xh_core_map_info_t *)malloc(sizeof(xh_core_map_info_t)))) continue;
- if(NULL == (mi->pathname = strdup(pathname)))
- {
- free(mi);
- continue;
- }
- mi->base_addr = base_addr;
-
- //repeated?
- //We only keep the first one, that is the real base address
- if(NULL != RB_INSERT(xh_core_map_info_tree, &map_info_refreshed, mi))
- {
-#if XH_CORE_DEBUG
- XH_LOG_DEBUG("repeated map info when create: %s", line);
-#endif
- free(mi->pathname);
- free(mi);
- continue;
- }
-
- //hook
- xh_core_hook(mi); //hook
- }
- }
- fclose(fp);
-
- //free all missing map item, maybe dlclosed?
- RB_FOREACH_SAFE(mi, xh_core_map_info_tree, &xh_core_map_info, mi_tmp)
- {
-#if XH_CORE_DEBUG
- XH_LOG_DEBUG("remove missing map info: %s", mi->pathname);
-#endif
- RB_REMOVE(xh_core_map_info_tree, &xh_core_map_info, mi);
- if(mi->pathname) free(mi->pathname);
- free(mi);
- }
-
- //save the new refreshed map info tree
- xh_core_map_info = map_info_refreshed;
-
- XH_LOG_INFO("map refreshed");
-
-#if XH_CORE_DEBUG
- RB_FOREACH(mi, xh_core_map_info_tree, &xh_core_map_info)
- XH_LOG_DEBUG(" %"PRIxPTR" %s\n", mi->base_addr, mi->pathname);
-#endif
-}
-
-static void *xh_core_refresh_thread_func(void *arg)
-{
- (void)arg;
-
- pthread_setname_np(pthread_self(), "xh_refresh_loop");
-
- while(xh_core_refresh_thread_running)
- {
- //waiting for a refresh task or exit
- pthread_mutex_lock(&xh_core_mutex);
- while(!xh_core_refresh_thread_do && xh_core_refresh_thread_running)
- {
- pthread_cond_wait(&xh_core_cond, &xh_core_mutex);
- }
- if(!xh_core_refresh_thread_running)
- {
- pthread_mutex_unlock(&xh_core_mutex);
- break;
- }
- xh_core_refresh_thread_do = 0;
- pthread_mutex_unlock(&xh_core_mutex);
-
- //refresh
- pthread_mutex_lock(&xh_core_refresh_mutex);
- xh_core_refresh_impl();
- pthread_mutex_unlock(&xh_core_refresh_mutex);
- }
-
- return NULL;
-}
-
-static void xh_core_init_once()
-{
- if(xh_core_inited) return;
-
- pthread_mutex_lock(&xh_core_mutex);
-
- if(xh_core_inited) goto end;
-
- xh_core_inited = 1;
-
- //dump debug info
- XH_LOG_INFO("%s\n", xh_version_str_full());
-#if XH_CORE_DEBUG
- xh_core_hook_info_t *hi;
- TAILQ_FOREACH(hi, &xh_core_hook_info, link)
- XH_LOG_INFO(" hook: %s @ %s, (%p, %p)\n", hi->symbol, hi->pathname_regex_str,
- hi->new_func, hi->old_func);
- xh_core_ignore_info_t *ii;
- TAILQ_FOREACH(ii, &xh_core_ignore_info, link)
- XH_LOG_INFO(" ignore: %s @ %s\n", ii->symbol ? ii->symbol : "ALL ",
- ii->pathname_regex_str);
-#endif
-
- //register signal handler
- if(0 != xh_core_add_sigsegv_handler()) goto end;
-
- //OK
- xh_core_init_ok = 1;
-
- end:
- pthread_mutex_unlock(&xh_core_mutex);
-}
-
-static void xh_core_init_async_once()
-{
- if(xh_core_async_inited) return;
-
- pthread_mutex_lock(&xh_core_mutex);
-
- if(xh_core_async_inited) goto end;
-
- xh_core_async_inited = 1;
-
- //create async refresh thread
- xh_core_refresh_thread_running = 1;
- if(0 != pthread_create(&xh_core_refresh_thread_tid, NULL, &xh_core_refresh_thread_func, NULL))
- {
- xh_core_refresh_thread_running = 0;
- goto end;
- }
-
- //OK
- xh_core_async_init_ok = 1;
-
- end:
- pthread_mutex_unlock(&xh_core_mutex);
-}
-
-int xh_core_refresh(int async)
-{
- //init
- xh_core_init_once();
- if(!xh_core_init_ok) return XH_ERRNO_UNKNOWN;
-
- if(async)
- {
- //init for async
- xh_core_init_async_once();
- if(!xh_core_async_init_ok) return XH_ERRNO_UNKNOWN;
-
- //refresh async
- pthread_mutex_lock(&xh_core_mutex);
- xh_core_refresh_thread_do = 1;
- pthread_cond_signal(&xh_core_cond);
- pthread_mutex_unlock(&xh_core_mutex);
- }
- else
- {
- //refresh sync
- pthread_mutex_lock(&xh_core_refresh_mutex);
- xh_core_refresh_impl();
- pthread_mutex_unlock(&xh_core_refresh_mutex);
- }
-
- return 0;
-}
-
-void xh_core_clear()
-{
- //stop the async refresh thread
- if(xh_core_async_init_ok)
- {
- pthread_mutex_lock(&xh_core_mutex);
- xh_core_refresh_thread_running = 0;
- pthread_cond_signal(&xh_core_cond);
- pthread_mutex_unlock(&xh_core_mutex);
-
- pthread_join(xh_core_refresh_thread_tid, NULL);
- xh_core_async_init_ok = 0;
- }
- xh_core_async_inited = 0;
-
- //unregister the sig handler
- if(xh_core_init_ok)
- {
- xh_core_del_sigsegv_handler();
- xh_core_init_ok = 0;
- }
- xh_core_inited = 0;
-
- pthread_mutex_lock(&xh_core_mutex);
- pthread_mutex_lock(&xh_core_refresh_mutex);
-
- //free all map info
- xh_core_map_info_t *mi, *mi_tmp;
- RB_FOREACH_SAFE(mi, xh_core_map_info_tree, &xh_core_map_info, mi_tmp)
- {
- RB_REMOVE(xh_core_map_info_tree, &xh_core_map_info, mi);
- if(mi->pathname) free(mi->pathname);
- free(mi);
- }
-
- //free all hook info
- xh_core_hook_info_t *hi, *hi_tmp;
- TAILQ_FOREACH_SAFE(hi, &xh_core_hook_info, link, hi_tmp)
- {
- TAILQ_REMOVE(&xh_core_hook_info, hi, link);
-#if XH_CORE_DEBUG
- free(hi->pathname_regex_str);
-#endif
- regfree(&(hi->pathname_regex));
- free(hi->symbol);
- free(hi);
- }
-
- //free all ignore info
- xh_core_ignore_info_t *ii, *ii_tmp;
- TAILQ_FOREACH_SAFE(ii, &xh_core_ignore_info, link, ii_tmp)
- {
- TAILQ_REMOVE(&xh_core_ignore_info, ii, link);
-#if XH_CORE_DEBUG
- free(ii->pathname_regex_str);
-#endif
- regfree(&(ii->pathname_regex));
- free(ii->symbol);
- free(ii);
- }
-
- pthread_mutex_unlock(&xh_core_refresh_mutex);
- pthread_mutex_unlock(&xh_core_mutex);
-}
-
-void xh_core_enable_debug(int flag)
-{
- xh_log_priority = (flag ? ANDROID_LOG_DEBUG : ANDROID_LOG_WARN);
-}
-
-void xh_core_enable_sigsegv_protection(int flag)
-{
- xh_core_sigsegv_enable = (flag ? 1 : 0);
-}
diff --git a/riru-core/jni/external/xhook/xh_core.h b/riru-core/jni/external/xhook/xh_core.h
deleted file mode 100644
index 3508794..0000000
--- a/riru-core/jni/external/xhook/xh_core.h
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright (c) 2018-present, iQIYI, Inc. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
-
-// Created by caikelun on 2018-04-11.
-
-#ifndef XH_CORE_H
-#define XH_CORE_H 1
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-int xh_core_register(const char *pathname_regex_str, const char *symbol,
- void *new_func, void **old_func);
-
-int xh_core_ignore(const char *pathname_regex_str, const char *symbol);
-
-int xh_core_refresh(int async);
-
-void xh_core_clear();
-
-void xh_core_enable_debug(int flag);
-
-void xh_core_enable_sigsegv_protection(int flag);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/riru-core/jni/external/xhook/xh_elf.c b/riru-core/jni/external/xhook/xh_elf.c
deleted file mode 100644
index 286ed87..0000000
--- a/riru-core/jni/external/xhook/xh_elf.c
+++ /dev/null
@@ -1,1042 +0,0 @@
-// Copyright (c) 2018-present, iQIYI, Inc. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
-
-// Created by caikelun on 2018-04-11.
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include "xh_errno.h"
-#include "xh_log.h"
-#include "xh_util.h"
-#include "xh_elf.h"
-
-#define XH_ELF_DEBUG 0
-
-#ifndef EI_ABIVERSION
-#define EI_ABIVERSION 8
-#endif
-
-#if defined(__arm__)
-#define XH_ELF_R_GENERIC_JUMP_SLOT R_ARM_JUMP_SLOT //.rel.plt
-#define XH_ELF_R_GENERIC_GLOB_DAT R_ARM_GLOB_DAT //.rel.dyn
-#define XH_ELF_R_GENERIC_ABS R_ARM_ABS32 //.rel.dyn
-#elif defined(__aarch64__)
-#define XH_ELF_R_GENERIC_JUMP_SLOT R_AARCH64_JUMP_SLOT
-#define XH_ELF_R_GENERIC_GLOB_DAT R_AARCH64_GLOB_DAT
-#define XH_ELF_R_GENERIC_ABS R_AARCH64_ABS64
-#elif defined(__i386__)
-#define XH_ELF_R_GENERIC_JUMP_SLOT R_386_JMP_SLOT
-#define XH_ELF_R_GENERIC_GLOB_DAT R_386_GLOB_DAT
-#define XH_ELF_R_GENERIC_ABS R_386_32
-#elif defined(__x86_64__)
-#define XH_ELF_R_GENERIC_JUMP_SLOT R_X86_64_JUMP_SLOT
-#define XH_ELF_R_GENERIC_GLOB_DAT R_X86_64_GLOB_DAT
-#define XH_ELF_R_GENERIC_ABS R_X86_64_64
-#endif
-
-#if defined(__LP64__)
-#define XH_ELF_R_SYM(info) ELF64_R_SYM(info)
-#define XH_ELF_R_TYPE(info) ELF64_R_TYPE(info)
-#else
-#define XH_ELF_R_SYM(info) ELF32_R_SYM(info)
-#define XH_ELF_R_TYPE(info) ELF32_R_TYPE(info)
-#endif
-
-//iterator for plain PLT
-typedef struct
-{
- uint8_t *cur;
- uint8_t *end;
- int is_use_rela;
-} xh_elf_plain_reloc_iterator_t;
-
-static void xh_elf_plain_reloc_iterator_init(xh_elf_plain_reloc_iterator_t *self,
- ElfW(Addr) rel, ElfW(Word) rel_sz, int is_use_rela)
-{
- self->cur = (uint8_t *)rel;
- self->end = self->cur + rel_sz;
- self->is_use_rela = is_use_rela;
-}
-
-static void *xh_elf_plain_reloc_iterator_next(xh_elf_plain_reloc_iterator_t *self)
-{
- if(self->cur >= self->end) return NULL;
-
- self->cur += (self->is_use_rela ? sizeof(ElfW(Rela)) : sizeof(ElfW(Rel)));
- return (void *)(self->cur);
-}
-
-//sleb128 decoder
-typedef struct
-{
- uint8_t *cur;
- uint8_t *end;
-} xh_elf_sleb128_decoder_t;
-
-static void xh_elf_sleb128_decoder_init(xh_elf_sleb128_decoder_t *self,
- ElfW(Addr) rel, ElfW(Word) rel_sz)
-{
- self->cur = (uint8_t *)rel;
- self->end = self->cur + rel_sz;
-}
-
-static int xh_elf_sleb128_decoder_next(xh_elf_sleb128_decoder_t *self, size_t *ret)
-{
- size_t value = 0;
- static const size_t size = 8 * sizeof(value);
- size_t shift = 0;
- uint8_t byte;
-
- do
- {
- if(self->cur >= self->end)
- return XH_ERRNO_FORMAT;
-
- byte = *(self->cur)++;
- value |= ((size_t)(byte & 127) << shift);
- shift += 7;
- } while(byte & 128);
-
- if(shift < size && (byte & 64))
- {
- value |= -((size_t)(1) << shift);
- }
-
- *ret = value;
- return 0;
-}
-
-//iterator for sleb128 decoded packed PLT
-typedef struct
-{
- xh_elf_sleb128_decoder_t decoder;
- size_t relocation_count;
- size_t group_size;
- size_t group_flags;
- size_t group_r_offset_delta;
- size_t relocation_index;
- size_t relocation_group_index;
- ElfW(Rela) rela;
- ElfW(Rel) rel;
- ElfW(Addr) r_offset;
- size_t r_info;
- ssize_t r_addend;
- int is_use_rela;
-} xh_elf_packed_reloc_iterator_t;
-
-const size_t RELOCATION_GROUPED_BY_INFO_FLAG = 1;
-const size_t RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG = 2;
-const size_t RELOCATION_GROUPED_BY_ADDEND_FLAG = 4;
-const size_t RELOCATION_GROUP_HAS_ADDEND_FLAG = 8;
-
-static int xh_elf_packed_reloc_iterator_init(xh_elf_packed_reloc_iterator_t *self,
- ElfW(Addr) rel, ElfW(Word) rel_sz, int is_use_rela)
-{
- int r;
-
- memset(self, 0, sizeof(xh_elf_packed_reloc_iterator_t));
- xh_elf_sleb128_decoder_init(&(self->decoder), rel, rel_sz);
- self->is_use_rela = is_use_rela;
-
- if(0 != (r = xh_elf_sleb128_decoder_next(&(self->decoder), &(self->relocation_count)))) return r;
- if(0 != (r = xh_elf_sleb128_decoder_next(&(self->decoder), (size_t *)&(self->r_offset)))) return r;
- return 0;
-}
-
-static int xh_elf_packed_reloc_iterator_read_group_fields(xh_elf_packed_reloc_iterator_t *self)
-{
- int r;
- size_t val;
-
- if(0 != (r = xh_elf_sleb128_decoder_next(&(self->decoder), &(self->group_size)))) return r;
- if(0 != (r = xh_elf_sleb128_decoder_next(&(self->decoder), &(self->group_flags)))) return r;
-
- if(self->group_flags & RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG)
- if(0 != (r = xh_elf_sleb128_decoder_next(&(self->decoder), &(self->group_r_offset_delta)))) return r;
-
- if(self->group_flags & RELOCATION_GROUPED_BY_INFO_FLAG)
- if(0 != (r = xh_elf_sleb128_decoder_next(&(self->decoder), (size_t *)&(self->r_info)))) return r;
-
- if((self->group_flags & RELOCATION_GROUP_HAS_ADDEND_FLAG) &&
- (self->group_flags & RELOCATION_GROUPED_BY_ADDEND_FLAG))
- {
- if(0 == self->is_use_rela)
- {
- XH_LOG_ERROR("unexpected r_addend in android.rel section");
- return XH_ERRNO_FORMAT;
- }
- if(0 != (r = xh_elf_sleb128_decoder_next(&(self->decoder), &val))) return r;
- self->r_addend += (ssize_t)val;
- }
- else if(0 == (self->group_flags & RELOCATION_GROUP_HAS_ADDEND_FLAG))
- {
- self->r_addend = 0;
- }
-
- self->relocation_group_index = 0;
- return 0;
-}
-
-static void *xh_elf_packed_reloc_iterator_next(xh_elf_packed_reloc_iterator_t *self)
-{
- size_t val;
-
- if(self->relocation_index >= self->relocation_count) return NULL;
-
- if(self->relocation_group_index == self->group_size)
- {
- if(0 != xh_elf_packed_reloc_iterator_read_group_fields(self)) return NULL;
- }
-
- if(self->group_flags & RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG)
- {
- self->r_offset += self->group_r_offset_delta;
- }
- else
- {
- if(0 != xh_elf_sleb128_decoder_next(&(self->decoder), &val)) return NULL;
- self->r_offset += val;
- }
-
- if(0 == (self->group_flags & RELOCATION_GROUPED_BY_INFO_FLAG))
- if(0 != xh_elf_sleb128_decoder_next(&(self->decoder), &(self->r_info))) return NULL;
-
- if(self->is_use_rela &&
- (self->group_flags & RELOCATION_GROUP_HAS_ADDEND_FLAG) &&
- (0 == (self->group_flags & RELOCATION_GROUPED_BY_ADDEND_FLAG)))
- {
- if(0 != xh_elf_sleb128_decoder_next(&(self->decoder), &val)) return NULL;
- self->r_addend += (ssize_t)val;
- }
-
- self->relocation_index++;
- self->relocation_group_index++;
-
- if(self->is_use_rela)
- {
- self->rela.r_offset = self->r_offset;
- self->rela.r_info = self->r_info;
- self->rela.r_addend = self->r_addend;
- return (void *)(&(self->rela));
- }
- else
- {
- self->rel.r_offset = self->r_offset;
- self->rel.r_info = self->r_info;
- return (void *)(&(self->rel));
- }
-}
-
-//ELF header checker
-int xh_elf_check_elfheader(uintptr_t base_addr)
-{
- ElfW(Ehdr) *ehdr = (ElfW(Ehdr) *)base_addr;
-
- //check magic
- if(0 != memcmp(ehdr->e_ident, ELFMAG, SELFMAG)) return XH_ERRNO_FORMAT;
-
- //check class (64/32)
-#if defined(__LP64__)
- if(ELFCLASS64 != ehdr->e_ident[EI_CLASS]) return XH_ERRNO_FORMAT;
-#else
- if(ELFCLASS32 != ehdr->e_ident[EI_CLASS]) return XH_ERRNO_FORMAT;
-#endif
-
- //check endian (little/big)
- if(ELFDATA2LSB != ehdr->e_ident[EI_DATA]) return XH_ERRNO_FORMAT;
-
- //check version
- if(EV_CURRENT != ehdr->e_ident[EI_VERSION]) return XH_ERRNO_FORMAT;
-
- //check type
- if(ET_EXEC != ehdr->e_type && ET_DYN != ehdr->e_type) return XH_ERRNO_FORMAT;
-
- //check machine
-#if defined(__arm__)
- if(EM_ARM != ehdr->e_machine) return XH_ERRNO_FORMAT;
-#elif defined(__aarch64__)
- if(EM_AARCH64 != ehdr->e_machine) return XH_ERRNO_FORMAT;
-#elif defined(__i386__)
- if(EM_386 != ehdr->e_machine) return XH_ERRNO_FORMAT;
-#elif defined(__x86_64__)
- if(EM_X86_64 != ehdr->e_machine) return XH_ERRNO_FORMAT;
-#else
- return XH_ERRNO_FORMAT;
-#endif
-
- //check version
- if(EV_CURRENT != ehdr->e_version) return XH_ERRNO_FORMAT;
-
- return 0;
-}
-
-//ELF hash func
-static uint32_t xh_elf_hash(const uint8_t *name)
-{
- uint32_t h = 0, g;
-
- while (*name) {
- h = (h << 4) + *name++;
- g = h & 0xf0000000;
- h ^= g;
- h ^= g >> 24;
- }
-
- return h;
-}
-
-//GNU hash func
-static uint32_t xh_elf_gnu_hash(const uint8_t *name)
-{
- uint32_t h = 5381;
-
- while(*name != 0)
- {
- h += (h << 5) + *name++;
- }
- return h;
-}
-
-static ElfW(Phdr) *xh_elf_get_first_segment_by_type(xh_elf_t *self, ElfW(Word) type)
-{
- ElfW(Phdr) *phdr;
-
- for(phdr = self->phdr; phdr < self->phdr + self->ehdr->e_phnum; phdr++)
- {
- if(phdr->p_type == type)
- {
- return phdr;
- }
- }
- return NULL;
-}
-
-static ElfW(Phdr) *xh_elf_get_first_segment_by_type_offset(xh_elf_t *self, ElfW(Word) type, ElfW(Off) offset)
-{
- ElfW(Phdr) *phdr;
-
- for(phdr = self->phdr; phdr < self->phdr + self->ehdr->e_phnum; phdr++)
- {
- if(phdr->p_type == type && phdr->p_offset == offset)
- {
- return phdr;
- }
- }
- return NULL;
-}
-
-static int xh_elf_hash_lookup(xh_elf_t *self, const char *symbol, uint32_t *symidx)
-{
- uint32_t hash = xh_elf_hash((uint8_t *)symbol);
- const char *symbol_cur;
- uint32_t i;
-
- for(i = self->bucket[hash % self->bucket_cnt]; 0 != i; i = self->chain[i])
- {
- symbol_cur = self->strtab + self->symtab[i].st_name;
-
- if(0 == strcmp(symbol, symbol_cur))
- {
- *symidx = i;
- XH_LOG_INFO("found %s at symidx: %u (ELF_HASH)\n", symbol, *symidx);
- return 0;
- }
- }
-
- return XH_ERRNO_NOTFND;
-}
-
-static int xh_elf_gnu_hash_lookup_def(xh_elf_t *self, const char *symbol, uint32_t *symidx)
-{
- uint32_t hash = xh_elf_gnu_hash((uint8_t *)symbol);
-
- static uint32_t elfclass_bits = sizeof(ElfW(Addr)) * 8;
- size_t word = self->bloom[(hash / elfclass_bits) % self->bloom_sz];
- size_t mask = 0
- | (size_t)1 << (hash % elfclass_bits)
- | (size_t)1 << ((hash >> self->bloom_shift) % elfclass_bits);
-
- //if at least one bit is not set, this symbol is surely missing
- if((word & mask) != mask) return XH_ERRNO_NOTFND;
-
- //ignore STN_UNDEF
- uint32_t i = self->bucket[hash % self->bucket_cnt];
- if(i < self->symoffset) return XH_ERRNO_NOTFND;
-
- //loop through the chain
- while(1)
- {
- const char *symname = self->strtab + self->symtab[i].st_name;
- const uint32_t symhash = self->chain[i - self->symoffset];
-
- if((hash | (uint32_t)1) == (symhash | (uint32_t)1) && 0 == strcmp(symbol, symname))
- {
- *symidx = i;
- XH_LOG_INFO("found %s at symidx: %u (GNU_HASH DEF)\n", symbol, *symidx);
- return 0;
- }
-
- //chain ends with an element with the lowest bit set to 1
- if(symhash & (uint32_t)1) break;
-
- i++;
- }
-
- return XH_ERRNO_NOTFND;
-}
-
-static int xh_elf_gnu_hash_lookup_undef(xh_elf_t *self, const char *symbol, uint32_t *symidx)
-{
- uint32_t i;
-
- for(i = 0; i < self->symoffset; i++)
- {
- const char *symname = self->strtab + self->symtab[i].st_name;
- if(0 == strcmp(symname, symbol))
- {
- *symidx = i;
- XH_LOG_INFO("found %s at symidx: %u (GNU_HASH UNDEF)\n", symbol, *symidx);
- return 0;
- }
- }
- return XH_ERRNO_NOTFND;
-}
-
-static int xh_elf_gnu_hash_lookup(xh_elf_t *self, const char *symbol, uint32_t *symidx)
-{
- if(0 == xh_elf_gnu_hash_lookup_def(self, symbol, symidx)) return 0;
- if(0 == xh_elf_gnu_hash_lookup_undef(self, symbol, symidx)) return 0;
- return XH_ERRNO_NOTFND;
-}
-
-static int xh_elf_find_symidx_by_name(xh_elf_t *self, const char *symbol, uint32_t *symidx)
-{
- if(self->is_use_gnu_hash)
- return xh_elf_gnu_hash_lookup(self, symbol, symidx);
- else
- return xh_elf_hash_lookup(self, symbol, symidx);
-}
-
-static int xh_elf_replace_function(xh_elf_t *self, const char *symbol, ElfW(Addr) addr, void *new_func, void **old_func)
-{
- void *old_addr;
- unsigned int old_prot = 0;
- unsigned int need_prot = PROT_READ | PROT_WRITE;
- int r;
-
- //already replaced?
- //here we assume that we always have read permission, is this a problem?
- if(*(void **)addr == new_func) return 0;
-
- //get old prot
- if(0 != (r = xh_util_get_addr_protect(addr, self->pathname, &old_prot)))
- {
- XH_LOG_ERROR("get addr prot failed. ret: %d", r);
- return r;
- }
-
- if(old_prot != need_prot)
- {
- //set new prot
- if(0 != (r = xh_util_set_addr_protect(addr, need_prot)))
- {
- XH_LOG_ERROR("set addr prot failed. ret: %d", r);
- return r;
- }
- }
-
- //save old func
- old_addr = *(void **)addr;
- if(NULL != old_func) *old_func = old_addr;
-
- //replace func
- *(void **)addr = new_func; //segmentation fault sometimes
-
- if(old_prot != need_prot)
- {
- //restore the old prot
- if(0 != (r = xh_util_set_addr_protect(addr, old_prot)))
- {
- XH_LOG_WARN("restore addr prot failed. ret: %d", r);
- }
- }
-
- //clear cache
- xh_util_flush_instruction_cache(addr);
-
- XH_LOG_INFO("XH_HK_OK %p: %p -> %p %s %s\n", (void *)addr, old_addr, new_func, symbol, self->pathname);
- return 0;
-}
-
-static int xh_elf_check(xh_elf_t *self)
-{
- if(0 == self->base_addr)
- {
- XH_LOG_ERROR("base_addr == 0\n");
- return 1;
- }
- if(0 == self->bias_addr)
- {
- XH_LOG_ERROR("bias_addr == 0\n");
- return 1;
- }
- if(NULL == self->ehdr)
- {
- XH_LOG_ERROR("ehdr == NULL\n");
- return 1;
- }
- if(NULL == self->phdr)
- {
- XH_LOG_ERROR("phdr == NULL\n");
- return 1;
- }
- if(NULL == self->strtab)
- {
- XH_LOG_ERROR("strtab == NULL\n");
- return 1;
- }
- if(NULL == self->symtab)
- {
- XH_LOG_ERROR("symtab == NULL\n");
- return 1;
- }
- if(NULL == self->bucket)
- {
- XH_LOG_ERROR("bucket == NULL\n");
- return 1;
- }
- if(NULL == self->chain)
- {
- XH_LOG_ERROR("chain == NULL\n");
- return 1;
- }
- if(1 == self->is_use_gnu_hash && NULL == self->bloom)
- {
- XH_LOG_ERROR("bloom == NULL\n");
- return 1;
- }
-
- return 0;
-}
-
-#if XH_ELF_DEBUG
-
-static void xh_elf_dump_elfheader(xh_elf_t *self)
-{
- static char alpha_tab[17] = "0123456789ABCDEF";
- int i;
- uint8_t ch;
- char buff[EI_NIDENT * 3 + 1];
-
- for(i = 0; i < EI_NIDENT; i++)
- {
- ch = self->ehdr->e_ident[i];
- buff[i * 3 + 0] = alpha_tab[(int)((ch >> 4) & 0x0F)];
- buff[i * 3 + 1] = alpha_tab[(int)(ch & 0x0F)];
- buff[i * 3 + 2] = ' ';
- }
- buff[EI_NIDENT * 3] = '\0';
-
- XH_LOG_DEBUG("Elf Header:\n");
- XH_LOG_DEBUG(" Magic: %s\n", buff);
- XH_LOG_DEBUG(" Class: %#x\n", self->ehdr->e_ident[EI_CLASS]);
- XH_LOG_DEBUG(" Data: %#x\n", self->ehdr->e_ident[EI_DATA]);
- XH_LOG_DEBUG(" Version: %#x\n", self->ehdr->e_ident[EI_VERSION]);
- XH_LOG_DEBUG(" OS/ABI: %#x\n", self->ehdr->e_ident[EI_OSABI]);
- XH_LOG_DEBUG(" ABI Version: %#x\n", self->ehdr->e_ident[EI_ABIVERSION]);
- XH_LOG_DEBUG(" Type: %#x\n", self->ehdr->e_type);
- XH_LOG_DEBUG(" Machine: %#x\n", self->ehdr->e_machine);
- XH_LOG_DEBUG(" Version: %#x\n", self->ehdr->e_version);
- XH_LOG_DEBUG(" Entry point address: %"XH_UTIL_FMT_X"\n", self->ehdr->e_entry);
- XH_LOG_DEBUG(" Start of program headers: %"XH_UTIL_FMT_X" (bytes into file)\n", self->ehdr->e_phoff);
- XH_LOG_DEBUG(" Start of section headers: %"XH_UTIL_FMT_X" (bytes into file)\n", self->ehdr->e_shoff);
- XH_LOG_DEBUG(" Flags: %#x\n", self->ehdr->e_flags);
- XH_LOG_DEBUG(" Size of this header: %u (bytes)\n", self->ehdr->e_ehsize);
- XH_LOG_DEBUG(" Size of program headers: %u (bytes)\n", self->ehdr->e_phentsize);
- XH_LOG_DEBUG(" Number of program headers: %u\n", self->ehdr->e_phnum);
- XH_LOG_DEBUG(" Size of section headers: %u (bytes)\n", self->ehdr->e_shentsize);
- XH_LOG_DEBUG(" Number of section headers: %u\n", self->ehdr->e_shnum);
- XH_LOG_DEBUG(" Section header string table index: %u\n", self->ehdr->e_shstrndx);
-}
-
-static void xh_elf_dump_programheader(xh_elf_t *self)
-{
- ElfW(Phdr) *phdr = self->phdr;
- size_t i;
-
- XH_LOG_DEBUG("Program Headers:\n");
- XH_LOG_DEBUG(" %-8s " \
- "%-"XH_UTIL_FMT_FIXED_S" " \
- "%-"XH_UTIL_FMT_FIXED_S" " \
- "%-"XH_UTIL_FMT_FIXED_S" " \
- "%-"XH_UTIL_FMT_FIXED_S" " \
- "%-"XH_UTIL_FMT_FIXED_S" " \
- "%-8s " \
- "%-s\n",
- "Type",
- "Offset",
- "VirtAddr",
- "PhysAddr",
- "FileSiz",
- "MemSiz",
- "Flg",
- "Align");
- for(i = 0; i < self->ehdr->e_phnum; i++, phdr++)
- {
- XH_LOG_DEBUG(" %-8x " \
- "%."XH_UTIL_FMT_FIXED_X" " \
- "%."XH_UTIL_FMT_FIXED_X" " \
- "%."XH_UTIL_FMT_FIXED_X" " \
- "%."XH_UTIL_FMT_FIXED_X" " \
- "%."XH_UTIL_FMT_FIXED_X" " \
- "%-8x " \
- "%"XH_UTIL_FMT_X"\n",
- phdr->p_type,
- phdr->p_offset,
- phdr->p_vaddr,
- phdr->p_paddr,
- phdr->p_filesz,
- phdr->p_memsz,
- phdr->p_flags,
- phdr->p_align);
- }
-}
-
-static void xh_elf_dump_dynamic(xh_elf_t *self)
-{
- ElfW(Dyn) *dyn = self->dyn;
- size_t dyn_cnt = (self->dyn_sz / sizeof(ElfW(Dyn)));
- size_t i;
-
- XH_LOG_DEBUG("Dynamic section contains %zu entries:\n", dyn_cnt);
- XH_LOG_DEBUG(" %-"XH_UTIL_FMT_FIXED_S" " \
- "%s\n",
- "Tag",
- "Val");
- for(i = 0; i < dyn_cnt; i++, dyn++)
- {
- XH_LOG_DEBUG(" %-"XH_UTIL_FMT_FIXED_X" " \
- "%-"XH_UTIL_FMT_X"\n",
- dyn->d_tag,
- dyn->d_un.d_val);
- }
-}
-
-static void xh_elf_dump_rel(xh_elf_t *self, const char *type, ElfW(Addr) rel_addr, ElfW(Word) rel_sz)
-{
- ElfW(Rela) *rela;
- ElfW(Rel) *rel;
- ElfW(Word) cnt;
- ElfW(Word) i;
- ElfW(Sym) *sym;
-
- if(self->is_use_rela)
- {
- rela = (ElfW(Rela) *)(rel_addr);
- cnt = rel_sz / sizeof(ElfW(Rela));
- }
- else
- {
- rel = (ElfW(Rel) *)(rel_addr);
- cnt = rel_sz / sizeof(ElfW(Rel));
- }
-
- XH_LOG_DEBUG("Relocation section '.rel%s%s' contains %u entries:\n",
- (self->is_use_rela ? "a" : ""), type, cnt);
- XH_LOG_DEBUG(" %-"XH_UTIL_FMT_FIXED_S" " \
- "%-"XH_UTIL_FMT_FIXED_S" " \
- "%-8s " \
- "%-8s " \
- "%-8s " \
- "%s\n",
- "Offset",
- "Info",
- "Type",
- "Sym.Idx",
- "Sym.Val",
- "Sym.Name");
- const char *fmt = " %."XH_UTIL_FMT_FIXED_X" " \
- "%."XH_UTIL_FMT_FIXED_X" " \
- "%.8x " \
- "%.8u " \
- "%.8x " \
- "%s\n";
- for(i = 0; i < cnt; i++)
- {
- if(self->is_use_rela)
- {
- sym = &(self->symtab[XH_ELF_R_SYM(rela[i].r_info)]);
- XH_LOG_DEBUG(fmt,
- rela[i].r_offset,
- rela[i].r_info,
- XH_ELF_R_TYPE(rela[i].r_info),
- XH_ELF_R_SYM(rela[i].r_info),
- sym->st_value,
- self->strtab + sym->st_name);
- }
- else
- {
- sym = &(self->symtab[XH_ELF_R_SYM(rel[i].r_info)]);
- XH_LOG_DEBUG(fmt,
- rel[i].r_offset,
- rel[i].r_info,
- XH_ELF_R_TYPE(rel[i].r_info),
- XH_ELF_R_SYM(rel[i].r_info),
- sym->st_value,
- self->strtab + sym->st_name);
- }
- }
-}
-
-static void xh_elf_dump_symtab(xh_elf_t *self)
-{
- if(self->is_use_gnu_hash) return;
-
- ElfW(Word) symtab_cnt = self->chain_cnt;
- ElfW(Word) i;
-
- XH_LOG_DEBUG("Symbol table '.dynsym' contains %u entries:\n", symtab_cnt);
- XH_LOG_DEBUG(" %-8s " \
- "%-"XH_UTIL_FMT_FIXED_S" " \
- "%s\n",
- "Idx",
- "Value",
- "Name");
- for(i = 0; i < symtab_cnt; i++)
- {
- XH_LOG_DEBUG(" %-8u " \
- "%."XH_UTIL_FMT_FIXED_X" " \
- "%s\n",
- i,
- self->symtab[i].st_value,
- self->strtab + self->symtab[i].st_name);
- }
-}
-
-static void xh_elf_dump(xh_elf_t *self)
-{
- if(xh_log_priority < ANDROID_LOG_DEBUG) return;
-
- XH_LOG_DEBUG("Elf Pathname: %s\n", self->pathname);
- XH_LOG_DEBUG("Elf bias addr: %p\n", (void *)self->bias_addr);
- xh_elf_dump_elfheader(self);
- xh_elf_dump_programheader(self);
- xh_elf_dump_dynamic(self);
- xh_elf_dump_rel(self, ".plt", self->relplt, self->relplt_sz);
- xh_elf_dump_rel(self, ".dyn", self->reldyn, self->reldyn_sz);
- xh_elf_dump_symtab(self);
-}
-
-#endif
-
-int xh_elf_init(xh_elf_t *self, uintptr_t base_addr, const char *pathname)
-{
- if(0 == base_addr || NULL == pathname) return XH_ERRNO_INVAL;
-
- //always reset
- memset(self, 0, sizeof(xh_elf_t));
-
- self->pathname = pathname;
- self->base_addr = (ElfW(Addr))base_addr;
- self->ehdr = (ElfW(Ehdr) *)base_addr;
- self->phdr = (ElfW(Phdr) *)(base_addr + self->ehdr->e_phoff); //segmentation fault sometimes
-
- //find the first load-segment with offset 0
- ElfW(Phdr) *phdr0 = xh_elf_get_first_segment_by_type_offset(self, PT_LOAD, 0);
- if(NULL == phdr0)
- {
- XH_LOG_ERROR("Can NOT found the first load segment. %s", pathname);
- return XH_ERRNO_FORMAT;
- }
-
-#if XH_ELF_DEBUG
- if(0 != phdr0->p_vaddr)
- XH_LOG_DEBUG("first load-segment vaddr NOT 0 (vaddr: %p). %s",
- (void *)(phdr0->p_vaddr), pathname);
-#endif
-
- //save load bias addr
- if(self->base_addr < phdr0->p_vaddr) return XH_ERRNO_FORMAT;
- self->bias_addr = self->base_addr - phdr0->p_vaddr;
-
- //find dynamic-segment
- ElfW(Phdr) *dhdr = xh_elf_get_first_segment_by_type(self, PT_DYNAMIC);
- if(NULL == dhdr)
- {
- XH_LOG_ERROR("Can NOT found dynamic segment. %s", pathname);
- return XH_ERRNO_FORMAT;
- }
-
- //parse dynamic-segment
- self->dyn = (ElfW(Dyn) *)(self->bias_addr + dhdr->p_vaddr);
- self->dyn_sz = dhdr->p_memsz;
- ElfW(Dyn) *dyn = self->dyn;
- ElfW(Dyn) *dyn_end = self->dyn + (self->dyn_sz / sizeof(ElfW(Dyn)));
- uint32_t *raw;
- for(; dyn < dyn_end; dyn++)
- {
- switch(dyn->d_tag) //segmentation fault sometimes
- {
- case DT_NULL:
- //the end of the dynamic-section
- dyn = dyn_end;
- break;
- case DT_STRTAB:
- {
- self->strtab = (const char *)(self->bias_addr + dyn->d_un.d_ptr);
- if((ElfW(Addr))(self->strtab) < self->base_addr) return XH_ERRNO_FORMAT;
- break;
- }
- case DT_SYMTAB:
- {
- self->symtab = (ElfW(Sym) *)(self->bias_addr + dyn->d_un.d_ptr);
- if((ElfW(Addr))(self->symtab) < self->base_addr) return XH_ERRNO_FORMAT;
- break;
- }
- case DT_PLTREL:
- //use rel or rela?
- self->is_use_rela = (dyn->d_un.d_val == DT_RELA ? 1 : 0);
- break;
- case DT_JMPREL:
- {
- self->relplt = (ElfW(Addr))(self->bias_addr + dyn->d_un.d_ptr);
- if((ElfW(Addr))(self->relplt) < self->base_addr) return XH_ERRNO_FORMAT;
- break;
- }
- case DT_PLTRELSZ:
- self->relplt_sz = dyn->d_un.d_val;
- break;
- case DT_REL:
- case DT_RELA:
- {
- self->reldyn = (ElfW(Addr))(self->bias_addr + dyn->d_un.d_ptr);
- if((ElfW(Addr))(self->reldyn) < self->base_addr) return XH_ERRNO_FORMAT;
- break;
- }
- case DT_RELSZ:
- case DT_RELASZ:
- self->reldyn_sz = dyn->d_un.d_val;
- break;
- case DT_ANDROID_REL:
- case DT_ANDROID_RELA:
- {
- self->relandroid = (ElfW(Addr))(self->bias_addr + dyn->d_un.d_ptr);
- if((ElfW(Addr))(self->relandroid) < self->base_addr) return XH_ERRNO_FORMAT;
- break;
- }
- case DT_ANDROID_RELSZ:
- case DT_ANDROID_RELASZ:
- self->relandroid_sz = dyn->d_un.d_val;
- break;
- case DT_HASH:
- {
- raw = (uint32_t *)(self->bias_addr + dyn->d_un.d_ptr);
- if((ElfW(Addr))raw < self->base_addr) return XH_ERRNO_FORMAT;
- self->bucket_cnt = raw[0];
- self->chain_cnt = raw[1];
- self->bucket = &raw[2];
- self->chain = &(self->bucket[self->bucket_cnt]);
- break;
- }
- case DT_GNU_HASH:
- {
- raw = (uint32_t *)(self->bias_addr + dyn->d_un.d_ptr);
- if((ElfW(Addr))raw < self->base_addr) return XH_ERRNO_FORMAT;
- self->bucket_cnt = raw[0];
- self->symoffset = raw[1];
- self->bloom_sz = raw[2];
- self->bloom_shift = raw[3];
- self->bloom = (ElfW(Addr) *)(&raw[4]);
- self->bucket = (uint32_t *)(&(self->bloom[self->bloom_sz]));
- self->chain = (uint32_t *)(&(self->bucket[self->bucket_cnt]));
- self->is_use_gnu_hash = 1;
- break;
- }
- default:
- break;
- }
- }
-
- //check android rel/rela
- if(0 != self->relandroid)
- {
- const char *rel = (const char *)self->relandroid;
- if(self->relandroid_sz < 4 ||
- rel[0] != 'A' ||
- rel[1] != 'P' ||
- rel[2] != 'S' ||
- rel[3] != '2')
- {
- XH_LOG_ERROR("android rel/rela format error\n");
- return XH_ERRNO_FORMAT;
- }
-
- self->relandroid += 4;
- self->relandroid_sz -= 4;
- }
-
- //check elf info
- if(0 != xh_elf_check(self))
- {
- XH_LOG_ERROR("elf init check failed. %s", pathname);
- return XH_ERRNO_FORMAT;
- }
-
-#if XH_ELF_DEBUG
- xh_elf_dump(self);
-#endif
-
- XH_LOG_INFO("init OK: %s (%s %s PLT:%u DYN:%u ANDROID:%u)\n", self->pathname,
- self->is_use_rela ? "RELA" : "REL",
- self->is_use_gnu_hash ? "GNU_HASH" : "ELF_HASH",
- self->relplt_sz, self->reldyn_sz, self->relandroid_sz);
-
- return 0;
-}
-
-static int xh_elf_find_and_replace_func(xh_elf_t *self, const char *section,
- int is_plt, const char *symbol,
- void *new_func, void **old_func,
- uint32_t symidx, void *rel_common,
- int *found)
-{
- ElfW(Rela) *rela;
- ElfW(Rel) *rel;
- ElfW(Addr) r_offset;
- size_t r_info;
- size_t r_sym;
- size_t r_type;
- ElfW(Addr) addr;
- int r;
-
- if(NULL != found) *found = 0;
-
- if(self->is_use_rela)
- {
- rela = (ElfW(Rela) *)rel_common;
- r_info = rela->r_info;
- r_offset = rela->r_offset;
- }
- else
- {
- rel = (ElfW(Rel) *)rel_common;
- r_info = rel->r_info;
- r_offset = rel->r_offset;
- }
-
- //check sym
- r_sym = XH_ELF_R_SYM(r_info);
- if(r_sym != symidx) return 0;
-
- //check type
- r_type = XH_ELF_R_TYPE(r_info);
- if(is_plt && r_type != XH_ELF_R_GENERIC_JUMP_SLOT) return 0;
- if(!is_plt && (r_type != XH_ELF_R_GENERIC_GLOB_DAT && r_type != XH_ELF_R_GENERIC_ABS)) return 0;
-
- //we found it
- XH_LOG_INFO("found %s at %s offset: %p\n", symbol, section, (void *)r_offset);
- if(NULL != found) *found = 1;
-
- //do replace
- addr = self->bias_addr + r_offset;
- if(addr < self->base_addr) return XH_ERRNO_FORMAT;
- if(0 != (r = xh_elf_replace_function(self, symbol, addr, new_func, old_func)))
- {
- XH_LOG_ERROR("replace function failed: %s at %s\n", symbol, section);
- return r;
- }
-
- return 0;
-}
-
-int xh_elf_hook(xh_elf_t *self, const char *symbol, void *new_func, void **old_func)
-{
- uint32_t symidx;
- void *rel_common;
- xh_elf_plain_reloc_iterator_t plain_iter;
- xh_elf_packed_reloc_iterator_t packed_iter;
- int found;
- int r;
-
- if(NULL == self->pathname)
- {
- XH_LOG_ERROR("not inited\n");
- return XH_ERRNO_ELFINIT; //not inited?
- }
-
- if(NULL == symbol || NULL == new_func) return XH_ERRNO_INVAL;
-
- XH_LOG_INFO("hooking %s in %s\n", symbol, self->pathname);
-
- //find symbol index by symbol name
- if(0 != (r = xh_elf_find_symidx_by_name(self, symbol, &symidx))) return 0;
-
- //replace for .rel(a).plt
- if(0 != self->relplt)
- {
- xh_elf_plain_reloc_iterator_init(&plain_iter, self->relplt, self->relplt_sz, self->is_use_rela);
- while(NULL != (rel_common = xh_elf_plain_reloc_iterator_next(&plain_iter)))
- {
- if(0 != (r = xh_elf_find_and_replace_func(self,
- (self->is_use_rela ? ".rela.plt" : ".rel.plt"), 1,
- symbol, new_func, old_func,
- symidx, rel_common, &found))) return r;
- if(found) break;
- }
- }
-
- //replace for .rel(a).dyn
- if(0 != self->reldyn)
- {
- xh_elf_plain_reloc_iterator_init(&plain_iter, self->reldyn, self->reldyn_sz, self->is_use_rela);
- while(NULL != (rel_common = xh_elf_plain_reloc_iterator_next(&plain_iter)))
- {
- if(0 != (r = xh_elf_find_and_replace_func(self,
- (self->is_use_rela ? ".rela.dyn" : ".rel.dyn"), 0,
- symbol, new_func, old_func,
- symidx, rel_common, NULL))) return r;
- }
- }
-
- //replace for .rel(a).android
- if(0 != self->relandroid)
- {
- xh_elf_packed_reloc_iterator_init(&packed_iter, self->relandroid, self->relandroid_sz, self->is_use_rela);
- while(NULL != (rel_common = xh_elf_packed_reloc_iterator_next(&packed_iter)))
- {
- if(0 != (r = xh_elf_find_and_replace_func(self,
- (self->is_use_rela ? ".rela.android" : ".rel.android"), 0,
- symbol, new_func, old_func,
- symidx, rel_common, NULL))) return r;
- }
- }
-
- return 0;
-}
diff --git a/riru-core/jni/external/xhook/xh_elf.h b/riru-core/jni/external/xhook/xh_elf.h
deleted file mode 100644
index 1697dc4..0000000
--- a/riru-core/jni/external/xhook/xh_elf.h
+++ /dev/null
@@ -1,85 +0,0 @@
-// Copyright (c) 2018-present, iQIYI, Inc. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
-
-// Created by caikelun on 2018-04-11.
-
-#ifndef XH_ELF_H
-#define XH_ELF_H 1
-
-#include
-#include
-#include
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef struct
-{
- const char *pathname;
-
- ElfW(Addr) base_addr;
- ElfW(Addr) bias_addr;
-
- ElfW(Ehdr) *ehdr;
- ElfW(Phdr) *phdr;
-
- ElfW(Dyn) *dyn; //.dynamic
- ElfW(Word) dyn_sz;
-
- const char *strtab; //.dynstr (string-table)
- ElfW(Sym) *symtab; //.dynsym (symbol-index to string-table's offset)
-
- ElfW(Addr) relplt; //.rel.plt or .rela.plt
- ElfW(Word) relplt_sz;
-
- ElfW(Addr) reldyn; //.rel.dyn or .rela.dyn
- ElfW(Word) reldyn_sz;
-
- ElfW(Addr) relandroid; //android compressed rel or rela
- ElfW(Word) relandroid_sz;
-
- //for ELF hash
- uint32_t *bucket;
- uint32_t bucket_cnt;
- uint32_t *chain;
- uint32_t chain_cnt; //invalid for GNU hash
-
- //append for GNU hash
- uint32_t symoffset;
- ElfW(Addr) *bloom;
- uint32_t bloom_sz;
- uint32_t bloom_shift;
-
- int is_use_rela;
- int is_use_gnu_hash;
-} xh_elf_t;
-
-int xh_elf_init(xh_elf_t *self, uintptr_t base_addr, const char *pathname);
-int xh_elf_hook(xh_elf_t *self, const char *symbol, void *new_func, void **old_func);
-
-int xh_elf_check_elfheader(uintptr_t base_addr);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/riru-core/jni/external/xhook/xh_errno.h b/riru-core/jni/external/xhook/xh_errno.h
deleted file mode 100644
index e628cd7..0000000
--- a/riru-core/jni/external/xhook/xh_errno.h
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright (c) 2018-present, iQIYI, Inc. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
-
-// Created by caikelun on 2018-04-11.
-
-#ifndef XH_ERRNO_H
-#define XH_ERRNO_H 1
-
-#define XH_ERRNO_UNKNOWN 1001
-#define XH_ERRNO_INVAL 1002
-#define XH_ERRNO_NOMEM 1003
-#define XH_ERRNO_REPEAT 1004
-#define XH_ERRNO_NOTFND 1005
-#define XH_ERRNO_BADMAPS 1006
-#define XH_ERRNO_FORMAT 1007
-#define XH_ERRNO_ELFINIT 1008
-#define XH_ERRNO_SEGVERR 1009
-
-#endif
diff --git a/riru-core/jni/external/xhook/xh_jni.c b/riru-core/jni/external/xhook/xh_jni.c
deleted file mode 100644
index f8ae223..0000000
--- a/riru-core/jni/external/xhook/xh_jni.c
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright (c) 2018-present, iQIYI, Inc. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
-
-// Created by caikelun on 2018-04-11.
-
-#include
-#include "xhook.h"
-
-#define JNI_API_DEF(f) Java_com_qiyi_xhook_NativeHandler_##f
-
-JNIEXPORT jint JNI_API_DEF(refresh)(JNIEnv *env, jobject obj, jboolean async)
-{
- (void)env;
- (void)obj;
-
- return xhook_refresh(async ? 1 : 0);
-}
-
-JNIEXPORT void JNI_API_DEF(clear)(JNIEnv *env, jobject obj)
-{
- (void)env;
- (void)obj;
-
- xhook_clear();
-}
-
-JNIEXPORT void JNI_API_DEF(enableDebug)(JNIEnv *env, jobject obj, jboolean flag)
-{
- (void)env;
- (void)obj;
-
- xhook_enable_debug(flag ? 1 : 0);
-}
-
-JNIEXPORT void JNI_API_DEF(enableSigSegvProtection)(JNIEnv *env, jobject obj, jboolean flag)
-{
- (void)env;
- (void)obj;
-
- xhook_enable_sigsegv_protection(flag ? 1 : 0);
-}
diff --git a/riru-core/jni/external/xhook/xh_log.c b/riru-core/jni/external/xhook/xh_log.c
deleted file mode 100644
index 6cba947..0000000
--- a/riru-core/jni/external/xhook/xh_log.c
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (c) 2018-present, iQIYI, Inc. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
-
-// Created by caikelun on 2018-04-11.
-
-#include
-#include "xh_log.h"
-
-android_LogPriority xh_log_priority = ANDROID_LOG_WARN;
diff --git a/riru-core/jni/external/xhook/xh_log.h b/riru-core/jni/external/xhook/xh_log.h
deleted file mode 100644
index e108c4b..0000000
--- a/riru-core/jni/external/xhook/xh_log.h
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright (c) 2018-present, iQIYI, Inc. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
-
-// Created by caikelun on 2018-04-11.
-
-#ifndef XH_LOG_H
-#define XH_LOG_H 1
-
-#include
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-extern android_LogPriority xh_log_priority;
-
-#define XH_LOG_TAG "xhook"
-#define XH_LOG_DEBUG(fmt, ...) do{if(xh_log_priority <= ANDROID_LOG_DEBUG) __android_log_print(ANDROID_LOG_DEBUG, XH_LOG_TAG, fmt, ##__VA_ARGS__);}while(0)
-#define XH_LOG_INFO(fmt, ...) do{if(xh_log_priority <= ANDROID_LOG_INFO) __android_log_print(ANDROID_LOG_INFO, XH_LOG_TAG, fmt, ##__VA_ARGS__);}while(0)
-#define XH_LOG_WARN(fmt, ...) do{if(xh_log_priority <= ANDROID_LOG_WARN) __android_log_print(ANDROID_LOG_WARN, XH_LOG_TAG, fmt, ##__VA_ARGS__);}while(0)
-#define XH_LOG_ERROR(fmt, ...) do{if(xh_log_priority <= ANDROID_LOG_ERROR) __android_log_print(ANDROID_LOG_ERROR, XH_LOG_TAG, fmt, ##__VA_ARGS__);}while(0)
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/riru-core/jni/external/xhook/xh_util.c b/riru-core/jni/external/xhook/xh_util.c
deleted file mode 100644
index 0e2dca2..0000000
--- a/riru-core/jni/external/xhook/xh_util.c
+++ /dev/null
@@ -1,121 +0,0 @@
-// Copyright (c) 2018-present, iQIYI, Inc. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
-
-// Created by caikelun on 2018-04-11.
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include "xh_util.h"
-#include "xh_errno.h"
-#include "xh_log.h"
-
-#define PAGE_START(addr) ((addr) & PAGE_MASK)
-#define PAGE_END(addr) (PAGE_START(addr + sizeof(uintptr_t) - 1) + PAGE_SIZE)
-#define PAGE_COVER(addr) (PAGE_END(addr) - PAGE_START(addr))
-
-int xh_util_get_mem_protect(uintptr_t addr, size_t len, const char *pathname, unsigned int *prot)
-{
- uintptr_t start_addr = addr;
- uintptr_t end_addr = addr + len;
- FILE *fp;
- char line[512];
- uintptr_t start, end;
- char perm[5];
- int load0 = 1;
- int found_all = 0;
-
- *prot = 0;
-
- if(NULL == (fp = fopen("/proc/self/maps", "r"))) return XH_ERRNO_BADMAPS;
-
- while(fgets(line, sizeof(line), fp))
- {
- if(NULL != pathname)
- if(NULL == strstr(line, pathname)) continue;
-
- if(sscanf(line, "%"PRIxPTR"-%"PRIxPTR" %4s ", &start, &end, perm) != 3) continue;
-
- if(perm[3] != 'p') continue;
-
- if(start_addr >= start && start_addr < end)
- {
- if(load0)
- {
- //first load segment
- if(perm[0] == 'r') *prot |= PROT_READ;
- if(perm[1] == 'w') *prot |= PROT_WRITE;
- if(perm[2] == 'x') *prot |= PROT_EXEC;
- load0 = 0;
- }
- else
- {
- //others
- if(perm[0] != 'r') *prot &= ~PROT_READ;
- if(perm[1] != 'w') *prot &= ~PROT_WRITE;
- if(perm[2] != 'x') *prot &= ~PROT_EXEC;
- }
-
- if(end_addr <= end)
- {
- found_all = 1;
- break; //finished
- }
- else
- {
- start_addr = end; //try to find the next load segment
- }
- }
- }
-
- fclose(fp);
-
- if(!found_all) return XH_ERRNO_SEGVERR;
-
- return 0;
-}
-
-int xh_util_get_addr_protect(uintptr_t addr, const char *pathname, unsigned int *prot)
-{
- return xh_util_get_mem_protect(addr, sizeof(addr), pathname, prot);
-}
-
-int xh_util_set_addr_protect(uintptr_t addr, unsigned int prot)
-{
- if(0 != mprotect((void *)PAGE_START(addr), PAGE_COVER(addr), (int)prot))
- return 0 == errno ? XH_ERRNO_UNKNOWN : errno;
-
- return 0;
-}
-
-void xh_util_flush_instruction_cache(uintptr_t addr)
-{
- __builtin___clear_cache((void *)PAGE_START(addr), (void *)PAGE_END(addr));
-}
diff --git a/riru-core/jni/external/xhook/xh_util.h b/riru-core/jni/external/xhook/xh_util.h
deleted file mode 100644
index b57f8dc..0000000
--- a/riru-core/jni/external/xhook/xh_util.h
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright (c) 2018-present, iQIYI, Inc. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
-
-// Created by caikelun on 2018-04-11.
-
-#ifndef XH_UTILS_H
-#define XH_UTILS_H 1
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#if defined(__LP64__)
-#define XH_UTIL_FMT_LEN "16"
-#define XH_UTIL_FMT_X "llx"
-#else
-#define XH_UTIL_FMT_LEN "8"
-#define XH_UTIL_FMT_X "x"
-#endif
-
-#define XH_UTIL_FMT_FIXED_X XH_UTIL_FMT_LEN XH_UTIL_FMT_X
-#define XH_UTIL_FMT_FIXED_S XH_UTIL_FMT_LEN "s"
-
-int xh_util_get_mem_protect(uintptr_t addr, size_t len, const char *pathname, unsigned int *prot);
-int xh_util_get_addr_protect(uintptr_t addr, const char *pathname, unsigned int *prot);
-int xh_util_set_addr_protect(uintptr_t addr, unsigned int prot);
-void xh_util_flush_instruction_cache(uintptr_t addr);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/riru-core/jni/external/xhook/xh_version.c b/riru-core/jni/external/xhook/xh_version.c
deleted file mode 100644
index b237f16..0000000
--- a/riru-core/jni/external/xhook/xh_version.c
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright (c) 2018-present, iQIYI, Inc. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
-
-// Created by caikelun on 2018-04-11.
-
-#include "xh_version.h"
-
-#define XH_VERSION_MAJOR 1
-#define XH_VERSION_MINOR 1
-#define XH_VERSION_EXTRA 9
-
-#define XH_VERSION ((XH_VERSION_MAJOR << 16) | (XH_VERSION_MINOR << 8) | (XH_VERSION_EXTRA))
-
-#define XH_VERSION_TO_STR_HELPER(x) #x
-#define XH_VERSION_TO_STR(x) XH_VERSION_TO_STR_HELPER(x)
-
-#define XH_VERSION_STR XH_VERSION_TO_STR(XH_VERSION_MAJOR) "." \
- XH_VERSION_TO_STR(XH_VERSION_MINOR) "." \
- XH_VERSION_TO_STR(XH_VERSION_EXTRA)
-
-#if defined(__arm__)
-#define XH_VERSION_ARCH "arm"
-#elif defined(__aarch64__)
-#define XH_VERSION_ARCH "aarch64"
-#elif defined(__i386__)
-#define XH_VERSION_ARCH "x86"
-#elif defined(__x86_64__)
-#define XH_VERSION_ARCH "x86_64"
-#else
-#define XH_VERSION_ARCH "unknown"
-#endif
-
-#define XH_VERSION_STR_FULL "libxhook "XH_VERSION_STR" ("XH_VERSION_ARCH")"
-
-unsigned int xh_version()
-{
- return XH_VERSION;
-}
-
-const char *xh_version_str()
-{
- return XH_VERSION_STR;
-}
-
-const char *xh_version_str_full()
-{
- return XH_VERSION_STR_FULL;
-}
diff --git a/riru-core/jni/external/xhook/xh_version.h b/riru-core/jni/external/xhook/xh_version.h
deleted file mode 100644
index b70b4f2..0000000
--- a/riru-core/jni/external/xhook/xh_version.h
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright (c) 2018-present, iQIYI, Inc. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
-
-// Created by caikelun on 2018-04-11.
-
-#ifndef XH_VERSION_H
-#define XH_VERSION_H 1
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-unsigned int xh_version();
-
-const char *xh_version_str();
-
-const char *xh_version_str_full();
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/riru-core/jni/external/xhook/xhook.c b/riru-core/jni/external/xhook/xhook.c
deleted file mode 100644
index 49dfc59..0000000
--- a/riru-core/jni/external/xhook/xhook.c
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright (c) 2018-present, iQIYI, Inc. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
-
-// Created by caikelun on 2018-04-11.
-
-#include "xh_core.h"
-#include "xhook.h"
-
-int xhook_register(const char *pathname_regex_str, const char *symbol,
- void *new_func, void **old_func)
-{
- return xh_core_register(pathname_regex_str, symbol, new_func, old_func);
-}
-
-int xhook_ignore(const char *pathname_regex_str, const char *symbol)
-{
- return xh_core_ignore(pathname_regex_str, symbol);
-}
-
-int xhook_refresh(int async)
-{
- return xh_core_refresh(async);
-}
-
-void xhook_clear()
-{
- return xh_core_clear();
-}
-
-void xhook_enable_debug(int flag)
-{
- return xh_core_enable_debug(flag);
-}
-
-void xhook_enable_sigsegv_protection(int flag)
-{
- return xh_core_enable_sigsegv_protection(flag);
-}
diff --git a/riru-core/jni/external/xhook/xhook.h b/riru-core/jni/external/xhook/xhook.h
deleted file mode 100644
index b14b8de..0000000
--- a/riru-core/jni/external/xhook/xhook.h
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright (c) 2018-present, iQIYI, Inc. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
-
-// Created by caikelun on 2018-04-11.
-
-#ifndef XHOOK_H
-#define XHOOK_H 1
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define XHOOK_EXPORT
-
-int xhook_register(const char *pathname_regex_str, const char *symbol,
- void *new_func, void **old_func) XHOOK_EXPORT;
-
-int xhook_ignore(const char *pathname_regex_str, const char *symbol) XHOOK_EXPORT;
-
-int xhook_refresh(int async) XHOOK_EXPORT;
-
-void xhook_clear() XHOOK_EXPORT;
-
-void xhook_enable_debug(int flag) XHOOK_EXPORT;
-
-void xhook_enable_sigsegv_protection(int flag) XHOOK_EXPORT;
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/riru-core/jni/main/Android.mk b/riru-core/jni/main/Android.mk
deleted file mode 100644
index 3673326..0000000
--- a/riru-core/jni/main/Android.mk
+++ /dev/null
@@ -1,14 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libmemtrack
-LOCAL_C_INCLUDES := \
- $(LOCAL_PATH) \
- jni/external/include
-LOCAL_STATIC_LIBRARIES := xhook
-LOCAL_LDLIBS += -ldl -llog
-LOCAL_LDFLAGS := -Wl,--hash-style=both
-
-LOCAL_SRC_FILES:= main.cpp jni_native_method.cpp misc.cpp wrap.cpp redirect_memtrack.cpp version.cpp api.cpp
-
-include $(BUILD_SHARED_LIBRARY)
\ No newline at end of file
diff --git a/riru-core/jni/main/JNIHelper.h b/riru-core/jni/main/JNIHelper.h
deleted file mode 100644
index 399ad86..0000000
--- a/riru-core/jni/main/JNIHelper.h
+++ /dev/null
@@ -1,73 +0,0 @@
-#ifndef JNIHELPER_H
-#define JNIHELPER_H
-
-#include
-#include "logging.h"
-
-static int ClearException(JNIEnv *env) {
- jthrowable exception = env->ExceptionOccurred();
- if (exception != nullptr) {
- env->ExceptionDescribe();
- env->ExceptionClear();
- return true;
- }
- return false;
-}
-
-#define JNI_FindClass(env, name) \
- env->FindClass(name); \
- if (ClearException(env)) LOGE("FindClass " #name);
-
-#define JNI_GetObjectClass(env, obj) \
- env->GetObjectClass(obj); \
- if (ClearException(env)) LOGE("GetObjectClass " #obj);
-
-#define JNI_GetFieldID(env, class, name, sig) \
- env->GetFieldID(class, name, sig); \
- if (ClearException(env)) LOGE("GetFieldID " #name);
-
-#define JNI_GetObjectField(env, class, fieldId) \
- env->GetObjectField(class, fieldId); \
- if (ClearException(env)) LOGE("GetObjectField " #fieldId);
-
-#define JNI_GetMethodID(env, class, name, sig) \
- env->GetMethodID(class, name, sig); \
- if (ClearException(env)) LOGE("GetMethodID " #name);
-
-#define JNI_CallObjectMethod(env, obj, ...) \
- env->CallObjectMethod(obj, __VA_ARGS__); \
- if (ClearException(env)) LOGE("CallObjectMethod " #obj " " #__VA_ARGS__);
-
-#define JNI_CallVoidMethod(env, obj, ...) \
- env->CallVoidMethod(obj, __VA_ARGS__); \
- if (ClearException(env)) LOGE("CallVoidMethod " #obj " " #__VA_ARGS__);
-
-#define JNI_GetStaticFieldID(env, class, name, sig) \
- env->GetStaticFieldID(class, name, sig); \
- if (ClearException(env)) LOGE("GetStaticFieldID " #name " " #sig);
-
-#define JNI_GetStaticObjectField(env, class, fieldId) \
- env->GetStaticObjectField(class, fieldId); \
- if (ClearException(env)) LOGE("GetStaticObjectField " #fieldId);
-
-#define JNI_GetStaticMethodID(env, class, name, sig) \
- env->GetStaticMethodID(class, name, sig); \
- if (ClearException(env)) LOGE("GetStaticMethodID " #name);
-
-#define JNI_CallStaticVoidMethod(env, obj, ...) \
- env->CallStaticVoidMethod(obj, __VA_ARGS__); \
- if (ClearException(env)) LOGE("CallStaticVoidMethod " #obj " " #__VA_ARGS__);
-
-#define JNI_GetArrayLength(env, array) \
- env->GetArrayLength(array); \
- if (ClearException(env)) LOGE("GetArrayLength " #array);
-
-#define JNI_NewObject(env, class, ...) \
- env->NewObject(class, __VA_ARGS__); \
- if (ClearException(env)) LOGE("NewObject " #class " " #__VA_ARGS__);
-
-#define JNI_RegisterNatives(env, class, methods, size) \
- env->RegisterNatives(class, methods, size); \
- if (ClearException(env)) LOGE("RegisterNatives " #class);
-
-#endif // JNIHELPER_H
diff --git a/riru-core/jni/main/api.cpp b/riru-core/jni/main/api.cpp
deleted file mode 100644
index 11cdc13..0000000
--- a/riru-core/jni/main/api.cpp
+++ /dev/null
@@ -1,126 +0,0 @@
-#include
-#include
-#include