vdso

VDSO(7)                    Manuel du programmeur Linux                   VDSO(7)



NOM
       vdso – Présentation de l’objet partagé dynamique ELF virtuel

SYNOPSIS
       #include <sys/auxv.h>

       void *vdso = (uintptr_t) getauxval(AT_SYSINFO_EHDR);

DESCRIPTION
       Le « vDSO » (objet partagé dynamique virtuel, « virtual dynamic shared
       object ») est une petite bibliothèque partagée que le noyau projette
       automatiquement dans l’espace d’adresses de toutes les applications en
       espace utilisateur. Les applications n’ont normalement pas besoin de
       s’occuper elles-mêmes de ces détails puisque le vDSO est d’habitude
       appelé par la bibliothèque C. Ainsi, vous pouvez écrire du code
       normalement en utilisant les fonctions standards et la bibliothèque C
       s’occupera d’utiliser toutes les fonctionnalités disponibles par
       l’intermédiaire du vDSO.

       Pourquoi le vDSO existe ? Certains appels système fournis par le noyau
       finissent par être utilisés fréquemment par le code en espace
       utilisateur, au point que ces appels peuvent avoir une emprise excessive
       sur les performances. C’est à la fois dû à la fréquence des appels qu’aux
       nombreux changements de contexte à force de sortir de l’espace
       utilisateur pour entrer dans le noyau.

       La suite de cette documentation est orientée pour les curieux et les
       auteurs de la bibliothèque C plutôt que pour les développeurs généraux.
       Si vous essayez d’appeler le vDSO dans vos propres applications plutôt
       que d’utiliser la bibliothèque C, vous faites sans doute fausse route.

   Contexte exemple
       Réaliser des appels système peut être lent. Dans les systèmes 32 bits
       x86, vous pouvez déclencher une interruption logicielle (int $0x80) pour
       indiquer au noyau que vous voulez faire un appel système. Cependant,
       cette instruction est coûteuse : elle passe par tous les chemins complets
       de traitement des interruptions dans le microcode du processeur ainsi que
       dans le noyau. Les nouveaux processeurs ont des instructions plus rapides
       (mais non rétrocompatibles) pour initier les appels système. Plutôt que
       forcer la bibliothèque C à vérifier si cette fonctionnalité est
       disponible au moment de l’exécution, la bibliothèque C peut utiliser les
       fonctions fournies par le noyau dans le vDSO.

       Remarquez que cette terminologie peut être source de confusion. Sur les
       systèmes x86, la fonction vDSO utilisée pour déterminer la méthode
       préférée pour réaliser un appel système est appelée « __kernel_vsyscall »
       alors que sous x86_64, le terme « vsyscall » se réfère aussi à une façon
       obsolète de demander au noyau l’heure ou le processeur sur lequel est
       l’appelant.

       Un appel système fréquemment utilisé est gettimeofday(2). Cet appel
       système est appelé à la fois directement par les applications en espace
       utilisateur et indirectement par la bibliothèque C. Remarquez que les
       horodatages, boucles temporelles ou scrutations — ont tous fréquemment
       besoin de savoir l’heure exacte. Ce n’est pas non plus un secret
       — n’importe quelle application dans n’importe quel mode (superutilisateur
       ou utilisateur normal) aura la même réponse. Alors le noyau s’arrange
       pour que les informations nécessaires pour répondre à cette question
       soient placées dans la mémoire accessible au processus. Ainsi un appel de
       gettimeofday(2) est transformé d’un appel système en un appel normal de
       fonction, avec peu d’accès mémoire.

   Trouver le vDSO
       L’adresse de base du vDSO (s’il existe) est passée par le noyau à tous
       les programmes dans le vecteur auxiliaire initial (consultez
       getauxval(3)) à l’aide de l’indicateur AT_SYSINFO_EHDR.

       Vous ne devez pas supposer que le vDSO est projeté à un endroit
       particulier de la projection en mémoire de l’utilisateur. L’adresse de
       base sera normalement aléatoire au moment de l’exécution à chaque fois
       qu’une nouvelle image de processus est créée (au moment de execve(2)).
       C’est ainsi pour des raisons de sécurité, afin d’éviter les attaques de
       « retour vers libc ».

       Pour certaines architectures, un indicateur AT_SYSINFO est aussi présent.
       Il n’est utilisé que pour localiser le point d’entrée vsyscall et est
       souvent omis ou défini à 0 (signifiant qu’il n’est pas disponible). Cet
       indicateur est un rappel du fonctionnement initial de vDSO (consultez
       Historique ci-dessous) et son utilisation devrait être évitée.

   Format de fichier
       Puisque le vDSO est une image ELF complète, vous pouvez y rechercher des
       symboles. Cela permet d’ajouter de nouveaux symboles avec les versions de
       noyau plus récentes et permet à la bibliothèque C de détecter les
       fonctionnalités disponibles au moment de l’exécution lors de l’exécution
       sous différentes versions de noyau. D’habitude, la bibliothèque C fera la
       détection lors du premier appel puis mettra en cache le résultat pour les
       appels suivants.

       Tous les appels sont aussi versionnés (en utilisant le format de version
       GNU). Cela permet au noyau de mettre à jour la signature de fonction sans
       casser la rétrocompatibilité. Cela signifie modifier les arguments
       acceptés par la fonction et la valeur de retour. Ainsi, lors de la
       recherche de symboles dans le vDSO, vous devez toujours inclure la
       version pour correspondre à l’ABI attendue.

       Typiquement, le vDSO suit la convention de nommage de préfixer tous les
       symboles par « __vdso_ » ou « __kernel_ » afin de les distinguer des
       autres symboles standards. Par exemple, la fonction « gettimeofday » est
       nommée « __vdso_gettimeofday ».

       Utilisez les conventions d’appel C standard pour appeler n’importe
       laquelle de ces fonctions. Pas la peine de vous embêter avec les
       registres bizarres ou les comportements de pile.

