diff options
author | Martin Kiewitz | 2010-09-02 09:05:08 +0000 |
---|---|---|
committer | Martin Kiewitz | 2010-09-02 09:05:08 +0000 |
commit | cf3289ee3f11f37a2459da34d45c868a07133e76 (patch) | |
tree | 3804b2e1f08d3a7ad32efc031be4da584970ead2 | |
parent | 9324a80d93621894ce6f618778015944f3c72b11 (diff) | |
download | scummvm-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.cpp | 55 | ||||
-rw-r--r-- | engines/sci/console.h | 2 | ||||
-rw-r--r-- | engines/sci/debug.h | 6 | ||||
-rw-r--r-- | engines/sci/engine/vm.cpp | 112 | ||||
-rw-r--r-- | engines/sci/sci.h | 2 |
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); |