Espace de noms Linker

Le liant dynamique résout deux défis dans la conception du VNDK Treble:

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

Ces deux problèmes peuvent être résolus à l'aide du 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, ne se battent pas.

D'autre part, le mécanisme d'espace de noms de l'éditeur de liens offre une certaine flexibilité, de sorte que certaines bibliothèques partagées peuvent ê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 cachant les détails de leur implémentation dans leurs espaces de noms de l'é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 d'association afin que les modules de 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'autre part, /system/lib[64]/libc.so est un exemple de bibliothèque publique exportée par un espace de noms de l'éditeur de liens et importée dans de nombreux espaces de noms de l'é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 /system/lib[64]/libc.so réside. Les autres espaces de noms n'auront pas accès à ces dépendances. Ce mécanisme encapsule les détails d'implémentation tout en fournissant les interfaces publiques.

Fonctionnement

Le liant dynamique est chargé de charger les bibliothèques partagées spécifiées dans les entrées DT_NEEDED ou les bibliothèques partagées spécifiées par l'argument dlopen() ou android_dlopen_ext(). Dans les deux cas, le chargeur dynamique recherche l'espace de noms du chargeur dynamique où se trouve l'appelant et tente de charger les dépendances dans le même espace de noms du chargeur dynamique. Si le liant dynamique ne peut pas charger la bibliothèque partagée dans l'espace de noms du liant spécifié, il demande au lien de l'espace de noms du liant des 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. Voici à quoi ressemble un fichier de configuration type :

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 inclut:

  • Plusieurs propriétés de mappage de répertoires et de sections au début pour que le liant dynamique sélectionne la section effective.
  • 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 remplacement entre les espaces de noms (arcs du graphique).
    • Chaque espace de noms possède ses propres paramètres d'isolation, de chemins de recherche, de chemins autorisés et de visibilité.

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

Propriété de mappage des sections de l'annuaire

Propriété Description Exemple

dir.name

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 du linker. Il peut y avoir deux (ou plusieurs) propriétés ayant 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 à partir de /vendor/bin.

Propriétés de la relation

Propriété Description Exemple
additional.namespaces

Liste d'espaces de noms supplémentaires (en plus de l'espace de noms default) pour la section, séparés par une virgule.

additional.namespaces = sphal,vndk

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

namespace.name.links

Liste d'espaces de noms de remplacement séparés par une virgule.

Si une bibliothèque partagée ne peut pas être trouvée dans l'espace de noms actuel, le liant dynamique tente de la charger à partir des espaces de noms de remplacement. 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, le liant dynamique tente de charger la bibliothèque partagée à partir de l'espace de noms default.

Ensuite, si la bibliothèque partagée ne peut pas être chargée à partir de l'espace de noms default, le chargeur dynamique tente de la charger à partir de l'espace de noms vndk.

Enfin, si toutes les tentatives échouent, le liant dynamique renvoie une erreur.

namespace.name.link.other.shared_libs

Liste des bibliothèques partagées séparées par deux-points que vous pouvez rechercher dans les espaces de noms other lorsque vous ne les trouvez pas dans l'espace de noms 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 remplacement n'accepte que libc.so ou libm.so comme nom de bibliothèque demandé. L'éditeur de liens dynamique ignore le lien de remplacement de l'espace de noms sphal vers l'espace de noms default si le nom de bibliothèque demandé n'est pas libc.so ou libm.so.

namespace.name.link.other.allow_all_shared_libs

Valeur booléenne indiquant si toutes les bibliothèques partagées peuvent être recherchées dans l'espace de noms other lorsque ces bibliothèques sont introuvables dans l'espace de noms 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èque peuvent passer par le lien de remplacement de l'espace de noms vndk à l'espace de noms sphal.

Propriétés de l'espace de noms

Propriété Description Exemple
namespace.name.isolated

Valeur booléenne indiquant si le liant dynamique doit vérifier l'emplacement de 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'exception des sous-répertoires) ou qui se trouvent sous 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 d'accès des bibliothèques partagées.

namespace.sphal.isolated = true

Cela signifie 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

Liste de répertoires séparés par un signe deux-points dans lesquels rechercher des bibliothèques partagées.

Les répertoires spécifiés dans search.paths sont précédés du nom de bibliothèque demandé si les appels de fonction aux entrées dlopen() ou DT_NEEDED ne spécifient pas le chemin d'accès 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'exception des sous-répertoires) peuvent être chargées, quelle que soit la propriété permitted.paths.

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

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

Cela indique que le lisseur dynamique recherche des bibliothèques partagées dans /system/${LIB}.

namespace.name.asan.search.paths

