aboutsummaryrefslogtreecommitdiff
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
parent015195b66ead210334c66ca6cb81b67c29aa50a6 (diff)
downloadpk-19c8f691480ccc5ea8654dceff9c47888d5ea407.zip
pk-19c8f691480ccc5ea8654dceff9c47888d5ea407.tar.gz
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.
-rw-r--r--pk/elf.c12
-rw-r--r--pk/elf.h6
-rw-r--r--pk/pk.ld14
3 files changed, 13 insertions, 19 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); \
diff --git a/pk/elf.h b/pk/elf.h
index dfe6c63..a05ccf2 100644
--- a/pk/elf.h
+++ b/pk/elf.h
@@ -12,8 +12,10 @@
#define IS_ELF32(hdr) (IS_ELF(hdr) && (hdr).e_ident[4] == 1)
#define IS_ELF64(hdr) (IS_ELF(hdr) && (hdr).e_ident[4] == 2)
-#define SHT_PROGBITS 1
-#define SHT_NOBITS 8
+#define ET_EXEC 2
+#define ET_DYN 3
+
+#define PT_LOAD 1
#define AT_NULL 0
#define AT_PHDR 3
diff --git a/pk/pk.ld b/pk/pk.ld
index 1bad03a..6a93b32 100644
--- a/pk/pk.ld
+++ b/pk/pk.ld
@@ -87,18 +87,4 @@ SECTIONS
/* End of uninitialized data segment (used by syscalls.c for heap) */
PROVIDE( end = . );
_end = .;
-
- /*--------------------------------------------------------------------*/
- /* Special gcc sections (this was in idt32.ld) */
- /*--------------------------------------------------------------------*/
-
- .mdebug.abi32 0 : { KEEP(*(.mdebug.abi32)) }
- .mdebug.abiN32 0 : { KEEP(*(.mdebug.abiN32)) }
- .mdebug.abi64 0 : { KEEP(*(.mdebug.abi64)) }
- .mdebug.abiO64 0 : { KEEP(*(.mdebug.abiO64)) }
- .mdebug.eabi32 0 : { KEEP(*(.mdebug.eabi32)) }
- .mdebug.eabi64 0 : { KEEP(*(.mdebug.eabi64)) }
- .gcc_compiled_long32 0 : { KEEP(*(.gcc_compiled_long32)) }
- .gcc_compiled_long64 0 : { KEEP(*(.gcc_compiled_long64)) }
-
}