~vdupras/duskos

60edd420cc32c189d716d5a847019702ab4f7563 — Virgil Dupras 22 days ago 18d90ee
posix/vm: add memory protection mechanism

very useful for debugging memory corruption.
1 files changed, 17 insertions(+), 4 deletions(-)

M posix/vm.c
M posix/vm.c => posix/vm.c +17 -4
@@ 91,6 91,8 @@ struct VM {
	dword W;  // W is PS top
	dword A;
	dword T; // tmp register. not directly addressable
	dword mprotect; // halt when protected memory is changed
	dword mprotectsz;
	byte Z;
	byte C;
	byte SC; // signed C


@@ 111,10 113,17 @@ static dword mainaddr;
static void vmabort() { vm.PC = MEMSZ + 1; }
static dword memchk(dword a) {
	if (a < MEMSZ) return a;
	printf("Out of bounds memory access! Halting");
	printf("Out of bounds memory access! Halting\n");
	vmabort();
	return 0;
}
static dword memchkmut(dword a) {
	if ((a >= vm.mprotect) && (a < vm.mprotect + vm.mprotectsz)) {
		printf("Access to protected memory! Halting\n");
		vmabort();
		return 0;
	} else { return a; }
}
static byte gb(dword addr) { return vm.mem[memchk(addr)]; }
static word gw(dword addr) { return gb(addr) | (gb(addr+1)<<8); }
static dword gd(dword addr) { return gw(addr) | (gw(addr+2)<<16); }


@@ 130,7 139,7 @@ static dword gdr(dword addr) {
}
static dword gpc() { dword n = gd(vm.PC); vm.PC += 4; return n; }
static byte gpcb() { dword n = gb(vm.PC); vm.PC++; return n; }
static void sb(dword addr, byte b) { vm.mem[memchk(addr)] = b; }
static void sb(dword addr, byte b) { vm.mem[memchkmut(addr)] = b; }
static void sw(dword addr, word w) { sb(addr, w); sb(addr+1, w>>8); }
static void sd(dword addr, dword d) { sw(addr, d); sw(addr+2, d>>16); }
static void sdr(dword addr, dword d) {


@@ 595,6 604,8 @@ static void DBG() {
	printf("RS "); _stackdump(vm.RSP, RSTOP);
}
static void USLEEP() { usleep(ppop()); }
// ( a u -- )
static void MPROTECT() { vm.mprotectsz = ppop(); vm.mprotect = ppop(); }

// 0x60
static void WCHECKZ() { vm.Z = !vm.W; }


@@ 894,7 905,7 @@ static void (*ops[OPCNT])() = {
	STACKCHK, COMPWORD, RUNWORD, COMPILING, STARTCOMP, STOPCOMP, RSADDWR, COMPOP,
	ALIGN4, ENTRY, CODE, CODE16, CODE8, COMPBINOP, NULL, NULL,
	WBINOP, WBINOP16, WBINOP8, DIVMOD, NULL, LT, NEG, NULL,
	BYE, BYEFAIL, QUIT, ABORT_, DBG, USLEEP, NULL, NULL,
	BYE, BYEFAIL, QUIT, ABORT_, DBG, USLEEP, MPROTECT, NULL,
	NULL, NULL, NULL, NULL, NULL, WCHECKZ, STOREC, ACHECKZ,
	FCHILD, FOPEN, FREADBUF, FCLOSE, FINFO, FITER, NULL, FSEEK,
	MOUNTDRV, UNMOUNTDRV, DRVRD, DRVWR, NULL, NULL, NULL, NULL,


@@ 937,7 948,7 @@ static char *opnames[OPCNT-0x28] = {
	"stack?", "compword", "runword", "compiling", "]", NULL, "rs+,", NULL,
	"align4", "entry", "code", "code16b", "code8b", NULL, NULL, NULL,
	NULL, NULL, NULL, "/mod", NULL, "<", NULL, NULL,
	"bye", "byefail", "quit", "(abort)", "dbg", "_usleep", NULL, NULL,
	"bye", "byefail", "quit", "(abort)", "dbg", "_usleep", "mprotect", NULL,
	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
	"_fchild", "_fopen", "_freadbuf", "_fclose", "_finfo", "_fiter", NULL, "_fseek",
	"_mountdrv", "_unmountdrv", "_drv@", "_drv!", NULL, NULL, NULL, NULL


@@ 1053,10 1064,12 @@ int main() {
		return 1;
	}
	buildsysdict();
	vm.mprotectsz = 0;
	vm.PC = find("(abort)");
	while (vm.PC < MEMSZ) oprun1();
	if (fp) fclose(fp);
	if (vm.PC > MEMSZ) {
		DBG();
		fprintf(stderr, "Dumping memory to memdump.\n");
		FILE *fp = fopen("memdump", "w");
		fwrite(vm.mem, MEMSZ, 1, fp);