finally handle virtual addresses

This commit is contained in:
2026-03-01 11:57:07 +01:00
parent d7f947eb50
commit d0659f9f8b
2 changed files with 46 additions and 26 deletions

View File

@@ -9,25 +9,13 @@ const char *const REGS[32] = {
"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"};
Section riscv64_get_code_section(uint8_t *exe_bytes, size_t exe_size) { Section riscv64_get_code_section(Elf *elf, GElf_Ehdr ehdr) {
Elf *elf = elf_memory((char *)exe_bytes, exe_size);
if (!elf) {
fprintf(stderr, "elf_begin failed: %s\n", elf_errmsg(-1));
exit(1);
}
size_t str_table_index; size_t str_table_index;
if (elf_getshdrstrndx(elf, &str_table_index) != 0) { if (elf_getshdrstrndx(elf, &str_table_index) != 0) {
fprintf(stderr, "elf_getshdrstrndx failed: %s\n", elf_errmsg(-1)); fprintf(stderr, "elf_getshdrstrndx failed: %s\n", elf_errmsg(-1));
exit(1); exit(1);
} }
GElf_Ehdr ehdr;
if (gelf_getehdr(elf, &ehdr) == 0) {
fprintf(stderr, "gelf_getehdr failed: %s\n", elf_errmsg(-1));
exit(1);
}
Elf_Scn *section = NULL; Elf_Scn *section = NULL;
while ((section = elf_nextscn(elf, section)) != NULL) { while ((section = elf_nextscn(elf, section)) != NULL) {
GElf_Shdr header; GElf_Shdr header;
@@ -36,11 +24,9 @@ Section riscv64_get_code_section(uint8_t *exe_bytes, size_t exe_size) {
const char *name = elf_strptr(elf, str_table_index, header.sh_name); const char *name = elf_strptr(elf, str_table_index, header.sh_name);
if (name && strcmp(name, ".text") == 0) { if (name && strcmp(name, ".text") == 0) {
elf_end(elf); return (Section){.offset = header.sh_addr,
return (Section){.offset = header.sh_offset,
.size = header.sh_size, .size = header.sh_size,
.entrypoint = .entrypoint = ehdr.e_entry};
ehdr.e_entry - header.sh_addr + header.sh_offset};
} }
} }
@@ -49,13 +35,28 @@ Section riscv64_get_code_section(uint8_t *exe_bytes, size_t exe_size) {
} }
RISCV64 riscv64_load(uint8_t *exe_bytes, size_t exe_size) { RISCV64 riscv64_load(uint8_t *exe_bytes, size_t exe_size) {
Section section = riscv64_get_code_section(exe_bytes, exe_size); uint8_t *memory = calloc(20 * 1024 * 1024, 1);
Elf *elf = elf_memory((char *)exe_bytes, exe_size);
GElf_Ehdr ehdr;
gelf_getehdr(elf, &ehdr);
Section text_section = riscv64_get_code_section(elf, ehdr);
for (size_t i = 0; i < ehdr.e_phnum; i++) {
GElf_Phdr phdr;
gelf_getphdr(elf, i, &phdr);
if (phdr.p_type == PT_LOAD) {
memcpy(memory + phdr.p_vaddr, exe_bytes + phdr.p_offset, phdr.p_filesz);
}
}
elf_end(elf);
return (RISCV64){ return (RISCV64){
.memory = exe_bytes, .memory = memory,
.pc = section.offset, .pc = text_section.offset,
.regs = {0}, .regs = {0},
.code_section = section, .code_section = text_section,
}; };
} }
@@ -132,7 +133,7 @@ void riscv64_execute(RISCV64 *r) {
exit(1); exit(1);
} }
} else if (funct3 == 0b011) { // sltiu } else if (funct3 == 0b011) { // sltiu
r->regs[rd] = (r->regs[rs1] < (uint64_t)(int64_t)imm) ? 1 : 0; r->regs[rd] = ((uint64_t)r->regs[rs1] < (uint64_t)(int64_t)imm) ? 1 : 0;
} else if (funct3 == 0b100) { // xori } else if (funct3 == 0b100) { // xori
r->regs[rd] = r->regs[rs1] ^ imm; r->regs[rd] = r->regs[rs1] ^ imm;
} else if (funct3 == 0b101) { } else if (funct3 == 0b101) {
@@ -299,7 +300,7 @@ void riscv64_execute(RISCV64 *r) {
} }
} else if (funct3 == 0b010) { } else if (funct3 == 0b010) {
if (funct7 == 0b0000000) { // slt if (funct7 == 0b0000000) { // slt
r->regs[rd] = ((int64_t)r->regs[rs1] < (int64_t)r->regs[rs2]) ? 1 : 0; r->regs[rd] = (r->regs[rs1] < r->regs[rs2]) ? 1 : 0;
} else { } else {
fprintf(stderr, "R-type 1: funct3=0b010: unrecognized funct7: %b\n", fprintf(stderr, "R-type 1: funct3=0b010: unrecognized funct7: %b\n",
funct7); funct7);
@@ -321,7 +322,7 @@ void riscv64_execute(RISCV64 *r) {
if (r->regs[rs2] == 0) { if (r->regs[rs2] == 0) {
r->regs[rd] = -1; r->regs[rd] = -1;
} else { } else {
r->regs[rd] = (int64_t)r->regs[rs1] / (int64_t)r->regs[rs2]; r->regs[rd] = r->regs[rs1] / r->regs[rs2];
} }
} else { } else {
fprintf(stderr, "R-type 1: funct3=0b100: unrecognized funct7: %b\n", fprintf(stderr, "R-type 1: funct3=0b100: unrecognized funct7: %b\n",
@@ -333,7 +334,7 @@ void riscv64_execute(RISCV64 *r) {
if (r->regs[rs2] == 0) { if (r->regs[rs2] == 0) {
r->regs[rd] = r->regs[rs1]; r->regs[rd] = r->regs[rs1];
} else { } else {
r->regs[rd] = (int64_t)r->regs[rs1] % (int64_t)r->regs[rs2]; r->regs[rd] = r->regs[rs1] % r->regs[rs2];
} }
} else if (funct7 == 0b0000000) { // or } else if (funct7 == 0b0000000) { // or
r->regs[rd] = r->regs[rs1] | r->regs[rs2]; r->regs[rd] = r->regs[rs1] | r->regs[rs2];
@@ -345,6 +346,12 @@ void riscv64_execute(RISCV64 *r) {
} else if (funct3 == 0b111) { } else if (funct3 == 0b111) {
if (funct7 == 0b000) { // and if (funct7 == 0b000) { // and
r->regs[rd] = r->regs[rs1] & r->regs[rs2]; r->regs[rd] = r->regs[rs1] & r->regs[rs2];
} else if (funct7 == 0b001) { // remu
if (r->regs[rs2] == 0) {
r->regs[rd] = r->regs[rs1];
} else {
r->regs[rd] = (uint64_t)r->regs[rs1] % (uint64_t)r->regs[rs2];
}
} else { } else {
fprintf(stderr, "R-type 1: funct3=0b111: unrecognized funct7: %b\n", fprintf(stderr, "R-type 1: funct3=0b111: unrecognized funct7: %b\n",
funct7); funct7);
@@ -369,6 +376,14 @@ void riscv64_execute(RISCV64 *r) {
funct7); funct7);
exit(1); exit(1);
} }
} else if (funct3 == 0b100) { // divw
int32_t a = r->regs[rs1];
int32_t b = r->regs[rs2];
if (b == 0) {
r->regs[rd] = (uint64_t)(int64_t)(-1);
} else {
r->regs[rd] = (int64_t)(a / b);
}
} else if (funct3 == 0b101) { } else if (funct3 == 0b101) {
if (funct7 == 0b0000001) { // divuw if (funct7 == 0b0000001) { // divuw
if (r->regs[rs2] == 0) { if (r->regs[rs2] == 0) {
@@ -472,6 +487,7 @@ int main(int argc, char *argv[]) {
fclose(file); fclose(file);
RISCV64 r = riscv64_load(exe_bytes, exe_size); RISCV64 r = riscv64_load(exe_bytes, exe_size);
free(exe_bytes);
for (r.pc = r.code_section.offset; for (r.pc = r.code_section.offset;
r.pc < r.code_section.offset + r.code_section.size; r.pc += 4) { r.pc < r.code_section.offset + r.code_section.size; r.pc += 4) {

View File

@@ -66,7 +66,7 @@ typedef struct {
extern const char *const REGS[32]; extern const char *const REGS[32];
inline void riscv64_disassemble_one(const RISCV64 *r) { void riscv64_disassemble_one(const RISCV64 *r) { // NOLINT
uint32_t ins; uint32_t ins;
memcpy(&ins, r->memory + r->pc, 4); memcpy(&ins, r->memory + r->pc, 4);
@@ -237,6 +237,8 @@ inline void riscv64_disassemble_one(const RISCV64 *r) {
} else if (funct3 == 0b111) { } else if (funct3 == 0b111) {
if (funct7 == 0b000) { if (funct7 == 0b000) {
printf("and %s, %s, %s\n", REGS[rd], REGS[rs1], REGS[rs2]); printf("and %s, %s, %s\n", REGS[rd], REGS[rs1], REGS[rs2]);
} else if (funct7 == 0b001) {
printf("remu %s, %s, %s\n", REGS[rd], REGS[rs1], REGS[rs2]);
} else { } else {
fprintf(stderr, "R-type 1: funct3=0b111: unrecognized funct7: %b\n", fprintf(stderr, "R-type 1: funct3=0b111: unrecognized funct7: %b\n",
funct7); funct7);
@@ -264,6 +266,8 @@ inline void riscv64_disassemble_one(const RISCV64 *r) {
funct7); funct7);
exit(1); exit(1);
} }
} else if (funct3 == 0b100) {
printf("divw %s, %s, %s\n", REGS[rd], REGS[rs1], REGS[rs2]);
} else if (funct3 == 0b101) { } else if (funct3 == 0b101) {
if (funct7 == 0b0000001) { if (funct7 == 0b0000001) {
printf("divuw %s, %s, %s\n", REGS[rd], REGS[rs1], REGS[rs2]); printf("divuw %s, %s, %s\n", REGS[rd], REGS[rs1], REGS[rs2]);