Espace de noms de l'éditeur de liens

L'éditeur de liens dynamique relève deux défis dans la conception du Treble VNDK :

  • Les bibliothèques partagées SP-HAL et leurs dépendances, y compris les bibliothèques VNDK-SP, sont chargées dans les processus framework. Il devrait y avoir des mécanismes pour éviter les conflits de symboles.
  • dlopen() et android_dlopen_ext() peuvent introduire certaines dépendances d'exécution qui ne sont pas visibles au moment de la construction et peuvent être difficiles à détecter à l'aide d'une analyse statique.

Ces deux défis peuvent être résolus par le mécanisme d'espace de noms de l'éditeur de liens . Ce mécanisme est fourni par l'éditeur de liens dynamique. Il peut isoler les bibliothèques partagées dans différents espaces de noms de l'éditeur de liens afin que les bibliothèques portant le même nom de bibliothèque mais avec des symboles différents n'entrent pas en conflit.

D'un autre côté, le mécanisme d'espace de noms de l'éditeur de liens offre la flexibilité nécessaire pour que certaines bibliothèques partagées puissent être exportées par un espace de noms de l'éditeur de liens et utilisées par un autre espace de noms de l'éditeur de liens. Ces bibliothèques partagées exportées peuvent devenir des interfaces de programmation d'applications publiques pour d'autres programmes tout en masquant les détails de leur implémentation dans leurs espaces de noms d'éditeur de liens.

Par exemple, /system/lib[64]/libcutils.so et /system/lib[64]/vndk-sp-${VER}/libcutils.so sont deux bibliothèques partagées. Ces deux bibliothèques peuvent avoir des symboles différents. Ils sont chargés dans différents espaces de noms de l'éditeur de liens afin que les modules du framework puissent dépendre de /system/lib[64]/libcutils.so et que les bibliothèques partagées SP-HAL puissent dépendre de /system/lib[64]/vndk-sp-${VER}/libcutils.so .

D'un autre côté, /system/lib[64]/libc.so est un exemple de bibliothèque publique exportée par un espace de noms d'éditeur de liens et importée dans de nombreux espaces de noms d'éditeur de liens. Les dépendances de /system/lib[64]/libc.so , telles que libnetd_client.so , sont chargées dans l'espace de noms dans lequel réside /system/lib[64]/libc.so . Les autres espaces de noms n'auront pas accès à ces dépendances. Ce mécanisme encapsule les détails de mise en œuvre tout en fournissant les interfaces publiques.

Comment ça marche?

L'éditeur de liens dynamique est responsable du chargement des bibliothèques partagées spécifiées dans les entrées DT_NEEDED ou des bibliothèques partagées spécifiées par l'argument de dlopen() ou android_dlopen_ext() . Dans les deux cas, l'éditeur de liens dynamique trouve l'espace de noms de l'éditeur de liens où réside l'appelant et tente de charger les dépendances dans le même espace de noms de l'éditeur de liens. Si l'éditeur de liens dynamique ne peut pas charger la bibliothèque partagée dans l'espace de noms de l'éditeur de liens spécifié, il demande à l' espace de noms de l'éditeur de liens lié les bibliothèques partagées exportées.

Format du fichier de configuration

Le format du fichier de configuration est basé sur le format de fichier INI. Un fichier de configuration typique ressemble à ceci :

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}

Le fichier de configuration comprend :

  • Plusieurs propriétés de mappage de section de répertoire au début pour que l'éditeur de liens dynamique sélectionne la section efficace.
  • Plusieurs sections de configuration des espaces de noms de l'éditeur de liens :
    • Chaque section contient plusieurs espaces de noms (sommets du graphique) et plusieurs liens de secours entre les espaces de noms (arcs du graphique).
    • Chaque espace de noms possède son propre isolement, ses propres chemins de recherche, ses chemins autorisés et ses propres paramètres de visibilité.

Les tableaux ci-dessous décrivent en détail la signification de chaque propriété.

Propriété de mappage de section de répertoire

Propriété Description Exemple

dir. name

Un chemin d'accès à un répertoire auquel la section [ name ] s'applique.

Chaque propriété mappe les exécutables du répertoire à une section de configuration des espaces de noms de l'éditeur de liens. Il peut y avoir deux (ou plus) propriétés portant le même name mais pointant vers des répertoires différents.

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

Cela indique que la configuration spécifiée dans la section [system] s'applique aux exécutables chargés à partir de /system/bin ou /system/xbin .

La configuration spécifiée dans la section [vendor] s'applique aux exécutables chargés depuis /vendor/bin .

Propriétés des relations

Propriété Description Exemple
additional. namespaces

