From dfd191367991cb157b53767dcc05824c826b5abd Mon Sep 17 00:00:00 2001 From: Iman Hosseini Date: Tue, 20 Sep 2022 00:05:00 -0400 Subject: detects the loading of isa-incompatible (i.e. 32 bit code to 64bit HART) code and emits an error message to help avoid unintentionally loading wrong elf. --- fesvr/elfloader.cc | 6 +++++- fesvr/elfloader.h | 2 +- fesvr/htif.cc | 10 ++++++++-- fesvr/htif.h | 4 ++-- fesvr/memif.h | 8 ++++++++ riscv/sim.cc | 1 + 6 files changed, 25 insertions(+), 6 deletions(-) diff --git a/fesvr/elfloader.cc b/fesvr/elfloader.cc index 76cd6da..1bdccd3 100644 --- a/fesvr/elfloader.cc +++ b/fesvr/elfloader.cc @@ -16,7 +16,7 @@ #include #include -std::map load_elf(const char* fn, memif_t* memif, reg_t* entry) +std::map load_elf(const char* fn, memif_t* memif, reg_t* entry, unsigned required_xlen = 0) { int fd = open(fn, O_RDONLY); struct stat s; @@ -32,6 +32,10 @@ std::map load_elf(const char* fn, memif_t* memif, reg_t* assert(size >= sizeof(Elf64_Ehdr)); const Elf64_Ehdr* eh64 = (const Elf64_Ehdr*)buf; assert(IS_ELF32(*eh64) || IS_ELF64(*eh64)); + unsigned xlen = IS_ELF32(*eh64) ? 32 : 64; + if (required_xlen != 0 && required_xlen != xlen) { + throw incompat_xlen(required_xlen, xlen); + } assert(IS_ELFLE(*eh64) || IS_ELFBE(*eh64)); assert(IS_ELF_EXEC(*eh64)); assert(IS_ELF_RISCV(*eh64) || IS_ELF_EM_NONE(*eh64)); diff --git a/fesvr/elfloader.h b/fesvr/elfloader.h index 696ef47..ae4ee78 100644 --- a/fesvr/elfloader.h +++ b/fesvr/elfloader.h @@ -8,6 +8,6 @@ #include class memif_t; -std::map load_elf(const char* fn, memif_t* memif, reg_t* entry); +std::map load_elf(const char* fn, memif_t* memif, reg_t* entry, unsigned required_xlen = 0); #endif diff --git a/fesvr/htif.cc b/fesvr/htif.cc index ead309c..29eb7d8 100644 --- a/fesvr/htif.cc +++ b/fesvr/htif.cc @@ -82,8 +82,14 @@ htif_t::~htif_t() void htif_t::start() { - if (!targs.empty() && targs[0] != "none") + if (!targs.empty() && targs[0] != "none") { + try { load_program(); + } catch (const incompat_xlen & err) { + fprintf(stderr, "Error: cannot execute %d-bit program on RV%d hart\n", err.actual_xlen, err.expected_xlen); + exit(1); + } + } reset(); } @@ -129,7 +135,7 @@ std::map htif_t::load_payload(const std::string& payload, } preload_aware_memif(this); try { - return load_elf(path.c_str(), &preload_aware_memif, entry); + return load_elf(path.c_str(), &preload_aware_memif, entry, expected_xlen); } catch (mem_trap_t& t) { bad_address("loading payload " + payload, t.get_tval()); abort(); diff --git a/fesvr/htif.h b/fesvr/htif.h index ca5b362..cf8b2d5 100644 --- a/fesvr/htif.h +++ b/fesvr/htif.h @@ -26,7 +26,7 @@ class htif_t : public chunked_memif_t int run(); bool done(); int exit_code(); - + void set_expected_xlen(unsigned int m) { expected_xlen = m; } virtual memif_t& memif() { return mem; } template inline T from_target(target_endian n) const @@ -74,7 +74,7 @@ class htif_t : public chunked_memif_t void parse_arguments(int argc, char ** argv); void register_devices(); void usage(const char * program_name); - + unsigned int expected_xlen = 0; memif_t mem; reg_t entry; bool writezeros; diff --git a/fesvr/memif.h b/fesvr/memif.h index 001c425..3f9bd2d 100644 --- a/fesvr/memif.h +++ b/fesvr/memif.h @@ -5,6 +5,7 @@ #include #include +#include #include "byteorder.h" typedef uint64_t reg_t; @@ -79,4 +80,11 @@ protected: chunked_memif_t* cmemif; }; +class incompat_xlen : public std::exception { +public: + const unsigned expected_xlen; + const unsigned actual_xlen; + incompat_xlen(unsigned _expected_xlen, unsigned _actual_xlen) : expected_xlen(_expected_xlen), actual_xlen(_actual_xlen) {} +}; + #endif // __MEMIF_H diff --git a/riscv/sim.cc b/riscv/sim.cc index 0000537..0ef13b8 100644 --- a/riscv/sim.cc +++ b/riscv/sim.cc @@ -202,6 +202,7 @@ int sim_t::run() { host = context_t::current(); target.init(sim_thread_main, this); + htif_t::set_expected_xlen(isa.get_max_xlen()); return htif_t::run(); } -- cgit v1.1