3
CPU.prototype.debug_init = function()
9
debug.init = function()
16
var seabios_debug = "";
18
cpu.io.register_write(0x402, this, handle);
19
cpu.io.register_write(0x500, this, handle);
22
function handle(out_byte)
26
dbg_log(seabios_debug, LOG_BIOS);
31
seabios_debug += String.fromCharCode(out_byte);
36
debug.get_regs_short = get_regs_short;
37
debug.dump_regs = dump_regs_short;
38
debug.get_state = get_state;
39
debug.dump_state = dump_state;
40
debug.dump_stack = dump_stack;
42
debug.dump_page_structures = dump_page_structures;
43
debug.dump_gdt_ldt = dump_gdt_ldt;
44
debug.dump_idt = dump_idt;
46
debug.get_memory_dump = get_memory_dump;
47
debug.memory_hex_dump = memory_hex_dump;
48
debug.used_memory_dump = used_memory_dump;
50
function dump_stack(start, end)
54
var esp = cpu.reg32[REG_ESP];
55
dbg_log("========= STACK ==========");
57
if(end >= start || end === undefined)
63
for(var i = start; i > end; i--)
69
line += h(i, 2) + " | ";
71
dbg_log(line + h(esp + 4 * i, 8) + " | " + h(cpu.read32s(esp + 4 * i) >>> 0));
75
function get_state(where)
79
var mode = cpu.protected_mode[0] ? "prot" : "real";
80
var vm = (cpu.flags[0] & FLAG_VM) ? 1 : 0;
81
var flags = cpu.get_eflags();
82
var iopl = cpu.getiopl();
84
var cs_eip = h(cpu.sreg[REG_CS], 4) + ":" + h(cpu.get_real_eip() >>> 0, 8);
85
var ss_esp = h(cpu.sreg[REG_SS], 4) + ":" + h(cpu.reg32[REG_ES] >>> 0, 8);
86
var op_size = cpu.is_32[0] ? "32" : "16";
87
var if_ = (cpu.flags[0] & FLAG_INTERRUPT) ? 1 : 0;
96
[FLAG_INTERRUPT]: "i",
97
[FLAG_DIRECTION]: "d",
100
var flag_string = "";
102
for(var i = 0; i < 16; i++)
104
if(flag_names[1 << i])
108
flag_string += flag_names[1 << i];
117
return ("mode=" + mode + "/" + op_size + " paging=" + (+((cpu.cr[0] & CR0_PG) !== 0)) +
118
" pae=" + (+((cpu.cr[4] & CR4_PAE) !== 0)) +
119
" iopl=" + iopl + " cpl=" + cpl + " if=" + if_ + " cs:eip=" + cs_eip +
120
" cs_off=" + h(cpu.get_seg_cs() >>> 0, 8) +
121
" flgs=" + h(cpu.get_eflags() >>> 0, 6) + " (" + flag_string + ")" +
122
" ss:esp=" + ss_esp +
123
" ssize=" + (+cpu.stack_size_32[0]) +
124
(where ? " in " + where : ""));
127
function dump_state(where)
131
dbg_log(get_state(where), LOG_CPU);
134
function get_regs_short()
137
r32 = { "eax": REG_EAX, "ecx": REG_ECX, "edx": REG_EDX, "ebx": REG_EBX,
138
"esp": REG_ESP, "ebp": REG_EBP, "esi": REG_ESI, "edi": REG_EDI },
139
r32_names = ["eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"],
140
s = { "cs": REG_CS, "ds": REG_DS, "es": REG_ES, "fs": REG_FS, "gs": REG_GS, "ss": REG_SS },
146
for(var i = 0; i < 4; i++)
148
line1 += r32_names[i] + "=" + h(cpu.reg32[r32[r32_names[i]]] >>> 0, 8) + " ";
149
line2 += r32_names[i+4] + "=" + h(cpu.reg32[r32[r32_names[i+4]]] >>> 0, 8) + " ";
155
line1 += " ds=" + h(cpu.sreg[REG_DS], 4) + " es=" + h(cpu.sreg[REG_ES], 4) + " fs=" + h(cpu.sreg[REG_FS], 4);
156
line2 += " gs=" + h(cpu.sreg[REG_GS], 4) + " cs=" + h(cpu.sreg[REG_CS], 4) + " ss=" + h(cpu.sreg[REG_SS], 4);
158
return [line1, line2];
161
function dump_regs_short()
165
var lines = get_regs_short();
167
dbg_log(lines[0], LOG_CPU);
168
dbg_log(lines[1], LOG_CPU);
171
function dump_gdt_ldt()
175
dbg_log("gdt: (len = " + h(cpu.gdtr_size[0]) + ")");
176
dump_table(cpu.translate_address_system_read(cpu.gdtr_offset[0]), cpu.gdtr_size[0]);
178
dbg_log("\nldt: (len = " + h(cpu.segment_limits[REG_LDTR]) + ")");
179
dump_table(cpu.translate_address_system_read(cpu.segment_offsets[REG_LDTR]), cpu.segment_limits[REG_LDTR]);
181
function dump_table(addr, size)
183
for(var i = 0; i < size; i += 8, addr += 8)
185
var base = cpu.read16(addr + 2) |
186
cpu.read8(addr + 4) << 16 |
187
cpu.read8(addr + 7) << 24,
189
limit = cpu.read16(addr) | (cpu.read8(addr + 6) & 0xF) << 16,
190
access = cpu.read8(addr + 5),
191
flags = cpu.read8(addr + 6) >> 4,
193
dpl = access >> 5 & 3;
238
flags_str += "sys: " + h(access & 15);
243
limit = limit << 12 | 0xFFF;
246
dbg_log(h(i & ~7, 4) + " " + h(base >>> 0, 8) + " (" + h(limit >>> 0, 8) + " bytes) " +
247
flags_str + "; dpl = " + dpl + ", a = " + access.toString(2) +
248
", f = " + flags.toString(2));
257
for(var i = 0; i < cpu.idtr_size[0]; i += 8)
259
var addr = cpu.translate_address_system_read(cpu.idtr_offset[0] + i),
260
base = cpu.read16(addr) | cpu.read16(addr + 6) << 16,
261
selector = cpu.read16(addr + 2),
262
type = cpu.read8(addr + 5),
266
if((type & 31) === 5)
270
else if((type & 31) === 14)
274
else if((type & 31) === 15)
296
dbg_log(h(i >> 3, 4) + " " + h(base >>> 0, 8) + ", " +
297
h(selector, 4) + "; " + line + "; dpl = " + dpl + ", t = " + type.toString(2));
301
function load_page_entry(dword_entry, pae, is_directory)
305
if(!(dword_entry & 1))
311
var size = (dword_entry & 128) === 128,
314
if(size && !is_directory)
316
address = dword_entry & (pae ? 0xFFE00000 : 0xFFC00000);
320
address = dword_entry & 0xFFFFF000;
325
global: (dword_entry & 256) === 256,
326
accessed: (dword_entry & 0x20) === 0x20,
327
dirty: (dword_entry & 0x40) === 0x40,
328
cache_disable : (dword_entry & 16) === 16,
329
user : (dword_entry & 4) === 4,
330
read_write : (dword_entry & 2) === 2,
331
address : address >>> 0
335
function dump_page_structures() {
336
var pae = !!(cpu.cr[4] & CR4_PAE);
339
dbg_log("PAE enabled");
341
for (var i = 0; i < 4; i++) {
342
var addr = cpu.cr[3] + 8 * i;
343
var dword = cpu.read32s(addr);
346
dump_page_directory(dword & 0xFFFFF000, true, i << 30);
352
dbg_log("PAE disabled");
353
dump_page_directory(cpu.cr[3], false, 0);
358
function dump_page_directory(pd_addr, pae, start)
362
var n = pae ? 512 : 1024;
363
var entry_size = pae ? 8 : 4;
364
var pd_shift = pae ? 21 : 22;
366
for(var i = 0; i < n; i++)
368
var addr = pd_addr + i * entry_size,
369
dword = cpu.read32s(addr),
370
entry = load_page_entry(dword, pae, true);
379
flags += entry.size ? "S " : " ";
380
flags += entry.accessed ? "A " : " ";
381
flags += entry.cache_disable ? "Cd " : " ";
382
flags += entry.user ? "U " : " ";
383
flags += entry.read_write ? "Rw " : " ";
387
dbg_log("=== " + h(start + (i << pd_shift) >>> 0, 8) + " -> " +
388
h(entry.address >>> 0, 8) + " | " + flags);
393
dbg_log("=== " + h(start + (i << pd_shift) >>> 0, 8) + " | " + flags);
396
for(var j = 0; j < n; j++)
398
var sub_addr = entry.address + j * entry_size;
399
dword = cpu.read32s(sub_addr);
401
var subentry = load_page_entry(dword, pae, false);
407
flags += subentry.cache_disable ? "Cd " : " ";
408
flags += subentry.user ? "U " : " ";
409
flags += subentry.read_write ? "Rw " : " ";
410
flags += subentry.global ? "G " : " ";
411
flags += subentry.accessed ? "A " : " ";
412
flags += subentry.dirty ? "Di " : " ";
414
dbg_log("# " + h(start + (i << pd_shift | j << 12) >>> 0, 8) + " -> " +
415
h(subentry.address, 8) + " | " + flags + " (at " + h(sub_addr, 8) + ")");
422
function get_memory_dump(start, count)
426
if(start === undefined)
429
count = cpu.memory_size[0];
431
else if(count === undefined)
437
return cpu.mem8.slice(start, start + count).buffer;
441
function memory_hex_dump(addr, length)
445
length = length || 4 * 0x10;
448
for(var i = 0; i < length >> 4; i++)
450
line = h(addr + (i << 4), 5) + " ";
452
for(var j = 0; j < 0x10; j++)
454
byt = cpu.read8(addr + (i << 4) + j);
455
line += h(byt, 2) + " ";
460
for(j = 0; j < 0x10; j++)
462
byt = cpu.read8(addr + (i << 4) + j);
463
line += (byt < 33 || byt > 126) ? "." : String.fromCharCode(byt);
470
function used_memory_dump()
476
block_size = cpu.memory_size[0] / width / height | 0,
479
for(var i = 0; i < height; i++)
481
row = h(i * width * block_size, 8) + " | ";
483
for(var j = 0; j < width; j++)
485
var used = cpu.mem32s[(i * width + j) * block_size] > 0;
487
row += used ? "X" : " ";
495
debug.debug_interrupt = function(interrupt_nr)
555
let capstone_decoder;
557
debug.dump_code = function(is_32, buffer, start)
559
if(!capstone_decoder)
563
if(typeof require === "function")
565
cs = require("./capstone-x86.min.js");
574
dbg_log("Warning: Missing capstone library, disassembly not available");
580
new cs.Capstone(cs.ARCH_X86, cs.MODE_16),
581
new cs.Capstone(cs.ARCH_X86, cs.MODE_32),
587
const instructions = capstone_decoder[is_32].disasm(buffer, start);
589
instructions.forEach(function (instr) {
590
dbg_log(h(instr.address >>> 0) + ": " +
591
v86util.pads(instr.bytes.map(x => h(x, 2).slice(-2)).join(" "), 20) + " " +
592
instr.mnemonic + " " + instr.op_str);
598
dbg_log("Could not disassemble: " + Array.from(buffer).map(x => h(x, 2)).join(" "));
602
function dump_file(ab, name)
604
var blob = new Blob([ab]);
606
var a = document.createElement("a");
607
a["download"] = name;
608
a.href = window.URL.createObjectURL(blob);
609
a.dataset["downloadurl"] = ["application/octet-stream", a["download"], a.href].join(":");
612
window.URL.revokeObjectURL(a.src);
617
debug.dump_wasm = function(buffer)
619
if(wabt === undefined)
621
if(typeof require === "function")
623
wabt = require("./libwabt.js");
627
wabt = new window.WabtModule;
630
if(wabt === undefined)
632
dbg_log("Warning: Missing libwabt, wasm dump not available");
639
buffer = buffer.slice();
643
var module = wabt.readWasm(buffer, { readDebugNames: false });
644
module.generateNames();
646
const result = module.toText({ foldExprs: true, inlineExport: true });
651
dump_file(buffer, "failed.wasm");
652
console.log(e.toString());