Implement loading of test signatures
This commit is contained in:
parent
89d9ca3814
commit
40179ed237
6 changed files with 167 additions and 29 deletions
97
src/elf.cpp
97
src/elf.cpp
|
@ -57,6 +57,15 @@ struct Elf32Section {
|
|||
uint32_t sh_entsize; // Entry size if section holds table
|
||||
};
|
||||
|
||||
struct Elf32Sym {
|
||||
uint32_t st_name; // Symbol name (index into string table)
|
||||
uint32_t st_value; // Symbol value (address or offset)
|
||||
uint32_t st_size; // Size of the symbol
|
||||
uint8_t st_info; // Symbol type and binding attributes
|
||||
uint8_t st_other; // Symbol visibility
|
||||
uint16_t st_shndx; // Section header index related to this symbol
|
||||
};
|
||||
|
||||
bool should_load_section(const Elf32Section& section_header) {
|
||||
// Check if the section has the SHF_ALLOC flag, which indicates
|
||||
// the section should be loaded into memory
|
||||
|
@ -143,7 +152,7 @@ std::vector<uint8_t> load_elf(const std::string& filename, size_t memory_size) {
|
|||
throw std::runtime_error("No loadable sections found");
|
||||
}
|
||||
|
||||
std::vector<uint8_t> loadedData(memoryEnd-memoryStart, 0);
|
||||
std::vector<uint8_t> loadedData(memoryEnd - memoryStart, 0);
|
||||
|
||||
// Load .text and .sdata sections
|
||||
for (const Elf32Section& shdr : sectionHeaders) {
|
||||
|
@ -153,7 +162,8 @@ std::vector<uint8_t> load_elf(const std::string& filename, size_t memory_size) {
|
|||
}
|
||||
|
||||
file.seekg(shdr.sh_offset);
|
||||
file.read(reinterpret_cast<char*>(&loadedData[shdr.sh_addr-memoryStart]),
|
||||
file.read(
|
||||
reinterpret_cast<char*>(&loadedData[shdr.sh_addr - memoryStart]),
|
||||
shdr.sh_size);
|
||||
if (!file) {
|
||||
throw std::runtime_error("Failed to read section data");
|
||||
|
@ -163,3 +173,86 @@ std::vector<uint8_t> load_elf(const std::string& filename, size_t memory_size) {
|
|||
|
||||
return loadedData;
|
||||
}
|
||||
|
||||
std::tuple<uint32_t, uint32_t> elf_get_signature(const std::string& filename) {
|
||||
std::ifstream file(filename, std::ios::binary);
|
||||
if (!file.is_open()) {
|
||||
throw std::runtime_error("Failed to open ELF file");
|
||||
}
|
||||
|
||||
// Read the ELF header
|
||||
Elf32Header ehdr;
|
||||
file.read(reinterpret_cast<char*>(&ehdr), sizeof(ehdr));
|
||||
if (!file) {
|
||||
throw std::runtime_error("Failed to read ELF header");
|
||||
}
|
||||
|
||||
// Validate ELF magic and basic properties
|
||||
if (std::memcmp(ehdr.e_ident, ELF_MAGIC, sizeof(ELF_MAGIC)) != 0) {
|
||||
throw std::runtime_error("Invalid ELF magic number");
|
||||
}
|
||||
if (ehdr.e_ident[4] != ELF_CLASS_32 || ehdr.e_ident[5] != ELF_LITTLE_ENDIAN) {
|
||||
throw std::runtime_error("Unsupported ELF class or endianness");
|
||||
}
|
||||
if (ehdr.e_type != ELF_TYPE_EXECUTABLE ||
|
||||
ehdr.e_machine != ELF_MACHINE_RISCV) {
|
||||
throw std::runtime_error("Unsupported ELF type or machine");
|
||||
}
|
||||
|
||||
// Read section headers
|
||||
file.seekg(ehdr.e_shoff);
|
||||
std::vector<Elf32Section> sectionHeaders(ehdr.e_shnum);
|
||||
for (size_t i = 0; i < ehdr.e_shnum; ++i) {
|
||||
file.read(reinterpret_cast<char*>(§ionHeaders[i]),
|
||||
sizeof(Elf32Section));
|
||||
if (!file) {
|
||||
throw std::runtime_error("Failed to read section headers");
|
||||
}
|
||||
}
|
||||
|
||||
// Load symbols
|
||||
std::vector<Elf32Sym> sectionSymTable;
|
||||
std::vector<char> sectionStrTable;
|
||||
|
||||
for (const Elf32Section& shdr : sectionHeaders) {
|
||||
if (shdr.sh_type == SHT_SYMTAB) {
|
||||
size_t symbol_count = shdr.sh_size / shdr.sh_entsize;
|
||||
sectionSymTable = std::vector<Elf32Sym>(symbol_count);
|
||||
|
||||
file.seekg(shdr.sh_offset);
|
||||
file.read(reinterpret_cast<char*>(sectionSymTable.data()), shdr.sh_size);
|
||||
if (!file) {
|
||||
throw std::runtime_error("Failed to read section symbol table");
|
||||
}
|
||||
|
||||
const Elf32Section& strtab_shdr = sectionHeaders[shdr.sh_link];
|
||||
|
||||
sectionStrTable = std::vector<char>(strtab_shdr.sh_size);
|
||||
file.seekg(strtab_shdr.sh_offset);
|
||||
file.read(sectionStrTable.data(), strtab_shdr.sh_size);
|
||||
if (!file) {
|
||||
throw std::runtime_error("Failed to read section symbol string table");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t begin_signature = 0;
|
||||
uint32_t end_signature = 0;
|
||||
|
||||
for (const Elf32Sym sym : sectionSymTable) {
|
||||
const char* name = §ionStrTable[sym.st_name];
|
||||
|
||||
if (std::strcmp(name, "begin_signature") == 0) {
|
||||
begin_signature = sym.st_value;
|
||||
}
|
||||
if (std::strcmp(name, "end_signature") == 0) {
|
||||
end_signature = sym.st_value;
|
||||
}
|
||||
}
|
||||
|
||||
if (end_signature == 0 || begin_signature >= end_signature) {
|
||||
return std::make_tuple<uint32_t, uint32_t>(0, 0);
|
||||
}
|
||||
|
||||
return std::make_tuple(begin_signature, end_signature);
|
||||
}
|
||||
|
|
|
@ -5,3 +5,5 @@
|
|||
#include <vector>
|
||||
|
||||
std::vector<uint8_t> load_elf(const std::string& filename, size_t memory_size);
|
||||
|
||||
std::tuple<uint32_t, uint32_t> elf_get_signature(const std::string& filename);
|
||||
|
|
40
src/rve.cpp
40
src/rve.cpp
|
@ -14,27 +14,37 @@ int main(int argc, char *argv[]) {
|
|||
|
||||
bool debug = false;
|
||||
std::string program_filename = "";
|
||||
std::string signature_filename = "";
|
||||
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
if (std::string(argv[i]) == "--debug")
|
||||
if (std::string(argv[i]) == "--debug") {
|
||||
debug = true;
|
||||
else
|
||||
} else if (std::string(argv[i]) == "--signature") {
|
||||
if (i + 1 < argc) {
|
||||
signature_filename = argv[i + 1];
|
||||
++i;
|
||||
}
|
||||
} else {
|
||||
program_filename = std::filesystem::absolute(argv[i]);
|
||||
}
|
||||
}
|
||||
if (program_filename == "") {
|
||||
std::cerr << "Expected filename of program to execute" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> memory;
|
||||
std::tuple<uint32_t, uint32_t> signature;
|
||||
try {
|
||||
memory = load_elf(program_filename, MEMORY_SIZE);
|
||||
|
||||
signature = elf_get_signature(program_filename);
|
||||
} catch (const std::exception &e) {
|
||||
std::cerr << e.what() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
memory.resize(MEMORY_SIZE, 0);
|
||||
memory.resize(std::max(memory.size(), MEMORY_SIZE), 0);
|
||||
|
||||
VM vm(memory, program_filename);
|
||||
|
||||
|
@ -46,6 +56,30 @@ int main(int argc, char *argv[]) {
|
|||
std::cerr << "Emulator error: " << e.what() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (signature_filename.size() > 0) {
|
||||
uint32_t signature_begin = std::get<0>(signature) + 4;
|
||||
uint32_t signature_end = std::get<1>(signature);
|
||||
|
||||
std::vector<uint8_t> mem =
|
||||
vm.read_memory(signature_begin, signature_end - signature_begin);
|
||||
|
||||
std::ofstream file(signature_filename);
|
||||
if (!file) {
|
||||
throw std::runtime_error("Failed to open signature file for writing");
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < mem.size() / 4; i++) {
|
||||
uint32_t val = *reinterpret_cast<uint32_t *>(&mem[i * 4]);
|
||||
file << std::hex << std::setfill('0') << std::setw(8) << val << std::dec
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
file.close();
|
||||
if (!file) {
|
||||
throw std::runtime_error("Error occurred while writing to file");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// to debug, do: "set debug remote 1" in gdb
|
||||
// and then "target remote :1234"
|
||||
|
|
|
@ -47,6 +47,7 @@ void VM::setreg(int regnum, uint32_t value) {
|
|||
|
||||
std::vector<uint8_t> VM::read_memory(size_t start, size_t size) {
|
||||
if (start >= PROGRAM_ADDR) {
|
||||
start -= PROGRAM_ADDR;
|
||||
if (start + size > memory_.size()) {
|
||||
return std::vector<uint8_t>(size, 0);
|
||||
}
|
||||
|
@ -172,6 +173,13 @@ void VM::step() {
|
|||
int32_t imm;
|
||||
|
||||
switch (opcode) {
|
||||
case 0x0F: {
|
||||
if (instr == 0xff0000f) { // fence iorw, iorw
|
||||
} else {
|
||||
throw std::runtime_error("Unknown fence instruction");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0x33: { // R-type
|
||||
if (funct7 == 0x00) {
|
||||
if (funct3 == 0x0) { // ADD
|
||||
|
|
1
test/rve/env/model_test.h
vendored
1
test/rve/env/model_test.h
vendored
|
@ -15,6 +15,7 @@
|
|||
li x1, 1; \
|
||||
write_tohost: \
|
||||
sw x1, tohost, t5; \
|
||||
ebreak
|
||||
j write_tohost;
|
||||
|
||||
#define RVMODEL_BOOT
|
||||
|
|
|
@ -145,7 +145,7 @@ class rve(pluginTemplate):
|
|||
# echo statement.
|
||||
if self.target_run:
|
||||
# set up the simulation command. Template is for spike. Please change.
|
||||
simcmd = self.dut_exe + ' {0}'.format(elf)
|
||||
simcmd = self.dut_exe + ' --signature {0} {1}'.format(sig_file, elf)
|
||||
else:
|
||||
simcmd = 'echo "NO RUN"'
|
||||
|
||||
|
|
Loading…
Reference in a new issue