kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

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 }