Je vois que personne n'a répondu à cette question, alors je vais essayer.
Je vais essayer de montrer comment cela fonctionne au moyen d'un exemple pratique. Voici un certain code C, qui a un mélange artificiel mais intentionnel de fonctions et de données globales externes - le pain et le beurre des relocalisations.
/* hello.c */
char* hello = "hello";
/* say.c */
#include "stdio.h"
extern char* hello;
void say(void){
printf(hello);
}
/* main.c */
extern void say(void);
void please_say(void){
say();
}
int main(void){
please_say();
return 0;
}
Maintenant, la manière habituelle pour obtenir un objet partagé/bibliothèque serait de compiler chaque fichier C avec -fPIC et relier le lot avec -shared. Après que nous faisons cela, nous pouvons utiliser readelf pour examiner les relocalisations. Quelque chose comme ceci:
gcc -fPIC -c *.c
gcc -shared -o libtemp.so *.o
readelf -r libtemp.so
Les données de déplacement se présente comme suit:
Relocation section '.rel.dyn' at offset 0x34c contains 6 entries:
Offset Info Type Sym.Value Sym. Name
000016dc 00000008 R_386_RELATIVE
000016e0 00000008 R_386_RELATIVE
000016ac 00000106 R_386_GLOB_DAT 00000000 __gmon_start__
000016b0 00000206 R_386_GLOB_DAT 00000000 _Jv_RegisterClasses
000016b4 00000d06 R_386_GLOB_DAT 000016e0 hello
000016b8 00000406 R_386_GLOB_DAT 00000000 __cxa_finalize
Relocation section '.rel.plt' at offset 0x37c contains 5 entries:
Offset Info Type Sym.Value Sym. Name
000016c8 00000107 R_386_JUMP_SLOT 00000000 __gmon_start__
000016cc 00000507 R_386_JUMP_SLOT 000004fc please_say
000016d0 00000807 R_386_JUMP_SLOT 00000540 say
000016d4 00000307 R_386_JUMP_SLOT 00000000 printf
000016d8 00000407 R_386_JUMP_SLOT 00000000 __cxa_finalize
L'élément R_386_GLOB_DAT pour bonjour est une entrée GOT. De même, les éléments R_386_JUMP_SLOT pour say, please_say et printf sont des entrées PLT. Ils proviennent de l'utilisation de code indépendant de la position, pas du fait que nous avons fait un objet partagé. Après avoir fait le même processus de construction sans -fPIC, nous obtenons des relocalisations différentes. Alors
gcc -c *.c
gcc -shared -o libtemp.so *.o
readelf -r libtemp.so
nous donne
Relocation section '.rel.dyn' at offset 0x34c contains 9 entries:
Offset Info Type Sym.Value Sym. Name
00001674 00000008 R_386_RELATIVE
00001678 00000008 R_386_RELATIVE
000004d3 00000802 R_386_PC32 000004f0 say
000004e0 00000502 R_386_PC32 000004cc please_say
000004f7 00000d01 R_386_32 00001678 hello
000004ff 00000302 R_386_PC32 00000000 printf
00001654 00000106 R_386_GLOB_DAT 00000000 __gmon_start__
00001658 00000206 R_386_GLOB_DAT 00000000 _Jv_RegisterClasses
0000165c 00000406 R_386_GLOB_DAT 00000000 __cxa_finalize
Relocation section '.rel.plt' at offset 0x394 contains 2 entries:
Offset Info Type Sym.Value Sym. Name
0000166c 00000107 R_386_JUMP_SLOT 00000000 __gmon_start__
00001670 00000407 R_386_JUMP_SLOT 00000000 __cxa_finalize
Maintenant l'objet partagé déménagements familiers pour toutes les définitions. Il y a une relocalisation absolue de bonjour, et des relocations relatives PC pour les fonctions.
Qu'est-ce que cela signifie? Eh bien, les tables GOT et PLT sont toujours là. Il y a deux choses importantes à noter. La première est qu'il n'y a pas d'entrées GOT ou PLT pour le code compilé. La seconde est que les tables GOT et PLT sont toujours nécessaires. Ils sont utilisés pour l'initialisation et le nettoyage (éventuellement pour la bibliothèque standard). Puisque vous utilisez un chargeur ELF personnalisé, il serait probablement conseillé d'implémenter une prise en charge de base pour les entrées GOT et PLT, même si votre application principale effectue des relocalisations standard à la place.
Votre application paiera alors le prix de la relocalisation, mais pas de l'indépendance de la position.