From: Brendan Hansen Date: Tue, 3 Jan 2023 17:29:26 +0000 (-0600) Subject: added disassembly view debug command X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=0a01440fa652bda9f6bbf9f846177ac9f17630a5;p=onyx.git added disassembly view debug command --- diff --git a/interpreter/src/debug/debug_thread.c b/interpreter/src/debug/debug_thread.c index c01f74fe..bd3994a5 100644 --- a/interpreter/src/debug/debug_thread.c +++ b/interpreter/src/debug/debug_thread.c @@ -96,14 +96,9 @@ static void resume_thread(debug_thread_state_t *thread) { sem_post(&thread->wait_semaphore); } -static void get_stack_frame_location(debug_state_t *debug, - debug_func_info_t *func_info, debug_file_info_t *file_info, debug_loc_info_t *loc_info, - debug_thread_state_t *thread, ovm_stack_frame_t *frame) { - +static u32 get_stack_frame_instruction_pointer(debug_state_t *debug, debug_thread_state_t *thread, ovm_stack_frame_t *frame) { ovm_func_t *func = frame->func; - assert(debug_info_lookup_func(debug->info, func->id, func_info)); - u32 instr; if (frame == &bh_arr_last(thread->ovm_state->stack_frames)) { instr = thread->ovm_state->pc; @@ -111,6 +106,19 @@ static void get_stack_frame_location(debug_state_t *debug, instr = (frame + 1)->return_address; } + return instr; +} + +static void get_stack_frame_location(debug_state_t *debug, + debug_func_info_t *func_info, debug_file_info_t *file_info, debug_loc_info_t *loc_info, + debug_thread_state_t *thread, ovm_stack_frame_t *frame) { + + ovm_func_t *func = frame->func; + + u32 instr = get_stack_frame_instruction_pointer(debug, thread, frame); + + assert(debug_info_lookup_func(debug->info, func->id, func_info)); + while (!debug_info_lookup_location(debug->info, instr, loc_info)) instr++; @@ -304,6 +312,7 @@ static DEBUG_COMMAND_HANDLER(debug_command_trace) { send_string(debug, func_info.name); send_string(debug, file_info.name); send_int(debug, loc_info.line); + send_int(debug, get_stack_frame_instruction_pointer(debug, thread, frame)); } } @@ -468,6 +477,31 @@ static DEBUG_COMMAND_HANDLER(debug_command_memory_write) { static DEBUG_COMMAND_HANDLER(debug_command_disassmble) { u32 addr = parse_int(debug, ctx); u32 count = parse_int(debug, ctx); + + send_response_header(debug, msg_id); + + bh_buffer instr_buf; + bh_buffer_init(&instr_buf, debug->tmp_alloc, 1024); + + // This is kind of a hack, but currently there is no + // easy way to access the program text for the current + // program without going through a thread. So I just go + // through the first thread. + ovm_program_t *prog = debug->threads[0]->ovm_state->program; + + while (addr < bh_arr_length(prog->code) && count--) { + send_int(debug, 0); + + ovm_disassemble(prog, addr, &instr_buf); + + send_bytes(debug, instr_buf.data, instr_buf.length); + bh_buffer_clear(&instr_buf); + + addr += 1; + } + + send_int(debug, 1); + bh_buffer_free(&instr_buf); } static debug_command_handler_t command_handlers[] = { diff --git a/interpreter/src/vm/disasm.c b/interpreter/src/vm/disasm.c index 25d3028b..c23cc192 100644 --- a/interpreter/src/vm/disasm.c +++ b/interpreter/src/vm/disasm.c @@ -17,6 +17,14 @@ enum instr_format_kind_t { instr_format_store, instr_format_idx_arr, + + instr_format_br, + instr_format_br_cond, + instr_format_bri, + instr_format_bri_cond, + + instr_format_call, + instr_format_calli, }; typedef struct instr_format_t { @@ -131,20 +139,57 @@ void ovm_disassemble(ovm_program_t *program, u32 instr_addr, bh_buffer *instr_te case OVM_TYPE_V128: bh_buffer_write_string(instr_text, "v128."); break; } - instr_format_t *format = &instr_formats[OVM_INSTR_INSTR(instr)]; + instr_format_t *format = &instr_formats[OVM_INSTR_INSTR(*instr)]; - bh_buffer_write(instr_text, format->instr); + bh_buffer_write_string(instr_text, format->instr); - char *formatted = NULL; + u32 formatted = 0; switch (format->kind) { case instr_format_rab: formatted = snprintf(buf, 255, "%%%d, %%%d, %%%d", instr->r, instr->a, instr->b); break; case instr_format_ra: formatted = snprintf(buf, 255, "%%%d, %%%d", instr->r, instr->a); break; case instr_format_a: formatted = snprintf(buf, 255, "%%%d", instr->a); break; + + case instr_format_imm: + switch (OVM_INSTR_TYPE(*instr)) { + case OVM_TYPE_I8: formatted = snprintf(buf, 255, "%%%d, %hhd", instr->r, instr->i); break; + case OVM_TYPE_I16: formatted = snprintf(buf, 255, "%%%d, %hd", instr->r, instr->i); break; + case OVM_TYPE_I32: formatted = snprintf(buf, 255, "%%%d, %d", instr->r, instr->i); break; + case OVM_TYPE_I64: formatted = snprintf(buf, 255, "%%%d, %ld", instr->r, instr->l); break; + case OVM_TYPE_F32: formatted = snprintf(buf, 255, "%%%d, %f", instr->r, instr->f); break; + case OVM_TYPE_F64: formatted = snprintf(buf, 255, "%%%d, %lf", instr->r, instr->d); break; + } + break; + + case instr_format_load: formatted = snprintf(buf, 255, "%%%d, [%%%d + %d]", instr->r, instr->a, instr->b); break; + case instr_format_store: formatted = snprintf(buf, 255, "[%%%d + %d], %%%d", instr->r, instr->b, instr->a); break; + + case instr_format_idx_arr: formatted = snprintf(buf, 255, "%%%d, __global_arr_%d[%%%d]", instr->r, instr->a, instr->b); break; + + case instr_format_br: formatted = snprintf(buf, 255, "%d", instr_addr + instr->a); break; + case instr_format_br_cond: formatted = snprintf(buf, 255, "%d, %%%d", instr_addr + instr->a, instr->b); break; + case instr_format_bri: formatted = snprintf(buf, 255, "ip + %%%d", instr->a); break; + case instr_format_bri_cond: formatted = snprintf(buf, 255, "ip + %%%d, %%%d", instr->a, instr->b); break; + + case instr_format_call: + if (instr->r >= 0) { + formatted = snprintf(buf, 255, "%%%d, %d <%s>", instr->r, instr->a, program->funcs[instr->a].name); + } else { + formatted = snprintf(buf, 255, "%d <%s>", instr->a, program->funcs[instr->a].name); + } + break; + + case instr_format_calli: + if (instr->r >= 0) { + formatted = snprintf(buf, 255, "%%%d, %%%d", instr->r, instr->a); + } else { + formatted = snprintf(buf, 255, "%%%d", instr->a); + } + break; } - if (formatted) { + if (formatted > 0) { bh_buffer_write_byte(instr_text, ' '); - bh_buffer_write_string(instr_text, formatted); + bh_buffer_append(instr_text, buf, formatted); } } diff --git a/misc/vscode/out/ovmDebug.js b/misc/vscode/out/ovmDebug.js index f3812dd9..efe9d3ec 100644 --- a/misc/vscode/out/ovmDebug.js +++ b/misc/vscode/out/ovmDebug.js @@ -158,7 +158,7 @@ class OVMDebugSession extends debugadapter_1.LoggingDebugSession { frameIndex: i }); let stack_frame = new debugadapter_1.StackFrame(frameRef, f.funcname, source, f.line); - stack_frame.instructionPointerReference = "1234"; + stack_frame.instructionPointerReference = f.instructionPointer.toString(); return stack_frame; }) }; @@ -269,16 +269,20 @@ class OVMDebugSession extends debugadapter_1.LoggingDebugSession { this.sendResponse(response); } disassembleRequest(response, args, request) { - console.log(args); - response.body = { - instructions: [ - { - address: "0", - instruction: "i32.add %3, %1, %2", - } - ] - }; - this.sendResponse(response); + return __awaiter(this, void 0, void 0, function* () { + console.log(args); + let addr = parseInt(args.memoryReference) + args.offset; + let instrs = yield this.debugger.disassemble(addr, args.instructionCount); + response.body = { + instructions: instrs.map((i, index) => { + return { + address: (index + addr).toString(), + instruction: i.instr + }; + }) + }; + this.sendResponse(response); + }); } readMemoryRequest(response, args, request) { return __awaiter(this, void 0, void 0, function* () { @@ -320,6 +324,7 @@ var OVMCommand; OVMCommand[OVMCommand["VARS"] = 8] = "VARS"; OVMCommand[OVMCommand["MEM_R"] = 9] = "MEM_R"; OVMCommand[OVMCommand["MEM_W"] = 10] = "MEM_W"; + OVMCommand[OVMCommand["DISASM"] = 11] = "DISASM"; })(OVMCommand || (OVMCommand = {})); var OVMEvent; (function (OVMEvent) { @@ -504,6 +509,20 @@ class OVMDebugger extends EventEmitter { this.pending_responses[cmd_id] = OVMCommand.MEM_W; return this.preparePromise(cmd_id); } + disassemble(addr, count) { + if (this.client == null) + return Promise.resolve([]); + let data = new ArrayBuffer(16); + let view = new DataView(data); + let cmd_id = this.next_command_id; + view.setUint32(0, cmd_id, true); + view.setUint32(4, OVMCommand.DISASM, true); + view.setUint32(8, addr, true); + view.setUint32(12, count, true); + this.client.write(new Uint8Array(data)); + this.pending_responses[cmd_id] = OVMCommand.DISASM; + return this.preparePromise(cmd_id); + } parseIncoming(data) { let parser = new DataParser(data); while (parser.offset != data.length) { @@ -580,7 +599,8 @@ class OVMDebugger extends EventEmitter { let funcname = parser.parseString(); let filename = parser.parseString(); let line = parser.parseInt32(); - result.push({ funcname, filename, line }); + let ip = parser.parseInt32(); + result.push({ funcname, filename, line, instructionPointer: ip }); } this.resolvePromise(msg_id, result); break; @@ -620,6 +640,15 @@ class OVMDebugger extends EventEmitter { this.resolvePromise(msg_id, count); break; } + case OVMCommand.DISASM: { + let result = new Array(); + while (parser.parseInt32() == 0) { + let instr = parser.parseString(); + result.push({ instr }); + } + this.resolvePromise(msg_id, result); + break; + } default: // console.log("Unrecognized command. ", cmd_id, msg_id); } diff --git a/misc/vscode/ovmDebug.ts b/misc/vscode/ovmDebug.ts index b6680210..940fb4f4 100644 --- a/misc/vscode/ovmDebug.ts +++ b/misc/vscode/ovmDebug.ts @@ -238,7 +238,7 @@ export class OVMDebugSession extends LoggingDebugSession { }); let stack_frame = new StackFrame(frameRef, f.funcname, source, f.line); - stack_frame.instructionPointerReference = "1234"; + stack_frame.instructionPointerReference = f.instructionPointer.toString(); return stack_frame; }) @@ -375,16 +375,17 @@ export class OVMDebugSession extends LoggingDebugSession { this.sendResponse(response); } - protected disassembleRequest(response: DebugProtocol.DisassembleResponse, args: DebugProtocol.DisassembleArguments, request?: DebugProtocol.Request): void { - console.log(args); + protected async disassembleRequest(response: DebugProtocol.DisassembleResponse, args: DebugProtocol.DisassembleArguments, request?: DebugProtocol.Request): Promise { + let addr = parseInt(args.memoryReference) + args.offset; + let instrs = await this.debugger.disassemble(addr, args.instructionCount); response.body = { - instructions: [ - { - address: "0", - instruction: "i32.add %3, %1, %2", - } - ] + instructions: instrs.map((i, index) => { + return { + address: (index + addr - 1).toString(), + instruction: i.instr, + }; + }) }; this.sendResponse(response); @@ -426,6 +427,7 @@ interface IFileLocation { funcname: string; filename: string; line: number; + instructionPointer: number; } interface IBreakpointValidation { @@ -452,6 +454,10 @@ interface IReadMemory { data: ArrayBuffer; } +interface IDisassembledInstruction { + instr: string; +} + enum OVMCommand { NOP = 0, RES = 1, @@ -464,6 +470,7 @@ enum OVMCommand { VARS = 8, MEM_R = 9, MEM_W = 10, + DISASM = 11 } enum OVMEvent { @@ -712,6 +719,26 @@ class OVMDebugger extends EventEmitter { return this.preparePromise(cmd_id); } + disassemble(addr: number, count: number): Promise { + if (this.client == null) return Promise.resolve([]); + + let data = new ArrayBuffer(16); + let view = new DataView(data); + + let cmd_id = this.next_command_id; + + view.setUint32(0, cmd_id, true); + view.setUint32(4, OVMCommand.DISASM, true); + view.setUint32(8, addr, true); + view.setUint32(12, count, true); + + this.client.write(new Uint8Array(data)); + + this.pending_responses[cmd_id] = OVMCommand.DISASM; + + return this.preparePromise(cmd_id); + } + private parseIncoming(data: Buffer): void { let parser = new DataParser(data); @@ -801,8 +828,9 @@ class OVMDebugger extends EventEmitter { let funcname = parser.parseString(); let filename = parser.parseString(); let line = parser.parseInt32(); + let ip = parser.parseInt32(); - result.push({funcname, filename, line}); + result.push({funcname, filename, line, instructionPointer: ip}); } this.resolvePromise(msg_id, result); @@ -854,6 +882,18 @@ class OVMDebugger extends EventEmitter { break; } + case OVMCommand.DISASM: { + let result = new Array(); + + while (parser.parseInt32() == 0) { + let instr = parser.parseString(); + result.push({ instr }); + } + + this.resolvePromise(msg_id, result); + break; + } + default: // console.log("Unrecognized command. ", cmd_id, msg_id); } diff --git a/shared/lib/linux_x86_64/lib/libovmwasm.so b/shared/lib/linux_x86_64/lib/libovmwasm.so index 2ba9dcba..3e670e14 100755 Binary files a/shared/lib/linux_x86_64/lib/libovmwasm.so and b/shared/lib/linux_x86_64/lib/libovmwasm.so differ