ld: get_dynsym can now resolve references to global symbols

This commit is contained in:
2026-05-31 17:25:53 +01:00
parent 9af325cdee
commit e492ac7974
+23 -11
View File
@@ -261,16 +261,24 @@ static int parse_phdr(struct elf_image *image)
} }
#if 1 #if 1
static elf_sym_t *get_dynsym(struct elf_image *image, size_t index) static virt_addr_t get_dynsym(struct elf_image *image, size_t index)
{ {
elf_sym_t *sym = (elf_sym_t *)(image->e_base + image->e_dynsym elf_sym_t *sym = (elf_sym_t *)(image->e_base + image->e_dynsym
+ (index * image->e_dynsym_entsize)); + (index * image->e_dynsym_entsize));
const char *sym_name = (const char *)(image->e_base + image->e_strtab
+ sym->st_name);
if (!sym->st_value) { if (sym->st_value) {
return NULL; return image->e_base + sym->st_value;
} }
return sym; virt_addr_t sym_addr = find_global_symbol(sym_name);
if (sym_addr) {
return sym_addr;
}
kern_tracef("cannot resolve symbol %s", sym_name);
return 0;
} }
static void resolve_symbol(unsigned int slot) static void resolve_symbol(unsigned int slot)
@@ -289,7 +297,7 @@ static int do_rela(struct elf_image *image, elf_rela_t *rela, bool lazy)
rela->r_offset); rela->r_offset);
#endif #endif
int type = ELF64_R_TYPE(rela->r_info); int type = ELF64_R_TYPE(rela->r_info);
elf_sym_t *sym = NULL; virt_addr_t v = 0;
switch (type) { switch (type) {
case R_X86_64_JUMP_SLOT: case R_X86_64_JUMP_SLOT:
@@ -303,13 +311,13 @@ static int do_rela(struct elf_image *image, elf_rela_t *rela, bool lazy)
#endif #endif
break; break;
case R_X86_64_GLOB_DAT: case R_X86_64_GLOB_DAT:
sym = get_dynsym(image, ELF64_R_SYM(rela->r_info)); v = get_dynsym(image, ELF64_R_SYM(rela->r_info));
if (!sym) { if (!v) {
return ENOEXEC; return ENOEXEC;
} }
*(uint64_t *)(image->e_base + rela->r_offset) *(uint64_t *)(image->e_base + rela->r_offset)
= image->e_base + sym->st_value + rela->r_addend; = v + rela->r_addend;
#if 0 #if 0
kern_tracef( kern_tracef(
"GLOB_DAT: offset=%zx, symbol=%zu, addend=%zx", "GLOB_DAT: offset=%zx, symbol=%zu, addend=%zx",
@@ -319,13 +327,13 @@ static int do_rela(struct elf_image *image, elf_rela_t *rela, bool lazy)
#endif #endif
break; break;
case R_X86_64_64: case R_X86_64_64:
sym = get_dynsym(image, ELF64_R_SYM(rela->r_info)); v = get_dynsym(image, ELF64_R_SYM(rela->r_info));
if (!sym) { if (!v) {
return ENOEXEC; return ENOEXEC;
} }
*(uint64_t *)(image->e_base + rela->r_offset) *(uint64_t *)(image->e_base + rela->r_offset)
= image->e_base + sym->st_value + rela->r_addend; = v + rela->r_addend;
#if 0 #if 0
kern_tracef( kern_tracef(
"64: offset=%zx, symbol=%zu, addend=%zx", "64: offset=%zx, symbol=%zu, addend=%zx",
@@ -404,6 +412,7 @@ static int relocate_rel(
size_t size, size_t size,
size_t entsize) size_t entsize)
{ {
kern_tracef("relocate_rel (unsupported)");
return ENOEXEC; return ENOEXEC;
} }
@@ -624,16 +633,19 @@ int elf_image_load(struct elf_image *img)
int e = reserve_exec_region(img); int e = reserve_exec_region(img);
if (e != SUCCESS) { if (e != SUCCESS) {
kern_log("error 1");
return e; return e;
} }
e = map_image(img); e = map_image(img);
if (e != SUCCESS) { if (e != SUCCESS) {
kern_log("error 2");
return e; return e;
} }
e = elf_image_parse_dynamic(img); e = elf_image_parse_dynamic(img);
if (e != SUCCESS) { if (e != SUCCESS) {
kern_log("error 3");
return e; return e;
} }