Vous avez l'erreur suivante lorsque j'ai essayé de compiler une application C dans FreeBSD 64 bits:
la relocalisation R_X86_64_32S ne peut pas être utilisée lors de la création d'un objet partagé; recompiler avec -fPIC
Quel est R_X86_64_32S
relocalisation et qu'est-ce que R_X86_64_64
?
J'ai cherché sur Google l'erreur, et ses causes possibles - Ce serait génial si quelqu'un pouvait dire ce que R_X86_64_32S signifie vraiment.
Le R_X86_64_32S
et R_X86_64_64
sont des noms de types de relocalisation, pour le code compilé pour l'architecture AMD64. Vous pouvez tous les rechercher dans le AMD64 ABI . Selon elle, R_X86_64_64
se décompose en:
et R_X86_64_32S
à:
ce qui signifie essentiellement "la valeur du symbole pointé par cette relocalisation, plus tout ajout", dans les deux cas. Pour R_X86_64_32S
l'éditeur de liens vérifie ensuite que la valeur générée signe-s'étend à la valeur 64 bits d'origine.
Maintenant, dans un fichier exécutable, le code et les segments de données reçoivent une adresse de base virtuelle spécifiée. Le code exécutable n'est pas partagé et chaque exécutable obtient son propre espace d'adressage frais. Cela signifie que le compilateur sait exactement où se trouvera la section de données et peut la référencer directement. Les bibliothèques, en revanche, ne peuvent savoir que leur section de données sera à un décalage spécifié par rapport à l'adresse de base; la valeur de cette adresse de base ne peut être connue qu'au moment de l'exécution. Par conséquent, toutes les bibliothèques doivent être produites avec du code qui peut s'exécuter peu importe où il est mis en mémoire, connu sous le nom de code indépendant de la position (ou PIC pour faire court).
Maintenant, lorsqu'il s'agit de résoudre votre problème, le message d'erreur parle de lui-même.
Pour que tout cela ait un sens, vous devez d'abord:
Normes
R_X86_64_64
, R_X86_64_32
et R_X86_64_32S
sont tous définis par le System V AMD ABI , qui contient les spécificités AMD64 du format de fichier ELF.
Ce sont toutes des valeurs possibles pour le ELF32_R_TYPE
champ d'une entrée de relocalisation, spécifié dans le System V ABI 4.1 (1997) qui spécifie les parties neutres de l'architecture du format ELF. Cette norme spécifie uniquement le champ, mais pas ses valeurs dépendantes de Arch.
Sous 4.4.1 "Types de réinstallation", nous voyons le tableau récapitulatif:
Name Field Calculation
------------ ------ -----------
R_X86_64_64 Word64 A + S
R_X86_64_32 Word32 A + S
R_X86_64_32S Word32 A + S
Nous expliquerons ce tableau plus tard.
Et la note:
Le
R_X86_64_32
etR_X86_64_32S
les relocalisations tronquent la valeur calculée à 32 bits. L'éditeur de liens doit vérifier que la valeur générée pour la relocalisation R_X86_64_32 (R_X86_64_32S) se déploie à zéro (extension de signe) à la valeur 64 bits d'origine.
Exemple de R_X86_64_64 et R_X86_64_32
Examinons d'abord R_X86_64_64
et R_X86_64_32
:
.section .text
/* Both a and b contain the address of s. */
a: .long s
b: .quad s
s:
Alors:
as --64 -o main.o main.S
objdump -dzr main.o
Contient:
0000000000000000 <a>:
0: 00 00 add %al,(%rax)
0: R_X86_64_32 .text+0xc
2: 00 00 add %al,(%rax)
0000000000000004 <b>:
4: 00 00 add %al,(%rax)
4: R_X86_64_64 .text+0xc
6: 00 00 add %al,(%rax)
8: 00 00 add %al,(%rax)
a: 00 00 add %al,(%rax)
Testé sur Ubuntu 14.04, Binutils 2.24.
Ignorez le démontage pour l'instant (ce qui n'a pas de sens car il s'agit de données) et ne regardez que les étiquettes, octets et relocalisations.
La première relocalisation:
0: R_X86_64_32 .text+0xc
Ce qui signifie:
0
: agit sur l'octet 0 (étiquette a
)R_X86_64_
: préfixe utilisé par tous les types de relocalisation du système AMD64 V ABI32
: l'adresse 64 bits de l'étiquette s
est tronquée à une adresse 32 bits car nous n'avons spécifié que .long
(4 octets).text
: nous sommes sur le .text
section0xc
: c'est le addend, qui est un champ de l'entrée de relocalisationL'adresse du déménagement est calculée comme suit:
A + S
Où:
A
: l'addend, ici 0xC
S
: la valeur du symbole avant relocalisation, ici 00 00 00 00 == 0
Par conséquent, après la relocalisation, la nouvelle adresse sera 0xC == 12 octets dans le .text
section.
C'est exactement ce que nous attendons, puisque s
vient après un .long
(4 octets) et un .quad
(8 octets).
R_X86_64_64
est analogue, mais plus simple, car ici il n'est pas nécessaire de tronquer l'adresse de s
. Ceci est indiqué par la norme par Word64
au lieu de Word32
dans la colonne Field
.
R_X86_64_32S vs R_X86_64_32
La différence entre R_X86_64_32S
contre R_X86_64_32
est lorsque l'éditeur de liens se plaindra "avec une relocalisation tronquée pour correspondre":
32
: se plaint si la valeur tronquée après la relocalisation ne prolonge pas zéro l'ancienne valeur, c'est-à-dire que les octets tronqués doivent être nuls:
Par exemple.: FF FF FF FF 80 00 00 00
à 80 00 00 00
génère une réclamation car FF FF FF FF
n'est pas nul.
32S
: se plaint si la valeur tronquée après la relocalisation ne signe étend l'ancienne valeur.
Par exemple.: FF FF FF FF 80 00 00 00
à 80 00 00 00
est très bien, car le dernier morceau de 80 00 00 00
et les bits tronqués sont tous 1.
Voir aussi: Que signifie cette erreur GCC "... relocalisation tronquée pour s'adapter ..."?
R_X86_64_32S
peut être généré avec:
.section .text
.global _start
_start:
mov s, %eax
s:
Alors:
as --64 -o main.o main.S
objdump -dzr main.o
Donne:
0000000000000000 <_start>:
0: 8b 04 25 00 00 00 00 mov 0x0,%eax
3: R_X86_64_32S .text+0x7
Nous pouvons maintenant observer la "relocalisation" tronquée pour tenir sur 32S
avec un script de l'éditeur de liens:
SECTIONS
{
. = 0xFFFFFFFF80000000;
.text :
{
*(*)
}
}
Maintenant:
ld -Tlink.ld a.o
Ça va, parce que: 0xFFFFFFFF80000000
est tronqué en 80000000
, qui est une extension de signe.
Mais si nous changeons le script de l'éditeur de liens en:
. = 0xFFFF0FFF80000000;
Il génère maintenant l'erreur, parce que 0
a fait que ce ne soit plus une extension de signe.
Justification de l'utilisation de 32S
pour l'accès à la mémoire mais 32
pour les intermédiaires: Quand est-il préférable pour un assembleur d'utiliser la relocalisation étendue de signe comme R_X86_64_32S au lieu d'une extension nulle comme R_X86_64_32?
R_X86_64_32S et PIE (positionner les exécutables indépendants
R_X86_64_32S ne peut pas être utilisé dans des exécutables indépendants de la position, par ex. fini avec gcc -pie
, sinon le lien échoue avec:
relocation R_X86_64_32S against `.text' can not be used when making a PIE object; recompile with -fPIC
l
J'ai fourni un exemple minimal l'expliquant à: Qu'est-ce que l'option -fPIE pour les exécutables indépendants de la position dans gcc et ld?
Cela signifie que compilé un objet partagé sans utiliser -fPIC
marquer comme il se doit:
gcc -shared foo.c -o libfoo.so # Wrong
Vous devez appeler
gcc -shared -fPIC foo.c -o libfoo.so # Right
Sous la plate-forme ELF (Linux), les objets partagés sont compilés avec du code indépendant de la position - code pouvant s'exécuter à partir de n'importe quel emplacement en mémoire, si cet indicateur n'est pas donné, le code généré dépend de la position, il n'est donc pas possible d'utiliser ce partage objet.
J'ai rencontré ce problème et j'ai trouvé que cette réponse ne m'a pas aidé. J'essayais de lier une bibliothèque statique à une bibliothèque partagée. J'ai également étudié la possibilité de placer le commutateur -fPIC plus tôt sur la ligne de commande (comme indiqué dans les réponses ailleurs). La seule chose qui a résolu le problème, pour moi, a été de changer la bibliothèque statique en partagée. Je soupçonne que le message d'erreur à propos de -fPIC peut se produire pour un certain nombre de causes, mais fondamentalement ce que vous voulez regarder est la façon dont vos bibliothèques sont construites et méfiez-vous des bibliothèques qui sont construites de différentes manières.
Dans mon cas, le problème est survenu parce que le programme à compiler s'attendait à trouver des bibliothèques partagées dans un répertoire distant, alors que seules les bibliothèques statiques correspondantes étaient là dans une erreur.
En fait, cette erreur de relocalisation était une erreur déguisée de fichier introuvable.
J'ai détaillé comment je m'en suis sorti dans cet autre fil https://stackoverflow.com/a/42388145/5459638