Refactor frame location printing
authorIgor Kulaychuk <i.kulaychuk@samsung.com>
Thu, 11 Jan 2018 17:20:45 +0000 (20:20 +0300)
committerIgor Kulaychuk <i.kulaychuk@samsung.com>
Thu, 11 Jan 2018 17:20:45 +0000 (20:20 +0300)
src/debug/netcoredbg/commands.cpp
src/debug/netcoredbg/debugger.h
src/debug/netcoredbg/frames.cpp
src/debug/netcoredbg/frames.h
src/debug/netcoredbg/main.cpp
src/debug/netcoredbg/protocol.h

index f1f70ba..fdac9d6 100644 (file)
@@ -14,6 +14,7 @@
 #include <algorithm>
 #include <mutex>
 #include <condition_variable>
+#include <iomanip>
 
 #include "platform.h"
 #include "debugger.h"
@@ -202,6 +203,82 @@ HRESULT Debugger::StepCommand(ICorDebugProcess *pProcess,
     return S_OK;
 }
 
+static std::string AddrToString(uint64_t addr)
+{
+    std::stringstream ss;
+    ss << "0x" << std::setw(2 * sizeof(void*)) << std::setfill('0') << std::hex << addr;
+    return ss.str();
+}
+
+HRESULT PrintFrameLocation(const StackFrame &stackFrame, std::string &output)
+{
+    HRESULT Status;
+
+    std::stringstream ss;
+
+    if (!stackFrame.source.isNull())
+    {
+        ss << "file=\"" << Debugger::EscapeMIValue(stackFrame.source.name) << "\","
+           << "fullname=\"" << Debugger::EscapeMIValue(stackFrame.source.path) << "\","
+           << "line=\"" << stackFrame.line << "\","
+           << "col=\"" << stackFrame.column << "\","
+           << "end-line=\"" << stackFrame.endLine << "\","
+           << "end-col=\"" << stackFrame.endColumn << "\",";
+    }
+
+    if (stackFrame.clrAddr.methodToken != 0)
+    {
+        ss << "clr-addr={module-id=\"{" << stackFrame.moduleId << "}\","
+           << "method-token=\"0x"
+           << std::setw(8) << std::setfill('0') << std::hex << stackFrame.clrAddr.methodToken << "\","
+           << "il-offset=\"" << std::dec << stackFrame.clrAddr.ilOffset
+           << "\",native-offset=\"" << stackFrame.clrAddr.nativeOffset << "\"},";
+    }
+
+    ss << "func=\"" << stackFrame.name << "\"";
+    if (stackFrame.id != 0)
+        ss << ",addr=\"" << AddrToString(stackFrame.id) << "\"";
+
+    output = ss.str();
+
+    return stackFrame.source.isNull() ? S_FALSE : S_OK;
+}
+
+static HRESULT PrintFrames(ICorDebugThread *pThread, std::string &output, int lowFrame, int highFrame)
+{
+    HRESULT Status;
+    std::stringstream ss;
+
+    std::vector<StackFrame> stackFrames;
+    IfFailRet(GetStackTrace(pThread, lowFrame, highFrame, stackFrames));
+
+    int currentFrame = lowFrame;
+
+    ss << "stack=[";
+    const char *sep = "";
+
+    for (const StackFrame &stackFrame : stackFrames)
+    {
+        ss << sep;
+        sep = ",";
+
+        std::string frameLocation;
+        PrintFrameLocation(stackFrame, frameLocation);
+
+        ss << "frame={level=\"" << currentFrame << "\"";
+        if (!frameLocation.empty())
+            ss << "," << frameLocation;
+        ss << "}";
+        currentFrame++;
+    }
+
+    ss << "]";
+
+    output = ss.str();
+
+    return S_OK;
+}
+
 static HRESULT ThreadInfoCommand(ICorDebugProcess *pProcess, const std::vector<std::string> &, std::string &output)
 {
     if (!pProcess) return E_FAIL;
index 67fef31..e617667 100644 (file)
@@ -83,3 +83,5 @@ public:
 HRESULT DisableAllSteppers(ICorDebugProcess *pProcess);
 int GetLastStoppedThreadId();
 void WaitProcessExited();
+
+HRESULT PrintFrameLocation(const StackFrame &stackFrame, std::string &output);
index 75be127..ac2b293 100644 (file)
@@ -8,7 +8,6 @@
 #include <vector>
 #include <list>
 #include <functional>
-#include <iomanip>
 #include <mutex>
 #include <condition_variable>
 #include <algorithm>
@@ -49,40 +48,30 @@ static HRESULT GetThreadsState(ICorDebugController *controller, std::vector<Thre
     return S_OK;
 }
 
-static std::string AddrToString(uint64_t addr)
-{
-    std::stringstream ss;
-    ss << "0x" << std::setw(2 * sizeof(void*)) << std::setfill('0') << std::hex << addr;
-    return ss.str();
-}
-
-static std::string FrameAddrToString(ICorDebugFrame *pFrame)
+static uint64_t FrameAddr(ICorDebugFrame *pFrame)
 {
     CORDB_ADDRESS startAddr = 0;
     CORDB_ADDRESS endAddr = 0;
     pFrame->GetStackRange(&startAddr, &endAddr);
-    return AddrToString(startAddr);
+    return startAddr;
 }
 
-HRESULT PrintFrameLocation(ICorDebugFrame *pFrame, std::string &output)
+HRESULT GetFrameLocation(ICorDebugFrame *pFrame, StackFrame &stackFrame)
 {
     HRESULT Status;
 
+    stackFrame.id = FrameAddr(pFrame);
+
     ULONG32 ilOffset;
     Modules::SequencePoint sp;
-    bool has_source = false;
-
-    std::stringstream ss;
 
     if (SUCCEEDED(Modules::GetFrameLocation(pFrame, ilOffset, sp)))
     {
-        ss << "file=\"" << GetFileName(sp.document) << "\","
-           << "fullname=\"" << Debugger::EscapeMIValue(sp.document) << "\","
-           << "line=\"" << sp.startLine << "\","
-           << "col=\"" << sp.startColumn << "\","
-           << "end-line=\"" << sp.endLine << "\","
-           << "end-col=\"" << sp.endColumn << "\",";
-        has_source = true;
+        stackFrame.source = Source(sp.document);
+        stackFrame.line = sp.startLine;
+        stackFrame.column = sp.startColumn;
+        stackFrame.endLine = sp.endLine;
+        stackFrame.endColumn = sp.endColumn;
     }
 
     mdMethodDef methodToken;
@@ -105,21 +94,15 @@ HRESULT PrintFrameLocation(ICorDebugFrame *pFrame, std::string &output)
     CorDebugMappingResult mappingResult;
     IfFailRet(pILFrame->GetIP(&ilOffset, &mappingResult));
 
-    std::string id;
-    IfFailRet(Modules::GetModuleId(pModule, id));
-
-    ss << "clr-addr={module-id=\"{" << id << "}\","
-       << "method-token=\"0x" << std::setw(8) << std::setfill('0') << std::hex << methodToken << "\","
-       << "il-offset=\"" << std::dec << ilOffset << "\",native-offset=\"" << nOffset << "\"},";
+    IfFailRet(Modules::GetModuleId(pModule, stackFrame.moduleId));
 
-    std::string methodName;
-    TypePrinter::GetMethodName(pFrame, methodName);
-    ss << "func=\"" << methodName << "\",";
-    ss << "addr=\"" << FrameAddrToString(pFrame) << "\"";
+    stackFrame.clrAddr.methodToken = methodToken;
+    stackFrame.clrAddr.ilOffset = ilOffset;
+    stackFrame.clrAddr.nativeOffset = nOffset;
 
-    output = ss.str();
+    TypePrinter::GetMethodName(pFrame, stackFrame.name);
 
-    return has_source ? S_OK : S_FALSE;
+    return stackFrame.source.isNull() ? S_FALSE : S_OK;
 }
 
 struct NativeFrame
@@ -405,16 +388,13 @@ static const char *GetInternalTypeName(CorDebugInternalFrameType frameType)
     }
 }
 
