Support SetRuntimeDebugState (#24)

This commit is contained in:
LoveSy 2022-09-14 00:42:07 +08:00 committed by GitHub
parent 2bd37aaba9
commit 7c5457a699
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 70 additions and 13 deletions

View File

@ -2,5 +2,5 @@ val androidTargetSdkVersion by extra(33)
val androidMinSdkVersion by extra(21) val androidMinSdkVersion by extra(21)
val androidBuildToolsVersion by extra("33.0.0") val androidBuildToolsVersion by extra("33.0.0")
val androidCompileSdkVersion by extra(33) val androidCompileSdkVersion by extra(33)
val androidNdkVersion by extra("24.0.8215888") val androidNdkVersion by extra("25.1.8937393")
val androidCmakeVersion by extra("3.22.1+") val androidCmakeVersion by extra("3.22.1+")

View File

@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists

View File

@ -114,7 +114,7 @@ publishing {
register<MavenPublication>("lsplant") { register<MavenPublication>("lsplant") {
group = "org.lsposed.lsplant" group = "org.lsposed.lsplant"
artifactId = "lsplant" artifactId = "lsplant"
version = "4.1" version = "4.2"
afterEvaluate { afterEvaluate {
from(components.getByName("release")) from(components.getByName("release"))
artifact(symbolsTask) artifact(symbolsTask)

View File

@ -24,19 +24,46 @@
namespace lsplant::art { namespace lsplant::art {
class Runtime { class Runtime {
public:
enum class RuntimeDebugState {
// This doesn't support any debug features / method tracing. This is the expected state
// usually.
kNonJavaDebuggable,
// This supports method tracing and a restricted set of debug features (for ex: redefinition
// isn't supported). We transition to this state when method tracing has started or when the
// debugger was attached and transition back to NonDebuggable once the tracing has stopped /
// the debugger agent has detached..
kJavaDebuggable,
// The runtime was started as a debuggable runtime. This allows us to support the extended
// set
// of debug features (for ex: redefinition). We never transition out of this state.
kJavaDebuggableAtInit
};
private: private:
inline static Runtime *instance_; inline static Runtime *instance_;
CREATE_MEM_FUNC_SYMBOL_ENTRY(void, SetJavaDebuggable, void *thiz, bool value) { CREATE_MEM_FUNC_SYMBOL_ENTRY(void, SetJavaDebuggable, void *thiz, bool value) {
if (SetJavaDebuggableSym) [[likely]] {
SetJavaDebuggableSym(thiz, value); SetJavaDebuggableSym(thiz, value);
} }
CREATE_MEM_FUNC_SYMBOL_ENTRY(void, SetRuntimeDebugState, void *thiz, RuntimeDebugState value) {
SetRuntimeDebugStateSym(thiz, value);
} }
inline static size_t debug_state_offset = 0U;
public: public:
inline static Runtime *Current() { return instance_; } inline static Runtime *Current() { return instance_; }
void SetJavaDebuggable(bool value) { SetJavaDebuggable(this, value); } void SetJavaDebuggable(RuntimeDebugState value) {
if (SetJavaDebuggableSym) {
SetJavaDebuggable(this, value != RuntimeDebugState::kNonJavaDebuggable);
} else if (debug_state_offset > 0) {
*reinterpret_cast<RuntimeDebugState *>(reinterpret_cast<uintptr_t>(instance_) +
debug_state_offset) = value;
}
}
static bool Init(const HookHandler &handler) { static bool Init(const HookHandler &handler) {
int sdk_int = GetAndroidApiLevel(); int sdk_int = GetAndroidApiLevel();
@ -48,7 +75,32 @@ public:
LOGD("runtime instance = %p", instance_); LOGD("runtime instance = %p", instance_);
if (sdk_int >= __ANDROID_API_O__) { if (sdk_int >= __ANDROID_API_O__) {
if (!RETRIEVE_MEM_FUNC_SYMBOL(SetJavaDebuggable, if (!RETRIEVE_MEM_FUNC_SYMBOL(SetJavaDebuggable,
"_ZN3art7Runtime17SetJavaDebuggableEb")) { "_ZN3art7Runtime17SetJavaDebuggableEb") &&
!RETRIEVE_MEM_FUNC_SYMBOL(
SetRuntimeDebugState,
"_ZN3art7Runtime20SetRuntimeDebugStateENS0_17RuntimeDebugStateE")) {
return false;
}
}
if (SetRuntimeDebugStateSym) {
static constexpr size_t kLargeEnoughSizeForRuntime = 4096;
std::array<uint8_t, kLargeEnoughSizeForRuntime> code;
static_assert(static_cast<int>(RuntimeDebugState::kJavaDebuggable) != 0);
static_assert(static_cast<int>(RuntimeDebugState::kJavaDebuggableAtInit) != 0);
code.fill(uint8_t{0});
auto *const fake_runtime = reinterpret_cast<Runtime *>(code.data());
SetRuntimeDebugState(fake_runtime, RuntimeDebugState::kJavaDebuggable);
for (size_t i = 0; i < kLargeEnoughSizeForRuntime; ++i) {
if (*reinterpret_cast<RuntimeDebugState *>(
reinterpret_cast<uintptr_t>(fake_runtime) + i) ==
RuntimeDebugState::kJavaDebuggable) {
LOGD("found debug_state at offset %zu", i);
debug_state_offset = i;
break;
}
}
if (debug_state_offset == 0) {
LOGE("failed to find debug_state");
return false; return false;
} }
} }

View File

@ -274,7 +274,7 @@ bool InitNative(JNIEnv *env, const HookHandler &handler) {
if (IsJavaDebuggable(env)) { if (IsJavaDebuggable(env)) {
// Make the runtime non-debuggable as a workaround // Make the runtime non-debuggable as a workaround
// when ShouldUseInterpreterEntrypoint inlined // when ShouldUseInterpreterEntrypoint inlined
Runtime::Current()->SetJavaDebuggable(false); Runtime::Current()->SetJavaDebuggable(Runtime::RuntimeDebugState::kNonJavaDebuggable);
} }
return true; return true;
} }
@ -735,8 +735,13 @@ using ::lsplant::IsHooked;
[[maybe_unused]] bool MakeDexFileTrusted(JNIEnv *env, jobject cookie) { [[maybe_unused]] bool MakeDexFileTrusted(JNIEnv *env, jobject cookie) {
struct Guard { struct Guard {
Guard() { Runtime::Current()->SetJavaDebuggable(true); } Guard() {
~Guard() { Runtime::Current()->SetJavaDebuggable(false); } Runtime::Current()->SetJavaDebuggable(
Runtime::RuntimeDebugState::kJavaDebuggableAtInit);
}
~Guard() {
Runtime::Current()->SetJavaDebuggable(Runtime::RuntimeDebugState::kNonJavaDebuggable);
}
} guard; } guard;
if (!cookie) return false; if (!cookie) return false;
return DexFile::SetTrusted(env, cookie); return DexFile::SetTrusted(env, cookie);

View File

@ -5,8 +5,8 @@ pluginManagement {
mavenCentral() mavenCentral()
} }
plugins { plugins {
id("com.android.application") version "7.2.1" id("com.android.application") version "7.2.2"
id("com.android.library") version "7.2.1" id("com.android.library") version "7.2.2"
} }
} }
dependencyResolutionManagement { dependencyResolutionManagement {