Une liste d'espaces de noms supplémentaires séparés par des virgules (en plus de l'espace de noms default ) pour la section.

additional. namespaces = sphal, vndk

Cela indique qu'il existe trois espaces de noms ( default , sphal et vndk ) dans la configuration [system] .

namespace. name . links

Une liste d'espaces de noms de secours, séparés par des virgules.

Si une bibliothèque partagée est introuvable dans l'espace de noms actuel, l'éditeur de liens dynamique tente de charger la bibliothèque partagée à partir des espaces de noms de secours. L'espace de noms spécifié au début de la liste a une priorité plus élevée.

namespace. sphal. links = default, vndk

Si une bibliothèque partagée ou un exécutable demande une bibliothèque partagée qui ne peut pas être chargée dans l'espace de noms sphal , l'éditeur de liens dynamique essaie de charger la bibliothèque partagée à partir de l'espace de noms default .

Et puis, si la bibliothèque partagée ne peut pas non plus être chargée à partir de l'espace de noms par default , l'éditeur de liens dynamique essaie de charger la bibliothèque partagée à partir de l'espace de noms vndk .

Enfin, si toutes les tentatives échouent, l'éditeur de liens dynamique renvoie une erreur.

namespace. name . link. other . shared_libs

Une liste de bibliothèques partagées, séparées par des deux-points, qui peuvent être recherchées dans les other espaces de noms lorsque ces bibliothèques sont introuvables dans l'espace name .

Cette propriété ne peut pas être utilisée avec namespace. name . link. other . allow_all_shared_libs .

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

Cela indique que le lien de secours accepte uniquement libc.so ou libm.so comme nom de bibliothèque demandé. L'éditeur de liens dynamique ignore le lien de secours de sphal vers l'espace de noms default si le nom de la bibliothèque demandé n'est pas libc.so ou libm.so .

namespace. name . link. other . allow_all_shared_libs

Valeur booléenne qui indique si toutes les bibliothèques partagées peuvent être recherchées dans l' other espace de noms lorsque ces bibliothèques sont introuvables dans l'espace name .

Cette propriété ne peut pas être utilisée avec namespace. name . link. other . shared_libs .

namespace. vndk. link. sphal. allow_all_shared_libs = true

Cela indique que tous les noms de bibliothèques peuvent parcourir le lien de secours de vndk vers l'espace de noms sphal .

Propriétés de l'espace de noms

Propriété Description Exemple
namespace. name . isolated

Une valeur booléenne qui indique si l'éditeur de liens dynamique doit vérifier où réside la bibliothèque partagée.

Si isolated est true , seules les bibliothèques partagées qui se trouvent dans l'un des répertoires search.paths (à l'exclusion des sous-répertoires) ou dans l'un des répertoires permitted.paths (y compris les sous-répertoires) peuvent être chargées.

Si isolated est false (par défaut), l'éditeur de liens dynamique ne vérifie pas le chemin des bibliothèques partagées.

namespace. sphal. isolated = true

Cela indique que seules les bibliothèques partagées dans search.paths ou sous permitted.paths peuvent être chargées dans l'espace de noms sphal .

namespace. name . search.paths

Une liste de répertoires séparés par des deux-points dans lesquels rechercher des bibliothèques partagées.

Les répertoires spécifiés dans search.paths sont ajoutés au nom de la bibliothèque demandée si les appels de fonction aux entrées dlopen() ou DT_NEEDED ne spécifient pas le chemin complet. Le répertoire spécifié au début de la liste a une priorité plus élevée.

Lorsque isolated est true , les bibliothèques partagées qui se trouvent dans l'un des répertoires search.paths (à l'exclusion des sous-répertoires) peuvent être chargées quelle que soit la propriété permitted.paths .

Par exemple, si search.paths est /system/${LIB} et permitted.paths est vide, /system/${LIB}/libc.so peut être chargé mais /system/${LIB}/vndk/libutils.so ne peut pas être chargé.

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

Cela indique que l'éditeur de liens dynamique recherche /system/${LIB} les bibliothèques partagées.

namespace. name . asan.search.paths

Une liste de répertoires séparés par des deux-points dans lesquels rechercher des bibliothèques partagées lorsque AddressSanitizer (ASan) est activé.

namespace. name . search.paths est ignoré lorsque ASan est activé.

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

Cela indique que lorsque ASan est activé, l'éditeur de liens dynamique recherche d'abord /data/asan/system/${LIB} puis recherche /system/${LIB} .

namespace. name . permitted.paths

Une liste de répertoires (y compris les sous-répertoires) séparés par deux-points dans lesquels l'éditeur de liens dynamique peut charger les bibliothèques partagées (en plus de search.paths ) lorsqu'ils isolated est true .

