aboutsummaryrefslogtreecommitdiff
path: root/pk/elf.c
diff options
context:
space:
mode:
authorAndrew Waterman <waterman@cs.berkeley.edu>2014-12-11 06:02:14 -0800
committerAndrew Waterman <waterman@cs.berkeley.edu>2014-12-11 06:02:14 -0800
commit19c8f691480ccc5ea8654dceff9c47888d5ea407 (patch)
treefaa98968f76ded3e157ace8cb98a97489209d5ff /pk/elf.c
parent015195b66ead210334c66ca6cb81b67c29aa50a6 (diff)
downloadriscv-pk-19c8f691480ccc5ea8654dceff9c47888d5ea407.zip
riscv-pk-19c8f691480ccc5ea8654dceff9c47888d5ea407.tar.gz
riscv-pk-19c8f691480ccc5ea8654dceff9c47888d5ea407.tar.bz2
Relocate binaries that conflict with the pk's address space
Of course, this is only possible for PIEs, e.g. the dynamic linker.
Diffstat (limited to 'pk/elf.c')
-rw-r--r--pk/elf.c12
1 files changed, 9 insertions, 3 deletions
diff --git a/pk/elf.c b/pk/elf.c
index 79ee756..28760eb 100644
--- a/pk/elf.c
+++ b/pk/elf.c
@@ -21,6 +21,11 @@ void load_elf(const char* fn, elf_info* info)
eh64.e_ident[2] == 'L' && eh64.e_ident[3] == 'F'))
goto fail;
+ size_t bias = 0;
+ extern char _end;
+ if (eh64.e_type == ET_DYN)
+ bias = ROUNDUP((uintptr_t)&_end, RISCV_PGSIZE);
+
#define LOAD_ELF do { \
eh = (typeof(eh))&eh64; \
size_t phdr_size = eh->e_phnum*sizeof(*ph); \
@@ -29,16 +34,17 @@ void load_elf(const char* fn, elf_info* info)
info->phdr = info->phdr_top - phdr_size; \
ssize_t ret = file_pread(file, (void*)info->phdr, phdr_size, eh->e_phoff); \
if (ret < (ssize_t)phdr_size) goto fail; \
- info->entry = eh->e_entry; \
+ info->entry = bias + eh->e_entry; \
info->phnum = eh->e_phnum; \
info->phent = sizeof(*ph); \
ph = (typeof(ph))info->phdr; \
for(int i = 0; i < eh->e_phnum; i++, ph++) { \
- if(ph->p_type == SHT_PROGBITS && ph->p_memsz) { \
- info->brk_min = MAX(info->brk_min, ph->p_vaddr + ph->p_memsz); \
+ if(ph->p_type == PT_LOAD && ph->p_memsz) { \
+ info->brk_min = MAX(info->brk_min, bias + ph->p_vaddr + ph->p_memsz); \
size_t vaddr = ROUNDDOWN(ph->p_vaddr, RISCV_PGSIZE), prepad = ph->p_vaddr - vaddr; \
size_t memsz = ph->p_memsz + prepad, filesz = ph->p_filesz + prepad; \
size_t offset = ph->p_offset - prepad; \
+ vaddr += bias; \
if (__do_mmap(vaddr, filesz, -1, MAP_FIXED|MAP_PRIVATE, file, offset) != vaddr) \
goto fail; \
size_t mapped = ROUNDUP(filesz, RISCV_PGSIZE); \