Przestrzeń nazw tagu łączącego

Linker dynamiczny rozwiązuje 2 problemy w projektowaniu Treble VNDK:

  • Biblioteki wspólne SP-HAL i ich zależności, w tym biblioteki VNDK-SP, są ładowane do procesów frameworka. Powinny istnieć mechanizmy zapobiegające konfliktom symboli.
  • dlopen()android_dlopen_ext() mogą wprowadzać zależności w czasie wykonywania, które nie są widoczne w czasie kompilacji i mogą być trudne do wykrycia za pomocą analizy statycznej.

Te 2 problemy można rozwiązać za pomocą mechanizmu przestrzeni nazw linkera. Ten mechanizm jest udostępniany przez dynamicznego linkera. Umożliwia to odizolowanie wspólnych bibliotek w różnych przestrzeniach nazw linkera, dzięki czemu biblioteki o tej samej nazwie, ale z różnymi symbolami, nie będą ze sobą kolidować.

Z drugiej strony mechanizm przestrzeni nazw linkera zapewnia elastyczność, dzięki której niektóre wspólne biblioteki mogą być eksportowane przez przestrzeń nazw linkera i używane przez inną przestrzeń nazw linkera. Te wyeksportowane biblioteki współdzielone mogą stać się interfejsami programowania aplikacji, które są publiczne dla innych programów, a szczegóły ich implementacji są ukryte w przestrzeni nazw linkera.

Na przykład /system/lib[64]/libcutils.so/system/lib[64]/vndk-sp-${VER}/libcutils.so to 2 udostępnione biblioteki. Te 2 biblioteki mogą mieć różne symbole. Są one ładowane do różnych przestrzeni nazw linkera, aby moduły frameworka mogły zależeć od /system/lib[64]/libcutils.so, a biblioteki udostępnione SP-HAL mogły zależeć od /system/lib[64]/vndk-sp-${VER}/libcutils.so.

Z drugiej strony /system/lib[64]/libc.so to przykład biblioteki publicznej, która jest eksportowana przez przestrzeń nazw linkera i importowana do wielu przestrzeni nazw linkera. Zależne od /system/lib[64]/libc.so elementy, takie jak libnetd_client.so, są ładowane do przestrzeni nazw, w której znajduje się /system/lib[64]/libc.so. Inne przestrzenie nazw nie będą miały dostępu do tych zależności. Mechanizm ten opisuje szczegóły implementacji, zapewniając jednocześnie interfejsy publiczne.

Jak to działa

Linker dynamiczny odpowiada za wczytywanie bibliotek udostępnionych określonych w elementach DT_NEEDED lub bibliotek udostępnionych określonych przez argument dlopen() lub android_dlopen_ext(). W obu przypadkach linker dynamiczny znajduje przestrzeń nazw linkera, w której znajduje się wywołujący, i próbuje załadować zależności do tej samej przestrzeni nazw linkera. Jeśli dynamiczny linker nie może załadować biblioteki współdzielonej w wyznaczonej przestrzeni nazw linkera, prosi połączoną przestrzeń nazw linkera o wyeksportowane biblioteki współdzielone.

Format pliku konfiguracji

Format pliku konfiguracyjnego jest oparty na formacie pliku INI. Typowy plik konfiguracji wygląda tak:

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}

Plik konfiguracji zawiera:

  • Na początku kilka właściwości mapowania sekcji katalogu, aby linker dynamiczny mógł wybrać skuteczną sekcję.
  • Kilka sekcji konfiguracji przestrzeni nazw linkera:
    • Każda sekcja zawiera kilka przestrzeni nazw (wierzchołków grafu) i kilka alternatywnych połączeń między przestrzeniami nazw (łuki grafu).
    • Każda nazwa przestrzeni ma własne ustawienia izolacji, ścieżek wyszukiwania, ścieżek dozwolonych i widoczności.

W tabelach poniżej znajdziesz szczegółowe omówienie każdej właściwości.

Właściwość mapowania sekcji katalogu

Właściwość Opis Przykład

dir.name

Ścieżka do katalogu, do którego ma zastosowanie sekcja [name].

Każda usługa mapuje pliki wykonywalne w danym katalogu do sekcji konfiguracji przestrzeni nazw linkera. Może być 2 lub więcej usług, które mają ten sam identyfikator name, ale odwołują się do różnych katalogów.

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

Oznacza to, że konfiguracja określona w sekcji [system] dotyczy plików wykonywalnych załadowanych z /system/bin lub /system/xbin.

Konfiguracja określona w sekcji [vendor] ma zastosowanie do plików wykonywalnych, które są ładowane z /vendor/bin.

Właściwości relacji

Właściwość Opis Przykład
additional.namespaces

Lista dodatkowych przestrzeni nazw (oprócz przestrzeni nazwdefault) rozdzielona przecinkami.

