Browse Source

Merge pull request #1670 from clementleger/dev/cleger/et_dyn

add support to load ET_DYN elf
pull/1684/head
Jerry Zhao 2 years ago
committed by GitHub
parent
commit
3a70f84b8a
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 2
      fesvr/elf.h
  2. 2
      fesvr/elf2hex.cc
  3. 19
      fesvr/elfloader.cc
  4. 3
      fesvr/elfloader.h
  5. 8
      fesvr/htif.cc
  6. 5
      fesvr/htif.h

2
fesvr/elf.h

@ -6,6 +6,7 @@
#include <stdint.h> #include <stdint.h>
#define ET_EXEC 2 #define ET_EXEC 2
#define ET_DYN 3
#define EM_RISCV 243 #define EM_RISCV 243
#define EM_NONE 0 #define EM_NONE 0
#define EV_CURRENT 1 #define EV_CURRENT 1
@ -21,6 +22,7 @@
#define IS_ELFLE(hdr) (IS_ELF(hdr) && (hdr).e_ident[5] == 1) #define IS_ELFLE(hdr) (IS_ELF(hdr) && (hdr).e_ident[5] == 1)
#define IS_ELFBE(hdr) (IS_ELF(hdr) && (hdr).e_ident[5] == 2) #define IS_ELFBE(hdr) (IS_ELF(hdr) && (hdr).e_ident[5] == 2)
#define IS_ELF_EXEC(hdr) (IS_ELF(hdr) && ELF_SWAP((hdr), (hdr).e_type) == ET_EXEC) #define IS_ELF_EXEC(hdr) (IS_ELF(hdr) && ELF_SWAP((hdr), (hdr).e_type) == ET_EXEC)
#define IS_ELF_DYN(hdr) (IS_ELF(hdr) && ELF_SWAP((hdr), (hdr).e_type) == ET_DYN)
#define IS_ELF_RISCV(hdr) (IS_ELF(hdr) && ELF_SWAP((hdr), (hdr).e_machine) == EM_RISCV) #define IS_ELF_RISCV(hdr) (IS_ELF(hdr) && ELF_SWAP((hdr), (hdr).e_machine) == EM_RISCV)
#define IS_ELF_EM_NONE(hdr) (IS_ELF(hdr) && ELF_SWAP((hdr), (hdr).e_machine) == EM_NONE) #define IS_ELF_EM_NONE(hdr) (IS_ELF(hdr) && ELF_SWAP((hdr), (hdr).e_machine) == EM_NONE)
#define IS_ELF_VCURRENT(hdr) (IS_ELF(hdr) && ELF_SWAP((hdr), (hdr).e_version) == EV_CURRENT) #define IS_ELF_VCURRENT(hdr) (IS_ELF(hdr) && ELF_SWAP((hdr), (hdr).e_version) == EV_CURRENT)

2
fesvr/elf2hex.cc

@ -40,7 +40,7 @@ int main(int argc, char** argv)
htif_hexwriter_t htif(base, width, depth); htif_hexwriter_t htif(base, width, depth);
memif_t memif(&htif); memif_t memif(&htif);
reg_t entry; reg_t entry;
load_elf(argv[3], &memif, &entry); load_elf(argv[3], &memif, &entry, 0);
std::cout << htif; std::cout << htif;
return 0; return 0;

19
fesvr/elfloader.cc

@ -18,7 +18,8 @@
#include <map> #include <map>
#include <cerrno> #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); int fd = open(fn, O_RDONLY);
struct stat s; 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); throw incompat_xlen(required_xlen, xlen);
} }
assert(IS_ELFLE(*eh64) || IS_ELFBE(*eh64)); 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_RISCV(*eh64) || IS_ELF_EM_NONE(*eh64));
assert(IS_ELF_VCURRENT(*eh64)); assert(IS_ELF_VCURRENT(*eh64));
if (IS_ELF_EXEC(*eh64)) {
load_offset = 0;
}
std::vector<uint8_t> zeros; std::vector<uint8_t> zeros;
std::map<std::string, uint64_t> symbols; 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 { \ do { \
ehdr_t* eh = (ehdr_t*)buf; \ ehdr_t* eh = (ehdr_t*)buf; \
phdr_t* ph = (phdr_t*)(buf + bswap(eh->e_phoff)); \ 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)); \ assert(size >= bswap(eh->e_phoff) + bswap(eh->e_phnum) * sizeof(*ph)); \
for (unsigned i = 0; i < bswap(eh->e_phnum); i++) { \ for (unsigned i = 0; i < bswap(eh->e_phnum); i++) { \
if (bswap(ph[i].p_type) == PT_LOAD && bswap(ph[i].p_memsz)) { \ 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)) { \ if (bswap(ph[i].p_filesz)) { \
assert(size >= bswap(ph[i].p_offset) + 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)); \ (uint8_t*)buf + bswap(ph[i].p_offset)); \
} \ } \
if (size_t pad = bswap(ph[i].p_memsz) - bswap(ph[i].p_filesz)) { \ if (size_t pad = bswap(ph[i].p_memsz) - bswap(ph[i].p_filesz)) { \
zeros.resize(pad); \ zeros.resize(pad); \
memif->write(bswap(ph[i].p_paddr) + bswap(ph[i].p_filesz), pad, \ memif->write(load_addr + bswap(ph[i].p_filesz), pad, zeros.data()); \
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); \ bswap(sh[strtabidx].sh_size) - bswap(sym[i].st_name); \
assert(bswap(sym[i].st_name) < bswap(sh[strtabidx].sh_size)); \ assert(bswap(sym[i].st_name) < bswap(sh[strtabidx].sh_size)); \
assert(strnlen(strtab + bswap(sym[i].st_name), max_len) < max_len); \ 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) } while (0)

