Changeset f356618 in mainline for uspace/lib/c/generic/rtld/rtld.c
- Timestamp:
- 2016-05-22T21:05:55Z (9 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. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
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 */
Note:
See TracChangeset
for help on using the changeset viewer.