Changes in uspace/lib/c/generic/rtld/rtld.c [9d58539:153c7a29] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/rtld/rtld.c
r9d58539 r153c7a29 35 35 */ 36 36 37 #include <errno.h> 38 #include <rtld/module.h> 37 39 #include <rtld/rtld.h> 38 39 runtime_env_t *runtime_env; 40 static runtime_env_t rt_env_static; 41 42 /** Initialize the loder for use in a statically-linked binary. */ 43 void rtld_init_static(void) 44 { 40 #include <rtld/rtld_debug.h> 41 #include <stdlib.h> 42 43 rtld_t *runtime_env; 44 static rtld_t rt_env_static; 45 46 /** Initialize the runtime linker for use in a statically-linked executable. */ 47 int rtld_init_static(void) 48 { 49 int rc; 50 45 51 runtime_env = &rt_env_static; 46 52 list_initialize(&runtime_env->modules); 53 list_initialize(&runtime_env->imodules); 47 54 runtime_env->next_bias = 0x2000000; 48 55 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; 49 271 } 50 272
Note:
See TracChangeset
for help on using the changeset viewer.