リンカー名前空間

ダイナミック リンカーは、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}

構成ファイルには次のものが含まれます。

  • ダイナミック リンカーが有効セクションを選択するための冒頭の複数のディレクトリ セクションのマッピング プロパティ。
  • 複数のリンカー名前空間の構成セクション:
    • 各セクションには、複数の名前空間(グラフの頂点)と名前空間の間(グラフの弧)の複数の代替リンクがあります。
    • 各名前空間には、独自の分離、検索パス、許可されたパス、公開設定があります。

以下の表で、各プロパティの意味を説明します。

ディレクトリ セクションのマッピング プロパティ

プロパティ 説明

dir.name

[name] セクションが適用されるディレクトリへのパス。

各プロパティは、実行可能ファイルをディレクトリ下でリンカー名前空間の構成セクションにマッピングします。2 つ以上のプロパティの name が同じでも、別々のディレクトリを指す場合があります。

dir.system = /system/bin
dir.system = /system/xbin
dir.vendor = /vendor/bin

これは、[system] セクションで指定される構成が、/system/bin/system/xbin のいずれかから読み込まれる実行可能ファイルに適用されることを意味します。

[vendor] セクション内で指定された構成は、/vendor/bin から読み込まれる実行可能ファイルに適用されます。

関係プロパティ

プロパティ 説明
additional.namespaces

セクションの default 名前空間、および追加の名前空間をカンマで区切ったリスト。

additional.namespaces = sphal,vndk

これは、[system] 構成に 3 つの名前空間(defaultsphalvndk)があることを示します。

namespace.name.links

代替名前空間をカンマで区切ったリスト。

現在の名前空間で共有ライブラリが検出できない場合、ダイナミック リンカーは共有ライブラリを代替名前空間から読み込もうとします。リストの先頭に指定された名前空間が優先されます。

namespace.sphal.links = default,vndk

共有ライブラリまたは実行可能ファイルが sphal 名前空間に読み込めない共有ライブラリを要求した場合、ダイナミック リンカーは default 名前空間から共有ライブラリを読み込もうとします。

その後、共有ライブラリを default 名前空間からも読み込めない場合、ダイナミック リンカーは vndk 名前空間から共有ライブラリを読み込もうとします。

最後に、すべての試行が失敗した場合、ダイナミック リンカーはエラーを返します。

namespace.name.link.other.shared_libs

共有ライブラリをコロンで区切ったリスト。これらのライブラリは、name 名前空間で検出できない場合でも、other 名前空間では検索できます。

このプロパティを namespace.name.link.other.allow_all_shared_libs とともに使用することはできません。

namespace.sphal.link.default.shared_libs = libc.so:libm.so

これは、代替リンクが、要求されたライブラリ名として libc.so または libm.so のみを受け入れることを示します。ダイナミック リンカーは、要求されたライブラリ名が libc.so でも libm.so でもない場合、sphal から default への名前空間の代替リンクを無視します。

namespace.name.link.other.allow_all_shared_libs

name 名前空間で共有ライブラリが検出できない場合、すべての共有ライブラリを other 名前空間で検索できるかどうかを示すブール値。

このプロパティを namespace.name.link.other.shared_libs とともに使用することはできません。

namespace.vndk.link.sphal.allow_all_shared_libs = true

これは、すべてのライブラリ名が、vndk から sphal への名前空間の代替リンクをウォークスルーできることを示します。

名前空間のプロパティ

プロパティ 説明
namespace.name.isolated

共有ライブラリが存在する場所をダイナミック リンカーが確認するべきかどうかを示すブール値。

isolatedtrue の場合、search.paths ディレクトリのいずれか(サブディレクトリを除く)、または permitted.paths ディレクトリのいずれか(サブディレクトリを含む)にある共有ライブラリのみを読み込むことができます。

isolatedfalse(デフォルト)の場合、ダイナミック リンカーは共有ライブラリのパスをチェックしません。

namespace.sphal.isolated = true

これは、search.paths 内または permitted.paths の下の共有ライブラリのみを sphal 名前空間に読み込めることを示します。

namespace.name.search.paths

共有ライブラリを検索するためのディレクトリをコロンで区切ったリスト。

search.paths 内で指定されたディレクトリは、関数が dlopen() を呼び出すか、または DT_NEEDED エントリにフルパスが指定されていない場合、要求されたライブラリ名の先頭に追加されます。リストの先頭に指定したディレクトリが優先されます。

isolatedtrue の場合、search.paths ディレクトリのいずれかにある共有ライブラリ(サブディレクトリを除く)は、permitted.paths プロパティに関係なく読み込むことができます。

たとえば、search.paths/system/${LIB} で、permitted.paths が空の場合、/system/${LIB}/libc.so は読み込めますが、/system/${LIB}/vndk/libutils.so は読み込めません。

namespace.default.search.paths = /system/${LIB}

これは、ダイナミック リンカーが共有ライブラリを /system/${LIB} で検索することを示します。

namespace.name.asan.search.paths

