Quelle est la différence entre la section et le segment dans le format de fichier ELF?

de wiki format exécutable et liable :

les segments contiennent les informations nécessaires à l'exécution de l'exécution du fichier, tandis que les sections contiennent des données importantes pour le lien et le déplacement. N'importe quel octet dans le dossier entier peut être possédé par au plus une section, et il peut y avoir des octets orphelins qui ne sont pas possédés par n'importe quelle section.

mais quelle est la différence entre la section et segment? Dans un fichier ELF exécutable, un segment contient-il une ou plusieurs sections?

53
demandé sur tsing 2013-01-16 18:58:24

2 réponses

mais quelle est la différence entre la section et le segment?

exactement ce que vous avez cité: les segments contiennent les informations nécessaires à l'exécution, tandis que les sections contiennent les informations nécessaires lors du lien.

un segment contient-il une ou plusieurs sections?

un segment peut contenir 0 ou plus de sections. Exemple:

readelf -l /bin/date

Elf file type is EXEC (Executable file)
Entry point 0x402000
There are 9 program headers, starting at offset 64

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  PHDR           0x0000000000000040 0x0000000000400040 0x0000000000400040
                 0x00000000000001f8 0x00000000000001f8  R E    8
  INTERP         0x0000000000000238 0x0000000000400238 0x0000000000400238
                 0x000000000000001c 0x000000000000001c  R      1
      [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
  LOAD           0x0000000000000000 0x0000000000400000 0x0000000000400000
                 0x000000000000d5ac 0x000000000000d5ac  R E    200000
  LOAD           0x000000000000de10 0x000000000060de10 0x000000000060de10
                 0x0000000000000440 0x0000000000000610  RW     200000
  DYNAMIC        0x000000000000de38 0x000000000060de38 0x000000000060de38
                 0x00000000000001a0 0x00000000000001a0  RW     8
  NOTE           0x0000000000000254 0x0000000000400254 0x0000000000400254
                 0x0000000000000044 0x0000000000000044  R      4
  GNU_EH_FRAME   0x000000000000c700 0x000000000040c700 0x000000000040c700
                 0x00000000000002a4 0x00000000000002a4  R      4
  GNU_STACK      0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x0000000000000000 0x0000000000000000  RW     8
  GNU_RELRO      0x000000000000de10 0x000000000060de10 0x000000000060de10
                 0x00000000000001f0 0x00000000000001f0  R      1

 Section to Segment mapping:
  Segment Sections...
   00     
   01     .interp 
   02     .interp .note.ABI-tag .note.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame 
   03     .ctors .dtors .jcr .dynamic .got .got.plt .data .bss 
   04     .dynamic 
   05     .note.ABI-tag .note.gnu.build-id 
   06     .eh_frame_hdr 
   07     
   08     .ctors .dtors .jcr .dynamic .got 

ici, Le segment PHDR contient 0 sections, le segment INTERP contient la section .interp , et le premier segment LOAD contient tout un tas de sections.

autre lecture avec une belle illustration .

48
répondu Employed Russian 2018-06-17 23:13:21

Section contient statique pour l'éditeur de liens, le segment dynamique des données pour le système d'exploitation

le devis est correct, mais pour le comprendre réellement la différence, vous devriez essayer de comprendre les champs de l'en-tête de section et les entrées de l'en-tête de programme (segment), et comment ils sont utilisés par le linker (sections) et le système d'exploitation (segment).

les informations particulièrement importantes sont (outre les longueurs):

  • section: indiquer au linker si une section est:

    • données brutes à charger en mémoire, p.ex. .data , .text , etc.
    • ou des métadonnées formatées sur d'autres sections, qui seront utilisées par le linker, mais disparaîtront à l'exécution, par exemple .symtab , .srttab , .rela.text
  • segment: indique le système d'exploitation:

    • où un segment être chargé dans la mémoire virtuelle
    • quelles permissions ont les segments (lire, écrire, exécuter). Rappelez-vous que cela peut être efficacement appliqué par le processeur: Comment fonctionne x86 paging?

j'ai écrit un tutoriel qui couvre cela plus en détail à: http://www.cirosantilli.com/elf-hello-world/

est-ce qu'un segment contient une ou plusieurs sections?

Oui, et c'est le linker qui met les sections en segments.

dans les Binutils, la façon dont les sections sont mises en segments par ld est déterminée par un fichier texte appelé linker script . Docs: https://sourceware.org/binutils/docs/ld/Scripts.html

Vous pouvez obtenir la valeur par défaut avec ld --verbose , et définir une valeur personnalisée avec -T .

par exemple, mon script par défaut Ubuntu 17.04 contient:

  .text           :                                                                                                                                                             
  {                                                                                                                                                                             
    *(.text.unlikely .text.*_unlikely .text.unlikely.*)                                                                                                                         
    *(.text.exit .text.exit.*)                                                                                                                                                  
    *(.text.startup .text.startup.*)                                                                                                                                            
    *(.text.hot .text.hot.*)                                                                                                                                                    
    *(.text .stub .text.* .gnu.linkonce.t.*)                                                                                                                                                                                                                                                                                               
  } 

qui dit au linker de mettre les sections nommées .text.unlikely , .text.*_unlikely , .text.exit , etc. dans le segment .text .

développement OS est un cas où les scripts personnalisés sont utiles, exemple minimal: https://github.com/cirosantilli/x86-bare-metal-examples/blob/d217b180be4220a0b4a453f31275d38e697a99e0/linker.ld

une fois que l'exécutable est lié, il n'est possible de savoir quelle section est passée à quel segment si le linker stocke l'en-tête de section optionnel dans l'exécutable: Où est la "section to segment mapping" stockée dans les fichiers ELF?

20