Les bibliothèques partagées qui se trouvent dans les sous-répertoires de permitted.paths peuvent également être chargées. Par exemple, si permitted.paths est /system/${LIB} , /system/${LIB}/libc.so et /system/${LIB}/vndk/libutils.so peuvent être chargés.

Si isolated est false , permitted.paths sont ignorés et un avertissement est émis.

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

Cela indique que les bibliothèques partagées sous /system/${LIB}/hw peuvent être chargées dans l'espace de noms default isolé.

Par exemple, sans permitted.paths , libaudiohal.so ne peut pas charger /system/${LIB}/hw/audio.a2dp.default.so dans l'espace de noms default .

namespace. name . asan.permitted.paths

Une liste de répertoires séparés par des deux-points dans lesquels l'éditeur de liens dynamique peut charger les bibliothèques partagées lorsque ASan est activé.

namespace. name . permitted.paths est ignoré lorsque ASan est activé.

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

Cela indique que lorsque ASan est activé, les bibliothèques partagées sous /data/asan/system/${LIB}/hw ou /system/${LIB}/hw peuvent être chargées dans l'espace de noms default isolé.

namespace. name . visible

Une valeur booléenne qui indique si le programme (autre que libc ) peut obtenir un handle d'espace de noms de l'éditeur de liens avec android_get_exported_namespace() et ouvrir une bibliothèque partagée dans l'espace de noms de l'éditeur de liens en passant le handle à android_dlopen_ext() .

Si visible est true , android_get_exported_namespace() renvoie toujours le handle si l'espace de noms existe.

Si visible est false (par défaut), android_get_exported_namespace() renvoie toujours NULL quelle que soit la présence de l'espace de noms. Les bibliothèques partagées ne peuvent être chargées dans cet espace de noms que si (1) elles sont demandées par un autre espace de noms de l'éditeur de liens qui a un lien de secours vers cet espace de noms, ou (2) elles sont demandées par d'autres bibliothèques partagées ou exécutables dans cet espace de noms.

namespace. sphal. visible = true

Cela indique que android_get_exported_namespace("sphal") peut renvoyer un handle d'espace de noms d'éditeur de liens valide.

Création d'espace de noms de l'éditeur de liens

Dans Android 11, la configuration de l'éditeur de liens est créée lors de l'exécution sous /linkerconfig au lieu d'utiliser des fichiers de texte brut dans ${android-src}/system/core/rootdir/etc . La configuration est générée au moment du démarrage en fonction de l'environnement d'exécution, qui comprend les éléments suivants :

  • Si l'appareil prend en charge VNDK
  • Version VNDK cible de la partition du fournisseur
  • Version VNDK de la partition du produit
  • Modules APEX installés

La configuration de l'éditeur de liens est créée en résolvant les dépendances entre les espaces de noms de l'éditeur de liens. Par exemple, s'il existe des mises à jour sur les modules APEX qui incluent des mises à jour de dépendances, la configuration de l'éditeur de liens est générée pour refléter ces modifications. Plus de détails sur la création d'une configuration de l'éditeur de liens peuvent être trouvés dans ${android-src}/system/linkerconfig .

Isolation de l'espace de noms de l'éditeur de liens

Il existe trois types de configuration. En fonction de la valeur de PRODUCT_TREBLE_LINKER_NAMESPACES et BOARD_VNDK_VERSION dans BoardConfig.mk , la configuration correspondante est générée au moment du démarrage.

PRODUCT_TREBLE_
LINKER_NAMESPACES
BOARD_VNDK_
VERSION
Configuration sélectionnée Exigence VTS
true current VNDK Obligatoire pour les appareils lancés avec Android 9 ou supérieur
Vide VNDK Lite Obligatoire pour les appareils lancés avec Android 8.x
false Vide Legacy Pour les appareils non-Treble

La configuration VNDK Lite isole les bibliothèques partagées SP-HAL et VNDK-SP. Sous Android 8.0, il doit s'agir du fichier de configuration de l'éditeur de liens dynamique lorsque PRODUCT_TREBLE_LINKER_NAMESPACES est true .

La configuration VNDK isole également les bibliothèques partagées SP-HAL et VNDK-SP. De plus, cette configuration fournit l’isolation complète de l’éditeur de liens dynamique. Cela garantit que les modules de la partition système ne dépendront pas des bibliothèques partagées dans les partitions du fournisseur et vice versa.

Sous Android 8.1 ou version ultérieure, la configuration VNDK est la configuration par défaut et il est fortement recommandé d'activer l'isolation complète de l'éditeur de liens dynamique en définissant BOARD_VNDK_VERSION sur current .

