2010-08-26 41 views
13

Comme un exercice pour apprendre plus précisément comment fonctionnent les programmes c et quel niveau minimum de contenu doit exister pour qu'un programme puisse utiliser libc, j'ai pris l'initiative de programmer principalement l'assemblage x86 en utilisant gas et ld . Comme un petit défi amusant, j'ai assemblé et lié avec succès plusieurs programmes liés à différentes bibliothèques dynamiques, mais je n'ai pas réussi à coder un programme à partir de zéro pour utiliser les appels de fonction libc sans utiliser directement gcc . Je comprends les conventions d'appel des différentes fonctions de la bibliothèque c, et ai inspecté minutieusement les programmes compilés à partir de gcc en utilisant objdump et readelf, mais je n'ai rien trouvé concernant les informations à inclure dans un fichier d'assemblage de gaz et quels paramètres invoquer dans ld pour établir un lien avec libc. Quelqu'un a un aperçu de cela? Je suis sous Linux, sur un ordinateur x86.Comment lier un programme d'assemblage de gaz qui utilise la bibliothèque standard C avec ld sans utiliser gcc?

Répondre

17

Il y a au moins trois choses à faire o utiliser avec succès libc avec liaison dynamique:

  1. Lien /usr/lib/crt1.o, qui contient _start, qui sera le point d'entrée pour le fichier binaire ELF;
  2. Lien /usr/lib/crti.o (avant libc) et /usr/lib/crtn.o (après), qui fournissent un certain code d'initialisation et de finalisation;
  3. Indiquez au lieur que le binaire utilisera le lieur dynamique, /lib/ld-linux.so.

Par exemple:

$ cat hello.s 
.text 
.globl main 
main: 
push %ebp 
mov %esp, %ebp 
pushl $hw_str 
call puts 
add $4, %esp 
xor %eax, %eax 
leave 
ret 

.data 
hw_str: 
.asciz "Hello world!" 

$ as -o hello.o hello.s 
$ ld -o hello -dynamic-linker /lib/ld-linux.so.2 /usr/lib/crt1.o /usr/lib/crti.o -lc hello.o /usr/lib/crtn.o 
$ ./hello 
Hello world! 
$ 
+0

Ceci est extrêmement utile, cela clarifie beaucoup d'informations. en appliquant cela à mon code, j'obtiens 2 erreurs, "référence indéfinie à '__libc_csu_fini'" et "référence non définie à '__libc_csu_init'" après avoir fait un vidage de symbole sur tous les fichiers objet, je n'ai pas réussi à trouver les symboles, et crt1.o semble appeler les symboles. Y at-il quelque chose qui pourrait avoir ces symboles à l'intérieur de leur fichier objet? – Cyro

+0

Ceux-ci proviennent d'une partie non partagée de la bibliothèque C; Lier avec '-lc' devrait tirer dans'/usr/lib/libc.so', qui est en fait un fragment de script de l'éditeur de liens référençant le bon fichier ('/ usr/lib/libc_nonshared.a'). Peut-être un problème avec l'ordre de lien? Je suis assez sûr que vous voulez 'crt1.o' suivi par' crti.o 'd'abord, puis vos objets et bibliothèques, puis 'crtn.o' juste à la fin - mais peut-être' -lc' devrait venir après vos objets (juste avant 'crtn.o'), pas avant. –

+0

Je suis allé de l'avant et simplement lié avec /usr/lib/libc_nonshared.a juste après avoir tapé -lc et tout a fonctionné! merci un million! – Cyro

-1

Je pense que quelque chose comme cela devrait fonctionner:

  1. faire un programme simple C
  2. gcc -S file.c
  3. modifier file.s
  4. file.s de gaz
  5. ld file.o -lc crt1.o -o myprog
2

Si vous définissez main dans l'assemblage

réponse de Matthieu fait un excellent travail de vous dire les exigences minimales. Permettez-moi de vous montrer comment trouver ces chemins dans votre système. Exécuter:

gcc -v hello_world.c |& grep 'collect2' | tr ' ' '\n' 

puis de récupérer les fichiers mentionnés par Matthew.

gcc -v vous donne la commande de liaison exacte utilisée par GCC.

collect2 est l'exécutable interne que GCC utilise en tant que frontal de liaison, qui a une interface similaire à ld.

Sous Ubuntu 14.04 64 bits (GCC 4.8), je me suis retrouvé avec:

ld -dynamic-linker /lib64/ld-linux-x86-64.so.2 \ 
    /usr/lib/x86_64-linux-gnu/crt1.o \ 
    /usr/lib/x86_64-linux-gnu/crti.o \ 
    -lc hello_world.o \ 
    /usr/lib/x86_64-linux-gnu/crtn.o 

Vous pourriez aussi avoir besoin -lgcc et -lgcc_s. Voir aussi: Do I really need libgcc?

Si vous définissez _start dans l'assemblage

Si je définissais le _start, le monde bonjour de glibc a travaillé avec juste:

ld -dynamic-linker /lib64/ld-linux-x86-64.so.2 -lc hello_world.o 

Je ne sais pas si cela est robuste, c'est-à-dire si les initialisations crt peuvent être ignorées en toute sécurité pour appeler les fonctions de la glibc. Voir aussi: Why does an assembly program only work when linked with crt1.o crti.o and crtn.o?