Address Sanitizer が有効なときに共有ライブラリを検索するためのディレクトリをコロンで区切ったリスト。

Address Sanitizer が有効な場合、namespace.name.search.paths は無視されます。

namespace.default.asan.search.paths = /data/asan/system/${LIB}:/system/${LIB}

これは、Address Sanitizer が有効な場合、ダイナミック リンカーは最初に /data/asan/system/${LIB} を検索してから /system/${LIB} を検索することを示します。

namespace.name.permitted.paths

isolatedtrue の場合に、ダイナミック リンカーが(search.paths に加えて)共有ライブラリを読み込めるディレクトリ(サブディレクトリを含む)をコロンで区切ったリスト。

permitted.paths のサブディレクトリの下にある共有ライブラリも読み込めます。たとえば、permitted.paths/system/${LIB}の場合、/system/${LIB}/libc.so/system/${LIB}/vndk/libutils.so のどちらも読み込めます。

isolatedfalse の場合、permitted.paths は無視され、警告が出ます。

namespace.default.permitted.paths = /system/${LIB}/hw

これは、/system/${LIB}/hw の下の共有ライブラリを分離された default 名前空間に読み込めることを示します。

たとえば、permitted.paths なしでは、libaudiohal.so/system/${LIB}/hw/audio.a2dp.default.sodefault 名前空間に読み込めません。

namespace.name.asan.permitted.paths

Address Sanitizer が有効な場合にダイナミック リンカーが共有ライブラリを読み込むことができる、ディレクトリをコロンで区切ったリスト。

Address Sanitizer が有効な場合、namespace.name.permitted.paths は無視されます。

namespace.default.asan.permitted.paths = /data/asan/system/${LIB}/hw:/system/${LIB}/hw

これは、Address Sanitizer が有効な場合、/data/asan/system/${LIB}/hw または /system/${LIB}/hw の下にある共有ライブラリを、分離された default 名前空間に読み込めることを示します。

namespace.name.visible

プログラム(libc 以外)が、android_get_exported_namespace() でリンカー名前空間ハンドルを取得し、ハンドルを android_dlopen_ext() に渡してリンカー名前空間内の共有ライブラリを開けるかどうかを示すブール値。

visibletrue の場合、android_get_exported_namespace() は、名前空間が存在するときに常にハンドルを返します。

visiblefalse の場合(デフォルト)、android_get_exported_namespace() は名前空間の存在に関係なく、常に NULL を返します。共有ライブラリは、この名前空間への代替リンクがある別のリンカー名前空間から要求されているか、この名前空間の他の共有ライブラリまたは実行可能ファイルから要求されている場合、この名前空間にしか読み込めません。

namespace.sphal.visible = true

これは、android_get_exported_namespace("sphal") が有効なリンカー名前空間ハンドルを返すことができることを示します。

リンカー名前空間の分離

${android-src}/system/core/rootdir/etc には、次の 3 つの構成ファイルがあります。BoardConfig.mk 内の PRODUCT_TREBLE_LINKER_NAMESPACESBOARD_VNDK_VERSIONBOARD_VNDK_RUNTIME_DISABLE の値に応じて、異なる構成が選択されます。

PRODUCT_TREBLE_
LINKER_NAMESPACES
BOARD_VNDK_
VERSION
BOARD_VNDK_
RUNTIME_DISABLE
選択した構成 VTS の要件
true current ld.config.txt Android P で起動したデバイスでは必須です。
true ld.config.vndk_lite.txt Android 8.x で起動したデバイスでは必須です。
任意
false 任意 任意 ld.config.legacy.txt Treble デバイス以外の場合

${android-src}/system/core/rootdir/etc/ld.config.vndk_lite.txt は、SP-HAL 共有ライブラリと VNDK-SP 共有ライブラリを分離します。Android 8.0 以降では、PRODUCT_TREBLE_LINKER_NAMESPACEStrue の場合、これがダイナミック リンカーの構成ファイルである必要があります。

${android-src}/system/core/rootdir/etc/ld.config.txt も、SP-HAL 共有ライブラリと VNDK-SP 共有ライブラリを分離します。さらに、ld.config.txt は、ダイナミック リンカーの完全分離も可能とします。これにより、システム パーティション内のモジュールと、ベンダー パーティション内の共有ライブラリが相互に依存しないようになります。

Android 8.1 では、ld.config.txt はデフォルトの構成ファイルであり、BOARD_VNDK_VERSIONcurrent に設定することによってダイナミック リンカーの完全分離を有効にすることを強くおすすめします。ただし、Android 8.1 でクリーンアップする必要がある依存関係が多すぎる場合は、すべての依存関係がクリーンアップされるまでは BOARD_VNDK_RUNTIME_DISABLEBoardConfig.mk に追加できます。

BOARD_VNDK_RUNTIME_DISABLE := true

BOARD_VNDK_RUNTIME_DISABLE は、依存関係をクリーンアップするために一時的に使用するオプションです。依存関係をクリーンアップしない場合は、BOARD_VNDK_VERSION の設定を解除して ld.config.vndk_lite.txt を使用します。

