aboutsummaryrefslogtreecommitdiff
path: root/fesvr/elfloader.cc
diff options
context:
space:
mode:
Diffstat (limited to 'fesvr/elfloader.cc')
-rw-r--r--fesvr/elfloader.cc19
1 files changed, 12 insertions, 7 deletions
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 <map>
#include <cerrno>
-std::map<std::string, uint64_t> load_elf(const char* fn, memif_t* memif, reg_t* entry, unsigned required_xlen = 0)
+std::map<std::string, uint64_t> 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<std::string, uint64_t> 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<uint8_t> zeros;
std::map<std::string, uint64_t> symbols;
@@ -52,19 +57,19 @@ std::map<std::string, uint64_t> 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<std::string, uint64_t> 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)