additional.namespaces = sphal,vndk

Oznacza to, że w konfiguracji [system] występują 3 przestrzenie nazw (default, sphalvndk).

namespace.name.links

Rozdzielana przecinkami lista przestrzeni nazw zapasowych.

Jeśli w bieżącej przestrzeni nazw nie można znaleźć biblioteki udostępnionej, dynamiczny linker próbuje załadować ją z przełączalnych przestrzeni nazw. Przestrzeń nazw określona na początku listy ma wyższy priorytet.

namespace.sphal.links = default,vndk

Jeśli biblioteka współdzielona lub plik wykonywalny żąda biblioteki współdzielonej, której nie można załadować do przestrzeni nazw sphal, linker dynamiczny próbuje załadować tę bibliotekę ze przestrzeni nazw default.

Jeśli biblioteki współdzielonej nie można załadować z przestrzeni nazw default, linker dynamiczny próbuje ją załadować z przestrzeni nazw vndk.

Jeśli wszystkie próby zawiodą, linker dynamiczny zwraca błąd.

namespace.name.link.other.shared_libs

Lista oddzielonych dwukropami nazw udostępnionych bibliotek, w których można przeszukiwać w przestrzeni nazw other, gdy nie można ich znaleźć w przestrzeni nazw name.

Tej właściwości nie można używać w połączeniu z wartością namespace.name.link.other.allow_all_shared_libs.

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

Oznacza to, że link zapasowy akceptuje jako nazwę biblioteki tylko libc.so lub libm.so. Link dynamiczny ignoruje alternatywne połączenie z przestrzeni nazw sphal z poziomu default, jeśli nazwa żądanej biblioteki nie jest libc.so ani libm.so.

namespace.name.link.other.allow_all_shared_libs

Wartość logiczna wskazująca, czy można wyszukiwać wszystkie wspólne biblioteki w przestrzeni nazw other, gdy nie można ich znaleźć w przestrzeni nazw name.

Nie można używać tej właściwości w połączeniu z usługą namespace.name.link.other.shared_libs.

namespace.vndk.link.sphal.allow_all_shared_libs = true

Oznacza to, że wszystkie nazwy bibliotek mogą przechodzić przez link zapasowy z przestrzeni nazw vndk do sphal.

Właściwości przestrzeni nazw

Właściwość Opis Przykład
namespace.name.isolated

Wartość logiczna wskazująca, czy dynamiczny linker ma sprawdzać, gdzie znajduje się biblioteka wspólna.

Jeśli isolated to true, można wczytać tylko te biblioteki współdzielone, które znajdują się w jednym z katalogów search.paths (z wyjątkiem podkatalogów) lub znajdują się w jednym z katalogów permitted.paths (w tym podkatalogach).

Jeśli isolated to false (wartość domyślna), linker dynamiczny nie sprawdza ścieżki bibliotek współdzielonych.

namespace.sphal.isolated = true

Oznacza to, że do przestrzeni nazw sphal można wczytywać tylko biblioteki udostępnione w search.paths lub permitted.paths.

namespace.name.search.paths

Lista katalogów rozdzielona dwukropkami, w których mają być wyszukiwane biblioteki udostępnione.

Katalogi określone w search.paths są dodawane na początku nazwy żądanej biblioteki, jeśli wywołania funkcji do elementów dlopen() lub DT_NEEDED nie zawierają pełnej ścieżki. Katalog podany na początku listy ma wyższy priorytet.

Gdy isolated jest true, biblioteki współdzielone, które znajdują się w jednym z katalogów search.paths (z wyłączeniem podkatalogów), można wczytywać niezależnie od właściwości permitted.paths.

Jeśli na przykład search.paths to /system/${LIB}, a permitted.paths jest puste, można załadować /system/${LIB}/libc.so, ale nie można załadować /system/${LIB}/vndk/libutils.so.

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

Oznacza to, że dynamiczny linker wyszukuje biblioteki udostępnione w katalogu /system/${LIB}.

namespace.name.asan.search.paths

Oddzielona dwukropkami lista katalogów, w których ma być wyszukiwana biblioteka współdzielona, gdy włączona jest opcja AddressSanitizer (ASan).

namespace.name.search.paths jest ignorowana, gdy włączona jest Asana.

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

Oznacza to, że gdy włączona jest opcja ASan, linker dynamiczny najpierw przeszukuje /data/asan/system/${LIB}, a następnie /system/${LIB}.

namespace.name.permitted.paths

Lista katalogów (w tym podkatalogów) oddzielonych dwukropkiem, w których linker dynamiczny może wczytywać udostępnione biblioteki (oprócz search.paths), gdy isolated to true.

