10 votes

signification de R_386_32/R_386_PC32 dans la section .rel.text de l'elf

Pour comprendre le concept de relocalisation, j'ai écrit un simple programme chk.c comme suit :

  1 #include<stdio.h>
  2 main(){
  3         int x,y,sum;
  4         x = 3;
  5         y = 4;
  6         sum = x + y;
  7         printf("sum = %d\n",sum);
  8 }

son code assembleur équivalent, en utilisant "objdump -d chk.o" est :

00000000 <main>:
   0:   55                      push   %ebp
   1:   89 e5                   mov    %esp,%ebp
   3:   83 e4 f0                and    $0xfffffff0,%esp
   6:   83 ec 20                sub    $0x20,%esp
   9:   c7 44 24 1c 03 00 00    movl   $0x3,0x1c(%esp)
  10:   00 
  11:   c7 44 24 18 04 00 00    movl   $0x4,0x18(%esp)
  18:   00 
  19:   8b 44 24 18             mov    0x18(%esp),%eax
  1d:   8b 54 24 1c             mov    0x1c(%esp),%edx
  21:   8d 04 02                lea    (%edx,%eax,1),%eax
  24:   89 44 24 14             mov    %eax,0x14(%esp)
  28:   b8 00 00 00 00          mov    $0x0,%eax
  2d:   8b 54 24 14             mov    0x14(%esp),%edx
  31:   89 54 24 04             mov    %edx,0x4(%esp)
  35:   89 04 24                mov    %eax,(%esp)
  38:   e8 fc ff ff ff          call   39 <main+0x39>
  3d:   c9                      leave  
  3e:   c3                      ret    

et la section .rel.text vue à l'aide de readelf est la suivante :

Relocation section '.rel.text' at offset 0x360 contains 2 entries:
 Offset     Info    Type            Sym.Value  Sym. Name
00000029  00000501 R_386_32          00000000   .rodata
00000039  00000902 R_386_PC32        00000000   printf

J'ai les questions suivantes à ce sujet :

1) à partir de la 2ème entrée dans la section .rel.text, je suis capable de comprendre que la valeur à l'offset 0x39 dans la section .text (qui est 0xfcffffff ici) doit être remplacée par l'adresse d'un symbole associé à l'index 9 de la table des symboles (& qui s'avère être printf). Mais je ne suis pas en mesure de comprendre clairement la signification de 0x02 (ELF32_R_TYPE) ici. Qu'est-ce que R_386_PC32 spécifie ici ? Quelqu'un peut-il m'expliquer clairement sa signification ?

2) Je ne suis pas non plus en mesure de comprendre la première entrée. Ce qui doit être remplacé à l'offset de 0x29 dans la section .text et pourquoi n'est pas clair ici. J'ai trouvé un pdf elf_format.pdf, mais je ne suis pas en mesure de comprendre clairement la signification de "Type" dans la section .rel.text.

3) Je souhaite également connaître la signification de l'inst. d'assemblage "lea (%edx,%eax,1),%eax". Bien que j'ai trouvé un très bon lien ( Quel est l'objectif de l'instruction LEA ? ) décrivant la signification de lea, mais le format de lea (ce que sont les 3 arg entre parenthèses) n'est pas clair.

si quelqu'un peut expliquer clairement les réponses aux questions ci-dessus, ce sera très apprécié. j'ai toujours du mal à trouver les réponses à ces questions, bien que j'aie beaucoup essayé avec google.

J'ai indiqué ci-dessous les entrées de la table des symboles pour les décalages 5 et 9.

 Num: Value Size Type Bind Vis Ndx Name 
 5: 00000000 0 SECTION LOCAL DEFAULT 5 
 9: 00000000 0 NOTYPE GLOBAL DEFAULT UND printf' 

Le champ d'information de la première entrée de la table .rel.text est 0x05, ce qui indique l'index de la table des symboles. J'ai montré l'entrée de la table des symboles pour l'index 5 ci-dessus, mais je n'arrive pas à comprendre comment cela nous indique qu'il s'agit de .rodata .

13voto

nneonneo Points 56821

1), 2) : R_386_32 est une relocalisation qui place le adresse absolue de 32 bits du symbole dans l'emplacement de mémoire spécifié. R_386_PC32 est une relocalisation qui place le Adresse 32 bits relative au PC du symbole dans l'emplacement de mémoire spécifié. R_386_32 est utile pour les données statiques, comme indiqué ici, puisque le compilateur charge simplement l'adresse du symbole relocalisé dans un registre et le traite ensuite comme un pointeur. R_386_PC32 est utile pour les références de fonctions puisqu'il peut être utilisé comme argument immédiat de la fonction call . Voir elf_machdep.c pour un exemple de traitement des relocalisations.

3) lea (%edx,%eax,1),%eax signifie simplement %eax = %edx + 1*%eax si elle est exprimée en syntaxe C. Ici, il est essentiellement utilisé comme substitut de la fonction add opcode.

EDIT : Voici un exemple.

Supposons que votre code soit chargé dans la mémoire à partir de 0x401000, que la chaîne de caractères "sum = %d\n" se termine à 0x401800 (au début de la chaîne de caractères .rodata section), et que printf se trouve à 0x1400ab80, dans la libc.

Ensuite, le R_386_32 La relocalisation à 0x29 placera les octets 00 18 40 00 à 0x401029 (en copiant simplement l'adresse absolue du symbole), ce qui rend l'instruction à 0x401028

  401028:   b8 00 18 40 00          mov    $0x401800,%eax

En R_386_PC32 La relocalisation à 0x39 place les octets 43 9b c0 13 à 0x401039 (la valeur 0x1400ab80 - 0x40103d = 0x13c09b43 en hexadécimal), ce qui rend cette instruction

  401038:   e8 43 9b c0 13          call   $0x1400ab80 <printf>

Nous soustrayons 0x40103d pour tenir compte de la valeur de %pc (qui est l'adresse de l'instruction qui suit l'instruction call ).

5voto

twalberg Points 19804

La première entrée de relocalisation consiste à récupérer le pointeur de votre chaîne de format ( "sum = ..." ) dans le processus de mise en place de l'appel à printf . Étant donné que le .rodata est déplacée ainsi que la section .text les références aux chaînes de caractères et autres données constantes devront être corrigées.

En gardant cela à l'esprit, il semblerait que les relocalisations R_386_32 concernent les données, et les R_386_PC32 les adresses de code, mais la spécification ELF (dont je n'ai pas d'exemplaire à portée de main) explique probablement les différents détails.

En lea est ce que le compilateur a choisi pour effectuer l'addition pour cette routine. Il aurait pu choisir add ou quelques autres possibilités, mais cette forme de lea semble être utilisé assez souvent dans certains cas, car il permet de combiner une addition avec une multiplication. Le résultat de l'instruction est lea (%edx,%eax,1),%eax est que %eax obtiendra la valeur de %edx + 1 * %eax . Le 1 peut être remplacé par un ensemble restreint de petits nombres entiers. L'objectif initial du lea était "Load Effective Address" (charger l'adresse effective) - pour prendre un pointeur de base, un index et une taille et obtenir l'adresse d'un élément dans un tableau. Mais, comme vous pouvez le voir, les compilateurs peuvent choisir de l'utiliser pour d'autres choses...

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X