Liste de répertoires séparés par un signe deux-points à rechercher dans les 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é, le liant dynamique recherche d'abord /data/asan/system/${LIB}, puis /system/${LIB}.

namespace.name.permitted.paths

Liste des répertoires (y compris des sous-répertoires) séparés par un signe deux-points, dans lesquels l'éditeur de liens dynamique peut charger les bibliothèques partagées (en plus de search.paths) lorsque isolated est défini sur 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, les 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

Liste des répertoires séparés par deux-points dans lesquels le liant 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

Valeur booléenne indiquant si le programme (autre que libc) peut obtenir un gestionnaire 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 transmettant le gestionnaire à android_dlopen_ext().

Si visible est défini sur 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, que l'espace de noms soit présent ou non. 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 dispose d'un lien de remplacement vers cet espace de noms, ou (2) elles sont demandées par d'autres bibliothèques partagées ou exécutables de cet espace de noms.

namespace.sphal.visible = true

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

Création d'un espace de noms Linker

Dans Android 11, la configuration du liant est créée au moment 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 démarrage en fonction de l'environnement d'exécution, qui comprend les éléments suivants:

  • Si l'appareil est compatible avec le VNDK
  • Version VNDK cible de la partition du fournisseur
  • Version du VNDK de la partition de produits
  • Modules APEX installés

La configuration du linker est créée en résolvant les dépendances entre les espaces de noms du linker. Par exemple, si des mises à jour des modules APEX incluent des mises à jour de dépendances, la configuration du linker est générée pour refléter ces modifications. Pour en savoir plus sur la création de la configuration du linker, consultez ${android-src}/system/linkerconfig.

Isolation de l'espace de noms du linker

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 démarrage.

PRODUCT_TREBLE_
LINKER_NAMESPACES
BOARD_VNDK_
VERSION
Configuration sélectionnée Exigence concernant le VTS
true current VNDK Obligatoire pour les appareils lancés avec Android 9 ou version ultérieure
Vide VNDK Lite Obligatoire pour les appareils lancés avec Android 8.x
false Vide Legacy Pour les appareils autres que 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 du linker dynamique lorsque PRODUCT_TREBLE_LINKER_NAMESPACES est true.

La configuration du VNDK isole également les bibliothèques partagées SP-HAL et VNDK-SP. En outre, cette configuration fournit une isolation complète du linker dynamique. Il garantit que les modules de la partition système ne dépendront pas des bibliothèques partagées des partitions du fournisseur, et vice-versa.

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

Configuration VNDK

La configuration VNDK isole les dépendances de la 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 de framework

    • 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 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 pour les fournisseurs

    • Les espaces de noms default, vndk et system sont créés.
    • L'espace de noms default est isolé.
    • Les bibliothèques partagées des fournisseurs 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 du linker est illustrée ci-dessous.

Graphique de l'espace de noms du linker décrit dans la configuration du VNDK

Figure 1 : Isolement de l'espace de noms du linker (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

Pour en savoir plus, consultez /linkerconfig/ld.config.txt sur l'appareil.

Configuration VNDK Lite

À partir d'Android 8.0, le liant dynamique est configuré pour isoler les bibliothèques partagées SP-HAL et VNDK-SP afin que leurs symboles ne soient pas en conflit avec d'autres bibliothèques partagées de framework. La relation entre les espaces de noms du linker est illustrée ci-dessous.

Graphique de l'espace de noms du linker décrit dans la configuration VNDK Lite
Figure 2 Isolation de l'espace de noms Linker (configuration VNDK Lite)

LL-NDK et VNDK-SP correspondent aux 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 (non inclus 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 framework, qui est extraite de la section [system] de la configuration 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, qui est extrait de la section [vendor] de la configuration 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

Pour en savoir plus, consultez /linkerconfig/ld.config.txt sur l'appareil.

Historique du document

Nouveautés Android 11

  • Dans Android 11, les fichiers statiques ld.config.*.txt sont supprimés du codebase, et LinkerConfig les génère au moment de l'exécution.

Modifications apportées à Android 9

  • Dans Android 9, l'espace de noms du liant vndk est ajouté aux processus du fournisseur, et les bibliothèques partagées VNDK sont isolées de l'espace de noms du liant par défaut.
  • Remplacez PRODUCT_FULL_TREBLE par une PRODUCT_TREBLE_LINKER_NAMESPACES plus spécifique.
  • Android 9 modifie les noms des fichiers de configuration du liant dynamique 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 du linker VNDK-SP
    ld.config.legacy.txt ld.config.legacy.txt Pour les anciens appareils équipés d'Android 7.x ou version antérieure
  • Supprimez android.hardware.graphics.allocator@2.0.so.
  • Les partitions product et odm sont ajoutées.