Add support for Android 11 RefBase ABI (#29)
Implements a compatibility layer to allow the binary to run on Android 11 (API 30) and older, which lack the `incStrongRequireStrong` symbol in their `libutils.so`. This is achieved by creating a runtime wrapper that checks the device's SDK version. - On Android 12 (API 31) and newer, it dynamically loads and calls the `incStrongRequireStrong` function using `dlsym`. - On older versions, it safely falls back to the universally available `incStrong` method. This resolves the fatal `dlopen` error "cannot locate symbol" when injecting the library into processes on older Android versions. See AOSP change https://android-review.googlesource.com/c/platform/system/core/+/1660499
This commit is contained in:
@@ -12,7 +12,7 @@ add_subdirectory(external/LSPlt/lsplt/src/main/jni)
|
|||||||
|
|
||||||
add_compile_definitions(BINDER_DISABLE_NATIVE_HANDLE)
|
add_compile_definitions(BINDER_DISABLE_NATIVE_HANDLE)
|
||||||
add_library(utils SHARED stub/stub_utils.cpp)
|
add_library(utils SHARED stub/stub_utils.cpp)
|
||||||
target_include_directories(utils PUBLIC external/AOSP/include)
|
target_include_directories(utils PUBLIC external/AOSP/include compat)
|
||||||
|
|
||||||
add_library(binder SHARED stub/stub_binder.cpp)
|
add_library(binder SHARED stub/stub_binder.cpp)
|
||||||
target_include_directories(binder PUBLIC external/AOSP/include)
|
target_include_directories(binder PUBLIC external/AOSP/include)
|
||||||
@@ -22,7 +22,7 @@ add_executable(libinject.so inject/main.cpp inject/utils.cpp)
|
|||||||
target_include_directories(libinject.so PUBLIC include)
|
target_include_directories(libinject.so PUBLIC include)
|
||||||
target_link_libraries(libinject.so PRIVATE lsplt_static)
|
target_link_libraries(libinject.so PRIVATE lsplt_static)
|
||||||
|
|
||||||
add_library(${CMAKE_PROJECT_NAME} SHARED binder_interceptor.cpp)
|
add_library(${CMAKE_PROJECT_NAME} SHARED binder_interceptor.cpp compat/refbase_compat.cpp)
|
||||||
target_include_directories(${CMAKE_PROJECT_NAME} PUBLIC external/linux-kernel/include include)
|
target_include_directories(${CMAKE_PROJECT_NAME} PUBLIC external/linux-kernel/include include)
|
||||||
target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE binder lsplt_static utils)
|
target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE binder lsplt_static utils)
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,61 @@
|
|||||||
|
#include "refbase_compat.h"
|
||||||
|
#include "utils/RefBase.h"
|
||||||
|
#include <atomic>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cstring> // For memcpy
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#include <mutex>
|
||||||
|
#include <sys/system_properties.h>
|
||||||
|
|
||||||
|
namespace android {
|
||||||
|
|
||||||
|
// Helper function to get the Android API level at runtime.
|
||||||
|
// It caches the result for performance.
|
||||||
|
int32_t get_android_api_level() {
|
||||||
|
static std::atomic<int32_t> api_level = -1;
|
||||||
|
if (api_level.load(std::memory_order_relaxed) == -1) {
|
||||||
|
char sdk_version_str[PROP_VALUE_MAX];
|
||||||
|
if (__system_property_get("ro.build.version.sdk", sdk_version_str) > 0) {
|
||||||
|
api_level.store(atoi(sdk_version_str), std::memory_order_relaxed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return api_level.load(std::memory_order_relaxed);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Define the function pointer type for the const member function
|
||||||
|
// RefBase::incStrongRequireStrong.
|
||||||
|
using incStrongRequireStrong_t = void (RefBase::*)(const void *) const;
|
||||||
|
|
||||||
|
// This is the implementation of our compatibility wrapper.
|
||||||
|
void incStrongFromExisting(const RefBase *ref, const void *id) {
|
||||||
|
// Only attempt to use the new function on Android 12 (API 31) or higher.
|
||||||
|
if (get_android_api_level() >= 31) {
|
||||||
|
static incStrongRequireStrong_t sIncStrongRequireStrong = nullptr;
|
||||||
|
static std::once_flag sFlag;
|
||||||
|
|
||||||
|
// Thread-safe, one-time initialization.
|
||||||
|
std::call_once(sFlag, []() {
|
||||||
|
// Find the symbol in the already loaded libraries.
|
||||||
|
// The mangled symbol is _ZNK7android7RefBase22incStrongRequireStrongEPKv
|
||||||
|
void *sym = dlsym(RTLD_DEFAULT,
|
||||||
|
"_ZNK7android7RefBase22incStrongRequireStrongEPKv");
|
||||||
|
if (sym) {
|
||||||
|
// Safely cast the void* symbol to our member function pointer.
|
||||||
|
memcpy(&sIncStrongRequireStrong, &sym, sizeof(void *));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (sIncStrongRequireStrong) {
|
||||||
|
// If the symbol was found, call it as member function.
|
||||||
|
(ref->*sIncStrongRequireStrong)(id);
|
||||||
|
return; // Success, we are done.
|
||||||
|
}
|
||||||
|
// If dlsym failed for any reason, we fall through to the old method.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback for older Android versions or if dlsym failed.
|
||||||
|
// This calls the universally available incStrong method.
|
||||||
|
ref->incStrong(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace android
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace android {
|
||||||
|
|
||||||
|
// Forward-declare the RefBase class.
|
||||||
|
class RefBase;
|
||||||
|
|
||||||
|
// Declares our compatibility function.
|
||||||
|
void incStrongFromExisting(const RefBase *ref, const void *id);
|
||||||
|
|
||||||
|
} // namespace android
|
||||||
@@ -17,6 +17,7 @@
|
|||||||
#ifndef ANDROID_STRONG_POINTER_H
|
#ifndef ANDROID_STRONG_POINTER_H
|
||||||
#define ANDROID_STRONG_POINTER_H
|
#define ANDROID_STRONG_POINTER_H
|
||||||
|
|
||||||
|
#include "refbase_compat.h"
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <type_traits> // for common_type.
|
#include <type_traits> // for common_type.
|
||||||
|
|
||||||
@@ -212,7 +213,7 @@ sp<T> sp<T>::make(Args&&... args) {
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
sp<T> sp<T>::fromExisting(T* other) {
|
sp<T> sp<T>::fromExisting(T* other) {
|
||||||
if (other) {
|
if (other) {
|
||||||
other->incStrongRequireStrong(other);
|
incStrongFromExisting(other, other);
|
||||||
sp<T> result;
|
sp<T> result;
|
||||||
result.m_ptr = other;
|
result.m_ptr = other;
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
Reference in New Issue
Block a user