NOTES
   Source
       Lors de la compilation du noyau, le code vDSO est compilé et lié
       automatiquement. Il se trouve souvent dans le répertoire spécifique à
       l’architecture :

           find arch/$ARCH/ -name '*vdso*.so*' -o -name '*gate*.so*'

   Noms vDSO
       Le nom du vDSO dépend des architectures. Il est souvent visible dans des
       endroits comme la sortie de ldd(1) de la glibc. Le nom exact ne devrait
       affecter aucun code, donc pas la peine de le coder en dur.

       ABI utilisateur   Nom vDSO
       ────────────────────────────────────
       aarch64           linux-vdso.so.1
       arm               linux-vdso.so.1
       ia64              linux-gate.so.1
       mips              linux-vdso.so.1
       ppc/32            linux-vdso32.so.1
       ppc/64            linux-vdso64.so.1
       riscv             linux-vdso.so.1

       s390              linux-vdso32.so.1
       s390x             linux-vdso64.so.1
       sh                linux-gate.so.1
       i386              linux-gate.so.1
       x86-64            linux-vdso.so.1
       x86/x32           linux-vdso.so.1

   strace(1), seccomp(2) et le vDSO
       Lors du suivi des appels système avec strace(1), les symboles (appels
       système) qui sont exportés par le vDSO n’apparaîtront pas dans la sortie
       du suivi. De même, ces appels système ne seront pas visibles par les
       filtres seccomp(2).

