Baike.dev
All toolsAI codingTrendingOpen sourceNewsSubmit
Log in
< Back to tools
X

xDL

> 编程语言
Open source

:fire: xDL is an enhanced implementation of the Android DL series functions.

643 stars0 likes0 views
WebsiteGitHub

About

:fire: xDL is an enhanced implementation of the Android DL series functions.

xDL

xDL is an enhanced implementation of the Android DL series functions.

简体中文

Features

  • Enhanced dlopen() + dlsym() + dladdr().
    • Bypass the restrictions of Android 7.0+ linker namespace.
    • Lookup dynamic link symbols in .dynsym.
    • Lookup debuging symbols in .symtab and ".symtab in .gnu_debugdata".
  • Enhanced dl_iterate_phdr().
    • Compatible with Android 4.x on ARM32.
    • Including linker / linker64 (for Android CMakeLists.txt
find_package(xdl REQUIRED CONFIG)

add_library(mylib SHARED mylib.c)
target_link_libraries(mylib xdl::xdl)

Android.mk

include $(CLEAR_VARS)
LOCAL_MODULE           := mylib
LOCAL_SRC_FILES        := mylib.c
LOCAL_SHARED_LIBRARIES += xdl
include $(BUILD_SHARED_LIBRARY)

$(call import-module,prefab/xdl)

3. Specify one or more ABI(s) you need

android {
    defaultConfig {
        ndk {
            abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
        }
    }
}

4. Add packaging options

If you are using xDL in an SDK project, you may need to avoid packaging libxdl.so into your AAR, so as not to encounter duplicate libxdl.so file when packaging the app project.

android {
    packagingOptions {
        exclude '**/libxdl.so'
    }
}

On the other hand, if you are using xDL in an APP project, you may need to add some options to deal with conflicts caused by duplicate libxdl.so file.

android {
    packagingOptions {
        pickFirst '**/libxdl.so'
    }
}

There is a sample app in the xdl-sample folder you can refer to.

API

#include "xdl.h"

1. xdl_open() and xdl_close()

#define XDL_DEFAULT           0x00
#define XDL_TRY_FORCE_LOAD    0x01
#define XDL_ALWAYS_FORCE_LOAD 0x02

void *xdl_open(const char *filename, int flags);
void *xdl_open2(struct dl_phdr_info *info);
void *xdl_close(void *handle);

They are very similar to dlopen() and dlclose(). But xdl_open() can bypass the restrictions of Android 7.0+ linker namespace.

Depending on the value of the flags parameter, the behavior of xdl_open() will have some differences:

  • XDL_DEFAULT: If the library has been loaded into memory, xdl_open() will not dlopen() it again. (But it will still return a valid handle)
  • XDL_TRY_FORCE_LOAD: If the library has not been loaded into memory, xdl_open() will try to dlopen() it.
  • XDL_ALWAYS_FORCE_LOAD: xdl_open() will always dlopen() the library.

If xdl_open() really uses dlopen() to load the library, xdl_close() will return the handle from linker (the return value of dlopen()), and then you can decide whether and when to close it with standard dlclose(). Otherwise, NULL will be returned.

filename can be basename or full pathname. However, Android linker has used the namespace mechanism since 7.0. If you pass basename, you need to make sure that no duplicate ELF is loaded into the current process. xdl_open() will only return the first matching ELF. Please consider this fragment of /proc/self/maps on Android 10:

…

xdl_open2() creates a handle from struct dl_phdr_info. xdl_open2() is always XDL_DEFAULT semantics, i.e. it will not try to load ELF with dlopen().

2. xdl_sym() and xdl_dsym()

void *xdl_sym(void *handle, const char *symbol, size_t *symbol_size);
void *xdl_dsym(void *handle, const char *symbol, size_t *symbol_size);

They are very similar to dlsym(). They all takes a "handle" of an ELF returned by xdl_open() and the null-terminated symbol name, returning the address where that symbol is loaded into memory.

If the symbol_size parameter is not NULL, it will be assigned as "the bytes occupied by the content corresponding to the symbol in the ELF". If you don't need this information, just pass NULL.

xdl_sym() lookup "dynamic link symbols" in .dynsym as dlsym() does.

xdl_dsym() lookup "debuging symbols" in .symtab and ".symtab in .gnu_debugdata".

Notice:

  • The symbol sets in .dynsym and .symtab do not contain each other. Some symbols only exist in .dynsym, and some only exist in .symtab. You may need to use tools such as readelf to determine which ELF section the symbol you are looking for is in.
  • xdl_dsym() needs to load debuging symbols from disk file, and xdl_sym() only lookup dynamic link symbols from memory. So xdl_dsym() runs slower than xdl_sym().
  • The dynamic linker only uses symbols in .dynsym. The debugger actually uses the symbols in both .dynsym and .symtab.

3. xdl_addr()

typedef struct
{
    const char       *dli_fname;
    void             *dli_fbase;
    const char       *dli_sname;
    void             *dli_saddr;
    size_t            dli_ssize;
    const ElfW(Phdr) *dlpi_phdr;
    size_t            dlpi_phnum;
} xdl_info_t;

#define XDL_DEFAULT 0x00
#define XDL_NON_SYM 0x01

int xdl_addr(void *addr, xdl_info_t *info, void **cache);
int xdl_addr4(void *addr, xdl_info_t *info, void **cache, int flags);
void xdl_addr_clean(void **cache);

xdl_addr() is similar to dladdr(). But there are a few differences:

  • xdl_addr() can lookup not only dynamic link symbols, but also debugging symbols.
  • 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.
  • 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:
void *cache = NULL;
xdl_info_t info;
xdl_addr(addr_1, &info, &cache);
xdl_addr(addr_2, &info, &cache);
xdl_addr(addr_3, &info, &cache);
xdl_addr_clean(&cache);
  • xdl_addr4() is similar to xdl_addr(), except that it adds the flags parameter. When the flags value is XDL_DEFAULT, the behavior of xdl_addr4() is the same as xdl_addr(). When the flags value is XDL_NON_SYM, xdl_addr4() will not obtain symbol-related information (the values of dli_sname, dli_saddr, and dli_ssize in xdl_info_t are all 0).

4. xdl_iterate_phdr()

#define XDL_DEFAULT       0x00
#define XDL_FULL_PATHNAME 0x01

int xdl_iterate_phdr(int (*callback)(struct dl_phdr_info *, size_t, void *), void *data, int flags);

xdl_iterate_phdr() is similar to dl_iterate_phdr(). But xdl_iterate_phdr() is compatible with android 4.x on ARM32, and always including linker / linker64.

xdl_iterate_phdr() has an additional "flags" parameter, one or more flags can be bitwise-or'd in it:

  • XDL_DEFAULT: Default behavior.
  • XDL_FULL_PATHNAME: Always return full pathname instead of basename.

These flags are needed because these capabilities require additional execution time, and you don't always need them.

5. xdl_info()

#define XDL_DI_DLINFO 1  // type of info: xdl_info_t

int xdl_info(void *handle, int request, void *info);

xdl_info() is similar to dlinfo(). xdl_info() obtains information about the dynamically loaded object referred to by handle (obtained by an earlier call to xdl_open).

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).

On success, xdl_info() returns 0. On failure, it returns -1.

Support

  • GitHub Issues
  • GitHub Discussions

Contributing

  • Code of Conduct
  • Contributing Guide
  • Reporting Security vulnerabilities

License

xDL is MIT licensed, as found in the LICENSE file.

Issues· 0 open

View all issuesOpen on GitHub

No open issues yet, or sync has not completed.

> Tags

Candroidbypassdebugging-symboldlopen

No comments yet. Be the first to share.

> Details

PublishedAug 1, 2026
UpdatedSep 17, 2026
Category编程语言
PricingOpen source

> Related tools

T
TypeScript
JavaScript 的超集,为前端与全栈提供静态类型
P
Python
通用编程语言,广泛用于 Web、数据与 AI
G
Go
Google 推出的简洁高效系统语言