Ignore:
File:
1 edited

Legend:

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

    r153c7a29 r9d58539  
    3535 */
    3636
    37 #include <errno.h>
    38 #include <rtld/module.h>
    3937#include <rtld/rtld.h>
    40 #include <rtld/rtld_debug.h>
    41 #include <stdlib.h>
    4238
    43 rtld_t *runtime_env;
    44 static rtld_t rt_env_static;
     39runtime_env_t *runtime_env;
     40static runtime_env_t rt_env_static;
    4541
    46 /** Initialize the runtime linker for use in a statically-linked executable. */
    47 int rtld_init_static(void)
     42/** Initialize the loder for use in a statically-linked binary. */
     43void rtld_init_static(void)
    4844{
    49         int rc;
    50 
    5145        runtime_env = &rt_env_static;
    5246        list_initialize(&runtime_env->modules);
    53         list_initialize(&runtime_env->imodules);
    5447        runtime_env->next_bias = 0x2000000;
    5548        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;
    65 }
    66 
    67 /** Initialize and process a dynamically linked executable.
    68  *
    69  * @param p_info Program info
    70  * @return EOK on success or non-zero error code
    71  */
    72 int rtld_prog_process(elf_finfo_t *p_info, rtld_t **rre)
    73 {
    74         rtld_t *env;
    75         module_t *prog;
    76 
    77         DPRINTF("Load dynamically linked program.\n");
    78 
    79         /* Allocate new RTLD environment to pass to the loaded program */
    80         env = calloc(1, sizeof(rtld_t));
    81         if (env == NULL)
    82                 return ENOMEM;
    83 
    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 
    92         /*
    93          * First we need to process dynamic sections of the executable
    94          * program and insert it into the module graph.
    95          */
    96 
    97         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);
    113 
    114         /* Initialize list of loaded modules */
    115         list_initialize(&env->modules);
    116         list_initialize(&env->imodules);
    117         list_append(&prog->modules_link, &env->modules);
    118 
    119         /* Pointer to program module. Used as root of the module graph. */
    120         env->program = prog;
    121 
    122         /* Work around non-existent memory space allocation. */
    123         env->next_bias = 0x1000000;
    124 
    125         /*
    126          * Now we can continue with loading all other modules.
    127          */
    128 
    129         DPRINTF("Load all program dependencies\n");
    130         module_load_deps(prog, 0);
    131 
    132         /* Compute static TLS size */
    133         modules_process_tls(env);
    134 
    135         /*
    136          * Now relocate/link all modules together.
    137          */
    138 
    139         /* Process relocations in all modules */
    140         DPRINTF("Relocate all modules\n");
    141         modules_process_relocs(env, prog);
    142 
    143         *rre = env;
    144         return EOK;
    145 }
    146 
    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;
    27149}
    27250
Note: See TracChangeset for help on using the changeset viewer.