Impossible de lier un fichier d’object à l’aide de ld – Mac OS X

/********* exit.asm */ [SECTION .text] global _start _start: xor eax, eax xor ebx, ebx mov al, 1 int 0x80 //**************************** 

J’ai d’abord utilisé nasm -f elf exit.asm pour générer le fichier object.

puis j’ai exécuté la commande “ld” suivante sur mon Mac OS X 10.7, il contient ces sorties et cet avertissement, j’ai essayé de l’exécuter sur ma machine Linux 32 bits, tout s’est passé sans problème, pourriez-vous expliquer pourquoi ne le ferait-on pas? linker fonctionne sur mon Mac?

Je vous remercie!

 Alfred says: ld -o exiter exit.o ld: warning: -arch not specified ld: warning: -macosx_version_min not specified, assuming 10.7 ld: warning: ignoring file exit.o, file was built for unsupported file format ( 0x7f 0x45 0x4c 0x46 0x 1 0x 1 0x 1 0x 0 0x 0 0x 0 0x 0 0x 0 0x 0 0x 0 0x 0 0x 0 ) which is not the architecture being linked (x86_64): exit.o Undefined symbols for architecture x86_64: "start", referenced from: implicit entry/start for main executable ld: symbol(s) not found for inferred architecture x86_64 

après avoir spécifié ma voûte et sa version, j’ai obtenu:

 Alfred says: ld -arch x86_64 -macosx_version_min 10.7 -o exiter exit.o ld: warning: ignoring file exit.o, file was built for unsupported file format ( 0x7f 0x45 0x4c 0x46 0x 1 0x 1 0x 1 0x 0 0x 0 0x 0 0x 0 0x 0 0x 0 0x 0 0x 0 0x 0 ) which is not the architecture being linked (x86_64): exit.o Undefined symbols for architecture x86_64: "start", referenced from: implicit entry/start for main executable ld: symbol(s) not found for architecture x86_64 

    Obtenir la liaison du programme est la partie la plus facile:

    • Changer _start pour start
    • $ nasm -f macho exit.asm
    • $ ld -arch i386 -o exiter exit.o

    Le problème est que exit.asm appelle l’appel système ( EAX = 1) de Linux exit() i386 Linux et que le programme ne se fermerait PAS avec un statut zéro comme prévu sur OS X.

    Appels système

    Un appel système est une requête adressée au kernel. exit() , contrairement à sqrt() , doit implémenter une demande à un composant logiciel doté de privilèges plus élevés dans la mesure où il met fin à un programme en cours d’exécution. Les applications ne peuvent pas créer ou mettre fin à des processus par elles-mêmes. Les appels système fournissent aux applications un moyen de demander au kernel d’effectuer des actions pour leur compte.

    Faire un appel système ressemble à ceci:

    • Les applications décrivent l’opération qu’elles souhaitent effectuer en plaçant les données dans des registres de la CPU (ou de la mémoire pointée par les registres), par exemple:
      • La valeur 1 dans EAX est le numéro d’appel système de l’ exit .
      • La valeur 0 dans EBX ( EBX a été effacé par xor ) est le premier argument de l’appel système, l’état de sortie.
    • Les applications émettent une instruction qui entraîne le transfert du contrôle vers le kernel, par exemple:
      • int 80 sur i386
      • sycall sur x86-64
      • svc en mode pouce sur ARMv7
    • Le kernel inspecte la requête et décide de l’exécuter ou de la refuser.
    • Le kernel renvoie le contrôle à l’application avec la valeur de retour dans un emplacement convenu, par exemple EAX sur i386.

    Linux et OS X fournissent tous deux une fonction void exit(int) pour les programmes C mais ne s’entendent pas sur les détails pour décrire cette requête au kernel. Le code dans exit.asm est au même niveau que l’implémentation de la fonction _exit() dans libc .

    Même entre les différentes architectures fonctionnant sous Linux, les numéros d’appel système et les conventions d’appel diffèrent. Par exemple, sur x86-64 Linux, exit(0) est plus communément émis comme ceci:

     xor rdi, rdi mov al, 60 syscall 

    Vous pouvez le voir en désassemblant _exit dans /lib64/libc.so.6 .

    Ne pouvons-nous pas simplement appeler exit () à partir de la libc?

    Vous pouvez. Mais vous devez lier le programme avec libc . C’est la différence entre lier exit.asm ci-dessus avec:

     $ cc -m32 -nostdlib exit.o -o exiter 

    et

    exit-libc.asm

     extern exit global main main: push 0 call exit 

    qui doit être lié avec:

     $ cc -m32 exit-libc.o -o exit-libc 

    Essayez ceci et regardez la taille du fichier.

    Mac OS X n’utilisant pas ELF, vous voudrez donc générer un object Mach-O avec lequel vous souhaitez établir une liaison sur ce système. Sur ma machine, nasm semble prendre en charge que la sortie 32 bits, vous devez donc également nasm cette architecture lors de la liaison.

    Je devais aussi changer _start pour start à le relier.

    Voici un exemple de travail avec votre code:

     $ cat exit.asm [SECTION .text] global start start: xor eax, eax xor ebx, ebx mov al, 1 int 0x80 $ nasm -f macho exit.asm $ ld -arch i386 -macosx_version_min 10.7 -o exiter exit.o $ ./exiter $ echo $? 236 

    Notez que le programme ne fait probablement pas ce que vous voulez sur Mac OS X, car il ne fait pas les appels système de la même manière que Linux.

    La plupart du temps, lorsque vous recevez cette erreur:

     ld: warning: PIE disabled. Absolute addressing (perhaps -mdynamic-no-pic) not allowed in code signed PIE, but used in _start from hello.o. To fix this warning, don't comstack with -mdynamic-no-pic or link with -Wl,-no_pie 

    C’est parce qu’il recherche votre fonction “main ()” (label) pour moi le label “start:”. Il est toujours préférable de spécifier le libellé principal avec “ld -e”.

    Pour nasm:

     -o hello.tmp - outfile -f macho - specify format Linux - elf or elf64 Mac OSX - macho 

    Pour ld:

     -arch i386 - specify architecture (32 bit assembly) -macosx_version_min 10.6 (Mac OSX - complains about default specification) -no_pie (Mac OSX - removes ld warning) -e main - specify main symbol name (Mac OSX - default is start) -o hello.o - outfile 

    Pour Shell:

     ./hello.o - execution 

    Bon mot:

     nasm -o hello.tmp -f macho hello.s && ld -arch i386 -macosx_version_min 10.6 -no_pie -e _main -o hello.o hello.tmp && ./hello.o 

    Faites-moi savoir si cela aide!

    J’ai écrit comment faire sur mon blog ici:

    http://blog.burrowsapps.com/2013/07/how-to-comstack-helloworld-in-intel-x86.html

    Pour une explication plus détaillée, j’ai expliqué sur mon Github ici:

    https://github.com/jaredsburrows/Assembly

    Le mac standard gcc ne liera pas les objects elf. Pour ceux qui ont besoin de restr avec le format elf et de développer sur un mac, vous avez besoin d’un compilateur croisé …

    http://crossgcc.rts-software.org/doku.php?id=compiling_for_linux

    Ensuite, vous pouvez procéder avec quelque chose de similaire à ceci …

     /usr/local/gcc-4.8.1-for-linux32/bin/i586-pc-linux-ld -m elf_i386 -T link.ld -o kernel kasm.o kc.o