2017-09-08 1 views
1

Il s'agit d'un problème qui n'a jamais été rencontré. Je suis assez convaincu que c'est probablement un problème avec mes dépôts de paquets (j'ai récemment réinstallé mon système Arch et cela ne fait que commencer).L'assemblage avec GCC provoque une erreur de relocalisation étrange en ce qui concerne .data

j'ai écrit un petit monde bonjour en x86_64:

.data 
str: .asciz "Test" 

.text 
.globl main 
main: 
    sub $8, %rsp 
    mov $str, %rdi 
    call puts 
    add $8, %rsp 
    ret 

puis je tente de montage et lien en utilisant GCC - comme je l'ai fait à plusieurs reprises dans le passé - avec, tout simplement:

gcc test.s -o test

et cette erreur est émis:

/usr/bin/ld: /tmp/ccAKVV4D.o: relocation R_X86_64_32S against `.data' can not be used when making a shared object; recompile with -fPIC /usr/bin/ld: final link failed: Nonrepresentable section on output collect2: error: ld returned 1 exit status

cette erreur n'a jamais eu lieu pour moi jamais. J'ai essayé de résoudre le problème en recherchant le même message d'erreur, mais il arrive avec des choses qui sont si spécifiques alors que je considère cela comme un problème général. J'ai essayé de réinstaller base-devel et l'ensemble de la chaîne d'outils GCC. Je ne sais pas ce que je peux faire d'autre (s'il vous plaît ne suggère pas d'utiliser nasm, c'est hérésie). Je voudrais penser qu'il me manque quelque chose d'évident mais j'ai utilisé GCC pour mes besoins d'assemblage depuis longtemps.

+0

Je suis un peu sûr que c'est un doublon, mais je vais le chercher plus tard, donc juste un bref résumé de ce qui se passe. Il y a quelque temps, Debian a basculé sur les binaires PIC/PIE en mode 64b (comme OS X le fait déjà depuis un certain temps, et maintenant d'autres distributions suivent), donc les valeurs par défaut pour toolchain ont été modifiées, et le 'gcc' dans votre cas essayer de lier votre objet en tant que PIC, mais il rencontrera l'adresse absolue dans 'mov $ str,% rdi'. Vous devriez donc soit réécrire votre code pour qu'il soit «rip» relatif partout, soit il y a probablement un moyen de configurer le lien gcc pour appliquer l'ancienne liaison non-PIC de l'exécutable. – Ped7g

+0

Merci pour la perspicacité @ Ped7g Je vais y jeter un coup d'oeil – oldjohn1994

+4

Vous utilisez probablement une version plus récente/différente d'Arch Linux qui a GCC compiler du code 64 bits comme relocalisable par défaut. La meilleure façon de gérer cela est de modifier votre code pour utiliser l'adressage RIP (relatif au pointeur d'instruction). CHangez votre 'mov' à' lea str (% rip),% rdi' et lorsque vous appelez la bibliothèque _C_, utilisez 'call puts @ plt' au lieu de' call puts'. –

Répondre

3

La façon de contourner cette erreur est de générer un no-pie (non Position exécutable indépendant) exécutable:

gcc -no-pie test.s -o test 

La raison de ce comportement est comme expliqué par @ Ped7g:

Debian mis à PIC/Binaires PIE en mode 64 bits & GCC dans votre cas tente de lier votre objet en tant que PIC, mais il rencontre l'adresse absolue en mov $str, %rdi.

+2

Il utilise Arch dans ce cas, mais c'est la même chose pour Debian. l'adresse de la chaîne n'est pas le seul problème. Les appels à la bibliothèque _C_ doivent également être modifiés. –

+0

@MichaelPetch: '-no-pie' corrige tout, et transforme' call puts' en 'call puts @ plt' pour vous. Vous avez seulement besoin de modifier les instructions 'call' si vous voulez que cela fonctionne dans un PIE. Plus précisément, 'call * met @ GOTPCREL (% rip)' si compilant avec 'gcc -fno-plt' (liaison dynamique non-paresseuse pour éviter un PLT exécutable + modifiable, et éviter toute indirection supplémentaire), ou' call puts @ PLT' pour la manière par défaut. (Ou 'call puts @ plt' fonctionne aussi, le compilateur émet un PLT majuscule lors de la compilation de C.) –