-HRESULT PrintFrames(ICorDebugThread *pThread, std::string &output, int lowFrame, int highFrame)
+HRESULT GetStackTrace(ICorDebugThread *pThread, int lowFrame, int highFrame, std::vector<StackFrame> &stackFrames)
 {
     HRESULT Status;
     std::stringstream ss;
 
     int currentFrame = -1;
 
-    ss << "stack=[";
-    const char *sep = "";
-
     IfFailRet(WalkFrames(pThread, [&](
         FrameType frameType,
         ICorDebugFrame *pFrame,
@@ -428,23 +408,18 @@ HRESULT PrintFrames(ICorDebugThread *pThread, std::string &output, int lowFrame,
         if (currentFrame > highFrame)
             return S_OK; // Todo implement fast break mechanism
 
-        ss << sep;
-        sep = ",";
-
         switch(frameType)
         {
             case FrameUnknown:
-                ss << "frame={level=\"" << currentFrame << "\",func=\"?\"}";
+                stackFrames.emplace_back(FrameAddr(pFrame), "?");
                 break;
             case FrameNative:
-                ss << "frame={level=\"" << currentFrame << "\",func=\"" << pNative->symbol << "\","
-                   << "file=\"" << pNative->file << "\","
-                   << "line=\"" << pNative->linenum << "\","
-                   << "addr=\"" << AddrToString(pNative->addr) << "\"}";
+                stackFrames.emplace_back(pNative->addr, pNative->symbol);
+                stackFrames.back().source = Source(pNative->file);
+                stackFrames.back().line = pNative->linenum;
                 break;
             case FrameCLRNative:
-                ss << "frame={level=\"" << currentFrame << "\",func=\"[Native Frame]\","
-                   << "addr=\"" << FrameAddrToString(pFrame) << "\"}";
+                stackFrames.emplace_back(FrameAddr(pFrame), "[Native Frame]");
                 break;
             case FrameCLRInternal:
                 {
@@ -452,28 +427,22 @@ HRESULT PrintFrames(ICorDebugThread *pThread, std::string &output, int lowFrame,
                     IfFailRet(pFrame->QueryInterface(IID_ICorDebugInternalFrame, (LPVOID*) &pInternalFrame));
                     CorDebugInternalFrameType frameType;
                     IfFailRet(pInternalFrame->GetFrameType(&frameType));
-                    ss << "frame={level=\"" << currentFrame << "\",func=\"[" << GetInternalTypeName(frameType) << "]\","
-                       << "addr=\"" << FrameAddrToString(pFrame) << "\"}";
+                    std::string name = "[";
+                    name += GetInternalTypeName(frameType);
+                    name += "]";
+                    stackFrames.emplace_back(FrameAddr(pFrame), name);
                 }
                 break;
             case FrameCLRManaged:
                 {
-                    std::string frameLocation;
-                    PrintFrameLocation(pFrame, frameLocation);
-
-                    ss << "frame={level=\"" << currentFrame << "\"";
-                    if (!frameLocation.empty())
-                        ss << "," << frameLocation;
-                    ss << "}";
+                    StackFrame stackFrame;
+                    GetFrameLocation(pFrame, stackFrame);
+                    stackFrames.push_back(stackFrame);
                 }
                 break;
         }
         return S_OK;
     }));
 
-    ss << "]";
-
-    output = ss.str();
-
     return S_OK;
 }
index ab248a1..191b5e8 100644 (file)
@@ -2,8 +2,7 @@
 // Distributed under the MIT License.
 // See the LICENSE file in the project root for more information.
 
-HRESULT PrintFrameLocation(ICorDebugFrame *pFrame, std::string &output);
+HRESULT GetFrameLocation(ICorDebugFrame *pFrame, StackFrame &stackFrame);
 HRESULT GetFrameAt(ICorDebugThread *pThread, int level, ICorDebugFrame **ppFrame);
-
 HRESULT GetThreadsState(ICorDebugController *controller, std::vector<Thread> &threads);
-HRESULT PrintFrames(ICorDebugThread *pThread, std::string &output, int lowFrame = 0, int highFrame = INT_MAX);
+HRESULT GetStackTrace(ICorDebugThread *pThread, int lowFrame, int highFrame, std::vector<StackFrame> &stackFrames);
index a911e76..b7a5d3e 100644 (file)
@@ -372,14 +372,16 @@ public:
             ULONG32 times = 0;
             HitBreakpoint(pThread, id, times);
 
-            std::string output;
+            StackFrame stackFrame;
             ToRelease<ICorDebugFrame> pFrame;
             if (SUCCEEDED(pThread->GetActiveFrame(&pFrame)) && pFrame != nullptr)
-                PrintFrameLocation(pFrame, output);
+                GetFrameLocation(pFrame, stackFrame);
 
             DWORD threadId = 0;
             pThread->GetID(&threadId);
 
+            std::string output;
+            PrintFrameLocation(stackFrame, output);
             Debugger::Printf("*stopped,reason=\"breakpoint-hit\",thread-id=\"%i\",stopped-threads=\"all\",bkptno=\"%u\",times=\"%u\",frame={%s}\n",
                 (int)threadId, (unsigned int)id, (unsigned int)times, output.c_str());
 
@@ -394,11 +396,11 @@ public:
             /* [in] */ ICorDebugStepper *pStepper,
             /* [in] */ CorDebugStepReason reason)
         {
-            std::string output;
+            StackFrame stackFrame;
             ToRelease<ICorDebugFrame> pFrame;
             HRESULT Status = S_FALSE;
             if (SUCCEEDED(pThread->GetActiveFrame(&pFrame)) && pFrame != nullptr)
-                Status = PrintFrameLocation(pFrame, output);
+                Status = GetFrameLocation(pFrame, stackFrame);
 
             const bool no_source = Status == S_FALSE;
 
@@ -411,7 +413,8 @@ public:
             {
                 DWORD threadId = 0;
                 pThread->GetID(&threadId);
-
+                std::string output;
+                PrintFrameLocation(stackFrame, output);
                 Debugger::Printf("*stopped,reason=\"end-stepping-range\",thread-id=\"%i\",stopped-threads=\"all\",frame={%s}\n",
                     (int)threadId, output.c_str());
 
@@ -429,10 +432,10 @@ public:
             /* [in] */ ICorDebugThread *pThread,
             /* [in] */ BOOL unhandled)
         {
-            std::string frameLocation;
+            StackFrame stackFrame;
             ToRelease<ICorDebugFrame> pFrame;
             if (SUCCEEDED(pThread->GetActiveFrame(&pFrame)) && pFrame != nullptr)
-                PrintFrameLocation(pFrame, frameLocation);
+                GetFrameLocation(pFrame, stackFrame);
 
             DWORD threadId = 0;
             pThread->GetID(&threadId);
@@ -444,6 +447,8 @@ public:
 
             if (unhandled)
             {
+                std::string frameLocation;
+                PrintFrameLocation(stackFrame, frameLocation);
                 ToRelease<ICorDebugValue> pExceptionValue;
                 std::string details = "An unhandled exception of type '" + excType + "' occurred in " + excModule;
                 std::string category = "clr";
index 447ae5d..90b76e6 100644 (file)
@@ -1,5 +1,6 @@
 #pragma once
 
+#include "platform.h"
 #include <string>
 
 struct Thread
@@ -10,3 +11,41 @@ struct Thread
 
     Thread(int id, std::string name, bool running) : id(id), name(name), running(running) {}
 };
+
+struct Source
+{
+    std::string name;
+    std::string path;
+
+    Source(std::string path = std::string()) : name(GetFileName(path)), path(path) {}
+    bool isNull() const { return name.empty() && path.empty(); }
+};
+
+struct ClrAddr
+{
+    uint32_t ilOffset;
+    uint32_t nativeOffset;
+    uint32_t methodToken;
+
+    ClrAddr() : ilOffset(0), nativeOffset(0), methodToken(0) {}
+    bool isNull() const { return methodToken == 0; }
+};
+
+struct StackFrame
+{
+    uint64_t id; // frame start address
+    std::string name;
+    Source source;
+    int line;
+    int column;
+    int endLine;
+    int endColumn;
+    std::string moduleId;
+
+    ClrAddr clrAddr;
+
+    StackFrame() :
+        id(0), line(0), column(0), endLine(0), endColumn(0) {}
+
+    StackFrame(uint64_t id, std::string name) : id(id), name(name) {}
+};