pqy@localhost ~/src/test/a $ cat lib.c int fun() { return 5; } pqy@localhost ~/src/test/a $ cat m.c #include <stdio.h> __attribute__((weak)) int fun() { return 8; } int main(void){ printf("%d\n", fun()); return 0; } pqy@localhost ~/src/test/a $ gcc lib.c -fPIC -shared -o libb.so;gcc m.c -O0 -o m -L. -lb -Wl,-rpath=$PWD;./m 8 pqy@localhost ~/src/test/a $ ldd m linux-vdso.so.1 (0x00007ffd819ec000) libb.so => /home/pqy/src/test/a/libb.so (0x00007f7226738000) libc.so.6 => /lib64/libc.so.6 (0x00007f7226533000) /lib64/ld-linux-x86-64.so.2 (0x00007f7226744000) pqy@localhost ~/src/test/a $
3 Réponses :
Le symbole est résolu à l'étape de liaison, pendant l'étape de liaison, seul le symbole faible aaaaa = 8
est visible.
Si le symbole peut être résolu à l'étape de liaison, il ne le sera pas générer une entrée de relocalisation, alors rien ne se passera au stade du chargement
Il n'y a pas de aaaaa
dans la table de relocalisation:
% objdump -R m m: file format elf64-x86-64 DYNAMIC RELOCATION RECORDS OFFSET TYPE VALUE 0000000000003dc8 R_X86_64_RELATIVE *ABS*+0x0000000000001130 0000000000003dd0 R_X86_64_RELATIVE *ABS*+0x00000000000010f0 0000000000004028 R_X86_64_RELATIVE *ABS*+0x0000000000004028 0000000000003fd8 R_X86_64_GLOB_DAT _ITM_deregisterTMCloneTable 0000000000003fe0 R_X86_64_GLOB_DAT __libc_start_main@GLIBC_2.2.5 0000000000003fe8 R_X86_64_GLOB_DAT __gmon_start__ 0000000000003ff0 R_X86_64_GLOB_DAT _ITM_registerTMCloneTable 0000000000003ff8 R_X86_64_GLOB_DAT __cxa_finalize@GLIBC_2.2.5 0000000000004018 R_X86_64_JUMP_SLOT printf@GLIBC_2.2.5
p >
Je crée également un lien avec libb.so, qui a aaaaa = 5, pourquoi aaaa = 5 n'est pas visible au stade du lien?
@MrPang Le symbole est lié à la définition , la bibliothèque partagée ne fournit que la déclaration , seuls l'objet réel et la bibliothèque statique fournissent des définitions. la bibliothèque partagée fournit des définitions au stade du chargement.
Au fond, ce que vous avez observé ici est simplement le fait que l'éditeur de liens ne résoudre un symbole de manière dynamique s'il peut le résoudre de manière statique. Voir:
main.c
$ gcc -o prog main.o static_foo.o libfoo.so static_strong_foo.o -Wl,-rpath=$PWD static_strong_foo.o: In function `foo': static_strong_foo.c:(.text+0x0): multiple definition of `foo' static_foo.o:static_foo.c:(.text+0x0): first defined here collect2: error: ld returned 1 exit status
dynamic_foo.c
$ ./prog foo (static strong) need_dynamic_foo need_static_foo
Le compilateur ou l'éditeur de liens construit les fichiers à partir de la ligne de commande dans l'ordre inverse. En d'autres termes, les fichiers avec ((faible)) doivent être situés plus tôt dans la ligne de commande que les fichiers dynamiques.
Que montre
ldd ./m
? Affiche-t-illibb.so
en cours de chargement?Oui. libb.so a été chargé
Je pense qu'il existe plusieurs définitions de la variable. Chaque unité de traduction ne voit que sa propre copie.
main
voit le fort et le faible voit le faible. Vous devriez probablement réexécuter vos tests avec une variable globale déclaréeextern
dans toutes les unités de traduction. Voir également Comment faire fonctionner les liens faibles avec GCC? , Pourquoi une variable globale non initialisée est un symbole faible? et Symboles forts et faibles dans GCC