Można też wczytywać biblioteki udostępnione znajdujące się w podkatalogach permitted.paths. Jeśli na przykład permitted.paths = /system/${LIB}, można załadować zarówno /system/${LIB}/libc.so, jak i /system/${LIB}/vndk/libutils.so.

Jeśli isolated = false, wartości permitted.paths są ignorowane, a wyświetlane jest ostrzeżenie.

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

Oznacza to, że biblioteki udostępnione w przestrzeni nazw /system/${LIB}/hw można wczytać w odizolowanej przestrzeni nazw default.

Na przykład bez permitted.paths usługa libaudiohal.so nie może wczytać /system/${LIB}/hw/audio.a2dp.default.so do przestrzeni nazw default.

namespace.name.asan.permitted.paths

Lista katalogów oddzielonych dwukropkiem, z których dynamiczny linker może wczytywać współdzielone biblioteki, gdy włączona jest opcja ASan.

namespace.name.permitted.paths jest ignorowana, gdy włączona jest Asana.

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

Oznacza to, że gdy włączona jest usługa ASan, biblioteki współdzielone w poziomie /data/asan/system/${LIB}/hw lub /system/${LIB}/hw można wczytać do odizolowanej przestrzeni nazw default.

namespace.name.visible

Wartość logiczna wskazująca, czy program (inny niż libc) może uzyskać uchwyt nazwy przestrzeni nazw linkera za pomocą funkcji android_get_exported_namespace() i otworzyć współdzieloną bibliotekę w przestrzeni nazw linkera, przekazując uchwyt do funkcji android_dlopen_ext().

Jeśli visible to true, instrukcja android_get_exported_namespace() zawsze zwraca identyfikator, jeśli istnieje taka nazwa przestrzeni.

Jeśli visible to false (domyślnie), android_get_exported_namespace() zawsze zwraca NULL niezależnie od obecności przestrzeni nazw. Udostępnione biblioteki mogą być ładowane w tej przestrzeni nazw tylko wtedy, gdy: (1) są wymagane przez inną przestrzeń nazw linkera, która ma link zapasowy do tej przestrzeni nazw, lub (2) są wymagane przez inne udostępnione biblioteki lub pliki wykonywalne w tej przestrzeni nazw.

namespace.sphal.visible = true

Oznacza to, że android_get_exported_namespace("sphal")może zwrócić prawidłowy identyfikator przestrzeni nazw linkera.

Tworzenie przestrzeni nazw linkera

W Androidzie 11 konfiguracja linkera jest tworzona w czasie wykonywania w katalogu /linkerconfig, a nie w plikach tekstowych w katalogu /linkerconfig.${android-src}/system/core/rootdir/etc Konfiguracja jest generowana podczas uruchamiania na podstawie środowiska uruchomieniowego, które obejmuje te elementy:

  • Jeśli urządzenie obsługuje VNDK
  • Docelowa wersja VNDK partycji dostawcy
  • Wersja VNDK w podziale produktu
  • Zainstalowane moduły APEX

Konfiguracja linkera jest tworzona przez rozwiązywanie zależności między przestrzeniami nazw linkera. Jeśli na przykład w modułach APEX pojawią się aktualizacje, które obejmują aktualizacje zależności, konfiguracja linkera zostanie wygenerowana z uwzględnieniem tych zmian. Więcej informacji o tworzeniu konfiguracji linkera znajdziesz w ${android-src}/system/linkerconfig.

Izolacja przestrzeni nazw linkera

Istnieją 3 typy konfiguracji. W zależności od wartości PRODUCT_TREBLE_LINKER_NAMESPACES i BOARD_VNDK_VERSION w BoardConfig.mk odpowiednia konfiguracja jest generowana podczas uruchamiania.

PRODUCT_TREBLE_
LINKER_NAMESPACES
BOARD_VNDK_
VERSION
Wybrana konfiguracja Wymagania dotyczące VTS
true current VNDK Wymagane na urządzeniach z Androidem 9 lub nowszym
Puste VNDK Lite Wymagane w przypadku urządzeń z Androidem 8.x
false Puste Legacy Urządzenia inne niż Treble

Konfiguracja VNDK Lite izoluje biblioteki wspólne SP-HAL i VNDK-SP. W Androidzie 8.0 musi to być plik konfiguracji dla linkera dynamicznego, gdy PRODUCT_TREBLE_LINKER_NAMESPACES to true.

Konfiguracja VNDK izoluje też biblioteki współdzielone SP-HAL i VNDK-SP. Dodatkowo ta konfiguracja zapewnia pełną izolację dynamicznego linkera. Dzięki temu moduły w partycji systemowej nie będą zależeć od udostępnionych bibliotek w partycjach dostawców i odwrotnie.

W Androidzie 8.1 lub nowszym konfiguracja VNDK jest konfiguracją domyślną. Zalecamy, aby włączyć pełną izolację linkera dynamicznego, ustawiając wartość BOARD_VNDK_VERSION na current.

