Le fichier d'en-tête <elf.h> définit le
format des fichiers binaires exécutables ELF. Ces fichiers peuvent
être soit des fichiers exécutables normaux, des fichiers
objets repositionnables, des fichiers core ou des objets
partagés.
Un fichier exécutable utilisant le format de fichier ELF
est constitué d'un en-tête ELF, suivi d'une table
d'en-tête de programme ou d'une table des en-têtes de
sections, ou des deux. L'en-tête ELF est toujours situé
à un déplacement de zéro par rapport au début du
fichier. Les déplacements dans le fichier des tables d'en-tête
de programme et des en-têtes de sections sont définis dans
l'en-tête ELF. Ces deux tables décrivent le reste des
particularités du fichier.
Ce fichier d'en-tête décrit, sous la forme de
structures C, les en-têtes mentionnés
précédemment et inclut également des structures pour
les sections dynamiques, les sections de repositionnement et les tables de
symboles.
Les types suivants sont utilisés pour les architectures
N-bit (avec N=32,64 ; ElfN signifie Elf32 ou
Elf64 ; uintN_t signifie uint32_t ou
uint64_t) :
ElfN_Addr adresse (non signée) du programme, uintN_t
ElfN_Off déplacement (non signé) dans le fichier, uintN_t
ElfN_Section indice (non signé) de section, uint16_t
ElfN_Versym informations (non signées) sur les versions
des symboles, uint16_t
Elf_Byte caractère (char) non signé
ElfN_Half uint16_t
ElfN_Sword int32_t
ElfN_Word uint32_t
ElfN_Sxword int64_t
ElfN_Xword uint64_t
(Note : la terminologie *BSD est quelque peu
différente. Elf64_Half est deux fois plus grand que
Elf32_Half et Elf64Quarter est utilisé pour
uint16_t. Afin d'éviter toute confusion, ces types seront
remplacés par des types plus explicites dans la suite de ce
document.)
Toutes les structures de données définies par le
format de fichier suivent la taille
« naturelle » et les principes d'alignement de
la classe correspondante. Si nécessaire, les structures de
données contiennent un remplissage explicite pour assurer
l'alignement sur 4 octets des objets de 4 octets et pour
forcer les tailles des structures à être des multiples de
4, etc.
En-tête ELF (Ehdr)
L'en-tête ELF est décrit par le type
Elf32_Ehdr ou par le type Elf64_Ehdr :
#define EI_NIDENT 16
typedef struct {
unsigned char e_ident[EI_NIDENT];
uint16_t e_type;
uint16_t e_machine;
uint32_t e_version;
ElfN_Addr e_entry;
ElfN_Off e_phoff;
ElfN_Off e_shoff;
uint32_t e_flags;
uint16_t e_ehsize;
uint16_t e_phentsize;
uint16_t e_phnum;
uint16_t e_shentsize;
uint16_t e_shnum;
uint16_t e_shstrndx;
} ElfN_Ehdr;
Les champs ont les significations suivantes :
- e_ident
- Ce tableau d'octets indique comment interpréter le fichier,
indépendamment du processeur ou du reste du contenu du fichier.
Dans ce tableau, chacun des éléments s'appelle une macro qui
commence par le préfixe EI_ et peut contenir des valeurs
commençant par le préfixe ELF. Les macros suivantes
sont définies :
- EI_MAG0
- Premier octet du nombre magique. Il doit être rempli par
ELFMAG0 (0: 0x7f).
- EI_MAG1
- Deuxième octet du nombre magique. Il doit être rempli par
ELFMAG1 (1: « E »).
- EI_MAG2
- Troisième octet du nombre magique. Il doit être rempli par
ELFMAG2 (2: « L »).
- EI_MAG3
- Quatrième octet du nombre magique. Il doit être rempli par
ELFMAG3 (3: « F »).
- EI_CLASS
- Le cinquième octet indique l'architecture pour ce
binaire :
- ELFCLASSNONE
- Cette classe n'est pas valable.
- ELFCLASS32
- Cela définit une architecture 32 bits. Elle permet
d'utiliser des machines avec des espaces d'adressage virtuel et des
fichiers d'une taille allant jusqu'à 4 gigaoctets.
- ELFCLASS64
- Cela définit une architecture 64 bits.
- EI_DATA
- Le sixième octet indique le codage utilisé pour les
données de ce fichier spécifiques au processeur.
Actuellement, les codages suivants sont gérés :
- ELFDATANONE
- Format de données inconnu.
- ELFDATA2LSB
- Complément à deux, petit boutiste.
- ELFDATA2MSB
- Complément à deux, gros boutiste.
- EI_VERSION
- Le 7e octet est le numéro de version de la spécification du
format ELF :
- EI_OSABI
- Le 8e octet identifie le système d'exploitation et l'interface
binaire des applications (ABI) auxquels cet objet est destiné.
Certains des champs d'autres structures ELF contiennent des valeurs et des
drapeaux dont la signification dépend de la plate-forme ;
l'interprétation de ces champs dépend de la valeur de cet
octet. Par exemple :
- EI_ABIVERSION
- Le 9e octet identifie la version de l'interface binaire des applications
(ABI) à laquelle cet objet est destiné. Ce champ permet de
différencier des versions incompatibles d'une même ABI.
L'interprétation de ce numéro de version dépend de
l'ABI indiquée par le champ EI_OSABI. Les applications
respectant cette spécification utilisent la valeur 0.
- EI_PAD
- Début de remplissage. Ces octets sont réservés et
positionnés à zéro. Les programmes qui les lisent ne
doivent pas en tenir compte. La valeur de EI_PAD sera
modifiée dans le futur si l'on décide de donner une
signification à des octets actuellement inutilisés.
- EI_NIDENT
- Taille du tableau e_ident.
- e_type
- Ce membre de la structure identifie le type de fichier objet :
- e_machine
- Ce membre indique l'architecture nécessaire à un fichier
particulier. Par exemple :
- e_version
- Ce membre indique la version du fichier :
- EV_NONE
- Version non valable
- EV_CURRENT
- Version actuelle
- e_entry
- Ce membre indique l'adresse virtuelle à laquelle le système
transfère initialement le contrôle, démarrant ainsi
le processus. Si ce fichier ne comporte pas de point d'entrée, ce
champ contient zéro.
- e_phoff
- Ce membre contient le déplacement en octets de la table contenant
l'en-tête de programme. Si ce fichier ne comporte pas de table
d'en-tête de programme, ce champ contient zéro.
- e_shoff
- Ce membre contient le déplacement en octets de la table des
en-têtes de sections. Si ce fichier ne comporte pas de table des
en-têtes des sections, ce champ contient zéro.
- e_flags
- Ce membre contient des drapeaux spécifiques au processeur
associés au fichier. Le nom de ces drapeaux est de la forme
EF_machine_drapeau. À l'heure actuelle, aucun drapeau n'a
été défini.
- e_ehsize
- Ce membre contient la taille de l'en-tête ELF en octets.
- e_phentsize
- Ce membre contient la taille en octets d'une entrée de la table
d'en-tête de programme ; toutes les entrées sont de
même taille.
- e_phnum
- Ce membre contient le nombre d'entrées de la table d'en-tête
de programme. Ainsi, la taille en octets de la table pourra être
obtenue en multipliant e_phentsize par e_phnum. Si un
fichier ne comporte pas d'en-tête de programme, e_phnum
contiendra la valeur zéro.
- Si le nombre d'entrées de la table d'en-tête de programme
est supérieur ou égal à PN_XNUM (0xffff), ce
membre contient PN_XNUM (0xffff) et le nombre réel
d'entrées dans la table d'en-tête de programme est
stocké dans le membre sh_info de l'entrée initiale de
la table des en-têtes de sections. Dans le cas contraire, le membre
sh_info de l'entrée initiale de la table des en-têtes
de sections contient la valeur zéro.
- PN_XNUM
- Ce nombre est défini comme 0xffff, le plus grand nombre que
e_phnum peut valoir, qui spécifie où le nombre
réel d'en-têtes de programme est assigné.
- e_shentsize
- Ce membre 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 sections ; toutes les entrées sont de
même taille.
- e_shnum
- Ce membre contient le nombre d'entrées de la table des
en-têtes de sections. Ainsi, la taille en octets de la table des
en-têtes de sections pourra être obtenue en multipliant
e_shentsize par e_shnum. Si un fichier ne comporte pas de
table des en-têtes de sections, le champ e_shnum contiendra
zéro.
- Si le nombre d'entrées de la table des en-têtes de sections
est supérieur ou égal à SHN_LORESERVE
(0xff00), e_shnum contient la valeur zéro et le nombre
réel d'entrées dans la table des en-têtes de sections
est stocké dans le membre sh_size de l'entrée
initiale de la table des en-têtes de sections. Dans le cas
contraire, le membre sh_size de l'entrée initiale de la
table des en-têtes de sections contient la valeur zéro.
- e_shstrndx
- Ce membre contient l'indice dans la table des en-têtes de sections
de l'entrée associée à la table des chaînes de
noms des sections. Si le fichier ne comporte pas de table des
chaînes de noms des sections, ce champ contiendra la valeur
SHN_UNDEF.
- Si l'indice de la section de la table des chaînes de noms des
sections est supérieur ou égal à SHN_LORESERVE
(0xff00), ce membre contient la valeur SHN_XINDEX (0xffff) et
l'indice réel de la section de la table des chaînes de noms
des sections est stocké dans le membre sh_link de
l'entrée initiale de la table des en-têtes de sections. Dans
le cas contraire, le membre sh_link de l'entrée initiale de
la table des en-têtes de sections contient la valeur
zéro.
En-tête de programme (Phdr)
La table d'en-tête de programme d'un exécutable ou
d'un fichier objet partagé est un tableau de structures, chacune
d'entre elles décrivant un segment ou d'autres informations dont le
système a besoin pour préparer l'exécution du
programme. Un segment de fichier objet contient une ou plusieurs
sections. L'en-tête de programme n'a de sens que pour les
fichiers objets partagés ou les fichiers exécutables. Un
fichier indique la taille de son propre en-tête de programme à
l'aide des membres e_phentsize et e_phnum de l'en-tête
ELF. Selon l'architecture, l'en-tête de programme ELF est
représenté par un type Elf32_Phdr ou un type
Elf64_Phdr :
typedef struct {
uint32_t p_type;
Elf32_Off p_offset;
Elf32_Addr p_vaddr;
Elf32_Addr p_paddr;
uint32_t p_filesz;
uint32_t p_memsz;
uint32_t p_flags;
uint32_t p_align;
} Elf32_Phdr;
typedef struct {
uint32_t p_type;
uint32_t p_flags;
Elf64_Off p_offset;
Elf64_Addr p_vaddr;
Elf64_Addr p_paddr;
uint64_t p_filesz;
uint64_t p_memsz;
uint64_t p_align;
} Elf64_Phdr;
La principale différence entre l'en-tête d'un
programme 32 bits et l'en-tête d'un programme 64 bits
repose sur l'emplacement du champ p_flags au sein de la structure
complète.
- p_type
- Ce membre de la structure indique le type de segment décrit par cet
élément de tableau ou comment interpréter ses
informations.
- PT_NULL
- Cet élément du tableau est inutilisé et les valeurs
des autres membres ne sont pas définies. Cela permet à
l'en-tête de programme de contenir des entrées qui ne sont
pas prises en compte.
- PT_LOAD
- Cet élément du tableau indique un segment chargeable,
décrit par p_filesz et p_memsz. Les octets du fichier
sont projetés au début du segment mémoire. Si la
taille mémoire du segment p_memsz est plus grande que la
taille du fichier p_filesz, les octets
« supplémentaires » sont définis
comme contenant la valeur 0 et placés à la suite de la zone
initialisée du segment. La taille du fichier ne peut être
supérieure à la taille de la mémoire. Dans la table
d'en-tête de programme, les entrées de segments chargeables
sont indiquées par ordre croissant, classées selon le membre
p_vaddr.
- PT_DYNAMIC
- L'élément de tableau contient des informations de liaison
dynamique.
- PT_INTERP
- L'élément de tableau contient l'emplacement et la taille du
nom de chemin, terminé par un octet NULL, utilisé pour
invoquer l'interpréteur. Ce type de segment n'a de sens que pour
des fichiers exécutables (bien qu'il puisse être
présent dans des objets partagés). Il ne peut être
présent qu'une seule fois dans un fichier. S'il est présent,
il doit précéder chaque entrée de segment
chargeable.
- PT_NOTE
- L'élément de tableau spécifie l'emplacement de notes
(ElfN_Nhdr).
- PT_SHLIB
- Ce type de segment est réservé, mais sa sémantique
n'est pas définie. Les programmes contenant un tel
élément de tableau ne sont pas conformes à
l'interface binaire (ABI).
- PT_PHDR
- L'élément de tableau, s'il est présent, contiendra
l'emplacement 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 peut être
présent qu'une seule fois dans un fichier. Qui plus est, il ne peut
être présent que si l'en-tête de programme fait
partie de l'image mémoire du programme. S'il est présent, il
doit précéder chaque entrée de segment
chargeable.
- PT_LOPROC
- PT_HIPROC
- Les valeurs comprises dans la plage inclusive [PT_LOPROC,
PT_HIPROC] sont réservées à des
sémantiques spécifiques au processeur.
- PT_GNU_STACK
- Extension GNU qui est utilisée par le noyau de Linux pour
contrôler l'état de la pile à l'aide de l'indicateur
positionné dans le membre p_flags.
- p_offset
- Ce membre contient le déplacement du premier octet du segment par
rapport au début du fichier.
- p_vaddr
- Ce membre contient l'adresse virtuelle à laquelle se trouve en
mémoire le premier octet du segment.
- p_paddr
- Sur les systèmes pour lesquels l'adresse physique est pertinente,
ce membre est réservé pour l'adresse physique du segment.
Sous BSD, ce champ n'est pas utilisé et doit avoir la valeur
zéro.
- p_filesz
- Ce membre contient la taille en octets dans l'image du fichier de ce
segment. Il peut être égal à zéro.
- p_memsz
- Ce membre contient la taille en octets de l'image mémoire de ce
segment. Il peut être égal à zéro.
- p_flags
- Ce membre contient un masque de bits d'options relatives au
segment :
- PF_X
- Segment exécutable.
- PF_W
- Segment accessible en écriture.
- PF_R
- Segment accessible en lecture.
- Un segment de texte est souvent affecté des drapeaux PF_X et
PF_R. Un segment de données est souvent affecté des
drapeaux PF_W et PF_R.
- p_align
- Ce membre contient la valeur selon laquelle les segments sont
alignés en mémoire et dans le fichier. Pour des segments de
processus chargeables, les valeurs p_vaddr et p_offset
doivent être congrues modulo la taille de la page. Des valeurs de
zéro ou de un indiquent qu'aucun alignement n'est
nécessaire. Sinon, p_align doit être un nombre
positif, puissance entière de deux, et p_vaddr doit
être égal à p_offset modulo
p_align.
En-tête de section (Shdr)
La table des en-têtes de sections d'un fichier permet de
retrouver toutes les sections du fichier. C'est un tableau de structures
Elf32_Shdr ou Elf64_Shdr. Le champ e_shoff de
l'en-tête ELF donne son déplacement en octets depuis le
début du fichier. e_shnum contient le nombre d'entrées
que contient la table des en-têtes de sections. e_shentsize
contient la taille en octets de chaque entrée.
Un indice de la table des en-têtes de sections est un
indice de ce tableau. Certains de ces indices de table des en-têtes
de sections sont réservés : l'entrée initiale et
toutes les entrées comprises entre SHN_LORESERVE et
SHN_HIRESERVE. L'entrée initiale est utilisée par des
extensions ELF pour e_phnum, e_shnum et
e_shstrndx ; dans les autres cas, chaque champ de
l'entrée initiale est mis à zéro. Un fichier objet ne
contient pas de section correspondant à ces indices
spéciaux :
- SHN_UNDEF
- Cette valeur indique une référence de section non
définie, manquante, non pertinente ou, d'une manière ou
d'une autre, sans signification.
- SHN_LORESERVE
- Cette valeur indique la borne inférieure de la plage des indices
réservés.
- SHN_LOPROC
- SHN_HIPROC
- Les valeurs supérieures dans la plage inclusive [SHN_LOPROC,
SHN_HIPROC] sont réservées à des
sémantiques spécifiques au processeur.
- SHN_ABS
- Cette valeur définit la valeur absolue de la
référence correspondante. Par exemple, un symbole
défini par rapport à la section numéro SHN_ABS
a une valeur absolue et n'est pas affecté par un
repositionnement.
- SHN_COMMON
- Les symboles définis par rapport à cette section sont des
symboles communs, comme des COMMON Fortran ou des variables
externes C non allouées.
- SHN_HIRESERVE
- Cette valeur indique la borne supérieure de la plage des indices
réservés. Le système réserve les indices
compris entre SHN_LORESERVE et SHN_HIRESERVE, inclus. La
table des en-têtes de sections ne contient pas d'entrée pour
les indices réservés.
L'en-tête de section a la structure suivante :
typedef struct {
uint32_t sh_name;
uint32_t sh_type;
uint32_t sh_flags;
Elf32_Addr sh_addr;
Elf32_Off sh_offset;
uint32_t sh_size;
uint32_t sh_link;
uint32_t sh_info;
uint32_t sh_addralign;
uint32_t sh_entsize;
} Elf32_Shdr;
typedef struct {
uint32_t sh_name;
uint32_t sh_type;
uint64_t sh_flags;
Elf64_Addr sh_addr;
Elf64_Off sh_offset;
uint64_t sh_size;
uint32_t sh_link;
uint32_t sh_info;
uint64_t sh_addralign;
uint64_t sh_entsize;
} Elf64_Shdr;
Il n'y a pas de réelle différence entre les
en-têtes des sections 32 bits et 64 bits.
- sh_name
- Ce membre indique le nom de la section. Sa valeur est un indice de la
table des chaînes des en-têtes de sections, contenant
l'emplacement d'une chaîne terminée par un octet NULL.
- sh_type
- Ce membre définit le contenu et la sémantique de la
section.
- SHT_NULL
- Cette valeur indique que cet en-tête de section est inactif. Il
n'est donc associé à aucune section. Les valeurs des autres
champs de l'en-tête de section ne sont pas définies.
- SHT_PROGBITS
- Cette section contient des informations définies par le programme,
dont le format et le sens ne sont déterminés que par
celui-ci.
- SHT_SYMTAB
- Cette section contient une table de symboles. Typiquement,
SHT_SYMTAB contient des symboles pour l'édition de liens,
bien qu'elle puisse aussi être utilisée pour la liaison
dynamique. Comme il s'agit d'une table de symboles complète, elle
peut contenir de nombreux symboles inutiles à la liaison dynamique.
Un fichier objet peut aussi contenir une section SHT_DYNSYM.
- SHT_STRTAB
- Cette section contient une table de chaînes. Un fichier objet peut
contenir plusieurs sections de ce type.
- SHT_RELA
- Cette section contient des entrées de repositionnement ayant des
additifs explicites, par exemple les entrées du type
Elf32_Rela pour les fichiers objets 32 bits. Un objet peut
avoir plusieurs sections de ce type.
- SHT_HASH
- Cette section contient une table de hachage pour les symboles. Un objet
participant à une liaison dynamique doit en contenir une. Un
fichier objet ne peut contenir qu'une seule table de hachage.
- SHT_DYNAMIC
- Cette section contient les informations de liaison dynamique. Un fichier
objet ne peut contenir qu'une seule section dynamique.
- SHT_NOTE
- Cette section contient des notes (ElfN_Nhdr).
- SHT_NOBITS
- Une section de ce type ressemble à SHT_PROGBITS mais
n'occupe pas d'espace dans le fichier. Bien que cette section ne contienne
aucun octet, le membre sh_offset contient son déplacement
théorique dans le fichier.
- SHT_REL
- Cette section contient des entrées de repositionnement sans additif
explicite, par exemple du type Elf32_Rel pour les fichiers objets
de la classe de 32 bits. Un objet peut contenir plusieurs sections
de repositionnement.
- SHT_SHLIB
- Cette section est réservée et sa sémantique n'est pas
définie.
- SHT_DYNSYM
- Cette section contient un jeu minimal de symboles de liaison dynamique. Un
fichier objet peut aussi contenir une section SHT_SYMTAB.
- SHT_LOPROC
- SHT_HIPROC
- Les valeurs comprises dans la plage inclusive [SHT_LOPROC,
SHT_HIPROC] sont réservées à des
sémantiques spécifiques au processeur.
- SHT_LOUSER
- Cette valeur indique la borne inférieure de la plage des indices
réservés aux programmes applicatifs.
- SHT_HIUSER
- Cette valeur indique la borne supérieure de la plage des indices
réservés aux programmes applicatifs. Les types de section
entre SHT_LOUSER et SHT_HIUSER peuvent être
utilisés par l'application, sans que cela n'entre en conflit avec
les types de section actuels ou futurs définis par le
système.
- sh_flags
- Les sections contiennent des indicateurs sous forme d'un bit
décrivant divers attributs. Si, dans sh_flags, le bit
correspondant à un indicateur est positionné, l'attribut est
« activé » pour cette section. Sinon,
l'attribut est « désactivé » ou
ne s'applique pas. Les attributs non définis sont mis à
zéro.
- SHF_WRITE
- Cette section contient des données qu'il devrait être
possible d'écrire durant l'exécution du processus.
- SHF_ALLOC
- Cette section est présente en mémoire durant
l'exécution du processus. Certaines sections de contrôle ne
sont pas présentes dans l'image mémoire d'un fichier objet.
Cet attribut est désactivé pour ces sections.
- SHF_EXECINSTR
- Cette section contient des instructions machine exécutables.
- SHF_MASKPROC
- Tous les bits contenus dans ce masque sont réservés à
des sémantiques spécifiques au processeur.
- sh_addr
- Si cette section apparaît dans l'image mémoire d'un
processus, ce membre contient l'adresse à laquelle le premier octet
de la section doit se trouver. Sinon, ce membre contient zéro.
- sh_offset
- La valeur de ce membre indique le déplacement du premier octet de
la section par rapport au début du fichier. Une section de type
SHT_NOBITS, n'occupe pas de place dans le fichier et son champ
sh_offset indique son emplacement théorique dans le
fichier.
- sh_size
- Ce membre contient la taille en octets de la section. À moins que
cette section ne soit de type SHT_NOBITS, elle occupe
sh_size octets dans le fichier. Une section de type
SHT_NOBITS peut avoir une taille différente de zéro,
mais elle n'occupera cependant aucune place dans le fichier.
- sh_link
- Ce membre contient un lien vers un indice de la table des en-têtes
de sections, son interprétation dépend du type de
section.
- sh_info
- Ce membre contient des informations complémentaires, son
interprétation dépend du type de section.
- sh_addralign
- Certaines sections ont des contraintes d'alignement d'adresse. Si une
section contient un mot double, le système doit s'assurer que la
section tout entière est alignée sur les mots doubles.
Autrement dit, la valeur de sh_addr doit être congrue
à zéro modulo la valeur de sh_addralign. Seules
zéro ou des puissances entières positives de deux sont
autorisés. Une valeur de zéro ou de un indique qu'aucune
contrainte d'alignement ne s'applique à la section.
- sh_entsize
- Certaines sections contiennent une table d'entrées de taille fixe,
comme les tables de symboles. Pour de telles sections, ce champ donne la
taille en octets de chaque entrée. Ce membre contient zéro
si cette section ne contient pas une table de ce type.
Diverses sections contiennent des informations de contrôle
et sur le programme :
- .bss
- Cette section contient des données non initialisées qui
contribuent à l'image mémoire du programme. Par
définition, le système initialise ces données avec
des zéros lorsque le programme démarre. Cette section est du
type SHT_NOBITS. Les types de ses attributs sont SHF_ALLOC
et SHF_WRITE.
- .comment
- Cette section contient des informations de suivi des versions. Cette
section est du type SHT_PROGBITS. Aucun attribut n'est
utilisé.
- .ctors
- Cette section contient des pointeurs initialisés vers des
constructeurs C++. Cette section est du type SHT_PROGBITS. Les
types de ses attributs sont SHF_ALLOC et SHF_WRITE.
- .data
- Cette section contient des données initialisées qui
contribuent à l'image mémoire du programme. Elle est du type
SHT_PROGBITS. Les types de ses attributs sont SHF_ALLOC et
SHF_WRITE.
- .data1
- Cette section contient des données initialisées qui
contribuent à l'image mémoire du programme. Elle est du type
SHT_PROGBITS. Les types de ses attributs sont SHF_ALLOC et
SHF_WRITE.
- .debug
- Cette section contient des données de débogage symbolique.
Son contenu n'est pas précisé. Elle est du type
SHT_PROGBITS. Aucun type d'attribut n'est utilisé.
- .dtors
- Cette section contient des pointeurs initialisés vers des
destructeurs C++. Elle est du type SHT_PROGBITS. Les types de ses
attributs sont SHF_ALLOC et SHF_WRITE.
- .dynamic
- Cette section contient des informations de liaison dynamique. Les
attributs de cette section comprennent le bit SHF_ALLOC. Le
positionnement du bit SHF_WRITE est spécifique au
processeur. Cette section est du type SHT_DYNAMIC. Voir ci-dessus
pour les attributs.
- .dynstr
- Cette section contient les chaînes nécessaires à la
liaison dynamique, le plus souvent les chaînes représentant
les noms associés aux entrées de la table des symboles.
Cette section est du type SHT_STRTAB. Le type d'attribut
utilisé est SHF_ALLOC.
- .dynsym
- Cette section contient la table des symboles de liaison dynamique. Cette
section est du type SHT_DYNSYM. Le type d'attribut utilisé
est SHF_ALLOC.
- .fini
- Cette section contient des instructions exécutables qui font partie
du code de fin du processus. Lorsqu'un programme se termine normalement,
le système organise l'exécution du code de cette section.
Elle est du type SHT_PROGBITS. Les attributs utilisés sont
SHF_ALLOC et SHF_EXECINSTR.
- .gnu.version
- Cette section contient la table des symboles de version, un tableau
d'éléments ElfN_Half. Cette section est du type
SHT_GNU_versym. Le type d'attribut utilisé est
SHF_ALLOC.
- .gnu.version_d
- Cette section contient les définitions de version de symboles, une
table de structures ElfN_Verdef. Cette section est du type
SHT_GNU_verdef. Le type d'attribut utilisé est
SHF_ALLOC.
- .gnu.version_r
- Cette section contient la version de symbole des éléments
nécessaires, une table de structures ElfN_Verneed. Cette
section est du type SHT_GNU_versym. Le type d'attribut
utilisé est SHF_ALLOC.
- .got
- Cette section contient la table globale des déplacements. Elle est
du type SHT_PROGBITS. Les attributs sont spécifiques au
processeur.
- .hash
- Cette section contient la table de hachage des symboles. Elle est du type
SHT_HASH. L'attribut utilisé est SHF_ALLOC.
- .init
- Cette section contient des instructions exécutables qui font partie
du code d'initialisation du processus. Lorsqu'un programme démarre,
le système organise l'exécution du code de cette section
avant d'appeler le point d'entrée principal du programme. Cette
section est du type SHT_PROGBITS. Les attributs utilisés
sont SHF_ALLOC et SHF_EXECINSTR.
- .interp
- Cette section contient le chemin vers un interpréteur de
programmes. Si le fichier comporte un segment chargeable contenant cette
section, les attributs de la section contiendront le bit SHF_ALLOC.
Sinon, ce bit sera désactivé. Cette section est du type
SHT_PROGBITS.
- .line
- Cette section contient des informations sur les numéros de lignes,
qui seront utilisées pour le débogage symbolique. Ces
informations établissent la correspondance entre le code source du
programme et le code machine. Le contenu de cette section n'est pas
spécifié. Cette section est du type SHT_PROGBITS.
Aucun attribut n'est utilisé.
- .note
- Cette section contient diverses notes. Elle est du type SHT_NOTE.
Aucun type d'attribut.
- .note.ABI-tag
- Cette section est utilisée pour déclarer l'ABI
d'exécution attendue de l'image ELF. Elle peut comprendre le nom du
système d'exploitation et ses versions d'exécution. Cette
section est du type SHT_NOTE. Le seul attribut utilisé est
SHF_ALLOC.
- .note.gnu.build-id
- Cette section est utilisée pour conserver un identifiant unique du
contenu de l'image ELF. Différents fichiers avec le même
identifiant de construction pourraient contenir le même contenu
exécutable. Voir l'option --build-id de l'éditeur de
liens GNU (ld(1)) pour plus de détails. Cette section est du
type SHT_NOTE. Le seul attribut utilisé est
SHF_ALLOC.
- .note.GNU-stack
- Cette section est utilisée dans les fichiers objets de Linux pour
déclarer les attributs de la pile. Cette section est du type
SHT_PROGBITS. Le seul attribut utilisé est
SHF_EXECINSTR. Cela indique à l'éditeur de liens GNU
que le fichier objet requiert une pile exécutable.
- .note.openbsd.ident
- Les exécutables natifs d'OpenBSD contiennent en
général une section .note.openbsd.ident leur
permettant de s'identifier afin que le noyau court-circuite, lors du
chargement du fichier, tous les tests de compatibilité de
l'émulation binaire ELF.
- .plt
- Cette section contient une table de liaison des procédures. Elle
est du type SHT_PROGBITS. Ses attributs sont spécifiques au
processeur.
- .relNOM
- Cette section contient des informations de repositionnement, comme
décrit ci-dessous. Si ce fichier comporte un segment chargeable
comprenant du repositionnement, les attributs de la section contiendront
le bit SHF_ALLOC. Sinon, ce bit sera désactivé. Par
convention, le « NOM » est fourni par la
section à laquelle le repositionnement s'applique. Ainsi, une
section de repositionnement pour du .text s'appellera normalement
.rel.text. Cette section est du type SHT_REL.
- .relaNOM
- Cette section contient des informations de repositionnement, comme
décrit ci-dessous. Si ce fichier comporte un segment chargeable
comprenant du repositionnement, les attributs de la section contiendront
le bit SHF_ALLOC. Sinon, ce bit sera désactivé. Par
convention, le « NOM » est fourni par la
section à laquelle le repositionnement s'applique. Ainsi, une
section de repositionnement pour du .text s'appellera normalement
.rela.text. Cette section est du type SHT_RELA.
- .rodata
- Cette section contient des données en lecture seule, qui feront
classiquement partie d'un segment non accessible en écriture dans
l'image du processus. Cette section est du type SHT_PROGBITS.
L'attribut utilisé est SHF_ALLOC.
- .rodata1
- Cette section contient des données en lecture seule, qui feront
classiquement partie d'un segment non accessible en écriture dans
l'image du processus. Cette section est du type SHT_PROGBITS.
L'attribut utilisé est SHF_ALLOC.
- .shstrtab
- Cette section contient les noms des sections. Elle est du type
SHT_STRTAB. Aucun type d'attribut.
- .strtab
- Cette section contient des chaînes, le plus souvent ces
chaînes représentent les noms associés aux
entrées de la table des symboles. Si ce fichier comporte un segment
chargeable comprenant la table des chaînes de symboles, les
attributs de la section contiendront le bit SHF_ALLOC. Sinon, ce
bit sera désactivé. Cette section est du type
SHT_STRTAB.
- .symtab
- Cette section contient une table des symboles. Si ce fichier comporte un
segment chargeable contenant la table des symboles, les attributs de la
section contiendront le bit SHF_ALLOC. Sinon, ce bit sera
désactivé. Cette section est du type SHT_SYMTAB.
- .text
- Cette section contient le « texte », autrement
dit les instructions exécutables, d'un programme. Cette section est
du type SHT_PROGBITS. Les attributs utilisés sont
SHF_ALLOC et SHF_EXECINSTR.
Les sections de tables de chaînes contiennent des
séquences de caractères terminées par un octet NULL,
communément appelées chaînes. Le fichier objet utilise
ces chaînes pour représenter les noms des symboles et des
sections. Une chaîne peut être vue comme un indice dans la
section de table de chaînes. Le premier octet, qui est l'indice
zéro, est défini comme contenant un octet
NULL(« \0 »). De même, le dernier octet
de la table de chaînes est défini comme contenant un octet
NULL, ce qui assure que toutes les chaînes se termineront bien par un
octet NULL.
La table des symboles d'un fichier objet contient les informations
permettant de localiser et de repositionner les définitions et
références symboliques d'un programme. Un indice dans une
table de symbole est un indice de ce tableau.
typedef struct {
uint32_t st_name;
Elf32_Addr st_value;
uint32_t st_size;
unsigned char st_info;
unsigned char st_other;
uint16_t st_shndx;
} Elf32_Sym;
typedef struct {
uint32_t st_name;
unsigned char st_info;
unsigned char st_other;
uint16_t st_shndx;
Elf64_Addr st_value;
uint64_t st_size;
} Elf64_Sym;
Les versions 32 bits et 64 bits comportent les mêmes
membres, seul leur ordre diffère.
- st_name
- Ce membre contient un indice de la table des chaînes de symboles
d'un fichier objet. Cette table contient la représentation sous la
forme de chaînes de caractères des noms des symboles. Si la
valeur de ce champ est différente de zéro, il
représente l'indice de la table des chaînes qui donne son
nom au symbole. Sinon, le symbole n'a pas de nom.
- st_value
- Ce membre donne la valeur associée au symbole.
- st_size
- De nombreux symboles sont associés à des tailles. Ce champ
contient zéro si le symbole n'a pas de taille ou si sa taille est
inconnue.
- st_info
- Ce membre indique le type de symbole et ses attributs de
liaison :
- STT_NOTYPE
- Le type de ce symbole n'est pas défini.
- STT_OBJECT
- Ce symbole est associé à un objet de données.
- STT_FUNC
- Ce symbole est associé à une fonction ou un autre code
exécutable.
- STT_SECTION
- Ce symbole est associé à une section. Les entrées de
ce type de la table des symboles existent principalement pour le
repositionnement et ont normalement des liaisons STB_LOCAL.
- STT_FILE
- Par convention, le nom de ce symbole donne le nom du fichier source
associé au fichier objet. Un symbole de ce type a des liaisons
STB_LOCAL, son indice de section est SHN_ABS, et, s'il est
présent, il précède les autres symboles
STB_LOCAL du fichier.
- STT_LOPROC
- STT_HIPROC
- Les valeurs comprises dans la plage inclusive [STT_LOPROC,
STT_HIPROC] incluse sont réservées à des
sémantiques spécifiques au processeur.
- STB_LOCAL
- Les symboles locaux ne sont pas visibles en dehors du fichier objet
contenant leur définition. Des symboles locaux de même nom
peuvent exister dans plusieurs fichiers sans interférer entre
eux.
- STB_GLOBAL
- Les symboles globaux sont visibles de tous les fichiers objets devant
être réunis. La définition par un fichier d'un
symbole global satisfera une référence non définie
d'un autre fichier à ce même symbole.
- STB_WEAK
- Les symboles faibles ressemblent à des symboles globaux, mais leur
définition a une priorité plus faible.
- STB_LOPROC
- STB_HIPROC
- Les valeurs comprises dans la plage inclusive [STB_LOPROC,
STB_HIPROC] incluse sont réservées à des
sémantiques spécifiques au processeur.
- Il existe des macros permettant d”empaqueter et dépaqueter
les champs de type et de liaison :
- st_other
- Ce membre définit la visibilité du symbole.
- STV_DEFAULT
- Règles de visibilité des symboles par défaut. Les
symboles globaux et les symboles faibles sont disponibles pour d'autres
modules ; les définitions dans d'autres modules peuvent
s'interposer dans les références du module local.
- STV_INTERNAL
- Classe cachée spécifique au processeur.
- STV_HIDDEN
- Le symbole n'est pas disponible pour d'autres modules ; les
références du module local se résolvent toujours dans
le symbole local (c'est-à-dire les définitions des autres
modules ne peuvent s'interposer dans le symbole).
- STV_PROTECTED
- Le symbole est disponible pour d'autres modules, mais les
références du module local se résolvent toujours dans
le symbole local.
Il existe des macros permettant d'extraire le type de
visibilité :
ELF32_ST_VISIBILITY(autre) ou
ELF64_ST_VISIBILITY(autre)
- st_shndx
- Chaque entrée de la table des symboles est
« définie » en relation avec une
section. Ce membre contient l'indice correspondant de la table des
en-têtes de sections.
Le repositionnement est le processus consistant à relier
des références symboliques à des définitions
symboliques. Les fichiers repositionnables doivent contenir des informations
décrivant comment modifier le contenu de leurs sections, ce qui
permet aux fichiers objets partagés et exécutables de
détenir les bonnes informations concernant l'image mémoire
d'un programme. Les entrées de repositionnement sont ces
données.
Structures de repositionnement pour lesquelles un additif n'est
pas nécessaire :
typedef struct {
Elf32_Addr r_offset;
uint32_t r_info;
} Elf32_Rel;
typedef struct {
Elf64_Addr r_offset;
uint64_t r_info;
} Elf64_Rel;
Structures de repositionnement pour lesquelles un additif est
nécessaire :
typedef struct {
Elf32_Addr r_offset;
uint32_t r_info;
int32_t r_addend;
} Elf32_Rela;
typedef struct {
Elf64_Addr r_offset;
uint64_t r_info;
int64_t r_addend;
} Elf64_Rela;
- r_offset
- Ce membre donne l'emplacement où appliquer l'action de
repositionnement. Pour un fichier repositionnable, sa valeur est le
déplacement en octets depuis le début de la section
jusqu'à l'unité de stockage affectée par le
repositionnement. Pour un fichier exécutable ou un objet
partagé, sa valeur est l'adresse virtuelle de l'unité de
stockage affectée par le repositionnement.
- r_info
- Ce membre donne à la fois l'indice de la table des symboles par
rapport auquel on doit effectuer le repositionnement et le type de
repositionnement à appliquer. Les types de repositionnement
dépendent du processeur. Lorsque le texte mentionne le type de
repositionnement ou l'indice de la table des symboles d'une entrée
de repositionnement, il s'agit du résultat de l'application de
ELF[32|64]_R_TYPE ou ELF[32|64]_R_SYM, respectivement, au
champ r_info de cette entrée.
- r_addend
- Ce membre indique un additif constant pour le calcul de la valeur à
stocker dans le champ repositionnable.
Étiquettes dynamiques (Dyn)
La section .dynamic comporte une série de structures
qui contiennent les informations relatives à l'édition de
liens dynamique. Le membre d_tag contrôle
l'interprétation de d_un.
typedef struct {
Elf32_Sword d_tag;
union {
Elf32_Word d_val;
Elf32_Addr d_ptr;
} d_un;
} Elf32_Dyn;
extern Elf32_Dyn _DYNAMIC[];
typedef struct {
Elf64_Sxword d_tag;
union {
Elf64_Xword d_val;
Elf64_Addr d_ptr;
} d_un;
} Elf64_Dyn;
extern Elf64_Dyn _DYNAMIC[];
- d_tag
- Ce membre peut prendre l'une des trois valeurs suivantes :
- DT_NULL
- Indication de la fin de la section dynamique
- DT_NEEDED
- Déplacement dans la table des chaînes vers le nom d'une
bibliothèque nécessaire
- DT_PLTRELSZ
- Taille en octets des entrées de repositionnement PLT
- DT_PLTGOT
- Adresse de PLT et/ou de GOT
- DT_HASH
- Adresse de la table de hachage des symboles
- DT_STRTAB
- Adresse de la table des chaînes
- DT_SYMTAB
- Adresse de la table des symboles
- DT_RELA
- Adresse de la table de repositionnement Rela
- DT_RELASZ
- Taille en octets de la table de repositionnement Rela
- DT_RELAENT
- Taille en octets d'une entrée de la table de repositionnement
Rela
- DT_STRSZ
- Taille en octets de la table des chaînes
- DT_SYMENT
- Taille en octets d'une entrée de la table des symboles
- DT_INIT
- Adresse de la fonction d'initialisation
- DT_FINI
- Adresse de la fonction de terminaison
- DT_SONAME
- Déplacement dans la table des chaînes vers le nom de l'objet
partagé
- DT_RPATH
- Déplacement dans la table des chaînes pour le chemin de
recherche des dépendances directes et indirectes de la
bibliothèque
- DT_SYMBOLIC
- Demander à l'éditeur de liens de rechercher les symboles
dans cet objet partagé avant l'exécutable
- DT_REL
- Adresse de la table de repositionnement Rel
- DT_RELSZ
- Taille en octets de la table de repositionnement Rela
- DT_RELENT
- Taille en octets d'une entrée de la table Rel
- DT_PLTREL
- Type d'entrée de repositionnement auquel se réfère
PLT (Rela ou Rel)
- DT_DEBUG
- Utilisation non définie pour le débogage
- DT_TEXTREL
- Son absence indique qu'aucune entrée de repositionnement ne devrait
s'appliquer à un segment non accessible en écriture
- DT_JMPREL
- Adresse des entrées de repositionnement, associées
uniquement à la PLT
- DT_BIND_NOW
- Enjoindre à l'éditeur de liens dynamique de traiter tous les
repositionnements avant de transférer le contrôle à
l'exécutable
- DT_RUNPATH
- Déplacement dans la table des chaînes pour le chemin de
recherche des dépendances directes de la bibliothèque
- DT_LOPROC
- DT_HIPROC
- Les valeurs comprises dans la plage inclusive [DT_LOPROC,
DT_HIPROC] sont réservées à des
sémantiques spécifiques au processeur.
- d_val
- Ce membre représente des valeurs entières ayant des
interprétations diverses.
- d_ptr
- Ce membre représente les adresses virtuelles du programme. Lors de
l'interprétation de ces adresses, l'adresse réelle doit
être calculée en se basant sur la valeur originale du
fichier et sur l'adresse de base de la mémoire. Les fichiers ne
contiennent pas d'entrées de repositionnement pour corriger ces
adresses.
- _DYNAMIC
- Tableau contenant toutes les structures dynamiques de la section
.dynamic. Cela est automatiquement rempli par l'éditeur de
liens.
Les notes d'ELF permettent d'ajouter des informations arbitraires
pour le système à utiliser. Elles sont largement
utilisées par les fichiers core (e_type de ET_CORE),
mais de nombreux projets définissent leur propre jeu d'extensions.
Par exemple, la chaîne de compilation GNU utilise les notes d'ELF
pour passer des informations de l'éditeur de liens à la
bibliothèque C.
Les sections note contiennent une série de notes (voir les
définitions struct plus loin). Chaque note est suivie par le
champ nom (dont la longueur est définie dans n_namesz), puis
par le champ descripteur (dont la longueur est définie dans
n_descsz) et dont l'adresse de départ a un alignement de
4 octets. Aucun champ n'est défini dans la structure de note
à cause de leur longueur arbitraire.
Un exemple pour analyser deux notes consécutives peut
clarifier leur disposition en mémoire :
void *memory, *name, *desc;
Elf64_Nhdr *note, *next_note;
/* Le tampon pointe vers le début de la section ou du segment. */
note = memory;
/* Si le descripteur est défini, il suit la note. */
name = note->n_namesz == 0 ? NULL : memory + sizeof(*note);
/* Si le descripteur est défini, il suit le nom*/
(avec l'alignement). */
desc = note->n_descsz == 0 ? NULL :
memory + sizeof(*note) + ALIGN_UP(note->n_namesz, 4);
/* La note suivante suit les deux (avec l'alignement). */
next_note = memory + sizeof(*note) +
ALIGN_UP(note->n_namesz, 4) +
ALIGN_UP(note->n_descsz, 4);
Garder en mémoire que l'interprétation de
n_type dépend de l'espace de noms défini par le champ
n_namesz. Si le champ n_namesz n'est pas défini (par
exemple, est 0), il y a deux jeux de notes : un pour les
fichiers core et un pour tous les autres types d'ELF. Si l'espace de noms
est inconnu, les outils se replieront aussi habituellement sur ces jeux de
notes.
typedef struct {
Elf32_Word n_namesz;
Elf32_Word n_descsz;
Elf32_Word n_type;
} Elf32_Nhdr;
typedef struct {
Elf64_Word n_namesz;
Elf64_Word n_descsz;
Elf64_Word n_type;
} Elf64_Nhdr;
- n_namesz
- La longueur du champ nom en octets. Le contenu suivra immédiatement
cette note dans la mémoire. Le nom se termine par un octet NULL.
Par exemple, si le nom est « GNU »,
n_namesz sera défini à 4.
- n_descsz
- La longueur du champ descripteur en octets. Le contenu suivra
immédiatement le champ du nom dans la mémoire.
- n_type
- Selon la valeur du champ nom, ce membre peut prendre l'une des trois
valeurs suivantes :
- Core files (e_type =
ET_CORE)
- Notes utilisées par les fichiers core. Elles sont très
spécifiques au système d'exploitation ou à
l'architecture et requièrent souvent une étroite
coordination avec les noyaux, les bibliothèques C et les
débogueurs. Elles sont utilisées quand l'espace de noms est
celui par défaut (c'est-à-dire n_namesz sera
défini à 0), ou un repli est utilisé quand
l'espace de noms est inconnu).
- n_name =
GNU
- Extensions utilisées par la chaîne de compilation GNU.
- NT_GNU_ABI_TAG
- Information sur l'ABI du système d'exploitation (OS). Le champ desc
sera composé de quatre mots :
- [0]
- descripteur du système d'exploitation (ELF_NOTE_OS_LINUX,
ELF_NOTE_OS_GNU, etc.)
- [1]
- version majeure de l'ABI
- [2]
- version mineure de l'ABI
- [3]
- version sous-mineure de l'ABI
- NT_GNU_HWCAP
- Information synthétique sur les capacités matérielles
(hwcap). Le champ desc commence par deux mots :
- [0]
- nombre d'entrées
- [1]
- masque de bits des entrées activées.
- Puis suivent les entrées à longueur variable, un octet suivi
d'une chaîne terminée par un octet NULL de nom de
« hwcap ». L'octet donne le numéro du
bit à tester s'il est activé, (1U << bit) & masque
de bits.
- NT_GNU_BUILD_ID
- Identifiant unique de construction tel que généré par
l'option --build-id de GNU ld(1). Le desc consiste en
n'importe quel nombre d'octets différent de zéro.
- NT_GNU_GOLD_VERSION
- Le desc contient la version de l'éditeur de liens Gold de GNU
utilisé.
- Default/unknown
namespace (e_type != ET_CORE)
- Elles sont utilisées quand l'espace de noms est celui par
défaut (c'est-à-dire n_namesz sera défini
à 0), ou un repli est utilisé quand l'espace de noms
est inconnu).
- NT_VERSION
- Une chaîne de version d'un certain type.
- NT_ARCH
- Information sur l'architecture.
as(1), elfedit(1), gdb(1), ld(1),
nm(1), objcopy(1), objdump(1), patchelf(1),
readelf(1), size(1), strings(1), strip(1),
execve(2), dl_iterate_phdr(3), core(5),
ld.so(8)
Hewlett-Packard, Format de fichiers Elf-64 (Elf-64
Object File Format).
Santa Cruz Operation, Interface binaire des applications
System V (System V Application Binary Interface).
UNIX System Laboratories, « Object
Files », Format des fichiers exécutables ELF
(Executable and Linking Format)
Sun Microsystems, Guide de l'éditeur de liens et des
bibliothèques (Linker and Libraries Guide).
Version préliminaire de l'ABI AMD64 (System V
Application Binary Interface. AMD64 Architecture Processor Supplement
– Interface binaire des applications System V).
La traduction française de cette page de manuel a
été créée par Christophe Blaess
<https://www.blaess.fr/christophe/>, Stéphan Rafin
<stephan.rafin@laposte.net>, Thierry Vignaud
<tvignaud@mandriva.com>, François Micaux, Alain Portal
<aportal@univ-montp2.fr>, Jean-Philippe Guérard
<fevrier@tigreraye.org>, Jean-Luc Coulon (f5ibh)
<jean-luc.coulon@wanadoo.fr>, Julien Cristau
<jcristau@debian.org>, Thomas Huriaux
<thomas.huriaux@gmail.com>, Nicolas François
<nicolas.francois@centraliens.net>, Florentin Duneau
<fduneau@gmail.com>, Simon Paillard
<simon.paillard@resel.enst-bretagne.fr>, Denis Barbier
<barbier@debian.org>, David Prévot <david@tilapin.org> et
Jean-Pierre Giraud <jean-pierregiraud@neuf.fr>
Cette traduction est une documentation libre ; veuillez
vous reporter à la
GNU General
Public License version 3 concernant les conditions de copie et de
distribution. Il n'y a aucune RESPONSABILITÉ LÉGALE.
Si vous découvrez un bogue dans la traduction de cette page
de manuel, veuillez envoyer un message à
debian-l10n-french@lists.debian.org.