vDSO(7) Miscellaneous Information Manual vDSO(7) NOM vdso - Presentation de l'objet partage dynamique ELF virtuel SYNOPSIS #include void *vdso = (uintptr_t) getauxval(AT_SYSINFO_EHDR); DESCRIPTION Le << vDSO >> (objet partage dynamique virtuel, << virtual dynamic shared object >>) est une petite bibliotheque partagee 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-memes de ces details puisque le vDSO est d'habitude appele par la bibliotheque C. Ainsi, vous pouvez ecrire du code normalement en utilisant les fonctions standards et la bibliotheque C s'occupera d'utiliser toutes les fonctionnalites disponibles par l'intermediaire du vDSO. Pourquoi le vDSO existe ? Certains appels systeme fournis par le noyau finissent par etre utilises frequemment par le code en espace utilisateur, au point que ces appels peuvent avoir une emprise excessive sur les performances. C'est a la fois du a la frequence des appels qu'aux nombreux changements de contexte a force de sortir de l'espace utilisateur pour entrer dans le noyau. La suite de cette documentation est orientee pour les curieux et les auteurs de la bibliotheque C plutot que pour les developpeurs generaux. Si vous essayez d'appeler le vDSO dans vos propres applications plutot que d'utiliser la bibliotheque C, vous faites sans doute fausse route. Contexte exemple Realiser des appels systeme peut etre lent. Dans les systemes 32 bits x86, vous pouvez declencher une interruption logicielle (int $0x80) pour indiquer au noyau que vous voulez faire un appel systeme. Cependant, cette instruction est couteuse : 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 retrocompatibles) pour initier les appels systeme. Plutot que forcer la bibliotheque C a verifier si cette fonctionnalite est disponible au moment de l'execution, la bibliotheque C peut utiliser les fonctions fournies par le noyau dans le vDSO. Remarquez que cette terminologie peut etre source de confusion. Sur les systemes x86, la fonction vDSO utilisee pour determiner la methode preferee pour realiser un appel systeme est appelee << __kernel_vsyscall >> alors que sous x86_64, le terme << vsyscall >> se refere aussi a une facon obsolete de demander au noyau l'heure ou le processeur sur lequel est l'appelant. Un appel systeme frequemment utilise est gettimeofday(2). Cet appel systeme est appele a la fois directement par les applications en espace utilisateur et indirectement par la bibliotheque C. Remarquez que les horodatages, boucles temporelles ou scrutations -- ont tous frequemment 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 meme reponse. Alors le noyau s'arrange pour que les informations necessaires pour repondre a cette question soient placees dans la memoire accessible au processus. Ainsi un appel de gettimeofday(2) est transforme d'un appel systeme en un appel normal de fonction, avec peu d'acces memoire. Trouver le vDSO L'adresse de base du vDSO (s'il existe) est passee par le noyau a tous les programmes dans le vecteur auxiliaire initial (consultez getauxval(3)) a l'aide de l'indicateur AT_SYSINFO_EHDR. Vous ne devez pas supposer que le vDSO est projete a un endroit particulier de la projection en memoire de l'utilisateur. L'adresse de base sera normalement aleatoire au moment de l'execution a chaque fois qu'une nouvelle image de processus est creee (au moment de execve(2)). C'est ainsi pour des raisons de securite, afin d'eviter les attaques de << retour vers libc >>. Pour certaines architectures, un indicateur AT_SYSINFO est aussi present. Il n'est utilise que pour localiser le point d'entree vsyscall et est souvent omis ou defini a 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 etre evitee. Format de fichier Puisque le vDSO est une image ELF complete, vous pouvez y rechercher des symboles. Cela permet d'ajouter de nouveaux symboles avec les versions de noyau plus recentes et permet a la bibliotheque C de detecter les fonctionnalites disponibles au moment de l'execution lors de l'execution sous differentes versions de noyau. D'habitude, la bibliotheque C fera la detection lors du premier appel puis mettra en cache le resultat pour les appels suivants. Tous les appels sont aussi versionnes (en utilisant le format de version GNU). Cela permet au noyau de mettre a jour la signature de fonction sans casser la retrocompatibilite. Cela signifie modifier les arguments acceptes 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 a l'ABI attendue. Typiquement, le vDSO suit la convention de nommage de prefixer tous les symboles par << __vdso_ >> ou << __kernel_ >> afin de les distinguer des autres symboles standards. Par exemple, la fonction << gettimeofday >> est nommee << __vdso_gettimeofday >>. Utilisez les conventions d'appel C standard pour appeler n'importe laquelle de ces fonctions. Pas la peine de vous embeter avec les registres bizarres ou les comportements de pile. NOTES Source Lors de la compilation du noyau, le code vDSO est compile et lie automatiquement. Il se trouve souvent dans le repertoire specifique a l'architecture : find arch/$ARCH/ -name '*vdso*.so*' -o -name '*gate*.so*' Noms vDSO Le nom du vDSO depend 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 systeme avec strace(1), les symboles (appels systeme) qui sont exportes par le vDSO n'apparaitront pas dans la sortie du suivi. De meme, ces appels systeme ne seront pas visibles par les filtres seccomp(2). NOTES SPECIFIQUES AUX ARCHITECTURES Les sous-sections suivantes fournissent des notes specifiques aux architectures sur le vDSO. Remarquez que le vDSO utilise est base sur l'ABI du code en espace utilisateur et non sur l'ABI du noyau. Ainsi, par exemple, si vous executez un binaire ELF 32 bits i386, vous obtiendrez le meme vDSO que vous l'executiez avec un noyau 32 bits i386 ou avec un noyau 64 bits x86_64. Par consequent, le nom de l'ABI en espace utilisateur devrait etre utilise pour determiner la section suivante adequate. Fonctions ARM Le tableau suivant indique les symboles exportes 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 extremement detaillee et couvre tous ce que vous devez savoir : Documentation/arm/kernel_user_helpers.rst. Fonctions aarch64 Le tableau suivant indique les symboles exportes 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 supprime dans Linux 4.17) Comme ce processeur n'a pas d'unite de gestion memoire (MMU), il ne definit pas de vDSO au sens usuel. A la place, il projette au demarrage quelques fonctions brutes a un endroit specifique de la memoire. Les applications en espace utilisateur appellent ensuite directement dans cette zone. Aucune mesure de retrocompatibilite n'est prise a part en sniffant les codes operatoires bruts, mais comme il s'agit d'un processeur embarque, il peut s'en sortir impunement - certains formats d'objet qu'il execute ne sont meme pas bases 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 exportes 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 exportes 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 perilleux. En plus du vDSO ci-dessus, il a aussi des << appels systeme legers >> (aussi appeles << appels systeme rapides >> ou << fsys >>). Ils peuvent etre appeles a l'aide de l'assistant vDSO __kernel_syscall_via_epc. Les appels systeme indiques ici ont la meme semantique que si vous les appeliez directement a l'aide de syscall(2), donc consultez la documentation adequate pour chacun d'entre eux. Le tableau suivant indique les fonctions disponibles par ce mecanisme. fonction ---------------- clock_gettime getcpu getpid getppid gettimeofday set_tid_address Fonctions parisc (hppa) Le portage parisc a une page de code pleine de fonctions utilitaires appelee une page passerelle. Plutot que d'utiliser l'approche classique du vecteur auxiliaire ELF, il passe l'adresse de la page au processus a l'aide du registre SR2. Les permissions sur la page sont telles qu'executer simplement ces adresses s'execute 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 adequate a l'aide de l'instruction de branche, par exemple : ble (%sr2, %r0) offset fonction ----------------------------------------------------- 00b0 lws_entry (operations CAS) 00e0 set_thread_pointer (utilise par la glibc) 0100 linux_gateway_entry (syscall) Fonctions ppc/32 Le tableau suivant indique les symboles exportes par le vDSO. Les fonctions marquees 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_clock_gettime64 LINUX_5.11 __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 Avant Linux 5.6, 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 a l'appel systeme reel. Fonctions ppc/64 Le tableau suivant indique les symboles exportes 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 Avant Linux 4.16, 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 a l'appel systeme reel. Fonctions riscv Le tableau suivant indique les symboles exportes par le vDSO. symbole version ---------------------------------- __vdso_rt_sigreturn LINUX_4.15 __vdso_gettimeofday LINUX_4.15 __vdso_clock_gettime LINUX_4.15 __vdso_clock_getres LINUX_4.15 __vdso_getcpu LINUX_4.15 __vdso_flush_icache LINUX_4.15 Fonctions s390 Le tableau suivant indique les symboles exportes 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 exportes 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 exportes 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 exportes 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 exportes par le vDSO. Tous ces symboles sont aussi disponibles sans le prefixe << __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 exportes 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'etait a l'origine qu'une seule fonction -- le vsyscall. Dans les anciens noyaux, ce nom pourrait etre vu dans une projection en memoire de processus a la place de << vdso >>. Le temps passant, les gens ont realise que ce mecanisme etait un excellent moyen pour passer plus de fonctionnalites a l'espace utilisateur, il a donc ete reconcu 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.rst Documentation/vDSO/* (contient des exemples d'utilisation du vDSO) find arch/ -iname '*vdso*' -o -iname '*gate*' TRADUCTION La traduction francaise de cette page de manuel a ete creee par Christophe Blaess , Stephan Rafin , Thierry Vignaud , Francois Micaux, Alain Portal , Jean-Philippe Guerard , Jean-Luc Coulon (f5ibh) , Julien Cristau , Thomas Huriaux , Nicolas Francois , Florentin Duneau , Simon Paillard , Denis Barbier , David Prevot et Jean-Paul Guillonneau Cette traduction est une documentation libre ; veuillez vous reporter a la GNU General Public License version 3 concernant les conditions de copie et de distribution. Il n'y a aucune RESPONSABILITE LEGALE. Si vous decouvrez un bogue dans la traduction de cette page de manuel, veuillez envoyer un message a . Pages du manuel de Linux 6.8 2 mai 2024 vDSO(7)