HelenOS sources
This source file includes following definitions.
- rtld_init_static
- rtld_prog_process
- rtld_tls_make
- rtld_get_next_id
- rtld_tls_get_addr
#include <errno.h>
#include <rtld/module.h>
#include <rtld/rtld.h>
#include <rtld/rtld_debug.h>
#include <stdlib.h>
#include <str.h>
rtld_t *runtime_env;
static rtld_t rt_env_static;
errno_t rtld_init_static(void)
{
errno_t rc;
runtime_env = &rt_env_static;
list_initialize(&runtime_env->modules);
list_initialize(&runtime_env->imodules);
runtime_env->program = NULL;
runtime_env->next_id = 1;
rc = module_create_static_exec(runtime_env, NULL);
if (rc != EOK)
return rc;
modules_process_tls(runtime_env);
return EOK;
}
errno_t rtld_prog_process(elf_finfo_t *p_info, rtld_t **rre)
{
rtld_t *env;
module_t *prog;
DPRINTF("Load dynamically linked program.\n");
env = calloc(1, sizeof(rtld_t));
if (env == NULL)
return ENOMEM;
env->next_id = 1;
prog = calloc(1, sizeof(module_t));
if (prog == NULL) {
free(env);
return ENOMEM;
}
DPRINTF("Parse program .dynamic section at %p\n", p_info->dynamic);
dynamic_parse(p_info->dynamic, 0, &prog->dyn);
prog->bias = 0;
prog->dyn.soname = "[program]";
prog->rtld = env;
prog->id = rtld_get_next_id(env);
prog->exec = true;
prog->local = false;
prog->tdata = p_info->tls.tdata;
prog->tdata_size = p_info->tls.tdata_size;
prog->tbss_size = p_info->tls.tbss_size;
prog->tls_align = p_info->tls.tls_align;
DPRINTF("prog tdata at %p size %zu, tbss size %zu\n",
prog->tdata, prog->tdata_size, prog->tbss_size);
list_initialize(&env->modules);
list_initialize(&env->imodules);
list_append(&prog->modules_link, &env->modules);
env->program = prog;
DPRINTF("Load all program dependencies\n");
errno_t rc = module_load_deps(prog, 0);
if (rc != EOK) {
return rc;
}
modules_process_tls(env);
DPRINTF("Relocate all modules\n");
modules_process_relocs(env, prog);
*rre = env;
return EOK;
}
tcb_t *rtld_tls_make(rtld_t *rtld)
{
tcb_t *tcb;
void **dtv;
size_t nmods;
size_t i;
tcb = tls_alloc_arch(rtld->tls_size, rtld->tls_align);
if (tcb == NULL)
return NULL;
nmods = list_count(&rtld->imodules);
dtv = malloc((nmods + 1) * sizeof(void *));
if (dtv == NULL) {
tls_free(tcb);
return NULL;
}
DTV_GN(dtv) = nmods;
i = 1;
list_foreach(rtld->imodules, imodules_link, module_t, m) {
assert(i++ == m->id);
dtv[m->id] = (void *) tcb + m->tpoff;
assert(((uintptr_t) dtv[m->id]) % m->tls_align == 0);
if (m->tdata)
memcpy(dtv[m->id], m->tdata, m->tdata_size);
memset(dtv[m->id] + m->tdata_size, 0, m->tbss_size);
}
tcb->dtv = dtv;
return tcb;
}
unsigned long rtld_get_next_id(rtld_t *rtld)
{
return rtld->next_id++;
}
void *rtld_tls_get_addr(rtld_t *rtld, tcb_t *tcb, unsigned long mod_id,
unsigned long offset)
{
module_t *m;
size_t dtv_len;
void *tls_block;
dtv_len = DTV_GN(tcb->dtv);
if (dtv_len < mod_id) {
tcb->dtv = realloc(tcb->dtv, (1 + mod_id) * sizeof(void *));
assert(tcb->dtv != NULL);
memset(tcb->dtv + (1 + dtv_len), 0, (mod_id - dtv_len) *
sizeof(void *));
}
if (tcb->dtv[mod_id] == NULL) {
m = module_by_id(rtld, mod_id);
assert(m != NULL);
assert(!link_used(&m->imodules_link));
tls_block = memalign(m->tls_align, m->tdata_size + m->tbss_size);
assert(tls_block != NULL);
memcpy(tls_block, m->tdata, m->tdata_size);
memset(tls_block + m->tdata_size, 0, m->tbss_size);
tcb->dtv[mod_id] = tls_block;
}
return (uint8_t *)(tcb->dtv[mod_id]) + offset;
}
HelenOS homepage, sources at GitHub