@@ 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);