SCI: Add inspect, none breakpoint actions

This commit is contained in:
Willem Jan Palenstijn 2017-05-26 18:40:43 +02:00
parent 423ecde8e0
commit be84cfdb59
3 changed files with 50 additions and 11 deletions

View File

@ -3741,6 +3741,12 @@ bool Console::cmdBreakpointList(int argc, const char **argv) {
case BREAK_BACKTRACE:
bpaction = " (action: show backtrace)";
break;
case BREAK_INSPECT:
bpaction = " (action: show object)";
break;
case BREAK_NONE:
bpaction = " (action: ignore)";
break;
default:
bpaction = "";
}
@ -3802,13 +3808,7 @@ bool Console::cmdBreakpointDelete(int argc, const char **argv) {
// Delete it
_debugState._breakpoints.erase(bp);
// Update EngineState::_activeBreakpointTypes.
int type = 0;
for (bp = _debugState._breakpoints.begin(); bp != end; ++bp) {
type |= bp->_type;
}
_debugState._activeBreakpointTypes = type;
_debugState.updateActiveBreakpointTypes();
return true;
}
@ -3831,13 +3831,22 @@ bool Console::cmdBreakpointAction(int argc, const char **argv) {
bpaction = BREAK_LOG;
else if (arg == "bt")
bpaction = BREAK_BACKTRACE;
else if (arg == "inspect")
bpaction = BREAK_INSPECT;
else if (arg == "none")
bpaction = BREAK_NONE;
else
usage = true;
if (usage) {
debugPrintf("Change the action for the breakpoint with the specified index.\n");
debugPrintf("Usage: %s <breakpoint index> break|log|bt\n", argv[0]);
debugPrintf("Usage: %s <breakpoint index> break|log|bt|inspect|none\n", argv[0]);
debugPrintf("<index> * will process all breakpoints\n");
debugPrintf("Actions: break : break into debugger\n");
debugPrintf(" log : log without breaking\n");
debugPrintf(" bt : show backtrace without breaking\n");
debugPrintf(" inspect: show object (only for bpx/bpr/bpw)\n");
debugPrintf(" none : ignore breakpoint\n");
return true;
}
@ -3846,6 +3855,7 @@ bool Console::cmdBreakpointAction(int argc, const char **argv) {
if (strcmp(argv[1], "*") == 0) {
for (; bp != end; ++bp)
bp->_action = bpaction;
_debugState.updateActiveBreakpointTypes();
return true;
}
@ -3862,6 +3872,9 @@ bool Console::cmdBreakpointAction(int argc, const char **argv) {
}
bp->_action = bpaction;
_debugState.updateActiveBreakpointTypes();
return true;
}

View File

@ -47,9 +47,11 @@ enum BreakpointType {
};
enum BreakpointAction {
BREAK_BREAK, // break into debugger when breakpoint is triggered
BREAK_LOG, // log the breakpoint, and don't break into debugger
BREAK_BACKTRACE // show a backtrace, and don't break into debugger
BREAK_NONE, // ignore breakpoint
BREAK_BREAK, // break into debugger when breakpoint is triggered
BREAK_LOG, // log the breakpoint, and don't break into debugger
BREAK_BACKTRACE, // show a backtrace, and don't break into debugger
BREAK_INSPECT // show object, and don't break into debugger
};
struct Breakpoint {
@ -81,6 +83,8 @@ struct DebugState {
StackPtr old_sp;
Common::List<Breakpoint> _breakpoints; //< List of breakpoints
int _activeBreakpointTypes; //< Bit mask specifying which types of breakpoints are active
void updateActiveBreakpointTypes();
};
// Various global variables used for debugging are declared here

View File

@ -68,6 +68,16 @@ const char *opcodeNames[] = {
};
#endif // REDUCE_MEMORY_USAGE
void DebugState::updateActiveBreakpointTypes() {
int type = 0;
for (Common::List<Breakpoint>::iterator bp = _breakpoints.begin(); bp != _breakpoints.end(); ++bp) {
if (bp->_action != BREAK_NONE)
type |= bp->_type;
}
_activeBreakpointTypes = type;
}
// Disassembles one command from the heap, returns address of next command or 0 if a ret was encountered.
reg_t disassemble(EngineState *s, reg32_t pos, reg_t objAddr, bool printBWTag, bool printBytecode) {
SegmentObj *mobj = s->_segMan->getSegment(pos.getSegment(), SEG_TYPE_SCRIPT);
@ -688,6 +698,8 @@ bool SciEngine::checkSelectorBreakpoint(BreakpointType breakpointType, reg_t sen
for (bpIter = _debugState._breakpoints.begin(); bpIter != _debugState._breakpoints.end(); ++bpIter) {
if (bpIter->_type != breakpointType)
continue;
if (bpIter->_action == BREAK_NONE)
continue;
if (bpIter->_name == methodName ||
(bpIter->_name.hasSuffix("::") && methodName.hasPrefix(bpIter->_name))) {
_console->debugPrintf("Break on %s (in [%04x:%04x])\n", methodName.c_str(), PRINT_REG(send_obj));
@ -696,6 +708,8 @@ bool SciEngine::checkSelectorBreakpoint(BreakpointType breakpointType, reg_t sen
_debugState.breakpointWasHit = true;
} else if (bpIter->_action == BREAK_BACKTRACE) {
logBacktrace();
} else if (bpIter->_action == BREAK_INSPECT) {
printObject(send_obj);
}
return true;
}
@ -709,6 +723,8 @@ bool SciEngine::checkExportBreakpoint(uint16 script, uint16 pubfunct) {
Common::List<Breakpoint>::const_iterator bp;
for (bp = _debugState._breakpoints.begin(); bp != _debugState._breakpoints.end(); ++bp) {
if (bp->_action == BREAK_NONE)
continue;
if (bp->_type == BREAK_EXPORT && bp->_address == bpaddress) {
_console->debugPrintf("Break on script %d, export %d\n", script, pubfunct);
if (bp->_action == BREAK_BREAK) {
@ -716,6 +732,8 @@ bool SciEngine::checkExportBreakpoint(uint16 script, uint16 pubfunct) {
_debugState.breakpointWasHit = true;
} else if (bp->_action == BREAK_BACKTRACE) {
logBacktrace();
} else if (bp->_action == BREAK_INSPECT) {
// Ignoring this mode, to make it identical to BREAK_LOG
}
return true;
}
@ -729,6 +747,8 @@ bool SciEngine::checkAddressBreakpoint(const reg32_t &address) {
if (_debugState._activeBreakpointTypes & BREAK_ADDRESS) {
Common::List<Breakpoint>::const_iterator bp;
for (bp = _debugState._breakpoints.begin(); bp != _debugState._breakpoints.end(); ++bp) {
if (bp->_action == BREAK_NONE)
continue;
if (bp->_type == BREAK_ADDRESS && bp->_regAddress == address) {
_console->debugPrintf("Break at %04x:%04x\n", PRINT_REG(address));
if (bp->_action == BREAK_BREAK) {
@ -736,6 +756,8 @@ bool SciEngine::checkAddressBreakpoint(const reg32_t &address) {
_debugState.breakpointWasHit = true;
} else if (bp->_action == BREAK_BACKTRACE) {
logBacktrace();
} else if (bp->_action == BREAK_INSPECT) {
// Ignoring this mode, to make it identical to BREAK_LOG
}
return true;
}