ld: get_dynsym can now resolve references to global symbols
This commit is contained in:
+23
-11
@@ -261,16 +261,24 @@ static int parse_phdr(struct elf_image *image)
|
||||
}
|
||||
|
||||
#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
|
||||
+ (index * image->e_dynsym_entsize));
|
||||
const char *sym_name = (const char *)(image->e_base + image->e_strtab
|
||||
+ sym->st_name);
|
||||
|
||||
if (!sym->st_value) {
|
||||
return NULL;
|
||||
if (sym->st_value) {
|
||||
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)
|
||||
@@ -289,7 +297,7 @@ static int do_rela(struct elf_image *image, elf_rela_t *rela, bool lazy)
|
||||
rela->r_offset);
|
||||
#endif
|
||||
int type = ELF64_R_TYPE(rela->r_info);
|
||||
elf_sym_t *sym = NULL;
|
||||
virt_addr_t v = 0;
|
||||
|
||||
switch (type) {
|
||||
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
|
||||
break;
|
||||
case R_X86_64_GLOB_DAT:
|
||||
sym = get_dynsym(image, ELF64_R_SYM(rela->r_info));
|
||||
if (!sym) {
|
||||
v = get_dynsym(image, ELF64_R_SYM(rela->r_info));
|
||||
if (!v) {
|
||||
return ENOEXEC;
|
||||
}
|
||||
|
||||
*(uint64_t *)(image->e_base + rela->r_offset)
|
||||
= image->e_base + sym->st_value + rela->r_addend;
|
||||
= v + rela->r_addend;
|
||||
#if 0
|
||||
kern_tracef(
|
||||
"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
|
||||
break;
|
||||
case R_X86_64_64:
|
||||
sym = get_dynsym(image, ELF64_R_SYM(rela->r_info));
|
||||
if (!sym) {
|
||||
v = get_dynsym(image, ELF64_R_SYM(rela->r_info));
|
||||
if (!v) {
|
||||
return ENOEXEC;
|
||||
}
|
||||
|
||||
*(uint64_t *)(image->e_base + rela->r_offset)
|
||||
= image->e_base + sym->st_value + rela->r_addend;
|
||||
= v + rela->r_addend;
|
||||
#if 0
|
||||
kern_tracef(
|
||||
"64: offset=%zx, symbol=%zu, addend=%zx",
|
||||
@@ -404,6 +412,7 @@ static int relocate_rel(
|
||||
size_t size,
|
||||
size_t entsize)
|
||||
{
|
||||
kern_tracef("relocate_rel (unsupported)");
|
||||
return ENOEXEC;
|
||||
}
|
||||
|
||||
@@ -624,16 +633,19 @@ int elf_image_load(struct elf_image *img)
|
||||
|
||||
int e = reserve_exec_region(img);
|
||||
if (e != SUCCESS) {
|
||||
kern_log("error 1");
|
||||
return e;
|
||||
}
|
||||
|
||||
e = map_image(img);
|
||||
if (e != SUCCESS) {
|
||||
kern_log("error 2");
|
||||
return e;
|
||||
}
|
||||
|
||||
e = elf_image_parse_dynamic(img);
|
||||
if (e != SUCCESS) {
|
||||
kern_log("error 3");
|
||||
return e;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user