Recursive Loading

ReLinker can now resolve and link intra-library dependencies for you. The resolution of intra-library dependency happens recursively until all dependencies are properly linked. All that is needed is for you to specify that you would like ReLinker to recursively load libraries:

Specifically speaking, ReLinker will attempt to load any libraries defined as DT_NEEDED within your shared object file. You can check what libraries ReLinker will attempt to recursively load by executing

$ readelf -d lib.so | grep NEEDED

Which, for libhellojni.so (bundled with ReLinker’s sample), outputs:

0x00000001 (NEEDED) Shared library: [libhello.so]

0x00000001 (NEEDED) Shared library: [libstdc++.so]

0x00000001 (NEEDED) Shared library: [libm.so]

0x00000001 (NEEDED) Shared library: [libc.so]

0x00000001 (NEEDED) Shared library: [libdl.so]

Recursive loading exists to resolve an issue with Android’s native library linker on older versions of Android (< API 18) where the linker fails to resolve any intra-library dependencies not bundled with the system.

On Android, shared libraries utilize the ELF format. Within the library file, the ELF format defines a list of dependencies (other libraries) that the library relies on. Typically you will see very common libraries such as libc, libm, and libdl defined as dependencies for your library. Each of these libraries are typically provided by the system itself and do not need to be bundled with your app.

The problem arises when you define your own supplied library as a dependency in another library. On versions of Android < API 18, your supplied library is not added to the library load path, and thus will not be found by the system’s linker. This is because the system’s linker does not consider your app’s library directory for libraries and looks in a static list of directories for libraries. This can be seen here in Bionic’s linker source code for Gingerbread.

Unfortunately, this means that you need to explicitly load libraries in reverse order of dependence manually on versions of Android < API 18. If you don’t, then you get a lovely exception similar to: