#include "elf.h" #include #include #include uintptr_t dl_runtime_resolve(struct elf_image *img, unsigned long sym_id) { unsigned long slot_id = sym_id; switch (img->e_rel_entsize[ELF_RT_PLTREL]) { case sizeof(elf_rela_t): { elf_rela_t *rela = (elf_rela_t *)((virt_addr_t)img->e_base + img->e_rel_offset[ELF_RT_PLTREL]); elf_rela_t *rela_sym = &rela[sym_id]; kern_tracef( "rela %u -> .dynsym %u, .got %u", sym_id, ELF64_R_SYM(rela_sym->r_info), slot_id); sym_id = ELF64_R_SYM(rela_sym->r_info); /* the first three entries in the GOT are not symbols. */ slot_id += 3; break; } default: return 0; } elf_sym_t *sym = (elf_sym_t *)((virt_addr_t)img->e_base + img->e_dynsym); virt_addr_t *got = (virt_addr_t *)((virt_addr_t)img->e_base + img->e_got_plt); const char *sym_name = (const char *)img->e_base + img->e_strtab + sym[sym_id].st_name; kern_tracef( "%s: request for symbol %u: %s", img->e_leaf.l_name, sym_id, sym_name); #if 0 virt_addr_t sym_addr = elf_image_find_linked_symbol(img, sym_name); #else virt_addr_t sym_addr = find_global_symbol(sym_name); #endif kern_tracef("symbol %s = %zx", sym_name, sym_addr); kern_tracef("slot %s = %zx", sym_name, &got[slot_id]); got[slot_id] = sym_addr; return sym_addr; }