Refactor Debugger into the ManagedDebugger class which implements Debugger interface
authorIgor Kulaychuk <i.kulaychuk@samsung.com>
Thu, 18 Jan 2018 19:41:37 +0000 (22:41 +0300)
committerIgor Kulaychuk <i.kulaychuk@samsung.com>
Thu, 18 Jan 2018 19:41:37 +0000 (22:41 +0300)
src/debug/netcoredbg/breakpoints.cpp
src/debug/netcoredbg/commands.cpp
src/debug/netcoredbg/debugger.h
src/debug/netcoredbg/frames.cpp
src/debug/netcoredbg/main.cpp
src/debug/netcoredbg/variables.cpp

index 3845a0f..a96e99c 100644 (file)
@@ -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<int> &lines,
     std::vector<Breakpoint> &breakpoints)
index 8b388ea..e574ded 100644 (file)
@@ -161,89 +161,6 @@ void MIProtocol::EmitBreakpointEvent(BreakpointEvent event)
     }
 }
 
-HRESULT Debugger::SetupStep(ICorDebugThread *pThread, Debugger::StepType stepType)
-{
-    HRESULT Status;
-
-    ToRelease<ICorDebugStepper> 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<ICorDebugStepper2> 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<ICorDebugThread> 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<Thread> &threads)
-{
-    if (!m_pProcess)
-        return E_FAIL;
-    return GetThreadsState(m_pProcess, threads);
-}
-
-HRESULT Debugger::GetStackTrace(int threadId, int lowFrame, int highFrame, std::vector<StackFrame> &stackFrames)
-{
-    HRESULT Status;
-    if (!m_pProcess)
-        return E_FAIL;
-    ToRelease<ICorDebugThread> pThread;
-    IfFailRet(m_pProcess->GetThread(threadId, &pThread));
-    return GetStackTrace(pThread, lowFrame, highFrame, stackFrames);
-}
-
 HRESULT MIProtocol::StepCommand(const std::vector<std::string> &args,
                                 std::string &output,
                                 Debugger::StepType stepType)
index 0e69ae7..ec5ee27 100644 (file)
@@ -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<std::string> 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<Thread> &threads) = 0;
+    virtual HRESULT SetBreakpoints(std::string filename, const std::vector<int> &lines, std::vector<Breakpoint> &breakpoints) = 0;
+    virtual void InsertExceptionBreakpoint(const std::string &name, Breakpoint &breakpoint) = 0;
+    virtual HRESULT GetStackTrace(int threadId, int lowFrame, int highFrame, std::vector<StackFrame> &stackFrames) = 0;
+    virtual HRESULT StepCommand(int threadId, StepType stepType) = 0;
+    virtual HRESULT GetScopes(uint64_t frameId, std::vector<Scope> &scopes) = 0;
+    virtual HRESULT GetVariables(uint32_t variablesReference, VariablesFilter filter, int start, int count, std::vector<Variable> &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<StackFrame> &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<std::string> 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<std::string> execArgs) override;
 
-    int GetLastStoppedThreadId();
+    HRESULT AttachToProcess(int pid) override;
+    HRESULT DetachFromProcess() override;
+    HRESULT TerminateProcess() override;
 
-    HRESULT Continue();
-    HRESULT Pause();
-    HRESULT GetThreads(std::vector<Thread> &threads);
-    HRESULT SetBreakpoints(std::string filename, const std::vector<int> &lines, std::vector<Breakpoint> &breakpoints);
-    void InsertExceptionBreakpoint(const std::string &name, Breakpoint &breakpoint);
-    HRESULT GetStackTrace(int threadId, int lowFrame, int highFrame, std::vector<StackFrame> &stackFrames);
-    HRESULT StepCommand(int threadId, StepType stepType);
-    HRESULT GetScopes(uint64_t frameId, std::vector<Scope> &scopes);
-    HRESULT GetVariables(uint32_t variablesReference, VariablesFilter filter, int start, int count, std::vector<Variable> &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<Thread> &threads) override;
+    HRESULT SetBreakpoints(std::string filename, const std::vector<int> &lines, std::vector<Breakpoint> &breakpoints) override;
+    void InsertExceptionBreakpoint(const std::string &name, Breakpoint &breakpoint) override;
+    HRESULT GetStackTrace(int threadId, int lowFrame, int highFrame, std::vector<StackFrame> &stackFrames) override;
+    HRESULT StepCommand(int threadId, StepType stepType) override;
+    HRESULT GetScopes(uint64_t frameId, std::vector<Scope> &scopes) override;
+    HRESULT GetVariables(uint32_t variablesReference, VariablesFilter filter, int start, int count, std::vector<Variable> &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<std::string, Variable> m_vars;
     std::unordered_map<std::string, std::unordered_map<int32_t, int> > 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) {}
index 0a73391..e83866e 100644 (file)
@@ -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<StackFrame> &stackFrames)
+HRESULT ManagedDebugger::GetStackTrace(ICorDebugThread *pThread, int lowFrame, int highFrame, std::vector<StackFrame> &stackFrames)
 {
     HRESULT Status;
     std::stringstream ss;
index 500e5c7..5cc3456 100644 (file)
 #undef __out
 
 
-void Debugger::NotifyProcessCreated()
+void ManagedDebugger::NotifyProcessCreated()
 {
     std::lock_guard<std::mutex> lock(m_processAttachedMutex);
     m_processAttachedState = ProcessAttached;
 }
 
-void Debugger::NotifyProcessExited()
+void ManagedDebugger::NotifyProcessExited()
 {
     std::lock_guard<std::mutex> 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<std::mutex> 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<std::mutex> 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<Debugger*>(parameter);
+    HRESULT Status;
+
+    ToRelease<ICorDebugStepper> 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<ICorDebugStepper2> 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<ICorDebugThread> 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<Thread> &threads)
+{
+    if (!m_pProcess)
+        return E_FAIL;
+    return GetThreadsState(m_pProcess, threads);
+}
+
+HRESULT ManagedDebugger::GetStackTrace(int threadId, int lowFrame, int highFrame, std::vector<StackFrame> &stackFrames)
+{
+    HRESULT Status;
+    if (!m_pProcess)
+        return E_FAIL;
+    ToRelease<ICorDebugThread> 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<ManagedDebugger*>(parameter);
 
     std::unique_lock<std::mutex> 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<std::string> execArgs)
+HRESULT ManagedDebugger::RunProcess(std::string fileExec, std::vector<std::string> execArgs)
 {
     static const auto startupCallbackWaitTimeout = std::chrono::milliseconds(5000);
     HRESULT Status;
@@ -852,15 +934,15 @@ HRESULT Debugger::RunProcess(std::string fileExec, std::vector<std::string> 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<std::string> 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)
     {
index 703465f..74c2360 100644 (file)
@@ -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<Scope> &scopes)
+HRESULT ManagedDebugger::GetScopes(uint64_t frameId, std::vector<Scope> &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);
 }