kit

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

emu.c (17200B)


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