Configuration du VNDK

La configuration VNDK isole les dépendances de bibliothèque partagée entre la partition système et les partitions du fournisseur. Par rapport aux configurations mentionnées dans la sous-section précédente, les différences sont décrites comme suit :

  • Processus-cadres

    • Les espaces de noms default , vndk , sphal et rs sont créés.
    • Tous les espaces de noms sont isolés.
    • Les bibliothèques partagées du système sont chargées dans l'espace de noms default .
    • Les SP-HAL sont chargés dans l'espace de noms sphal .
    • Bibliothèques partagées VNDK-SP chargées dans l'espace de noms vndk .
  • Processus du fournisseur

    • Les espaces de noms default , vndk et system sont créés.
    • L'espace de noms default est isolé.
    • Les bibliothèques partagées du fournisseur sont chargées dans l'espace de noms default .
    • Les bibliothèques partagées VNDK et VNDK-SP sont chargées dans l'espace de noms vndk .
    • LL-NDK et ses dépendances sont chargés dans l'espace de noms system .

La relation entre les espaces de noms de l'éditeur de liens est illustrée ci-dessous.

Graphique d'espace de noms de l'éditeur de liens décrit dans la configuration du VNDK
Figure 1. Isolation de l'espace de noms de l'éditeur de liens (configuration VNDK)

Dans l'image ci-dessus, LL-NDK et VNDK-SP représentent les bibliothèques partagées suivantes :

  • 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

Vous pouvez trouver plus de détails dans /linkerconfig/ld.config.txt à partir de l'appareil.

Configuration VNDK Lite

Depuis Android 8.0, l'éditeur de liens dynamique est configuré pour isoler les bibliothèques partagées SP-HAL et VNDK-SP de sorte que leurs symboles n'entrent pas en conflit avec d'autres bibliothèques partagées du framework. La relation entre les espaces de noms de l'éditeur de liens est indiquée ci-dessous.

Graphique d'espace de noms de l'éditeur de liens décrit dans la configuration de VNDK Lite
Figure 2. Isolation de l'espace de noms de l'éditeur de liens (configuration VNDK Lite)

LL-NDK et VNDK-SP représentent les bibliothèques partagées suivantes :

  • LL-NDK
    • libEGL.so
    • libGLESv1_CM.so
    • libGLESv2.so
    • libc.so
    • libdl.so
    • liblog.so
    • libm.so
    • libnativewindow.so
    • libstdc++.so (pas dans la configuration)
    • libsync.so
    • libvndksupport.so
    • libz.so (déplacé vers VNDK-SP dans la 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

Le tableau ci-dessous répertorie la configuration des espaces de noms pour les processus de structure, extraite de la section [system] de la configuration de VNDK Lite.

Espace de noms Propriété Valeur
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 (pour 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 (pour 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 (pour le noyau RS compilé)
isolated true
visible true
links default,vndk
link.default.shared_libs LL-NDK
libmediandk.so
libft2.so
link.vndk.shared_libs VNDK-SP

Le tableau ci-dessous présente la configuration des espaces de noms pour les processus du fournisseur, extraite de la section [vendor] de la configuration de VNDK Lite.

Espace de noms Propriété Valeur
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} (obsolète)
/product/${LIB} (obsolète)
isolated false

Plus de détails peuvent être trouvés dans /linkerconfig/ld.config.txt à partir de l'appareil.

Historique du document

Modifications d'Android 11

  • Dans Android 11, les fichiers statiques ld.config.*.txt sont supprimés de la base de code et LinkerConfig les génère à la place lors de l'exécution.

Modifications d'Android 9

  • Dans Android 9, l'espace de noms de l'éditeur de liens vndk est ajouté aux processus du fournisseur et les bibliothèques partagées VNDK sont isolées de l'espace de noms de l'éditeur de liens par défaut.
  • Remplacez PRODUCT_FULL_TREBLE par PRODUCT_TREBLE_LINKER_NAMESPACES plus spécifique.
  • Android 9 modifie les noms des fichiers de configuration de l'éditeur de liens dynamiques suivants.
    Android 8.x Android 9 Description
    ld.config.txt.in ld.config.txt Pour les appareils avec isolation de l'espace de noms de l'éditeur de liens d'exécution
    ld.config.txt ld.config.vndk_lite.txt Pour les appareils avec isolation de l'espace de noms de l'éditeur de liens VNDK-SP
    ld.config.legacy.txt ld.config.legacy.txt Pour les anciens appareils exécutant Android 7.x ou une version antérieure
  • Supprimez android.hardware.graphics.allocator@2.0.so .
  • Les partitions product et odm sont ajoutées.