diff --git a/modules/pcjs/lib/debugger.js b/modules/pcjs/lib/debugger.js index 03da1e7d8..52a55742f 100644 --- a/modules/pcjs/lib/debugger.js +++ b/modules/pcjs/lib/debugger.js @@ -155,9 +155,8 @@ function Debugger(parmsDbg) this.dbgAddrAssemble = this.newAddr(); /* - * aSymbolTable is an array of SymbolTable objects, one per ROM or other chunk of address space. - * - * Each SymbolTable object contains the following properties: + * aSymbolTable is an array of SymbolTable objects, one per ROM or other chunk of address space, + * where each object contains the following properties: * * sModule * nSegment @@ -166,7 +165,7 @@ function Debugger(parmsDbg) * addr (physical address, if any; eg, if symbols are for a ROM) * len * aSymbols - * aOffsetPairs + * aOffsets * * See addSymbols() for more details, since that's how callers add sets of symbols to the table. */ @@ -1388,6 +1387,7 @@ if (DEBUGGER) { * removeSectionInfo(nSegment, dbgAddr, fPrint) * * @this {Debugger} + * @param {number} nSegment (logical segment number) * @param {DbgAddr} dbgAddr (address of module) * @param {boolean} [fPrint] */ @@ -1425,7 +1425,7 @@ if (DEBUGGER) { * * TODO: Consider "consuming" all VW32_Int41Dispatch callbacks, because the Windows 95 kernel goes to * great effort to pass those requests on to the DEBUG VxD, which end up going nowhere when the VxD isn't - * loaded (to load it, you must either run WDEB386.EXE or install it via your SYSTEM.INI). Regrettably, + * loaded (to load it, you must either run WDEB386.EXE or install the VxD via SYSTEM.INI). Regrettably, * Windows 95 assumes that if WDEB386 support is present, then a DEBUG VxD must be present as well. * * @this {Debugger} @@ -1487,8 +1487,6 @@ if (DEBUGGER) { var DI = cpu.regEDI & 0xffff; var ES = cpu.segES.sel; - var seg, limit, sModule; - if (this.fWinDbg == null) { if (AX == Interrupts.WINDBG.IS_LOADED) { /* @@ -1516,22 +1514,22 @@ if (DEBUGGER) { * responsibility for all requests (don't assume there's valid interrupt handler inside the machine). */ switch(AX) { - case Interrupts.WINDBG.IS_LOADED: + case Interrupts.WINDBG.IS_LOADED: // 0x004F if (this.fWinDbg) { cpu.regEAX = (cpu.regEAX & ~0xffff) | Interrupts.WINDBG.LOADED; this.println("INT 0x41 handling enabled"); } break; - case Interrupts.WINDBG.LOADSEG: + case Interrupts.WINDBG.LOADSEG: // 0x0050 this.addSegmentInfo(this.newAddr(DI, ES), BX+1, CX, !(SI & 0x1), this.fWinDbg); break; - case Interrupts.WINDBG.FREESEG: + case Interrupts.WINDBG.FREESEG: // 0x0052 this.removeSegmentInfo(BX); break; - case Interrupts.WINDBG.KRNLVARS: + case Interrupts.WINDBG.KRNLVARS: // 0x005A /* * BX = version number of this data (0x3A0) * DX:CX points to: @@ -1551,28 +1549,40 @@ if (DEBUGGER) { */ break; - case Interrupts.WINDBG.RELSEG: - case Interrupts.WINDBG.LOADDLL: - case Interrupts.WINDBG.DELMODULE: + case Interrupts.WINDBG.RELSEG: // 0x005C + case Interrupts.WINDBG.LOADDLL: // 0x0064 + case Interrupts.WINDBG.DELMODULE: // 0x0065 /* * TODO: Figure out what to do with these notifications, if anything */ break; - case Interrupts.WINDBG.REGDOTCMD: - case Interrupts.WINDBG.CONDBP: - case Interrupts.WINDBG.LOADHIGH: + case Interrupts.WINDBG.LOADHIGH: // 0x005D + case Interrupts.WINDBG.REGDOTCMD: // 0x0070 + case Interrupts.WINDBG.CONDBP: // 0xF001 break; - case Interrupts.WINDBG.GETSYMBOL: - if (this.fWinDbg) cpu.regEAX = (cpu.regEAX & ~0xffff)|1; // AX == 1 means not found - break; - - case Interrupts.WINDBG.CHECKFAULT: + case Interrupts.WINDBG.CHECKFAULT: // 0x007F if (this.fWinDbg) cpu.regEAX = (cpu.regEAX & ~0xffff)|0; // AX == 0 means handle fault normally break; - case Interrupts.WINDBG.LOADSEG32: + case Interrupts.WINDBG.TRAPFAULT: // 0x0083 + /* + * Ordinarily (I think), since we're responding with AX=0 to all CHECKFAULT notifications, + * all TRAPFAULT notifications should be withheld; however, one exception may be if the user + * is presented with a fault dialog containing a "Debug" button, and the user clicks it.... + * + * So for now, we'll allocate a temporary breakpoint at the reported fault address whenever + * this notification comes through. + */ + this.addBreakpoint(this.aBreakExec, this.newAddr(cpu.regEDX, CX), true); + break; + + case Interrupts.WINDBG.GETSYMBOL: // 0x008D + if (this.fWinDbg) cpu.regEAX = (cpu.regEAX & ~0xffff)|1; // AX == 1 means not found + break; + + case Interrupts.WINDBG.LOADSEG32: // 0x0150 /* * SI == segment type: * 0x0 code selector @@ -1582,7 +1592,7 @@ if (DEBUGGER) { this.addSectionInfo(this.newAddr(cpu.regEBX, DX), !SI, this.fWinDbg); break; - case Interrupts.WINDBG.FREESEG32: + case Interrupts.WINDBG.FREESEG32: // 0x0152 /* * BX == segment number * DX:EDI -> module name @@ -1671,13 +1681,13 @@ if (DEBUGGER) { * responsibility for all requests (don't assume there's valid interrupt handler inside the machine). */ switch(AH) { - case Interrupts.WINDBGRM.IS_LOADED: + case Interrupts.WINDBGRM.IS_LOADED: // 0x43 if (this.fWinDbgRM) { cpu.regEAX = (cpu.regEAX & ~0xffff) | Interrupts.WINDBGRM.LOADED; } break; - case Interrupts.WINDBGRM.PREP_PMODE: + case Interrupts.WINDBGRM.PREP_PMODE: // 0x44 if (this.fWinDbgRM) { var a = cpu.segCS.addCallBreak(this.callWindowsDebuggerPMInit.bind(this)); if (a) { @@ -1687,18 +1697,18 @@ if (DEBUGGER) { } break; - case Interrupts.WINDBGRM.FREESEG: + case Interrupts.WINDBGRM.FREESEG: // 0x48 this.removeSegmentInfo(BX); break; - case Interrupts.WINDBGRM.REMOVESEGS: + case Interrupts.WINDBGRM.REMOVESEGS: // 0x4F /* * TODO: This probably just signals the end of module loading; nothing is required, but we should * clean up whatever we can.... */ break; - case Interrupts.WINDBGRM.LOADSEG: + case Interrupts.WINDBGRM.LOADSEG: // 0x50 if (AL == 0x20) { /* * Real-mode EXE @@ -5394,18 +5404,18 @@ if (DEBUGGER) { * We add all these entries to our internal symbol table, which is an array of 4-element arrays, each of which * look like: * - * [sel, off, addr, len, aSymbols, aOffsetPairs] + * [sel, off, addr, len, aSymbols, aOffsets] * * There are two basic symbol operations: findSymbol(), which takes an address and finds the symbol, if any, * at that address, and findSymbolAddr(), which takes a string and attempts to match it to a non-anonymous * symbol with a matching offset ('o') property. * * To implement findSymbol() efficiently, addSymbols() creates an array of [offset, sSymbol] pairs - * (aOffsetPairs), one pair for each symbol that corresponds to an offset within the specified address space. + * (aOffsets), one pair for each symbol that corresponds to an offset within the specified address space. * - * We guarantee the elements of aOffsetPairs are in offset order, because we build it using binaryInsert(); + * We guarantee the elements of aOffsets are in offset order, because we build it using binaryInsert(); * it's quite likely that the MAP file already ordered all its symbols in offset order, but since they're - * hand-edited files, we can't assume that. This ensures that findSymbol()'s binarySearch() will operate + * hand-edited files, we can't assume that, and we need to ensure that findSymbol()'s binarySearch() operates * properly. * * @this {Debugger} @@ -5420,7 +5430,7 @@ if (DEBUGGER) { Debugger.prototype.addSymbols = function(sModule, nSegment, sel, off, addr, len, aSymbols) { var dbgAddr = {}; - var aOffsetPairs = []; + var aOffsets = []; for (var sSymbol in aSymbols) { var symbol = aSymbols[sSymbol]; if (typeof symbol == "number") { @@ -5448,7 +5458,7 @@ if (DEBUGGER) { } symbol['p'] = dbgAddr.addr; } - usr.binaryInsert(aOffsetPairs, [offSymbol >>> 0, sSymbol], this.comparePairs); + usr.binaryInsert(aOffsets, [offSymbol >>> 0, sSymbol], this.comparePairs); } if (sAnnotation) symbol['a'] = sAnnotation.replace(/''/g, "\""); } @@ -5460,7 +5470,7 @@ if (DEBUGGER) { addr: addr, len: len, aSymbols: aSymbols, - aOffsetPairs: aOffsetPairs + aOffsets: aOffsets }; this.aSymbolTable.push(symbolTable); }; @@ -5541,7 +5551,7 @@ if (DEBUGGER) { var len = symbolTable.len; if (sel == 0x30) sel = 0x28; // TODO: Remove this hack once we're able to differentiate Windows 95 ring 0 code and data if (sel == dbgAddr.sel && offSymbol >= off && offSymbol < off + len || addr != null && addrSymbol >= addr && addrSymbol < addr + len) { - var result = usr.binarySearch(symbolTable.aOffsetPairs, [offSymbol], this.comparePairs); + var result = usr.binarySearch(symbolTable.aOffsets, [offSymbol], this.comparePairs); if (result >= 0) { this.returnSymbol(iTable, result, aSymbol); } @@ -5616,11 +5626,11 @@ if (DEBUGGER) { Debugger.prototype.returnSymbol = function(iTable, iOffset, aSymbol) { var symbol = {}; - var aOffsetPairs = this.aSymbolTable[iTable].aOffsetPairs; + var aOffsets = this.aSymbolTable[iTable].aOffsets; var offset = 0, sSymbol = null; - if (iOffset >= 0 && iOffset < aOffsetPairs.length) { - offset = aOffsetPairs[iOffset][0]; - sSymbol = aOffsetPairs[iOffset][1]; + if (iOffset >= 0 && iOffset < aOffsets.length) { + offset = aOffsets[iOffset][0]; + sSymbol = aOffsets[iOffset][1]; } if (sSymbol) { symbol = this.aSymbolTable[iTable].aSymbols[sSymbol]; diff --git a/modules/pcjs/lib/disk.js b/modules/pcjs/lib/disk.js index 87d2ea072..c268a0979 100644 --- a/modules/pcjs/lib/disk.js +++ b/modules/pcjs/lib/disk.js @@ -265,10 +265,10 @@ Component.subclass(Disk); * where offset is relative to the segment's offStart value, and symbol is a string describing the * entry. * - * NOTE: Although aEntries uses a format similar to the Debugger's aOffsetPairs, they are not - * interchangeable data structures, because ours is ordered by ordinal, whereas aOffsetPairs is + * NOTE: Although aEntries arrays are similar to the Debugger's aOffsets arrays, they are not + * interchangeable data structures, because ours is ordered by ordinal, whereas aOffsets is * ordered by offset. We provide an interface, getModuleInfo(), to the Debugger that converts - * our data into an intermediate array, aSymbols, which the Debugger then uses to build aOffsetPairs. + * our data into an intermediate array, aSymbols, which the Debugger then uses to build aOffsets. * It would be nice to avoid building that intermediate representation, but it's a side-effect of * the Debugger's earlier support for JSON-encoded MAP files. *