3
fesvr/elfloader.h

@ -8,6 +8,7 @@
#include <string> #include <string>
class memif_t; class memif_t;
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);
#endif #endif

8
fesvr/htif.cc

@ -103,7 +103,7 @@ static void bad_address(const std::string& situation, reg_t addr)
exit(-1); exit(-1);
} }
std::map<std::string, uint64_t> htif_t::load_payload(const std::string& payload, reg_t* entry) std::map<std::string, uint64_t> htif_t::load_payload(const std::string& payload, reg_t* entry, reg_t load_offset)
{ {
std::string path; std::string path;
if (access(payload.c_str(), F_OK) == 0) if (access(payload.c_str(), F_OK) == 0)
@ -143,7 +143,7 @@ std::map<std::string, uint64_t> htif_t::load_payload(const std::string& payload,
} preload_aware_memif(this); } preload_aware_memif(this);
try { try {
return load_elf(path.c_str(), &preload_aware_memif, entry, expected_xlen); return load_elf(path.c_str(), &preload_aware_memif, entry, load_offset, expected_xlen);
} catch (mem_trap_t& t) { } catch (mem_trap_t& t) {
bad_address("loading payload " + payload, t.get_tval()); bad_address("loading payload " + payload, t.get_tval());
abort(); abort();
@ -152,7 +152,7 @@ std::map<std::string, uint64_t> htif_t::load_payload(const std::string& payload,
void htif_t::load_program() void htif_t::load_program()
{ {
std::map<std::string, uint64_t> symbols = load_payload(targs[0], &entry); std::map<std::string, uint64_t> symbols = load_payload(targs[0], &entry, load_offset);
if (symbols.count("tohost") && symbols.count("fromhost")) { if (symbols.count("tohost") && symbols.count("fromhost")) {
tohost_addr = symbols["tohost"]; tohost_addr = symbols["tohost"];
@ -169,7 +169,7 @@ void htif_t::load_program()
for (auto payload : payloads) { for (auto payload : payloads) {
reg_t dummy_entry; reg_t dummy_entry;
load_payload(payload, &dummy_entry); load_payload(payload, &dummy_entry, 0);
} }
class nop_memif_t : public memif_t { class nop_memif_t : public memif_t {

5
fesvr/htif.h

@ -7,6 +7,7 @@
#include "syscall.h" #include "syscall.h"
#include "device.h" #include "device.h"
#include "byteorder.h" #include "byteorder.h"
#include "../riscv/platform.h"
#include <string.h> #include <string.h>
#include <map> #include <map>
#include <vector> #include <vector>
@ -58,7 +59,8 @@ class htif_t : public chunked_memif_t
virtual size_t chunk_align() = 0; virtual size_t chunk_align() = 0;
virtual size_t chunk_max_size() = 0; virtual size_t chunk_max_size() = 0;
virtual std::map<std::string, uint64_t> load_payload(const std::string& payload, reg_t* entry); virtual std::map<std::string, uint64_t> load_payload(const std::string& payload, reg_t* entry,
reg_t load_addr);
virtual void load_program(); virtual void load_program();
virtual void idle() {} virtual void idle() {}
@ -79,6 +81,7 @@ class htif_t : public chunked_memif_t
void register_devices(); void register_devices();
void usage(const char * program_name); void usage(const char * program_name);
unsigned int expected_xlen = 0; unsigned int expected_xlen = 0;
const reg_t load_offset = DRAM_BASE;
memif_t mem; memif_t mem;
reg_t entry; reg_t entry;
bool writezeros; bool writezeros;

Loading…
Cancel
Save