ELF(5) Formats de fichiers de FreeBSD
elf - format de fichiers binaires exécutables ELF
#include <elf.h>
L'en-tête <elf.h> définit le format des fichiers binaires exécutables ELF. Ces binaires peuvent être des fichiers exécutables, des fichiers d'objet relocalisables, des fichiers du noyau ou des bibliothèques partagées.
Un exécutable au format ELF est formé d'un en-tête ELF suivi d'une table d'en-têtes de programmes ou de sections ou des deux. L'en-tête ELF est toujours au tout début du fichier (position zéro). La table d'en-têtes de programme et la table d'en-en-têtes de sections se trouvent à l'endroit défini par l'en-tête ELF. Les deux tables décrivent le reste des particularités du fichier.
Les applications voulant traiter des binaires ELF dans leur architecture ont simplement à inclure sys/elf.h dans leur code source. Elles pourront alors se référer à tous les types et structures en utilisant leurs noms génériques "Elf_xxx" et aux macros en utilisant "ELF_xxx". De cette manière, l'application peut être compilée sur n'importe quelle architecture sans avoir besoin de savoir si la machine est 32 ou 64 bits.
Si une application a besoin d'un fichier ELF issu d'une architecture inconnue, elle devra inclure à la fois sys/elf32.h et sys/elf64.h à la place de sys/elf.h. En outre, les types et structures devront être identifiés soit par " Elf32_xxx", soit par " Elf64_xxx" et les macros soit par " ELF32_xxx" soit par " ELF64_xxx".
Quelque soit le système, l'architecture doit obligatoirement inclure sys/elf_common.h ainsi que sys/elf_generic.h.
Ces fichiers d'en-tête décrivent les structures C dont nous parlions ci-dessus ainsi que celles des sections dynamiques, de relocalisation et des tables des symboles.
Les types suivants sont à utiliser sur les architectures 32 bits :
Elf32_Addr adresse de prognamme non-signée Elf32_Half champ demi-mot non-signé Elf32_Off position de fichier non-signée Elf32_Sword grand entier signé Elf32_Word champ ou grand entier signé Elf32_Size taille d'objet non-signée
Pour les architectures 64 bits, nous avons les types suivants :
Elf64_Addr adresse de prognamme non-signée Elf64_Half champ demi-mot non-signé Elf64_Off position de fichier non-signée Elf64_Sword grand entier signé Elf64_Word champ ou grand entier signé Elf64_Size taille d'objet non-signée Elf64_Quarter champ quart-de-mot non-signé
Toutes les structures de données définies suivent la taille "naturelle" et les directives d'alignement des classes significatives. Si necéssaire, les structures de données contiennent du remplissage afin d'assurer l'alignement 4 octets pour les objets de 4 octets, afin que la taille de la structure soit un multiple de 4, etc...
L'en-tête ELF est décrit par les types Elf32_Ehdr ou Elf64_Ehdr :
typedef struct { unsigned char e_ident[EI_NIDENT]; Elf32_Half e_type; Elf32_Half e_machine; Elf32_Word e_version; Elf32_Addr e_entry; Elf32_Off e_phoff; Elf32_Off e_shoff; Elf32_Word e_flags; Elf32_Half e_ehsize; Elf32_Half e_phentsize; Elf32_Half e_phnum; Elf32_Half e_shentsize; Elf32_Half e_shnum; Elf32_Half e_shstrndx; } Elf32_Ehdr; typedef struct { unsigned char e_ident[EI_NIDENT]; Elf64_Quarter e_type; Elf64_Quarter e_machine; Elf64_Half e_version; Elf64_Addr e_entry; Elf64_Off e_phoff; Elf64_Off e_shoff; Elf64_Half e_flags; Elf64_Quarter e_ehsize; Elf64_Quarter e_phentsize; Elf64_Quarter e_phnum; Elf64_Quarter e_shentsize; Elf64_Quarter e_shnum; Elf64_Quarter e_shstrndx; } Elf64_Ehdr;
Les champs ont la signification suivante :
e_ident
Ce tableau d'octets sert à interpréter le fichier, indépendamment du processeur ou de la suite du fichier. Dans ce tableau, tout est nommé par des macros qui commencent par le préfixe EI_ et qui contiennent des valeurs qui commencent par ELF. Les macros suivantes sont définies :
EI_MAG0 : le premier octet du nombre magique. Il doit être rempli avec ELFMAG0.
EI_MAG1 : le second octet du nombre magique. Il doit être rempli avec ELFMAG1.
EI_MAG2 : le troisième octet du nombre magique. Il doit être rempli avec ELFMAG2.
EI_MAG3 : le quatrième octet du nombre magique. Il doit être rempli avec ELFMAG3.
EI_CLASS : le cinquième octet identifie l'architecture pour ce binaire :
ELFCLASSNONE: cette classe est invalide.
ELFCLASS32 : définit l'architecture 32 bits. Cela supporte les machines dont les fichiers et les adresses virtuelles vont jusqu'à 4 giga-octets.
ELFCLASS64 : pour l'architecture 64 bits.
EI_DATA : le sixième octet indique le codage des données spécifique au processeur. Actuellement, les codages sont :
ELFDATANONE : format de données inconnu.
ELFDATA2LSB : le complément de deux, petit endien.
ELFDATA2MSB : le complément de deux, grand endien.
EI_VERSION : Le numéro de version de la spécification ELF :
EV_NONE : version non-valide.
EV_CURRENT : version courante.
EI_PAD : début du remplissage. Ces octets sont réservés et mis à zéro. Les programmes qui les lisent doivent les ignorer. La valeur d' EI_PAD changera si des octets inutilisés acquièrent une signification.
EI_BRAND : début de l'identification de l'architecture.
EI_NIDENT : la taille du tableau e_ident.
e_type
Cet élément de la structure identifie les types de fichiers odjet :
ET_NONE : type inconnu.
ET_REL : fichier relocalisable.
ET_EXEC : fichier exécutable.
ET_DYN : fichier partagé.
ET_CORE : un fichier du noyau (core file).
e_machine
Cet élément indique l'architecture requise pour le fichier :
EM_NONE : machine inconnue.
EM_M32 : AT&T WE 32100.
EM_SPARC : SPARC de Sun Microsystems
EM_386 : Intel 80386.
EM_68K : Motorola 68000.
EM_88K : Motorola 88000.
EM_486 : Intel 80486.
EM_860 : Intel 80860.
EM_MIPS : MIPS RS3000 (big-endian seulement).
EM_MIPS_RS4_BE : MIPS RS4000 (big-endian seulement ).
EM_SPARC64 : SPARC v9 64 bits non-officiel.
EM_PARISC : HPPA.
EM_PPC : PowerPC.
EM_ALPHA : Compaq [DEC] Alpha.
e_version
Cet élément indique la version du fichier :
EV_NONE : version non valide.
EV_CURRENT : version courante.
e_entry
Cet élément donne l'adresse virtuelle sur laquelle le système doit transférer le contrôle puis lancer l'exécution. Si le fichier n'a pas de point d'entrée, la valeur est à zéro.
e_phoff
Cet élément contient la position dans le fichier, en octets, de la table d'en-tête du programme. Si le fichier n'a pas de table d'en-tête de programme, l'élément vaut zéro.
e_shoff
Cet élément contient la position dans le fichier, en octets, de la table d'en-tête de la section. Si le fichier n'a pas cette section, l'élément vaut zéro.
e_flags
Cet élément contient les drapeaux spécifiques au processeur associé au fichier. Leurs noms sont de la forme EF_" drapeaux-machine". Actuellement, aucun n'a été défini.
e_ehsize
Cet élément contient la taille en octets de l'en-tête ELF.
e_phentsize
Cet élément contient la taille en octets d'une entrée de la table d'en-têtes de programme. Toutes les entrées ont la même taille.
e_phnum
Cet élément contient le nombre d'entrées de la table d'en-tête de programme. Ainsi, le produit de e_phentsize par e_phnum donne la taille de la table en octets. Si un fichier n'a pas d'en-tête de programmes, e_phnum prend la valeur de zéro.
e_shentsize
Cet élément contient la taille en octets d'un en-tête de section. Un en-tête de section est une entrée de la table des en-têtes de section. Toutes les entrées ont la même taille.
e_shnum
Cet élément contient le nombre d'entrées de la table des en-têtes de section. Ainsi le produit de e_shentsize par e_shnum donne la taille en octets de la table d' en-têtes de section. Si le fichier n'a pas cette table, e_shnum prend la valeur zéro.
e_shstrndx
Cet élément contient l'index de la table d'en-têtes de section de l'entrée associée à la table des chaines de noms de sections. Si le fichier n'a pas de table des chaines de noms de sections, cet élément prend la valeur SHN_UNDEF.
SHN_UNDEF : Cette valeur indique une référence de section indéfinie, absente, inappropriée ou autres non-sens. Par exemple, un symbole "défini" par rapport à la section numéro SHN_UNDEF est un symbole indéfini.
SHN_LORESERVE : Cette valeur indique la limite inférieure de l'intervalle des indices réservés.
SHN_LOPROC : cette valeur, jusqu'à SHN_HIPROC inclus, est réservée à la sémantique propre au processeur.
SHN_HIPROC : cette valeur, à partir de SHN_LOPROC inclus, est réservée à la sémantique propre au processeur.
SHN_ABS : indique la valeur absolue de la référence correspondente. Par exemple, les symboles définis par rapport à la section numéro SHN_ABS ont une valeur absolue et ne sont pas affectés par les relocalisations.
SHN_COMMON : Les symboles définis par rapport à cette section sont des symboles communs, comme COMMON en Fortran ou comme les variables externes non allouées en C.
SHN_HIRESERVE : Cette valeur indique la limite supérieure de l'intervalle des indices réservés entre SHN_LORESERVE et SHN_HIRESERVE, inclus. Elle ne référence pas la table des en-têtes de section. Celle-ci ne contient pas d'entrées pour les indices réservés.
Un exécutable ou une table d'en-tête de programme issue d'un fichier d'objets partagés est un tableau de structures, chacune décrivant un segment ou contenant d'autres informations utiles au système pour préparer l'exécution du programme. Un segment de fichier d'objets contient une section ou plus. Les en-têtes de programmes ne sont pertinants que dans le cas d'exécutables et de fichiers d'objets partagés. Un fichier définit ses propres tailles d'en-têtes de programme à l'aide des éléments ELF e_phentsize et e_phnum. De même que pour les en-têtes d'exécutables ELF, les en-têtes de programmes dépendent de l'architecture :
typedef struct { Elf32_Word p_type; Elf32_Off p_offset; Elf32_Addr p_vaddr; Elf32_Addr p_paddr; Elf32_Size p_filesz; Elf32_Size p_memsz; Elf32_Word p_flags; Elf32_Size p_align; } Elf32_Phdr; typedef struct { Elf64_Half p_type; Elf64_Half p_flags; Elf64_Off p_offset; Elf64_Addr p_vaddr; Elf64_Addr p_paddr; Elf64_Size p_filesz; Elf64_Size p_memsz; Elf64_Size p_align; } Elf64_Phdr;
La principale différence entre les programmes 32 et 64 bits se situe seulement dans la position de l'élément p_flags dans la structure.
p_type
Cet élément de la structure Phdr indique le type de segment que décrit cet élément de tableau ou bien comment interpréter l'information.
PT_NULL : l'élément du tableau est inutilisé et les autres valeurs sont indéfinies. L'en-tête de programme peut ignorer ces entrées.
PT_LOAD : L'élement de tableau indique un segment chargeable, décrit par p_filesz et p_memsz. Les octets du fichiers sont en correspondance avec le début du segment mémoire. Si la taille mémoire du segment ( p_memsz) est supérieure à la taille du fichier ( p_filesz), les octets supplémentaires prennent la valeur zéro et suivent la zone initiale du segment. La taille du fichier ne doit pas dépasser celle de la mémoire. Les entrées de segments chargeables de la table des en-têtes du programme sont dans l'ordre croissant de p_vaddr.
PT_DYNAMIC : Cet élément de tableau contient des information sur les liens dynamiques.
PT_INTERP : Cet élément de tableau détermine l'endroit et la taille du chemin d'accès (terminé par null) qui permet d'appeler un interpréteur. Cette information n'est pertinente que dans le cas de fichiers exécutables (mais elle peut apparaître dans des objets partagés) et ne peut exister qu'une fois dans un fichier. Si présente, elle doit précéder tout segment chargeable.
PT_NOTE : Cet élément de tableau détermine l'endroit et la taille d'informations auxiliaires.
PT_SHLIB : Ce type de segment est réservé et ne possède pas de sémantique spécifique. Les programmes qui le possèdent ne sont pas conformes à ABI.
PT_PHDR : S'il est présent, cet élément de tableau détermine l'endroit et la taille de la table d'en-tête de programme elle-même, à la fois dans le fichier et dans l'image mémoire du programme. Ce type de segment ne doit pas aparaître plus d'une fois dans un fichier et uniquement si la table des en-têtes de programme fait partie de l'image mémoire du programme. Il doit précéder tout segment chargeable.
PT_LOPROC : Cette valeur, jusqu'à PT_HIPROC inclus, est réservée à la sémantique propre du processeur.
PT_HIPROC : Cette valeur, à partir de PT_LOPROC inclus, est réservée à la sémantique propre du processeur.
p_offset
Ce membre contient la position, à partir du début du fichier, à laquelle se trouve le premier octet du segment.
p_vaddr
Ce membre contient l'adresse virtuelle à laquelle se trouve le premier octet du segment, en mémoire.
p_paddr
Dans les systèmes pour lesquels il est pertinant, ce membre est réservé au segment d'adressage physique. Ce n'est pas le cas avec BSD où il doit être à zéro.
p_filesz
Ce membre contient le nombre d'octets de l'image fichier du segment. Il doit être à zéro.
p_memsz
Ce membre contient le nombre d'octets de l'image mémoire du segment. Il doit être à zéro.
p_flags
Ce membre contient les flags utiles au segment :
PF_X : un segment exécutable.
PF_W : un segment inscriptible.
PF_R : un segment en lecture.
En général, un segment texte a le flag PF_X et PF_R et un segment de données PF_X, PF_W et PF_R.
p_align
Ce membre contient la valeur sur laquelle sont alignés les segments, en mémoire et dans le fichier. Les segments de processus chargeables doivent avoir des valeurs de p_vaddr et p_offset congruantes modulo taille de page. Les valeurs de zéro et un signifient qu'aucun alignement n'est requis. Sinon, p_align doit être une puissance de deux et p_vaddr doit être égal à p_offset, modulo p_align.
Une table d'en-tête de section dans un fichier permet de localiser toutes les sections du fichier. Elle se présente sous la forme d'un tableau de structures Elf32_Shdr ou Elf64_Shdr. Le membre e_shoff de l'en-tête ELF donne la position en octets, par rapport au début du fichier, de la table d'en-tête de sections. e_shnum contient le nombre d'entrées de la table d'en-tête de sections. e_shentsize contient la taille en octets de chacune des ces entrées.
Un index est attaché à ce tableau et certains indices sont réservés. Un fichier objet n'a pas de sections pour ces indices spécifiques :
SHN_UNDEF
Cette valeur indique une référence de section indéfinie, absente, non-pertinente ou autrement non-significative.
SHN_LORESERVE
Cette valeur indique la limite inférieure des indices réservés.
SHN_LOPROC
Cette valeur, jusqu'à SHN_HIPROC inclus, est réservée à la sémantique propre au processeur.
SHN_HIPROC
Cette valeur, à partir de SHN_LOPROC inclus, est réservée à la sémantique propre au processeur.
SHN_ABS
Cette valeur indique la valeur absolue de la référence correspondante. Par exemple, les symboles définis par rapport à la section numéro SHN_ABS ont une valeur absolue et ne sont donc pas effectés par la relocalisation.
SHN_COMMON
Les symboles définis par rapport à cette section sont des symboles communs, comme COMMON en FORTRAN ou comme les variables externes non-localisées en C.
SHN_HIRESERVE
Cette valeur indique la limite supérieure des indices réservés. Le système réserve les indices compris entre SHN_LORESERVE et SHN_HIRESERVE, inclusivement. Cette table d'en-tête de section ne contient aucune entrée pour les indices réservés.
L'en-tête de section est de cette forme :
typedef struct { Elf32_Word sh_name; Elf32_Word sh_type; Elf32_Word sh_flags; Elf32_Addr sh_addr; Elf32_Off sh_offset; Elf32_Size sh_size; Elf32_Word sh_link; Elf32_Word sh_info; Elf32_Size sh_addralign; Elf32_Size sh_entsize; } Elf32_Shdr; typedef struct { Elf64_Half sh_name; Elf64_Half sh_type; Elf64_Size sh_flags; Elf64_Addr sh_addr; Elf64_Off sh_offset; Elf64_Size sh_size; Elf64_Half sh_link; Elf64_Half sh_info; Elf64_Size sh_addralign; Elf64_Size sh_entsize; } Elf64_Shdr;
sh_name
Ce membre donne le nom de la section. Sa valeur est un index vers l'en-tête de section de la table des chaînes, donnant la position de la chaîne terminée par null.
sh_type
Ce membre ordonne le contenu et la sémantique de la section.
SHT_NULL
Cette valeur désactive l'en-tête de section. Elle n'a pas de section associée et les autres membres ont une valeur indéfinie.
SHT_PROGBITS
La section contient des informations dont le format et la signification ne sont déterminés que par le programme.
SHT_SYMTAB
Cette section est une table de symboles. D'une manière générale, SHT_SYMTAB fournit les symboles pour l'édition de liens tant statique que dynamique. Les tables de symboles complètes peuvent aussi contenir des éléments non-nécessaires aux liens dynamiques. Un fichier objet peut aussi contenir une section SHN_DYNSYM.
SHT_STRTAB
Cette section contient une table de chaînes. Un fichier objet peut avoir plusieurs sections tables de chaines.
SHT_RELA
Cette section contient des entrées de relocalisation, avec des compléments explicites, comme le type Elf32_Rela dans le cas de classes 32 bits de fichiers objets. Un fichier objet peut avoir plusieurs sections de relocalisation.
SHT_HASH
Cette section contient une table fractionnée de symboles. Tous les objets participant aux liens dynamiques doivent avoir une telle table. Un fichier objet ne peut en avoir qu'une.
SHT_DYNAMIC
Cette section contient des informations utiles aux liens dynamiques. Un fichier objet ne peut avoir qu'une section dynamique.
SHT_NOTE
Cette section contient diverses informations sur le fichier.
SHT_NOBITS
Une section de ce type n'occupe aucune place dans le fichier mais ressemble à SHN_PROGBITS. Par ailleurs, elle ne contient aucun octet et sh_offset indique la position conceptuelle dans le fichier.
SHT_REL
Cette section contient les postions de relocalisation, sans les compléments explicites, comme le type Elf32_Rel dans le cas de classes 32 bits de fichiers objets. Un fichier objet peut avoir plusieurs sections de relocalisation.
SHT_SHLIB
Cette section, sans organisation spécifique, est réservée.
SHT_DYNSYM
Cette section contient le minimum requis de symboles dynamiques. Un fichier objet peut aussi avoir une section SHN_SYMTAB.
SHT_LOPROC
Cette valeur, jusqu'à SHT_HIPROC inclus, est réservée à la sémantique propre au processeur.
SHT_HIPROC
Cette valeur, à partir de SHT_LOPROC inclus, est réservée à la sémantique propre au processeur.
SHT_LOUSER
Cette valeur indique la limite inférieure des indices réservés à l'application.
SHT_HIUSER
Cette valeur indique la limite supérieure des indices réservés à l'application. Les types de sections compris entre SHT_LOUSER et SHT_HIUSER peuvent être utilisés par l'application sans conflits avec les types de sections actuels et futurs.
sh_flags
La section accepte les flags d'un bit décrivant divers attributs. Si un bit est positionné dans sh_flags, l'attribut correspondant est actif pour cette section sinon il est inactif. Les attributs indéfinis sont mis à zéro.
SHF_WRITE
Cette section contient des données qui peuvent être écrites pendant l'exécution du processus.
SHF_ALLOC
La section occupe une place en mémoire durant l'exécution du processus. Des sections de contrôle ne se placent pas dans l'image mémoire d'un fichier objet. Cet attribut est désactivé dans ce cas.
SHF_EXECINSTR
La section contient des instructions machine exécutables.
SHF_MASKPROC
Tous les bits de ce masque sont réservés à la sémantique propre du processeur.
sh_addr
Si la section doit apparaitre en mémoire, ce membre contient l'adresse à laquelle le premier octet doit résider. Sinon il vaut zéro.
sh_offset
Ce membre contient la position en octets, à partir du début du fichier, du premier octet de la section. Une section de type SHT_NOBITS n'occupe aucune place dans le fichier et son sh_offset localise son emplacement conceptuel dans le fichier.
sh_size
Ce membre contient la taille en octets de la section. A moins qu'elle ne soit de type SHT_NOBITS, la section occupe sh_size octets dans le fichier. Une section SHT_NOBITS peut avoir une taille différente de zéro mais n'occupe quand même aucune place dans le fichier.
sh_link
Ce membre contient un lien d'index de table d'en-tête de section dont l'interprétation dépend de la section.
sh_info
Ce membre contient des informations supplémentaires dont l'interprétation dépend de la section.
sh_addralign
Certaines sections possèdent des contraintes d'alignement sur les adresses. Si une section contient un mot-double, le système doit assurer l'alignement pour toute la section. C'est à dire que la valeur sh_addr doit être congrue à zéro modulo sh_addralign. Seules la valeur zéro ou une valeur positive puissance de deux est acceptée. Une valeur de zéro ou un signifie que la section n'a aucune contrainte d'alignement.
sh_entsize
Certaines sections contiennent une table dont les entrées sont de taille fixe, comme une table de symboles. Pour celles-ci, ce membre indique la taille des entrées. Ce membre est à zéro dans les autres cas.
Diverses sections contiennent des informations de programme ou de contrôle :
.bss
Cette section contient des données non-initialisées utiles à l'image mémoire du programme. Par définition, le système initialise les données à zéro lors du lancement du programme. Cette section est de type SHT_NOBITS. Les types d'attributs utilisés sont SHF_ALLOC et SHF_WRITE.
.comment
Cette section contient des informations de contrôle de version. Elle est de type SHT_PROGBITS et aucun attribut n'est utilisé.
.data
Cette section contient des données initialisées utiles à l'image mémoire du programme. Elle est de type SHT_PROGBITS et ses attributs sont SHF_ALLOC et SHF_WRITE.
.data1
Cette section contient des données initialisées utiles à l'image mémoire du programme. Elle est de type SHT_PROGBITS et ses attributs sont SHF_ALLOC et SHF_WRITE.
.debug
Cette section contient des informations pour le débogage des symboles. Son contenu n'a pas de spécification mais elle est de type SHT_PROGBITS, sans attributs.
.dynamic
Cette section, de type SHT_DYNAMIC, contient des informations sur les liens dynamiques. Ses attributs incluent le bit SHF_ALLOC. Le bit SHF_WRITE positionné est spécifique au processeur. Voir les attributs plus loin.
.dynstr
Cette section contient les chaines utiles aux liens dynamiques ou, plus courrament, les chaines représentant les noms associés aux entrées des tables de symboles. Elle est de type SHT_STRTAB et l'attribut utilisé SHF_ALLOC.
.dynsym
Cette section contient la table de symboles des liens dynamiques. Elle est de type SHT_DYNSYM et l'attribut utilisé SHF_ALLOC.
.fini
Cette section contient les instructions exécutables qui apparaissent lorsque le programme se termine. Le système s'arrange alors pour exécuter le code de cette section. Elle est de type SHT_PROGBITS et les attributs utilisés SHF_ALLOC et SHF_EXECINSTR.
.got
Cette section contient la table de positionnement global. Elle est de type SHT_PROGBITS et ses attributs dépendent du processeur.
.hash
Cette section contient la table segmentée des symboles. Elle est de type SHT_HASH et l'attribut utilisé SHF_ALLOC.
.init
Cette section contient les instructions exécutables utiles à l'initialisation du processus. Lorsqu'un programme démarre, le système s'arrange pour exécuter le code de cette section avant d'en appeler le point d'entrée principal. Elle est de type SHT_PROGBITS et les attributs utilisés SHF_ALLOC et SHF_EXECINSTR.
.interp
Cette section contient le chemin d'accès d'un interpréteur de programme. Si le fichier possède un segment chargeable avec cette section, les attributs auront le bit SHF_ALLOC positionné. Elle est de type SHT_PROGBITS.
.line
Cette section contient des informations sur les numéros de lignes pour le débogage. Elle fait la correspondance entre les sources du programme et le code machine, sans spécifications particulières. Elle est de type SHT_PROGBITS sans attributs.
.note
Cette section contient des informations dans le format "Section de notes" décrit plus loin. Elle est de type SHT_NOTE sans attributs.
.plt
Cette section contient la table des liens de procédures. Elle est de type SHT_PROGBITS et les attributs dépendent du processeur.
.relNOM
Cette section, de type SHT_REL, contient des informations de relocalisation, comme décrit plus loin. Si un segment chargeable a une telle section, le bit SHF_ALLOC sera positionné. Par convention, "NOM" est donné par la section concernée par la relocalisation. De cette manière, une section .text aura le nom .rel.text.
.relaNOM
Cette section, de type SHT_RELA, contient des informations de relocalisation, comme décrit plus loin. Si un segment chargeable a une telle section, le bit SHF_ALLOC sera positionné. Par convention, "NOM" est donné par la section concernée par la relocalisation. De cette manière, une section .text aura le nom .rela.text.
.rodata
Cette section contient des données en lecture seule qui, typiquement, contribuent au segment non-inscriptible de l'image du processus. Elle est de type SHT_PROGBITS et l'attribut utilisé SHF_ALLOC.
.rodata1
Cette section contient des données en lecture seule qui, typiquement, contribuent au segment non-inscriptible de l'image du processus. Elle est de type SHT_PROGBITS et l'attribut utilisé SHF_ALLOC.
.shstrtab
Cette section est celle des noms. Elle est de type SHT_STRTAB sans attributs.
.strtab
Cette section, de type SHT_STRTAB, contient des chaines qui représentent, la plupart du temps, les noms associés aux entrées des tables de symboles. Si le fichier a des segments chargeables possèdant la table des chaines de symboles, l'attribut aura le bit SHF_ALLOC positionné, sinon non.
.symtab
Cette section, de type SHT_SYMTAB, contient une table de symboles. Si le fichier a des segments chargeable possédant une table de symboles, l'attribut aura le bit SHF_ALLOC positionné, sinon non.
.text
Cette section contient les instructions "texte" ou exécutables du programme. Elle est de type SHT_PROGBITS et les attributs utilisés sont SHF_ALLOC et SHF_EXECINSTR.
Les sections table de chaines contiennent des suites de caractères terminées par null, appelées chaines. Le fichier objet les utilise comme noms de symboles et de sections. Les références se font par index vers cette section. Le premier octet, à l'index zéro, contient le caractère null par définition. Le dernier octet contient aussi le caractère null, de manière à ce que toutes les chaines soient terminées par celui-ci.
Une table de symboles d'un fichier objet contient les informations utiles à la localisation et à la relocalisation des références et définitions des symboles du programme. Un index de table de symbole désigne un endroit de cette table.
typedef struct { Elf32_Word st_name; Elf32_Addr st_value; Elf32_Size st_size; unsigned char st_info; unsigned char st_other; Elf32_Half st_shndx; } Elf32_Sym; typedef struct { Elf64_Half st_name; unsigned char st_info; unsigned char st_other; Elf64_Quarter st_shndx; Elf64_Addr st_value; Elf64_Size st_size; } Elf64_Sym;
st_name
Ce membre contient un index vers la table des chaines de symboles du fichier objet, qui contient le nom du symbole. Si la valeur est différente de zéro, il s'agit d'un index vers la table de chaines qui donne le nom du simbole sinon la table de symbole n'a pas de nom.
st_value
Ce membre donne la valeur du symbole associé.
st_size
La plupart des symboles ont une taille. Ce membre contient zéro s'il n'en a pas ou si elle est inconnue.
st_info
Ce membre indique le type de symbole et ses attributs liés :
STT_NOTYPE
Le type n'est pas défini.
STT_OBJECT
Le symbole est associé à un objet de données.
STT_FUNC
Le symbole est associé à une fonction ou autre code exécutable.
STT_SECTION
Le symbole est associé à une section. Les entrées de table de symbole de ce type existaient pour la localisation et avaient des liens STB_LOCAL.
STT_FILE
Par convention, le nom de symbole donne le nom du fichier source associé au fichier objet. Un symbole fichier a des liens STB_LOCAL, son index de section est SHN_ABS et il précède tout autre symbole STB_LOCAL du fichier.
STT_LOPROC
Ces valeurs jusqu'à STT_HIPROC inclus sont réservées à la sémantique propre du processeur.
STT_HIPROC
Ces valeurs à partir de STT_LOPROC inclus sont réservées à la sémantique propre du processeur.
STB_LOCAL
Les symboles locaux ne sont pas visibles hors du fichier objet contenant leur description. Des symboles locaux de même nom peuvent exister dans plusieurs fichiers sans interférer entre eux.
STB_GLOBAL
Les symboles globaux sont visibles à partir de tous les fichiers objets auxquels ils sont combinés. La définition d'un symbole global dans un fichier satisfera une référence non-définie dans un autre fichier au même symbole.
STB_WEAK
Les symboles faibles (weak) ressemblent aux symboles globaux mais leur définition a une moindre préséance.
STB_LOPROC
Ces valeurs jusqu'à STB_HIPROC inclus sont réservées à la sémantique propre du processeur.
STB_HIPROC
Ces valeurs à partir de STT_LOPROC inclus sont réservées à la sémantique propre du processeur.
Il existe des macros qui permettent de paqueter et dépaqueter les liens et les types de champs :
ELF32_ST_BIND(info) ou ELF64_ST_BIND(info)
Récupère un lien à partir d'une valeur st_info.
ELF64_ST_TYPE(info) ou ELF32_ST_TYPE(info)
Récupère un type à partir d'une valeur st_info.
ELF32_ST_INFO(lien, type) ou ELF64_ST_INFO(lien, type)
Convertie un lien et un type en valeur st_info.
st_other
Ce membre ne contient actuellement que des zéros et n'a pas de signification définie.
st_shndx
Chaque entrée de table de syboles est "définie" par rapport à une action. Ce membre contient l'index vers la table d'en-tête de section qui correspond.
La relocalisation est le processus qui consiste à associer les références de symboles aux définitions de symboles. Les fichiers relocalisables doivent avoir des informations sur la façon dont le contenu de leur sections est modifiable, permettant aux exécutables et aux objet partagés d'obtenir la bonne information pour l'image du programme. Les entrées de relocalisation sont ces données.
Les structures de relocalisation ne nécessitant aucun complément :
typedef struct { Elf32_Addr r_offset; Elf32_Word r_info; } Elf32_Rel; typedef struct { Elf64_Addr r_offset; Elf64_Size r_info; } Elf64_Rel;
Les structures de relocalisation nécessitant des compléments :
typedef struct { Elf32_Addr r_offset; Elf32_Word r_info; Elf32_Sword r_addend; } Elf32_Rela; typedef struct { Elf64_Addr r_offset; Elf64_Size r_info; Elf64_Off r_addend; } Elf64_Rela;
r_offset
Ce membre donne la position à laquelle appliquer la relocalisation. Pour un fichier relocalisable, la valeur correspond au nombre d'octets, à partir du début de la section, des données concernées. Pour un fichier exécutable ou un objet partagé, la valeur est l'adresse virtuelle de ces données.
r_info
Ce membre donne à la fois l'index de la table des symboles auquel appliquer la relocalisation et le type de relocalisation à appliquer. Ces derniers dépendent du processeur. Lorsque le texte se réfère à un type d'entrée de relocalisation ou à un index de table de symbole, il se réfère, en fait, au résultat de ELF_[32|64]_R_TYPE ou ELF[32|64]_R_SYM sur le membre r_info de l'entrée.
r_addend
Ce membre spécifie un complément constant utilisé pour calculer la valeur à enregistrer dans le champ relocalisable.
as(1), gdb(1), ld(1), objdump(1), execve(2), core(5)
Hewlett Packard, Elf-64 Object File Format.
Santa Cruz Operation, System V Application Binary Interface.
Unix System Laboratories, "Object Files", Executable and Linking Format (ELF).
Les fichiers ELF font leur apparition avec FreeBSD 2.2.6. ELF lui-même apparait dans UNIX AT&T System V. Ce format est un standard adopté.
Cette page de manuel a été écrite par Jeroen Ruigrok van der Werven <asmodai@wxs.nl> en s'inspirant de celle issue de BSD/OS de BSDI.
La version française est de Guillain SEUILLOT <Guillain@lycosmail.com>.
FreeBSD 3.3
31 juillet 1999, 12 mai 2000 pour la version française.