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 łączących. Ten mechanizm jest udostępniany przez dynamicznego linkera. Może izolować biblioteki udostępnione w różnych przestrzeniach nazw kreatora linków, co pozwala uniknąć konfliktu w bibliotekach o tej samej nazwie, ale z różnymi symbolami.

Z drugiej strony mechanizm przestrzeni nazw tagu łączącego zapewnia elastyczność, dzięki czemu niektóre biblioteki udostępnione można eksportować za pomocą przestrzeni nazw tagu łączącego i używać ich w innej przestrzeni nazw tagu łączącego. 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 i /system/lib[64]/vndk-sp-${VER}/libcutils.so to 2 współdzielone 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 tag łączący nie może wczytać biblioteki udostępnionej do określonej przestrzeni nazw tagu łączącego, wysyła do połączonej przestrzeni nazw kreatora linków prośbę o wyeksportowane biblioteki udostępnione.

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) oraz kilka linków zapasowych między przestrzeniami nazw (łuki grafu).
    • Każda przestrzeń nazw 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 wczytywanych z poziomu /system/bin lub /system/xbin.

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

Właściwości relacji

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

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

additional.namespaces = sphal,vndk

Oznacza to, że w konfiguracji [system] są 3 przestrzenie nazw (default, sphal i vndk).

namespace.name.links

Rozdzielana przecinkami lista przestrzeni nazw zapasowych.

Jeśli nie można znaleźć biblioteki udostępnionej w bieżącej przestrzeni nazw, dynamiczny linker próbuje załadować bibliotekę udostępnioną z przełączalnych przestrzeni nazw. Przestrzeń nazw podana 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ę z 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 żadna próba się nie powiedzie, dynamiczny tag łączący zwróci 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.

Nie można używać tej usługi w połączeniu z usługą 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. Dynamiczny tag łączący ignoruje link zastępczy z przestrzeni nazw sphal do przestrzeni nazw default, jeśli żądana nazwa biblioteki jest inna niż libc.so lub libm.so.

namespace.name.link.other.allow_all_shared_libs

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

Nie można używać tej usługi 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ółdzielona.

Jeśli isolated to true, można wczytać tylko te biblioteki współdzielone, które są w jednym z katalogów search.paths (z wyłączeniem podkatalogów) lub znajdują się w jednym z katalogów permitted.paths (w tym w 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 ładować tylko biblioteki udostępnione z regionu search.paths lub niższego niż 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 podają pełnej ścieżki. Katalog podany na początku listy ma wyższy priorytet.

Gdy isolated ma wartość true, biblioteki udostępnione znajdujące się w jednym z katalogów search.paths (z wyłączeniem podkatalogów) mogą być ładowane 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 wczytać /system/${LIB}/libc.so, ale nie można wczytać /system/${LIB}/vndk/libutils.so.

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

Oznacza to, że linker dynamiczny przeszukuje /system/${LIB} w poszukiwaniu bibliotek udostępnionych.

namespace.name.asan.search.paths

Lista katalogów oddzielonych dwukropkiem, w których mają być wyszukiwane współdzielone biblioteki, 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 funkcja ASan, dynamiczny tag łączący przeszukuje najpierw /data/asan/system/${LIB}, a następnie przeszukuje /system/${LIB}.

namespace.name.permitted.paths

Rozdzielona dwukropkiem lista katalogów (łącznie z podkatalogami), w których dynamiczny tag łączący może wczytywać biblioteki udostępnione (oprócz search.paths), gdy isolated ma wartość true.

Można też wczytywać biblioteki udostępnione znajdujące się w podkatalogach permitted.paths. Jeśli np. permitted.paths to /system/${LIB}, można wczytać 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 z poziomu /system/${LIB}/hw można wczytać do izolowanej 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

Rozdzielona dwukropkiem lista katalogów, do których dynamiczny tag łączący może wczytywać biblioteki udostępnione, gdy włączony jest protokół 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, android_get_exported_namespace() zawsze zwraca nick, o ile istnieje przestrzeń nazw.

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 łącznika

W Androidzie 11 konfiguracja linkera jest tworzona w czasie wykonywania w katalogu /linkerconfig, a nie w plikach tekstowych w katalogu /linkerconfig. 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 tagu łączącego znajdziesz tutaj: ${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 jej konfiguracja jest generowana podczas uruchamiania.

PRODUCT_TREBLE_
LINKER_NAMESPACES
BOARD_VNDK_
VERSION
Wybrana konfiguracja Wymagania dotyczące VTS
true current VNDK Obowiązkowe w przypadku urządzeń 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 tagu łączącego. Dzięki temu moduły na partycji systemowej nie będą zależeć od bibliotek udostępnionych na partycjach dostawcy 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 sekcji różnice są następujące:

  • Procesy dotyczące platformy

    • 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 izolowana.
    • 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. Poniżej przedstawiliśmy relację między przestrzeniami nazw tagu łączącego.

Wykres przestrzeni nazw tagu łączącego 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 (przeniesiono do VNDK-SP w 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 platformy wyodrębnionej z sekcji [system] 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

Poniższa tabela przedstawia konfigurację przestrzeni nazw dla procesów dostawcy, która została pobrana z sekcji [vendor] 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 statyczne pliki ld.config.*.txt są usuwane z bazy kodu, a LinkerConfig generuje je w czasie działania.

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 poniższych plików konfiguracji dynamicznego tagu łączącego.
    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.