Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset 6adb775f in mainline


Ignore:
Timestamp:
2016-04-25T16:46:31Z (6 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master
Children:
32573ff
Parents:
dc0d8b52
Message:

TLS for dynamically linked executables and initially loaded DSOs (but must not call dlopen or there will be trouble).

Files:
15 edited

Legend:

Unmodified
Added
Removed
  • abi/include/abi/elf.h

    rdc0d8b52 r6adb775f  
    170170#define PT_SHLIB    5
    171171#define PT_PHDR     6
     172#define PT_TLS      7
    172173#define PT_LOPROC   0x70000000
    173174#define PT_HIPROC   0x7fffffff
  • kernel/generic/src/lib/elf.c

    rdc0d8b52 r6adb775f  
    163163        case PT_LOAD:
    164164                return load_segment(entry, elf, as);
     165        case PT_TLS:
     166                break;
    165167        case PT_DYNAMIC:
    166168        case PT_INTERP:
  • uspace/lib/c/arch/ia32/_link.ld.in

    rdc0d8b52 r6adb775f  
    1212#endif
    1313        data PT_LOAD FLAGS(6);
     14        tls PT_TLS;
    1415#if defined(SHLIB) || defined(DLEXE)
    1516        dynamic PT_DYNAMIC;
     
    9596#endif
    9697       
     98        .tdata : {
    9799#ifndef DLEXE
    98         .tdata : {
    99100                _tdata_start = .;
     101#endif
    100102                *(.tdata);
    101103                *(.gnu.linkonce.tb.*);
     104#ifndef DLEXE
    102105                _tdata_end = .;
     106#endif
     107        } :data :tls
     108        .tbss : {
     109#ifndef DLEXE
    103110                _tbss_start = .;
     111#endif
    104112                *(.tbss);
     113#ifndef DLEXE
    105114                _tbss_end = .;
    106         } :data
     115#endif
     116        } :data :tls
    107117       
     118#ifndef DLEXE
    108119        _tls_alignment = ALIGNOF(.tdata);
    109120#endif
  • uspace/lib/c/arch/ia32/src/rtld/reloc.c

    rdc0d8b52 r6adb775f  
    171171                        break;
    172172
     173//              case R_386_TLS_DTPOFF32:
     174//                      *r_ptr = sym_def->st_value;
     175//                      break;
     176
    173177                case R_386_TLS_DTPMOD32:
    174                         /*
    175                          * We can ignore this as long as the only module
    176                          * with TLS variables is libc.so.
    177                          */
    178                         DPRINTF("Ignoring R_386_TLS_DTPMOD32\n");
     178                        *r_ptr = dest->id;
    179179                        break;
    180180
  • uspace/lib/c/arch/ia32/src/tls.c

    rdc0d8b52 r6adb775f  
    11/*
    22 * Copyright (c) 2006 Ondrej Palkovsky
     3 * Copyright (c) 2016 Jiri Svoboda
    34 * All rights reserved.
    45 *
     
    3940#include <align.h>
    4041
     42#ifdef CONFIG_RTLD
     43#include <rtld/rtld.h>
     44#endif
     45
    4146tcb_t *tls_alloc_arch(void **data, size_t size)
    4247{
     
    6873
    6974        /* Calculate size of TLS block */
    70         tls_size = ALIGN_UP(&_tbss_end - &_tdata_start, &_tls_alignment);
     75        tls_size = tls_get_size();
    7176
    7277        /* The TLS block is just before TCB */
    7378        tls = (uint8_t *)__tcb_get() - tls_size;
    7479
     80#ifdef CONFIG_RTLD
     81        if (runtime_env != NULL) {
     82                return rtld_tls_get_addr(runtime_env, tls, ti->ti_module,
     83                    ti->ti_offset);
     84        }
     85#endif
    7586        return tls + ti->ti_offset;
    7687}
  • uspace/lib/c/generic/elf/elf_mod.c

    rdc0d8b52 r6adb775f  
    248248}
    249249
     250/** Process TLS program header.
     251 *
     252 * @param elf  Pointer to loader state buffer.
     253 * @param hdr  TLS program header
     254 * @param info Place to store TLS info
     255 */
     256static void tls_program_header(elf_ld_t *elf, elf_segment_header_t *hdr,
     257    elf_tls_info_t *info)
     258{
     259        info->tdata = (void *)((uint8_t *)hdr->p_vaddr + elf->bias);
     260        info->tdata_size = hdr->p_filesz;
     261        info->tbss_size = hdr->p_memsz - hdr->p_filesz;
     262}
     263
    250264/** Process segment header.
    251265 *
     266 * @param elf   Pointer to loader state buffer.
    252267 * @param entry Segment header.
    253268 *
     
    277292        case 0x70000000:
    278293                /* FIXME: MIPS reginfo */
     294                break;
     295        case PT_TLS:
     296                /* Parse TLS program header */
     297                tls_program_header(elf, entry, &elf->info->tls);
     298                DPRINTF("TLS header found at %p\n",
     299                    (void *)((uint8_t *)entry->p_vaddr + elf->bias));
    279300                break;
    280301        case PT_SHLIB:
  • uspace/lib/c/generic/rtld/module.c

    rdc0d8b52 r6adb775f  
    3737#include <adt/list.h>
    3838#include <elf/elf_load.h>
     39#include <errno.h>
    3940#include <fcntl.h>
    4041#include <loader/pcb.h>
     
    129130        int rc;
    130131       
    131         m = malloc(sizeof(module_t));
    132         if (!m) {
     132        m = calloc(1, sizeof(module_t));
     133        if (m == NULL) {
    133134                printf("malloc failed\n");
    134135                exit(1);
     
    136137
    137138        m->rtld = rtld;
     139        m->id = rtld_get_next_id(rtld);
    138140
    139141        if (str_size(name) > NAME_BUF_SIZE - 2) {
     
    174176        /* Insert into the list of loaded modules */
    175177        list_append(&m->modules_link, &rtld->modules);
     178
     179        /* Copy TLS info */
     180        m->tdata = info.tls.tdata;
     181        m->tdata_size = info.tls.tdata_size;
     182        m->tbss_size = info.tls.tbss_size;
     183
     184        printf("tdata at %p size %zu, tbss size %zu\n",
     185            m->tdata, m->tdata_size, m->tbss_size);
    176186
    177187        return m;
     
    236246}
    237247
     248/** Find module structure by ID. */
     249module_t *module_by_id(rtld_t *rtld, unsigned long id)
     250{
     251        list_foreach(rtld->modules, modules_link, module_t, m) {
     252                if (m->id == id)
     253                        return m;
     254        }
     255
     256        return NULL;
     257}
     258
    238259/** Process relocations in modules.
    239260 *
     
    253274}
    254275
     276void modules_process_tls(rtld_t *rtld)
     277{
     278        list_foreach(rtld->modules, modules_link, module_t, m) {
     279                m->ioffs = rtld->tls_size;
     280                rtld->tls_size += m->tdata_size + m->tbss_size;
     281        }
     282}
     283
    255284/** Clear BFS tags of all modules.
    256285 */
  • uspace/lib/c/generic/rtld/rtld.c

    rdc0d8b52 r6adb775f  
    4343rtld_t *runtime_env;
    4444static rtld_t rt_env_static;
    45 static module_t prog_mod;
    4645
    4746/** Initialize the runtime linker for use in a statically-linked executable. */
     
    6261{
    6362        rtld_t *env;
     63        module_t *prog;
    6464
    6565        DPRINTF("Load dynamically linked program.\n");
     
    7070                return ENOMEM;
    7171
     72        env->next_id = 1;
     73
     74        prog = calloc(1, sizeof(module_t));
     75        if (prog == NULL) {
     76                free(env);
     77                return ENOMEM;
     78        }
     79
    7280        /*
    7381         * First we need to process dynamic sections of the executable
     
    7684
    7785        DPRINTF("Parse program .dynamic section at %p\n", p_info->dynamic);
    78         dynamic_parse(p_info->dynamic, 0, &prog_mod.dyn);
    79         prog_mod.bias = 0;
    80         prog_mod.dyn.soname = "[program]";
    81         prog_mod.rtld = env;
     86        dynamic_parse(p_info->dynamic, 0, &prog->dyn);
     87        prog->bias = 0;
     88        prog->dyn.soname = "[program]";
     89        prog->rtld = env;
     90        prog->id = rtld_get_next_id(env);
     91
     92        prog->tdata = p_info->tls.tdata;
     93        prog->tdata_size = p_info->tls.tdata_size;
     94        prog->tbss_size = p_info->tls.tbss_size;
     95
     96        printf("prog tdata at %p size %zu, tbss size %zu\n",
     97            prog->tdata, prog->tdata_size, prog->tbss_size);
    8298
    8399        /* Initialize list of loaded modules */
    84100        list_initialize(&env->modules);
    85         list_append(&prog_mod.modules_link, &env->modules);
     101        list_append(&prog->modules_link, &env->modules);
    86102
    87103        /* Pointer to program module. Used as root of the module graph. */
    88         env->program = &prog_mod;
     104        env->program = prog;
    89105
    90106        /* Work around non-existent memory space allocation. */
     
    96112
    97113        DPRINTF("Load all program dependencies\n");
    98         module_load_deps(&prog_mod);
     114        module_load_deps(prog);
    99115
    100116        /*
     
    104120        /* Process relocations in all modules */
    105121        DPRINTF("Relocate all modules\n");
    106         modules_process_relocs(env, &prog_mod);
     122        modules_process_relocs(env, prog);
     123
     124        modules_process_tls(env);
    107125
    108126        *rre = env;
     
    110128}
    111129
     130/** Create TLS (Thread Local Storage) data structures.
     131 *
     132 * @return Pointer to TCB.
     133 */
     134tcb_t *rtld_tls_make(rtld_t *rtld)
     135{
     136        void *data;
     137        tcb_t *tcb;
     138        size_t offset;
     139
     140        tcb = tls_alloc_arch(&data, rtld->tls_size);
     141        if (tcb == NULL)
     142                return NULL;
     143
     144        /*
     145         * Copy thread local data from the modules' initialization images.
     146         * Zero out thread-local uninitialized data.
     147         */
     148
     149        offset = 0;
     150        list_foreach(rtld->modules, modules_link, module_t, m) {
     151                memcpy(data + offset, m->tdata, m->tdata_size);
     152                offset += m->tdata_size;
     153                memset(data + offset, 0, m->tbss_size);
     154                offset += m->tbss_size;
     155        }
     156
     157        return tcb;
     158}
     159
     160unsigned long rtld_get_next_id(rtld_t *rtld)
     161{
     162        return rtld->next_id++;
     163}
     164
     165void *rtld_tls_get_addr(rtld_t *rtld, void *tls, unsigned long mod_id,
     166    unsigned long offset)
     167{
     168        module_t *m;
     169
     170        m = module_by_id(rtld, mod_id);
     171        assert(m != NULL);
     172
     173        return tls + m->ioffs + offset;
     174}
     175
     176
    112177/** @}
    113178 */
  • uspace/lib/c/generic/tls.c

    rdc0d8b52 r6adb775f  
    3434 * Support for thread-local storage, as described in:
    3535 *      Drepper U.: ELF Handling For Thread-Local Storage, 2005
    36  *
    37  * Only static model is supported.
    38  */
     36 */
    3937
    4038#include <tls.h>
    4139#include <malloc.h>
    4240#include <str.h>
    43 #include <align.h>
    4441#include <unistd.h>
    4542
     43#ifdef CONFIG_RTLD
     44#include <rtld/rtld.h>
     45#endif
     46
     47size_t tls_get_size(void)
     48{
     49        return &_tbss_end - &_tdata_start;
     50}
     51
    4652/** Create TLS (Thread Local Storage) data structures.
    47  *
    48  * The code requires, that sections .tdata and .tbss are adjacent. It may be
    49  * changed in the future.
    5053 *
    5154 * @return Pointer to TCB.
     
    5659        tcb_t *tcb;
    5760        size_t tls_size = &_tbss_end - &_tdata_start;
    58        
     61
     62#ifdef CONFIG_RTLD
     63        if (runtime_env != NULL)
     64                return rtld_tls_make(runtime_env);
     65#endif
    5966        tcb = tls_alloc_arch(&data, tls_size);
    6067        if (!tcb)
    6168                return NULL;
    62        
     69
    6370        /*
    6471         * Copy thread local data from the initialization image.
     
    7784{
    7885        size_t tls_size = &_tbss_end - &_tdata_start;
     86
     87#ifdef CONFIG_RTLD
     88        if (runtime_env != NULL)
     89                tls_size = runtime_env->tls_size;
     90#endif
    7991        tls_free_arch(tcb, tls_size);
    8092}
     
    121133{
    122134        tcb_t *tcb;
    123        
    124         size = ALIGN_UP(size, &_tls_alignment);
    125         *data = memalign((uintptr_t) &_tls_alignment, sizeof(tcb_t) + size);
    126         if (!*data)
     135
     136        *data = malloc(sizeof(tcb_t) + size);
     137        if (*data == NULL)
    127138                return NULL;
    128139        tcb = (tcb_t *) (*data + size);
     
    139150void tls_free_variant_2(tcb_t *tcb, size_t size)
    140151{
    141         size = ALIGN_UP(size, &_tls_alignment);
    142152        void *start = ((void *) tcb) - size;
    143153        free(start);
  • uspace/lib/c/include/elf/elf_mod.h

    rdc0d8b52 r6adb775f  
    5858} eld_flags_t;
    5959
     60/** TLS info for a module */
     61typedef struct {
     62        /** tdata section image */
     63        void *tdata;
     64        /** Size of tdata section image in bytes */
     65        size_t tdata_size;
     66        /** Size of tbss section */
     67        size_t tbss_size;
     68} elf_tls_info_t;
     69
    6070/**
    6171 * Some data extracted from the headers are stored here
     
    7080        /** Pointer to the dynamic section */
    7181        void *dynamic;
     82
     83        /** TLS info */
     84        elf_tls_info_t tls;
    7285} elf_finfo_t;
    7386
  • uspace/lib/c/include/rtld/module.h

    rdc0d8b52 r6adb775f  
    4646extern module_t *module_load(rtld_t *, const char *);
    4747extern void module_load_deps(module_t *);
     48extern module_t *module_by_id(rtld_t *, unsigned long);
    4849
    4950extern void modules_process_relocs(rtld_t *, module_t *);
     51extern void modules_process_tls(rtld_t *);
    5052extern void modules_untag(rtld_t *);
    5153
  • uspace/lib/c/include/rtld/rtld.h

    rdc0d8b52 r6adb775f  
    4141
    4242#include <rtld/dynamic.h>
     43#include <tls.h>
    4344#include <types/rtld/rtld.h>
    4445
     
    4748extern void rtld_init_static(void);
    4849extern int rtld_prog_process(elf_finfo_t *, rtld_t **);
     50extern tcb_t *rtld_tls_make(rtld_t *);
     51extern unsigned long rtld_get_next_id(rtld_t *);
     52extern void *rtld_tls_get_addr(rtld_t *, void *, unsigned long, unsigned long);
    4953
    5054#endif
  • uspace/lib/c/include/tls.h

    rdc0d8b52 r6adb775f  
    5252extern void tls_free(tcb_t *);
    5353extern void tls_free_arch(tcb_t *, size_t);
     54extern size_t tls_get_size(void);
    5455
    5556#ifdef CONFIG_TLS_VARIANT_1
  • uspace/lib/c/include/types/rtld/module.h

    rdc0d8b52 r6adb775f  
    4040
    4141typedef struct module {
     42        /** Module ID */
     43        unsigned long id;
     44        /** Dynamic info for this module */
    4245        dyn_info_t dyn;
     46        /** Load bias */
    4347        size_t bias;
     48
     49        /** tdata image start */
     50        void *tdata;
     51        /** tdata image size */
     52        size_t tdata_size;
     53        /** tbss size */
     54        size_t tbss_size;
     55
     56        size_t ioffs;
    4457
    4558        /** Containing rtld */
  • uspace/lib/c/include/types/rtld/rtld.h

    rdc0d8b52 r6adb775f  
    4848        module_t *program;
    4949
     50        /** Next module ID */
     51        unsigned long next_id;
     52
     53        /** Size of initial TLS tdata + tbss */
     54        size_t tls_size;
     55
    5056        /** List of all loaded modules including rtld and the program */
    5157        list_t modules;
Note: See TracChangeset for help on using the changeset viewer.