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
|
#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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user