5 votes

Décalage de l'en-tête du programme ELF

J'écris manuellement un en-tête ELF exécutable+en-tête de programme comme ceci :

elf_head:
e_ident db      7Fh, 'ELF', 1, 1, 1
        times   9 db 0
e_type  dw      2                       ; ET_EXEC
e_mach  dw      3                       ; EM_386
e_ver   dd      1                       ; EV_CURRENT
e_entry dd      0x08048000+elf_head_len ; entry point
e_phoff dd      34h                     ; program header table offset
e_shoff dd      00h                     ; section header table offset
e_flags dd      0                       ; flags
e_elfhs dw      34h                     ; ELF header size
e_phes  dw      20h                     ; program header entry size
e_phec  dw      01h                     ; program header entries count
e_shes  dw      00h                     
e_shec  dw      00h                    
e_shsn  dw      00h                     
elf_ph:
p_type  dd      01h                     ; PT_LOAD
p_off   dd      elf_head_len        
p_vaddr dd      0x08048000+elf_head_len 
p_paddr dd      0x08048000+elf_head_len 
p_filsz dd      elf_head_len+file_len           
p_memsz dd      elf_head_len+file_len      
p_flags dd      7                       ; segment flags (RWX)
p_align dd      0x1000                  ; page_size==4096bytes
elf_head_len  equ  $ - elf_head

J'ai configuré le point du champ e_entry juste après le champ p_align où j'ai mis mon code dans le fichier en cours de création. Mais cela ne fonctionne pas ! Je suis un peu confus avec le champ p_offset. J'y ai placé un décalage entre le début du fichier (0x00) et le premier octet du code du segment. Comme le code du segment commence juste après le champ p_align, est-ce que j'entre correctement la valeur elf_head_len ? Lorsque j'essaie d'exécuter le nouvel exécutable créé, bash répond : Segmentation fault !

Ok, j'ai découvert que j'avais une erreur dans le programme qui a donné le défaut de segmentation. (désolé pour cela). Mais la question reste sur le champ p_off et je me rends compte aussi que si je mets p_off dd 0 et p_vaddr dd 0x08048000 et p_paddr dd 0x08048000 l'exécutable fonctionne. Il fonctionne également si j'entre p_off dd elf_head_len et p_vaddr dd 0x08048000+elf_head_len et p_paddr dd 0x08048000+elf_head_len. Cela me rappelle quelque chose que j'ai lu dans les spécifications du format ELF à propos des valeurs de p_off et p_vaddr qui doivent être congruentes (c'est-à-dire que je pense qu'elles doivent donner le même résultat lorsqu'elles sont modulées chacune avec la taille de la page). C'est pourquoi le programme fonctionne avec ces valeurs. La question qui se pose maintenant est la suivante : S'il y a une erreur dans la logique ci-dessus, veuillez envisager de la corriger.

4voto

Simon Richter Points 11471

La spécification ELF exige que pour les exécutables paginés à la demande, le décalage du fichier et l'adresse virtuelle d'un segment doivent effectivement correspondre dans les bits d'ordre inférieur.

Ces restrictions sont les mêmes que celles que le mmap() sur les mappings -- il n'accepte que les mappings à un décalage dans le fichier qui est un multiple de la taille de la page. Lors du mappage d'un fichier ELF, les segments sont étendus à la limite de page la plus proche, donc les bits d'ordre inférieur sont effectivement ignorés sauf pour le calcul de la taille du segment.

Cela peut s'expliquer par le fait que le périphérique sous-jacent peut déjà être mappé en mémoire - comme un tampon de trame ou une mémoire flash - auquel cas la création d'un mappage avec un décalage qui n'est pas aligné sur une page représenterait une surcharge importante.

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