NOTES SPÉCIFIQUES AUX ARCHITECTURES
       Les sous-sections suivantes fournissent des notes spécifiques aux
       architectures sur le vDSO.

       Remarquez que le vDSO utilisé est basé sur l’ABI du code en espace
       utilisateur et non sur l’ABI du noyau. Ainsi, par exemple, si vous
       exécutez un binaire ELF 32 bits i386, vous obtiendrez le même vDSO que
       vous l’exécutiez avec un noyau 32 bits i386 ou avec un noyau 64 bits
       x86_64. Par conséquent, le nom de l’ABI en espace utilisateur devrait
       être utilisé pour déterminer la section suivante adéquate.

   Fonctions ARM
       Le tableau suivant indique les symboles exportés par le vDSO.

       symbole                version
       ────────────────────────────────────────────────────────────
       __vdso_gettimeofday    LINUX_2.6 (exported since Linux 4.1)
       __vdso_clock_gettime   LINUX_2.6 (exported since Linux 4.1)

       De plus, le portage ARM a une page de code pleine de fonctions
       utilitaires. Puisque ce n’est qu’une page de code brut, aucune
       information ELF n’existe pour faire la recherche de symboles ou le
       versionnage. Elle fournit cependant une prise en charge pour plusieurs
       versions.

       Pour des renseignements sur cette page de code, mieux vaut consulter la
       documentation du noyau puisqu’elle est extrêmement détaillée et couvre
       tous ce que vous devez savoir :
       Documentation/arm/kernel_user_helpers.txt.

   Fonctions aarch64
       Le tableau suivant indique les symboles exportés par le vDSO.

       symbole                  version
       ──────────────────────────────────────
       __kernel_rt_sigreturn    LINUX_2.6.39
       __kernel_gettimeofday    LINUX_2.6.39
       __kernel_clock_gettime   LINUX_2.6.39
       __kernel_clock_getres    LINUX_2.6.39

   Fonctions bfin (Blackfin) (portage supprimé dans Linux 4.17)
       Comme ce processeur n’a pas d’unité de gestion mémoire (MMU), il ne
       définit pas de vDSO au sens usuel. À la place, il projette au démarrage
       quelques fonctions brutes à un endroit spécifique de la mémoire. Les
       applications en espace utilisateur appellent ensuite directement dans
       cette zone. Aucune mesure de rétrocompatibilité n’est prise à part en
       sniffant les codes opératoires bruts, mais comme il s’agit d’un
       processeur embarqué, il peut s’en sortir impunément – certains formats
       d’objet qu’il exécute ne sont même pas basés sur ELF (ils sont
       bFLT/FLAT).

       Pour des renseignements sur cette page de code, mieux vaut consulter la
       documentation publique :
       http://docs.blackfin.uclinux.org/doku.php?id=linux-kernel:fixed-code

   Fonctions mips
       Le tableau suivant indique les symboles exportés par le vDSO.

       symbole                  version
       ──────────────────────────────────────────────────────────────────
       __kernel_gettimeofday    LINUX_2.6 (exportation depuis Linux 4.4)
       __kernel_clock_gettime   LINUX_2.6 (exportation depuis Linux 4.4)

   Fonctions ia64 (Itanium)
       Le tableau suivant indique les symboles exportés par le vDSO.

       symbole                      version
       ───────────────────────────────────────
       __kernel_sigtramp            LINUX_2.5
       __kernel_syscall_via_break   LINUX_2.5
       __kernel_syscall_via_epc     LINUX_2.5

       Le portage Itanium est un peu périlleux. En plus du vDSO ci-dessus, il a
       aussi des « appels système légers » (aussi appelés « appels système
       rapides » ou « fsys »). Ils peuvent être appelés à l’aide de l’assistant
       vDSO __kernel_syscall_via_epc. Les appels système indiqués ici ont la
       même sémantique que si vous les appeliez directement à l’aide de
       syscall(2), donc consultez la documentation adéquate pour chacun d’entre
       eux. Le tableau suivant indique les fonctions disponibles par ce
       mécanisme.

       fonction
       ────────────────
       clock_gettime
       getcpu
       getpid
       getppid
       gettimeofday
       set_tid_address

   Fonctions parisc (hppa)
       Le portage parisc à une page de code pleine de fonctions utilitaires
       appelée une page passerelle. Plutôt que d’utiliser l’approche classique
       du vecteur auxiliaire ELF, il passe l’adresse de la page au processus à
       l’aide du registre SR2. Les permissions sur la page sont telles
       qu’exécuter simplement ces adresses s’exécute automatiquement avec les
       droits du noyau et pas en espace utilisateur. C’est ainsi afin de
       correspondre au mode de fonctionnement HP-UX.

       Puisque ce n’est qu’une page de code brut, aucune information ELF
       n’existe pour faire la recherche de symboles ou le versionnage. Appelez
       simplement l’adresse adéquate à l’aide de l’instruction de branche, par
       exemple :

           ble <offset>(%sr2, %r0)

       offset   fonction
       ───────────────────────────────────────────────────
       00b0     lws_entry (opérations CAS)
       00e0     set_thread_pointer (utilisé par la glibc)
       0100     linux_gateway_entry (syscall)

   Fonctions ppc/32
       Le tableau suivant indique les symboles exportés par le vDSO. Les
       fonctions marquées avec un * ne sont disponibles que si le noyau est
       PowerPC64 (64 bits).



       symbole                    version
       ────────────────────────────────────────
       __kernel_clock_getres      LINUX_2.6.15
       __kernel_clock_gettime     LINUX_2.6.15
       __kernel_datapage_offset   LINUX_2.6.15
       __kernel_get_syscall_map   LINUX_2.6.15
       __kernel_get_tbfreq        LINUX_2.6.15
       __kernel_getcpu *          LINUX_2.6.15
       __kernel_gettimeofday      LINUX_2.6.15
       __kernel_sigtramp_rt32     LINUX_2.6.15
       __kernel_sigtramp32        LINUX_2.6.15
       __kernel_sync_dicache      LINUX_2.6.15
       __kernel_sync_dicache_p5   LINUX_2.6.15

       Les horloges CLOCK_REALTIME_COARSE et CLOCK_MONOTONIC_COARSE ne sont pas
       prises en charge par les interfaces __kernel_clock_getres et
       __kernel_clock_gettime. Le noyau a recours à l’appel système réel.

   Fonctions ppc/64
       Le tableau suivant indique les symboles exportés par le vDSO.

       symbole                    version
       ────────────────────────────────────────
       __kernel_clock_getres      LINUX_2.6.15
       __kernel_clock_gettime     LINUX_2.6.15
       __kernel_datapage_offset   LINUX_2.6.15
       __kernel_get_syscall_map   LINUX_2.6.15
       __kernel_get_tbfreq        LINUX_2.6.15
       __kernel_getcpu            LINUX_2.6.15
       __kernel_gettimeofday      LINUX_2.6.15
       __kernel_sigtramp_rt64     LINUX_2.6.15
       __kernel_sync_dicache      LINUX_2.6.15
       __kernel_sync_dicache_p5   LINUX_2.6.15

       Les horloges CLOCK_REALTIME_COARSE et CLOCK_MONOTONIC_COARSE ne sont pas
       prises en charge par les interfaces __kernel_clock_getres et
       __kernel_clock_gettime. Le noyau a recours à l’appel système réel.

   Fonctions riscv
       Le tableau suivant indique les symboles exportés par le vDSO.

       symbole                  version
       ────────────────────────────────────
       __kernel_rt_sigreturn    LINUX_4.15
       __kernel_gettimeofday    LINUX_4.15
       __kernel_clock_gettime   LINUX_4.15
       __kernel_clock_getres    LINUX_4.15
       __kernel_getcpu          LINUX_4.15
       __kernel_flush_icache    LINUX_4.15

   Fonctions s390
       Le tableau suivant indique les symboles exportés par le vDSO.

       symbole                  version
       ──────────────────────────────────────
       __kernel_clock_getres    LINUX_2.6.29
       __kernel_clock_gettime   LINUX_2.6.29
       __kernel_gettimeofday    LINUX_2.6.29

   Fonctions s390x
       Le tableau suivant indique les symboles exportés par le vDSO.

       symbole                  version
       ──────────────────────────────────────
       __kernel_clock_getres    LINUX_2.6.29

       __kernel_clock_gettime   LINUX_2.6.29
       __kernel_gettimeofday    LINUX_2.6.29

   Fonctions sh (SuperH)
       Le tableau suivant indique les symboles exportés par le vDSO.

       symbole                 version
       ──────────────────────────────────
       __kernel_rt_sigreturn   LINUX_2.6
       __kernel_sigreturn      LINUX_2.6
       __kernel_vsyscall       LINUX_2.6

   Fonctions i386
       Le tableau suivant indique les symboles exportés par le vDSO.

       symbole                 version
       ──────────────────────────────────────────────────────────────────
       __kernel_sigreturn      LINUX_2.5
       __kernel_rt_sigreturn   LINUX_2.5
       __kernel_vsyscall       LINUX_2.5
       __vdso_clock_gettime    LINUX_2.6 (exportation depuis Linux 3.15)
       __vdso_gettimeofday     LINUX_2.6 (exportation depuis Linux 3.15)
       __vdso_time             LINUX_2.6 (exportation depuis Linux 3.15)

   Fonctions x86-64
       Le tableau suivant indique les symboles exportés par le vDSO. Tous ces
       symboles sont aussi disponibles sans le préfixe « __vdso_ », mais vous
       devriez les ignorer et vous cantonner aux noms suivants.

       symbole                version
       ─────────────────────────────────
       __vdso_clock_gettime   LINUX_2.6
       __vdso_getcpu          LINUX_2.6
       __vdso_gettimeofday    LINUX_2.6
       __vdso_time            LINUX_2.6

   Fonctions x86/x32
       Le tableau suivant indique les symboles exportés par le vDSO.

       symbole                version
       ─────────────────────────────────
       __vdso_clock_gettime   LINUX_2.6
       __vdso_getcpu          LINUX_2.6
       __vdso_gettimeofday    LINUX_2.6
       __vdso_time            LINUX_2.6

   Historique
       Le vDSO n’était à l’origine qu’une seule fonction — le vsyscall. Dans les
       anciens noyaux, ce nom pourrait être vu dans une projection en mémoire de
       processus à la place de « vdso ». Le temps passant, les gens ont réalisé
       que ce mécanisme était un excellent moyen pour passer plus de
       fonctionnalités à l’espace utilisateur, il a donc été reconçu en tant que
       vDSO au format actuel.

