feat: basic flag challenge working + fix elf loading
This commit is contained in:
2
Makefile
2
Makefile
@@ -49,7 +49,7 @@ build/%.riscv.o: src/emulated/%.c $(GENERATED) | build
|
|||||||
$(RISCV_CC) $(RISCV_ARCH_FLAGS) -I $(dir $(GENERATED)) -I src/emulated -c $< -o $@
|
$(RISCV_CC) $(RISCV_ARCH_FLAGS) -I $(dir $(GENERATED)) -I src/emulated -c $< -o $@
|
||||||
|
|
||||||
$(EMU_OBJ): $(EMU_OBJ_FILES) | build
|
$(EMU_OBJ): $(EMU_OBJ_FILES) | build
|
||||||
$(RISCV_CC) $(RISCV_ARCH_FLAGS) -nostdlib -Wl,-e,entry -Wl,-Ttext=0 $(EMU_OBJ_FILES) -o $@
|
$(RISCV_CC) $(RISCV_ARCH_FLAGS) -nostdlib -Wl,-e,entry -Wl,-Ttext=0 -Wl,--emit-relocs $(EMU_OBJ_FILES) -o $@
|
||||||
|
|
||||||
|
|
||||||
.FORCE:
|
.FORCE:
|
||||||
|
|||||||
@@ -1,5 +1,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define EMU_MEM_SIZE 4096u
|
#define EMU_MEM_SIZE 16384u
|
||||||
#define EMU_PROGRAM_PATH "build/emulated.riscv.elf"
|
#define EMU_PROGRAM_PATH "build/emulated.riscv.elf"
|
||||||
#define EMU_ENTRY_SYMBOL "entry"
|
#define EMU_ENTRY_SYMBOL "entry"
|
||||||
|
|
||||||
|
#define STACK_SIZE 1024
|
||||||
|
#define RISCV_MEM_OFFSET 0x80000000
|
||||||
|
#define SIZE_USERDATA 512
|
||||||
|
#define SECTION_USERDATA (EMU_MEM_SIZE - STACK_SIZE - SIZE_USERDATA)
|
||||||
|
|||||||
230
src/elf.c
230
src/elf.c
@@ -67,6 +67,13 @@ uint32_t read_u32_le(const uint8_t* data) {
|
|||||||
| ((uint32_t)data[3] << 24);
|
| ((uint32_t)data[3] << 24);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void write_u32_le(uint8_t* data, uint32_t value) {
|
||||||
|
data[0] = (uint8_t)(value & 0xffu);
|
||||||
|
data[1] = (uint8_t)((value >> 8) & 0xffu);
|
||||||
|
data[2] = (uint8_t)((value >> 16) & 0xffu);
|
||||||
|
data[3] = (uint8_t)((value >> 24) & 0xffu);
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t align_up(uint32_t value, uint32_t align) {
|
uint32_t align_up(uint32_t value, uint32_t align) {
|
||||||
if (align == 0u) {
|
if (align == 0u) {
|
||||||
return value;
|
return value;
|
||||||
@@ -74,6 +81,192 @@ uint32_t align_up(uint32_t value, uint32_t align) {
|
|||||||
return (value + align - 1u) & ~(align - 1u);
|
return (value + align - 1u) & ~(align - 1u);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int apply_relocations(const uint8_t* file_buf, size_t bytes, uint8_t* memory,
|
||||||
|
uint32_t mem_size, uint32_t e_shoff, uint16_t e_shentsize, uint16_t e_shnum,
|
||||||
|
const uint32_t* section_runtime, const uint32_t* section_addr,
|
||||||
|
const uint32_t* section_size, const uint8_t* section_loaded) {
|
||||||
|
|
||||||
|
for (uint16_t i = 0; i < e_shnum; ++i) {
|
||||||
|
const uint8_t* sh = file_buf + e_shoff + (uint32_t)i * e_shentsize;
|
||||||
|
uint32_t sh_type = read_u32_le(sh + 4);
|
||||||
|
uint32_t sh_offset = read_u32_le(sh + 16);
|
||||||
|
uint32_t sh_size = read_u32_le(sh + 20);
|
||||||
|
uint32_t sh_link = read_u32_le(sh + 24);
|
||||||
|
uint32_t sh_info = read_u32_le(sh + 28);
|
||||||
|
uint32_t sh_entsize = read_u32_le(sh + 36);
|
||||||
|
|
||||||
|
if (sh_type != SHT_RELA && sh_type != SHT_REL) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sh_link >= e_shnum || sh_info >= e_shnum) {
|
||||||
|
return LOAD_ERR_RELOC_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sh_offset >= bytes || sh_size > (uint32_t)bytes - sh_offset) {
|
||||||
|
return LOAD_ERR_RELOC_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!section_loaded[sh_info]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint8_t* symtab_sh = file_buf + e_shoff + sh_link * (uint32_t)e_shentsize;
|
||||||
|
uint32_t symtab_offset = read_u32_le(symtab_sh + 16);
|
||||||
|
uint32_t symtab_size = read_u32_le(symtab_sh + 20);
|
||||||
|
uint32_t symtab_entsize = read_u32_le(symtab_sh + 36);
|
||||||
|
|
||||||
|
if (symtab_offset >= bytes || symtab_size > (uint32_t)bytes - symtab_offset) {
|
||||||
|
return LOAD_ERR_STRTAB_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (symtab_entsize == 0u) {
|
||||||
|
symtab_entsize = 16u;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (symtab_entsize < 16u) {
|
||||||
|
return LOAD_ERR_STRTAB_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint8_t* symtab = file_buf + symtab_offset;
|
||||||
|
uint32_t symtab_count = symtab_size / symtab_entsize;
|
||||||
|
|
||||||
|
uint32_t entry_size = sh_entsize;
|
||||||
|
if (entry_size == 0u) {
|
||||||
|
entry_size = (sh_type == SHT_RELA) ? 12u : 8u;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry_size < ((sh_type == SHT_RELA) ? 12u : 8u)) {
|
||||||
|
return LOAD_ERR_RELOC_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t count = sh_size / entry_size;
|
||||||
|
const uint8_t* reltab = file_buf + sh_offset;
|
||||||
|
|
||||||
|
for (uint32_t r = 0u; r < count; ++r) {
|
||||||
|
const uint8_t* rel = reltab + r * entry_size;
|
||||||
|
uint32_t r_offset = read_u32_le(rel + 0);
|
||||||
|
uint32_t r_info = read_u32_le(rel + 4);
|
||||||
|
int32_t r_addend = 0;
|
||||||
|
|
||||||
|
if (sh_type == SHT_RELA) {
|
||||||
|
r_addend = (int32_t)read_u32_le(rel + 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t sym_index = r_info >> 8;
|
||||||
|
uint32_t r_type = r_info & 0xffu;
|
||||||
|
|
||||||
|
if (sym_index >= symtab_count) {
|
||||||
|
return LOAD_ERR_RELOC_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint8_t* sym = symtab + sym_index * symtab_entsize;
|
||||||
|
uint32_t st_value = read_u32_le(sym + 4);
|
||||||
|
uint16_t st_shndx = read_u16_le(sym + 14);
|
||||||
|
|
||||||
|
uint32_t sym_runtime = 0u;
|
||||||
|
if (st_shndx == 0u) {
|
||||||
|
sym_runtime = st_value;
|
||||||
|
} else {
|
||||||
|
if (st_shndx >= e_shnum || !section_loaded[st_shndx]) {
|
||||||
|
return LOAD_ERR_SYMBOL_INVALID_SECTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t base_runtime = section_runtime[st_shndx];
|
||||||
|
uint32_t base_elf = section_addr[st_shndx];
|
||||||
|
if (st_value < base_elf) {
|
||||||
|
return LOAD_ERR_SYMBOL_INVALID_SECTION;
|
||||||
|
}
|
||||||
|
sym_runtime = base_runtime + (st_value - base_elf);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t reloc_addr = 0u;
|
||||||
|
if (section_addr[sh_info] != 0u) {
|
||||||
|
reloc_addr = r_offset;
|
||||||
|
} else {
|
||||||
|
if (r_offset >= section_size[sh_info]) {
|
||||||
|
return LOAD_ERR_RELOC_INVALID;
|
||||||
|
}
|
||||||
|
reloc_addr = section_runtime[sh_info] + r_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reloc_addr >= mem_size || mem_size - reloc_addr < 4u) {
|
||||||
|
return LOAD_ERR_RELOC_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t inst = read_u32_le(memory + reloc_addr);
|
||||||
|
uint32_t sym_addr = sym_runtime + RISCV_MEM_OFFSET;
|
||||||
|
int32_t value = (int32_t)sym_addr + r_addend;
|
||||||
|
|
||||||
|
switch (r_type) {
|
||||||
|
case R_RISCV_NONE:
|
||||||
|
case R_RISCV_RELAX:
|
||||||
|
break;
|
||||||
|
case R_RISCV_HI20: {
|
||||||
|
uint32_t hi20 = (uint32_t)((value + 0x800) >> 12);
|
||||||
|
inst = (inst & 0x00000fffu) | (hi20 << 12);
|
||||||
|
write_u32_le(memory + reloc_addr, inst);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case R_RISCV_LO12_I: {
|
||||||
|
uint32_t imm12 = (uint32_t)(value & 0xfffu);
|
||||||
|
inst = (inst & 0x000fffffu) | (imm12 << 20);
|
||||||
|
write_u32_le(memory + reloc_addr, inst);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case R_RISCV_LO12_S: {
|
||||||
|
uint32_t imm12 = (uint32_t)(value & 0xfffu);
|
||||||
|
inst &= 0x01fff07fu;
|
||||||
|
inst |= (imm12 & 0x1fu) << 7;
|
||||||
|
inst |= ((imm12 >> 5) & 0x7fu) << 25;
|
||||||
|
write_u32_le(memory + reloc_addr, inst);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case R_RISCV_BRANCH: {
|
||||||
|
uint32_t reloc_addr_cpu = reloc_addr + RISCV_MEM_OFFSET;
|
||||||
|
int32_t rel = (int32_t)(value - (int32_t)reloc_addr_cpu);
|
||||||
|
uint32_t uimm = (uint32_t)rel;
|
||||||
|
uint32_t imm12 = (uimm >> 12) & 0x1u;
|
||||||
|
uint32_t imm10_5 = (uimm >> 5) & 0x3fu;
|
||||||
|
uint32_t imm4_1 = (uimm >> 1) & 0xfu;
|
||||||
|
uint32_t imm11 = (uimm >> 11) & 0x1u;
|
||||||
|
inst &= 0x01fff07fu;
|
||||||
|
inst |= (imm11 << 7);
|
||||||
|
inst |= (imm4_1 << 8);
|
||||||
|
inst |= (imm10_5 << 25);
|
||||||
|
inst |= (imm12 << 31);
|
||||||
|
write_u32_le(memory + reloc_addr, inst);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case R_RISCV_JAL: {
|
||||||
|
uint32_t reloc_addr_cpu = reloc_addr + RISCV_MEM_OFFSET;
|
||||||
|
int32_t rel = (int32_t)(value - (int32_t)reloc_addr_cpu);
|
||||||
|
uint32_t uimm = (uint32_t)rel;
|
||||||
|
uint32_t imm20 = (uimm >> 20) & 0x1u;
|
||||||
|
uint32_t imm10_1 = (uimm >> 1) & 0x3ffu;
|
||||||
|
uint32_t imm11 = (uimm >> 11) & 0x1u;
|
||||||
|
uint32_t imm19_12 = (uimm >> 12) & 0xffu;
|
||||||
|
inst = (inst & 0x00000fffu)
|
||||||
|
| (imm20 << 31)
|
||||||
|
| (imm19_12 << 12)
|
||||||
|
| (imm11 << 20)
|
||||||
|
| (imm10_1 << 21);
|
||||||
|
write_u32_le(memory + reloc_addr, inst);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case R_RISCV_32: {
|
||||||
|
write_u32_le(memory + reloc_addr, (uint32_t)value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return LOAD_ERR_RELOC_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return LOAD_OK;
|
||||||
|
}
|
||||||
|
|
||||||
int load_elf_object_sections(const char* path, uint8_t* memory, uint32_t mem_size) {
|
int load_elf_object_sections(const char* path, uint8_t* memory, uint32_t mem_size) {
|
||||||
uint8_t* file_buf = NULL;
|
uint8_t* file_buf = NULL;
|
||||||
size_t bytes = 0u;
|
size_t bytes = 0u;
|
||||||
@@ -117,6 +310,19 @@ int load_elf_object_sections(const char* path, uint8_t* memory, uint32_t mem_siz
|
|||||||
return LOAD_ERR_SHT_OUT_OF_BOUNDS;
|
return LOAD_ERR_SHT_OUT_OF_BOUNDS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t* section_runtime = (uint32_t*)calloc(e_shnum, sizeof(uint32_t));
|
||||||
|
uint32_t* section_addr = (uint32_t*)calloc(e_shnum, sizeof(uint32_t));
|
||||||
|
uint32_t* section_size = (uint32_t*)calloc(e_shnum, sizeof(uint32_t));
|
||||||
|
uint8_t* section_loaded = (uint8_t*)calloc(e_shnum, sizeof(uint8_t));
|
||||||
|
if (!section_runtime || !section_addr || !section_size || !section_loaded) {
|
||||||
|
free(section_runtime);
|
||||||
|
free(section_addr);
|
||||||
|
free(section_size);
|
||||||
|
free(section_loaded);
|
||||||
|
free(file_buf);
|
||||||
|
return LOAD_ERR_OOM;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t cursor = 0u;
|
uint32_t cursor = 0u;
|
||||||
|
|
||||||
for (uint16_t i = 0; i < e_shnum; ++i) {
|
for (uint16_t i = 0; i < e_shnum; ++i) {
|
||||||
@@ -129,6 +335,9 @@ int load_elf_object_sections(const char* path, uint8_t* memory, uint32_t mem_siz
|
|||||||
uint32_t sh_size = read_u32_le(sh + 20);
|
uint32_t sh_size = read_u32_le(sh + 20);
|
||||||
uint32_t sh_addralign = read_u32_le(sh + 32);
|
uint32_t sh_addralign = read_u32_le(sh + 32);
|
||||||
|
|
||||||
|
section_addr[i] = sh_addr;
|
||||||
|
section_size[i] = sh_size;
|
||||||
|
|
||||||
if ((sh_flags & SHF_ALLOC) == 0u || sh_size == 0u) {
|
if ((sh_flags & SHF_ALLOC) == 0u || sh_size == 0u) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -137,6 +346,10 @@ int load_elf_object_sections(const char* path, uint8_t* memory, uint32_t mem_siz
|
|||||||
|
|
||||||
if (dst >= mem_size || sh_size > mem_size - dst) {
|
if (dst >= mem_size || sh_size > mem_size - dst) {
|
||||||
fprintf(stderr, "Section %u does not fit into emulator memory\n", (unsigned)i);
|
fprintf(stderr, "Section %u does not fit into emulator memory\n", (unsigned)i);
|
||||||
|
free(section_runtime);
|
||||||
|
free(section_addr);
|
||||||
|
free(section_size);
|
||||||
|
free(section_loaded);
|
||||||
free(file_buf);
|
free(file_buf);
|
||||||
return LOAD_ERR_SECTION_TOO_LARGE;
|
return LOAD_ERR_SECTION_TOO_LARGE;
|
||||||
}
|
}
|
||||||
@@ -146,19 +359,34 @@ int load_elf_object_sections(const char* path, uint8_t* memory, uint32_t mem_siz
|
|||||||
} else {
|
} else {
|
||||||
if (sh_offset >= bytes || sh_size > (uint32_t)bytes - sh_offset) {
|
if (sh_offset >= bytes || sh_size > (uint32_t)bytes - sh_offset) {
|
||||||
fprintf(stderr, "Section %u exceeds object file bounds\n", (unsigned)i);
|
fprintf(stderr, "Section %u exceeds object file bounds\n", (unsigned)i);
|
||||||
|
free(section_runtime);
|
||||||
|
free(section_addr);
|
||||||
|
free(section_size);
|
||||||
|
free(section_loaded);
|
||||||
free(file_buf);
|
free(file_buf);
|
||||||
return LOAD_ERR_SECTION_FILE_BOUNDS;
|
return LOAD_ERR_SECTION_FILE_BOUNDS;
|
||||||
}
|
}
|
||||||
memcpy(memory + dst, file_buf + sh_offset, sh_size);
|
memcpy(memory + dst, file_buf + sh_offset, sh_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
section_runtime[i] = dst;
|
||||||
|
section_loaded[i] = 1u;
|
||||||
|
|
||||||
if (sh_addr == 0u) {
|
if (sh_addr == 0u) {
|
||||||
cursor = dst + sh_size;
|
cursor = dst + sh_size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int reloc_status = apply_relocations(file_buf, bytes, memory, mem_size,
|
||||||
|
e_shoff, e_shentsize, e_shnum, section_runtime, section_addr,
|
||||||
|
section_size, section_loaded);
|
||||||
|
|
||||||
|
free(section_runtime);
|
||||||
|
free(section_addr);
|
||||||
|
free(section_size);
|
||||||
|
free(section_loaded);
|
||||||
free(file_buf);
|
free(file_buf);
|
||||||
return LOAD_OK;
|
return reloc_status;
|
||||||
}
|
}
|
||||||
|
|
||||||
int resolve_elf_symbol_memory_offset(const char* path, const char* symbol_name,
|
int resolve_elf_symbol_memory_offset(const char* path, const char* symbol_name,
|
||||||
|
|||||||
17
src/elf.h
17
src/elf.h
@@ -8,10 +8,21 @@
|
|||||||
#define ELFCLASS32 1
|
#define ELFCLASS32 1
|
||||||
#define ELFDATA2LSB 1
|
#define ELFDATA2LSB 1
|
||||||
|
|
||||||
#define SHT_NOBITS 8u
|
|
||||||
#define SHT_SYMTAB 2u
|
#define SHT_SYMTAB 2u
|
||||||
|
#define SHT_RELA 4u
|
||||||
|
#define SHT_NOBITS 8u
|
||||||
|
#define SHT_REL 9u
|
||||||
#define SHF_ALLOC 0x2u
|
#define SHF_ALLOC 0x2u
|
||||||
|
|
||||||
|
#define R_RISCV_32 1u
|
||||||
|
#define R_RISCV_NONE 0u
|
||||||
|
#define R_RISCV_BRANCH 16u
|
||||||
|
#define R_RISCV_JAL 17u
|
||||||
|
#define R_RISCV_HI20 26u
|
||||||
|
#define R_RISCV_LO12_I 27u
|
||||||
|
#define R_RISCV_LO12_S 28u
|
||||||
|
#define R_RISCV_RELAX 51u
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@@ -29,7 +40,9 @@ enum {
|
|||||||
LOAD_ERR_STRTAB_INVALID = -11,
|
LOAD_ERR_STRTAB_INVALID = -11,
|
||||||
LOAD_ERR_SYMBOL_NOT_FOUND = -12,
|
LOAD_ERR_SYMBOL_NOT_FOUND = -12,
|
||||||
LOAD_ERR_SYMBOL_INVALID_SECTION = -13,
|
LOAD_ERR_SYMBOL_INVALID_SECTION = -13,
|
||||||
LOAD_ERR_SYMBOL_OUT_OF_RANGE = -14
|
LOAD_ERR_SYMBOL_OUT_OF_RANGE = -14,
|
||||||
|
LOAD_ERR_RELOC_INVALID = -15,
|
||||||
|
LOAD_ERR_RELOC_UNSUPPORTED = -16
|
||||||
};
|
};
|
||||||
|
|
||||||
uint16_t read_u16_le(const uint8_t* data);
|
uint16_t read_u16_le(const uint8_t* data);
|
||||||
|
|||||||
@@ -1,13 +0,0 @@
|
|||||||
|
|
||||||
#include "function.h"
|
|
||||||
|
|
||||||
#include "custom_instructions.h"
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int32_t operation(int32_t a) {
|
|
||||||
return trunc_xor(a, 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
int32_t operation(int32_t a);
|
|
||||||
|
|
||||||
@@ -1,10 +1,14 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "function.h"
|
#include "../config.h"
|
||||||
#include "custom_instructions.h"
|
#include "custom_instructions.h"
|
||||||
|
|
||||||
|
#include "generated.h"
|
||||||
|
|
||||||
uint8_t entry(uint8_t a) {
|
uint32_t entry(void* userdata) {
|
||||||
return operation(a);
|
uint8_t len = (uint8_t)*((uint8_t*)userdata);
|
||||||
|
char* userflag = (char*)(userdata + 1);
|
||||||
|
|
||||||
|
return check(userflag, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
33
src/main.c
33
src/main.c
@@ -15,14 +15,28 @@
|
|||||||
|
|
||||||
|
|
||||||
int main(){
|
int main(){
|
||||||
|
const int maxninput = 255;
|
||||||
|
printf("Please enter the flag: ");
|
||||||
|
fflush(stdout);
|
||||||
|
char userinput[maxninput];
|
||||||
|
fgets(userinput, sizeof(userinput), stdin);
|
||||||
|
// Replace newline with null terminator
|
||||||
|
userinput[strcspn(userinput, "\r\n")] = 0;
|
||||||
|
|
||||||
uint8_t memory[EMU_MEM_SIZE]; //4kb of internal memory
|
uint8_t memory[EMU_MEM_SIZE]; //4kb of internal memory
|
||||||
tinyriscv_core cpu; //create the emulation core
|
tinyriscv_core cpu; //create the emulation core
|
||||||
memset(&cpu, 0, sizeof(cpu));
|
memset(&cpu, 0, sizeof(cpu));
|
||||||
cpu.mem = memory; //use the uint8_t array as the memory
|
cpu.mem = memory; //use the uint8_t array as the memory
|
||||||
cpu.mem_size = EMU_MEM_SIZE;
|
cpu.mem_size = EMU_MEM_SIZE;
|
||||||
memset(memory, 0, sizeof(memory));
|
memset(memory, 0, sizeof(memory));
|
||||||
|
uint8_t real_len = strnlen(userinput, maxninput);
|
||||||
|
|
||||||
int load_status = load_elf_object_sections(EMU_PROGRAM_PATH, memory, cpu.mem_size);
|
// Load user data, first, the string length
|
||||||
|
memory[SECTION_USERDATA] = real_len;
|
||||||
|
memcpy(memory + SECTION_USERDATA + 1, userinput, real_len);
|
||||||
|
|
||||||
|
// Load elf, keep 512 bytes as safe buffer
|
||||||
|
int load_status = load_elf_object_sections(EMU_PROGRAM_PATH, memory, cpu.mem_size - SIZE_USERDATA);
|
||||||
if (load_status != LOAD_OK) {
|
if (load_status != LOAD_OK) {
|
||||||
fprintf(stderr, "ELF load failed with code %d for '%s'\n", load_status, EMU_PROGRAM_PATH);
|
fprintf(stderr, "ELF load failed with code %d for '%s'\n", load_status, EMU_PROGRAM_PATH);
|
||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
@@ -43,9 +57,7 @@ int main(){
|
|||||||
tinyriscv_init(&cpu); //initialise core for execution
|
tinyriscv_init(&cpu); //initialise core for execution
|
||||||
cpu.pc = tinyriscv_MEM_OFFSET + entry_offset;
|
cpu.pc = tinyriscv_MEM_OFFSET + entry_offset;
|
||||||
|
|
||||||
// Call operation(a, b) using RV32 calling convention:
|
cpu.x[10] = tinyriscv_MEM_OFFSET + SECTION_USERDATA;
|
||||||
// a0=x10, return value in a0, return address in ra=x1.
|
|
||||||
cpu.x[10] = TEST_A;
|
|
||||||
cpu.x[1] = tinyriscv_MEM_OFFSET + cpu.mem_size;
|
cpu.x[1] = tinyriscv_MEM_OFFSET + cpu.mem_size;
|
||||||
|
|
||||||
uint32_t steps = 0u;
|
uint32_t steps = 0u;
|
||||||
@@ -59,15 +71,12 @@ int main(){
|
|||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t actual = (uint32_t)cpu.x[10];
|
uint32_t result = (uint32_t)cpu.x[10];
|
||||||
uint32_t expected = ((TEST_A << 3) ^ 0xFF) >> 3;
|
|
||||||
printf("operation(%u) -> %u (expected %u)\n",
|
|
||||||
(unsigned)TEST_A,
|
|
||||||
(unsigned)actual, (unsigned)expected);
|
|
||||||
|
|
||||||
if (actual != expected) {
|
if(result == 1) {
|
||||||
fprintf(stderr, "Verification failed\n");
|
printf("Congrats! That's the flag!");
|
||||||
return 3;
|
} else {
|
||||||
|
printf("Nope, sorry, that's incorrect!");
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user