From dcea218f9d4be1e3b7568a5e58491c37396a891b Mon Sep 17 00:00:00 2001 From: Igor Kulaychuk Date: Thu, 11 Jan 2018 20:20:45 +0300 Subject: [PATCH] Refactor frame location printing --- src/debug/netcoredbg/commands.cpp | 77 +++++++++++++++++++++++++++++++++ src/debug/netcoredbg/debugger.h | 2 + src/debug/netcoredbg/frames.cpp | 89 +++++++++++++-------------------------- src/debug/netcoredbg/frames.h | 5 +-- src/debug/netcoredbg/main.cpp | 19 ++++++--- src/debug/netcoredbg/protocol.h | 39 +++++++++++++++++ 6 files changed, 161 insertions(+), 70 deletions(-) diff --git a/src/debug/netcoredbg/commands.cpp b/src/debug/netcoredbg/commands.cpp index f1f70ba..fdac9d6 100644 --- a/src/debug/netcoredbg/commands.cpp +++ b/src/debug/netcoredbg/commands.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #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 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 &output) { if (!pProcess) return E_FAIL; diff --git a/src/debug/netcoredbg/debugger.h b/src/debug/netcoredbg/debugger.h index 67fef31..e617667 100644 --- a/src/debug/netcoredbg/debugger.h +++ b/src/debug/netcoredbg/debugger.h @@ -83,3 +83,5 @@ public: HRESULT DisableAllSteppers(ICorDebugProcess *pProcess); int GetLastStoppedThreadId(); void WaitProcessExited(); + +HRESULT PrintFrameLocation(const StackFrame &stackFrame, std::string &output); diff --git a/src/debug/netcoredbg/frames.cpp b/src/debug/netcoredbg/frames.cpp index 75be127..ac2b293 100644 --- a/src/debug/netcoredbg/frames.cpp +++ b/src/debug/netcoredbg/frames.cpp @@ -8,7 +8,6 @@ #include #include #include -#include #include #include #include @@ -49,40 +48,30 @@ static HRESULT GetThreadsState(ICorDebugController *controller, std::vectorGetStackRange(&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 &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; } diff --git a/src/debug/netcoredbg/frames.h b/src/debug/netcoredbg/frames.h index ab248a1..191b5e8 100644 --- a/src/debug/netcoredbg/frames.h +++ b/src/debug/netcoredbg/frames.h @@ -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 &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 &stackFrames); diff --git a/src/debug/netcoredbg/main.cpp b/src/debug/netcoredbg/main.cpp index a911e76..b7a5d3e 100644 --- a/src/debug/netcoredbg/main.cpp +++ b/src/debug/netcoredbg/main.cpp @@ -372,14 +372,16 @@ public: ULONG32 times = 0; HitBreakpoint(pThread, id, times); - std::string output; + StackFrame stackFrame; ToRelease 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 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 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 pExceptionValue; std::string details = "An unhandled exception of type '" + excType + "' occurred in " + excModule; std::string category = "clr"; diff --git a/src/debug/netcoredbg/protocol.h b/src/debug/netcoredbg/protocol.h index 447ae5d..90b76e6 100644 --- a/src/debug/netcoredbg/protocol.h +++ b/src/debug/netcoredbg/protocol.h @@ -1,5 +1,6 @@ #pragma once +#include "platform.h" #include 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) {} +}; -- 2.7.4