2011-01-25 1 views
0

J'ai une chaîne d'outils personnalisée qui génère des bibliothèques partagées relogeables. Cela fonctionne avec un chargeur ELF également personnalisé qui les charge dans la mémoire, en les réparant. J'essaie maintenant de persuader gcc et binutils de produire des fichiers ELF compatibles avec ce chargeur.Création d'une bibliothèque partagée relogeable avec binutils

Malheureusement, il semblerait que binutils refuse de générer relogeable objets partagés. Il va générer des objets partagés PIC, mais je ne veux pas le faire en raison de la surcharge supplémentaire du GOT/PLT (et en plus, le chargeur ELF personnalisé ne le supporte pas). Et il va générer des objets relogeables, mais ce ne sont pas des objets dynamiques et n'ont donc pas les sections appropriées que le chargeur ELF veut pouvoir charger. Je ne comprends pas pourquoi GNU ld refuse de me permettre de spécifier --relocatable et -shared sur la même ligne de commande. Quelqu'un peut-il m'éclairer? Et est-ce que quelqu'un sait l'incantation pour que ld génère les fichiers objet que je cherche?

Répondre

2

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.

Questions connexes