aboutsummaryrefslogtreecommitdiff
path: root/pk
diff options
context:
space:
mode:
authorAndrew Waterman <andrew@sifive.com>2016-11-13 16:40:58 -0800
committerAndrew Waterman <andrew@sifive.com>2016-11-13 17:50:43 -0800
commitff807a20bd9a2b4b7e86cb49c466cac0a298b64e (patch)
tree038a981445eda9e850b90297343de02d28f89716 /pk
parent558039d5465f3f06b9472c42568f38e34a52c12f (diff)
downloadpk-ff807a20bd9a2b4b7e86cb49c466cac0a298b64e.zip
pk-ff807a20bd9a2b4b7e86cb49c466cac0a298b64e.tar.gz
pk-ff807a20bd9a2b4b7e86cb49c466cac0a298b64e.tar.bz2
Fix ld.so load address at 4 KiB
Diffstat (limited to 'pk')
-rw-r--r--pk/elf.c16
1 files changed, 10 insertions, 6 deletions
diff --git a/pk/elf.c b/pk/elf.c
index 1da29b2..5db3680 100644
--- a/pk/elf.c
+++ b/pk/elf.c
@@ -46,7 +46,6 @@ void load_elf(const char* fn, elf_info* info)
assert(!(eh.e_flags & EF_RISCV_RVC));
#endif
- uintptr_t min_vaddr = -1;
size_t phdr_size = eh.e_phnum * sizeof(Elf_Phdr);
if (phdr_size > info->phdr_size)
goto fail;
@@ -56,14 +55,19 @@ void load_elf(const char* fn, elf_info* info)
info->phnum = eh.e_phnum;
info->phent = sizeof(Elf_Phdr);
Elf_Phdr* ph = (typeof(ph))info->phdr;
+
+ // compute highest VA in ELF
+ uintptr_t max_vaddr = 0;
for (int i = 0; i < eh.e_phnum; i++)
- if (ph[i].p_type == PT_LOAD && ph[i].p_memsz && ph[i].p_vaddr < min_vaddr)
- min_vaddr = ph[i].p_vaddr;
- min_vaddr = ROUNDDOWN(min_vaddr, RISCV_PGSIZE);
+ if (ph[i].p_type == PT_LOAD && ph[i].p_memsz)
+ max_vaddr = MAX(max_vaddr, ph[i].p_vaddr + ph[i].p_memsz);
+ max_vaddr = ROUNDUP(max_vaddr, RISCV_PGSIZE);
+
+ // don't load dynamic linker at 0, else we can't catch NULL pointer derefs
uintptr_t bias = 0;
if (eh.e_type == ET_DYN)
- bias = first_free_paddr - min_vaddr;
- min_vaddr += bias;
+ bias = RISCV_PGSIZE;
+
info->entry = eh.e_entry + bias;
int flags = MAP_FIXED | MAP_PRIVATE;
for (int i = eh.e_phnum - 1; i >= 0; i--) {