ld: implement support for exposing ld functions to loaded executables
This commit is contained in:
+28
-9
@@ -6,10 +6,10 @@
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <mango/config.h>
|
||||
#include <mango/handle.h>
|
||||
#include <mango/log.h>
|
||||
#include <mango/vm.h>
|
||||
#include <magenta/config.h>
|
||||
#include <magenta/handle.h>
|
||||
#include <magenta/log.h>
|
||||
#include <magenta/vm.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -112,14 +112,17 @@ static int map_image(struct elf_image *image)
|
||||
int r = read(image->e_fd, &phdr, sizeof phdr);
|
||||
|
||||
if (r < 0) {
|
||||
kern_tracef("PHDR read failed");
|
||||
return -r;
|
||||
}
|
||||
|
||||
if (r != sizeof phdr) {
|
||||
kern_tracef("PHDR bad size");
|
||||
return ENOEXEC;
|
||||
}
|
||||
|
||||
if (phdr.p_type != PT_LOAD) {
|
||||
kern_tracef("PHDR != PT_LOAD");
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -163,7 +166,8 @@ static int map_image(struct elf_image *image)
|
||||
fd,
|
||||
offset);
|
||||
if (p == MAP_FAILED) {
|
||||
return EIO;
|
||||
kern_tracef("PHDR map failed (%d)", errno);
|
||||
return errno;
|
||||
}
|
||||
|
||||
kern_tracef(
|
||||
@@ -184,6 +188,8 @@ static int map_image(struct elf_image *image)
|
||||
}
|
||||
}
|
||||
|
||||
close(image->e_fd);
|
||||
image->e_fd = -1;
|
||||
kern_tracef("ld: image %s -> %zx", image->e_leaf.l_name, image->e_base);
|
||||
return SUCCESS;
|
||||
}
|
||||
@@ -274,23 +280,27 @@ static void resolve_symbol(unsigned int slot)
|
||||
|
||||
static int do_rela(struct elf_image *image, elf_rela_t *rela, bool lazy)
|
||||
{
|
||||
#if 0
|
||||
kern_tracef(
|
||||
"do_rela(%p, %d, %d, %d)",
|
||||
image,
|
||||
rela->r_info,
|
||||
rela->r_addend,
|
||||
rela->r_offset);
|
||||
#endif
|
||||
int type = ELF64_R_TYPE(rela->r_info);
|
||||
elf_sym_t *sym = NULL;
|
||||
|
||||
switch (type) {
|
||||
case R_X86_64_JUMP_SLOT:
|
||||
*(uint64_t *)(image->e_base + rela->r_offset) += image->e_base;
|
||||
#if 0
|
||||
kern_tracef(
|
||||
"JUMP_SLOT: offset=%zx, symbol=%zu, addend=%zx",
|
||||
rela->r_offset,
|
||||
ELF64_R_SYM(rela->r_info),
|
||||
rela->r_addend);
|
||||
#endif
|
||||
break;
|
||||
case R_X86_64_GLOB_DAT:
|
||||
sym = get_dynsym(image, ELF64_R_SYM(rela->r_info));
|
||||
@@ -300,11 +310,13 @@ static int do_rela(struct elf_image *image, elf_rela_t *rela, bool lazy)
|
||||
|
||||
*(uint64_t *)(image->e_base + rela->r_offset)
|
||||
= image->e_base + sym->st_value + rela->r_addend;
|
||||
#if 0
|
||||
kern_tracef(
|
||||
"GLOB_DAT: offset=%zx, symbol=%zu, addend=%zx",
|
||||
rela->r_offset,
|
||||
ELF64_R_SYM(rela->r_info),
|
||||
rela->r_addend);
|
||||
#endif
|
||||
break;
|
||||
case R_X86_64_64:
|
||||
sym = get_dynsym(image, ELF64_R_SYM(rela->r_info));
|
||||
@@ -314,19 +326,23 @@ static int do_rela(struct elf_image *image, elf_rela_t *rela, bool lazy)
|
||||
|
||||
*(uint64_t *)(image->e_base + rela->r_offset)
|
||||
= image->e_base + sym->st_value + rela->r_addend;
|
||||
#if 0
|
||||
kern_tracef(
|
||||
"64: offset=%zx, symbol=%zu, addend=%zx",
|
||||
rela->r_offset,
|
||||
ELF64_R_SYM(rela->r_info),
|
||||
rela->r_addend);
|
||||
#endif
|
||||
break;
|
||||
case R_X86_64_RELATIVE:
|
||||
*(uint64_t *)(image->e_base + rela->r_offset)
|
||||
= image->e_base + rela->r_addend;
|
||||
#if 0
|
||||
kern_tracef(
|
||||
"RELATIVE: offset=%zx, addend=%zx",
|
||||
rela->r_offset,
|
||||
rela->r_addend);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
kern_trace("Unknown relocation type");
|
||||
@@ -409,13 +425,14 @@ static int load_dependency(struct elf_image *image, const char *name)
|
||||
return ENOEXEC;
|
||||
}
|
||||
|
||||
static int parse_dynamic(struct elf_image *image)
|
||||
int elf_image_parse_dynamic(struct elf_image *image)
|
||||
{
|
||||
if (image->e_dynamic.p_type != PT_DYNAMIC) {
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
image->e_dyn = (elf_dyn_t *)(image->e_base + image->e_dynamic.p_vaddr);
|
||||
kern_tracef("%s .dynamic = %zx", image->e_leaf.l_name, image->e_dyn);
|
||||
|
||||
int status = SUCCESS;
|
||||
|
||||
@@ -507,8 +524,9 @@ static int parse_dynamic(struct elf_image *image)
|
||||
|
||||
static int reserve_exec_region(struct elf_image *image)
|
||||
{
|
||||
static virt_addr_t next_base = 0x10000000;
|
||||
void *base
|
||||
= mmap(NULL,
|
||||
= mmap((void *)next_base,
|
||||
image->e_length,
|
||||
PROT_NONE,
|
||||
MAP_ANONYMOUS | MAP_PRIVATE,
|
||||
@@ -518,6 +536,7 @@ static int reserve_exec_region(struct elf_image *image)
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
next_base += 0x10000000;
|
||||
image->e_base = (virt_addr_t)base;
|
||||
return KERN_OK;
|
||||
}
|
||||
@@ -613,7 +632,7 @@ int elf_image_load(struct elf_image *img)
|
||||
return e;
|
||||
}
|
||||
|
||||
e = parse_dynamic(img);
|
||||
e = elf_image_parse_dynamic(img);
|
||||
if (e != SUCCESS) {
|
||||
return e;
|
||||
}
|
||||
@@ -737,7 +756,7 @@ int elf_image_add_dependency(struct elf_image *img, struct elf_image *dep)
|
||||
|
||||
void elf_image_close(struct elf_image *image)
|
||||
{
|
||||
if (image->e_fd) {
|
||||
if (image->e_fd != -1) {
|
||||
close(image->e_fd);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user