aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorWillem Jan Palenstijn2017-05-26 14:12:41 +0200
committerWillem Jan Palenstijn2017-06-10 21:32:35 +0200
commit8e683db72b280fbe4319d68466c7f3c61a6c107d (patch)
treef7d23f413eef10dabad968083696d87b2d83c7c3 /engines
parentcb69d10e962e2cea604175fdd35189726f6a6436 (diff)
downloadscummvm-rg350-8e683db72b280fbe4319d68466c7f3c61a6c107d.tar.gz
scummvm-rg350-8e683db72b280fbe4319d68466c7f3c61a6c107d.tar.bz2
scummvm-rg350-8e683db72b280fbe4319d68466c7f3c61a6c107d.zip
SCI: Add break/log/backtrace actions for triggered breakpoints
The action can be set using the new console command bp_action/bpact.
Diffstat (limited to 'engines')
-rw-r--r--engines/sci/console.cpp83
-rw-r--r--engines/sci/console.h1
-rw-r--r--engines/sci/debug.h7
-rw-r--r--engines/sci/engine/scriptdebug.cpp25
4 files changed, 105 insertions, 11 deletions
diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp
index 2274dac1a7..6c9be970cb 100644
--- a/engines/sci/console.cpp
+++ b/engines/sci/console.cpp
@@ -205,6 +205,8 @@ Console::Console(SciEngine *engine) : GUI::Debugger(),
registerCmd("bp_del", WRAP_METHOD(Console, cmdBreakpointDelete));
registerCmd("bpdel", WRAP_METHOD(Console, cmdBreakpointDelete)); // alias
registerCmd("bc", WRAP_METHOD(Console, cmdBreakpointDelete)); // alias
+ registerCmd("bp_action", WRAP_METHOD(Console, cmdBreakpointAction));
+ registerCmd("bpact", WRAP_METHOD(Console, cmdBreakpointAction)); // alias
registerCmd("bp_address", WRAP_METHOD(Console, cmdBreakpointAddress));
registerCmd("bpa", WRAP_METHOD(Console, cmdBreakpointAddress)); // alias
registerCmd("bp_method", WRAP_METHOD(Console, cmdBreakpointMethod));
@@ -443,6 +445,7 @@ bool Console::cmdHelp(int argc, const char **argv) {
debugPrintf("Breakpoints:\n");
debugPrintf(" bp_list / bplist / bl - Lists the current breakpoints\n");
debugPrintf(" bp_del / bpdel / bc - Deletes a breakpoint with the specified index\n");
+ debugPrintf(" bp_action / bpact - Set action to be performed when breakpoint is triggered\n");
debugPrintf(" bp_address / bpa - Sets a breakpoint on a script address\n");
debugPrintf(" bp_method / bpx - Sets a breakpoint on the execution of a specified method/selector\n");
debugPrintf(" bp_read / bpr - Sets a breakpoint on reading of a specified selector\n");
@@ -3729,22 +3732,34 @@ bool Console::cmdBreakpointList(int argc, const char **argv) {
Common::List<Breakpoint>::const_iterator end = _debugState._breakpoints.end();
for (; bp != end; ++bp) {
debugPrintf(" #%i: ", i);
+ const char *bpaction;
+
+ switch (bp->_action) {
+ case BREAK_LOG:
+ bpaction = " (action: log only)";
+ break;
+ case BREAK_BACKTRACE:
+ bpaction = " (action: show backtrace)";
+ break;
+ default:
+ bpaction = "";
+ }
switch (bp->_type) {
case BREAK_SELECTOREXEC:
- debugPrintf("Execute %s\n", bp->_name.c_str());
+ debugPrintf("Execute %s%s\n", bp->_name.c_str(), bpaction);
break;
case BREAK_SELECTORREAD:
- debugPrintf("Read %s\n", bp->_name.c_str());
+ debugPrintf("Read %s%s\n", bp->_name.c_str(), bpaction);
break;
case BREAK_SELECTORWRITE:
- debugPrintf("Write %s\n", bp->_name.c_str());
+ debugPrintf("Write %s%s\n", bp->_name.c_str(), bpaction);
break;
case BREAK_EXPORT:
bpdata = bp->_address;
- debugPrintf("Execute script %d, export %d\n", bpdata >> 16, bpdata & 0xFFFF);
+ debugPrintf("Execute script %d, export %d%s\n", bpdata >> 16, bpdata & 0xFFFF, bpaction);
break;
case BREAK_ADDRESS:
- debugPrintf("Execute address %04x:%04x\n", PRINT_REG(bp->_regAddress));
+ debugPrintf("Execute address %04x:%04x%s\n", PRINT_REG(bp->_regAddress), bpaction);
}
i++;
@@ -3798,6 +3813,59 @@ bool Console::cmdBreakpointDelete(int argc, const char **argv) {
return true;
}
+bool Console::cmdBreakpointAction(int argc, const char **argv) {
+ bool usage = false;
+
+ if (argc != 3) {
+ usage = true;
+ }
+
+ Common::String arg;
+ if (argc >= 3)
+ arg = argv[2];
+
+ BreakpointAction bpaction;
+ if (arg == "break")
+ bpaction = BREAK_BREAK;
+ else if (arg == "log")
+ bpaction = BREAK_LOG;
+ else if (arg == "bt")
+ bpaction = BREAK_BACKTRACE;
+ 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("<index> * will process all breakpoints\n");
+ return true;
+ }
+
+ Common::List<Breakpoint>::iterator bp = _debugState._breakpoints.begin();
+ const Common::List<Breakpoint>::iterator end = _debugState._breakpoints.end();
+ if (strcmp(argv[1], "*") == 0) {
+ for (; bp != end; ++bp)
+ bp->_action = bpaction;
+ return true;
+ }
+
+ const int idx = atoi(argv[1]);
+
+ // Find the breakpoint at index idx.
+ for (int i = 0; bp != end && i < idx; ++bp, ++i) {
+ // do nothing
+ }
+
+ if (bp == end) {
+ debugPrintf("Invalid breakpoint index %i\n", idx);
+ return true;
+ }
+
+ bp->_action = bpaction;
+ return true;
+}
+
+
bool Console::cmdBreakpointMethod(int argc, const char **argv) {
if (argc != 2) {
debugPrintf("Sets a breakpoint on execution of a specified method/selector.\n");
@@ -3814,6 +3882,7 @@ bool Console::cmdBreakpointMethod(int argc, const char **argv) {
Breakpoint bp;
bp._type = BREAK_SELECTOREXEC;
bp._name = argv[1];
+ bp._action = BREAK_BREAK;
_debugState._breakpoints.push_back(bp);
_debugState._activeBreakpointTypes |= BREAK_SELECTOREXEC;
@@ -3831,6 +3900,7 @@ bool Console::cmdBreakpointRead(int argc, const char **argv) {
Breakpoint bp;
bp._type = BREAK_SELECTORREAD;
bp._name = argv[1];
+ bp._action = BREAK_BREAK;
_debugState._breakpoints.push_back(bp);
_debugState._activeBreakpointTypes |= BREAK_SELECTORREAD;
@@ -3848,6 +3918,7 @@ bool Console::cmdBreakpointWrite(int argc, const char **argv) {
Breakpoint bp;
bp._type = BREAK_SELECTORWRITE;
bp._name = argv[1];
+ bp._action = BREAK_BREAK;
_debugState._breakpoints.push_back(bp);
_debugState._activeBreakpointTypes |= BREAK_SELECTORWRITE;
@@ -3894,6 +3965,7 @@ bool Console::cmdBreakpointFunction(int argc, const char **argv) {
bp._type = BREAK_EXPORT;
// script number, export number
bp._address = (atoi(argv[1]) << 16 | atoi(argv[2]));
+ bp._action = BREAK_BREAK;
_debugState._breakpoints.push_back(bp);
_debugState._activeBreakpointTypes |= BREAK_EXPORT;
@@ -3919,6 +3991,7 @@ bool Console::cmdBreakpointAddress(int argc, const char **argv) {
Breakpoint bp;
bp._type = BREAK_ADDRESS;
bp._regAddress = make_reg32(addr.getSegment(), addr.getOffset());
+ bp._action = BREAK_BREAK;
_debugState._breakpoints.push_back(bp);
_debugState._activeBreakpointTypes |= BREAK_ADDRESS;
diff --git a/engines/sci/console.h b/engines/sci/console.h
index 1bb86b9bee..d0faf8a030 100644
--- a/engines/sci/console.h
+++ b/engines/sci/console.h
@@ -149,6 +149,7 @@ private:
// Breakpoints
bool cmdBreakpointList(int argc, const char **argv);
bool cmdBreakpointDelete(int argc, const char **argv);
+ bool cmdBreakpointAction(int argc, const char **argv);
bool cmdBreakpointMethod(int argc, const char **argv);
bool cmdBreakpointRead(int argc, const char **argv);
bool cmdBreakpointWrite(int argc, const char **argv);
diff --git a/engines/sci/debug.h b/engines/sci/debug.h
index b8557bb493..03ab594e0d 100644
--- a/engines/sci/debug.h
+++ b/engines/sci/debug.h
@@ -46,11 +46,18 @@ enum BreakpointType {
BREAK_ADDRESS = 1 << 4 // break when pc is at this address
};
+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
+};
+
struct Breakpoint {
BreakpointType _type;
uint32 _address; ///< Breakpoints on exports
reg32_t _regAddress; ///< Breakpoints on addresses
Common::String _name; ///< Breakpoints on selector names
+ BreakpointAction _action;
};
enum DebugSeeking {
diff --git a/engines/sci/engine/scriptdebug.cpp b/engines/sci/engine/scriptdebug.cpp
index a4392983a1..c5a617a17a 100644
--- a/engines/sci/engine/scriptdebug.cpp
+++ b/engines/sci/engine/scriptdebug.cpp
@@ -28,6 +28,7 @@
#include "sci/engine/state.h"
#include "sci/engine/kernel.h"
#include "sci/engine/script.h"
+#include "sci/engine/scriptdebug.h"
namespace Sci {
@@ -690,8 +691,12 @@ bool SciEngine::checkSelectorBreakpoint(BreakpointType breakpointType, reg_t sen
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));
- _debugState.debugging = true;
- _debugState.breakpointWasHit = true;
+ if (bpIter->_action == BREAK_BREAK) {
+ _debugState.debugging = true;
+ _debugState.breakpointWasHit = true;
+ } else if (bpIter->_action == BREAK_BACKTRACE) {
+ logBacktrace();
+ }
return true;
}
}
@@ -706,8 +711,12 @@ bool SciEngine::checkExportBreakpoint(uint16 script, uint16 pubfunct) {
for (bp = _debugState._breakpoints.begin(); bp != _debugState._breakpoints.end(); ++bp) {
if (bp->_type == BREAK_EXPORT && bp->_address == bpaddress) {
_console->debugPrintf("Break on script %d, export %d\n", script, pubfunct);
- _debugState.debugging = true;
- _debugState.breakpointWasHit = true;
+ if (bp->_action == BREAK_BREAK) {
+ _debugState.debugging = true;
+ _debugState.breakpointWasHit = true;
+ } else if (bp->_action == BREAK_BACKTRACE) {
+ logBacktrace();
+ }
return true;
}
}
@@ -722,8 +731,12 @@ bool SciEngine::checkAddressBreakpoint(const reg32_t &address) {
for (bp = _debugState._breakpoints.begin(); bp != _debugState._breakpoints.end(); ++bp) {
if (bp->_type == BREAK_ADDRESS && bp->_regAddress == address) {
_console->debugPrintf("Break at %04x:%04x\n", PRINT_REG(address));
- _debugState.debugging = true;
- _debugState.breakpointWasHit = true;
+ if (bp->_action == BREAK_BREAK) {
+ _debugState.debugging = true;
+ _debugState.breakpointWasHit = true;
+ } else if (bp->_action == BREAK_BACKTRACE) {
+ logBacktrace();
+ }
return true;
}
}