2 votes

Comprendre le syscall Linux simple dans libc.a

Je suis en train de faire un 64-bit Debian 4.7.2-5 Linux en utilisant glibc-2.13-1 . Alors que je recherchais le code d'assemblage de certains appels de fonction dans libc.a Je suis tombé sur ça :

file format elf64-x86-64

Disassembly of section .text:

0000000000000000 <sync>:
   0:   b9 a2 00 00 00        mov    eax,0xa2
   5:   0f 05                 syscall
   7:   48 3d 01 f0 ff ff     cmp    rax,0xfffffffffffff001
   d:   0f 83 00 00 00 00     jae    13 <sync+0x13>
  13:   c3                    ret

Je suis un peu confus sur ce que cela fait. Quel est l'intérêt de mov eax,0xa2 et pourquoi le rax utilisé s'il s'agit d'une machine 64 bits (comment syscall sait-il quel appel système effectuer) ? En bref : que font ces 5 lignes de code ?

5voto

Igor Skochinsky Points 13292

0xa2 est le numéro de syscall. Le noyau l'utilise pour décider de la fonction réelle à exécuter, puisque la fonction syscall L'instruction elle-même ne contient aucune information.

Quant à rax il fait être utilisé. Pour continuer la tradition commencée dans les anciens jours, les eax est un alias pour les 32 bits inférieurs de rax . Cependant, il existe une particularité peu connue de l'architecture x64 : chaque fois que vous modifiez la partie basse de 32 bits, les 32 bits supérieurs être mis à zéro . Donc, en fait mov eax, 0xa2 est équivalent à mov rax, 0xa2 sauf que son encodage est plus court. NASM, ou as -O2 se chargera même de l'optimisation pour vous.

Les trois dernières instructions effectuent la gestion des erreurs. Dans le cas %rax est comprise entre -1 et -4095, cela signifie que la syscall a renvoyé une erreur, pour tout Appel système Linux. Voici comment cela se présente dans la source originale :

cmpq $-4095, %rax    /* Check %rax for error.  */
jae __syscall_error  /* Branch forward if it failed.  */
ret                  /* Return to caller.  */

Vous voyez la mauvaise cible pour le jae parce que vous désassemblez un objet relocalisable, et les champs relocalisables ont été mis à 0 car ils seront corrigés au moment de la liaison finale.

Pour voir les cibles de relocalisation, ajouter -r passer à objdump ligne de commande :

0000000000000000 <sync>:
   0:   b8 a2 00 00 00          mov    $0xa2,%eax
   5:   0f 05                   syscall 
   7:   48 3d 01 f0 ff ff       cmp    $0xfffffffffffff001,%rax
   d:   0f 83 00 00 00 00       jae    13 <sync+0x13>
                        f: R_X86_64_PC32        __syscall_error-0x4
  13:   c3                      retq   

Vous pouvez voir que les octets à l'offset f sera corrigé de façon à ce que le saut aille vers __syscall_error .

Lire https://cs.lmu.edu/~ray/notes/syscalls/ pour plus d'informations sur les syscalls.
Aussi Le guide définitif des appels système de Linux article de blog.

1voto

nrz Points 6599

mov eax,0xa2 est suffisant pour mettre l'ensemble de la rax car la modification des registres généraux 32 bits tels que eax met toujours à zéro les 32 bits supérieurs du registre 64 bits correspondant (dans ce cas, il s'agit de rax ).

Numéro Syscall a2 es sync voir /usr/src/linux/usr/include/asm/unistd_64.h pour la liste des syscalls de Linux x86-64 (remplacez /usr/src/linux/ avec le répertoire où vous avez installé votre source Linux).

Dans l'ensemble, ces lignes ouvrent un fichier déjà défini avant ces instructions, puis comparent la valeur de retour de syscall (en rax ) avec 0xfffffffffffff001 et puis il y a quelque chose d'un peu étrange : 0f 83 00 00 00 00 jae 13 est un saut conditionnel vers l'instruction suivante, qui serait atteinte de toute façon.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X