|
|
|
@ -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) |
|
|
|
|