4
votes

__attribute__ ((faible)) ne fonctionne pas pour la variable globale

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 commentaires

Que montre ldd ./m ? Affiche-t-il libb.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ée extern 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


3 Réponses :


0
votes

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 >


2 commentaires

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.



3
votes

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


0 commentaires

0
votes

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.


0 commentaires