2017-06-02 12 views
1

J'écris en assembleur et j'essaie de comprendre comment exécuter un appel système execve, mais au lieu d'avoir la sortie imprimée sur le terminal, j'aimerais savoir où il est stocké pour pouvoir l'utiliser plus tard, un peu comme les commandes de tuyauterie.Comment renvoyer la sortie d'un appel système syscall à un registre ou à la pile après l'avoir exécuté dans l'assembly?

Par exemple, l'assemblage est ici pour exécuter la commande « qui » via exec, essentiellement l'exécution de la commande « $ qui ls »:

GLOBAL _start 
SECTION .TEXT 

_start: 
    XOR   EAX,EAX 
    PUSH  EAX 
    PUSH  0x68636968 
    PUSH  0x772f6e69 
    PUSH  0x622f7273 
    PUSH  0x752f2f2f 
    MOV   EBX, ESP 
    PUSH  EAX 
    PUSH  0x736c 
    MOV   ESI, ESP 
    XOR   EDX, EDX 
    PUSH  EDX 
    PUSH  ESI 
    PUSH  EBX 
    MOV   ECX, ESP 
    MOV   AL, 0x0B; EXECVE SYSCALL NUMBER 
    INT   0x80 

lignes 7-10 pousser l'adresse de /usr/bin/which sur la pile, et La ligne 13 pousse l'argument ls sur la pile. Il pousse ensuite le tableau d'arguments sur la pile et stocke celui dans l'ECX, a l'EBX pointant vers l'adresse de l'emplacement de /usr/bin/which, et l'EAX est mis au numéro de syscall 0xb (11) pour le syscall execve. Lorsqu'il est exécuté, il renvoie /bin/ls, l'emplacement de ls que nous lui avons demandé de trouver.

Comment stocker ce résultat de /bin/ls quelque part pour une autre utilisation? Comme si je voulais continuer à écrire du code et utiliser ce qui est retourné ici comme une partie du code suivant, comment garder la valeur retournée dans un registre ou dans la pile?

+0

Possible duplication de [Redirection de la sortie exec vers un tampon ou un fichier] (https://stackoverflow.com/questions/2605130/redirecting-exec-output-to-a-buffer-or-file). –

+0

execve ne retourne pas sauf s'il échoue. – stark

Répondre

0

Fondamentalement, vous devez faire une variante de celle-ci:

  1. Utilisez l'appel système pipe() pour faire un fifo.
  2. fork() d'un processus enfant. Dans le parent, cela renvoie l'ID de processus de l'enfant dont vous devez vous souvenir. Chez l'enfant, cela renvoie zéro.
  3. Dans le parent, fermez l'extrémité d'écriture du fifo, chez l'enfant fermez l'extrémité de lecture.
  4. Dans l'enfant, utilisez dup2() pour déplacer l'extrémité d'écriture du canal vers le descripteur de fichier 1. Puis fermez le descripteur de fichier d'origine du canal. Dans l'enfant, execve le programme que vous souhaitez exécuter. Notez que execve remplace le processus actuel par une nouvelle image, donc je ne suis pas sûr de la manière dont vous vous attendiez à ce que votre programme précédent fonctionne.
  5. Dans le parent, lisez à partir du canal jusqu'à ce que vous rencontriez EOF (par exemple read() renvoie zéro). Ce que vous lisez est la sortie standard de l'enfant. Stocker cette sortie dans un tampon.
  6. Enfin, utilisez wait() pour collecter le statut de sortie de l'enfant. Si vous ne le faites pas, l'enfant mort s'attardera dans la table de processus en tant que zombie, prenant des ressources.

Au lieu d'un tube, vous pouvez également écrire un fichier à open(). Cela a l'avantage que vous pouvez utiliser fstat() pour savoir combien de sortie le processus a écrit. Cependant, vous devez ensuite implémenter une logique similaire à la fonction tmpfile pour créer et ouvrir un fichier temporaire.