mirror of
https://github.com/ringtailsoftware/uvm32.git
synced 2026-06-06 06:53:39 +00:00
Remove stackoverflow error, have one CORE_INTERNAL error for catastrophic crash
This commit is contained in:
parent
59f5d6449b
commit
508d41c8c5
10 changed files with 163 additions and 57 deletions
|
|
@ -1,8 +1,9 @@
|
||||||
PREFIX:=riscv64-elf-
|
PREFIX:=riscv64-elf-
|
||||||
|
OPT ?= -Os
|
||||||
CFLAGS+=-I${TOPDIR}/common
|
CFLAGS+=-I${TOPDIR}/common
|
||||||
CFLAGS+=-fno-stack-protector
|
CFLAGS+=-fno-stack-protector
|
||||||
CFLAGS+=-static-libgcc -fdata-sections -ffunction-sections
|
CFLAGS+=-static-libgcc -fdata-sections -ffunction-sections
|
||||||
CFLAGS+=-g -Os -march=rv32im -mabi=ilp32 -static
|
CFLAGS+=-g ${OPT} -march=rv32im -mabi=ilp32 -static
|
||||||
LDFLAGS:= -T ${TOPDIR}/apps/linker.ld -nostdlib -Wl,--gc-sections
|
LDFLAGS:= -T ${TOPDIR}/apps/linker.ld -nostdlib -Wl,--gc-sections
|
||||||
LIBS:= -lgcc # needed for softfp
|
LIBS:= -lgcc # needed for softfp
|
||||||
|
|
||||||
|
|
@ -21,8 +22,8 @@ else
|
||||||
endif
|
endif
|
||||||
|
|
||||||
all_common:
|
all_common:
|
||||||
${PREFIX}gcc -o ${PROJECT}.elf ${CFLAGS} ${LDFLAGS} ${SRCS} ${LIBS}
|
@${PREFIX}gcc -o ${PROJECT}.elf ${CFLAGS} ${LDFLAGS} ${SRCS} ${LIBS}
|
||||||
$(PREFIX)objcopy ${PROJECT}.elf -O binary ${PROJECT}.bin
|
@$(PREFIX)objcopy ${PROJECT}.elf -O binary ${PROJECT}.bin
|
||||||
|
|
||||||
disasm_common: all
|
disasm_common: all
|
||||||
$(PREFIX)objdump -S -d -f ${PROJECT}.elf
|
$(PREFIX)objdump -S -d -f ${PROJECT}.elf
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,8 @@
|
||||||
all:
|
all:
|
||||||
make -C example_1
|
@make -C example_1
|
||||||
|
@make -C stackoverflow
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
make -C example_1 clean
|
make -C example_1 clean
|
||||||
|
make -C stackoverflow clean
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,15 +17,15 @@ INC_DIRS=-I$(UNITY_ROOT)/src -I../../uvm32/ -I../../common -Irom
|
||||||
.PHONY: rom
|
.PHONY: rom
|
||||||
|
|
||||||
default: $(SRC_FILES1) rom
|
default: $(SRC_FILES1) rom
|
||||||
$(C_COMPILER) $(CFLAGS) $(INC_DIRS) $(SYMBOLS) $(SRC_FILES1) rom/rom-header.c -o $(TARGET1)
|
@$(C_COMPILER) $(CFLAGS) $(INC_DIRS) $(SYMBOLS) $(SRC_FILES1) rom/rom-header.c -o $(TARGET1)
|
||||||
- ./$(TARGET1)
|
@- ./$(TARGET1)
|
||||||
|
|
||||||
rom:
|
rom:
|
||||||
(cd rom && make)
|
@(cd rom && make)
|
||||||
|
|
||||||
test/test_runners/${SUITE_NAME}_Runner.c: test/${SUITE_NAME}.c
|
test/test_runners/${SUITE_NAME}_Runner.c: test/${SUITE_NAME}.c
|
||||||
mkdir -p test/test_runners
|
@mkdir -p test/test_runners
|
||||||
ruby $(UNITY_ROOT)/auto/generate_test_runner.rb test/${SUITE_NAME}.c test/test_runners/${SUITE_NAME}_Runner.c
|
@ruby $(UNITY_ROOT)/auto/generate_test_runner.rb test/${SUITE_NAME}.c test/test_runners/${SUITE_NAME}_Runner.c
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf $(TARGET1) test/test_runners
|
rm -rf $(TARGET1) test/test_runners
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,9 @@ TOPDIR=../../../
|
||||||
PROJECT:=$(shell basename ${PWD})
|
PROJECT:=$(shell basename ${PWD})
|
||||||
SRCS=${PROJECT}.c ${TOPDIR}/apps/crt0.S
|
SRCS=${PROJECT}.c ${TOPDIR}/apps/crt0.S
|
||||||
all: all_common
|
all: all_common
|
||||||
# Convert ROM to C file and header
|
@# Convert ROM to C file and header
|
||||||
xxd -i ${PROJECT}.bin > ${PROJECT}-header.c
|
@xxd -i ${PROJECT}.bin > ${PROJECT}-header.c
|
||||||
echo "extern unsigned char ${PROJECT}_bin[]; extern int ${PROJECT}_bin_len;" > ${PROJECT}-header.h
|
@echo "extern unsigned char ${PROJECT}_bin[]; extern int ${PROJECT}_bin_len;" > ${PROJECT}-header.h
|
||||||
|
|
||||||
test: test_common
|
test: test_common
|
||||||
clean: clean_common
|
clean: clean_common
|
||||||
|
|
|
||||||
33
test/stackoverflow/Makefile
Normal file
33
test/stackoverflow/Makefile
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
C_COMPILER=gcc
|
||||||
|
|
||||||
|
UNITY_ROOT=../unity
|
||||||
|
|
||||||
|
CFLAGS=-std=c99
|
||||||
|
CFLAGS += -Wall
|
||||||
|
CFLAGS += -Werror
|
||||||
|
CFLAGS += -DUVM32_MEMORY_SIZE=512
|
||||||
|
|
||||||
|
SUITE_NAME=tests
|
||||||
|
|
||||||
|
TARGET_BASE1=test1
|
||||||
|
TARGET1 = $(TARGET_BASE1)
|
||||||
|
SRC_FILES1=$(UNITY_ROOT)/src/unity.c test/${SUITE_NAME}.c test/test_runners/${SUITE_NAME}_Runner.c ../../uvm32/uvm32.c
|
||||||
|
INC_DIRS=-I$(UNITY_ROOT)/src -I../../uvm32/ -I../../common -Irom
|
||||||
|
|
||||||
|
.PHONY: rom
|
||||||
|
|
||||||
|
default: $(SRC_FILES1) rom
|
||||||
|
@$(C_COMPILER) $(CFLAGS) $(INC_DIRS) $(SYMBOLS) $(SRC_FILES1) rom/rom-header.c -o $(TARGET1)
|
||||||
|
@- ./$(TARGET1)
|
||||||
|
|
||||||
|
rom:
|
||||||
|
@(cd rom && make)
|
||||||
|
|
||||||
|
test/test_runners/${SUITE_NAME}_Runner.c: test/${SUITE_NAME}.c
|
||||||
|
@mkdir -p test/test_runners
|
||||||
|
@ruby $(UNITY_ROOT)/auto/generate_test_runner.rb test/${SUITE_NAME}.c test/test_runners/${SUITE_NAME}_Runner.c
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf $(TARGET1) test/test_runners
|
||||||
|
(cd rom && make clean)
|
||||||
|
|
||||||
14
test/stackoverflow/rom/Makefile
Normal file
14
test/stackoverflow/rom/Makefile
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
TOPDIR=../../../
|
||||||
|
PROJECT:=$(shell basename ${PWD})
|
||||||
|
SRCS=${PROJECT}.c ${TOPDIR}/apps/crt0.S
|
||||||
|
OPT=-O0 # don't optimise
|
||||||
|
all: all_common
|
||||||
|
@# Convert ROM to C file and header
|
||||||
|
@xxd -i ${PROJECT}.bin > ${PROJECT}-header.c
|
||||||
|
@echo "extern unsigned char ${PROJECT}_bin[]; extern int ${PROJECT}_bin_len;" > ${PROJECT}-header.h
|
||||||
|
|
||||||
|
test: test_common
|
||||||
|
clean: clean_common
|
||||||
|
rm -f ${PROJECT}-header.h ${PROJECT}-header.c
|
||||||
|
|
||||||
|
include ${TOPDIR}/apps/makefile.common
|
||||||
12
test/stackoverflow/rom/rom.c
Normal file
12
test/stackoverflow/rom/rom.c
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
#include "uvm32_target.h"
|
||||||
|
|
||||||
|
int foo(int a) {
|
||||||
|
yield(0);
|
||||||
|
printdec(a);
|
||||||
|
return foo(a+1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main(void) {
|
||||||
|
foo(1);
|
||||||
|
}
|
||||||
|
|
||||||
34
test/stackoverflow/test/tests.c
Normal file
34
test/stackoverflow/test/tests.c
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
#include <string.h>
|
||||||
|
#include "unity.h"
|
||||||
|
#include "uvm32.h"
|
||||||
|
#include "../common/uvm32_common_custom.h"
|
||||||
|
|
||||||
|
#include "rom-header.h"
|
||||||
|
|
||||||
|
static uvm32_state_t vmst;
|
||||||
|
static uvm32_evt_t evt;
|
||||||
|
|
||||||
|
void setUp(void) {
|
||||||
|
// runs before each test
|
||||||
|
uvm32_init(&vmst);
|
||||||
|
uvm32_load(&vmst, rom_bin, rom_bin_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tearDown(void) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_stackoverflow(void) {
|
||||||
|
// run the vm
|
||||||
|
while(1) {
|
||||||
|
uvm32_run(&vmst, &evt, 100);
|
||||||
|
if (evt.typ == UVM32_EVT_SYSCALL) {
|
||||||
|
// ignore syscalls
|
||||||
|
} else {
|
||||||
|
TEST_ASSERT_EQUAL(UVM32_EVT_ERR, evt.typ);
|
||||||
|
TEST_ASSERT_EQUAL(UVM32_ERR_INTERNAL_CORE, evt.data.err.errcode);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -141,7 +141,7 @@ uint32_t uvm32_run(uvm32_state_t *vmst, uvm32_evt_t *evt, uint32_t instr_meter)
|
||||||
uint32_t num_instr = 0;
|
uint32_t num_instr = 0;
|
||||||
|
|
||||||
if (vmst->stack_canary != UVM32_NULL && *vmst->stack_canary != STACK_CANARY_VALUE) {
|
if (vmst->stack_canary != UVM32_NULL && *vmst->stack_canary != STACK_CANARY_VALUE) {
|
||||||
setStatusErr(vmst, UVM32_ERR_STACKOVERFLOW);
|
setStatusErr(vmst, UVM32_ERR_INTERNAL_CORE);
|
||||||
setup_err_evt(vmst, evt);
|
setup_err_evt(vmst, evt);
|
||||||
return num_instr;
|
return num_instr;
|
||||||
}
|
}
|
||||||
|
|
@ -159,7 +159,11 @@ uint32_t uvm32_run(uvm32_state_t *vmst, uvm32_evt_t *evt, uint32_t instr_meter)
|
||||||
uint64_t elapsedUs = 1;
|
uint64_t elapsedUs = 1;
|
||||||
uint32_t ret;
|
uint32_t ret;
|
||||||
ret = MiniRV32IMAStep(vmst, &vmst->core, vmst->memory, 0, elapsedUs, 1);
|
ret = MiniRV32IMAStep(vmst, &vmst->core, vmst->memory, 0, elapsedUs, 1);
|
||||||
if (3 == ret) {
|
|
||||||
|
switch(ret) {
|
||||||
|
case 0: // ok
|
||||||
|
break;
|
||||||
|
case 12: { // ecall
|
||||||
// Fetch registers used by syscall
|
// Fetch registers used by syscall
|
||||||
const uint32_t syscall = vmst->core.regs[17]; // a7
|
const uint32_t syscall = vmst->core.regs[17]; // a7
|
||||||
// on exception we should jump to mtvec, but we handle directly
|
// on exception we should jump to mtvec, but we handle directly
|
||||||
|
|
@ -175,10 +179,12 @@ uint32_t uvm32_run(uvm32_state_t *vmst, uvm32_evt_t *evt, uint32_t instr_meter)
|
||||||
if (vmst->stack_canary == (uint8_t *)UVM32_NULL) {
|
if (vmst->stack_canary == (uint8_t *)UVM32_NULL) {
|
||||||
uint32_t param0 = vmst->core.regs[10]; // a0
|
uint32_t param0 = vmst->core.regs[10]; // a0
|
||||||
uint32_t mem_offset = param0 - MINIRV32_RAM_IMAGE_OFFSET;
|
uint32_t mem_offset = param0 - MINIRV32_RAM_IMAGE_OFFSET;
|
||||||
|
mem_offset &= ~0xF; // round up by 16 bytes
|
||||||
|
mem_offset += 16*4;
|
||||||
|
|
||||||
// check data fits in ram
|
// check data fits in ram
|
||||||
if (mem_offset > UVM32_MEMORY_SIZE) {
|
if (mem_offset > UVM32_MEMORY_SIZE) {
|
||||||
setStatusErr(vmst, UVM32_ERR_STACKOVERFLOW);
|
setStatusErr(vmst, UVM32_ERR_INTERNAL_CORE);
|
||||||
setup_err_evt(vmst, evt);
|
setup_err_evt(vmst, evt);
|
||||||
}
|
}
|
||||||
// check canary is inside valid memory
|
// check canary is inside valid memory
|
||||||
|
|
@ -198,11 +204,13 @@ uint32_t uvm32_run(uvm32_state_t *vmst, uvm32_evt_t *evt, uint32_t instr_meter)
|
||||||
vmst->ioevt.data.syscall.params[1] = &vmst->core.regs[11]; // a1
|
vmst->ioevt.data.syscall.params[1] = &vmst->core.regs[11]; // a1
|
||||||
setStatus(vmst, UVM32_STATUS_PAUSED);
|
setStatus(vmst, UVM32_STATUS_PAUSED);
|
||||||
break;
|
break;
|
||||||
}
|
} // end switch(syscall)
|
||||||
} else if (ret != 0) {
|
} break; // end ecall
|
||||||
|
default:
|
||||||
// unhandled exception
|
// unhandled exception
|
||||||
setStatusErr(vmst, UVM32_ERR_INTERNAL_CORE);
|
setStatusErr(vmst, UVM32_ERR_INTERNAL_CORE);
|
||||||
setup_err_evt(vmst, evt);
|
setup_err_evt(vmst, evt);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
num_instr++;
|
num_instr++;
|
||||||
|
|
@ -213,8 +221,10 @@ uint32_t uvm32_run(uvm32_state_t *vmst, uvm32_evt_t *evt, uint32_t instr_meter)
|
||||||
setup_err_evt(vmst, evt);
|
setup_err_evt(vmst, evt);
|
||||||
return num_instr;
|
return num_instr;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (vmst->status == UVM32_STATUS_ENDED) {
|
if (vmst->status == UVM32_STATUS_ENDED) {
|
||||||
evt->typ = UVM32_EVT_END;
|
evt->typ = UVM32_EVT_END;
|
||||||
return num_instr;
|
return num_instr;
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,6 @@
|
||||||
X(UVM32_ERR_INTERNAL_CORE) \
|
X(UVM32_ERR_INTERNAL_CORE) \
|
||||||
X(UVM32_ERR_INTERNAL_STATE) \
|
X(UVM32_ERR_INTERNAL_STATE) \
|
||||||
X(UVM32_ERR_ARGS) \
|
X(UVM32_ERR_ARGS) \
|
||||||
X(UVM32_ERR_STACKOVERFLOW) \
|
|
||||||
|
|
||||||
#define X(name) name,
|
#define X(name) name,
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
|
@ -55,7 +54,7 @@ typedef struct {
|
||||||
|
|
||||||
#define MINIRV32_DECORATE static
|
#define MINIRV32_DECORATE static
|
||||||
#define MINI_RV32_RAM_SIZE UVM32_MEMORY_SIZE
|
#define MINI_RV32_RAM_SIZE UVM32_MEMORY_SIZE
|
||||||
#define MINIRV32_POSTEXEC(pc, ir, retval) {if (retval > 0) return 3;}
|
#define MINIRV32_POSTEXEC(pc, ir, retval) {if (retval > 0) return retval;}
|
||||||
#ifndef MINIRV32_IMPLEMENTATION
|
#ifndef MINIRV32_IMPLEMENTATION
|
||||||
#define MINIRV32_STEPPROTO
|
#define MINIRV32_STEPPROTO
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue