kit

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

emu_load.c (18676B)


      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[EMU_MAX_NEEDED];
    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 < EMU_MAX_NEEDED)
    152           needed_offs[nneeded_offs++] = val;
    153         else
    154           KIT_LOGW(
    155               "emu: >%d DT_NEEDED entries; extra shared-library deps "
    156               "ignored",
    157               EMU_MAX_NEEDED);
    158         break;
    159       case DT_STRTAB:
    160         strtab = ptr;
    161         dinfo->strtab = ptr;
    162         break;
    163       case DT_STRSZ:
    164         strsz = val;
    165         dinfo->strsz = val;
    166         break;
    167       case DT_SYMTAB:
    168         dinfo->symtab = ptr;
    169         break;
    170       case DT_SYMENT:
    171         dinfo->syment = val;
    172         break;
    173       case DT_HASH:
    174         dinfo->hash = ptr;
    175         break;
    176       case DT_GNU_HASH:
    177         dinfo->gnu_hash = ptr;
    178         break;
    179       case DT_RELA:
    180         dinfo->rela = ptr;
    181         break;
    182       case DT_RELASZ:
    183         dinfo->relasz = val;
    184         break;
    185       case DT_RELAENT:
    186         dinfo->relaent = val;
    187         break;
    188       case DT_JMPREL:
    189         dinfo->jmprel = ptr;
    190         break;
    191       case DT_PLTRELSZ:
    192         dinfo->pltrelsz = val;
    193         break;
    194       case DT_PLTGOT:
    195         dinfo->pltgot = ptr;
    196         break;
    197       case DT_INIT:
    198         obj->init_fini.init = ptr;
    199         break;
    200       case DT_FINI:
    201         obj->init_fini.fini = ptr;
    202         break;
    203       case DT_INIT_ARRAY:
    204         obj->init_fini.init_array = ptr;
    205         break;
    206       case DT_INIT_ARRAYSZ:
    207         obj->init_fini.init_arraysz = val;
    208         break;
    209       case DT_FINI_ARRAY:
    210         obj->init_fini.fini_array = ptr;
    211         break;
    212       case DT_FINI_ARRAYSZ:
    213         obj->init_fini.fini_arraysz = val;
    214         break;
    215       case DT_SONAME:
    216         if (strtab) {
    217           u8* s = emu_addr_space_ptr(&img->addr_space, strtab + val, 1,
    218                                      EMU_MEM_READ);
    219           if (s) {
    220             obj->soname = cstr_at(s, strsz > val ? strsz - val : 0);
    221           }
    222         }
    223         break;
    224       default:
    225         break;
    226     }
    227   }
    228   for (j = 0; j < nneeded_offs; ++j) {
    229     u64 val = needed_offs[j];
    230     if (strtab && obj->imports.nneeded < EMU_MAX_NEEDED) {
    231       u8* s =
    232           emu_addr_space_ptr(&img->addr_space, strtab + val, 1, EMU_MEM_READ);
    233       if (s)
    234         obj->imports.needed[obj->imports.nneeded++] =
    235             cstr_at(s, strsz > val ? strsz - val : 0);
    236     }
    237   }
    238   return KIT_OK;
    239 }
    240 
    241 static KitStatus elf_load_one_object(Compiler* c, EmuProcess* process,
    242                                      EmuLoadedImage* img, KitSlice name,
    243                                      KitSlice bytes_slice, int is_main,
    244                                      u32* out_index) {
    245   const u8* bytes = bytes_slice.data;
    246   size_t len = bytes_slice.len;
    247   u16 e_type, e_machine, e_phentsize, e_phnum;
    248   const ObjFormatImpl* fmt;
    249   const ObjElfArchOps* arch_ops;
    250   u64 e_entry, e_phoff;
    251   u64 lo_va = 0, hi_va = 0, load_bias = 0;
    252   int saw_load = 0;
    253   u32 i;
    254   EmuLoadedObject* obj;
    255 
    256   if (!bytes || len < ELF64_EHDR_SIZE) return KIT_INVALID;
    257   if (bytes[EI_MAG0] != ELFMAG0 || bytes[EI_MAG1] != ELFMAG1 ||
    258       bytes[EI_MAG2] != ELFMAG2 || bytes[EI_MAG3] != ELFMAG3)
    259     return KIT_INVALID;
    260   if (bytes[EI_CLASS] != ELFCLASS64 || bytes[EI_DATA] != ELFDATA2LSB)
    261     return KIT_UNSUPPORTED;
    262   e_type = rd16(bytes + 16);
    263   e_machine = rd16(bytes + 18);
    264   e_entry = rd64(bytes + 24);
    265   e_phoff = rd64(bytes + 32);
    266   e_phentsize = rd16(bytes + 54);
    267   e_phnum = rd16(bytes + 56);
    268   fmt = obj_format_lookup(KIT_OBJ_ELF);
    269   arch_ops = fmt && fmt->elf_machine ? fmt->elf_machine(e_machine) : NULL;
    270   if (!arch_ops) return KIT_UNSUPPORTED;
    271   if (process && process->guest_target.arch != arch_ops->arch)
    272     return KIT_UNSUPPORTED;
    273   if (is_main ? e_type != ET_EXEC : e_type != ET_DYN) return KIT_UNSUPPORTED;
    274   if (e_phentsize < ELF64_PHDR_SIZE) return KIT_INVALID;
    275   if ((u64)e_phoff + (u64)e_phnum * e_phentsize > len) return KIT_INVALID;
    276 
    277   for (i = 0; i < e_phnum; ++i) {
    278     const u8* ph = bytes + e_phoff + (u64)i * e_phentsize;
    279     u32 p_type = rd32(ph);
    280     u64 p_vaddr = rd64(ph + 16);
    281     u64 p_memsz = rd64(ph + 40);
    282     if (p_type != PT_LOAD) continue;
    283     if (!saw_load) {
    284       lo_va = round_down(p_vaddr, EMU_PAGE_SIZE);
    285       hi_va = round_up(p_vaddr + p_memsz, EMU_PAGE_SIZE);
    286       saw_load = 1;
    287     } else {
    288       u64 lo = round_down(p_vaddr, EMU_PAGE_SIZE);
    289       u64 hi = round_up(p_vaddr + p_memsz, EMU_PAGE_SIZE);
    290       if (lo < lo_va) lo_va = lo;
    291       if (hi > hi_va) hi_va = hi;
    292     }
    293   }
    294   if (!saw_load) return KIT_INVALID;
    295   if (!is_main) {
    296     if (emu_addr_space_find_gap(&img->addr_space, hi_va - lo_va, EMU_PAGE_SIZE,
    297                                 0x2000000000ull, 0x3000000000ull,
    298                                 &load_bias) != KIT_OK)
    299       return KIT_ERR;
    300     load_bias -= lo_va;
    301   }
    302 
    303   if (ensure_object_cap(c, img, img->link_map.nobjects + 1u) != KIT_OK)
    304     return KIT_ERR;
    305   obj = &img->link_map.objects[img->link_map.nobjects];
    306   memset(obj, 0, sizeof(*obj));
    307   obj->name = name;
    308   obj->load_bias = load_bias;
    309   obj->map_start = load_bias + lo_va;
    310   obj->map_end = load_bias + hi_va;
    311   if (emu_object_format_data_alloc(c, obj, sizeof(EmuElfDynInfo),
    312                                    _Alignof(EmuElfDynInfo),
    313                                    &obj->format.data) != KIT_OK)
    314     return KIT_ERR;
    315   *out_index = img->link_map.nobjects++;
    316 
    317   for (i = 0; i < e_phnum; ++i) {
    318     const u8* ph = bytes + e_phoff + (u64)i * e_phentsize;
    319     u32 p_type = rd32(ph);
    320     u32 p_flags = rd32(ph + 4);
    321     u64 p_offset = rd64(ph + 8);
    322     u64 p_vaddr = rd64(ph + 16);
    323     u64 p_filesz = rd64(ph + 32);
    324     u64 p_memsz = rd64(ph + 40);
    325     u64 p_align = rd64(ph + 48);
    326     if (p_type == PT_LOAD) {
    327       u64 map_start = round_down(load_bias + p_vaddr, EMU_PAGE_SIZE);
    328       u64 map_end = round_up(load_bias + p_vaddr + p_memsz, EMU_PAGE_SIZE);
    329       if (p_filesz > p_memsz || p_offset + p_filesz > len) return KIT_INVALID;
    330       if (emu_addr_space_map(&img->addr_space, map_start, map_end - map_start,
    331                              elf_phdr_perms(p_flags), EMU_MAP_FILE) != KIT_OK)
    332         return KIT_ERR;
    333       if (p_filesz &&
    334           emu_addr_space_copy_in(&img->addr_space, load_bias + p_vaddr,
    335                                  bytes + p_offset, p_filesz) != KIT_OK)
    336         return KIT_ERR;
    337     } else if (p_type == PT_DYNAMIC) {
    338       EmuElfDynInfo* dinfo = elf_dyn(obj);
    339       if (!dinfo) return KIT_ERR;
    340       dinfo->dynamic_vaddr = load_bias + p_vaddr;
    341       dinfo->dynamic_size = p_filesz;
    342     } else if (p_type == PT_TLS) {
    343       obj->tls.image_vaddr = load_bias + p_vaddr;
    344       obj->tls.filesz = p_filesz;
    345       obj->tls.memsz = p_memsz;
    346       obj->tls.align = p_align;
    347       obj->tls.module_id = *out_index + 1u;
    348     } else if (is_main && p_type == PT_INTERP && p_offset + p_filesz <= len) {
    349       img->process_info.interpreter_path = cstr_at(bytes + p_offset, p_filesz);
    350     }
    351   }
    352   if (is_main) {
    353     img->entry_pc = e_entry;
    354     img->process_info.headers_vaddr = lo_va + e_phoff;
    355     img->process_info.header_entry_size = e_phentsize;
    356     img->process_info.header_count = e_phnum;
    357   }
    358   return parse_object_dynamic(img, obj);
    359 }
    360 
    361 static KitStatus elf_load_executable(Compiler* c, const EmuLoadOptions* opts,
    362                                      EmuLoadedImage* out) {
    363   u32 index = 0;
    364   if (!out) return KIT_INVALID;
    365   memset(out, 0, sizeof(*out));
    366   if (!c || !opts || !opts->bytes.data || opts->bytes.len < ELF64_EHDR_SIZE)
    367     return KIT_INVALID;
    368   if (emu_addr_space_init(&out->addr_space, c, EMU_PAGE_SIZE) != KIT_OK)
    369     return KIT_ERR;
    370   if (elf_load_one_object(c, opts->process, out, opts->name, opts->bytes, 1,
    371                           &index) != KIT_OK) {
    372     emu_unload_image(c, out);
    373     return KIT_ERR;
    374   }
    375   out->link_map.main_object = index;
    376   out->link_map.global_scope_head = index;
    377   return KIT_OK;
    378 }
    379 
    380 static u32 elf_emu_reloc_from(KitArchKind arch, u32 wire_type) {
    381   const ObjFormatImpl* fmt = obj_format_lookup(KIT_OBJ_ELF);
    382   const ObjElfArchOps* ops;
    383   if (!fmt || !fmt->elf_arch) return (u32)-1;
    384   ops = fmt->elf_arch(arch);
    385   if (!ops || !ops->reloc_from) return (u32)-1;
    386   return ops->reloc_from(wire_type);
    387 }
    388 
    389 static u32 elf_object_sym_count(EmuProcess* process,
    390                                 const EmuLoadedObject* obj) {
    391   u8* h;
    392   const EmuElfDynInfo* dinfo = elf_dyn_const(obj);
    393   if (dinfo && dinfo->hash) {
    394     h = emu_addr_space_ptr(&process->image.addr_space, dinfo->hash, 8u,
    395                            EMU_MEM_READ);
    396     if (h) return rd32(h + 4u);
    397   }
    398   return 32u;
    399 }
    400 
    401 static KitStatus elf_symbol_at(EmuProcess* process, const EmuLoadedObject* obj,
    402                                u64 index, EmuDynSymbol* out) {
    403   u8* sym;
    404   u32 st_name;
    405   u16 st_shndx;
    406   u8* name;
    407   const EmuElfDynInfo* dinfo = elf_dyn_const(obj);
    408   if (!process || !obj || !out || !dinfo || !dinfo->symtab || !dinfo->strtab)
    409     return KIT_INVALID;
    410   sym = emu_addr_space_ptr(&process->image.addr_space,
    411                            dinfo->symtab + index * ELF64_SYM_SIZE,
    412                            ELF64_SYM_SIZE, EMU_MEM_READ);
    413   if (!sym) return KIT_INVALID;
    414   st_name = rd32(sym);
    415   st_shndx = (u16)(sym[6u] | ((u16)sym[7u] << 8));
    416   memset(out, 0, sizeof(*out));
    417   out->index = index;
    418   out->value = rd64(sym + 8u);
    419   out->size = rd64(sym + 16u);
    420   out->defined = st_shndx != SHN_UNDEF;
    421   if (st_name) {
    422     name = emu_addr_space_ptr(&process->image.addr_space,
    423                               dinfo->strtab + st_name, 1u, EMU_MEM_READ);
    424     if (!name) return KIT_INVALID;
    425     out->name =
    426         cstr_at(name, dinfo->strsz > st_name ? dinfo->strsz - st_name : 256u);
    427   }
    428   return KIT_OK;
    429 }
    430 
    431 static void elf_dyn_needed_iter(const EmuLoadedObject* obj,
    432                                 EmuDynNeededIter* out) {
    433   if (!out) return;
    434   memset(out, 0, sizeof(*out));
    435   out->object = obj;
    436 }
    437 
    438 static int elf_dyn_needed_next(EmuProcess* process, EmuDynNeededIter* it,
    439                                KitSlice* out) {
    440   (void)process;
    441   if (!it || !it->object || !out) return 0;
    442   if (it->index >= it->object->imports.nneeded) return 0;
    443   *out = it->object->imports.needed[it->index++];
    444   return 1;
    445 }
    446 
    447 static KitStatus elf_dyn_symbol_lookup(EmuProcess* process,
    448                                        const EmuLoadedObject* obj,
    449                                        KitSlice symbol, EmuDynSymbol* out) {
    450   u32 n;
    451   u32 i;
    452   if (!process || !obj || !out) return KIT_INVALID;
    453   n = elf_object_sym_count(process, obj);
    454   for (i = 1u; i < n; ++i) {
    455     EmuDynSymbol have;
    456     if (elf_symbol_at(process, obj, i, &have) != KIT_OK) continue;
    457     if (have.defined && have.name.data && kit_slice_eq(have.name, symbol)) {
    458       *out = have;
    459       return KIT_OK;
    460     }
    461   }
    462   return KIT_NOT_FOUND;
    463 }
    464 
    465 static KitStatus elf_dyn_symbol_by_index(EmuProcess* process,
    466                                          const EmuLoadedObject* obj,
    467                                          u64 symbol_index, EmuDynSymbol* out) {
    468   return elf_symbol_at(process, obj, symbol_index, out);
    469 }
    470 
    471 static void elf_reloc_iter(const EmuLoadedObject* obj,
    472                            EmuDynRelocTableKind table, EmuDynRelocIter* out) {
    473   if (!out) return;
    474   memset(out, 0, sizeof(*out));
    475   out->object = obj;
    476   out->table = table;
    477 }
    478 
    479 static int elf_reloc_next(EmuProcess* process, EmuDynRelocIter* it,
    480                           EmuDynReloc* out) {
    481   const EmuLoadedObject* obj;
    482   u64 base;
    483   u64 size;
    484   u8* rela;
    485   u64 r_info;
    486   const EmuElfDynInfo* dinfo;
    487   if (!process || !it || !it->object || !out) return 0;
    488   obj = it->object;
    489   dinfo = elf_dyn_const(obj);
    490   if (!dinfo) return 0;
    491   if (it->table == EMU_DYN_RELOC_TABLE_PLT) {
    492     base = dinfo->jmprel;
    493     size = dinfo->pltrelsz;
    494   } else {
    495     base = dinfo->rela;
    496     size = dinfo->relasz;
    497   }
    498   if (!base || it->cursor + ELF64_RELA_SIZE > size) return 0;
    499   rela = emu_addr_space_ptr(&process->image.addr_space, base + it->cursor,
    500                             ELF64_RELA_SIZE, EMU_MEM_READ);
    501   it->cursor += ELF64_RELA_SIZE;
    502   if (!rela) return 0;
    503   r_info = rd64(rela + 8u);
    504   memset(out, 0, sizeof(*out));
    505   out->patch_addr = obj->load_bias + rd64(rela);
    506   out->symbol_index = r_info >> 32;
    507   out->wire_type = r_info & 0xffffffffull;
    508   out->addend = (i64)rd64(rela + 16u);
    509   out->width = 8u;
    510   return 1;
    511 }
    512 
    513 static KitStatus elf_reloc_classify(EmuProcess* process,
    514                                     const EmuLoadedObject* obj,
    515                                     const EmuDynReloc* reloc,
    516                                     EmuDynRelocClass* cls, u32* kind_out) {
    517   u32 r_type;
    518   (void)obj;
    519   if (!process || !reloc || !cls || !kind_out) return KIT_INVALID;
    520   r_type = (u32)reloc->wire_type;
    521   *cls = EMU_DYN_RELOC_NONE;
    522   *kind_out = R_NONE;
    523   if (process->guest_target.arch == KIT_ARCH_RV64 &&
    524       r_type == ELF_R_RISCV_RELATIVE) {
    525     *cls = EMU_DYN_RELOC_RELATIVE;
    526     *kind_out = (u32)R_ABS64;
    527     return KIT_OK;
    528   }
    529   if (process->guest_target.arch == KIT_ARCH_RV64 &&
    530       (r_type == ELF_R_RISCV_JUMP_SLOT || r_type == ELF_R_RISCV_64)) {
    531     *cls = r_type == ELF_R_RISCV_JUMP_SLOT ? EMU_DYN_RELOC_IMPORT_SLOT
    532                                            : EMU_DYN_RELOC_SYMBOLIC;
    533     *kind_out = (u32)R_ABS64;
    534     return KIT_OK;
    535   }
    536   if (r_type == 0) return KIT_OK;
    537   if (elf_emu_reloc_from(process->guest_target.arch, r_type) == (u32)-1)
    538     return KIT_UNSUPPORTED;
    539   *cls = EMU_DYN_RELOC_RELATIVE;
    540   *kind_out = elf_emu_reloc_from(process->guest_target.arch, r_type);
    541   return *kind_out == R_NONE ? KIT_UNSUPPORTED : KIT_OK;
    542 }
    543 
    544 const ObjFormatEmuOps elf_emu_ops = {
    545     .detect_executable = elf_detect_executable,
    546     .load_executable = elf_load_executable,
    547     .map_object = elf_load_one_object,
    548     .dyn_needed_iter = elf_dyn_needed_iter,
    549     .dyn_needed_next = elf_dyn_needed_next,
    550     .dyn_symbol_lookup = elf_dyn_symbol_lookup,
    551     .dyn_symbol_by_index = elf_dyn_symbol_by_index,
    552     .reloc_iter = elf_reloc_iter,
    553     .reloc_next = elf_reloc_next,
    554     .reloc_classify = elf_reloc_classify,
    555     .reloc_from = elf_emu_reloc_from,
    556 };