ダイナミック リンカーは、Treble VNDK の設計上の 2 つの課題に対応します。
- SP-HAL 共有ライブラリとその依存関係(VNDK-SP ライブラリを含む)は、フレームワーク プロセスに読み込まれます。そこで、シンボルの競合を防ぐなんらかのメカニズムが必要になります。
dlopen()
とandroid_dlopen_ext()
により、ビルド時に隠れたランタイム依存関係が発生し、静的解析では検出が困難になる場合があります。
これらの 2 つの課題はリンカー名前空間のメカニズムで解決できます。このメカニズムはダイナミック リンカーによってもたらされ、別のリンカー名前空間にある共有ライブラリが分離されるため、シンボルが異なる同名のライブラリが競合しなくなります。
さらに、リンカー名前空間のメカニズムの持つ柔軟性により、あるリンカー名前空間が共有ライブラリをエクスポートし、別のリンカー名前空間がそれを使用するといったことも実現できます。このようにエクスポートされた共有ライブラリは、リンカー名前空間内に実装の詳細を隠しながら、他のプログラムに公開されるアプリケーション プログラミング インターフェースになります。
たとえば、/system/lib[64]/libcutils.so
と /system/lib[64]/vndk-sp-${VER}/libcutils.so
は、2 つの共有ライブラリです。これらの 2 つのライブラリは、異なるシンボルを持つことができます。それぞれのライブラリは異なるリンカー名前空間に読み込まれるため、フレームワーク モジュールは /system/lib[64]/libcutils.so
に、SP-HAL 共有ライブラリは /system/lib[64]/vndk-sp-${VER}/libcutils.so
に依存できます。
一方、/system/lib[64]/libc.so
は、リンカー名前空間によってエクスポートされ、多くのリンカー名前空間にインポートされる公開ライブラリの一例です。/system/lib[64]/libc.so
の依存関係(例: libnetd_client.so
)は、/system/lib[64]/libc.so
が存在する名前空間に読み込まれます。他の名前空間が、それらの依存関係へのアクセス権を持つことはありません。このメカニズムは、実装の詳細をカプセル化し、公開インターフェースを提供します。
仕組み
ダイナミック リンカーは、DT_NEEDED
エントリで指定された共有ライブラリまたは dlopen()
や android_dlopen_ext()
の引数で指定された共有ライブラリの読み込みを行います。どちらの場合も、ダイナミック リンカーは、呼び出し元が存在するリンカー名前空間を見つけ、同じリンカー名前空間に依存関係を読み込もうとします。指定されたリンカー名前空間に共有ライブラリを読み込めない場合、ダイナミック リンカーはエクスポートされた共有ライブラリをリンクされたリンカー名前空間に求めます。
構成ファイルの形式
構成ファイルの形式は、INI ファイル形式に基づいています。標準の構成ファイルは次のようになります。
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}
構成ファイルには次のものが含まれます。
- 冒頭に複数ある、ディレクトリとセクション間のマッピング プロパティ。これはダイナミック リンカーが有効セクションを選択するためのものです。
-
複数のリンカー名前空間の構成セクション:
- 各セクションには、複数の名前空間(グラフの頂点)と名前空間の間(グラフの弧)の複数の代替リンクがあります。
- 各名前空間には、独自の分離、検索パス、許可されたパス、公開設定があります。
以下の表で、各プロパティの意味を説明します。
ディレクトリとセクション間のマッピング プロパティ
プロパティ | 説明 | 例 |
---|---|---|
|
各プロパティは、該当ディレクトリ下の実行可能ファイルをリンカー名前空間の構成セクションにマッピングします。 |
これは、
|
関係プロパティ
プロパティ | 説明 | 例 |
---|---|---|
additional. |
セクションの( |
これは、 |
namespace. |
代替名前空間をカンマで区切ったリスト。 現在の名前空間で共有ライブラリが検出できない場合、ダイナミック リンカーは共有ライブラリを代替名前空間から読み込もうとします。リストの先頭に指定された名前空間が優先されます。 |
共有ライブラリまたは実行可能ファイルが その後、共有ライブラリを 最後に、すべての試行が失敗した場合、ダイナミック リンカーはエラーを返します。 |
namespace. |
共有ライブラリをコロンで区切ったリスト。ここで指定したライブラリが このプロパティを |
これは、代替リンクが、要求されたライブラリ名として |
namespace. |
このプロパティを |
これは、すべてのライブラリ名が、 |
名前空間のプロパティ
プロパティ | 説明 | 例 |
---|---|---|
namespace. |
共有ライブラリが存在する場所をダイナミック リンカーが確認するべきかどうかを示すブール値。
|
これは、 |
namespace. |
共有ライブラリを検索するためのディレクトリをコロンで区切ったリスト。
たとえば、 |
これは、ダイナミック リンカーが共有ライブラリを |
namespace. |
AddressSanitizer(ASan)が有効な場合に共有ライブラリを検索するディレクトリをコロンで区切ったリスト。 ASan が有効な場合、 |
これは、ASan が有効な場合、ダイナミック リンカーが最初に |
namespace. |
|
これは、 たとえば、 |
namespace. |
ASan が有効な場合にダイナミック リンカーが共有ライブラリを読み込むことができるディレクトリをコロンで区切ったリスト。 ASan が有効な場合、 |
これは、ASan が有効な場合、 |
namespace. |
プログラム(
|
これは、 |
リンカー名前空間の作成
Android 11 では、リンカー構成は ${android-src}/system/core/rootdir/etc
で書式なしテキスト ファイルを使用して作成されるのではなく、実行時に /linkerconfig
で作成されます。この構成は、以下の項目を含むランタイム環境に基づいて起動時に生成されます。
- デバイスが VNDK をサポートしているかどうか
- ベンダー パーティションの対象 VNDK のバージョン
- プロダクト パーティションの VNDK のバージョン
- インストール済みの APEX モジュール
リンカー構成は、リンカー名前空間間の依存関係を解決することで作成されます。たとえば、依存関係のアップデートを含む APEX モジュールにアップデートがある場合、これらの変更を反映したリンカー構成が生成されます。リンカー構成を作成する方法について詳しくは、${android-src}/system/linkerconfig
をご覧ください。
リンカー名前空間の分離
構成には次の 3 種類があります。BoardConfig.mk
内の PRODUCT_TREBLE_LINKER_NAMESPACES
と BOARD_VNDK_VERSION
の値に応じて、起動時に対応する構成が生成されます。
PRODUCT_TREBLE_ LINKER_NAMESPACES |
BOARD_VNDK_ VERSION |
選択した構成 | VTS の要件 |
---|---|---|---|
true |
current |
VNDK |
Android 9 以降を搭載したデバイスでは必須 |
なし | VNDK Lite |
Android 8.x で起動するデバイスでは必須 | |
false |
なし | Legacy |
Treble デバイス以外の場合 |
VNDK Lite 構成は、SP-HAL 共有ライブラリと VNDK-SP 共有ライブラリを分離します。Android 8.0 では、PRODUCT_TREBLE_LINKER_NAMESPACES
が true
の場合、これがダイナミック リンカーの構成ファイルである必要があります。
VNDK 構成も、SP-HAL 共有ライブラリと VNDK-SP 共有ライブラリを分離します。さらに、この構成は、ダイナミック リンカーの完全分離も実現します。これにより、システム パーティション内のモジュールと、ベンダー パーティション内の共有ライブラリが相互に依存しないようになります。
Android 8.1 以降では、VNDK の構成はデフォルトの構成であり、BOARD_VNDK_VERSION
を current
に設定することによってダイナミック リンカーの完全分離を有効にすることを強くおすすめします。
VNDK の構成
VNDK の構成は、システム パーティションとベンダー パーティション間の共有ライブラリの依存関係を分離します。前のサブセクションで説明した構成との大まかな違いは次のとおりです。
-
フレームワーク プロセス
default
、vndk
、sphal
、rs
の名前空間が作成されます。- すべての名前空間は分離されます。
- システムの共有ライブラリは、
default
名前空間に読み込まれます。 - SP-HAL は、
sphal
名前空間に読み込まれます。 - VNDK-SP 共有ライブラリは、
vndk
名前空間に読み込まれます。
-
ベンダー プロセス
default
、vndk
、system
の名前空間が作成されます。default
名前空間は分離されます。- ベンダーの共有ライブラリは、
default
名前空間に読み込まれます。 - VNDK および VNDK-SP 共有ライブラリは、
vndk
名前空間に読み込まれます。 - LL-NDK とその依存関係は、
system
名前空間に読み込まれます。
リンカー名前空間の関係を以下に示します。
![VNDK 構成に記述されているリンカー名前空間のグラフ](https://source.android.com/static/docs/core/architecture/images/treble_vndk_linker_namespace3.png?authuser=0&hl=ja)
図 1. リンカー名前空間の分離(VNDK の構成)。
上記の画像の LL-NDK と VNDK-SP は、次の共有ライブラリを意味します。
-
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
詳しくは、デバイスの /linkerconfig/ld.config.txt
をご覧ください。
VNDK Lite の構成
Android 8.0 以降、ダイナミック リンカーは、シンボルが他のフレームワーク共有ライブラリと競合しないように、SP-HAL 共有ライブラリと VNDK-SP 共有ライブラリを分離するよう構成されています。リンカー名前空間の関係を以下に示します。
![VNDK Lite 構成に記述されているリンカー名前空間のグラフ](https://source.android.com/static/docs/core/architecture/images/treble_vndk_linker_namespace1.png?authuser=0&hl=ja)
LL-NDK と VNDK-SP は、次の共有ライブラリを意味します。
-
LL-NDK
libEGL.so
libGLESv1_CM.so
libGLESv2.so
libc.so
libdl.so
liblog.so
libm.so
libnativewindow.so
libstdc++.so
(構成内にない)libsync.so
libvndksupport.so
libz.so
(構成内の VNDK-SP に移動)
-
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
以下の表は、VNDK Lite 構成内の [system]
セクションから抜粋したフレームワーク プロセスの名前空間の構成を示しています。
名前空間 | プロパティ | 値 |
---|---|---|
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 (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 (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 (コンパイルされた RS カーネルの場合)
|
|
isolated |
true |
|
visible |
true |
|
links |
default,vndk |
|
link.default.shared_libs |
LL-NDKlibmediandk.so libft2.so
|
|
link.vndk.shared_libs |
VNDK-SP |
以下の表は、VNDK Lite 構成内の [vendor]
セクションから抜粋したベンダー プロセスの名前空間の構成を示しています。
名前空間 | プロパティ | 値 |
---|---|---|
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} (サポート終了)/product/${LIB} (サポート終了)
|
isolated |
false |
詳しくは、デバイスの /linkerconfig/ld.config.txt
をご覧ください。
ドキュメントの履歴
Android 11 の変更点
- Android 11 では、コードベースから静的
ld.config.*.txt
ファイルが削除され、代わりに LinkerConfig によって実行時に生成されます。
Android 9 の変更点
- Android 9 では、
vndk
リンカー名前空間がベンダー プロセスに追加され、VNDK 共有ライブラリはデフォルトのリンカー名前空間から分離されています。 PRODUCT_FULL_TREBLE
を、より具体的なPRODUCT_TREBLE_LINKER_NAMESPACES
に置き換えています。- Android 9 では、次のダイナミック リンカー構成ファイルの名前が変更されています。
Android 8.x Android 9 説明 ld.config.txt.in
ld.config.txt
ランタイムのリンカー名前空間の分離があるデバイスの場合 ld.config.txt
ld.config.vndk_lite.txt
VNDK-SP のリンカー名前空間の分離があるデバイスの場合 ld.config.legacy.txt
ld.config.legacy.txt
Android 7.x 以前を搭載した従来のデバイスの場合 android.hardware.graphics.allocator@2.0.so
を削除しています。product
パーティションとodm
パーティションが追加されています。