From a316a37331aaaa4c8905ba37a86bde42a2c75343 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20L=C3=A9ger?= Date: Wed, 15 May 2024 17:15:40 +0200 Subject: add support to load ET_DYN elf MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When compiled as PIE, executable can be loaded at any memory address. Lately, OpenSBI switched to such behavior and spike was not able to load it anymore. This patch add an additional load_offset parameter for load_elf(). This load_offset value is passed as DRAM_BASE and used only for ET_DYN elfs. Signed-off-by: Clément Léger --- fesvr/elfloader.cc | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) (limited to 'fesvr/elfloader.cc') diff --git a/fesvr/elfloader.cc b/fesvr/elfloader.cc index 391afa0..5cab050 100644 --- a/fesvr/elfloader.cc +++ b/fesvr/elfloader.cc @@ -18,7 +18,8 @@ #include #include -std::map load_elf(const char* fn, memif_t* memif, reg_t* entry, unsigned required_xlen = 0) +std::map load_elf(const char* fn, memif_t* memif, reg_t* entry, + reg_t load_offset, unsigned required_xlen = 0) { int fd = open(fn, O_RDONLY); struct stat s; @@ -41,10 +42,14 @@ std::map load_elf(const char* fn, memif_t* memif, reg_t* throw incompat_xlen(required_xlen, xlen); } assert(IS_ELFLE(*eh64) || IS_ELFBE(*eh64)); - assert(IS_ELF_EXEC(*eh64)); + assert(IS_ELF_EXEC(*eh64) || IS_ELF_DYN(*eh64)); assert(IS_ELF_RISCV(*eh64) || IS_ELF_EM_NONE(*eh64)); assert(IS_ELF_VCURRENT(*eh64)); + if (IS_ELF_EXEC(*eh64)) { + load_offset = 0; + } + std::vector zeros; std::map symbols; @@ -52,19 +57,19 @@ std::map load_elf(const char* fn, memif_t* memif, reg_t* do { \ ehdr_t* eh = (ehdr_t*)buf; \ phdr_t* ph = (phdr_t*)(buf + bswap(eh->e_phoff)); \ - *entry = bswap(eh->e_entry); \ + *entry = bswap(eh->e_entry) + load_offset; \ assert(size >= bswap(eh->e_phoff) + bswap(eh->e_phnum) * sizeof(*ph)); \ for (unsigned i = 0; i < bswap(eh->e_phnum); i++) { \ if (bswap(ph[i].p_type) == PT_LOAD && bswap(ph[i].p_memsz)) { \ + reg_t load_addr = bswap(ph[i].p_paddr) + load_offset; \ if (bswap(ph[i].p_filesz)) { \ assert(size >= bswap(ph[i].p_offset) + bswap(ph[i].p_filesz)); \ - memif->write(bswap(ph[i].p_paddr), bswap(ph[i].p_filesz), \ + memif->write(load_addr, bswap(ph[i].p_filesz), \ (uint8_t*)buf + bswap(ph[i].p_offset)); \ } \ if (size_t pad = bswap(ph[i].p_memsz) - bswap(ph[i].p_filesz)) { \ zeros.resize(pad); \ - memif->write(bswap(ph[i].p_paddr) + bswap(ph[i].p_filesz), pad, \ - zeros.data()); \ + memif->write(load_addr + bswap(ph[i].p_filesz), pad, zeros.data()); \ } \ } \ } \ @@ -96,7 +101,7 @@ std::map load_elf(const char* fn, memif_t* memif, reg_t* bswap(sh[strtabidx].sh_size) - bswap(sym[i].st_name); \ assert(bswap(sym[i].st_name) < bswap(sh[strtabidx].sh_size)); \ assert(strnlen(strtab + bswap(sym[i].st_name), max_len) < max_len); \ - symbols[strtab + bswap(sym[i].st_name)] = bswap(sym[i].st_value); \ + symbols[strtab + bswap(sym[i].st_name)] = bswap(sym[i].st_value) + load_offset; \ } \ } \ } while (0) -- cgit v1.1