Konfiguracja VNDK

Konfiguracja VNDK izoluje zależności biblioteki udostępnionej między partycją systemową a partycjami dostawcy. W porównaniu z konfiguracjami wymienionymi w poprzedniej podsekcji różnice przedstawiają się następująco:

  • Procesy dotyczące ram

    • Tworzone są przestrzenie nazw default, vndk, sphal i rs.
    • Wszystkie przestrzenie nazw są odizolowane.
    • Systemowe biblioteki udostępnione są ładowane do przestrzeni nazw default.
    • Pliki SP-HAL są ładowane do przestrzeni nazw sphal.
    • biblioteki udostępnione VNDK-SP wczytane do przestrzeni nazw vndk.
  • Procesy dostawcy

    • Tworzone są przestrzenie nazw default, vndk i system.
    • Przestrzeń nazw default jest odizolowana.
    • Biblioteki udostępnione dostawców są ładowane do przestrzeni nazw default.
    • Biblioteki udostępnione VNDK i VNDK-SP są ładowane do przestrzeni nazw vndk.
    • LL-NDK i jego zależności są ładowane do przestrzeni nazw system.

Powiązania między przestrzeniami nazw linkera zostały zilustrowane poniżej.

Graf Linker namespace opisany w konfiguracji VNDK

Rysunek 1. Izolacja przestrzeni nazw linkera (konfiguracja VNDK).

Na powyższym obrazie LL-NDKVNDK-SP oznaczają te biblioteki współdzielone:

  • 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

Więcej informacji znajdziesz w /linkerconfig/ld.config.txt na urządzeniu.

Konfiguracja VNDK Lite

Od Androida 8.0 linker dynamiczny jest skonfigurowany tak, aby izolować biblioteki wspólne SP-HAL i VNDK-SP, aby ich symbole nie wchodziły w kolizję z innymi bibliotekami wspólnymi frameworka. Powiązanie między przestrzeniami nazw linkera pokazano poniżej.

Graf Linker namespace opisany w konfiguracji VNDK Lite
Rysunek 2. Izolacja przestrzeni nazw linkera (konfiguracja VNDK Lite)

LL-NDK i VNDK-SP to nazwy następujących bibliotek udostępnionych:

  • LL-NDK
    • libEGL.so
    • libGLESv1_CM.so
    • libGLESv2.so
    • libc.so
    • libdl.so
    • liblog.so
    • libm.so
    • libnativewindow.so
    • libstdc++.so (nie ma w konfiguracji)
    • libsync.so
    • libvndksupport.so
    • libz.so (przeniesione do VNDK-SP w ramach konfiguracji)
  • 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

Tabela poniżej zawiera konfigurację przestrzeni nazw dla procesów frameworku, która jest fragmentem sekcji [system] w konfiguracji VNDK Lite.

Namespace Właściwość Wartość
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 (w przypadku 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 (dla 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 (dla skompilowanego jądra PS)
isolated true
visible true
links default,vndk
link.default.shared_libs LL-NDK
libmediandk.so
libft2.so
link.vndk.shared_libs VNDK-SP

Tabela poniżej przedstawia konfigurację przestrzeni nazw dla procesów dostawcy, która jest wyodrębniona z sekcji [vendor] w konfiguracji VNDK Lite.

Namespace Właściwość Wartość
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} (wycofane)
/product/${LIB} (wycofane)
isolated false

Więcej informacji znajdziesz w /linkerconfig/ld.config.txt na urządzeniu.

Historia dokumentu

Zmiany w Androidzie 11

  • W Androidzie 11 pliki statyczne ld.config.*.txt są usuwane z kodu źródłowego, a zamiast tego LinkerConfig generuje je w czasie wykonywania.

Zmiany w Androidzie 9

  • W Androidzie 9 do procesów dostawcy dodana jest przestrzeń nazw linkera vndk, a biblioteki współdzielone VNDK są izolowane od domyślnej przestrzeni nazw linkera.
  • Zastąp PRODUCT_FULL_TREBLE bardziej szczegółowym PRODUCT_TREBLE_LINKER_NAMESPACES.
  • Android 9 zmienia nazwy tych plików konfiguracji linkera dynamicznego:
    Android 8.x Android 9 Opis
    ld.config.txt.in ld.config.txt Na urządzeniach z izolacją przestrzeni nazw linkera w czasie wykonywania
    ld.config.txt ld.config.vndk_lite.txt Dotyczy urządzeń z izolacją przestrzeni nazw linkera VNDK-SP
    ld.config.legacy.txt ld.config.legacy.txt Urządzenia starsze z Androidem 7.x lub starszym
  • Usuń android.hardware.graphics.allocator@2.0.so.
  • Dodano partycje product i odm.