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 androidBuildToolsVersion by extra("33.0.0")
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+")

View File

@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
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
zipStorePath=wrapper/dists

View File

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

View File

@ -24,19 +24,46 @@
namespace lsplant::art {
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:
inline static Runtime *instance_;
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:
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) {
int sdk_int = GetAndroidApiLevel();
@ -48,7 +75,32 @@ public:
LOGD("runtime instance = %p", instance_);
if (sdk_int >= __ANDROID_API_O__) {
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;
}
}

View File

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

View File

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