parse elf

This commit is contained in:
2026-03-08 17:40:01 +01:00
parent f71784909b
commit 3f62e1ec2b

View File

@@ -1,29 +1,27 @@
// https://docs.riscv.org/reference/isa/unpriv/rv-32-64g.html // https://docs.riscv.org/reference/isa/unpriv/rv-32-64g.html
// https://riscv.org/wp-content/uploads/2024/12/riscv-calling.pdf // https://riscv.org/wp-content/uploads/2024/12/riscv-calling.pdf
#if !defined(__cplusplus) || __cplusplus < 201703L
#error "This file requires at least C++17"
#endif
#include <array> #include <array>
#include <cstring>
#include <fstream> #include <fstream>
#include <gelf.h> #include <gelf.h>
#include <iostream> #include <iostream>
#include <libelf.h> #include <libelf.h>
#include <vector> #include <vector>
typedef int8_t i8; using i8 = int8_t;
typedef int16_t i16; using i16 = int16_t;
typedef int32_t i32; using i32 = int32_t;
typedef int64_t i64; using i64 = int64_t;
typedef uint8_t u8; using u8 = uint8_t;
typedef uint16_t u16; using u16 = uint16_t;
typedef uint32_t u32; using u32 = uint32_t;
typedef uint64_t u64; using u64 = uint64_t;
static_assert(sizeof(size_t) == sizeof(u64), "size_t must be 64-bit");
static constexpr u64 MEMORY_SIZE = 20 * 1024 * 1024; // should be enough static constexpr u64 MEMORY_SIZE = 20 * 1024 * 1024; // should be enough
static std::array<const char *, 32> REGS = { static constexpr std::array<const char *, 32> REGS = {
"zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2", "fp", "s1", "a0", "zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2", "fp", "s1", "a0",
"a1", "a2", "a3", "a4", "a5", "a6", "a7", "s2", "s3", "s4", "s5", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "s2", "s3", "s4", "s5",
"s6", "s7", "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6"}; "s6", "s7", "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6"};
@@ -36,13 +34,56 @@ struct Section {
class RISCV64 { class RISCV64 {
public: public:
RISCV64(const std::vector<char> &exe_bytes) {} RISCV64(const std::vector<char> &exe_bytes) {
Elf *elf =
elf_memory(const_cast<char *>(exe_bytes.data()), exe_bytes.size());
GElf_Ehdr ehdr;
gelf_getehdr(elf, &ehdr);
m_code_section = get_code_section(elf, ehdr);
m_pc = m_code_section.offset;
for (u64 i = 0; i < ehdr.e_phnum; i++) {
GElf_Phdr phdr;
gelf_getphdr(elf, i, &phdr);
if (phdr.p_type == PT_LOAD) {
memcpy(m_memory.data() + phdr.p_vaddr, exe_bytes.data() + phdr.p_offset,
phdr.p_filesz);
}
}
elf_end(elf);
}
private: private:
std::array<u8, MEMORY_SIZE> m_memory; std::vector<u8> m_memory = std::vector<u8>(MEMORY_SIZE, 0);
u64 m_pc; u64 m_pc;
i64 m_regs[32]; std::array<i64, 32> m_regs = {0};
Section m_code_section; Section m_code_section;
static Section get_code_section(Elf *elf, GElf_Ehdr ehdr) {
u64 str_table_index;
if (elf_getshdrstrndx(elf, &str_table_index) != 0) {
std::cerr << "elf_getshdrstrndx failed: " << elf_errmsg(-1) << "\n";
exit(1);
}
Elf_Scn *section = nullptr;
while ((section = elf_nextscn(elf, section)) != nullptr) {
GElf_Shdr header;
if (gelf_getshdr(section, &header) != &header)
continue;
const char *name = elf_strptr(elf, str_table_index, header.sh_name);
if (name && std::string_view(name) == ".text") {
return Section{.offset = header.sh_addr,
.size = header.sh_size,
.entrypoint = ehdr.e_entry};
}
}
std::cerr << "Failed to locate .text\n";
exit(1);
}
}; };
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
@@ -78,14 +119,8 @@ int main(int argc, char *argv[]) {
exe_bytes = {}; exe_bytes = {};
r.disassemble_all(); // r.disassemble_all();
std::cout << "END DISASSEMBLY\n";
// for (r.pc = r.code_section.offset;
// r.pc < r.code_section.offset + r.code_section.size; r.pc += 4) {
// riscv64_disassemble_one(&r);
// }
// printf("END DISASSEMBLY\n"); // printf("END DISASSEMBLY\n");
// riscv64_execute(&r); // r.execute();
} }