diff options
author | Andrew Waterman <waterman@cs.berkeley.edu> | 2014-12-11 06:02:14 -0800 |
---|---|---|
committer | Andrew Waterman <waterman@cs.berkeley.edu> | 2014-12-11 06:02:14 -0800 |
commit | 19c8f691480ccc5ea8654dceff9c47888d5ea407 (patch) | |
tree | faa98968f76ded3e157ace8cb98a97489209d5ff | |
parent | 015195b66ead210334c66ca6cb81b67c29aa50a6 (diff) | |
download | pk-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.c | 12 | ||||
-rw-r--r-- | pk/elf.h | 6 | ||||
-rw-r--r-- | pk/pk.ld | 14 |
3 files changed, 13 insertions, 19 deletions
@@ -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); \ @@ -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 @@ -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)) } - } |