2010-11-08 46 views
4
int i; 
int main() { 
    return i;  
} 

Après -static compilent readelf -l montre les en-têtes de programme d'Elf:sections programme fichier ELF TLS et CHARGE

Elf file type is EXEC (Executable file) 
Entry point 0xxxxx30 
There are 6 program headers, starting at offset 52 

Program Headers: 
    Type   Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align 
    LOAD   0x000000 0x08048000 0x08048000 0x79868 0x79868 R E 0x1000 
> LOAD   0x079f94 0x080c2f94 0x080c2f94 0x0078c 0x02254 RW 0x1000 << 
    NOTE   0x0000f4 0x080480f4 0x080480f4 0x00020 0x00020 R 0x4 
> TLS   0x079f94 0x080c2f94 0x080c2f94 0x00010 0x0002c R 0x4  << 
    GNU_STACK  0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0x4 
    PAX_FLAGS  0x000000 0x00000000 0x00000000 0x00000 0x00000  0x4 

Section to Segment mapping: 
    Segment Sections... 
    00  .note.ABI-tag .init .text __libc_freeres_fn .fini .rodata __libc_subfreeres __libc_atexit .eh_frame .gcc_except_table 
    01  .tdata .ctors .dtors .jcr .data.rel.ro .got .got.plt .data .bss __libc_freeres_ptrs 
    02  .note.ABI-tag 
    03  .tdata .tbss 

quelqu'un peut-il expliquer, pourquoi les 2e et 4e têtes de programme ne se croisent (ils commencent par même décalage 0x079f94 et VirtAddr 0x080c2f94).

En outre, la section de segment .tdata est référencée deux fois.

Comment PT_TLS et PT_LOAD seront chargés pour le premier thread (le programme lui-même)? Où se trouve .tbss dans la mémoire?

+0

ressemble à tls placé sur HEAP ... – osgx

+0

Vous pouvez vérifier comment TLS est chargé par grepping stracing pour 'set_thread_area' syscall – osgx

Répondre

3

Première section .tdata - est une "image initiale" de données TLS. Ce sont les valeurs initiales des variables TLS, qui seront utilisées dans chaque thread (et dans le thread principal aussi). Dans le crt (je suppose) il y a une copie de l'image initiale TLS dans TLS du fil principal. Le même code est dans pthread_create. PT_TLS n'est pas chargé, car PT_LOAD et PT_LOAD contiennent déjà ce PT_TLS. Je pense que PT_TLS est pour l'image initiale - car elle est plus courte que les données locales de threads entières (tbss + tdata> size (PT_TLS)).

2

TLS est l'abréviation de "Thread-Local Storage".

Pour permettre l'association de copies séparées de données allouées au moment de la compilation avec des threads d'exécution individuels, des sections de stockage local au thread peuvent être utilisées pour spécifier la taille et le contenu initial de ces données. Les implémentations ne supportent pas le stockage local. Une entrée de programme de PT_TLS a les membres suivants:

Member  Value 
p_offset File offset of the TLS initialization image 
p_vaddr Virtual memory address of the TLS initialization image 
p_paddr reserved 
p_filesz Size of the TLS initialization image 
p_memsz Total size of the TLS template 
p_flags PF_R 
p_align Alignment of the TLS template 

Le modèle TLS est formé de la combinaison de toutes les sections avec le drapeau SHF_TLS. La partie du modèle TLS qui contient les données initialisées est l'image d'initialisation TLS. (La partie restante du gabarit TLS est une ou plusieurs sections de type SHT_NOBITS.)

+0

ok. mais "Comment PT_TLS et PT_LOAD seront chargés pour le premier thread (le programme lui-même)?" est la question. – osgx

2

En ce qui concerne le mappage des régions de mémoire, je pense que le noyau ne regarde que les segments PT_LOAD et les mute. (Le noyau regarde aussi PT_GNU_STACK pour déterminer si la pile doit être mappée avec l'autorisation Execute ou pas.) Jetez un oeil à binfmt_elf.c: load_elf_binary() pour le code approprié.

Le segment PT_TLS est lu par libc pour déterminer la mémoire à configurer pour le stockage Thread-Local. Jetez un oeil à __libc_setup_tls() pour le code pertinent. Le segment PT_TLS croise le segment PT_LOAD pour qu'il soit mappé dans la mémoire de processus.