VOIR AUSSI
       syscalls(2), getauxval(3), proc(5)

       Les documents, exemples et le code source dans l’arborescence du code
       source de Linux :

           Documentation/ABI/stable/vdso
           Documentation/ia64/fsys.txt
           Documentation/vDSO/* (contient des exemples d’utilisation du vDSO)

           find arch/ -iname '*vdso*' -o -iname '*gate*'

COLOPHON
       Cette page fait partie de la publication 5.11 du projet man-pages Linux.
       Une description du projet et des instructions pour signaler des anomalies
       et la dernière version de cette page, peuvent être trouvées à l'adresse
       https://www.kernel.org/doc/man-pages/.


TRADUCTION
       La traduction française de cette page de manuel a été créée par
       Christophe Blaess <https://www.blaess.fr/christophe/>, Stéphan Rafin
       <stephan.rafin@laposte.net>, Thierry Vignaud <tvignaud@mandriva.com>,
       François Micaux, Alain Portal <aportal@univ-montp2.fr>, Jean-Philippe
       Guérard <fevrier@tigreraye.org>, Jean-Luc Coulon (f5ibh) <jean-
       luc.coulon@wanadoo.fr>, Julien Cristau <jcristau@debian.org>, Thomas
       Huriaux <thomas.huriaux@gmail.com>, Nicolas François
       <nicolas.francois@centraliens.net>, Florentin Duneau <fduneau@gmail.com>,
       Simon Paillard <simon.paillard@resel.enst-bretagne.fr>, Denis Barbier
       <barbier@debian.org>, David Prévot <david@tilapin.org> et Jean-Paul
       Guillonneau <guillonneau.jeanpaul@free.fr>

       Cette traduction est une documentation libre ; veuillez vous reporter à
       la GNU General Public License version 3
       ⟨https://www.gnu.org/licenses/gpl-3.0.html⟩ concernant les conditions de
       copie et de distribution. Il n'y a aucune RESPONSABILITÉ LÉGALE.

       Si vous découvrez un bogue dans la traduction de cette page de manuel,
       veuillez envoyer un message à debian-l10n-french@lists.debian.org ⟨⟩.




Linux                             22 mars 2021                           VDSO(7)