kit

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

emu_load.c (18625B)


      1 /* Guest ELF loader.
      2  *
      3  * The host gives us an ELF buffer in `bytes`. We parse the ELF64 header
      4  * directly (no need to involve obj/elf_read.c — its purpose is to build
      5  * an ObjBuilder for the linker, which we don't want here), walk PT_LOAD
      6  * program headers, map them through EmuAddrSpace, and copy file contents in.
      7  *
      8  * Handles ELF64 LE ET_EXEC/ET_DYN at the object-format boundary: PT_LOAD
      9  * mapping plus PT_INTERP, PT_DYNAMIC, and PT_TLS metadata. OS process layout
     10  * and dynamic-loader policy live in src/os and src/emu/dl.c.
     11  */
     12 
     13 #include <string.h>
     14 
     15 #include "core/core.h"
     16 #include "core/slice.h"
     17 #include "emu/emu.h"
     18 #include "obj/elf/elf.h"
     19 #include "obj/format.h"
     20 
     21 /* Page size we align segments to. The actual guest page granularity is
     22  * unspecified for the flat address-space model; 4KiB is a reasonable default.
     23  */
     24 #define EMU_PAGE_SIZE 0x1000ull
     25 
     26 extern const ObjFormatEmuOps elf_emu_ops;
     27 
     28 typedef struct EmuElfDynInfo {
     29   u64 dynamic_vaddr;
     30   u64 dynamic_size;
     31   u64 strtab;
     32   u64 strsz;
     33   u64 symtab;
     34   u64 syment;
     35   u64 hash;
     36   u64 gnu_hash;
     37   u64 rela;
     38   u64 relasz;
     39   u64 relaent;
     40   u64 jmprel;
     41   u64 pltrelsz;
     42   u64 pltgot;
     43   u32 flags;
     44 } EmuElfDynInfo;
     45 
     46 static u64 round_up(u64 v, u64 a) { return (v + a - 1u) & ~(a - 1u); }
     47 static u64 round_down(u64 v, u64 a) { return v & ~(a - 1u); }
     48 
     49 /* ---- ELF64 wire reads ---- */
     50 static u16 rd16(const u8* p) { return (u16)p[0] | ((u16)p[1] << 8); }
     51 static u32 rd32(const u8* p) {
     52   return (u32)p[0] | ((u32)p[1] << 8) | ((u32)p[2] << 16) | ((u32)p[3] << 24);
     53 }
     54 static u64 rd64(const u8* p) { return (u64)rd32(p) | ((u64)rd32(p + 4) << 32); }
     55 
     56 static KitSlice cstr_at(const u8* base, u64 max) {
     57   u64 n = 0;
     58   while (n < max && base[n]) ++n;
     59   return (KitSlice){.data = base, .len = (size_t)n};
     60 }
     61 
     62 static EmuElfDynInfo* elf_dyn(EmuLoadedObject* obj) {
     63   return obj ? (EmuElfDynInfo*)obj->format.data : NULL;
     64 }
     65 
     66 static const EmuElfDynInfo* elf_dyn_const(const EmuLoadedObject* obj) {
     67   return obj ? (const EmuElfDynInfo*)obj->format.data : NULL;
     68 }
     69 
     70 static u8 elf_phdr_perms(u32 p_flags) {
     71   u8 perms = 0;
     72   if (p_flags & PF_R) perms |= EMU_MEM_READ;
     73   if (p_flags & PF_W) perms |= EMU_MEM_WRITE;
     74   if (p_flags & PF_X) perms |= EMU_MEM_EXEC;
     75   return perms;
     76 }
     77 
     78 static KitStatus elf_detect_executable(Compiler* c, KitSlice slice,
     79                                        KitTargetSpec* out) {
     80   const u8* bytes = slice.data;
     81   const ObjFormatImpl* fmt;
     82   const ObjElfArchOps* arch_ops;
     83   u16 e_type;
     84   u16 e_machine;
     85   (void)c;
     86   if (!bytes || slice.len < ELF64_EHDR_SIZE || !out) return KIT_INVALID;
     87   if (bytes[EI_MAG0] != ELFMAG0 || bytes[EI_MAG1] != ELFMAG1 ||
     88       bytes[EI_MAG2] != ELFMAG2 || bytes[EI_MAG3] != ELFMAG3) {
     89     return KIT_INVALID;
     90   }
     91   if (bytes[EI_CLASS] != ELFCLASS64 || bytes[EI_DATA] != ELFDATA2LSB)
     92     return KIT_UNSUPPORTED;
     93 
     94   e_type = rd16(bytes + 16);
     95   e_machine = rd16(bytes + 18);
     96   if (e_type != ET_EXEC) return KIT_UNSUPPORTED;
     97   fmt = obj_format_lookup(KIT_OBJ_ELF);
     98   arch_ops = fmt && fmt->elf_machine ? fmt->elf_machine(e_machine) : NULL;
     99   if (!arch_ops) return KIT_UNSUPPORTED;
    100 
    101   memset(out, 0, sizeof(*out));
    102   out->arch = arch_ops->arch;
    103   out->os = KIT_OS_LINUX;
    104   out->obj = KIT_OBJ_ELF;
    105   out->ptr_size = 8u;
    106   out->ptr_align = 8u;
    107   out->big_endian = false;
    108   return KIT_OK;
    109 }
    110 
    111 static KitStatus ensure_object_cap(Compiler* c, EmuLoadedImage* img, u32 need) {
    112   Heap* heap = c->ctx->heap;
    113   u32 old_cap;
    114   u32 new_cap;
    115   EmuLoadedObject* grown;
    116   if (img->link_map.objects_cap >= need) return KIT_OK;
    117   old_cap = img->link_map.objects_cap;
    118   new_cap = old_cap ? old_cap * 2u : 4u;
    119   while (new_cap < need) new_cap *= 2u;
    120   grown = (EmuLoadedObject*)heap->realloc(
    121       heap, img->link_map.objects, sizeof(*img->link_map.objects) * old_cap,
    122       sizeof(*img->link_map.objects) * new_cap, _Alignof(EmuLoadedObject));
    123   if (!grown) return KIT_ERR;
    124   memset(grown + old_cap, 0, sizeof(*grown) * (new_cap - old_cap));
    125   img->link_map.objects = grown;
    126   img->link_map.objects_cap = new_cap;
    127   return KIT_OK;
    128 }
    129 
    130 static KitStatus parse_object_dynamic(EmuLoadedImage* img,
    131                                       EmuLoadedObject* obj) {
    132   u8* dyn;
    133   u64 dynamic_size;
    134   u64 strtab = 0, strsz = 0;
    135   u64 needed_offs[16];
    136   u32 nneeded_offs = 0;
    137   u64 j;
    138   EmuElfDynInfo* dinfo = elf_dyn(obj);
    139   if (!dinfo || !dinfo->dynamic_vaddr) return KIT_OK;
    140   dynamic_size = dinfo->dynamic_size;
    141   dyn = emu_addr_space_ptr(&img->addr_space, dinfo->dynamic_vaddr, dynamic_size,
    142                            EMU_MEM_READ);
    143   if (!dyn) return KIT_INVALID;
    144   for (j = 0; j + ELF64_DYN_SIZE <= dynamic_size; j += ELF64_DYN_SIZE) {
    145     u64 tag = rd64(dyn + j);
    146     u64 val = rd64(dyn + j + 8u);
    147     u64 ptr = obj->load_bias + val;
    148     if (tag == DT_NULL) break;
    149     switch (tag) {
    150       case DT_NEEDED:
    151         if (nneeded_offs < sizeof(needed_offs) / sizeof(needed_offs[0]))
    152           needed_offs[nneeded_offs++] = val;
    153         break;
    154       case DT_STRTAB:
    155         strtab = ptr;
    156         dinfo->strtab = ptr;
    157         break;
    158       case DT_STRSZ:
    159         strsz = val;
    160         dinfo->strsz = val;
    161         break;
    162       case DT_SYMTAB:
    163         dinfo->symtab = ptr;
    164         break;
    165       case DT_SYMENT:
    166         dinfo->syment = val;
    167         break;
    168       case DT_HASH:
    169         dinfo->hash = ptr;
    170         break;
    171       case DT_GNU_HASH:
    172         dinfo->gnu_hash = ptr;
    173         break;
    174       case DT_RELA:
    175         dinfo->rela = ptr;
    176         break;
    177       case DT_RELASZ:
    178         dinfo->relasz = val;
    179         break;
    180       case DT_RELAENT:
    181         dinfo->relaent = val;
    182         break;
    183       case DT_JMPREL:
    184         dinfo->jmprel = ptr;
    185         break;
    186       case DT_PLTRELSZ:
    187         dinfo->pltrelsz = val;
    188         break;
    189       case DT_PLTGOT:
    190         dinfo->pltgot = ptr;
    191         break;
    192       case DT_INIT:
    193         obj->init_fini.init = ptr;
    194         break;
    195       case DT_FINI:
    196         obj->init_fini.fini = ptr;
    197         break;
    198       case DT_INIT_ARRAY:
    199         obj->init_fini.init_array = ptr;
    200         break;
    201       case DT_INIT_ARRAYSZ:
    202         obj->init_fini.init_arraysz = val;
    203         break;
    204       case DT_FINI_ARRAY:
    205         obj->init_fini.fini_array = ptr;
    206         break;
    207       case DT_FINI_ARRAYSZ:
    208         obj->init_fini.fini_arraysz = val;
    209         break;
    210       case DT_SONAME:
    211         if (strtab) {
    212           u8* s = emu_addr_space_ptr(&img->addr_space, strtab + val, 1,
    213                                      EMU_MEM_READ);
    214           if (s) {
    215             obj->soname = cstr_at(s, strsz > val ? strsz - val : 0);
    216           }
    217         }
    218         break;
    219       default:
    220         break;
    221     }
    222   }
    223   for (j = 0; j < nneeded_offs; ++j) {
    224     u64 val = needed_offs[j];
    225     if (strtab && obj->imports.nneeded < sizeof(obj->imports.needed) /
    226                                              sizeof(obj->imports.needed[0])) {
    227       u8* s =
    228           emu_addr_space_ptr(&img->addr_space, strtab + val, 1, EMU_MEM_READ);
    229       if (s)
    230         obj->imports.needed[obj->imports.nneeded++] =
    231             cstr_at(s, strsz > val ? strsz - val : 0);
    232     }
    233   }
    234   return KIT_OK;
    235 }
    236 
    237 static KitStatus elf_load_one_object(Compiler* c, EmuProcess* process,
    238                                      EmuLoadedImage* img, KitSlice name,
    239                                      KitSlice bytes_slice, int is_main,
    240                                      u32* out_index) {
    241   const u8* bytes = bytes_slice.data;
    242   size_t len = bytes_slice.len;
    243   u16 e_type, e_machine, e_phentsize, e_phnum;
    244   const ObjFormatImpl* fmt;
    245   const ObjElfArchOps* arch_ops;
    246   u64 e_entry, e_phoff;
    247   u64 lo_va = 0, hi_va = 0, load_bias = 0;
    248   int saw_load = 0;
    249   u32 i;
    250   EmuLoadedObject* obj;
    251 
    252   if (!bytes || len < ELF64_EHDR_SIZE) return KIT_INVALID;
    253   if (bytes[EI_MAG0] != ELFMAG0 || bytes[EI_MAG1] != ELFMAG1 ||
    254       bytes[EI_MAG2] != ELFMAG2 || bytes[EI_MAG3] != ELFMAG3)
    255     return KIT_INVALID;
    256   if (bytes[EI_CLASS] != ELFCLASS64 || bytes[EI_DATA] != ELFDATA2LSB)
    257     return KIT_UNSUPPORTED;
    258   e_type = rd16(bytes + 16);
    259   e_machine = rd16(bytes + 18);
    260   e_entry = rd64(bytes + 24);
    261   e_phoff = rd64(bytes + 32);
    262   e_phentsize = rd16(bytes + 54);
    263   e_phnum = rd16(bytes + 56);
    264   fmt = obj_format_lookup(KIT_OBJ_ELF);
    265   arch_ops = fmt && fmt->elf_machine ? fmt->elf_machine(e_machine) : NULL;
    266   if (!arch_ops) return KIT_UNSUPPORTED;
    267   if (process && process->guest_target.arch != arch_ops->arch)
    268     return KIT_UNSUPPORTED;
    269   if (is_main ? e_type != ET_EXEC : e_type != ET_DYN) return KIT_UNSUPPORTED;
    270   if (e_phentsize < ELF64_PHDR_SIZE) return KIT_INVALID;
    271   if ((u64)e_phoff + (u64)e_phnum * e_phentsize > len) return KIT_INVALID;
    272 
    273   for (i = 0; i < e_phnum; ++i) {
    274     const u8* ph = bytes + e_phoff + (u64)i * e_phentsize;
    275     u32 p_type = rd32(ph);
    276     u64 p_vaddr = rd64(ph + 16);
    277     u64 p_memsz = rd64(ph + 40);
    278     if (p_type != PT_LOAD) continue;
    279     if (!saw_load) {
    280       lo_va = round_down(p_vaddr, EMU_PAGE_SIZE);
    281       hi_va = round_up(p_vaddr + p_memsz, EMU_PAGE_SIZE);
    282       saw_load = 1;
    283     } else {
    284       u64 lo = round_down(p_vaddr, EMU_PAGE_SIZE);
    285       u64 hi = round_up(p_vaddr + p_memsz, EMU_PAGE_SIZE);
    286       if (lo < lo_va) lo_va = lo;
    287       if (hi > hi_va) hi_va = hi;
    288     }
    289   }
    290   if (!saw_load) return KIT_INVALID;
    291   if (!is_main) {
    292     if (emu_addr_space_find_gap(&img->addr_space, hi_va - lo_va, EMU_PAGE_SIZE,
    293                                 0x2000000000ull, 0x3000000000ull,
    294                                 &load_bias) != KIT_OK)
    295       return KIT_ERR;
    296     load_bias -= lo_va;
    297   }
    298 
    299   if (ensure_object_cap(c, img, img->link_map.nobjects + 1u) != KIT_OK)
    300     return KIT_ERR;
    301   obj = &img->link_map.objects[img->link_map.nobjects];
    302   memset(obj, 0, sizeof(*obj));
    303   obj->name = name;
    304   obj->load_bias = load_bias;
    305   obj->map_start = load_bias + lo_va;
    306   obj->map_end = load_bias + hi_va;
    307   if (emu_object_format_data_alloc(c, obj, sizeof(EmuElfDynInfo),
    308                                    _Alignof(EmuElfDynInfo),
    309                                    &obj->format.data) != KIT_OK)
    310     return KIT_ERR;
    311   *out_index = img->link_map.nobjects++;
    312 
    313   for (i = 0; i < e_phnum; ++i) {
    314     const u8* ph = bytes + e_phoff + (u64)i * e_phentsize;
    315     u32 p_type = rd32(ph);
    316     u32 p_flags = rd32(ph + 4);
    317     u64 p_offset = rd64(ph + 8);
    318     u64 p_vaddr = rd64(ph + 16);
    319     u64 p_filesz = rd64(ph + 32);
    320     u64 p_memsz = rd64(ph + 40);
    321     u64 p_align = rd64(ph + 48);
    322     if (p_type == PT_LOAD) {
    323       u64 map_start = round_down(load_bias + p_vaddr, EMU_PAGE_SIZE);
    324       u64 map_end = round_up(load_bias + p_vaddr + p_memsz, EMU_PAGE_SIZE);
    325       if (p_filesz > p_memsz || p_offset + p_filesz > len) return KIT_INVALID;
    326       if (emu_addr_space_map(&img->addr_space, map_start, map_end - map_start,
    327                              elf_phdr_perms(p_flags), EMU_MAP_FILE) != KIT_OK)
    328         return KIT_ERR;
    329       if (p_filesz &&
    330           emu_addr_space_copy_in(&img->addr_space, load_bias + p_vaddr,
    331                                  bytes + p_offset, p_filesz) != KIT_OK)
    332         return KIT_ERR;
    333     } else if (p_type == PT_DYNAMIC) {
    334       EmuElfDynInfo* dinfo = elf_dyn(obj);
    335       if (!dinfo) return KIT_ERR;
    336       dinfo->dynamic_vaddr = load_bias + p_vaddr;
    337       dinfo->dynamic_size = p_filesz;
    338     } else if (p_type == PT_TLS) {
    339       obj->tls.image_vaddr = load_bias + p_vaddr;
    340       obj->tls.filesz = p_filesz;
    341       obj->tls.memsz = p_memsz;
    342       obj->tls.align = p_align;
    343       obj->tls.module_id = *out_index + 1u;
    344     } else if (is_main && p_type == PT_INTERP && p_offset + p_filesz <= len) {
    345       img->process_info.interpreter_path = cstr_at(bytes + p_offset, p_filesz);
    346     }
    347   }
    348   if (is_main) {
    349     img->entry_pc = e_entry;
    350     img->process_info.headers_vaddr = lo_va + e_phoff;
    351     img->process_info.header_entry_size = e_phentsize;
    352     img->process_info.header_count = e_phnum;
    353   }
    354   return parse_object_dynamic(img, obj);
    355 }
    356 
    357 static KitStatus elf_load_executable(Compiler* c, const EmuLoadOptions* opts,
    358                                      EmuLoadedImage* out) {
    359   u32 index = 0;
    360   if (!out) return KIT_INVALID;
    361   memset(out, 0, sizeof(*out));
    362   if (!c || !opts || !opts->bytes.data || opts->bytes.len < ELF64_EHDR_SIZE)
    363     return KIT_INVALID;
    364   if (emu_addr_space_init(&out->addr_space, c, EMU_PAGE_SIZE) != KIT_OK)
    365     return KIT_ERR;
    366   if (elf_load_one_object(c, opts->process, out, opts->name, opts->bytes, 1,
    367                           &index) != KIT_OK) {
    368     emu_unload_image(c, out);
    369     return KIT_ERR;
    370   }
    371   out->link_map.main_object = index;
    372   out->link_map.global_scope_head = index;
    373   return KIT_OK;
    374 }
    375 
    376 static u32 elf_emu_reloc_from(KitArchKind arch, u32 wire_type) {
    377   const ObjFormatImpl* fmt = obj_format_lookup(KIT_OBJ_ELF);
    378   const ObjElfArchOps* ops;
    379   if (!fmt || !fmt->elf_arch) return (u32)-1;
    380   ops = fmt->elf_arch(arch);
    381   if (!ops || !ops->reloc_from) return (u32)-1;
    382   return ops->reloc_from(wire_type);
    383 }
    384 
    385 static u32 elf_object_sym_count(EmuProcess* process,
    386                                 const EmuLoadedObject* obj) {
    387   u8* h;
    388   const EmuElfDynInfo* dinfo = elf_dyn_const(obj);
    389   if (dinfo && dinfo->hash) {
    390     h = emu_addr_space_ptr(&process->image.addr_space, dinfo->hash, 8u,
    391                            EMU_MEM_READ);
    392     if (h) return rd32(h + 4u);
    393   }
    394   return 32u;
    395 }
    396 
    397 static KitStatus elf_symbol_at(EmuProcess* process, const EmuLoadedObject* obj,
    398                                u64 index, EmuDynSymbol* out) {
    399   u8* sym;
    400   u32 st_name;
    401   u16 st_shndx;
    402   u8* name;
    403   const EmuElfDynInfo* dinfo = elf_dyn_const(obj);
    404   if (!process || !obj || !out || !dinfo || !dinfo->symtab || !dinfo->strtab)
    405     return KIT_INVALID;
    406   sym = emu_addr_space_ptr(&process->image.addr_space,
    407                            dinfo->symtab + index * ELF64_SYM_SIZE,
    408                            ELF64_SYM_SIZE, EMU_MEM_READ);
    409   if (!sym) return KIT_INVALID;
    410   st_name = rd32(sym);
    411   st_shndx = (u16)(sym[6u] | ((u16)sym[7u] << 8));
    412   memset(out, 0, sizeof(*out));
    413   out->index = index;
    414   out->value = rd64(sym + 8u);
    415   out->size = rd64(sym + 16u);
    416   out->defined = st_shndx != SHN_UNDEF;
    417   if (st_name) {
    418     name = emu_addr_space_ptr(&process->image.addr_space,
    419                               dinfo->strtab + st_name, 1u, EMU_MEM_READ);
    420     if (!name) return KIT_INVALID;
    421     out->name =
    422         cstr_at(name, dinfo->strsz > st_name ? dinfo->strsz - st_name : 256u);
    423   }
    424   return KIT_OK;
    425 }
    426 
    427 static void elf_dyn_needed_iter(const EmuLoadedObject* obj,
    428                                 EmuDynNeededIter* out) {
    429   if (!out) return;
    430   memset(out, 0, sizeof(*out));
    431   out->object = obj;
    432 }
    433 
    434 static int elf_dyn_needed_next(EmuProcess* process, EmuDynNeededIter* it,
    435                                KitSlice* out) {
    436   (void)process;
    437   if (!it || !it->object || !out) return 0;
    438   if (it->index >= it->object->imports.nneeded) return 0;
    439   *out = it->object->imports.needed[it->index++];
    440   return 1;
    441 }
    442 
    443 static KitStatus elf_dyn_symbol_lookup(EmuProcess* process,
    444                                        const EmuLoadedObject* obj,
    445                                        KitSlice symbol, EmuDynSymbol* out) {
    446   u32 n;
    447   u32 i;
    448   if (!process || !obj || !out) return KIT_INVALID;
    449   n = elf_object_sym_count(process, obj);
    450   for (i = 1u; i < n; ++i) {
    451     EmuDynSymbol have;
    452     if (elf_symbol_at(process, obj, i, &have) != KIT_OK) continue;
    453     if (have.defined && have.name.data && kit_slice_eq(have.name, symbol)) {
    454       *out = have;
    455       return KIT_OK;
    456     }
    457   }
    458   return KIT_NOT_FOUND;
    459 }
    460 
    461 static KitStatus elf_dyn_symbol_by_index(EmuProcess* process,
    462                                          const EmuLoadedObject* obj,
    463                                          u64 symbol_index, EmuDynSymbol* out) {
    464   return elf_symbol_at(process, obj, symbol_index, out);
    465 }
    466 
    467 static void elf_reloc_iter(const EmuLoadedObject* obj,
    468                            EmuDynRelocTableKind table, EmuDynRelocIter* out) {
    469   if (!out) return;
    470   memset(out, 0, sizeof(*out));
    471   out->object = obj;
    472   out->table = table;
    473 }
    474 
    475 static int elf_reloc_next(EmuProcess* process, EmuDynRelocIter* it,
    476                           EmuDynReloc* out) {
    477   const EmuLoadedObject* obj;
    478   u64 base;
    479   u64 size;
    480   u8* rela;
    481   u64 r_info;
    482   const EmuElfDynInfo* dinfo;
    483   if (!process || !it || !it->object || !out) return 0;
    484   obj = it->object;
    485   dinfo = elf_dyn_const(obj);
    486   if (!dinfo) return 0;
    487   if (it->table == EMU_DYN_RELOC_TABLE_PLT) {
    488     base = dinfo->jmprel;
    489     size = dinfo->pltrelsz;
    490   } else {
    491     base = dinfo->rela;
    492     size = dinfo->relasz;
    493   }
    494   if (!base || it->cursor + ELF64_RELA_SIZE > size) return 0;
    495   rela = emu_addr_space_ptr(&process->image.addr_space, base + it->cursor,
    496                             ELF64_RELA_SIZE, EMU_MEM_READ);
    497   it->cursor += ELF64_RELA_SIZE;
    498   if (!rela) return 0;
    499   r_info = rd64(rela + 8u);
    500   memset(out, 0, sizeof(*out));
    501   out->patch_addr = obj->load_bias + rd64(rela);
    502   out->symbol_index = r_info >> 32;
    503   out->wire_type = r_info & 0xffffffffull;
    504   out->addend = (i64)rd64(rela + 16u);
    505   out->width = 8u;
    506   return 1;
    507 }
    508 
    509 static KitStatus elf_reloc_classify(EmuProcess* process,
    510                                     const EmuLoadedObject* obj,
    511                                     const EmuDynReloc* reloc,
    512                                     EmuDynRelocClass* cls, u32* kind_out) {
    513   u32 r_type;
    514   (void)obj;
    515   if (!process || !reloc || !cls || !kind_out) return KIT_INVALID;
    516   r_type = (u32)reloc->wire_type;
    517   *cls = EMU_DYN_RELOC_NONE;
    518   *kind_out = R_NONE;
    519   if (process->guest_target.arch == KIT_ARCH_RV64 &&
    520       r_type == ELF_R_RISCV_RELATIVE) {
    521     *cls = EMU_DYN_RELOC_RELATIVE;
    522     *kind_out = (u32)R_ABS64;
    523     return KIT_OK;
    524   }
    525   if (process->guest_target.arch == KIT_ARCH_RV64 &&
    526       (r_type == ELF_R_RISCV_JUMP_SLOT || r_type == ELF_R_RISCV_64)) {
    527     *cls = r_type == ELF_R_RISCV_JUMP_SLOT ? EMU_DYN_RELOC_IMPORT_SLOT
    528                                            : EMU_DYN_RELOC_SYMBOLIC;
    529     *kind_out = (u32)R_ABS64;
    530     return KIT_OK;
    531   }
    532   if (r_type == 0) return KIT_OK;
    533   if (elf_emu_reloc_from(process->guest_target.arch, r_type) == (u32)-1)
    534     return KIT_UNSUPPORTED;
    535   *cls = EMU_DYN_RELOC_RELATIVE;
    536   *kind_out = elf_emu_reloc_from(process->guest_target.arch, r_type);
    537   return *kind_out == R_NONE ? KIT_UNSUPPORTED : KIT_OK;
    538 }
    539 
    540 const ObjFormatEmuOps elf_emu_ops = {
    541     .detect_executable = elf_detect_executable,
    542     .load_executable = elf_load_executable,
    543     .map_object = elf_load_one_object,
    544     .dyn_needed_iter = elf_dyn_needed_iter,
    545     .dyn_needed_next = elf_dyn_needed_next,
    546     .dyn_symbol_lookup = elf_dyn_symbol_lookup,
    547     .dyn_symbol_by_index = elf_dyn_symbol_by_index,
    548     .reloc_iter = elf_reloc_iter,
    549     .reloc_next = elf_reloc_next,
    550     .reloc_classify = elf_reloc_classify,
    551     .reloc_from = elf_emu_reloc_from,
    552 };