From a8f56b6e27d368c11546f1def319be1c66370d1d Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Mon, 23 Sep 2024 09:28:27 +0200 Subject: [PATCH] removes code dupication by unifying elf file read --- src/iss/arch/riscv_hart_common.h | 98 ++++++++++++++++++-------------- src/iss/arch/riscv_hart_m_p.h | 63 ++++---------------- src/iss/arch/riscv_hart_msu_vp.h | 76 +++---------------------- src/iss/arch/riscv_hart_mu_p.h | 76 +++---------------------- 4 files changed, 83 insertions(+), 230 deletions(-) diff --git a/src/iss/arch/riscv_hart_common.h b/src/iss/arch/riscv_hart_common.h index f3b1596..471566a 100644 --- a/src/iss/arch/riscv_hart_common.h +++ b/src/iss/arch/riscv_hart_common.h @@ -35,6 +35,7 @@ #ifndef _RISCV_HART_COMMON #define _RISCV_HART_COMMON +#include "iss/vm_types.h" #include #include #include @@ -314,55 +315,66 @@ struct riscv_hart_common { riscv_hart_common(){}; ~riscv_hart_common(){}; std::unordered_map symbol_table; + uint64_t entry_address{0}; + uint64_t tohost = tohost_dflt; + uint64_t fromhost = fromhost_dflt; - std::unordered_map get_sym_table(std::string name) { - if(!symbol_table.empty()) - return symbol_table; - FILE* fp = fopen(name.c_str(), "r"); - if(fp) { - std::array buf; - auto n = fread(buf.data(), 1, 4, fp); - fclose(fp); - if(n != 4) - throw std::runtime_error("input file has insufficient size"); - buf[4] = 0; - if(strcmp(buf.data() + 1, "ELF") == 0) { - // Create elfio reader - ELFIO::elfio reader; - // Load ELF data - if(!reader.load(name)) - throw std::runtime_error("could not process elf file"); - // check elf properties - if(reader.get_type() != ET_EXEC) - throw std::runtime_error("wrong elf type in file"); - if(reader.get_machine() != EM_RISCV) - throw std::runtime_error("wrong elf machine in file"); - const auto sym_sec = reader.sections[".symtab"]; - if(SHT_SYMTAB == sym_sec->get_type() || SHT_DYNSYM == sym_sec->get_type()) { - ELFIO::symbol_section_accessor symbols(reader, sym_sec); - auto sym_no = symbols.get_symbols_num(); - std::string name; - ELFIO::Elf64_Addr value = 0; - ELFIO::Elf_Xword size = 0; - unsigned char bind = 0; - unsigned char type = 0; - ELFIO::Elf_Half section = 0; - unsigned char other = 0; - for(auto i = 0U; i < sym_no; ++i) { - symbols.get_symbol(i, name, value, size, bind, type, section, other); - if(name != "") { - this->symbol_table[name] = value; + bool read_elf_file(std::string name, uint8_t expected_elf_class, std::function cb) { + // Create elfio reader + ELFIO::elfio reader; + // Load ELF data + if(reader.load(name)) { + // check elf properties + if(reader.get_class() != expected_elf_class) + return false; + if(reader.get_type() != ET_EXEC) + return false; + if(reader.get_machine() != EM_RISCV) + return false; + entry_address = reader.get_entry(); + for(const auto pseg : reader.segments) { + const auto fsize = pseg->get_file_size(); // 0x42c/0x0 + const auto seg_data = pseg->get_data(); + const auto type = pseg->get_type(); + if(type == 1 && fsize > 0) { + auto res = cb(pseg->get_physical_address(), fsize, reinterpret_cast(seg_data)); + if(res != iss::Ok) + CPPLOG(ERR) << "problem writing " << fsize << "bytes to 0x" << std::hex << pseg->get_physical_address(); + } + } + const auto sym_sec = reader.sections[".symtab"]; + if(SHT_SYMTAB == sym_sec->get_type() || SHT_DYNSYM == sym_sec->get_type()) { + ELFIO::symbol_section_accessor symbols(reader, sym_sec); + auto sym_no = symbols.get_symbols_num(); + std::string name; + ELFIO::Elf64_Addr value = 0; + ELFIO::Elf_Xword size = 0; + unsigned char bind = 0; + unsigned char type = 0; + ELFIO::Elf_Half section = 0; + unsigned char other = 0; + for(auto i = 0U; i < sym_no; ++i) { + symbols.get_symbol(i, name, value, size, bind, type, section, other); + if(type==0 && name != "") { + this->symbol_table[name] = value; #ifndef NDEBUG - CPPLOG(DEBUG) << "Found Symbol " << name; + CPPLOG(DEBUG) << "Found Symbol " << name; #endif - } } } - return symbol_table; + try { + tohost = symbol_table.at("tohost"); + try { + fromhost = symbol_table.at("fromhost"); + } catch(std::out_of_range& e) { + fromhost = tohost + 0x40; + } + } catch(std::out_of_range& e) { + } } - throw std::runtime_error(fmt::format("memory load file {} is not a valid elf file", name)); - } else - throw std::runtime_error(fmt::format("memory load file not found, check if {} is a valid file", name)); + return true; + } + return false; }; }; diff --git a/src/iss/arch/riscv_hart_m_p.h b/src/iss/arch/riscv_hart_m_p.h index 6ff1a82..cc2dcd2 100644 --- a/src/iss/arch/riscv_hart_m_p.h +++ b/src/iss/arch/riscv_hart_m_p.h @@ -41,6 +41,7 @@ #include "iss/vm_if.h" #include "iss/vm_types.h" #include "riscv_hart_common.h" +#include #include #ifndef FMT_HEADER_ONLY #define FMT_HEADER_ONLY @@ -321,7 +322,7 @@ protected: unsigned get_reg_size(unsigned num) override { return traits::reg_bit_widths[num]; } - std::unordered_map get_symbol_table(std::string name) override { return arch.get_sym_table(name); } + std::unordered_map const& get_symbol_table(std::string name) override { return arch.symbol_table; } riscv_hart_m_p& arch; }; @@ -343,8 +344,6 @@ protected: int64_t instret_offset{0}; uint64_t minstret_csr{0}; reg_t fault_data; - uint64_t tohost = tohost_dflt; - uint64_t fromhost = fromhost_dflt; bool tohost_lower_written = false; riscv_instrumentation_if instr_if; @@ -573,57 +572,15 @@ riscv_hart_m_p::riscv_hart_m_p(feature_config cfg) template std::pair riscv_hart_m_p::load_file(std::string name, int type) { - get_sym_table(name); - try { - tohost = symbol_table.at("tohost"); - fromhost = symbol_table.at("fromhost"); - } catch(std::out_of_range& e) { + if(read_elf_file(name,sizeof(reg_t)==4?ELFCLASS32:ELFCLASS64, + [this](uint64_t addr, uint64_t size, const uint8_t* const data) -> iss::status { + return this->write(iss::address_type::PHYSICAL, iss::access_type::DEBUG_WRITE, traits::MEM, + addr, size, data); + + })) { + return std::make_pair(entry_address, true); } - FILE* fp = fopen(name.c_str(), "r"); - if(fp) { - std::array buf; - auto n = fread(buf.data(), 1, 4, fp); - fclose(fp); - if(n != 4) - throw std::runtime_error("input file has insufficient size"); - buf[4] = 0; - if(strcmp(buf.data() + 1, "ELF") == 0) { - // Create elfio reader - ELFIO::elfio reader; - // Load ELF data - if(!reader.load(name)) - throw std::runtime_error("could not process elf file"); - // check elf properties - if(reader.get_class() != ELFCLASS32) - if(sizeof(reg_t) == 4) - throw std::runtime_error("wrong elf class in file"); - if(reader.get_type() != ET_EXEC) - throw std::runtime_error("wrong elf type in file"); - if(reader.get_machine() != EM_RISCV) - throw std::runtime_error("wrong elf machine in file"); - auto entry = reader.get_entry(); - for(const auto& pseg : reader.segments) { - const auto fsize = pseg->get_file_size(); // 0x42c/0x0 - const auto seg_data = pseg->get_data(); - const auto type = pseg->get_type(); - if(type == 1 && fsize > 0) { - auto res = this->write(iss::address_type::PHYSICAL, iss::access_type::DEBUG_WRITE, traits::MEM, - pseg->get_physical_address(), fsize, reinterpret_cast(seg_data)); - if(res != iss::Ok) - CPPLOG(ERR) << "problem writing " << fsize << "bytes to 0x" << std::hex << pseg->get_physical_address(); - } - } - for(const auto& sec : reader.sections) { - if(sec->get_name() == ".tohost") { - tohost = sec->get_address(); - fromhost = tohost + 0x40; - } - } - return std::make_pair(entry, true); - } - throw std::runtime_error(fmt::format("memory load file {} is not a valid elf file", name)); - } - throw std::runtime_error(fmt::format("memory load file not found, check if {} is a valid file", name)); + return std::make_pair(entry_address, false); } template diff --git a/src/iss/arch/riscv_hart_msu_vp.h b/src/iss/arch/riscv_hart_msu_vp.h index b886e2b..fc79aa6 100644 --- a/src/iss/arch/riscv_hart_msu_vp.h +++ b/src/iss/arch/riscv_hart_msu_vp.h @@ -371,7 +371,7 @@ protected: unsigned get_reg_size(unsigned num) override { return traits::reg_bit_widths[num]; } - std::unordered_map get_symbol_table(std::string name) override { return arch.get_sym_table(name); } + std::unordered_map const& get_symbol_table(std::string name) override { return arch.symbol_table; } riscv_hart_msu_vp& arch; }; @@ -393,8 +393,6 @@ protected: uint64_t minstret_csr{0}; reg_t fault_data; std::array vm; - uint64_t tohost = tohost_dflt; - uint64_t fromhost = fromhost_dflt; bool tohost_lower_written = false; riscv_instrumentation_if instr_if; @@ -557,71 +555,15 @@ riscv_hart_msu_vp::riscv_hart_msu_vp() } template std::pair riscv_hart_msu_vp::load_file(std::string name, int type) { - FILE* fp = fopen(name.c_str(), "r"); - if(fp) { - std::array buf; - auto n = fread(buf.data(), 1, 4, fp); - fclose(fp); - if(n != 4) - throw std::runtime_error("input file has insufficient size"); - buf[4] = 0; - if(strcmp(buf.data() + 1, "ELF") == 0) { - // Create elfio reader - ELFIO::elfio reader; - // Load ELF data - if(!reader.load(name)) - throw std::runtime_error("could not process elf file"); - // check elf properties - if(reader.get_class() != ELFCLASS32) - if(sizeof(reg_t) == 4) - throw std::runtime_error("wrong elf class in file"); - if(reader.get_type() != ET_EXEC) - throw std::runtime_error("wrong elf type in file"); - if(reader.get_machine() != EM_RISCV) - throw std::runtime_error("wrong elf machine in file"); - auto entry = reader.get_entry(); - for(const auto pseg : reader.segments) { - const auto fsize = pseg->get_file_size(); // 0x42c/0x0 - const auto seg_data = pseg->get_data(); - const auto type = pseg->get_type(); - if(type == 1 && fsize > 0) { - auto res = this->write(iss::address_type::PHYSICAL, iss::access_type::DEBUG_WRITE, traits::MEM, - pseg->get_physical_address(), fsize, reinterpret_cast(seg_data)); - if(res != iss::Ok) - CPPLOG(ERR) << "problem writing " << fsize << "bytes to 0x" << std::hex << pseg->get_physical_address(); - } - } - for(const auto sec : reader.sections) { - if(sec->get_name() == ".symtab") { - if(SHT_SYMTAB == sec->get_type() || SHT_DYNSYM == sec->get_type()) { - ELFIO::symbol_section_accessor symbols(reader, sec); - auto sym_no = symbols.get_symbols_num(); - std::string name; - ELFIO::Elf64_Addr value = 0; - ELFIO::Elf_Xword size = 0; - unsigned char bind = 0; - unsigned char type = 0; - ELFIO::Elf_Half section = 0; - unsigned char other = 0; - for(auto i = 0U; i < sym_no; ++i) { - symbols.get_symbol(i, name, value, size, bind, type, section, other); - if(name == "tohost") { - tohost = value; - } else if(name == "fromhost") { - fromhost = value; - } - } - } - } else if(sec->get_name() == ".tohost") { - tohost = sec->get_address(); - fromhost = tohost + 0x40; - } - } - return std::make_pair(entry, true); - } - throw std::runtime_error(fmt::format("memory load file {} is not a valid elf file", name)); + if(read_elf_file(name,sizeof(reg_t)==4?ELFCLASS32:ELFCLASS64, + [this](uint64_t addr, uint64_t size, const uint8_t* const data) -> iss::status { + return this->write(iss::address_type::PHYSICAL, iss::access_type::DEBUG_WRITE, traits::MEM, + addr, size, data); + + })) { + return std::make_pair(entry_address, true); } - throw std::runtime_error(fmt::format("memory load file not found, check if {} is a valid file", name)); + return std::make_pair(entry_address, false); } template diff --git a/src/iss/arch/riscv_hart_mu_p.h b/src/iss/arch/riscv_hart_mu_p.h index 974e1b4..e0774e8 100644 --- a/src/iss/arch/riscv_hart_mu_p.h +++ b/src/iss/arch/riscv_hart_mu_p.h @@ -348,7 +348,7 @@ protected: unsigned get_reg_size(unsigned num) override { return traits::reg_bit_widths[num]; } - std::unordered_map get_symbol_table(std::string name) override { return arch.get_sym_table(name); } + std::unordered_map const& get_symbol_table(std::string name) override { return arch.symbol_table; } riscv_hart_mu_p& arch; }; @@ -370,8 +370,6 @@ protected: int64_t instret_offset{0}; uint64_t minstret_csr{0}; reg_t fault_data; - uint64_t tohost = tohost_dflt; - uint64_t fromhost = fromhost_dflt; bool tohost_lower_written = false; riscv_instrumentation_if instr_if; @@ -651,71 +649,15 @@ riscv_hart_mu_p::riscv_hart_mu_p(feature_config cfg) template std::pair riscv_hart_mu_p::load_file(std::string name, int type) { - FILE* fp = fopen(name.c_str(), "r"); - if(fp) { - std::array buf; - auto n = fread(buf.data(), 1, 4, fp); - fclose(fp); - if(n != 4) - throw std::runtime_error("input file has insufficient size"); - buf[4] = 0; - if(strcmp(buf.data() + 1, "ELF") == 0) { - // Create elfio reader - ELFIO::elfio reader; - // Load ELF data - if(!reader.load(name)) - throw std::runtime_error("could not process elf file"); - // check elf properties - if(reader.get_class() != ELFCLASS32) - if(sizeof(reg_t) == 4) - throw std::runtime_error("wrong elf class in file"); - if(reader.get_type() != ET_EXEC) - throw std::runtime_error("wrong elf type in file"); - if(reader.get_machine() != EM_RISCV) - throw std::runtime_error("wrong elf machine in file"); - auto entry = reader.get_entry(); - for(const auto& pseg : reader.segments) { - const auto fsize = pseg->get_file_size(); // 0x42c/0x0 - const auto seg_data = pseg->get_data(); - const auto type = pseg->get_type(); - if(type == 1 && fsize > 0) { - auto res = this->write(iss::address_type::PHYSICAL, iss::access_type::DEBUG_WRITE, traits::MEM, - pseg->get_physical_address(), fsize, reinterpret_cast(seg_data)); - if(res != iss::Ok) - CPPLOG(ERR) << "problem writing " << fsize << "bytes to 0x" << std::hex << pseg->get_physical_address(); - } - } - for(const auto& sec : reader.sections) { - if(sec->get_name() == ".symtab") { - if(SHT_SYMTAB == sec->get_type() || SHT_DYNSYM == sec->get_type()) { - ELFIO::symbol_section_accessor symbols(reader, sec); - auto sym_no = symbols.get_symbols_num(); - std::string name; - ELFIO::Elf64_Addr value = 0; - ELFIO::Elf_Xword size = 0; - unsigned char bind = 0; - unsigned char type = 0; - ELFIO::Elf_Half section = 0; - unsigned char other = 0; - for(auto i = 0U; i < sym_no; ++i) { - symbols.get_symbol(i, name, value, size, bind, type, section, other); - if(name == "tohost") { - tohost = value; - } else if(name == "fromhost") { - fromhost = value; - } - } - } - } else if(sec->get_name() == ".tohost") { - tohost = sec->get_address(); - fromhost = tohost + 0x40; - } - } - return std::make_pair(entry, true); - } - throw std::runtime_error(fmt::format("memory load file {} is not a valid elf file", name)); + if(read_elf_file(name,sizeof(reg_t)==4?ELFCLASS32:ELFCLASS64, + [this](uint64_t addr, uint64_t size, const uint8_t* const data) -> iss::status { + return this->write(iss::address_type::PHYSICAL, iss::access_type::DEBUG_WRITE, traits::MEM, + addr, size, data); + + })) { + return std::make_pair(entry_address, true); } - throw std::runtime_error(fmt::format("memory load file not found, check if {} is a valid file", name)); + return std::make_pair(entry_address, false); } template