Skip to content

Commit

Permalink
Improve the success rate of force dlopen.
Browse files Browse the repository at this point in the history
  • Loading branch information
caikelun committed Jan 9, 2024
1 parent e295323 commit 753d043
Show file tree
Hide file tree
Showing 6 changed files with 90 additions and 64 deletions.
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

![](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat)
![](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat)
![](https://img.shields.io/badge/release-2.0.0-red.svg?style=flat)
![](https://img.shields.io/badge/Android-4.1%20--%2013-blue.svg?style=flat)
![](https://img.shields.io/badge/release-2.1.0-red.svg?style=flat)
![](https://img.shields.io/badge/Android-4.1%20--%2014-blue.svg?style=flat)
![](https://img.shields.io/badge/arch-armeabi--v7a%20%7C%20arm64--v8a%20%7C%20x86%20%7C%20x86__64-blue.svg?style=flat)

xDL is an enhanced implementation of the Android DL series functions.
Expand All @@ -22,7 +22,7 @@ xDL is an enhanced implementation of the Android DL series functions.
* Including linker / linker64 (for Android <= 8.x).
* Return full pathname instead of basename (for Android 5.x).
* Return app\_process32 / app\_process64 instead of package name.
* Support Android 4.1 - 13 (API level 16 - 33).
* Support Android 4.1 - 14 (API level 16 - 34).
* Support armeabi-v7a, arm64-v8a, x86 and x86_64.
* MIT licensed.

Expand Down Expand Up @@ -53,7 +53,7 @@ android {
}
dependencies {
implementation 'io.github.hexhacking:xdl:2.0.0'
implementation 'io.github.hexhacking:xdl:2.1.0'
}
```

Expand Down
8 changes: 4 additions & 4 deletions README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

![](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat)
![](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat)
![](https://img.shields.io/badge/release-2.0.0-red.svg?style=flat)
![](https://img.shields.io/badge/Android-4.1%20--%2013-blue.svg?style=flat)
![](https://img.shields.io/badge/release-2.1.0-red.svg?style=flat)
![](https://img.shields.io/badge/Android-4.1%20--%2014-blue.svg?style=flat)
![](https://img.shields.io/badge/arch-armeabi--v7a%20%7C%20arm64--v8a%20%7C%20x86%20%7C%20x86__64-blue.svg?style=flat)

xDL 是 Android DL 系列函数的增强实现。
Expand All @@ -22,7 +22,7 @@ xDL 是 Android DL 系列函数的增强实现。
* 在 Android <= 8.x 时,包含 linker / linker64。
* 在 Android 5.x 中,返回完整的路径名(full pathname),而不是文件名(basename)。
* 返回 app\_process32 / app\_process64,而不是包名。
* 支持 Android 4.1 - 13 (API level 16 - 33)。
* 支持 Android 4.1 - 14 (API level 16 - 34)。
* 支持 armeabi-v7a, arm64-v8a, x86 和 x86_64。
* 使用 MIT 许可证授权。

Expand Down Expand Up @@ -53,7 +53,7 @@ android {
}
dependencies {
implementation 'io.github.hexhacking:xdl:2.0.0'
implementation 'io.github.hexhacking:xdl:2.1.0'
}
```

Expand Down
10 changes: 5 additions & 5 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,20 @@ task clean(type: Delete) {

ext {
minSdkVersion = 16
compileSdkVersion = 33
targetSdkVersion = 33
buildToolsVersion = "33.0.2"
compileSdkVersion = 34
targetSdkVersion = 34
buildToolsVersion = "34.0.0"
javaVersion = JavaVersion.VERSION_1_8
ndkVersion = "23.2.8568313"
cmakeVersion = "3.22.1"
abiFilters = "armeabi-v7a,arm64-v8a,x86,x86_64"
useASAN = false
dependencyOnLocalLibrary = true
xdlVersion = "2.0.0"
xdlVersion = "2.1.0"

POM_GROUP_ID = "io.github.hexhacking"
POM_ARTIFACT_ID = "xdl"
POM_VERSION_NAME = "2.0.0"
POM_VERSION_NAME = "2.1.0"

POM_NAME = "xDL Android Lib"
POM_DESCRIPTION = "xDL is an enhanced implementation of the Android DL series functions."
Expand Down
2 changes: 1 addition & 1 deletion xdl/src/main/cpp/include/xdl.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
// Created by caikelun on 2020-10-04.

//
// xDL version: 2.0.0
// xDL version: 2.1.0
//
// xDL is an enhanced implementation of the Android DL series functions.
// For more information, documentation, and the latest version please check:
Expand Down
124 changes: 75 additions & 49 deletions xdl/src/main/cpp/xdl_linker.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,28 +38,50 @@
#define XDL_LINKER_SYM_DLOPEN_O "__dl__Z8__dlopenPKciPKv"
#define XDL_LINKER_SYM_LOADER_DLOPEN_P "__loader_dlopen"

#ifndef __LP64__
#define LIB "lib"
#else
#define LIB "lib64"
#endif

typedef void *(*xdl_linker_dlopen_n_t)(const char *, int, const void *, void *);
typedef void *(*xdl_linker_dlopen_o_t)(const char *, int, const void *);

static pthread_mutex_t *xdl_linker_mutex = NULL;
static void *xdl_linker_dlopen = NULL;

static void *xdl_linker_caller_addr[] = {
NULL, // default
NULL, // art
NULL // vendor
};

#ifndef __LP64__
#define XDL_LINKER_LIB "lib"
#else
#define XDL_LINKER_LIB "lib64"
#endif
static const char *xdl_linker_vendor_path[] = {
// order is important
"/vendor/" XDL_LINKER_LIB "/egl/", "/vendor/" XDL_LINKER_LIB "/hw/",
"/vendor/" XDL_LINKER_LIB "/", "/odm/" XDL_LINKER_LIB "/",
"/vendor/" XDL_LINKER_LIB "/vndk-sp/", "/odm/" XDL_LINKER_LIB "/vndk-sp/"};
typedef enum { MATCH_PREFIX, MATCH_SUFFIX } xdl_linker_match_type_t;

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wpadded"
typedef struct {
xdl_linker_match_type_t type;
const char *value;
} xdl_linker_match_t;
#pragma clang diagnostic pop

typedef struct {
void *addr;
xdl_linker_match_t *matches;
size_t matches_cursor;
} xdl_linker_caller_t;

// https://source.android.com/docs/core/architecture/vndk/linker-namespace
// The following rules are loose and incomplete, you can add more according to your needs.
static xdl_linker_match_t xdl_linker_match_default[] = {{MATCH_SUFFIX, "/libc.so"}};
static xdl_linker_match_t xdl_linker_match_art[] = {{MATCH_SUFFIX, "/libart.so"}};
static xdl_linker_match_t xdl_linker_match_sphal[] = {{MATCH_PREFIX, "/vendor/" LIB "/egl/"},
{MATCH_PREFIX, "/vendor/" LIB "/hw/"},
{MATCH_PREFIX, "/vendor/" LIB "/"},
{MATCH_PREFIX, "/odm/" LIB "/"}};
static xdl_linker_match_t xdl_linker_match_vndk[] = {{MATCH_PREFIX, "/apex/com.android.vndk.v"},
{MATCH_PREFIX, "/vendor/" LIB "/vndk-sp/"},
{MATCH_PREFIX, "/odm/" LIB "/vndk-sp/"}};
static xdl_linker_caller_t xdl_linker_callers[] = {
{NULL, xdl_linker_match_default, sizeof(xdl_linker_match_default) / sizeof(xdl_linker_match_t)},
{NULL, xdl_linker_match_art, sizeof(xdl_linker_match_art) / sizeof(xdl_linker_match_t)},
{NULL, xdl_linker_match_sphal, sizeof(xdl_linker_match_sphal) / sizeof(xdl_linker_match_t)},
{NULL, xdl_linker_match_vndk, sizeof(xdl_linker_match_vndk) / sizeof(xdl_linker_match_t)}};

static void xdl_linker_init_symbols_impl(void) {
// find linker from: /proc/self/maps (API level < 18) or getauxval (API level >= 18)
Expand Down Expand Up @@ -121,41 +143,44 @@ static void *xdl_linker_get_caller_addr(struct dl_phdr_info *info) {
return NULL;
}

static int xdl_linker_get_caller_addr_cb(struct dl_phdr_info *info, size_t size, void *arg) {
(void)size;

size_t *vendor_match = (size_t *)arg;
static void xdl_linker_save_caller_addr(struct dl_phdr_info *info, xdl_linker_caller_t *caller,
size_t cursor) {
void *addr = xdl_linker_get_caller_addr(info);
if (NULL != addr) {
caller->addr = addr;
caller->matches_cursor = cursor;
}
}

static int xdl_linker_get_caller_addr_cb(struct dl_phdr_info *info, size_t size, void *arg) {
(void)size, (void)arg;
if (0 == info->dlpi_addr || NULL == info->dlpi_name) return 0; // continue

if (NULL == xdl_linker_caller_addr[0] && xdl_util_ends_with(info->dlpi_name, "/libc.so"))
xdl_linker_caller_addr[0] = xdl_linker_get_caller_addr(info);

if (NULL == xdl_linker_caller_addr[1] && xdl_util_ends_with(info->dlpi_name, "/libart.so"))
xdl_linker_caller_addr[1] = xdl_linker_get_caller_addr(info);

if (0 != *vendor_match) {
for (size_t i = 0; i < *vendor_match; i++) {
if (xdl_util_starts_with(info->dlpi_name, xdl_linker_vendor_path[i])) {
void *caller_addr = xdl_linker_get_caller_addr(info);
if (NULL != caller_addr) {
xdl_linker_caller_addr[2] = caller_addr;
*vendor_match = i;
}
int ret = 1; // OK
for (size_t i = 0; i < sizeof(xdl_linker_callers) / sizeof(xdl_linker_callers[0]); i++) {
xdl_linker_caller_t *caller = &xdl_linker_callers[i];
for (size_t j = 0; j < caller->matches_cursor; j++) {
xdl_linker_match_t *match = &caller->matches[j];
switch (match->type) {
case MATCH_PREFIX:
if (xdl_util_starts_with(info->dlpi_name, match->value)) {
xdl_linker_save_caller_addr(info, caller, j);
}
break;
case MATCH_SUFFIX:
if (xdl_util_ends_with(info->dlpi_name, match->value)) {
xdl_linker_save_caller_addr(info, caller, j);
}
break;
}
}
if (NULL == caller->addr || 0 != caller->matches_cursor) ret = 0; // continue
}

if (NULL != xdl_linker_caller_addr[0] && NULL != xdl_linker_caller_addr[1] && 0 == *vendor_match) {
return 1; // finish
} else {
return 0; // continue
}
return ret;
}

static void xdl_linker_init_caller_addr_impl(void) {
size_t vendor_match = sizeof(xdl_linker_vendor_path) / sizeof(xdl_linker_vendor_path[0]);
xdl_iterate_phdr_impl(xdl_linker_get_caller_addr_cb, &vendor_match, XDL_DEFAULT);
xdl_iterate_phdr_impl(xdl_linker_get_caller_addr_cb, NULL, XDL_DEFAULT);
}

static void xdl_linker_init_caller_addr(void) {
Expand Down Expand Up @@ -186,19 +211,20 @@ void *xdl_linker_force_dlopen(const char *filename) {
if (__ANDROID_API_N__ == api_level || __ANDROID_API_N_MR1__ == api_level) {
// == Android 7.x
xdl_linker_lock();
for (size_t i = 0; i < sizeof(xdl_linker_caller_addr) / sizeof(xdl_linker_caller_addr[0]); i++) {
if (NULL != xdl_linker_caller_addr[i]) {
handle =
((xdl_linker_dlopen_n_t)xdl_linker_dlopen)(filename, RTLD_NOW, NULL, xdl_linker_caller_addr[i]);
for (size_t i = 0; i < sizeof(xdl_linker_callers) / sizeof(xdl_linker_callers[0]); i++) {
xdl_linker_caller_t *caller = &xdl_linker_callers[i];
if (NULL != caller->addr) {
handle = ((xdl_linker_dlopen_n_t)xdl_linker_dlopen)(filename, RTLD_NOW, NULL, caller->addr);
if (NULL != handle) break;
}
}
xdl_linker_unlock();
} else {
// >= Android 8.0
for (size_t i = 0; i < sizeof(xdl_linker_caller_addr) / sizeof(xdl_linker_caller_addr[0]); i++) {
if (NULL != xdl_linker_caller_addr[i]) {
handle = ((xdl_linker_dlopen_o_t)xdl_linker_dlopen)(filename, RTLD_NOW, xdl_linker_caller_addr[i]);
for (size_t i = 0; i < sizeof(xdl_linker_callers) / sizeof(xdl_linker_callers[0]); i++) {
xdl_linker_caller_t *caller = &xdl_linker_callers[i];
if (NULL != caller->addr) {
handle = ((xdl_linker_dlopen_o_t)xdl_linker_dlopen)(filename, RTLD_NOW, caller->addr);
if (NULL != handle) break;
}
}
Expand Down
2 changes: 1 addition & 1 deletion xdl_sample/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ android {

dependencies {
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'com.google.android.material:material:1.8.0'
implementation 'com.google.android.material:material:1.11.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'

if (rootProject.ext.dependencyOnLocalLibrary) {
Expand Down

0 comments on commit 753d043

Please sign in to comment.