#include #include #include "error.h" #include "debug.h" #include "vmstate.h" #include "vmval.h" #include "unit.h" int debug_breakpoint(struct vm *vm) { struct vm_func_entry *func; struct vm_unit *unit; uint64_t w0; uint32_t opcode; char line[256]; char *p; unit = vector_ref(&vm->units, vm->lp); func = vector_ref(&unit->functions, vm->fp); opcode = func->bytecode[vm->ip]; fprintf(stderr, "%02zx:%02zx:%04zx: %08x\n", vm->lp, vm->fp, vm->ip, opcode); while (1) { fprintf(stderr, ">> "); if (!fgets(line, sizeof(line), stdin)) { return 0; } if ((p = strchr(line, '\n')) != NULL) { *p = 0; } if (!strcmp(line, "s")) { vm->flags |= VM_SINGLESTEP; return 0; } else if (!strcmp(line, "c")) { vm->flags &= ~VM_SINGLESTEP; return 0; } else if (!strcmp(line, "q")) { return -ERR_ERROR_EXIT; } else if (!strcmp(line, "regs")) { fprintf(stderr, " lp = 0x%04zx, fp = 0x%04zx\n", vm->lp, vm->fp); fprintf(stderr, " ip = 0x%04zx\n", vm->ip); fprintf(stderr, " dsp = 0x%04zx\n", vm->data_stack.sp); fprintf(stderr, " csp = 0x%04zx, cbp = 0x%04zx\n", vm->call_stack.sp, vm->bp); } else if (!strcmp(line, "locals")) { fprintf(stderr, "Local variables:\n"); for (size_t i = 0; i < func->local_count; ++i) { w0 = vm->call_stack.data[vm->bp - i - 1]; fprintf(stderr, "[bp - %zu]: ", i + 1); vm_print(stderr, w0); fprintf(stderr, "\n"); } fprintf(stderr, "Arguments:\n"); for (size_t i = 0; i < func->argc; ++i) { w0 = vm->call_stack.data[vm->bp + i]; fprintf(stderr, "[bp + %zu]: ", i); vm_print(stderr, w0); fprintf(stderr, "\n"); } } else if (!strcmp(line, "bt")) { fprintf(stderr, "Call frame trace:\n"); size_t bp, lp, fp, ip, sp; size_t count; struct vm_func_entry *f; struct vm_unit *u; bp = vm->bp; lp = vm->lp; fp = vm->fp; ip = vm->ip; count = 0; while (1) { u = vector_ref(&vm->units, lp); f = vector_ref(&u->functions, fp); sp = bp + f->argc; fprintf(stderr, "%2zu: %02zx:%02zx:%04zx: %08x\n", count, lp, fp, ip, f->bytecode[ip]); if (count == 5) { break; } bp = vm->call_stack.data[sp + 3]; lp = vm->call_stack.data[sp + 2]; fp = vm->call_stack.data[sp + 1]; ip = vm->call_stack.data[sp + 0]; ++count; if (bp == 0) { break; } } } } }