diff options
author | Jerry Zhao <jerryz123@berkeley.edu> | 2024-05-29 10:28:14 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-05-29 10:28:14 -0700 |
commit | 3a70f84b8a2249c92d35c2229b48ca5735a543fa (patch) | |
tree | 148610235fe88b66ef6577143677d328efa62814 /fesvr/elfloader.cc | |
parent | a53a71fcc3c985cf95973e86e40814c30c551a68 (diff) | |
parent | a316a37331aaaa4c8905ba37a86bde42a2c75343 (diff) | |
download | spike-3a70f84b8a2249c92d35c2229b48ca5735a543fa.zip spike-3a70f84b8a2249c92d35c2229b48ca5735a543fa.tar.gz spike-3a70f84b8a2249c92d35c2229b48ca5735a543fa.tar.bz2 |
Merge pull request #1670 from clementleger/dev/cleger/et_dyn
add support to load ET_DYN elf
Diffstat (limited to 'fesvr/elfloader.cc')
-rw-r--r-- | fesvr/elfloader.cc | 19 |
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) |