BOARD_VNDK_RUNTIME_DISABLEtrue の場合、${android-src}/system/core/rootdir/etc/ld.config.vndk_lite.txt がインストールされます。これはテスト専用です。

ld.config.txt

ld.config.txt は、システム パーティションとベンダー パーティション間の共有ライブラリの依存関係を分離します。前のサブセクションで言及した ld.config.txt との大まかな違いは次のとおりです。

  • フレームワーク プロセス

    • 4 つの名前空間(defaultvndksphalrs)が作成されます。
    • すべての名前空間は分離されます。
    • システムの共有ライブラリは、default 名前空間に読み込まれます。
    • SP-HAL は、sphal 名前空間に読み込まれます。
    • VNDK-SP 共有ライブラリは、vndk 名前空間に読み込まれます。
  • ベンダー プロセス

    • 3 つの名前空間(defaultvndksystem)が作成されます。
    • default 名前空間は分離されます。
    • ベンダーの共有ライブラリは、default 名前空間に読み込まれます。
    • VNDK および VNDK-SP 共有ライブラリは、vndk 名前空間に読み込まれます。
    • LL-NDK とその依存関係は、system 名前空間に読み込まれます。

リンカー名前空間間の関係を以下の図に示します。

ld.config.txt に記述されているリンカー名前空間のグラフ
図 1. リンカー名前空間の分離(ld.config.txt

上の図の 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

以下の表は、ld.config.txt 内の [system] セクションから抜粋されたフレームワーク プロセスの名前空間の構成を示しています。

名前空間 プロパティ
default search.paths /system/${LIB}
/product/${LIB}
permitted.paths /system/${LIB}/drm
/system/${LIB}/extractors
/system/${LIB}/hw
/product/${LIB}
/system/framework
/system/app
/system/priv-app
/vendor/app
/vendor/priv-app
/odm/app
/odm/priv-app
/oem/app
/product/framework
/product/app
/product/priv-app
/data
/mnt/expand
isolated true
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 defaultsphal
link.default.shared_libs LL-NDK
link.default.allow_all_shared_libs true
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-NDK
libmediandk.so
libft2.so
link.vndk.shared_libs VNDK-SP

以下の表は、ld.config.txt 内の [vendor] セクションから抜粋されたベンダー プロセスの名前空間の構成を示しています。

名前空間 プロパティ
default search.paths /odm/${LIB}
/vendor/${LIB}
permitted.paths /odm
/vendor
isolated true
visible true
links systemvndk
link.system.shared_libs LL-NDK
link.vndk.shared_libs VNDKVNDK-SP(ベンダー対応)
vndk search.paths /odm/${LIB}/vndk
/odm/${LIB}/vndk-sp
/vendor/${LIB}/vndk
/vendor/${LIB}/vndk-sp
/system/${LIB}/vndk-${VER}
/system/${LIB}/vndk-sp-${VER}
isolated true
links systemdefault
link.system.shared_libs LL-NDK
link.default.allow_all_shared_libs true
system search.paths /system/${LIB}
isolated false

詳しくは、${android-src}/system/core/rootdir/etc/ld.config.txt をご覧ください。

ld.config.vndk_lite.txt

Android 8.0 以降、ダイナミック リンカーは、シンボルが他のフレームワーク共有ライブラリと競合しないように、SP-HAL 共有ライブラリと VNDK-SP 共有ライブラリを分離するよう構成されています。リンカー名前空間間の関係を以下に示します。

ld.config.vndk_lite.txt に記述されているリンカー名前空間のグラフ
図 2. リンカー名前空間の分離(ld.config.vndk_lite.txt

LL-NDK と VNDK-SP は、次の共有ライブラリを意味します。

  • LL-NDK
    • libEGL.so
    • libGLESv1_CM.so
    • libGLESv2.so
    • libc.so
    • libdl.so
    • liblog.so
    • libm.so
    • libnativewindow.so
    • libstdc++.sold.config.txt に含まれない)
    • libsync.so
    • libvndksupport.so
    • libz.sold.config.txt の 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

以下の表は、ld.config.vndk_lite.txt 内の [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-NDK
libmediandk.so
libft2.so
link.vndk.shared_libs VNDK-SP

以下の表は、ld.config.vndk_lite.txt 内の [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

詳しくは、${android-src}/system/core/rootdir/etc/ld.config.vndk_lite.txt をご覧ください。

ドキュメントの履歴

Android P の変更点

  • Android P では、vndk リンカー名前空間がベンダー プロセスに追加され、VNDK 共有ライブラリはデフォルトのリンカー名前空間から分離されています。

  • PRODUCT_FULL_TREBLE を、より具体的な PRODUCT_TREBLE_LINKER_NAMESPACES に置き換えています。

  • Android P では、次のダイナミック リンカー構成ファイルの名前が変更されています。

    Android 8.x Android P 説明
    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 パーティションが追加されています。