Skip to content

Commit 0e09289

Browse files
committed
Add xdl_info().
1 parent 6ef0f9f commit 0e09289

File tree

8 files changed

+93
-34
lines changed

8 files changed

+93
-34
lines changed

README.md

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
![](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat)
44
![](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat)
5-
![](https://img.shields.io/badge/release-1.1.5-red.svg?style=flat)
5+
![](https://img.shields.io/badge/release-1.2.0-red.svg?style=flat)
66
![](https://img.shields.io/badge/Android-4.1%20--%2013-blue.svg?style=flat)
77
![](https://img.shields.io/badge/arch-armeabi--v7a%20%7C%20arm64--v8a%20%7C%20x86%20%7C%20x86__64-blue.svg?style=flat)
88

@@ -61,7 +61,7 @@ android {
6161
}
6262
6363
dependencies {
64-
implementation 'io.hexhacking:xdl:1.1.5'
64+
implementation 'io.hexhacking:xdl:1.2.0'
6565
}
6666
```
6767

@@ -202,21 +202,21 @@ typedef struct
202202
size_t dli_ssize;
203203
const ElfW(Phdr) *dlpi_phdr;
204204
size_t dlpi_phnum;
205-
} xdl_info;
205+
} xdl_info_t;
206206

207-
int xdl_addr(void *addr, xdl_info *info, void **cache);
207+
int xdl_addr(void *addr, xdl_info_t *info, void **cache);
208208
void xdl_addr_clean(void **cache);
209209
```
210210
211211
`xdl_addr()` is similar to [`dladdr()`](https://man7.org/linux/man-pages/man3/dladdr.3.html). But there are a few differences:
212212
213213
* `xdl_addr()` can lookup not only dynamic link symbols, but also debugging symbols.
214-
* `xdl_addr()` uses the `xdl_info` structure instead of the `Dl_info` structure, which contains more extended information: `dli_ssize` is the number of bytes occupied by the current symbol; `dlpi_phdr` points to the program headers array of the ELF where the current symbol is located; `dlpi_phnum` is the number of elements in the `dlpi_phdr` array.
214+
* `xdl_addr()` uses the `xdl_info_t` structure instead of the `Dl_info` structure, which contains more extended information: `dli_ssize` is the number of bytes occupied by the current symbol; `dlpi_phdr` points to the program headers array of the ELF where the current symbol is located; `dlpi_phnum` is the number of elements in the `dlpi_phdr` array.
215215
* `xdl_addr()` needs to pass an additional parameter (`cache`), which will cache the ELF handle opened during the execution of `xdl_addr()`. The purpose of caching is to make subsequent executions of `xdl_addr()` of the same ELF faster. When you do not need to execute `xdl_addr()`, please use `xdl_addr_clean()` to clear the cache. For example:
216216
217217
```C
218218
void *cache = NULL;
219-
xdl_info info;
219+
xdl_info_t info;
220220
xdl_addr(addr_1, &info, &cache);
221221
xdl_addr(addr_2, &info, &cache);
222222
xdl_addr(addr_3, &info, &cache);
@@ -241,6 +241,19 @@ int xdl_iterate_phdr(int (*callback)(struct dl_phdr_info *, size_t, void *), voi
241241
242242
These flags are needed because these capabilities require additional execution time, and you don't always need them.
243243
244+
### 5. `xdl_info()`
245+
246+
```C
247+
#define XDL_DI_DLINFO 1 // type of info: xdl_info_t
248+
249+
int xdl_info(void *handle, int request, void *info);
250+
```
251+
252+
`xdl_info()` is similar to [`dlinfo()`](https://man7.org/linux/man-pages/man3/dl_iterate_phdr.3.html). `xdl_info()` obtains information about the dynamically loaded object referred to by `handle` (obtained by an earlier call to `xdl_open`).
253+
254+
The only `request` parameter currently supported is `XDL_DI_DLINFO`, which means to return data of type `xdl_info_t` through the `info` parameter (note that the values of `dli_sname`, `dli_saddr`, `dli_ssize` in the returned `xdl_info_t` at this time both are `0`).
255+
256+
On success, `xdl_info()` returns `0`. On failure, it returns `-1`.
244257

245258
## Support
246259

README.zh-CN.md

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
![](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat)
44
![](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat)
5-
![](https://img.shields.io/badge/release-1.1.5-red.svg?style=flat)
5+
![](https://img.shields.io/badge/release-1.2.0-red.svg?style=flat)
66
![](https://img.shields.io/badge/Android-4.1%20--%2013-blue.svg?style=flat)
77
![](https://img.shields.io/badge/arch-armeabi--v7a%20%7C%20arm64--v8a%20%7C%20x86%20%7C%20x86__64-blue.svg?style=flat)
88

@@ -61,7 +61,7 @@ android {
6161
}
6262
6363
dependencies {
64-
implementation 'io.hexhacking:xdl:1.1.5'
64+
implementation 'io.hexhacking:xdl:1.2.0'
6565
}
6666
```
6767

@@ -142,7 +142,7 @@ void *xdl_open(const char *filename, int flags);
142142
void *xdl_close(void *handle);
143143
```
144144
145-
它们和 [`dlopen()`](https://man7.org/linux/man-pages/man3/dlopen.3.html) / [`dlclose()`](https://man7.org/linux/man-pages/man3/dlclose.3.html) 很相似。但是 `xdl_open()` 可以绕过 Android 7.0+ linker namespace 的限制。
145+
它们和 [`dlopen()`](https://man7.org/linux/man-pages/man3/dlopen.3.html) / [`dlclose()`](https://man7.org/linux/man-pages/man3/dlclose.3.html) 类似。但是 `xdl_open()` 可以绕过 Android 7.0+ linker namespace 的限制。
146146
147147
根据 `flags` 参数值的不同,`xdl_open()` 的行为会有一些差异:
148148
@@ -176,7 +176,7 @@ void *xdl_sym(void *handle, const char *symbol, size_t *symbol_size);
176176
void *xdl_dsym(void *handle, const char *symbol, size_t *symbol_size);
177177
```
178178

179-
它们和 [`dlsym()`](https://man7.org/linux/man-pages/man3/dlsym.3.html) 很相似。 它们都需要传递一个 `xdl_open()` 返回的 “handle”,和一个 null 结尾的符号名字,返回该符号在内存中的加载地址。
179+
它们和 [`dlsym()`](https://man7.org/linux/man-pages/man3/dlsym.3.html) 类似。 它们都需要传递一个 `xdl_open()` 返回的 “handle”,和一个 null 结尾的符号名字,返回该符号在内存中的加载地址。
180180

181181
如果 `symbol_size` 参数不为 `NULL`,它将被赋值为“符号对应的内容在 ELF 中占用的字节数”,如果你不需要这个信息,传递 `NULL` 就可以了。
182182

@@ -202,21 +202,21 @@ typedef struct
202202
size_t dli_ssize;
203203
const ElfW(Phdr) *dlpi_phdr;
204204
size_t dlpi_phnum;
205-
} xdl_info;
205+
} xdl_info_t;
206206

207-
int xdl_addr(void *addr, xdl_info *info, void **cache);
207+
int xdl_addr(void *addr, xdl_info_t *info, void **cache);
208208
void xdl_addr_clean(void **cache);
209209
```
210210
211-
`xdl_addr()` 和 [`dladdr()`](https://man7.org/linux/man-pages/man3/dladdr.3.html) 很相似。但有以下几点不同:
211+
`xdl_addr()` 和 [`dladdr()`](https://man7.org/linux/man-pages/man3/dladdr.3.html) 类似。但有以下几点不同:
212212
213213
* `xdl_addr()` 不仅能查询动态链接符号,还能查询调试符号。
214-
* `xdl_addr()` 使用 `dl_info` 结构体代替了 `Dl_info` 结构体,它包含了更多的扩展信息:`dli_ssize` 是当前符号所占用的字节数;`dlpi_phdr` 指向当前符号所在 ELF 的 program headers 数组;`dlpi_phnum` 是 `dlpi_phdr` 数组的元素个数。
214+
* `xdl_addr()` 使用 `xdl_info_t` 结构体代替了 `Dl_info` 结构体,它包含了更多的扩展信息:`dli_ssize` 是当前符号所占用的字节数;`dlpi_phdr` 指向当前符号所在 ELF 的 program headers 数组;`dlpi_phnum` 是 `dlpi_phdr` 数组的元素个数。
215215
* `xdl_addr()` 需要传递一个附加的参数(cache),其中会缓存 `xdl_addr()` 执行过程中打开的 ELF handle,缓存的目的是使后续对同一个 ELF 的 `xdl_addr()` 执行的更快。当不需要再执行 `xdl_addr()` 时,请使用 `xdl_addr_clean()` 清除缓存。举例:
216216
217217
```C
218218
void *cache = NULL;
219-
Dl_info info;
219+
xdl_info_t info;
220220
xdl_addr(addr_1, &info, &cache);
221221
xdl_addr(addr_2, &info, &cache);
222222
xdl_addr(addr_3, &info, &cache);
@@ -232,7 +232,7 @@ xdl_addr_clean(&cache);
232232
int xdl_iterate_phdr(int (*callback)(struct dl_phdr_info *, size_t, void *), void *data, int flags);
233233
```
234234
235-
`xdl_iterate_phdr()` 和 [`dl_iterate_phdr()`](https://man7.org/linux/man-pages/man3/dl_iterate_phdr.3.html) 很相似。但是 `xdl_iterate_phdr()` 兼容 ARM32 平台的 Android 4.x 系统,并且总是包含 linker / linker64。
235+
`xdl_iterate_phdr()` 和 [`dl_iterate_phdr()`](https://man7.org/linux/man-pages/man3/dl_iterate_phdr.3.html) 类似。但是 `xdl_iterate_phdr()` 兼容 ARM32 平台的 Android 4.x 系统,并且总是包含 linker / linker64。
236236
237237
`xdl_iterate_phdr()` 有一个额外的“flags”参数,一个或多个“flag”可以按位“或”后传递给它:
238238
@@ -241,6 +241,19 @@ int xdl_iterate_phdr(int (*callback)(struct dl_phdr_info *, size_t, void *), voi
241241
242242
需要这些 flags 的原因是,这些额外的能力也需要花费额外的执行时间,而你并不总是需要这些能力。
243243
244+
### 5. `xdl_info()`
245+
246+
```C
247+
#define XDL_DI_DLINFO 1 // type of info: xdl_info_t
248+
249+
int xdl_info(void *handle, int request, void *info);
250+
```
251+
252+
`xdl_info()`[`dlinfo()`](https://man7.org/linux/man-pages/man3/dl_iterate_phdr.3.html) 类似。`xdl_info()` 通过 `handle``xdl_open` 的返回值)来获取动态加载对象的信息。
253+
254+
目前唯一支持的 `request` 参数是 `XDL_DI_DLINFO`,表示通过 `info` 参数返回 `xdl_info_t` 类型的数据(注意,此时返回的 `xdl_info_t``dli_sname``dli_saddr``dli_ssize` 的值均为 `0`)。
255+
256+
成功时 `xdl_info()` 返回 `0`,失败时返回 `-1`
244257

245258
## 技术支持
246259

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ ext {
2121

2222
POM_GROUP_ID = "io.hexhacking"
2323
POM_ARTIFACT_ID = "xdl"
24-
POM_VERSION_NAME = "1.1.5"
24+
POM_VERSION_NAME = "1.2.0"
2525

2626
POM_NAME = "xDL Android Lib"
2727
POM_DESCRIPTION = "xDL is an enhanced implementation of the Android DL series functions."

xdl/src/main/cpp/include/xdl.h

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
// Created by caikelun on 2020-10-04.
2323

2424
//
25-
// xDL version: 1.1.5
25+
// xDL version: 1.2.0
2626
//
2727
// xDL is an enhanced implementation of the Android DL series functions.
2828
// For more information, documentation, and the latest version please check:
@@ -40,6 +40,18 @@
4040
extern "C" {
4141
#endif
4242

43+
typedef struct {
44+
// same as Dl_info:
45+
const char *dli_fname; // Pathname of shared object that contains address.
46+
void *dli_fbase; // Address at which shared object is loaded.
47+
const char *dli_sname; // Name of nearest symbol with address lower than addr.
48+
void *dli_saddr; // Exact address of symbol named in dli_sname.
49+
// added by xDL:
50+
size_t dli_ssize; // Symbol size of nearest symbol with address lower than addr.
51+
const ElfW(Phdr) *dlpi_phdr; // Pointer to array of ELF program headers for this object.
52+
size_t dlpi_phnum; // Number of items in dlpi_phdr.
53+
} xdl_info_t;
54+
4355
//
4456
// Default value for flags in both xdl_open() and xdl_iterate_phdr().
4557
//
@@ -58,18 +70,7 @@ void *xdl_dsym(void *handle, const char *symbol, size_t *symbol_size);
5870
//
5971
// Enhanced dladdr().
6072
//
61-
typedef struct {
62-
// same as Dl_info:
63-
const char *dli_fname; // Pathname of shared object that contains address.
64-
void *dli_fbase; // Address at which shared object is loaded.
65-
const char *dli_sname; // Name of nearest symbol with address lower than addr.
66-
void *dli_saddr; // Exact address of symbol named in dli_sname.
67-
// added by xDL:
68-
size_t dli_ssize; // Symbol size of nearest symbol with address lower than addr.
69-
const ElfW(Phdr) *dlpi_phdr; // Pointer to array of ELF program headers for this object.
70-
size_t dlpi_phnum; // Number of items in dlpi_phdr.
71-
} xdl_info;
72-
int xdl_addr(void *addr, xdl_info *info, void **cache);
73+
int xdl_addr(void *addr, xdl_info_t *info, void **cache);
7374
void xdl_addr_clean(void **cache);
7475

7576
//
@@ -78,6 +79,12 @@ void xdl_addr_clean(void **cache);
7879
#define XDL_FULL_PATHNAME 0x01
7980
int xdl_iterate_phdr(int (*callback)(struct dl_phdr_info *, size_t, void *), void *data, int flags);
8081

82+
//
83+
// Custom dlinfo().
84+
//
85+
#define XDL_DI_DLINFO 1 // type of info: xdl_info_t
86+
int xdl_info(void *handle, int request, void *info);
87+
8188
#ifdef __cplusplus
8289
}
8390
#endif

xdl/src/main/cpp/xdl.c

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -792,7 +792,7 @@ static ElfW(Sym) *xdl_dsym_by_addr(void *handle, void *addr) {
792792
return NULL;
793793
}
794794

795-
int xdl_addr(void *addr, xdl_info *info, void **cache) {
795+
int xdl_addr(void *addr, xdl_info_t *info, void **cache) {
796796
if (NULL == addr || NULL == info || NULL == cache) return 0;
797797

798798
memset(info, 0, sizeof(Dl_info));
@@ -851,3 +851,19 @@ int xdl_iterate_phdr(int (*callback)(struct dl_phdr_info *, size_t, void *), voi
851851

852852
return xdl_iterate_phdr_impl(callback, data, flags);
853853
}
854+
855+
int xdl_info(void *handle, int request, void *info) {
856+
if (NULL == handle || XDL_DI_DLINFO != request || NULL == info) return -1;
857+
858+
xdl_t *self = (xdl_t *)handle;
859+
xdl_info_t *dlinfo = (xdl_info_t *)info;
860+
861+
dlinfo->dli_fbase = (void *)self->load_bias;
862+
dlinfo->dli_fname = self->pathname;
863+
dlinfo->dli_sname = NULL;
864+
dlinfo->dli_saddr = 0;
865+
dlinfo->dli_ssize = 0;
866+
dlinfo->dlpi_phdr = self->dlpi_phdr;
867+
dlinfo->dlpi_phnum = (size_t)self->dlpi_phnum;
868+
return 0;
869+
}

xdl/src/main/cpp/xdl.map.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
xdl_addr;
88
xdl_addr_clean;
99
xdl_iterate_phdr;
10+
xdl_info;
1011

1112
local:
1213
*;

xdl_sample/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ dependencies {
6666
if (rootProject.ext.dependencyOnLocalLibrary) {
6767
implementation project(':xdl')
6868
} else {
69-
implementation 'io.hexhacking:xdl:1.1.5'
69+
implementation 'io.hexhacking:xdl:1.2.0'
7070
}
7171
}
7272

xdl_sample/src/main/cpp/sample.c

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,18 +65,27 @@ static void sample_test_iterate(void) {
6565

6666
static void *sample_test_dlsym(const char *filename, const char *symbol, bool debug_symbol, void **cache,
6767
bool try_force_dlopen) {
68+
xdl_info_t info;
69+
6870
if (try_force_dlopen) {
6971
void *linker_handle = dlopen(filename, RTLD_NOW);
7072
LOG("--- dlopen(%s) : handle %" PRIxPTR, filename, (uintptr_t)linker_handle);
7173
if (NULL != linker_handle) dlclose(linker_handle);
7274
}
7375

74-
LOG("+++ xdl_open + %s + xdl_addr", debug_symbol ? "xdl_dsym" : "xdl_sym");
76+
LOG("+++ xdl_open + xdl_info + %s + xdl_addr", debug_symbol ? "xdl_dsym" : "xdl_sym");
7577

7678
// xdl_open
7779
void *handle = xdl_open(filename, try_force_dlopen ? XDL_TRY_FORCE_LOAD : XDL_DEFAULT);
7880
LOG(">>> xdl_open(%s) : handle %" PRIxPTR, filename, (uintptr_t)handle);
7981

82+
// xdl_info
83+
memset(&info, 0, sizeof(xdl_info_t));
84+
xdl_info(handle, XDL_DI_DLINFO, &info);
85+
LOG(">>> xdl_info(%" PRIxPTR ") : %" PRIxPTR " %s (phdr %" PRIxPTR ", phnum %zu)", (uintptr_t)handle,
86+
(uintptr_t)info.dli_fbase, (NULL == info.dli_fname ? "(NULL)" : info.dli_fname),
87+
(uintptr_t)info.dlpi_phdr, info.dlpi_phnum);
88+
8089
// xdl_dsym / xdl_sym
8190
size_t symbol_size = 0;
8291
void *symbol_addr = (debug_symbol ? xdl_dsym : xdl_sym)(handle, symbol, &symbol_size);
@@ -87,7 +96,7 @@ static void *sample_test_dlsym(const char *filename, const char *symbol, bool de
8796
void *linker_handle = xdl_close(handle);
8897

8998
// xdl_addr
90-
xdl_info info;
99+
memset(&info, 0, sizeof(xdl_info_t));
91100
if (0 == xdl_addr(symbol_addr, &info, cache))
92101
LOG(">>> xdl_addr(%" PRIxPTR ") : FAILED", (uintptr_t)symbol_addr);
93102
else

0 commit comments

Comments
 (0)