Changeset f356618 in mainline for uspace/lib/c/generic
- Timestamp:
- 2016-05-22T21:05:55Z (10 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- b3364b7c
- Parents:
- af2254ec (diff), 3a9414e (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)links above to see all the changes relative to each parent. - Location:
- uspace/lib/c/generic
- Files:
-
- 7 edited
-
dlfcn.c (modified) (2 diffs)
-
elf/elf_mod.c (modified) (2 diffs)
-
libc.c (modified) (4 diffs)
-
rtld/module.c (modified) (7 diffs)
-
rtld/rtld.c (modified) (7 diffs)
-
rtld/symbol.c (modified) (1 diff)
-
tls.c (modified) (6 diffs)
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/dlfcn.c
raf2254ec rf356618 49 49 module_t *m; 50 50 51 if (runtime_env == NULL) {52 printf("Dynamic linker not set up -- initializing.\n");53 rtld_init_static();54 }55 56 printf("dlopen(\"%s\", %d)\n", path, flag);57 58 printf("module_find('%s')\n", path);59 51 m = module_find(runtime_env, path); 60 52 if (m == NULL) { 61 printf("NULL. module_load('%s')\n", path);62 53 m = module_load(runtime_env, path, mlf_local); 63 printf("module_load_deps(m)\n");64 54 module_load_deps(m, mlf_local); 65 55 /* Now relocate. */ 66 printf("module_process_relocs(m)\n");67 56 module_process_relocs(m); 68 } else {69 printf("not NULL\n");70 57 } 71 58 … … 81 68 module_t *sm; 82 69 83 printf("dlsym(0x%lx, \"%s\")\n", (long)mod, sym_name);84 70 sd = symbol_bfs_find(sym_name, (module_t *) mod, &sm); 85 71 if (sd != NULL) { 86 return symbol_get_addr(sd, sm );72 return symbol_get_addr(sd, sm, __tcb_get()); 87 73 } 88 74 -
uspace/lib/c/generic/elf/elf_mod.c
raf2254ec rf356618 248 248 } 249 249 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 */ 256 static 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 info->tls_align = hdr->p_align; 263 } 264 250 265 /** Process segment header. 251 266 * 267 * @param elf Pointer to loader state buffer. 252 268 * @param entry Segment header. 253 269 * … … 277 293 case 0x70000000: 278 294 /* FIXME: MIPS reginfo */ 295 break; 296 case PT_TLS: 297 /* Parse TLS program header */ 298 tls_program_header(elf, entry, &elf->info->tls); 299 DPRINTF("TLS header found at %p\n", 300 (void *)((uint8_t *)entry->p_vaddr + elf->bias)); 279 301 break; 280 302 case PT_SHLIB: -
uspace/lib/c/generic/libc.c
raf2254ec rf356618 41 41 */ 42 42 43 #include <errno.h> 43 44 #include <libc.h> 44 45 #include <stdlib.h> … … 68 69 __malloc_init(); 69 70 71 /* Save the PCB pointer */ 72 __pcb = (pcb_t *) pcb_ptr; 73 74 #ifdef CONFIG_RTLD 75 if (__pcb != NULL && __pcb->rtld_runtime != NULL) { 76 runtime_env = (rtld_t *) __pcb->rtld_runtime; 77 } else { 78 if (rtld_init_static() != EOK) 79 abort(); 80 } 81 #endif 82 70 83 fibril_t *fibril = fibril_setup(); 71 84 if (fibril == NULL) … … 74 87 __tcb_set(fibril->tcb); 75 88 76 /* Save the PCB pointer */77 __pcb = (pcb_t *) pcb_ptr;78 89 79 90 #ifdef FUTEX_UPGRADABLE … … 89 100 char **argv; 90 101 91 #ifdef CONFIG_RTLD92 if (__pcb != NULL && __pcb->rtld_runtime != NULL) {93 runtime_env = (rtld_t *) __pcb->rtld_runtime;94 }95 #endif96 102 /* 97 103 * Get command line arguments and initialize -
uspace/lib/c/generic/rtld/module.c
raf2254ec rf356618 37 37 #include <adt/list.h> 38 38 #include <elf/elf_load.h> 39 #include <errno.h> 39 40 #include <fcntl.h> 40 41 #include <loader/pcb.h> … … 48 49 #include <rtld/rtld_arch.h> 49 50 #include <rtld/module.h> 51 52 /** Create module for static executable. 53 * 54 * @param rtld Run-time dynamic linker 55 * @param rmodule Place to store pointer to new module or @c NULL 56 * @return EOK on success, ENOMEM if out of memory 57 */ 58 int module_create_static_exec(rtld_t *rtld, module_t **rmodule) 59 { 60 module_t *module; 61 62 module = calloc(1, sizeof(module_t)); 63 if (module == NULL) 64 return ENOMEM; 65 66 module->id = rtld_get_next_id(rtld); 67 module->dyn.soname = "[program]"; 68 69 module->rtld = rtld; 70 module->exec = true; 71 module->local = true; 72 73 module->tdata = &_tdata_start; 74 module->tdata_size = &_tdata_end - &_tdata_start; 75 module->tbss_size = &_tbss_end - &_tbss_start; 76 module->tls_align = (uintptr_t)&_tls_alignment; 77 78 list_append(&module->modules_link, &rtld->modules); 79 80 if (rmodule != NULL) 81 *rmodule = module; 82 return EOK; 83 } 50 84 51 85 /** (Eagerly) process all relocation tables in a module. … … 135 169 136 170 m = calloc(1, sizeof(module_t)); 137 if ( !m) {171 if (m == NULL) { 138 172 printf("malloc failed\n"); 139 173 exit(1); … … 141 175 142 176 m->rtld = rtld; 177 m->id = rtld_get_next_id(rtld); 178 143 179 if ((flags & mlf_local) != 0) 144 180 m->local = true; … … 181 217 /* Insert into the list of loaded modules */ 182 218 list_append(&m->modules_link, &rtld->modules); 219 220 /* Copy TLS info */ 221 m->tdata = info.tls.tdata; 222 m->tdata_size = info.tls.tdata_size; 223 m->tbss_size = info.tls.tbss_size; 224 m->tls_align = info.tls.tls_align; 225 226 DPRINTF("tdata at %p size %zu, tbss size %zu\n", 227 m->tdata, m->tdata_size, m->tbss_size); 183 228 184 229 return m; … … 243 288 } 244 289 290 /** Find module structure by ID. */ 291 module_t *module_by_id(rtld_t *rtld, unsigned long id) 292 { 293 list_foreach(rtld->modules, modules_link, module_t, m) { 294 if (m->id == id) 295 return m; 296 } 297 298 return NULL; 299 } 300 245 301 /** Process relocations in modules. 246 302 * … … 260 316 } 261 317 318 void modules_process_tls(rtld_t *rtld) 319 { 320 #ifdef CONFIG_TLS_VARIANT_1 321 list_foreach(rtld->modules, modules_link, module_t, m) { 322 m->ioffs = rtld->tls_size; 323 list_append(&m->imodules_link, &rtmd->imodules); 324 rtld->tls_size += m->tdata_size + m->tbss_size; 325 } 326 #else /* CONFIG_TLS_VARIANT_2 */ 327 size_t offs; 328 329 list_foreach(rtld->modules, modules_link, module_t, m) { 330 rtld->tls_size += m->tdata_size + m->tbss_size; 331 } 332 333 offs = 0; 334 list_foreach(rtld->modules, modules_link, module_t, m) { 335 offs += m->tdata_size + m->tbss_size; 336 m->ioffs = rtld->tls_size - offs; 337 list_append(&m->imodules_link, &rtld->imodules); 338 } 339 #endif 340 } 341 262 342 /** Clear BFS tags of all modules. 263 343 */ -
uspace/lib/c/generic/rtld/rtld.c
raf2254ec rf356618 43 43 rtld_t *runtime_env; 44 44 static rtld_t rt_env_static; 45 static module_t prog_mod;46 45 47 46 /** Initialize the runtime linker for use in a statically-linked executable. */ 48 void rtld_init_static(void) 49 { 47 int rtld_init_static(void) 48 { 49 int rc; 50 50 51 runtime_env = &rt_env_static; 51 52 list_initialize(&runtime_env->modules); 53 list_initialize(&runtime_env->imodules); 52 54 runtime_env->next_bias = 0x2000000; 53 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; 54 65 } 55 66 … … 62 73 { 63 74 rtld_t *env; 75 module_t *prog; 64 76 65 77 DPRINTF("Load dynamically linked program.\n"); … … 70 82 return ENOMEM; 71 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 72 92 /* 73 93 * First we need to process dynamic sections of the executable … … 76 96 77 97 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; 82 prog_mod.exec = true; 83 prog_mod.local = false; 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); 84 113 85 114 /* Initialize list of loaded modules */ 86 115 list_initialize(&env->modules); 87 list_append(&prog_mod.modules_link, &env->modules); 116 list_initialize(&env->imodules); 117 list_append(&prog->modules_link, &env->modules); 88 118 89 119 /* Pointer to program module. Used as root of the module graph. */ 90 env->program = &prog_mod;120 env->program = prog; 91 121 92 122 /* Work around non-existent memory space allocation. */ … … 98 128 99 129 DPRINTF("Load all program dependencies\n"); 100 module_load_deps(&prog_mod, 0); 130 module_load_deps(prog, 0); 131 132 /* Compute static TLS size */ 133 modules_process_tls(env); 101 134 102 135 /* … … 106 139 /* Process relocations in all modules */ 107 140 DPRINTF("Relocate all modules\n"); 108 modules_process_relocs(env, &prog_mod);141 modules_process_relocs(env, prog); 109 142 110 143 *rre = env; … … 112 145 } 113 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; 271 } 272 114 273 /** @} 115 274 */ -
uspace/lib/c/generic/rtld/symbol.c
raf2254ec rf356618 249 249 } 250 250 251 void *symbol_get_addr(elf_symbol_t *sym, module_t *m) 252 { 253 if (sym->st_shndx == SHN_ABS) { 251 /** Get symbol address. 252 * 253 * @param sym Symbol 254 * @param m Module contaning the symbol 255 * @param tcb TCB of the thread whose thread-local variable instance should 256 * be returned. If @a tcb is @c NULL then @c NULL is returned for 257 * thread-local variables. 258 * 259 * @return Symbol address 260 */ 261 void *symbol_get_addr(elf_symbol_t *sym, module_t *m, tcb_t *tcb) 262 { 263 if (ELF_ST_TYPE(sym->st_info) == STT_TLS) { 264 if (tcb == NULL) 265 return NULL; 266 return rtld_tls_get_addr(m->rtld, tcb, m->id, sym->st_value); 267 } else if (sym->st_shndx == SHN_ABS) { 254 268 /* Do not add bias to absolute symbols */ 255 269 return (void *) sym->st_value; -
uspace/lib/c/generic/tls.c
raf2254ec rf356618 34 34 * Support for thread-local storage, as described in: 35 35 * Drepper U.: ELF Handling For Thread-Local Storage, 2005 36 * 37 * Only static model is supported. 38 */ 36 */ 39 37 40 38 #include <tls.h> 41 39 #include <malloc.h> 42 40 #include <str.h> 43 #include <align.h>44 41 #include <unistd.h> 45 42 43 #ifdef CONFIG_RTLD 44 #include <rtld/rtld.h> 45 #endif 46 47 size_t tls_get_size(void) 48 { 49 #ifdef CONFIG_RTLD 50 if (runtime_env != NULL) 51 return runtime_env->tls_size; 52 #endif 53 return &_tbss_end - &_tdata_start; 54 } 55 56 /** Get address of static TLS block */ 57 void *tls_get(void) 58 { 59 #ifdef CONFIG_TLS_VARIANT_1 60 return (uint8_t *)__tcb_get() + sizeof(tcb_t); 61 #else /* CONFIG_TLS_VARIANT_2 */ 62 return (uint8_t *)__tcb_get() - tls_get_size(); 63 #endif 64 } 65 46 66 /** Create TLS (Thread Local Storage) data structures. 47 *48 * The code requires, that sections .tdata and .tbss are adjacent. It may be49 * changed in the future.50 67 * 51 68 * @return Pointer to TCB. … … 56 73 tcb_t *tcb; 57 74 size_t tls_size = &_tbss_end - &_tdata_start; 58 75 76 #ifdef CONFIG_RTLD 77 if (runtime_env != NULL) 78 return rtld_tls_make(runtime_env); 79 #endif 59 80 tcb = tls_alloc_arch(&data, tls_size); 60 81 if (!tcb) 61 82 return NULL; 62 83 63 84 /* 64 85 * Copy thread local data from the initialization image. … … 76 97 void tls_free(tcb_t *tcb) 77 98 { 78 size_t tls_size = &_tbss_end - &_tdata_start; 79 tls_free_arch(tcb, tls_size); 99 #ifdef CONFIG_RTLD 100 free(tcb->dtv); 101 #endif 102 tls_free_arch(tcb, tls_get_size()); 80 103 } 81 104 … … 89 112 tcb_t *tls_alloc_variant_1(void **data, size_t size) 90 113 { 91 tcb_t * result;114 tcb_t *tcb; 92 115 93 result= malloc(sizeof(tcb_t) + size);94 if (! result)116 tcb = malloc(sizeof(tcb_t) + size); 117 if (!tcb) 95 118 return NULL; 96 *data = ((void *)result) + sizeof(tcb_t); 119 *data = ((void *)tcb) + sizeof(tcb_t); 120 #ifdef CONFIG_RTLD 121 tcb->dtv = NULL; 122 #endif 97 123 98 return result;124 return tcb; 99 125 } 100 126 … … 121 147 { 122 148 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) 149 150 *data = malloc(sizeof(tcb_t) + size); 151 if (*data == NULL) 127 152 return NULL; 128 153 tcb = (tcb_t *) (*data + size); 129 154 tcb->self = tcb; 155 #ifdef CONFIG_RTLD 156 tcb->dtv = NULL; 157 #endif 130 158 131 159 return tcb; … … 139 167 void tls_free_variant_2(tcb_t *tcb, size_t size) 140 168 { 141 size = ALIGN_UP(size, &_tls_alignment);142 169 void *start = ((void *) tcb) - size; 143 170 free(start);
Note:
See TracChangeset
for help on using the changeset viewer.
