aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Kiewitz2010-09-02 09:05:08 +0000
committerMartin Kiewitz2010-09-02 09:05:08 +0000
commitcf3289ee3f11f37a2459da34d45c868a07133e76 (patch)
tree3804b2e1f08d3a7ad32efc031be4da584970ead2
parent9324a80d93621894ce6f618778015944f3c72b11 (diff)
downloadscummvm-rg350-cf3289ee3f11f37a2459da34d45c868a07133e76.tar.gz
scummvm-rg350-cf3289ee3f11f37a2459da34d45c868a07133e76.tar.bz2
scummvm-rg350-cf3289ee3f11f37a2459da34d45c868a07133e76.zip
SCI: adding "bpr" and "bpw" debug commands
"bpr" breakpoint on reading of selectors "bpw" breakpoint of writing of selectors "bpx" is now breakpoint on executing of selectors only svn-id: r52490
-rw-r--r--engines/sci/console.cpp55
-rw-r--r--engines/sci/console.h2
-rw-r--r--engines/sci/debug.h6
-rw-r--r--engines/sci/engine/vm.cpp112
-rw-r--r--engines/sci/sci.h2
5 files changed, 115 insertions, 62 deletions
diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp
index 7acbe56a12..6246754ec4 100644
--- a/engines/sci/console.cpp
+++ b/engines/sci/console.cpp
@@ -178,6 +178,10 @@ Console::Console(SciEngine *engine) : GUI::Debugger(),
DCmd_Register("bc", WRAP_METHOD(Console, cmdBreakpointDelete)); // alias
DCmd_Register("bp_method", WRAP_METHOD(Console, cmdBreakpointMethod));
DCmd_Register("bpx", WRAP_METHOD(Console, cmdBreakpointMethod)); // alias
+ DCmd_Register("bp_read", WRAP_METHOD(Console, cmdBreakpointRead));
+ DCmd_Register("bpr", WRAP_METHOD(Console, cmdBreakpointRead)); // alias
+ DCmd_Register("bp_write", WRAP_METHOD(Console, cmdBreakpointWrite));
+ DCmd_Register("bpw", WRAP_METHOD(Console, cmdBreakpointWrite)); // alias
DCmd_Register("bp_kernel", WRAP_METHOD(Console, cmdBreakpointKernel));
DCmd_Register("bpk", WRAP_METHOD(Console, cmdBreakpointKernel)); // alias
DCmd_Register("bp_function", WRAP_METHOD(Console, cmdBreakpointFunction));
@@ -389,7 +393,9 @@ 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_method / bpx - Sets a breakpoint on the execution or access of a specified method/selector\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");
+ DebugPrintf(" bp_write / bpw - Sets a breakpoint on writing to a specified selector\n");
DebugPrintf(" bp_kernel / bpk - Sets a breakpoint on execution of a kernel function\n");
DebugPrintf(" bp_function / bpe - Sets a breakpoint on the execution of the specified exported function\n");
DebugPrintf("\n");
@@ -2741,9 +2747,15 @@ bool Console::cmdBreakpointList(int argc, const char **argv) {
for (; bp != end; ++bp) {
DebugPrintf(" #%i: ", i);
switch (bp->type) {
- case BREAK_SELECTOR:
+ case BREAK_SELECTOREXEC:
DebugPrintf("Execute %s\n", bp->name.c_str());
break;
+ case BREAK_SELECTORREAD:
+ DebugPrintf("Read %s\n", bp->name.c_str());
+ break;
+ case BREAK_SELECTORWRITE:
+ DebugPrintf("Write %s\n", bp->name.c_str());
+ break;
case BREAK_EXPORT:
bpdata = bp->address;
DebugPrintf("Execute script %d, export %d\n", bpdata >> 16, bpdata & 0xFFFF);
@@ -2803,7 +2815,7 @@ bool Console::cmdBreakpointDelete(int argc, const char **argv) {
bool Console::cmdBreakpointMethod(int argc, const char **argv) {
if (argc != 2) {
- DebugPrintf("Sets a breakpoint on execution/access of a specified method/selector.\n");
+ DebugPrintf("Sets a breakpoint on execution of a specified method/selector.\n");
DebugPrintf("Usage: %s <name>\n", argv[0]);
DebugPrintf("Example: %s ego::doit\n", argv[0]);
DebugPrintf("May also be used to set a breakpoint that applies whenever an object\n");
@@ -2815,12 +2827,45 @@ bool Console::cmdBreakpointMethod(int argc, const char **argv) {
Thus, we can't check whether the command argument is a valid method name.
A breakpoint set on an invalid method name will just never trigger. */
Breakpoint bp;
- bp.type = BREAK_SELECTOR;
+ bp.type = BREAK_SELECTOREXEC;
bp.name = argv[1];
_debugState._breakpoints.push_back(bp);
- _debugState._activeBreakpointTypes |= BREAK_SELECTOR;
+ _debugState._activeBreakpointTypes |= BREAK_SELECTOREXEC;
+ return true;
+}
+bool Console::cmdBreakpointRead(int argc, const char **argv) {
+ if (argc != 2) {
+ DebugPrintf("Sets a breakpoint on reading of a specified selector.\n");
+ DebugPrintf("Usage: %s <name>\n", argv[0]);
+ DebugPrintf("Example: %s ego::view\n", argv[0]);
+ return true;
+ }
+
+ Breakpoint bp;
+ bp.type = BREAK_SELECTORREAD;
+ bp.name = argv[1];
+
+ _debugState._breakpoints.push_back(bp);
+ _debugState._activeBreakpointTypes |= BREAK_SELECTORREAD;
+ return true;
+}
+
+bool Console::cmdBreakpointWrite(int argc, const char **argv) {
+ if (argc != 2) {
+ DebugPrintf("Sets a breakpoint on writing of a specified selector.\n");
+ DebugPrintf("Usage: %s <name>\n", argv[0]);
+ DebugPrintf("Example: %s ego::view\n", argv[0]);
+ return true;
+ }
+
+ Breakpoint bp;
+ bp.type = BREAK_SELECTORWRITE;
+ bp.name = argv[1];
+
+ _debugState._breakpoints.push_back(bp);
+ _debugState._activeBreakpointTypes |= BREAK_SELECTORWRITE;
return true;
}
diff --git a/engines/sci/console.h b/engines/sci/console.h
index 60599ea783..444443154c 100644
--- a/engines/sci/console.h
+++ b/engines/sci/console.h
@@ -135,6 +135,8 @@ private:
bool cmdBreakpointList(int argc, const char **argv);
bool cmdBreakpointDelete(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);
bool cmdBreakpointKernel(int argc, const char **argv);
bool cmdBreakpointFunction(int argc, const char **argv);
// VM
diff --git a/engines/sci/debug.h b/engines/sci/debug.h
index 5cf0e38fbc..d9959f0b7f 100644
--- a/engines/sci/debug.h
+++ b/engines/sci/debug.h
@@ -37,13 +37,15 @@ enum BreakpointType {
* Break when selector is executed. data contains (char *) selector name
* (in the format Object::Method)
*/
- BREAK_SELECTOR = 1,
+ BREAK_SELECTOREXEC = 1 << 0, // break when selector gets executed
+ BREAK_SELECTORREAD = 1 << 1, // break when selector gets executed
+ BREAK_SELECTORWRITE = 1 << 2, // break when selector gets executed
/**
* Break when an exported function is called. data contains
* script_no << 16 | export_no.
*/
- BREAK_EXPORT = 2
+ BREAK_EXPORT = 1 << 3
};
struct Breakpoint {
diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp
index e841a3877f..39d919f333 100644
--- a/engines/sci/engine/vm.cpp
+++ b/engines/sci/engine/vm.cpp
@@ -366,27 +366,24 @@ struct CallsStruct {
int type; /**< Same as ExecStack.type */
};
-bool SciEngine::checkSelectorBreakpoint(reg_t send_obj, int selector) {
- if (_debugState._activeBreakpointTypes & BREAK_SELECTOR) {
- char method_name[256];
-
- sprintf(method_name, "%s::%s", _gamestate->_segMan->getObjectName(send_obj), getKernel()->getSelectorName(selector).c_str());
-
- Common::List<Breakpoint>::const_iterator bp;
- for (bp = _debugState._breakpoints.begin(); bp != _debugState._breakpoints.end(); ++bp) {
- int cmplen = bp->name.size();
- if (bp->name.lastChar() != ':')
- cmplen = 256;
-
- if (bp->type == BREAK_SELECTOR && !strncmp(bp->name.c_str(), method_name, cmplen)) {
- _console->DebugPrintf("Break on %s (in [%04x:%04x])\n", method_name, PRINT_REG(send_obj));
- _debugState.debugging = true;
- _debugState.breakpointWasHit = true;
- return true;
- }
+bool SciEngine::checkSelectorBreakpoint(BreakpointType breakpointType, reg_t send_obj, int selector) {
+ char method_name[256];
+
+ sprintf(method_name, "%s::%s", _gamestate->_segMan->getObjectName(send_obj), getKernel()->getSelectorName(selector).c_str());
+
+ Common::List<Breakpoint>::const_iterator bp;
+ for (bp = _debugState._breakpoints.begin(); bp != _debugState._breakpoints.end(); ++bp) {
+ int cmplen = bp->name.size();
+ if (bp->name.lastChar() != ':')
+ cmplen = 256;
+
+ if (bp->type == breakpointType && !strncmp(bp->name.c_str(), method_name, cmplen)) {
+ _console->DebugPrintf("Break on %s (in [%04x:%04x])\n", method_name, PRINT_REG(send_obj));
+ _debugState.debugging = true;
+ _debugState.breakpointWasHit = true;
+ return true;
}
}
-
return false;
}
@@ -399,12 +396,13 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt
int selector;
int argc;
int origin = s->_executionStack.size()-1; // Origin: Used for debugging
- bool printSendActions = false;
// We return a pointer to the new active ExecStack
// The selector calls we catch are stored below:
Common::Stack<CallsStruct> sendCalls;
+ int activeBreakpointTypes = g_sci->_debugState._activeBreakpointTypes;
+
while (framesize > 0) {
selector = validate_arithmetic(*argp++);
argc = validate_arithmetic(*argp);
@@ -413,9 +411,6 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt
error("send_selector(): More than 0x800 arguments to function call");
}
- // Check if a breakpoint is set on this method
- printSendActions = g_sci->checkSelectorBreakpoint(send_obj, selector);
-
#ifdef VM_DEBUG_SEND
printf("Send to %04x:%04x (%s), selector %04x (%s):", PRINT_REG(send_obj),
s->_segMan->getObjectName(send_obj), selector,
@@ -439,18 +434,23 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt
// argc == 0: read selector
// argc != 0: write selector
- if (printSendActions && !argc) { // read selector
- debug("[read selector]\n");
- printSendActions = false;
- }
-
- if (printSendActions && argc) {
- reg_t oldReg = *varp.getPointer(s->_segMan);
- reg_t newReg = argp[1];
- warning("[write to selector (%s:%s): change %04x:%04x to %04x:%04x]\n",
- s->_segMan->getObjectName(send_obj), g_sci->getKernel()->getSelectorName(selector).c_str(),
- PRINT_REG(oldReg), PRINT_REG(newReg));
- printSendActions = false;
+ if (!argc) {
+ // read selector
+ if (activeBreakpointTypes & BREAK_SELECTORREAD) {
+ if (g_sci->checkSelectorBreakpoint(BREAK_SELECTORREAD, send_obj, selector))
+ debug("[read selector]\n");
+ }
+ } else {
+ // write selector
+ if (activeBreakpointTypes & BREAK_SELECTORWRITE) {
+ if (g_sci->checkSelectorBreakpoint(BREAK_SELECTORWRITE, send_obj, selector)) {
+ reg_t oldReg = *varp.getPointer(s->_segMan);
+ reg_t newReg = argp[1];
+ warning("[write to selector (%s:%s): change %04x:%04x to %04x:%04x]\n",
+ s->_segMan->getObjectName(send_obj), g_sci->getKernel()->getSelectorName(selector).c_str(),
+ PRINT_REG(oldReg), PRINT_REG(newReg));
+ }
+ }
}
if (argc > 1) {
@@ -483,6 +483,8 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt
case kSelectorMethod:
#ifdef VM_DEBUG_SEND
+ if (_debugState._activeBreakpointTypes & BREAK_SELECTOREXEC)
+ g_sci->checkSelectorBreakpoint(BREAK_SELECTOREXEC, send_obj, selector);
printf("Funcselector(");
for (int i = 0; i < argc; i++) {
printf("%04x:%04x", PRINT_REG(argp[i+1]));
@@ -491,30 +493,32 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt
}
printf(") at %04x:%04x\n", PRINT_REG(funcp));
#endif // VM_DEBUG_SEND
- if (printSendActions) {
- printf("[invoke selector]");
#ifndef VM_DEBUG_SEND
- int displaySize = 0;
- for (int argNr = 1; argNr <= argc; argNr++) {
- if (argNr == 1)
- printf(" - ");
- reg_t curParam = argp[argNr];
- if (curParam.segment) {
- printf("[%04x:%04x] ", PRINT_REG(curParam));
- displaySize += 12;
- } else {
- printf("[%04x] ", curParam.offset);
- displaySize += 7;
- }
- if (displaySize > 50) {
- if (argNr < argc)
- printf("...");
- break;
+ if (activeBreakpointTypes & BREAK_SELECTOREXEC) {
+ if (g_sci->checkSelectorBreakpoint(BREAK_SELECTOREXEC, send_obj, selector)) {
+ printf("[execute selector]");
+
+ int displaySize = 0;
+ for (int argNr = 1; argNr <= argc; argNr++) {
+ if (argNr == 1)
+ printf(" - ");
+ reg_t curParam = argp[argNr];
+ if (curParam.segment) {
+ printf("[%04x:%04x] ", PRINT_REG(curParam));
+ displaySize += 12;
+ } else {
+ printf("[%04x] ", curParam.offset);
+ displaySize += 7;
+ }
+ if (displaySize > 50) {
+ if (argNr < argc)
+ printf("...");
+ break;
+ }
}
}
#endif
printf("\n");
- printSendActions = false;
}
{
diff --git a/engines/sci/sci.h b/engines/sci/sci.h
index a620f6cd09..7239abad17 100644
--- a/engines/sci/sci.h
+++ b/engines/sci/sci.h
@@ -260,7 +260,7 @@ public:
void scriptDebug();
bool checkExportBreakpoint(uint16 script, uint16 pubfunct);
- bool checkSelectorBreakpoint(reg_t send_obj, int selector);
+ bool checkSelectorBreakpoint(BreakpointType breakpointType, reg_t send_obj, int selector);
void patchGameSaveRestore(SegManager *segMan);