diff --git a/.github/workflows/core.yml b/.github/workflows/core.yml index 9b57b5625..1ea2d5e3f 100644 --- a/.github/workflows/core.yml +++ b/.github/workflows/core.yml @@ -63,7 +63,7 @@ jobs: uses: gradle/actions/setup-gradle@v4 - name: Setup ninja - uses: seanmiddleditch/gha-setup-ninja@v5 + uses: seanmiddleditch/gha-setup-ninja@v6 with: version: 1.12.1 diff --git a/.gitignore b/.gitignore index 9be6d25cf..658d21d74 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,4 @@ apache/local/generated .DS_Store /build /captures +/apache/build diff --git a/.gitmodules b/.gitmodules index 0ef33e53d..d3342e406 100644 --- a/.gitmodules +++ b/.gitmodules @@ -19,3 +19,6 @@ [submodule "external/lsplt"] path = external/lsplt url = https://github.com/JingMatrix/LSPlt +[submodule "external/riscv64-inline-hook"] + path = external/riscv64-inline-hook + url = https://github.com/eirv/riscv64-inline-hook diff --git a/README.md b/README.md index 1127bf994..af24205b4 100644 --- a/README.md +++ b/README.md @@ -58,6 +58,7 @@ You can contribute translation [here](https://crowdin.com/project/lsposed_jingma - [XposedBridge](https://github.com/rovo89/XposedBridge): the OG Xposed framework APIs - [LSPlant](https://github.com/JingMatrix/LSPlant): the core ART hooking framework - [Dobby](https://github.com/JingMatrix/Dobby): inline hooker for `LSPlant` and `native_api` implement +- [riscv64-inline-hook](https://github.com/eirv/riscv64-inline-hook): inline hooker for `RISC-V 64` - [EdXposed](https://github.com/ElderDrivers/EdXposed): fork source - [xz-embedded](https://github.com/tukaani-project/xz-embedded): decompress `.gnu_debugdata` header section of stripped `libart.so` - ~~[Riru](https://github.com/RikkaApps/Riru): provides a way to inject code into zygote process~~ diff --git a/build.gradle.kts b/build.gradle.kts index 03aaec248..2af8024fa 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -45,7 +45,7 @@ cmaker { ) cFlags.addAll(flags) cppFlags.addAll(flags) - abiFilters("arm64-v8a", "armeabi-v7a", "x86", "x86_64") + abiFilters("arm64-v8a", "armeabi-v7a", "x86", "x86_64", "riscv64") } buildTypes { if (it.name == "release") { diff --git a/core/src/main/jni/CMakeLists.txt b/core/src/main/jni/CMakeLists.txt index dce214922..f9e9ec3b2 100644 --- a/core/src/main/jni/CMakeLists.txt +++ b/core/src/main/jni/CMakeLists.txt @@ -17,10 +17,17 @@ set(IGNORED_WARNINGS -Wno-gnu-flexible-array-initializer -Wno-variadic-macros -Wno-zero-length-array) +set(${PROJECT_NAME}_LINK_LIBS lsplant_static xz_static log fmt-header-only) + +if (ANDROID_ABI STREQUAL "riscv64") + set(${PROJECT_NAME}_LINK_LIBS ${${PROJECT_NAME}_LINK_LIBS} rv64hook-static) +else () + set(${PROJECT_NAME}_LINK_LIBS ${${PROJECT_NAME}_LINK_LIBS} dobby_static) +endif () target_include_directories(${PROJECT_NAME} PUBLIC include) target_include_directories(${PROJECT_NAME} PRIVATE src ${EXTERNAL_ROOT}/xz-embedded/linux/include) target_compile_options(${PROJECT_NAME} PRIVATE -Wpedantic ${IGNORED_WARNINGS}) -target_link_libraries(${PROJECT_NAME} PUBLIC dobby_static lsplant_static xz_static log fmt-header-only) +target_link_libraries(${PROJECT_NAME} PUBLIC ${${PROJECT_NAME}_LINK_LIBS}) target_link_libraries(${PROJECT_NAME} PRIVATE dex_builder_static) diff --git a/core/src/main/jni/src/native_api.h b/core/src/main/jni/src/native_api.h index 4c6c4388e..18c3caea0 100644 --- a/core/src/main/jni/src/native_api.h +++ b/core/src/main/jni/src/native_api.h @@ -28,7 +28,11 @@ #include #include #include +#ifdef __riscv +#include +#else #include +#endif #include "config.h" #include "utils/hook_helper.hpp" @@ -56,24 +60,35 @@ namespace lspd { if constexpr (isDebug) { Dl_info info; if (dladdr(original, &info)) - LOGD("Dobby hooking {} ({}) from {} ({})", + LOGD("Inline hooking {} ({}) from {} ({})", info.dli_sname ? info.dli_sname : "(unknown symbol)", info.dli_saddr ? info.dli_saddr : original, info.dli_fname ? info.dli_fname : "(unknown file)", info.dli_fbase); } +#ifdef __riscv + rv64hook::ScopedRWXMemory rwx(original); + return rv64hook::InlineHook(original, replace, backup) != nullptr ? 0 : -1; +#else return DobbyHook(original, reinterpret_cast(replace), reinterpret_cast(backup)); +#endif } inline int UnhookInline(void *original) { if constexpr (isDebug) { Dl_info info; if (dladdr(original, &info)) - LOGD("Dobby unhooking {} ({}) from {} ({})", + LOGD("Inline unhooking {} ({}) from {} ({})", info.dli_sname ? info.dli_sname : "(unknown symbol)", info.dli_saddr ? info.dli_saddr : original, info.dli_fname ? info.dli_fname : "(unknown file)", info.dli_fbase); } +#ifdef __riscv + rv64hook::ScopedRWXMemory rwx(original); + rv64hook::UnhookFunction(original); + return 0; +#else return DobbyDestroy(original); +#endif } } diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt index 434f9b811..5a0491c5d 100644 --- a/external/CMakeLists.txt +++ b/external/CMakeLists.txt @@ -1,5 +1,9 @@ project(external) +if (ANDROID_ABI STREQUAL "riscv64") + set(ANDROID_PLATFORM "android-35") +endif () + macro(SET_OPTION option value) set(${option} ${value} CACHE INTERNAL "" FORCE) endmacro() @@ -20,7 +24,11 @@ target_compile_options(xz_static PRIVATE -DXZ_USE_CRC64) target_include_directories(xz_static PRIVATE ${XZ_INCLUDES}) OPTION(LSPLANT_BUILD_SHARED OFF) -add_subdirectory(dobby) +if (ANDROID_ABI STREQUAL "riscv64") + add_subdirectory(riscv64-inline-hook) +else () + add_subdirectory(dobby) +endif () add_subdirectory(fmt) add_subdirectory(lsplant/lsplant/src/main/jni) target_compile_definitions(fmt-header-only INTERFACE FMT_USE_LOCALE=0 FMT_USE_FLOAT=0 FMT_USE_DOUBLE=0 FMT_USE_LONG_DOUBLE=0 FMT_USE_BITINT=0) diff --git a/external/lsplant b/external/lsplant index 3f08bb72d..957cb7cdd 160000 --- a/external/lsplant +++ b/external/lsplant @@ -1 +1 @@ -Subproject commit 3f08bb72d87ad29501052217fcb78d7330c07ac5 +Subproject commit 957cb7cddd1b2b79e333efd379ac3b5162026e71 diff --git a/external/riscv64-inline-hook b/external/riscv64-inline-hook new file mode 160000 index 000000000..988717892 --- /dev/null +++ b/external/riscv64-inline-hook @@ -0,0 +1 @@ +Subproject commit 9887178920b664575594be24bd93f532ec24f8e3 diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index f4f4301ca..b1604edb8 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,7 +1,7 @@ [versions] -agp = "8.8.1" +agp = "8.8.2" kotlin = "2.1.10" -nav = "2.8.7" +nav = "2.8.8" appcenter = "5.0.5" libxposed = "100" glide = "4.16.0" @@ -31,10 +31,10 @@ rikkax-recyclerview = { module = "dev.rikka.rikkax.recyclerview:recyclerview-ktx rikkax-widget-borderview = { module = "dev.rikka.rikkax.widget:borderview", version = "1.1.0" } rikkax-widget-mainswitchbar = { module = "dev.rikka.rikkax.widget:mainswitchbar", version = "1.0.2" } -androidx-activity = { module = "androidx.activity:activity", version = "1.10.0" } +androidx-activity = { module = "androidx.activity:activity", version = "1.10.1" } androidx-annotation = { module = "androidx.annotation:annotation", version = "1.9.1" } androidx-browser = { module = "androidx.browser:browser", version = "1.8.0" } -androidx-constraintlayout = { module = "androidx.constraintlayout:constraintlayout", version = "2.2.0" } +androidx-constraintlayout = { module = "androidx.constraintlayout:constraintlayout", version = "2.2.1" } androidx-core = { module = "androidx.core:core", version = "1.15.0" } androidx-fragment = { module = "androidx.fragment:fragment", version = "1.8.6" } androidx-navigation-fragment = { group = "androidx.navigation", name = "navigation-fragment", version.ref = "nav" } diff --git a/magisk-loader/magisk_module/customize.sh b/magisk-loader/magisk_module/customize.sh index f1a12db22..0a506457d 100644 --- a/magisk-loader/magisk_module/customize.sh +++ b/magisk-loader/magisk_module/customize.sh @@ -62,7 +62,7 @@ check_incompatible_module enforce_install_from_magisk_app # Check architecture -if [ "$ARCH" != "arm" ] && [ "$ARCH" != "arm64" ] && [ "$ARCH" != "x86" ] && [ "$ARCH" != "x64" ]; then +if [ "$ARCH" != "arm" ] && [ "$ARCH" != "arm64" ] && [ "$ARCH" != "x86" ] && [ "$ARCH" != "x64" ] && [ "$ARCH" != "riscv64" ]; then abort "! Unsupported platform: $ARCH" else ui_print "- Device platform: $ARCH" @@ -115,6 +115,11 @@ if [ "$FLAVOR" == "zygisk" ]; then mv "$MODPATH/zygisk/liblspd.so" "$MODPATH/zygisk/x86_64.so" fi fi + + if [ "$ARCH" = "riscv64" ]; then + extract "$ZIPFILE" "lib/riscv64/liblspd.so" "$MODPATH/zygisk" true + mv "$MODPATH/zygisk/liblspd.so" "$MODPATH/zygisk/riscv64.so" + fi fi if [ "$API" -ge 29 ]; then @@ -145,12 +150,19 @@ if [ "$API" -ge 29 ]; then mv "$MODPATH/bin/dex2oat" "$MODPATH/bin/dex2oat64" mv "$MODPATH/bin/liboat_hook.so" "$MODPATH/bin/liboat_hook64.so" fi + elif [ "$ARCH" == "riscv64" ]; then + extract "$ZIPFILE" "bin/riscv64/dex2oat" "$MODPATH/bin" true + extract "$ZIPFILE" "bin/riscv64/liboat_hook.so" "$MODPATH/bin" true + mv "$MODPATH/bin/dex2oat" "$MODPATH/bin/dex2oat64" + mv "$MODPATH/bin/liboat_hook.so" "$MODPATH/bin/liboat_hook64.so" fi ui_print "- Patching binaries" DEV_PATH=$(tr -dc 'a-z0-9' < /dev/urandom | head -c 32) sed -i "s/5291374ceda0aef7c5d86cd2a4f6a3ac/$DEV_PATH/g" "$MODPATH/daemon.apk" - sed -i "s/5291374ceda0aef7c5d86cd2a4f6a3ac/$DEV_PATH/" "$MODPATH/bin/dex2oat32" + if [ "$ARCH" != "riscv64" ]; then + sed -i "s/5291374ceda0aef7c5d86cd2a4f6a3ac/$DEV_PATH/" "$MODPATH/bin/dex2oat32" + fi sed -i "s/5291374ceda0aef7c5d86cd2a4f6a3ac/$DEV_PATH/" "$MODPATH/bin/dex2oat64" else extract "$ZIPFILE" 'system.prop' "$MODPATH" diff --git a/magisk-loader/magisk_module/util_functions.sh b/magisk-loader/magisk_module/util_functions.sh index 4bb9ea87f..04e927125 100644 --- a/magisk-loader/magisk_module/util_functions.sh +++ b/magisk-loader/magisk_module/util_functions.sh @@ -35,17 +35,28 @@ check_magisk_version() { require_new_android() { ui_print "*********************************************************" - ui_print "! Unsupported Android version ${1} (below Oreo MR1)" + ui_print "! Unsupported Android version ${1} (below ${2})" ui_print "! Learn more from our GitHub" [ "$BOOTMODE" == "true" ] && am start -a android.intent.action.VIEW -d https://github.com/JingMatrix/LSPosed/#supported-versions abort "*********************************************************" } check_android_version() { - if [ "$API" -ge 27 ]; then + local required_version + local min_api + + if [ "$ARCH" == "riscv64" ]; then + required_version="Vanilla Ice Cream" + min_api=35 + else + required_version="Oreo MR1" + min_api=27 + fi + + if [ "$API" -ge "$min_api" ]; then ui_print "- Android SDK version: $API" else - require_new_android "$API" + require_new_android "$API" "$required_version" fi }