tls.c (3953B)
1 #include <string.h> 2 3 #include "emu/emu.h" 4 5 static u64 round_up(u64 v, u64 a) { 6 if (!a) return v; 7 return (v + a - 1u) & ~(a - 1u); 8 } 9 10 static KitStatus ensure_tls_module_cap(Compiler* c, EmuTlsState* st, u32 need) { 11 Heap* heap = c->ctx->heap; 12 u32 old_cap; 13 u32 new_cap; 14 EmuTlsModule* grown; 15 if (st->modules_cap >= need) return KIT_OK; 16 old_cap = st->modules_cap; 17 new_cap = old_cap ? old_cap * 2u : 4u; 18 while (new_cap < need) new_cap *= 2u; 19 grown = (EmuTlsModule*)heap->realloc( 20 heap, st->modules, sizeof(*st->modules) * old_cap, 21 sizeof(*st->modules) * new_cap, _Alignof(EmuTlsModule)); 22 if (!grown) return KIT_NOMEM; 23 memset(grown + old_cap, 0, sizeof(*grown) * (new_cap - old_cap)); 24 st->modules = grown; 25 st->modules_cap = new_cap; 26 return KIT_OK; 27 } 28 29 static KitStatus ensure_tls_block_cap(Compiler* c, EmuTlsBlocks* blocks, 30 u32 need) { 31 Heap* heap = c->ctx->heap; 32 u32 old_cap; 33 u32 new_cap; 34 EmuTlsBlock* grown; 35 if (blocks->blocks_cap >= need) return KIT_OK; 36 old_cap = blocks->blocks_cap; 37 new_cap = old_cap ? old_cap * 2u : 4u; 38 while (new_cap < need) new_cap *= 2u; 39 grown = (EmuTlsBlock*)heap->realloc( 40 heap, blocks->blocks, sizeof(*blocks->blocks) * old_cap, 41 sizeof(*blocks->blocks) * new_cap, _Alignof(EmuTlsBlock)); 42 if (!grown) return KIT_NOMEM; 43 memset(grown + old_cap, 0, sizeof(*grown) * (new_cap - old_cap)); 44 blocks->blocks = grown; 45 blocks->blocks_cap = new_cap; 46 return KIT_OK; 47 } 48 49 KitStatus emu_tls_rebuild_modules(Compiler* c, EmuProcess* process) { 50 EmuTlsState* st; 51 u32 i; 52 u32 next_id = 1u; 53 if (!c || !process) return KIT_INVALID; 54 st = &process->tls_state; 55 st->nmodules = 0; 56 st->static_size = 0; 57 st->static_align = 1u; 58 for (i = 0; i < process->image.link_map.nobjects; ++i) { 59 EmuTlsModule m = process->image.link_map.objects[i].tls; 60 u64 align; 61 if (!m.memsz && !m.filesz) continue; 62 if (ensure_tls_module_cap(c, st, st->nmodules + 1u) != KIT_OK) 63 return KIT_NOMEM; 64 m.module_id = next_id++; 65 process->image.link_map.objects[i].tls.module_id = m.module_id; 66 st->modules[st->nmodules++] = m; 67 align = m.align ? m.align : 1u; 68 if (align > st->static_align) st->static_align = align; 69 st->static_size = round_up(st->static_size, align) + m.memsz; 70 } 71 return KIT_OK; 72 } 73 74 KitStatus emu_tls_blocks_add(Compiler* c, EmuTlsBlocks* blocks, u32 module_id, 75 u64 base, u64 memsz) { 76 EmuTlsBlock* b; 77 if (!c || !blocks || !module_id) return KIT_INVALID; 78 if (ensure_tls_block_cap(c, blocks, blocks->nblocks + 1u) != KIT_OK) 79 return KIT_NOMEM; 80 b = &blocks->blocks[blocks->nblocks++]; 81 b->module_id = module_id; 82 b->base = base; 83 b->memsz = memsz; 84 return KIT_OK; 85 } 86 87 KitStatus emu_tls_copy_module_image(EmuProcess* process, 88 const EmuTlsModule* module, u64 base) { 89 u8* src; 90 if (!process || !module) return KIT_INVALID; 91 if (!module->filesz) return KIT_OK; 92 src = emu_addr_space_ptr(&process->image.addr_space, module->image_vaddr, 93 module->filesz, EMU_MEM_READ); 94 if (!src) return KIT_ERR; 95 return emu_addr_space_copy_in(&process->image.addr_space, base, src, 96 module->filesz); 97 } 98 99 void emu_tls_destroy_process(Compiler* c, EmuProcess* process) { 100 Heap* heap; 101 if (!c || !process) return; 102 heap = c->ctx->heap; 103 if (process->tls_state.modules) { 104 heap->free( 105 heap, process->tls_state.modules, 106 sizeof(*process->tls_state.modules) * process->tls_state.modules_cap); 107 } 108 memset(&process->tls_state, 0, sizeof(process->tls_state)); 109 } 110 111 void emu_tls_destroy_blocks(Compiler* c, EmuTlsBlocks* blocks) { 112 Heap* heap; 113 if (!c || !blocks) return; 114 heap = c->ctx->heap; 115 if (blocks->blocks) { 116 heap->free(heap, blocks->blocks, 117 sizeof(*blocks->blocks) * blocks->blocks_cap); 118 } 119 memset(blocks, 0, sizeof(*blocks)); 120 }