JSBool jsd_SetInterruptHook(JSDContext* jsdc, JSD_ExecutionHookProc hook, void* callerdata) { JSD_LOCK(); jsdc->interruptHookData = callerdata; jsdc->interruptHook = hook; JS_SetInterrupt(jsdc->jsrt, jsd_InterruptHandler, (void*) jsdc); JSD_UNLOCK(); return JS_TRUE; }
/* * call-seq: * debugger=(debugger) * * Sets a debugger object */ static VALUE set_debugger(VALUE self, VALUE debugger) { JohnsonRuntime* runtime; JSDebugHooks* debug_hooks; rb_iv_set(self, "@debugger", debugger); Data_Get_Struct(self, JohnsonRuntime, runtime); Data_Get_Struct(debugger, JSDebugHooks, debug_hooks); JSContext * context = johnson_get_current_context(runtime); JS_SetInterrupt( runtime->js, debug_hooks->interruptHandler, debug_hooks->interruptHandlerData); JS_SetNewScriptHook( runtime->js, debug_hooks->newScriptHook, debug_hooks->newScriptHookData); JS_SetDestroyScriptHook( runtime->js, debug_hooks->destroyScriptHook, debug_hooks->destroyScriptHookData); JS_SetDebuggerHandler( runtime->js, debug_hooks->debuggerHandler, debug_hooks->debuggerHandlerData); JS_SetSourceHandler( runtime->js, debug_hooks->sourceHandler, debug_hooks->sourceHandlerData); JS_SetExecuteHook( runtime->js, debug_hooks->executeHook, debug_hooks->executeHookData); JS_SetCallHook( runtime->js, debug_hooks->callHook, debug_hooks->callHookData); JS_SetObjectHook( runtime->js, debug_hooks->objectHook, debug_hooks->objectHookData); JS_SetThrowHook( runtime->js, debug_hooks->throwHook, debug_hooks->throwHookData); JS_SetDebugErrorHook( runtime->js, debug_hooks->debugErrorHook, debug_hooks->debugErrorHookData); JS_SetContextDebugHooks(context, debug_hooks); return debugger; }
void CThreadDebugger::Initialize(uint id, std::string name, ScriptInterface* pScriptInterface, CDebuggingServer* pDebuggingServer) { ENSURE(id != 0); m->m_ID = id; m->m_Name = name; m->m_pScriptInterface = pScriptInterface; m->m_pDebuggingServer = pDebuggingServer; JS_SetExecuteHook(m->m_pScriptInterface->GetRuntime(), CallHook_, (void*)this); JS_SetCallHook(m->m_pScriptInterface->GetRuntime(), CallHook_, (void*)this); JS_SetNewScriptHook(m->m_pScriptInterface->GetRuntime(), NewScriptHook_, (void*)this); JS_SetDestroyScriptHook(m->m_pScriptInterface->GetRuntime(), DestroyScriptHook_, (void*)this); JS_SetThrowHook(m->m_pScriptInterface->GetRuntime(), ThrowHandler_, (void*)this); if (m->m_pDebuggingServer->GetSettingSimultaneousThreadBreak()) { // Setup a handler to check for break-requests from the DebuggingServer regularly JS_SetInterrupt(m->m_pScriptInterface->GetRuntime(), CheckForBreakRequestHandler_, (void*)this); } }
JSTrapStatus CThreadDebugger::BreakHandler(JSContext* cx, JSScript* script, jsbytecode* pc, jsval* UNUSED(rval), jsval UNUSED(closure), BREAK_SRC breakSrc) { uint line = JS_PCToLineNumber(cx, script, pc); std::string filename(JS_GetScriptFilename(cx, script)); SetIsInBreak(true); SaveCallstack(); SetLastBreakLine(line); SetBreakFileName(filename); *m->m_pLastBreakFrame = NULL; if (breakSrc == BREAK_SRC_INTERRUP) { JS_ClearInterrupt(m->m_pScriptInterface->GetRuntime(), NULL, NULL); JS_SetSingleStepMode(cx, script, false); } if (m->m_pDebuggingServer->GetSettingSimultaneousThreadBreak()) { m->m_pDebuggingServer->SetBreakRequestedByThread(true); } // Wait until the user continues the execution while (1) { DBGCMD nextDbgCmd = GetNextDbgCmd(); while (!m->m_StackInfoRequests.empty()) { StackInfoRequest request = m->m_StackInfoRequests.front(); SaveStackFrameData(request.requestType, request.nestingLevel); SDL_SemPost(request.semaphore); m->m_StackInfoRequests.pop(); } if (nextDbgCmd == DBG_CMD_NONE) { // Wait a while before checking for new m_NextDbgCmd again. // We don't want this loop to take 100% of a CPU core for each thread that is in break mode. // On the other hande we don't want the debugger to become unresponsive. SDL_Delay(100); } else if (nextDbgCmd == DBG_CMD_SINGLESTEP || nextDbgCmd == DBG_CMD_STEPINTO || nextDbgCmd == DBG_CMD_STEPOUT) { JSStackFrame* iter = NULL; *m->m_pLastBreakFrame = JS_FrameIterator(m->m_pScriptInterface->GetContext(), &iter); if (!JS_SetSingleStepMode(cx, script, true)) LOGERROR(L"JS_SetSingleStepMode returned false!"); // TODO: When can this happen? else { if (nextDbgCmd == DBG_CMD_SINGLESTEP) { JS_SetInterrupt(m->m_pScriptInterface->GetRuntime(), StepHandler_, this); break; } else if (nextDbgCmd == DBG_CMD_STEPINTO) { JS_SetInterrupt(m->m_pScriptInterface->GetRuntime(), StepIntoHandler_, this); break; } else if (nextDbgCmd == DBG_CMD_STEPOUT) { JS_SetInterrupt(m->m_pScriptInterface->GetRuntime(), StepOutHandler_, this); break; } } } else if (nextDbgCmd == DBG_CMD_CONTINUE) { if (!JS_SetSingleStepMode(cx, script, true)) LOGERROR(L"JS_SetSingleStepMode returned false!"); // TODO: When can this happen? else { // Setup a handler to check for break-requests from the DebuggingServer regularly JS_SetInterrupt(m->m_pScriptInterface->GetRuntime(), CheckForBreakRequestHandler_, this); } break; } else debug_warn("Invalid DBGCMD found in CThreadDebugger::BreakHandler!"); } ClearTrapsToRemove(); SetAllNewTraps(); SetNextDbgCmd(DBG_CMD_NONE); SetIsInBreak(false); SetBreakFileName(""); // All saved stack data becomes invalid { CScopeLock lock(m->m_Mutex); m->m_StackFrameData.clear(); } return JSTRAP_CONTINUE; }