The dynamic linker tackles two challenges in Treble VNDK design:
- SP-HAL shared libraries and their dependencies, including VNDK-SP libraries, are loaded into framework processes. There should be some mechanisms to prevent symbol conflicts.
dlopen()
andandroid_dlopen_ext()
can introduce some runtime dependencies that aren't visible at build time and can be difficult to detect using static analysis.
These two challenges can be resolved by the linker namespace mechanism. This mechanism is provided by the dynamic linker. It can isolate the shared libraries in different linker namespaces so that libraries with same library name but with different symbols won't conflict.
On the other hand, the linker namespace mechanism provides the flexibility so that some shared libraries can be exported by a linker namespace and used by another linker namespace. These exported shared libraries can become application programming interfaces that are public to other programs while hiding their implementation details within their linker namespaces.
For example, /system/lib[64]/libcutils.so
and
/system/lib[64]/vndk-sp-${VER}/libcutils.so
are two shared
libraries. These two libraries can have different symbols. They're loaded
into different linker namespaces so that framework modules can depend on
/system/lib[64]/libcutils.so
and SP-HAL shared libraries can
depend on /system/lib[64]/vndk-sp-${VER}/libcutils.so
.
On the other hand, /system/lib[64]/libc.so
is an example of
a public library that's exported by a linker namespace and imported into
many linker namespaces. The dependencies of
/system/lib[64]/libc.so
, such as libnetd_client.so
,
are loaded into the namespace in which /system/lib[64]/libc.so
resides. Other namespaces won't have accesses to those dependencies. This
mechanism encapsulates the implementation details while providing the public
interfaces.
How it works
The dynamic linker is responsible for loading the shared libraries specified
in DT_NEEDED
entries or the shared libraries specified by the
argument of dlopen()
or android_dlopen_ext()
. In both
cases, the dynamic linker finds the linker namespace where the caller
resides and tries to load the dependencies into the same linker namespace. If
the dynamic linker can't load the shared library into the specified linker
namespace, it asks the linked linker namespace for exported shared
libraries.
Configuration file format
The configuration file format is based on the INI file format. A typical configuration file looks like this:
dir.system = /system/bin dir.system = /system/xbin dir.vendor = /vendor/bin [system] additional.namespaces = sphal,vndk namespace.default.isolated = true namespace.default.search.paths = /system/${LIB} namespace.default.permitted.paths = /system/${LIB}/hw namespace.default.asan.search.paths = /data/asan/system/${LIB}:/system/${LIB} namespace.default.asan.permitted.paths = /data/asan/system/${LIB}/hw:/system/${LIB}/hw namespace.sphal.isolated = true namespace.sphal.visible = true namespace.sphal.search.paths = /odm/${LIB}:/vendor/${LIB} namespace.sphal.permitted.paths = /odm/${LIB}:/vendor/${LIB} namespace.sphal.asan.search.paths = /data/asan/odm/${LIB}:/odm/${LIB} namespace.sphal.asan.search.paths += /data/asan/vendor/${LIB}:/vendor/${LIB} namespace.sphal.asan.permitted.paths = /data/asan/odm/${LIB}:/odm/${LIB} namespace.sphal.asan.permitted.paths += /data/asan/vendor/${LIB}:/vendor/${LIB} namespace.sphal.links = default,vndk namespace.sphal.link.default.shared_libs = libc.so:libm.so namespace.sphal.link.vndk.shared_libs = libbase.so:libcutils.so namespace.vndk.isolated = true namespace.vndk.search.paths = /system/${LIB}/vndk-sp-29 namespace.vndk.permitted.paths = /system/${LIB}/vndk-sp-29 namespace.vndk.links = default namespace.vndk.link.default.shared_libs = libc.so:libm.so [vendor] namespace.default.isolated = false namespace.default.search.paths = /vendor/${LIB}:/system/${LIB}
The configuration file includes:
- Several directory-section mapping properties at the beginning for the dynamic linker to select the effective section.
-
Several linker namespaces configuration sections:
- Each section contains several namespaces (graph vertexes) and several fallback links between namespaces (graph arcs).
- Each namespace has its own isolation, search paths, permitted paths, and visibility settings.
The tables below describe the meaning of each property in detail.
Directory-section mapping property
Property | Description | Example |
---|---|---|
|
A path to a directory that the Each property maps the executables under the directory to a linker
namespaces configuration section. There might be two (or more) properties
that have the same |
This indicates that the configuration specified in the
The configuration specified in the |
Relation properties
Property | Description | Example |
---|---|---|
additional. |
A comma-separated list of additional namespaces (in addition to the
|
This indicates that there are three namespaces ( |
namespace. |
A comma-separated list of fallback namespaces. If a shared library can't be found in the current namespace, the dynamic linker tries to load the shared library from the fallback namespaces. The namespace specified at the beginning of the list has higher priority. |
If a shared library or an executable requests a shared library that
can't be loaded into the And then, if the shared library can't be loaded from the
Finally, if all attempts fail, the dynamic linker returns an error. |
namespace. |
A colon-separated list of shared libraries that can be searched in the
This property can't be used with
|
This indicates that the fallback link accepts only |
namespace. |
A boolean value that indicates whether all shared libraries can be
searched in the This property can't be used with
|
This indicates that all library names can walk through the fallback link
from |
Namespace properties
Property | Description | Example |
---|---|---|
namespace. |
A boolean value that indicates whether the dynamic linker should check where the shared library resides. If If |
This indicates that only the shared libraries in
|
namespace. |
A colon-separated list of directories to search for shared libraries. The directories specified in When For example, if |
This indicates that the dynamic linker searches
|
namespace. |
A colon-separated list of directories to search for shared libraries when AddressSanitizer (ASan) is enabled.
|
This indicates that when
ASan is enabled the
dynamic linker searches |
namespace. |
A colon-separated list of directories (including subdirectories) where
the dynamic linker can load the shared libraries (in addition to
The shared libraries that are under the subdirectories of
If |
This indicates that the shared libraries under
For example, without |
namespace. |
A colon-separated list of directories where the dynamic linker can load the shared libraries when ASan is enabled.
|
This indicates that when ASan is enabled
shared libraries under |
namespace. |
A boolean value that indicates whether the program (other than
If If |
This indicates that |
Linker namespace creation
In Android 11, linker configuration is created at runtime under
/linkerconfig
instead of using plain text files in
${android-src}/system/core/rootdir/etc
. The configuration is generated at boot
time based on the runtime environment, which includes following items:
- If device supports VNDK
- Vendor partition's target VNDK version
- Product partition's VNDK version
- Installed APEX modules
Linker configuration is created by resolving dependencies between linker namespaces. For
example, if there are any updates on the APEX modules that include dependency updates, linker
configuration is generated reflecting these changes. More details to create linker configuration
can be found in
${android-src}/system/linkerconfig
.
Linker namespace isolation
There are three configuration types. Depending on the value of
PRODUCT_TREBLE_LINKER_NAMESPACES
and
BOARD_VNDK_VERSION
in BoardConfig.mk
, the
corresponding configuration is generated at boot time.
PRODUCT_TREBLE_ LINKER_NAMESPACES |
BOARD_VNDK_ VERSION |
Selected configuration | VTS requirement |
---|---|---|---|
true |
current |
VNDK |
Mandatory for devices launched with Android 9 or higher |
Empty | VNDK Lite |
Mandatory for devices launched with Android 8.x | |
false |
Empty | Legacy |
For non-Treble devices |
VNDK Lite configuration isolates SP-HAL and VNDK-SP shared libraries. In Android 8.0, this
must be the configuration file for dynamic linker when
PRODUCT_TREBLE_LINKER_NAMESPACES
is true
.
VNDK configuration also isolates SP-HAL and VNDK-SP shared libraries. In addition, this configuration provides the full dynamic linker isolation. It ensures that modules in the system partition won't depend on the shared libraries in the vendor partitions and vice versa.
In Android 8.1 or higher, VNDK configuration is the default configuration
and it's highly recommended to enable full dynamic linker isolation by setting
BOARD_VNDK_VERSION
to current
.
VNDK configuration
VNDK configuration isolates the shared library dependencies between the system partition and vendor partitions. Compared to configurations mentioned in the previous subsection, the differences are outlined as follows:
-
Framework processes
default
,vndk
,sphal
, andrs
namespaces are created.- All namespaces are isolated.
- System shared libraries are loaded into the
default
namespace. - SP-HALs are loaded into the
sphal
namespace. - VNDK-SP shared libraries loaded into the
vndk
namespace.
-
Vendor processes
default
,vndk
, andsystem
namespaces are created.- The
default
namespace is isolated. - Vendor shared libraries are loaded into the
default
namespace. - VNDK and VNDK-SP shared libraries are loaded into the
vndk
namespace. - LL-NDK and its dependencies are loaded into the
system
namespace.
The relationship between the linker namespaces is illustrated below.
Figure 1. Linker namespace isolation (VNDK configuration).
In the image above, LL-NDK and VNDK-SP stand for following shared libraries:
-
LL-NDK
libEGL.so
libGLESv1_CM.so
libGLESv2.so
libGLESv3.so
libandroid_net.so
libc.so
libdl.so
liblog.so
libm.so
libnativewindow.so
libneuralnetworks.so
libsync.so
libvndksupport.so
libvulkan.so
-
VNDK-SP
android.hardware.graphics.common@1.0.so
android.hardware.graphics.mapper@2.0.so
android.hardware.renderscript@1.0.so
android.hidl.memory@1.0.so
libRSCpuRef.so
libRSDriver.so
libRS_internal.so
libbase.so
libbcinfo.so
libc++.so
libcutils.so
libhardware.so
libhidlbase.so
libhidlmemory.so
libhidltransport.so
libhwbinder.so
libion.so
libutils.so
libz.so
You can find more details in /linkerconfig/ld.config.txt
from the device.
VNDK Lite configuration
As of Android 8.0, the dynamic linker is configured to isolate the SP-HAL and VNDK-SP shared libraries such that their symbols don't conflict with other framework shared libraries. The relationship between the linker namespaces is shown below.
LL-NDK and VNDK-SP stand for following shared libraries:
-
LL-NDK
libEGL.so
libGLESv1_CM.so
libGLESv2.so
libc.so
libdl.so
liblog.so
libm.so
libnativewindow.so
libstdc++.so
(not in the configuration)libsync.so
libvndksupport.so
libz.so
(moved to VNDK-SP in the configuration)
-
VNDK-SP
android.hardware.graphics.common@1.0.so
android.hardware.graphics.mapper@2.0.so
android.hardware.renderscript@1.0.so
android.hidl.memory@1.0.so
libbase.so
libc++.so
libcutils.so
libhardware.so
libhidlbase.so
libhidlmemory.so
libhidltransport.so
libhwbinder.so
libion.so
libutils.so
The table below lists the namespaces configuration for framework
processes, which is excerpted from the [system]
section in
the VNDK Lite configuration.
Namespace | Property | Value |
---|---|---|
default |
search.paths |
/system/${LIB} /odm/${LIB} /vendor/${LIB} /product/${LIB}
|
isolated |
false |
|
sphal |
search.paths |
/odm/${LIB} /vendor/${LIB}
|
permitted.paths |
/odm/${LIB} /vendor/${LIB}
|
|
isolated |
true |
|
visible |
true |
|
links |
default,vndk,rs |
|
link.default.shared_libs |
LL-NDK | |
link.vndk.shared_libs |
VNDK-SP | |
link.rs.shared_libs |
libRS_internal.so |
|
vndk (for VNDK-SP) |
search.paths |
/odm/${LIB}/vndk-sp /vendor/${LIB}/vndk-sp /system/${LIB}/vndk-sp-${VER}
|
permitted.paths |
/odm/${LIB}/hw /odm/${LIB}/egl /vendor/${LIB}/hw /vendor/${LIB}/egl /system/${LIB}/vndk-sp-${VER}/hw |
|
isolated |
true |
|
visible |
true |
|
links |
default |
|
link.default.shared_libs |
LL-NDK | |
rs (for RenderScript) |
search.paths |
/odm/${LIB}/vndk-sp /vendor/${LIB}/vndk-sp /system/${LIB}/vndk-sp-${VER} /odm/${LIB} /vendor/${LIB}
|
permitted.paths |
/odm/${LIB} /vendor/${LIB} /data (for compiled RS kernel)
|
|
isolated |
true |
|
visible |
true |
|
links |
default,vndk |
|
link.default.shared_libs |
LL-NDKlibmediandk.so libft2.so
|
|
link.vndk.shared_libs |
VNDK-SP |
The table below presents the namespaces configuration for vendor processes,
which is excerpted from the [vendor]
section in
the VNDK Lite configuration.
Namespace | Property | Value |
---|---|---|
default |
search.paths |
/odm/${LIB} /odm/${LIB}/vndk /odm/${LIB}/vndk-sp /vendor/${LIB} /vendor/${LIB}/vndk /vendor/${LIB}/vndk-sp /system/${LIB}/vndk-${VER} /system/${LIB}/vndk-sp-${VER} /system/${LIB} (deprecated)/product/${LIB} (deprecated)
|
isolated |
false |
More details can be found in /linkerconfig/ld.config.txt
from the device.
Document history
Android 11 Changes
- In Android 11, the static
ld.config.*.txt
files are removed from the codebase and LinkerConfig generates them in runtime instead.
Android 9 changes
- In Android 9, the
vndk
linker namespace is added to vendor processes and VNDK shared libraries are isolated from the default linker namespace. - Replace
PRODUCT_FULL_TREBLE
with more specificPRODUCT_TREBLE_LINKER_NAMESPACES
. - Android 9 changes the names of the following dynamic linker configuration
files.
Android 8.x Android 9 Description ld.config.txt.in
ld.config.txt
For devices with runtime linker namespace isolation ld.config.txt
ld.config.vndk_lite.txt
For devices with VNDK-SP linker namespace isolation ld.config.legacy.txt
ld.config.legacy.txt
For legacy devices running Android 7.x or lower - Remove
android.hardware.graphics.allocator@2.0.so
. product
andodm
partitions are added.