kit

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

emu.c (17221B)


      1 #include "emu/emu.h"
      2 
      3 #include <string.h>
      4 
      5 #include "arch/arch.h"
      6 #include "arch/rv64/isa.h"
      7 #include "core/slice.h"
      8 
      9 #define RV64_EMU_SYM_XREG "__emu_rv64_xreg"
     10 #define RV64_EMU_SYM_SET_XREG "__emu_rv64_set_xreg"
     11 #define RV64_EMU_SYM_JALR "__emu_rv64_jalr"
     12 
     13 typedef struct Rv64EmuCPUState {
     14   u64 x[32];
     15   u64 f[32];
     16   u32 fcsr;
     17   u64 reserved_addr;
     18   int has_reservation;
     19 } Rv64EmuCPUState;
     20 
     21 typedef struct Rv64EmuLiftSyms {
     22   KitCgSym xreg;
     23   KitCgSym set_xreg;
     24   KitCgSym load64;
     25   KitCgSym load64_checked;
     26   KitCgSym store64;
     27   KitCgSym jalr;
     28   KitCgSym syscall;
     29   KitCgTypeId xreg_fn;
     30   KitCgTypeId set_xreg_fn;
     31   KitCgTypeId load64_fn;
     32   KitCgTypeId load64_checked_fn;
     33   KitCgTypeId store64_fn;
     34   KitCgTypeId jalr_fn;
     35   KitCgTypeId syscall_fn;
     36   KitCgTypeId thread_ptr;
     37   KitCgTypeId i32;
     38   KitCgTypeId i64;
     39   KitCgTypeId i64_ptr;
     40   KitCgTypeId void_ty;
     41 } Rv64EmuLiftSyms;
     42 
     43 static KitCgSym rv64_emu_decl_helper(KitCompiler* c, KitCg* cg,
     44                                      const char* name, KitCgTypeId type) {
     45   KitCgDecl d;
     46   memset(&d, 0, sizeof(d));
     47   d.kind = KIT_CG_DECL_FUNC;
     48   d.linkage_name = kit_sym_intern(c, kit_slice_cstr(name));
     49   d.display_name = d.linkage_name;
     50   d.linkage_name = kit_cg_c_linkage_name(c, d.linkage_name);
     51   d.type = type;
     52   d.sym.bind = KIT_SB_GLOBAL;
     53   d.sym.visibility = KIT_CG_VIS_DEFAULT;
     54   return kit_cg_decl(cg, d);
     55 }
     56 
     57 static KitCgTypeId rv64_emu_func_type(KitCompiler* c, KitCgTypeId ret,
     58                                       const KitCgTypeId* params, u32 nparams) {
     59   KitCgFuncParam p[5];
     60   KitCgFuncResult result;
     61   KitCgFuncSig sig;
     62   u32 i;
     63   memset(p, 0, sizeof(p));
     64   for (i = 0; i < nparams; ++i) p[i].type = params[i];
     65   memset(&sig, 0, sizeof(sig));
     66   memset(&result, 0, sizeof(result));
     67   result.type = ret;
     68   sig.results = &result;
     69   sig.nresults = 1;
     70   sig.params = p;
     71   sig.nparams = nparams;
     72   sig.call_conv = KIT_CG_CC_TARGET_C;
     73   return kit_cg_type_func(c, sig);
     74 }
     75 
     76 static void rv64_emu_lift_syms_init(KitCompiler* c, KitCg* cg,
     77                                     Rv64EmuLiftSyms* out) {
     78   KitCgBuiltinTypes bi = kit_cg_builtin_types(c);
     79   KitCgTypeId params[5];
     80   memset(out, 0, sizeof(*out));
     81   out->void_ty = bi.id[KIT_CG_BUILTIN_VOID];
     82   out->i32 = bi.id[KIT_CG_BUILTIN_I32];
     83   out->i64 = bi.id[KIT_CG_BUILTIN_I64];
     84   out->i64_ptr = kit_cg_type_ptr(c, out->i64, 0);
     85   out->thread_ptr = emu_thread_type((Compiler*)c);
     86 
     87   params[0] = out->thread_ptr;
     88   params[1] = out->i32;
     89   out->xreg_fn = rv64_emu_func_type(c, out->i64, params, 2);
     90 
     91   params[0] = out->thread_ptr;
     92   params[1] = out->i32;
     93   params[2] = out->i64;
     94   out->set_xreg_fn = rv64_emu_func_type(c, out->void_ty, params, 3);
     95 
     96   params[0] = out->thread_ptr;
     97   params[1] = out->i64;
     98   out->load64_fn = rv64_emu_func_type(c, out->i64, params, 2);
     99 
    100   {
    101     KitCgTypeId load_params[5];
    102     load_params[0] = out->thread_ptr;
    103     load_params[1] = out->i64;
    104     load_params[2] = out->i64;
    105     load_params[3] = out->i64;
    106     load_params[4] = out->i64_ptr;
    107     out->load64_checked_fn = rv64_emu_func_type(c, out->i64, load_params, 5);
    108   }
    109 
    110   {
    111     KitCgTypeId store_params[5];
    112     store_params[0] = out->thread_ptr;
    113     store_params[1] = out->i64;
    114     store_params[2] = out->i64;
    115     store_params[3] = out->i64;
    116     store_params[4] = out->i64;
    117     out->store64_fn = rv64_emu_func_type(c, out->i64, store_params, 5);
    118   }
    119 
    120   {
    121     KitCgTypeId jalr_params[5];
    122     jalr_params[0] = out->thread_ptr;
    123     jalr_params[1] = out->i64;
    124     jalr_params[2] = out->i64;
    125     jalr_params[3] = out->i64;
    126     jalr_params[4] = out->i64;
    127     out->jalr_fn = rv64_emu_func_type(c, out->i64, jalr_params, 5);
    128   }
    129 
    130   params[0] = out->thread_ptr;
    131   params[1] = out->i64;
    132   out->syscall_fn = rv64_emu_func_type(c, out->i64, params, 2);
    133 
    134   out->xreg = rv64_emu_decl_helper(c, cg, RV64_EMU_SYM_XREG, out->xreg_fn);
    135   out->set_xreg =
    136       rv64_emu_decl_helper(c, cg, RV64_EMU_SYM_SET_XREG, out->set_xreg_fn);
    137   out->load64 = rv64_emu_decl_helper(c, cg, EMU_SYM_LOAD64, out->load64_fn);
    138   out->load64_checked = rv64_emu_decl_helper(c, cg, EMU_SYM_LOAD64_CHECKED,
    139                                              out->load64_checked_fn);
    140   out->store64 = rv64_emu_decl_helper(c, cg, EMU_SYM_STORE64, out->store64_fn);
    141   out->jalr = rv64_emu_decl_helper(c, cg, RV64_EMU_SYM_JALR, out->jalr_fn);
    142   out->syscall = rv64_emu_decl_helper(c, cg, EMU_SYM_SYSCALL, out->syscall_fn);
    143 }
    144 
    145 static KitCgMemAccess rv64_emu_mem(KitCgTypeId type) {
    146   KitCgMemAccess m;
    147   memset(&m, 0, sizeof(m));
    148   m.type = type;
    149   return m;
    150 }
    151 
    152 static void rv64_emu_push_thread(KitCg* cg, KitCgLocal thread,
    153                                  KitCgTypeId thread_ptr) {
    154   kit_cg_push_local(cg, thread);
    155   kit_cg_load(cg, rv64_emu_mem(thread_ptr));
    156 }
    157 
    158 static void rv64_emu_push_xreg(KitCg* cg, const Rv64EmuLiftSyms* s,
    159                                KitCgLocal thread, u32 reg) {
    160   if (reg == 0u) {
    161     kit_cg_push_int(cg, 0, s->i64);
    162     return;
    163   }
    164   rv64_emu_push_thread(cg, thread, s->thread_ptr);
    165   kit_cg_push_int(cg, reg, s->i32);
    166   kit_cg_call_symbol(cg, s->xreg, 2, (KitCgCallAttrs){0});
    167 }
    168 
    169 static void rv64_emu_store_xreg_from_tmp(KitCg* cg, const Rv64EmuLiftSyms* s,
    170                                          KitCgLocal thread, KitCgLocal tmp,
    171                                          u32 reg) {
    172   if (reg == 0u) return;
    173   rv64_emu_push_thread(cg, thread, s->thread_ptr);
    174   kit_cg_push_int(cg, reg, s->i32);
    175   kit_cg_push_local(cg, tmp);
    176   kit_cg_load(cg, rv64_emu_mem(s->i64));
    177   kit_cg_call_symbol(cg, s->set_xreg, 3, (KitCgCallAttrs){0});
    178 }
    179 
    180 static void rv64_emu_store_xreg_from_stack(KitCg* cg, const Rv64EmuLiftSyms* s,
    181                                            KitCgLocal thread, u32 reg,
    182                                            KitCgLocal tmp) {
    183   kit_cg_push_local(cg, tmp);
    184   kit_cg_swap(cg);
    185   kit_cg_store(cg, rv64_emu_mem(s->i64));
    186   if (reg == 0u) return;
    187   rv64_emu_store_xreg_from_tmp(cg, s, thread, tmp, reg);
    188 }
    189 
    190 static void rv64_emu_store_local_from_stack(KitCg* cg, const Rv64EmuLiftSyms* s,
    191                                             KitCgLocal local) {
    192   kit_cg_push_local(cg, local);
    193   kit_cg_swap(cg);
    194   kit_cg_store(cg, rv64_emu_mem(s->i64));
    195 }
    196 
    197 static void rv64_emu_push_local_value(KitCg* cg, const Rv64EmuLiftSyms* s,
    198                                       KitCgLocal local) {
    199   kit_cg_push_local(cg, local);
    200   kit_cg_load(cg, rv64_emu_mem(s->i64));
    201 }
    202 
    203 static void rv64_emu_push_addr(KitCg* cg, const Rv64EmuLiftSyms* s,
    204                                KitCgLocal thread,
    205                                const KitDecodedOperand* mem) {
    206   rv64_emu_push_xreg(cg, s, thread, mem->reg);
    207   if (mem->imm) {
    208     kit_cg_push_int(cg, (u64)mem->imm, s->i64);
    209     kit_cg_int_binop(cg, KIT_CG_INT_ADD, 0);
    210   }
    211 }
    212 
    213 static KitStatus rv64_emu_lift_block(Compiler* compiler, KitCg* cg,
    214                                      const KitDecodedInsn* insts, u32 n,
    215                                      const EmuLiftCtx* ctx) {
    216   Rv64EmuLiftSyms syms;
    217   KitCgLocal thread;
    218   KitCgLocal tmp;
    219   KitCgLocal fault_next;
    220   KitCgLocalAttrs attrs;
    221   u64 next_pc;
    222   u32 i;
    223   KitCompiler* c;
    224 
    225   if (!compiler || !cg || !insts || !ctx) return KIT_INVALID;
    226   c = (KitCompiler*)compiler;
    227   rv64_emu_lift_syms_init(c, cg, &syms);
    228 
    229   kit_cg_func_begin(cg, ctx->block_sym);
    230   memset(&attrs, 0, sizeof(attrs));
    231   attrs.name = kit_sym_intern(c, KIT_SLICE_LIT("thread"));
    232   thread = kit_cg_param(cg, 0, syms.thread_ptr, attrs);
    233   attrs.name = kit_sym_intern(c, KIT_SLICE_LIT("tmp"));
    234   tmp = kit_cg_local(cg, syms.i64, attrs);
    235   attrs.name = kit_sym_intern(c, KIT_SLICE_LIT("fault_next"));
    236   fault_next = kit_cg_local(cg, syms.i64, attrs);
    237 
    238   next_pc = ctx->guest_pc;
    239   for (i = 0; i < n; ++i) {
    240     const KitDecodedInsn* in = &insts[i];
    241     next_pc = in->pc + in->nbytes;
    242     switch (in->opcode) {
    243       case RV64_DEC_ADDI: {
    244         u32 rd = in->operands[0].reg;
    245         u32 rs1 = in->operands[1].reg;
    246         i64 imm = in->operands[2].imm;
    247         rv64_emu_push_xreg(cg, &syms, thread, rs1);
    248         kit_cg_push_int(cg, (u64)imm, syms.i64);
    249         kit_cg_int_binop(cg, KIT_CG_INT_ADD, 0);
    250         rv64_emu_store_xreg_from_stack(cg, &syms, thread, rd, tmp);
    251         break;
    252       }
    253       case RV64_DEC_ADD: {
    254         u32 rd = in->operands[0].reg;
    255         u32 rs1 = in->operands[1].reg;
    256         u32 rs2 = in->operands[2].reg;
    257         rv64_emu_push_xreg(cg, &syms, thread, rs1);
    258         rv64_emu_push_xreg(cg, &syms, thread, rs2);
    259         kit_cg_int_binop(cg, KIT_CG_INT_ADD, 0);
    260         rv64_emu_store_xreg_from_stack(cg, &syms, thread, rd, tmp);
    261         break;
    262       }
    263       case RV64_DEC_AUIPC: {
    264         u32 rd = in->operands[0].reg;
    265         i64 imm = in->operands[1].imm;
    266         kit_cg_push_int(cg, (u64)(in->pc + (u64)imm), syms.i64);
    267         rv64_emu_store_xreg_from_stack(cg, &syms, thread, rd, tmp);
    268         break;
    269       }
    270       case RV64_DEC_LD: {
    271         u32 rd = in->operands[0].reg;
    272         KitCgLabel ok = kit_cg_label_new(cg);
    273         rv64_emu_push_thread(cg, thread, syms.thread_ptr);
    274         rv64_emu_push_addr(cg, &syms, thread, &in->operands[1]);
    275         kit_cg_push_int(cg, in->pc, syms.i64);
    276         kit_cg_push_int(cg, next_pc, syms.i64);
    277         kit_cg_push_local_addr(cg, tmp);
    278         kit_cg_call_symbol(cg, syms.load64_checked, 5, (KitCgCallAttrs){0});
    279         rv64_emu_store_local_from_stack(cg, &syms, fault_next);
    280         rv64_emu_push_local_value(cg, &syms, fault_next);
    281         kit_cg_push_int(cg, 0, syms.i64);
    282         kit_cg_int_cmp(cg, KIT_CG_INT_NE);
    283         kit_cg_branch_false(cg, ok);
    284         rv64_emu_push_local_value(cg, &syms, fault_next);
    285         kit_cg_ret(cg);
    286         kit_cg_label_place(cg, ok);
    287         rv64_emu_store_xreg_from_tmp(cg, &syms, thread, tmp, rd);
    288         break;
    289       }
    290       case RV64_DEC_SD: {
    291         rv64_emu_push_thread(cg, thread, syms.thread_ptr);
    292         rv64_emu_push_addr(cg, &syms, thread, &in->operands[1]);
    293         rv64_emu_push_xreg(cg, &syms, thread, in->operands[0].reg);
    294         kit_cg_push_int(cg, in->pc, syms.i64);
    295         kit_cg_push_int(cg, next_pc, syms.i64);
    296         kit_cg_call_symbol(cg, syms.store64, 5, (KitCgCallAttrs){0});
    297         kit_cg_ret(cg);
    298         kit_cg_func_end(cg);
    299         return KIT_OK;
    300       }
    301       case RV64_DEC_JALR: {
    302         Rv64I ji = rv64_i_unpack(in->arch[0]);
    303         u32 rd = ji.rd;
    304         u32 rs1 = ji.rs1;
    305         i64 imm = rv64_sext(ji.imm12, 12);
    306         rv64_emu_push_thread(cg, thread, syms.thread_ptr);
    307         kit_cg_push_int(cg, rd, syms.i64);
    308         kit_cg_push_int(cg, rs1, syms.i64);
    309         kit_cg_push_int(cg, (u64)imm, syms.i64);
    310         kit_cg_push_int(cg, next_pc, syms.i64);
    311         kit_cg_call_symbol(cg, syms.jalr, 5, (KitCgCallAttrs){0});
    312         kit_cg_ret(cg);
    313         kit_cg_func_end(cg);
    314         return KIT_OK;
    315         break;
    316       }
    317       case RV64_DEC_ECALL:
    318         rv64_emu_push_thread(cg, thread, syms.thread_ptr);
    319         kit_cg_push_int(cg, next_pc, syms.i64);
    320         kit_cg_call_symbol(cg, syms.syscall, 2, (KitCgCallAttrs){0});
    321         kit_cg_ret(cg);
    322         kit_cg_func_end(cg);
    323         return KIT_OK;
    324       default:
    325         kit_cg_push_int(cg, in->pc, syms.i64);
    326         kit_cg_ret(cg);
    327         kit_cg_func_end(cg);
    328         return KIT_OK;
    329     }
    330   }
    331 
    332   kit_cg_push_int(cg, next_pc, syms.i64);
    333   kit_cg_ret(cg);
    334   kit_cg_func_end(cg);
    335   return KIT_OK;
    336 }
    337 
    338 static EmuCPUState* rv64_emu_cpu_new(Compiler* c, u64 initial_pc,
    339                                      u64 initial_sp) {
    340   EmuCPUState* cpu = emu_cpu_new_with_arch_state(c, KIT_ARCH_RV64, initial_pc,
    341                                                  sizeof(Rv64EmuCPUState),
    342                                                  _Alignof(Rv64EmuCPUState));
    343   Rv64EmuCPUState* rv = (Rv64EmuCPUState*)emu_cpu_arch_state(cpu);
    344   if (rv) rv->x[2] = initial_sp;
    345   return cpu;
    346 }
    347 
    348 static Rv64EmuCPUState* rv64_thread_state(EmuThread* thread) {
    349   return thread ? (Rv64EmuCPUState*)emu_cpu_arch_state(emu_thread_cpu(thread))
    350                 : NULL;
    351 }
    352 
    353 u64 emu_rv64_xreg(EmuThread* thread, u32 i) {
    354   Rv64EmuCPUState* rv = rv64_thread_state(thread);
    355   if (!rv || i >= 32u) return 0;
    356   return i == 0u ? 0u : rv->x[i];
    357 }
    358 
    359 void emu_rv64_set_xreg(EmuThread* thread, u32 i, u64 v) {
    360   Rv64EmuCPUState* rv = rv64_thread_state(thread);
    361   if (!rv || i >= 32u || i == 0u) return;
    362   rv->x[i] = v;
    363 }
    364 
    365 static u64 rv64_get_syscall_no(EmuThread* thread) {
    366   return emu_rv64_xreg(thread, 17u);
    367 }
    368 
    369 static u64 rv64_get_syscall_arg(EmuThread* thread, u32 index) {
    370   static const u32 regs[6] = {10u, 11u, 12u, 13u, 14u, 15u};
    371   return index < 6u ? emu_rv64_xreg(thread, regs[index]) : 0;
    372 }
    373 
    374 static void rv64_set_syscall_result(EmuThread* thread, u64 value) {
    375   emu_rv64_set_xreg(thread, 10u, value);
    376 }
    377 
    378 static u64 rv64_get_sp(EmuThread* thread) { return emu_rv64_xreg(thread, 2u); }
    379 
    380 static void rv64_set_sp(EmuThread* thread, u64 value) {
    381   emu_rv64_set_xreg(thread, 2u, value);
    382 }
    383 
    384 static u64 rv64_get_tp(EmuThread* thread) { return emu_rv64_xreg(thread, 4u); }
    385 
    386 static void rv64_set_tp(EmuThread* thread, u64 value) {
    387   emu_rv64_set_xreg(thread, 4u, value);
    388 }
    389 
    390 static void rv64_signal_wr64(u8* p, u64 v) {
    391   u32 i;
    392   for (i = 0; i < 8u; ++i) p[i] = (u8)(v >> (8u * i));
    393 }
    394 
    395 static u64 rv64_signal_rd64(const u8* p) {
    396   return (u64)p[0] | ((u64)p[1] << 8) | ((u64)p[2] << 16) | ((u64)p[3] << 24) |
    397          ((u64)p[4] << 32) | ((u64)p[5] << 40) | ((u64)p[6] << 48) |
    398          ((u64)p[7] << 56);
    399 }
    400 
    401 static u64 rv64_signal_context_size(EmuProcess* process, EmuThread* thread) {
    402   (void)process;
    403   (void)thread;
    404   return 32u * 8u;
    405 }
    406 
    407 static KitStatus rv64_save_signal_context(EmuProcess* process,
    408                                           EmuThread* thread, u8* dst,
    409                                           u64 size) {
    410   u32 i;
    411   (void)process;
    412   if (!thread || !dst || size < 32u * 8u) return KIT_INVALID;
    413   for (i = 0; i < 32u; ++i)
    414     rv64_signal_wr64(dst + (u64)i * 8u, emu_rv64_xreg(thread, i));
    415   return KIT_OK;
    416 }
    417 
    418 static KitStatus rv64_restore_signal_context(EmuProcess* process,
    419                                              EmuThread* thread, const u8* src,
    420                                              u64 size) {
    421   u32 i;
    422   (void)process;
    423   if (!thread || !src || size < 32u * 8u) return KIT_INVALID;
    424   for (i = 0; i < 32u; ++i)
    425     emu_rv64_set_xreg(thread, i, rv64_signal_rd64(src + (u64)i * 8u));
    426   return KIT_OK;
    427 }
    428 
    429 static KitStatus rv64_set_signal_handler_args(EmuProcess* process,
    430                                               EmuThread* thread, int signo,
    431                                               u64 siginfo, u64 ucontext) {
    432   (void)process;
    433   if (!thread) return KIT_INVALID;
    434   emu_rv64_set_xreg(thread, 10u, (u64)signo);
    435   emu_rv64_set_xreg(thread, 11u, siginfo);
    436   emu_rv64_set_xreg(thread, 12u, ucontext);
    437   return KIT_OK;
    438 }
    439 
    440 static u64 rv64_signal_stack_align(EmuProcess* process, EmuThread* thread) {
    441   (void)process;
    442   (void)thread;
    443   return 16u;
    444 }
    445 
    446 static KitStatus rv64_emit_import_thunk(EmuProcess* process, u64 thunk_vaddr) {
    447   u8 code[4];
    448   u32 word = 0x00008067u;
    449   u32 i;
    450   if (!process) return KIT_INVALID;
    451   for (i = 0; i < 4u; ++i) code[i] = (u8)(word >> (8u * i));
    452   return emu_addr_space_copy_in(&process->image.addr_space, thunk_vaddr, code,
    453                                 sizeof(code));
    454 }
    455 
    456 u64 emu_rv64_jalr(EmuThread* thread, u64 rd, u64 rs1, u64 imm, u64 next_pc) {
    457   EmuImportBinding* b = NULL;
    458   u64 target;
    459   if (rd != 0u) emu_rv64_set_xreg(thread, (u32)rd, next_pc);
    460   target = emu_rv64_xreg(thread, (u32)rs1) + imm;
    461   target &= ~1ull;
    462   if (emu_dl_resolve_import_thunk(thread ? thread->process : NULL, target,
    463                                   &b) == KIT_OK &&
    464       b) {
    465     u64 args[3];
    466     u64 result = 0;
    467     args[0] = emu_rv64_xreg(thread, 10u);
    468     args[1] = emu_rv64_xreg(thread, 11u);
    469     args[2] = emu_rv64_xreg(thread, 12u);
    470     if (emu_call_host_import(thread, b, args, 3u, &result) != KIT_OK) {
    471       emu_cpu_trap_fault(emu_thread_cpu(thread));
    472       return next_pc;
    473     }
    474     if (b->signature.result != KIT_EMU_VALUE_VOID)
    475       emu_rv64_set_xreg(thread, 10u, result);
    476     return next_pc;
    477   }
    478   return target;
    479 }
    480 
    481 static void* rv64_resolve_runtime_helper(void* emu, KitSlice name) {
    482   (void)emu;
    483   if (kit_slice_eq_cstr(name, RV64_EMU_SYM_XREG)) return (void*)emu_rv64_xreg;
    484   if (kit_slice_eq_cstr(name, RV64_EMU_SYM_SET_XREG))
    485     return (void*)emu_rv64_set_xreg;
    486   if (kit_slice_eq_cstr(name, RV64_EMU_SYM_JALR)) return (void*)emu_rv64_jalr;
    487   return NULL;
    488 }
    489 
    490 const ArchEmuOps rv64_emu_ops = {
    491     .cpu_new = rv64_emu_cpu_new,
    492     .block_fn_type = emu_block_fn_type,
    493     .lift_block = rv64_emu_lift_block,
    494     .get_gpr = emu_rv64_xreg,
    495     .set_gpr = emu_rv64_set_xreg,
    496     .get_syscall_no = rv64_get_syscall_no,
    497     .get_syscall_arg = rv64_get_syscall_arg,
    498     .set_syscall_result = rv64_set_syscall_result,
    499     .get_sp = rv64_get_sp,
    500     .set_sp = rv64_set_sp,
    501     .get_tp = rv64_get_tp,
    502     .set_tp = rv64_set_tp,
    503     .signal_context_size = rv64_signal_context_size,
    504     .save_signal_context = rv64_save_signal_context,
    505     .restore_signal_context = rv64_restore_signal_context,
    506     .set_signal_handler_args = rv64_set_signal_handler_args,
    507     .signal_stack_align = rv64_signal_stack_align,
    508     .import_thunk_size = 4u,
    509     .emit_import_thunk = rv64_emit_import_thunk,
    510     .resolve_runtime_helper = rv64_resolve_runtime_helper,
    511 };