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;
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++;
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));
}
}
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[] = {
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 {
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);
}
}
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;
})
};
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* () {
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) {
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) {
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;
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);
}
});
let stack_frame = new StackFrame(frameRef, f.funcname, source, f.line);
- stack_frame.instructionPointerReference = "1234";
+ stack_frame.instructionPointerReference = f.instructionPointer.toString();
return stack_frame;
})
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<void> {
+ 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);
funcname: string;
filename: string;
line: number;
+ instructionPointer: number;
}
interface IBreakpointValidation {
data: ArrayBuffer;
}
+interface IDisassembledInstruction {
+ instr: string;
+}
+
enum OVMCommand {
NOP = 0,
RES = 1,
VARS = 8,
MEM_R = 9,
MEM_W = 10,
+ DISASM = 11
}
enum OVMEvent {
return this.preparePromise(cmd_id);
}
+ disassemble(addr: number, count: number): Promise<IDisassembledInstruction[]> {
+ 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);
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);
break;
}
+ case OVMCommand.DISASM: {
+ let result = new Array<IDisassembledInstruction>();
+
+ 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);
}