Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/c/generic/rtld/rtld.c

    r153c7a29 r5035ba05  
    4343rtld_t *runtime_env;
    4444static rtld_t rt_env_static;
     45static module_t prog_mod;
    4546
    4647/** Initialize the runtime linker for use in a statically-linked executable. */
    47 int rtld_init_static(void)
     48void rtld_init_static(void)
    4849{
    49         int rc;
    50 
    5150        runtime_env = &rt_env_static;
    5251        list_initialize(&runtime_env->modules);
    53         list_initialize(&runtime_env->imodules);
    5452        runtime_env->next_bias = 0x2000000;
    5553        runtime_env->program = NULL;
    56         runtime_env->next_id = 1;
    57 
    58         rc = module_create_static_exec(runtime_env, NULL);
    59         if (rc != EOK)
    60                 return rc;
    61 
    62         modules_process_tls(runtime_env);
    63 
    64         return EOK;
    6554}
    6655
     
    7362{
    7463        rtld_t *env;
    75         module_t *prog;
    7664
    7765        DPRINTF("Load dynamically linked program.\n");
     
    8270                return ENOMEM;
    8371
    84         env->next_id = 1;
    85 
    86         prog = calloc(1, sizeof(module_t));
    87         if (prog == NULL) {
    88                 free(env);
    89                 return ENOMEM;
    90         }
    91 
    9272        /*
    9373         * First we need to process dynamic sections of the executable
     
    9676
    9777        DPRINTF("Parse program .dynamic section at %p\n", p_info->dynamic);
    98         dynamic_parse(p_info->dynamic, 0, &prog->dyn);
    99         prog->bias = 0;
    100         prog->dyn.soname = "[program]";
    101         prog->rtld = env;
    102         prog->id = rtld_get_next_id(env);
    103         prog->exec = true;
    104         prog->local = false;
    105 
    106         prog->tdata = p_info->tls.tdata;
    107         prog->tdata_size = p_info->tls.tdata_size;
    108         prog->tbss_size = p_info->tls.tbss_size;
    109         prog->tls_align = p_info->tls.tls_align;
    110 
    111         DPRINTF("prog tdata at %p size %zu, tbss size %zu\n",
    112             prog->tdata, prog->tdata_size, prog->tbss_size);
     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;
     82        prog_mod.exec = true;
     83        prog_mod.local = false;
    11384
    11485        /* Initialize list of loaded modules */
    11586        list_initialize(&env->modules);
    116         list_initialize(&env->imodules);
    117         list_append(&prog->modules_link, &env->modules);
     87        list_append(&prog_mod.modules_link, &env->modules);
    11888
    11989        /* Pointer to program module. Used as root of the module graph. */
    120         env->program = prog;
     90        env->program = &prog_mod;
    12191
    12292        /* Work around non-existent memory space allocation. */
     
    12898
    12999        DPRINTF("Load all program dependencies\n");
    130         module_load_deps(prog, 0);
    131 
    132         /* Compute static TLS size */
    133         modules_process_tls(env);
     100        module_load_deps(&prog_mod, 0);
    134101
    135102        /*
     
    139106        /* Process relocations in all modules */
    140107        DPRINTF("Relocate all modules\n");
    141         modules_process_relocs(env, prog);
     108        modules_process_relocs(env, &prog_mod);
    142109
    143110        *rre = env;
     
    145112}
    146113
    147 /** Create TLS (Thread Local Storage) data structures.
    148  *
    149  * @return Pointer to TCB.
    150  */
    151 tcb_t *rtld_tls_make(rtld_t *rtld)
    152 {
    153         void *data;
    154         tcb_t *tcb;
    155         size_t offset;
    156         void **dtv;
    157         size_t nmods;
    158         size_t i;
    159 
    160         tcb = tls_alloc_arch(&data, rtld->tls_size);
    161         if (tcb == NULL)
    162                 return NULL;
    163 
    164         /** Allocate dynamic thread vector */
    165         nmods = list_count(&rtld->imodules);
    166         dtv = malloc((nmods + 1) * sizeof(void *));
    167         if (dtv == NULL) {
    168                 tls_free(tcb);
    169                 return NULL;
    170         }
    171 
    172         /*
    173          * We define generation number to be equal to vector length.
    174          * We start with a vector covering the initially loaded modules.
    175          */
    176         DTV_GN(dtv) = nmods;
    177 
    178         /*
    179          * Copy thread local data from the initialization images of initial
    180          * modules. Zero out thread-local uninitialized data.
    181          */
    182 
    183 #ifdef CONFIG_TLS_VARIANT_1
    184         /*
    185          * Ascending addresses
    186          */
    187         offset = 0; i = 1;
    188         list_foreach(rtld->imodules, imodules_link, module_t, m) {
    189                 assert(i == m->id);
    190                 assert(offset + m->tdata_size + m->tbss_size <= rtld->tls_size);
    191                 dtv[i++] = data + offset;
    192                 memcpy(data + offset, m->tdata, m->tdata_size);
    193                 offset += m->tdata_size;
    194                 memset(data + offset, 0, m->tbss_size);
    195                 offset += m->tbss_size;
    196         }
    197 #else /* CONFIG_TLS_VARIANT_2 */
    198         /*
    199          * Descending addresses
    200          */
    201         offset = 0; i = 1;
    202         list_foreach(rtld->imodules, imodules_link, module_t, m) {
    203                 assert(i == m->id);
    204                 assert(offset + m->tdata_size + m->tbss_size <= rtld->tls_size);
    205                 offset += m->tbss_size;
    206                 memset(data + rtld->tls_size - offset, 0, m->tbss_size);
    207                 offset += m->tdata_size;
    208                 memcpy(data + rtld->tls_size - offset, m->tdata, m->tdata_size);
    209                 dtv[i++] = data + rtld->tls_size - offset;
    210         }
    211 #endif
    212 
    213         tcb->dtv = dtv;
    214         return tcb;
    215 }
    216 
    217 unsigned long rtld_get_next_id(rtld_t *rtld)
    218 {
    219         return rtld->next_id++;
    220 }
    221 
    222 /** Get address of thread-local variable.
    223  *
    224  * @param rtld RTLD instance
    225  * @param tcb TCB of the thread whose instance to return
    226  * @param mod_id Module ID
    227  * @param offset Offset within TLS block of the module
    228  *
    229  * @return Address of thread-local variable
    230  */
    231 void *rtld_tls_get_addr(rtld_t *rtld, tcb_t *tcb, unsigned long mod_id,
    232     unsigned long offset)
    233 {
    234         module_t *m;
    235         size_t dtv_len;
    236         void *tls_block;
    237 
    238         dtv_len = DTV_GN(tcb->dtv);
    239         if (dtv_len < mod_id) {
    240                 /* Vector is short */
    241 
    242                 tcb->dtv = realloc(tcb->dtv, (1 + mod_id) * sizeof(void *));
    243                 /* XXX This can fail if OOM */
    244                 assert(tcb->dtv != NULL);
    245                 /* Zero out new part of vector */
    246                 memset(tcb->dtv + (1 + dtv_len), 0, (mod_id - dtv_len) *
    247                     sizeof(void *));
    248         }
    249 
    250         if (tcb->dtv[mod_id] == NULL) {
    251                 /* TLS block is not allocated */
    252 
    253                 m = module_by_id(rtld, mod_id);
    254                 assert(m != NULL);
    255                 /* Should not be initial module, those have TLS pre-allocated */
    256                 assert(!link_used(&m->imodules_link));
    257 
    258                 tls_block = malloc(m->tdata_size + m->tbss_size);
    259                 /* XXX This can fail if OOM */
    260                 assert(tls_block != NULL);
    261 
    262                 /* Copy tdata */
    263                 memcpy(tls_block, m->tdata, m->tdata_size);
    264                 /* Zero out tbss */
    265                 memset(tls_block + m->tdata_size, 0, m->tbss_size);
    266 
    267                 tcb->dtv[mod_id] = tls_block;
    268         }
    269 
    270         return (uint8_t *)(tcb->dtv[mod_id]) + offset;
    271 }
    272 
    273114/** @}
    274115 */
Note: See TracChangeset for help on using the changeset viewer.