Make sure real-mode CS:IP changes never signal a stack switch
This commit is contained in:
parent
e76655a48f
commit
d45f3174f6
4 changed files with 39 additions and 23 deletions
|
|
@ -1116,10 +1116,7 @@ Bus.prototype.getBackTrackObject = function(bti)
|
||||||
{
|
{
|
||||||
if (BACKTRACK) {
|
if (BACKTRACK) {
|
||||||
var slot = bti >>> Bus.BACKTRACK.SLOT_SHIFT;
|
var slot = bti >>> Bus.BACKTRACK.SLOT_SHIFT;
|
||||||
if (slot) {
|
if (slot) return this.abtObjects[slot-1];
|
||||||
var bto = this.abtObjects[slot-1];
|
|
||||||
if (bto) return bto.obj;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
@ -1152,9 +1149,9 @@ Bus.prototype.getBackTrackInfo = function(bti)
|
||||||
var file = bto.obj.file;
|
var file = bto.obj.file;
|
||||||
if (file) {
|
if (file) {
|
||||||
this.assert(!bto.off);
|
this.assert(!bto.off);
|
||||||
return file.sName + '[' + (bto.obj.offFile + off) + ']';
|
return file.sName + '[' + str.toHexLong(bto.obj.offFile + off) + ']';
|
||||||
}
|
}
|
||||||
return bto.obj.idComponent + '[' + (bto.off + off) + ']';
|
return bto.obj.idComponent + '[' + str.toHexLong(bto.off + off) + ']';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
|
|
||||||
|
|
@ -1909,15 +1909,17 @@ if (DEBUGGER) {
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* dumpHistory(sCount)
|
* dumpHistory(sCount, cLines)
|
||||||
*
|
*
|
||||||
* @this {Debugger}
|
* @this {Debugger}
|
||||||
* @param {string|undefined} sCount is the number of instructions to rewind to (default is 10)
|
* @param {string} [sCount] is the number of instructions to rewind to (default is 10)
|
||||||
|
* @param {number} [cLines] is the number of instructions to print (default is, again, 10)
|
||||||
*/
|
*/
|
||||||
Debugger.prototype.dumpHistory = function(sCount)
|
Debugger.prototype.dumpHistory = function(sCount, cLines)
|
||||||
{
|
{
|
||||||
var sMore = "";
|
var sMore = "";
|
||||||
var cLines = 10;
|
cLines = cLines || 10;
|
||||||
|
var cHistory = 0;
|
||||||
var iHistory = this.iOpcodeHistory;
|
var iHistory = this.iOpcodeHistory;
|
||||||
var aHistory = this.aOpcodeHistory;
|
var aHistory = this.aOpcodeHistory;
|
||||||
if (aHistory.length) {
|
if (aHistory.length) {
|
||||||
|
|
@ -1960,10 +1962,11 @@ if (DEBUGGER) {
|
||||||
}
|
}
|
||||||
if (iHistory >= aHistory.length) iHistory = 0;
|
if (iHistory >= aHistory.length) iHistory = 0;
|
||||||
this.nextHistory = n;
|
this.nextHistory = n;
|
||||||
|
cHistory++;
|
||||||
cLines--;
|
cLines--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (cLines == 10) {
|
if (!cHistory) {
|
||||||
this.println("no " + sMore + "history available");
|
this.println("no " + sMore + "history available");
|
||||||
this.nextHistory = undefined;
|
this.nextHistory = undefined;
|
||||||
}
|
}
|
||||||
|
|
@ -2050,7 +2053,7 @@ if (DEBUGGER) {
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* getRegIndex(sReg)
|
* getRegIndex(sReg, off)
|
||||||
*
|
*
|
||||||
* @this {Debugger}
|
* @this {Debugger}
|
||||||
* @param {string} sReg
|
* @param {string} sReg
|
||||||
|
|
@ -2203,7 +2206,7 @@ if (DEBUGGER) {
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* replaceRegs()
|
* replaceRegs(s)
|
||||||
*
|
*
|
||||||
* @this {Debugger}
|
* @this {Debugger}
|
||||||
* @param {string} s
|
* @param {string} s
|
||||||
|
|
@ -4325,8 +4328,10 @@ if (DEBUGGER) {
|
||||||
this.println("\tdb [a] [#] dump # bytes at address a");
|
this.println("\tdb [a] [#] dump # bytes at address a");
|
||||||
this.println("\tdw [a] [#] dump # words at address a");
|
this.println("\tdw [a] [#] dump # words at address a");
|
||||||
this.println("\tdd [a] [#] dump # dwords at address a");
|
this.println("\tdd [a] [#] dump # dwords at address a");
|
||||||
this.println("\tdh [#] dump # instructions prior");
|
this.println("\tdh [#] [#] dump # instructions prior");
|
||||||
if (BACKTRACK) this.println("\tdi [a] dump backtrack info at address a");
|
if (BACKTRACK) {
|
||||||
|
this.println("\tdi [a] dump backtrack info at address a");
|
||||||
|
}
|
||||||
if (sDumpers.length) this.println("dump extensions:\n\t" + sDumpers);
|
if (sDumpers.length) this.println("dump extensions:\n\t" + sDumpers);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -4338,8 +4343,13 @@ if (DEBUGGER) {
|
||||||
this.dumpSymbols();
|
this.dumpSymbols();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
var cLines = 0;
|
||||||
|
if (sLen) {
|
||||||
|
if (sLen.charAt(0) == "l") sLen = sLen.substr(1);
|
||||||
|
cLines = +sLen;
|
||||||
|
}
|
||||||
if (sCmd == "dh") {
|
if (sCmd == "dh") {
|
||||||
this.dumpHistory(sAddr);
|
this.dumpHistory(sAddr, cLines);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (sCmd == "ds") { // transform a "ds" command into a "d desc" command
|
if (sCmd == "ds") { // transform a "ds" command into a "d desc" command
|
||||||
|
|
@ -4369,15 +4379,14 @@ if (DEBUGGER) {
|
||||||
sDump += sInfo || "no information";
|
sDump += sInfo || "no information";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
var cLines = 0;
|
|
||||||
var cBytes = (sCmd == "dd"? 4 : (sCmd == "dw"? 2 : 1));
|
var cBytes = (sCmd == "dd"? 4 : (sCmd == "dw"? 2 : 1));
|
||||||
var cNumbers = (16 / cBytes)|0;
|
var cNumbers = (16 / cBytes)|0;
|
||||||
if (sLen) {
|
if (!cLines) {
|
||||||
if (sLen.charAt(0) == "l") sLen = sLen.substr(1);
|
cLines = 8;
|
||||||
cLines = +sLen;
|
} else {
|
||||||
if (cLines) cLines = ((cLines + cNumbers - 1) / cNumbers)|0;
|
cLines = ((cLines + cNumbers - 1) / cNumbers)|0;
|
||||||
|
if (!cLines) cLines = 1;
|
||||||
}
|
}
|
||||||
if (!cLines) cLines = 8;
|
|
||||||
for (var iLine = 0; iLine < cLines; iLine++) {
|
for (var iLine = 0; iLine < cLines; iLine++) {
|
||||||
var data = 0, iByte = 0;
|
var data = 0, iByte = 0;
|
||||||
var sData = "", sChars = "";
|
var sData = "", sChars = "";
|
||||||
|
|
|
||||||
|
|
@ -2147,9 +2147,18 @@ X86.fnRETF = function RETF(n)
|
||||||
var newIP = this.popWord();
|
var newIP = this.popWord();
|
||||||
var newCS = this.popWord();
|
var newCS = this.popWord();
|
||||||
if (DEBUG) this.printMessage(" returning to " + str.toHex(newCS, 4) + ':' + str.toHex(newIP, this.dataSize << 1), this.bitsMessage, true);
|
if (DEBUG) this.printMessage(" returning to " + str.toHex(newCS, 4) + ':' + str.toHex(newIP, this.dataSize << 1), this.bitsMessage, true);
|
||||||
|
|
||||||
n <<= (this.dataSize >> 2);
|
n <<= (this.dataSize >> 2);
|
||||||
if (n) this.setSP(this.getSP() + n); // TODO: optimize
|
if (n) this.setSP(this.getSP() + n); // TODO: optimize
|
||||||
if (this.setCSIP(newIP, newCS, false)) {
|
|
||||||
|
if (this.setCSIP(newIP, newCS, false)) { // returns true if a stack switch occurred
|
||||||
|
/*
|
||||||
|
* Fool me once, shame on... whatever. If setCSIP() indicates a stack switch occurred,
|
||||||
|
* make sure we're in protected mode, because automatic stack switches can't occur in real mode,
|
||||||
|
* and adjusting SP again under those circumstances will likely cause great harm.
|
||||||
|
*/
|
||||||
|
this.assert(!!(this.regCR0 & X86.CR0.MSW.PE));
|
||||||
|
|
||||||
if (n) this.setSP(this.getSP() + n); // TODO: optimize
|
if (n) this.setSP(this.getSP() + n); // TODO: optimize
|
||||||
/*
|
/*
|
||||||
* As per Intel documentation: "If any of [the DS or ES] registers refer to segments whose DPL is
|
* As per Intel documentation: "If any of [the DS or ES] registers refer to segments whose DPL is
|
||||||
|
|
|
||||||
|
|
@ -1037,6 +1037,7 @@ X86Seg.prototype.updateMode = function(fLoad, fProt)
|
||||||
this.checkWrite = this.checkWriteReal;
|
this.checkWrite = this.checkWriteReal;
|
||||||
this.cpl = this.dpl = 0;
|
this.cpl = this.dpl = 0;
|
||||||
this.addrDesc = X86.ADDR_INVALID;
|
this.addrDesc = X86.ADDR_INVALID;
|
||||||
|
this.fStackSwitch = false;
|
||||||
}
|
}
|
||||||
return fProt;
|
return fProt;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue