From: Igor Kulaychuk Date: Thu, 18 Jan 2018 19:41:37 +0000 (+0300) Subject: Refactor Debugger into the ManagedDebugger class which implements Debugger interface X-Git-Tag: submit/tizen/20180620.071641~40 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=b61770ff4a54c763cf51b06b96fbd932a162be01;p=sdk%2Ftools%2Fnetcoredbg.git Refactor Debugger into the ManagedDebugger class which implements Debugger interface --- diff --git a/src/debug/netcoredbg/breakpoints.cpp b/src/debug/netcoredbg/breakpoints.cpp index 3845a0f..a96e99c 100644 --- a/src/debug/netcoredbg/breakpoints.cpp +++ b/src/debug/netcoredbg/breakpoints.cpp @@ -71,7 +71,7 @@ HRESULT Breakpoints::HitBreakpoint(ICorDebugThread *pThread, Breakpoint &breakpo return E_FAIL; } -void Debugger::InsertExceptionBreakpoint(const std::string &name, Breakpoint &breakpoint) +void ManagedDebugger::InsertExceptionBreakpoint(const std::string &name, Breakpoint &breakpoint) { m_breakpoints.InsertExceptionBreakpoint(name, breakpoint); } @@ -188,7 +188,7 @@ HRESULT Breakpoints::ResolveBreakpoint(ManagedBreakpoint &bp) return S_OK; } -HRESULT Debugger::SetBreakpoints( +HRESULT ManagedDebugger::SetBreakpoints( std::string filename, const std::vector &lines, std::vector &breakpoints) diff --git a/src/debug/netcoredbg/commands.cpp b/src/debug/netcoredbg/commands.cpp index 8b388ea..e574ded 100644 --- a/src/debug/netcoredbg/commands.cpp +++ b/src/debug/netcoredbg/commands.cpp @@ -161,89 +161,6 @@ void MIProtocol::EmitBreakpointEvent(BreakpointEvent event) } } -HRESULT Debugger::SetupStep(ICorDebugThread *pThread, Debugger::StepType stepType) -{ - HRESULT Status; - - ToRelease pStepper; - IfFailRet(pThread->CreateStepper(&pStepper)); - - CorDebugIntercept mask = (CorDebugIntercept)(INTERCEPT_ALL & ~(INTERCEPT_SECURITY | INTERCEPT_CLASS_INIT)); - IfFailRet(pStepper->SetInterceptMask(mask)); - - CorDebugUnmappedStop stopMask = STOP_NONE; - IfFailRet(pStepper->SetUnmappedStopMask(stopMask)); - - ToRelease pStepper2; - IfFailRet(pStepper->QueryInterface(IID_ICorDebugStepper2, (LPVOID *)&pStepper2)); - - IfFailRet(pStepper2->SetJMC(IsJustMyCode())); - - if (stepType == STEP_OUT) - { - IfFailRet(pStepper->StepOut()); - return S_OK; - } - - BOOL bStepIn = stepType == STEP_IN; - - COR_DEBUG_STEP_RANGE range; - if (SUCCEEDED(m_modules.GetStepRangeFromCurrentIP(pThread, &range))) - { - IfFailRet(pStepper->StepRange(bStepIn, &range, 1)); - } else { - IfFailRet(pStepper->Step(bStepIn)); - } - - return S_OK; -} - -HRESULT Debugger::StepCommand(int threadId, - StepType stepType) -{ - HRESULT Status; - ToRelease pThread; - IfFailRet(m_pProcess->GetThread(threadId, &pThread)); - DisableAllSteppers(m_pProcess); - IfFailRet(SetupStep(pThread, stepType)); - IfFailRet(m_pProcess->Continue(0)); - return S_OK; -} - -HRESULT Debugger::Continue() -{ - if (!m_pProcess) - return E_FAIL; - return m_pProcess->Continue(0); -} - -HRESULT Debugger::Pause() -{ - if (!m_pProcess) - return E_FAIL; - HRESULT Status = m_pProcess->Stop(0); - if (Status == S_OK) - m_protocol->EmitStoppedEvent(StoppedEvent(StopPause, 0)); - return Status; -} - -HRESULT Debugger::GetThreads(std::vector &threads) -{ - if (!m_pProcess) - return E_FAIL; - return GetThreadsState(m_pProcess, threads); -} - -HRESULT Debugger::GetStackTrace(int threadId, int lowFrame, int highFrame, std::vector &stackFrames) -{ - HRESULT Status; - if (!m_pProcess) - return E_FAIL; - ToRelease pThread; - IfFailRet(m_pProcess->GetThread(threadId, &pThread)); - return GetStackTrace(pThread, lowFrame, highFrame, stackFrames); -} - HRESULT MIProtocol::StepCommand(const std::vector &args, std::string &output, Debugger::StepType stepType) diff --git a/src/debug/netcoredbg/debugger.h b/src/debug/netcoredbg/debugger.h index 0e69ae7..ec5ee27 100644 --- a/src/debug/netcoredbg/debugger.h +++ b/src/debug/netcoredbg/debugger.h @@ -12,6 +12,7 @@ class ManagedCallback; class Protocol; +class Debugger; enum ValueKind { @@ -314,6 +315,34 @@ public: STEP_OUT }; + virtual ~Debugger() {} + + virtual bool IsJustMyCode() = 0; + virtual void SetJustMyCode(bool enable) = 0; + + virtual HRESULT RunProcess(std::string fileExec, std::vector execArgs) = 0; + + virtual HRESULT AttachToProcess(int pid) = 0; + virtual HRESULT DetachFromProcess() = 0; + virtual HRESULT TerminateProcess() = 0; + + virtual int GetLastStoppedThreadId() = 0; + + virtual HRESULT Continue() = 0; + virtual HRESULT Pause() = 0; + virtual HRESULT GetThreads(std::vector &threads) = 0; + virtual HRESULT SetBreakpoints(std::string filename, const std::vector &lines, std::vector &breakpoints) = 0; + virtual void InsertExceptionBreakpoint(const std::string &name, Breakpoint &breakpoint) = 0; + virtual HRESULT GetStackTrace(int threadId, int lowFrame, int highFrame, std::vector &stackFrames) = 0; + virtual HRESULT StepCommand(int threadId, StepType stepType) = 0; + virtual HRESULT GetScopes(uint64_t frameId, std::vector &scopes) = 0; + virtual HRESULT GetVariables(uint32_t variablesReference, VariablesFilter filter, int start, int count, std::vector &variables) = 0; + virtual int GetNamedVariables(uint32_t variablesReference) = 0; + virtual HRESULT Evaluate(uint64_t frameId, const std::string &expression, Variable &variable) = 0; +}; + +class ManagedDebugger : public Debugger +{ private: friend class ManagedCallback; enum ProcessAttachedState @@ -367,33 +396,33 @@ private: HRESULT GetStackTrace(ICorDebugThread *pThread, int lowFrame, int highFrame, std::vector &stackFrames); HRESULT GetFrameLocation(ICorDebugFrame *pFrame, int threadId, uint32_t level, StackFrame &stackFrame); public: - Debugger(); - ~Debugger(); - - bool IsJustMyCode() { return m_justMyCode; } - void SetJustMyCode(bool enable) { m_justMyCode = enable; } + ManagedDebugger(); + ~ManagedDebugger() override; void SetProtocol(Protocol *protocol) { m_protocol = protocol; } - HRESULT RunProcess(std::string fileExec, std::vector execArgs); + bool IsJustMyCode() override { return m_justMyCode; } + void SetJustMyCode(bool enable) override { m_justMyCode = enable; } - HRESULT AttachToProcess(int pid); - HRESULT DetachFromProcess(); - HRESULT TerminateProcess(); + HRESULT RunProcess(std::string fileExec, std::vector execArgs) override; - int GetLastStoppedThreadId(); + HRESULT AttachToProcess(int pid) override; + HRESULT DetachFromProcess() override; + HRESULT TerminateProcess() override; - HRESULT Continue(); - HRESULT Pause(); - HRESULT GetThreads(std::vector &threads); - HRESULT SetBreakpoints(std::string filename, const std::vector &lines, std::vector &breakpoints); - void InsertExceptionBreakpoint(const std::string &name, Breakpoint &breakpoint); - HRESULT GetStackTrace(int threadId, int lowFrame, int highFrame, std::vector &stackFrames); - HRESULT StepCommand(int threadId, StepType stepType); - HRESULT GetScopes(uint64_t frameId, std::vector &scopes); - HRESULT GetVariables(uint32_t variablesReference, VariablesFilter filter, int start, int count, std::vector &variables); - int GetNamedVariables(uint32_t variablesReference); - HRESULT Evaluate(uint64_t frameId, const std::string &expression, Variable &variable); + int GetLastStoppedThreadId() override; + + HRESULT Continue() override; + HRESULT Pause() override; + HRESULT GetThreads(std::vector &threads) override; + HRESULT SetBreakpoints(std::string filename, const std::vector &lines, std::vector &breakpoints) override; + void InsertExceptionBreakpoint(const std::string &name, Breakpoint &breakpoint) override; + HRESULT GetStackTrace(int threadId, int lowFrame, int highFrame, std::vector &stackFrames) override; + HRESULT StepCommand(int threadId, StepType stepType) override; + HRESULT GetScopes(uint64_t frameId, std::vector &scopes) override; + HRESULT GetVariables(uint32_t variablesReference, VariablesFilter filter, int start, int count, std::vector &variables) override; + int GetNamedVariables(uint32_t variablesReference) override; + HRESULT Evaluate(uint64_t frameId, const std::string &expression, Variable &variable) override; }; class Protocol @@ -422,7 +451,7 @@ class MIProtocol : public Protocol std::unordered_map m_vars; std::unordered_map > m_breakpoints; public: - void SetDebugger(Debugger *debugger) { m_debugger = debugger; m_debugger->SetProtocol(this); } + void SetDebugger(Debugger *debugger) { m_debugger = debugger; } static std::string EscapeMIValue(const std::string &str); MIProtocol() : m_exit(false), m_varCounter(0) {} diff --git a/src/debug/netcoredbg/frames.cpp b/src/debug/netcoredbg/frames.cpp index 0a73391..e83866e 100644 --- a/src/debug/netcoredbg/frames.cpp +++ b/src/debug/netcoredbg/frames.cpp @@ -55,7 +55,7 @@ static uint64_t FrameAddr(ICorDebugFrame *pFrame) return startAddr; } -HRESULT Debugger::GetFrameLocation(ICorDebugFrame *pFrame, int threadId, uint32_t level, StackFrame &stackFrame) +HRESULT ManagedDebugger::GetFrameLocation(ICorDebugFrame *pFrame, int threadId, uint32_t level, StackFrame &stackFrame) { HRESULT Status; @@ -387,7 +387,7 @@ static const char *GetInternalTypeName(CorDebugInternalFrameType frameType) } } -HRESULT Debugger::GetStackTrace(ICorDebugThread *pThread, int lowFrame, int highFrame, std::vector &stackFrames) +HRESULT ManagedDebugger::GetStackTrace(ICorDebugThread *pThread, int lowFrame, int highFrame, std::vector &stackFrames) { HRESULT Status; std::stringstream ss; diff --git a/src/debug/netcoredbg/main.cpp b/src/debug/netcoredbg/main.cpp index 500e5c7..5cc3456 100644 --- a/src/debug/netcoredbg/main.cpp +++ b/src/debug/netcoredbg/main.cpp @@ -27,13 +27,13 @@ #undef __out -void Debugger::NotifyProcessCreated() +void ManagedDebugger::NotifyProcessCreated() { std::lock_guard lock(m_processAttachedMutex); m_processAttachedState = ProcessAttached; } -void Debugger::NotifyProcessExited() +void ManagedDebugger::NotifyProcessExited() { std::lock_guard lock(m_processAttachedMutex); m_processAttachedState = ProcessUnattached; @@ -41,7 +41,7 @@ void Debugger::NotifyProcessExited() m_processAttachedCV.notify_one(); } -void Debugger::WaitProcessExited() +void ManagedDebugger::WaitProcessExited() { std::unique_lock lock(m_processAttachedMutex); if (m_processAttachedState != ProcessUnattached) @@ -148,7 +148,7 @@ static HRESULT DisableAllSteppersInAppDomain(ICorDebugAppDomain *pAppDomain) return S_OK; } -HRESULT Debugger::DisableAllSteppers(ICorDebugProcess *pProcess) +HRESULT ManagedDebugger::DisableAllSteppers(ICorDebugProcess *pProcess) { HRESULT Status; @@ -203,7 +203,7 @@ HRESULT DisableAllBreakpointsAndSteppers(ICorDebugProcess *pProcess) return S_OK; } -void Debugger::SetLastStoppedThread(ICorDebugThread *pThread) +void ManagedDebugger::SetLastStoppedThread(ICorDebugThread *pThread) { DWORD threadId = 0; pThread->GetID(&threadId); @@ -212,7 +212,7 @@ void Debugger::SetLastStoppedThread(ICorDebugThread *pThread) m_lastStoppedThreadId = threadId; } -int Debugger::GetLastStoppedThreadId() +int ManagedDebugger::GetLastStoppedThreadId() { std::lock_guard lock(m_lastStoppedThreadIdMutex); return m_lastStoppedThreadId; @@ -254,7 +254,7 @@ static HRESULT GetExceptionInfo(ICorDebugThread *pThread, class ManagedCallback : public ICorDebugManagedCallback, ICorDebugManagedCallback2 { ULONG m_refCount; - Debugger &m_debugger; + ManagedDebugger &m_debugger; public: void HandleEvent(ICorDebugController *controller, const std::string &eventName) @@ -264,7 +264,7 @@ public: controller->Continue(0); } - ManagedCallback(Debugger &debugger) : m_refCount(1), m_debugger(debugger) {} + ManagedCallback(ManagedDebugger &debugger) : m_refCount(1), m_debugger(debugger) {} virtual ~ManagedCallback() {} // IUnknown @@ -645,7 +645,7 @@ public: // case DEBUG_EXCEPTION_UNHANDLED: cbTypeName = "UNHANDLED"; break; // default: cbTypeName = "?"; break; // } - // Debugger::Printf("*stopped,reason=\"exception-received2\",exception-stage=\"%s\"\n", + // ManagedDebugger::Printf("*stopped,reason=\"exception-received2\",exception-stage=\"%s\"\n", // cbTypeName); pAppDomain->Continue(0); return S_OK; @@ -668,7 +668,7 @@ public: /* [in] */ ICorDebugMDA *pMDA) { HandleEvent(pController, "MDANotification"); return S_OK; } }; -Debugger::Debugger() : +ManagedDebugger::ManagedDebugger() : m_processAttachedState(ProcessUnattached), m_evaluator(m_modules), m_breakpoints(m_modules), @@ -684,13 +684,95 @@ Debugger::Debugger() : { } -Debugger::~Debugger() +ManagedDebugger::~ManagedDebugger() { } -VOID Debugger::StartupCallback(IUnknown *pCordb, PVOID parameter, HRESULT hr) +HRESULT ManagedDebugger::SetupStep(ICorDebugThread *pThread, Debugger::StepType stepType) { - Debugger *self = static_cast(parameter); + HRESULT Status; + + ToRelease pStepper; + IfFailRet(pThread->CreateStepper(&pStepper)); + + CorDebugIntercept mask = (CorDebugIntercept)(INTERCEPT_ALL & ~(INTERCEPT_SECURITY | INTERCEPT_CLASS_INIT)); + IfFailRet(pStepper->SetInterceptMask(mask)); + + CorDebugUnmappedStop stopMask = STOP_NONE; + IfFailRet(pStepper->SetUnmappedStopMask(stopMask)); + + ToRelease pStepper2; + IfFailRet(pStepper->QueryInterface(IID_ICorDebugStepper2, (LPVOID *)&pStepper2)); + + IfFailRet(pStepper2->SetJMC(IsJustMyCode())); + + if (stepType == STEP_OUT) + { + IfFailRet(pStepper->StepOut()); + return S_OK; + } + + BOOL bStepIn = stepType == STEP_IN; + + COR_DEBUG_STEP_RANGE range; + if (SUCCEEDED(m_modules.GetStepRangeFromCurrentIP(pThread, &range))) + { + IfFailRet(pStepper->StepRange(bStepIn, &range, 1)); + } else { + IfFailRet(pStepper->Step(bStepIn)); + } + + return S_OK; +} + +HRESULT ManagedDebugger::StepCommand(int threadId, StepType stepType) +{ + HRESULT Status; + ToRelease pThread; + IfFailRet(m_pProcess->GetThread(threadId, &pThread)); + DisableAllSteppers(m_pProcess); + IfFailRet(SetupStep(pThread, stepType)); + IfFailRet(m_pProcess->Continue(0)); + return S_OK; +} + +HRESULT ManagedDebugger::Continue() +{ + if (!m_pProcess) + return E_FAIL; + return m_pProcess->Continue(0); +} + +HRESULT ManagedDebugger::Pause() +{ + if (!m_pProcess) + return E_FAIL; + HRESULT Status = m_pProcess->Stop(0); + if (Status == S_OK) + m_protocol->EmitStoppedEvent(StoppedEvent(StopPause, 0)); + return Status; +} + +HRESULT ManagedDebugger::GetThreads(std::vector &threads) +{ + if (!m_pProcess) + return E_FAIL; + return GetThreadsState(m_pProcess, threads); +} + +HRESULT ManagedDebugger::GetStackTrace(int threadId, int lowFrame, int highFrame, std::vector &stackFrames) +{ + HRESULT Status; + if (!m_pProcess) + return E_FAIL; + ToRelease pThread; + IfFailRet(m_pProcess->GetThread(threadId, &pThread)); + return GetStackTrace(pThread, lowFrame, highFrame, stackFrames); +} + +VOID ManagedDebugger::StartupCallback(IUnknown *pCordb, PVOID parameter, HRESULT hr) +{ + ManagedDebugger *self = static_cast(parameter); std::unique_lock lock(self->m_startupMutex); @@ -786,7 +868,7 @@ static std::string GetCLRPath(int pid) return result; } -HRESULT Debugger::Startup(IUnknown *punk, int pid) +HRESULT ManagedDebugger::Startup(IUnknown *punk, int pid) { HRESULT Status; @@ -825,7 +907,7 @@ HRESULT Debugger::Startup(IUnknown *punk, int pid) return S_OK; } -HRESULT Debugger::RunProcess(std::string fileExec, std::vector execArgs) +HRESULT ManagedDebugger::RunProcess(std::string fileExec, std::vector execArgs) { static const auto startupCallbackWaitTimeout = std::chrono::milliseconds(5000); HRESULT Status; @@ -852,15 +934,15 @@ HRESULT Debugger::RunProcess(std::string fileExec, std::vector exec HANDLE resumeHandle; IfFailRet(CreateProcessForLaunch(&cmd[0], bSuspendProcess, lpEnvironment, lpCurrentDirectory, &m_processId, &resumeHandle)); - IfFailRet(RegisterForRuntimeStartup(m_processId, Debugger::StartupCallback, this, &m_unregisterToken)); + IfFailRet(RegisterForRuntimeStartup(m_processId, ManagedDebugger::StartupCallback, this, &m_unregisterToken)); // Resume the process so that StartupCallback can run IfFailRet(ResumeProcess(resumeHandle)); CloseResumeHandle(resumeHandle); - // Wait for Debugger::StartupCallback to complete + // Wait for ManagedDebugger::StartupCallback to complete - // FIXME: if the process exits too soon the Debugger::StartupCallback() + // FIXME: if the process exits too soon the ManagedDebugger::StartupCallback() // is never called (bug in dbgshim?). // The workaround is to wait with timeout. auto now = std::chrono::system_clock::now(); @@ -877,7 +959,7 @@ HRESULT Debugger::RunProcess(std::string fileExec, std::vector exec return m_startupResult; } -HRESULT Debugger::CheckNoProcess() +HRESULT ManagedDebugger::CheckNoProcess() { if (m_pProcess || m_pDebug) { @@ -891,7 +973,7 @@ HRESULT Debugger::CheckNoProcess() return S_OK; } -HRESULT Debugger::DetachFromProcess() +HRESULT ManagedDebugger::DetachFromProcess() { if (!m_pProcess || !m_pDebug) return E_FAIL; @@ -914,7 +996,7 @@ HRESULT Debugger::DetachFromProcess() return S_OK; } -HRESULT Debugger::TerminateProcess() +HRESULT ManagedDebugger::TerminateProcess() { if (!m_pProcess || !m_pDebug) return E_FAIL; @@ -939,7 +1021,7 @@ HRESULT Debugger::TerminateProcess() return S_OK; } -void Debugger::Cleanup() +void ManagedDebugger::Cleanup() { m_modules.CleanupAllModules(); m_evaluator.Cleanup(); @@ -947,7 +1029,7 @@ void Debugger::Cleanup() // TODO: Cleanup libcoreclr.so instance } -HRESULT Debugger::AttachToProcess(int pid) +HRESULT ManagedDebugger::AttachToProcess(int pid) { HRESULT Status; @@ -1025,10 +1107,11 @@ int main(int argc, char *argv[]) } } - Debugger debugger; - + ManagedDebugger debugger; MIProtocol protocol; + protocol.SetDebugger(&debugger); + debugger.SetProtocol(&protocol); if (pidDebuggee != 0) { diff --git a/src/debug/netcoredbg/variables.cpp b/src/debug/netcoredbg/variables.cpp index 703465f..74c2360 100644 --- a/src/debug/netcoredbg/variables.cpp +++ b/src/debug/netcoredbg/variables.cpp @@ -136,7 +136,7 @@ HRESULT Variables::FetchFieldsAndProperties( return S_OK; } -int Debugger::GetNamedVariables(uint32_t variablesReference) +int ManagedDebugger::GetNamedVariables(uint32_t variablesReference) { return m_variables.GetNamedVariables(variablesReference); } @@ -149,7 +149,7 @@ int Variables::GetNamedVariables(uint32_t variablesReference) return it->second.namedVariables; } -HRESULT Debugger::GetVariables( +HRESULT ManagedDebugger::GetVariables( uint32_t variablesReference, VariablesFilter filter, int start, @@ -266,7 +266,7 @@ HRESULT Variables::GetStackVariables( return S_OK; } -HRESULT Debugger::GetScopes(uint64_t frameId, std::vector &scopes) +HRESULT ManagedDebugger::GetScopes(uint64_t frameId, std::vector &scopes) { return m_variables.GetScopes(m_pProcess, frameId, scopes); } @@ -392,7 +392,7 @@ HRESULT Variables::GetChildren( return S_OK; } -HRESULT Debugger::Evaluate(uint64_t frameId, const std::string &expression, Variable &variable) +HRESULT ManagedDebugger::Evaluate(uint64_t frameId, const std::string &expression, Variable &variable) { return m_variables.Evaluate(m_pProcess, frameId, expression, variable); }