From f29a74888c6b6dcfa6afa1c7deb4cec08b68d3da Mon Sep 17 00:00:00 2001 From: Brian Fiete Date: Mon, 30 May 2022 15:43:49 -0700 Subject: [PATCH] Improved callstack handling with inlined methods --- BeefLibs/corlib/src/System.bf | 8 ++ IDE/dist/BeefDbgVis.toml | 9 ++- IDE/src/Debugger/DebugManager.bf | 6 +- IDE/src/IDEApp.bf | 6 +- IDEHelper/Compiler/CeDebugger.cpp | 2 +- IDEHelper/Compiler/CeDebugger.h | 2 +- IDEHelper/DbgExprEvaluator.h | 1 + IDEHelper/DebugManager.cpp | 4 +- IDEHelper/DebugVisualizers.cpp | 4 + IDEHelper/DebugVisualizers.h | 3 +- IDEHelper/Debugger.h | 2 +- IDEHelper/WinDebugger.cpp | 130 ++++++++++++++++++++++++++---- IDEHelper/WinDebugger.h | 2 +- 13 files changed, 151 insertions(+), 28 deletions(-) diff --git a/BeefLibs/corlib/src/System.bf b/BeefLibs/corlib/src/System.bf index a2386735..6cd97b92 100644 --- a/BeefLibs/corlib/src/System.bf +++ b/BeefLibs/corlib/src/System.bf @@ -47,6 +47,14 @@ namespace System } +#if BF_ENABLE_OBJECT_DEBUG_FLAGS + [AlwaysInclude] +#endif + struct CallStackList : int + { + + } + interface IDisposable { void Dispose() mut; diff --git a/IDE/dist/BeefDbgVis.toml b/IDE/dist/BeefDbgVis.toml index 91806b1c..c1642c28 100644 --- a/IDE/dist/BeefDbgVis.toml +++ b/IDE/dist/BeefDbgVis.toml @@ -2,8 +2,13 @@ [[Type]] Name = "System.CallStackAddr" -DisplayString = "{__funcName(this), ne}" -Action = "ShowCodeAddr {(int)this,X}" +DisplayString = "{__funcName(this - 1), ne}" +Action = "ShowCodeAddr {(int)this - 1,X}" + +[[Type]] +Name = "System.CallStackList" +DisplayString = "{__funcName(((int*)(int)this)[0] - 1), ne}" +[Type.Expand.CallStackList] [[Type]] Name = "System.DeferredCall" diff --git a/IDE/src/Debugger/DebugManager.bf b/IDE/src/Debugger/DebugManager.bf index 1d81475b..48f5b15f 100644 --- a/IDE/src/Debugger/DebugManager.bf +++ b/IDE/src/Debugger/DebugManager.bf @@ -260,7 +260,7 @@ namespace IDE.Debugger static extern int32 CallStack_GetBreakStackFrameIdx(); [CallingConvention(.Stdcall),CLink] - static extern char8* Debugger_GetCodeAddrInfo(int addr, out int32 hotIdx, out int32 defLineStart, out int32 defLineEnd, out int32 line, out int32 column); + static extern char8* Debugger_GetCodeAddrInfo(int addr, int inlineCallAddr, out int32 hotIdx, out int32 defLineStart, out int32 defLineEnd, out int32 line, out int32 column); [CallingConvention(.Stdcall),CLink] static extern void Debugger_GetStackAllocInfo(int addr, out int threadId, int32* outStackIdx); @@ -940,14 +940,14 @@ namespace IDE.Debugger return Debugger_GetStackFrameCalleeAddr(stackFrameIdx); } - public void GetCodeAddrInfo(int addr, String outFile, out int hotIdx, out int defLineStart, out int defLineEnd, out int line, out int column) + public void GetCodeAddrInfo(int addr, int inlineCallAddr, String outFile, out int hotIdx, out int defLineStart, out int defLineEnd, out int line, out int column) { int32 hotIdxOut; int32 lineOut; int32 columnOut; int32 defLineStartOut = -1; int32 defLineEndOut = -1; - char8* locationStr = Debugger_GetCodeAddrInfo(addr, out hotIdxOut, out defLineStartOut, out defLineEndOut, out lineOut, out columnOut); + char8* locationStr = Debugger_GetCodeAddrInfo(addr, inlineCallAddr, out hotIdxOut, out defLineStartOut, out defLineEndOut, out lineOut, out columnOut); hotIdx = hotIdxOut; defLineStart = defLineStartOut; defLineEnd = defLineEndOut; diff --git a/IDE/src/IDEApp.bf b/IDE/src/IDEApp.bf index de024ec9..d1f67260 100644 --- a/IDE/src/IDEApp.bf +++ b/IDE/src/IDEApp.bf @@ -1127,13 +1127,17 @@ namespace IDE sourceViewPanel.RecordHistoryLocation(); int64 addr = int64.Parse(cmds[1], System.Globalization.NumberStyles.HexNumber).GetValueOrDefault(); + int64 inlineCallAddr = 0; + if (cmds.Count >= 2) + inlineCallAddr = int64.Parse(cmds[2], System.Globalization.NumberStyles.HexNumber).GetValueOrDefault(); + String fileName = scope String(); int lineNum = 0; int column; int hotIdx; int defLineStart; int defLineEnd; - mDebugger.GetCodeAddrInfo((int)addr, fileName, out hotIdx, out defLineStart, out defLineEnd, out lineNum, out column); + mDebugger.GetCodeAddrInfo((int)addr, (int)inlineCallAddr, fileName, out hotIdx, out defLineStart, out defLineEnd, out lineNum, out column); if (fileName.Length > 0) { int showHotIdx = -1; diff --git a/IDEHelper/Compiler/CeDebugger.cpp b/IDEHelper/Compiler/CeDebugger.cpp index b33e8b5e..631fa792 100644 --- a/IDEHelper/Compiler/CeDebugger.cpp +++ b/IDEHelper/Compiler/CeDebugger.cpp @@ -4498,7 +4498,7 @@ void CeDebugger::UpdateCallStackMethod(int stackFrameIdx) { } -void CeDebugger::GetCodeAddrInfo(intptr addr, String* outFile, int* outHotIdx, int* outDefLineStart, int* outDefLineEnd, int* outLine, int* outColumn) +void CeDebugger::GetCodeAddrInfo(intptr addr, intptr inlineCallAddr, String* outFile, int* outHotIdx, int* outDefLineStart, int* outDefLineEnd, int* outLine, int* outColumn) { } diff --git a/IDEHelper/Compiler/CeDebugger.h b/IDEHelper/Compiler/CeDebugger.h index 920ff865..375ee140 100644 --- a/IDEHelper/Compiler/CeDebugger.h +++ b/IDEHelper/Compiler/CeDebugger.h @@ -374,7 +374,7 @@ public: virtual DbgMemoryFlags GetMemoryFlags(intptr address) override; virtual void UpdateRegisterUsage(int stackFrameIdx) override; virtual void UpdateCallStackMethod(int stackFrameIdx) override; - virtual void GetCodeAddrInfo(intptr addr, String* outFile, int* outHotIdx, int* outDefLineStart, int* outDefLineEnd, int* outLine, int* outColumn) override; + virtual void GetCodeAddrInfo(intptr addr, intptr inlineCallAddr, String* outFile, int* outHotIdx, int* outDefLineStart, int* outDefLineEnd, int* outLine, int* outColumn) override; virtual void GetStackAllocInfo(intptr addr, int* outThreadId, int* outStackIdx) override; virtual String GetStackFrameInfo(int stackFrameIdx, intptr* addr, String* outFile, int32* outHotIdx, int32* outDefLineStart, int32* outDefLineEnd, int32* outLine, int32* outColumn, int32* outLanguage, int32* outStackSize, int8* outFlags) override; virtual String Callstack_GetStackFrameOldFileInfo(int stackFrameIdx) override; diff --git a/IDEHelper/DbgExprEvaluator.h b/IDEHelper/DbgExprEvaluator.h index d248fa38..81c80889 100644 --- a/IDEHelper/DbgExprEvaluator.h +++ b/IDEHelper/DbgExprEvaluator.h @@ -203,6 +203,7 @@ struct DwFormatInfo DbgTypedValue mExplicitThis; int mTotalSummaryLength; String mReferenceId; + String mAction; String mSubjectExpr; String mExpectedType; String mNamespaceSearch; diff --git a/IDEHelper/DebugManager.cpp b/IDEHelper/DebugManager.cpp index 408f7b7f..58c706df 100644 --- a/IDEHelper/DebugManager.cpp +++ b/IDEHelper/DebugManager.cpp @@ -1428,11 +1428,11 @@ BF_EXPORT intptr BF_CALLTYPE Debugger_GetStackFrameCalleeAddr(int stackFrameIdx) return gDebugger->GetStackFrameCalleeAddr(stackFrameIdx); } -BF_EXPORT const char* BF_CALLTYPE Debugger_GetCodeAddrInfo(intptr addr, int* outHotIdx, int* outDefLineStart, int* outDefLineEnd, int* outLine, int* outColumn) +BF_EXPORT const char* BF_CALLTYPE Debugger_GetCodeAddrInfo(intptr addr, intptr inlineCallAddr, int* outHotIdx, int* outDefLineStart, int* outDefLineEnd, int* outLine, int* outColumn) { String& outString = *gTLStrReturn.Get(); outString.clear(); - gDebugger->GetCodeAddrInfo(addr, &outString, outHotIdx, outDefLineStart, outDefLineEnd, outLine, outColumn); + gDebugger->GetCodeAddrInfo(addr, inlineCallAddr, &outString, outHotIdx, outDefLineStart, outDefLineEnd, outLine, outColumn); return outString.c_str(); } diff --git a/IDEHelper/DebugVisualizers.cpp b/IDEHelper/DebugVisualizers.cpp index acbddd38..a95ed81c 100644 --- a/IDEHelper/DebugVisualizers.cpp +++ b/IDEHelper/DebugVisualizers.cpp @@ -325,6 +325,10 @@ bool DebugVisualizers::ReadFileTOML(const StringImpl& fileName) Fail("Unexpected entry", value); } } + else if (name == "CallStackList") + { + entry->mCollectionType = DebugVisualizerEntry::CollectionType_CallStackList; + } else Fail("Unexpected entry", value); } diff --git a/IDEHelper/DebugVisualizers.h b/IDEHelper/DebugVisualizers.h index 353e6645..aa25a744 100644 --- a/IDEHelper/DebugVisualizers.h +++ b/IDEHelper/DebugVisualizers.h @@ -35,7 +35,8 @@ public: CollectionType_LinkedList, CollectionType_Delegate, CollectionType_Dictionary, - CollectionType_ExpandedItem + CollectionType_ExpandedItem, + CollectionType_CallStackList }; public: diff --git a/IDEHelper/Debugger.h b/IDEHelper/Debugger.h index 12b94fb4..564ee980 100644 --- a/IDEHelper/Debugger.h +++ b/IDEHelper/Debugger.h @@ -326,7 +326,7 @@ public: virtual DbgMemoryFlags GetMemoryFlags(intptr address) = 0; virtual void UpdateRegisterUsage(int stackFrameIdx) = 0; virtual void UpdateCallStackMethod(int stackFrameIdx) = 0; - virtual void GetCodeAddrInfo(intptr addr, String* outFile, int* outHotIdx, int* outDefLineStart, int* outDefLineEnd, int* outLine, int* outColumn) = 0; + virtual void GetCodeAddrInfo(intptr addr, intptr inlineCallAddr, String* outFile, int* outHotIdx, int* outDefLineStart, int* outDefLineEnd, int* outLine, int* outColumn) = 0; virtual void GetStackAllocInfo(intptr addr, int* outThreadId, int* outStackIdx) = 0; virtual String GetStackFrameInfo(int stackFrameIdx, intptr* addr, String* outFile, int32* outHotIdx, int32* outDefLineStart, int32* outDefLineEnd, int32* outLine, int32* outColumn, int32* outLanguage, int32* outStackSize, int8* outFlags) = 0; virtual String GetStackFrameId(int stackFrameIdx) { return ""; } diff --git a/IDEHelper/WinDebugger.cpp b/IDEHelper/WinDebugger.cpp index a1cbcae1..6feac59f 100644 --- a/IDEHelper/WinDebugger.cpp +++ b/IDEHelper/WinDebugger.cpp @@ -5653,25 +5653,31 @@ bool WinDebugger::ParseFormatInfo(DbgModule* dbgModule, const StringImpl& format else if (strncmp(formatCmd.c_str(), "refid=", 6) == 0) { formatInfo->mReferenceId = formatCmd.Substring(6); - if (formatInfo->mReferenceId[0] == '\"') + if ((formatInfo->mReferenceId.mLength >= 2) && (formatInfo->mReferenceId[0] == '\"')) formatInfo->mReferenceId = formatInfo->mReferenceId.Substring(1, formatInfo->mReferenceId.length() - 2); } + else if (strncmp(formatCmd.c_str(), "action=", 7) == 0) + { + formatInfo->mAction = formatCmd.Substring(7); + if ((formatInfo->mAction.mLength >= 2) && (formatInfo->mAction[0] == '\"')) + formatInfo->mAction = formatInfo->mReferenceId.Substring(1, formatInfo->mReferenceId.length() - 2); + } else if (strncmp(formatCmd.c_str(), "_=", 2) == 0) { formatInfo->mSubjectExpr = formatCmd.Substring(2); - if (formatInfo->mSubjectExpr[0] == '\"') + if ((formatInfo->mSubjectExpr.mLength >= 2) && (formatInfo->mSubjectExpr[0] == '\"')) formatInfo->mSubjectExpr = formatInfo->mSubjectExpr.Substring(1, formatInfo->mSubjectExpr.length() - 2); } else if (strncmp(formatCmd.c_str(), "expectedType=", 13) == 0) { formatInfo->mExpectedType = formatCmd.Substring(13); - if (formatInfo->mExpectedType[0] == '\"') + if ((formatInfo->mExpectedType.mLength >= 2) && (formatInfo->mExpectedType[0] == '\"')) formatInfo->mExpectedType = formatInfo->mExpectedType.Substring(1, formatInfo->mExpectedType.length() - 2); } else if (strncmp(formatCmd.c_str(), "namespaceSearch=", 16) == 0) { formatInfo->mNamespaceSearch = formatCmd.Substring(16); - if (formatInfo->mNamespaceSearch[0] == '\"') + if ((formatInfo->mNamespaceSearch.mLength >= 2) && (formatInfo->mNamespaceSearch[0] == '\"')) formatInfo->mNamespaceSearch = formatInfo->mNamespaceSearch.Substring(1, formatInfo->mNamespaceSearch.length() - 2); } else if (formatCmd == "d") @@ -6088,7 +6094,6 @@ String WinDebugger::GetTreeItems(DbgCompileUnit* dbgCompileUnit, DebugVisualizer } } - DbgTypedValue val = valueEvaluationContext.EvaluateInContext(readNode); if (valueType == NULL) valueType = val.mType; @@ -6185,7 +6190,7 @@ String WinDebugger::GetCollectionContinuation(const StringImpl& continuationData retVal += "\n" + newContinuationData; return retVal; } - + return ""; } @@ -8307,14 +8312,7 @@ String WinDebugger::DbgTypedValueToString(const DbgTypedValue& origTypedValue, c stackTraceAddr = ptrVal + (dbgAllocInfo >> 16); } - if (stackTraceLen == 1) - { - retVal += StrFormat("\n[AllocStackTrace]\t*(System.CallStackAddr*)%s, nm", EncodeDataPtr(stackTraceAddr, true).c_str()); - } - else if (stackTraceLen > 0) - { - retVal += StrFormat("\n[AllocStackTrace]\t(System.CallStackAddr*)%s, %d, na", EncodeDataPtr(stackTraceAddr, true).c_str(), stackTraceLen); - } + retVal += StrFormat("\n[AllocStackTrace]\t(System.CallStackList)%s, count=%d, na", EncodeDataPtr(stackTraceAddr, true).c_str(), stackTraceLen); } retVal += StrFormat("\n:language\t%d", language); @@ -8350,6 +8348,12 @@ String WinDebugger::DbgTypedValueToString(const DbgTypedValue& origTypedValue, c if (isDeletedBfObject) retVal += "\n:deleted"; + if (!formatInfo.mAction.IsEmpty()) + { + retVal += "\n:action\t"; + retVal += formatInfo.mAction; + } + else if ((debugVis != NULL) && (!debugVis->mAction.empty())) { String rawActionStr = mDebugManager->mDebugVisualizers->DoStringReplace(debugVis->mAction, dbgVisWildcardCaptures); @@ -8771,6 +8775,58 @@ void WinDebugger::HandleCustomExpandedItems(String& retVal, DbgCompileUnit* dbgC } } } + else if (debugVis->mCollectionType == DebugVisualizerEntry::CollectionType_CallStackList) + { + int size = 0; + + String addrs; + String firstVal; + auto ptr = useTypedValue.mPtr; + + for (int i = 0; i < formatInfo.mOverrideCount; i++) + { + auto funcAddr = ReadMemory(ptr + i * sizeof(addr_target)); + auto srcFuncAddr = funcAddr; + + addrs += EncodeDataPtr(funcAddr - 1, false); + if (i == 0) + firstVal = addrs; + addrs += EncodeDataPtr((addr_target)0, false); + size++; + + int inlineIdx = 0; + + auto subProgram = mDebugTarget->FindSubProgram(funcAddr - 1, DbgOnDemandKind_LocalOnly); + while (subProgram != NULL) + { + if (subProgram->mInlineeInfo == NULL) + break; + + auto prevFuncAddr = subProgram->mBlock.mLowPC; + + subProgram = subProgram->mInlineeInfo->mInlineParent; + addrs += EncodeDataPtr(subProgram->mBlock.mLowPC + 1, false); + addrs += EncodeDataPtr(prevFuncAddr, false); + size++; + + inlineIdx++; + } + } + + String evalStr = "(CallStackAddr)0x{1}"; + + if (!debugVis->mShowElementAddrs) + evalStr.Insert(0, "*"); + + evalStr += ", refid=\"" + referenceId + ".[]\""; + evalStr += ", ne"; + retVal += "\n:repeat" + StrFormat("\t%d\t%d\t%d", 0, size, 10000) + + "\t[{0}]\t(CallStackAddr)0x{1}, action=ShowCodeAddr {1} {2}\t" + firstVal + "\t" + EncodeDataPtr((addr_target)0, false); + + retVal += "\n:addrs\t" + addrs; + retVal += "\n:addrsEntrySize\t2"; + return; + } if (formatInfo.mExpandItemDepth == 0) { @@ -11232,6 +11288,8 @@ void WinDebugger::UpdateCallStackMethod(int stackFrameIdx) mDebugTarget->FindSymbolAt(pcAddress, &symbolName, &offset, &dbgModule); } + auto prevStackFrame = wdStackFrame; + // Insert inlines int insertIdx = checkFrameIdx + 1; while ((dwSubprogram != NULL) && (dwSubprogram->mInlineeInfo != NULL)) @@ -11245,18 +11303,57 @@ void WinDebugger::UpdateCallStackMethod(int stackFrameIdx) dwSubprogram = dwSubprogram->mInlineeInfo->mInlineParent; insertIdx++; checkFrameIdx++; + + prevStackFrame = inlineStackFrame; } } } -void WinDebugger::GetCodeAddrInfo(intptr addr, String* outFile, int* outHotIdx, int* outDefLineStart, int* outDefLineEnd, int* outLine, int* outColumn) +void WinDebugger::GetCodeAddrInfo(intptr addr, intptr inlineCallAddr, String* outFile, int* outHotIdx, int* outDefLineStart, int* outDefLineEnd, int* outLine, int* outColumn) { AutoCrit autoCrit(mDebugManager->mCritSect); DbgSubprogram* subProgram = NULL; DbgLineData* callingLineData = FindLineDataAtAddress((addr_target)addr, &subProgram); + + if (inlineCallAddr != 0) + { + auto inlinedSubProgram = mDebugTarget->FindSubProgram(inlineCallAddr); + if (inlinedSubProgram != 0) + { + FixupLineDataForSubprogram(inlinedSubProgram->mInlineeInfo->mRootInliner); + DbgSubprogram* parentSubprogram = inlinedSubProgram->mInlineeInfo->mInlineParent; // Require it be in the inline parent + auto foundLine = parentSubprogram->FindClosestLine(inlinedSubProgram->mBlock.mLowPC, &parentSubprogram); + if (foundLine != NULL) + { + auto srcFile = parentSubprogram->GetLineSrcFile(*foundLine); + *outFile = srcFile->GetLocalPath(); + *outLine = foundLine->mLine; + } + + *outHotIdx = inlinedSubProgram->mCompileUnit->mDbgModule->mHotIdx; + *outColumn = -1; + + DbgSubprogram* callingSubProgram = NULL; + DbgLineData* callingLineData = FindLineDataAtAddress(inlinedSubProgram->mBlock.mLowPC - 1, &callingSubProgram); + if ((callingLineData != NULL) && (callingSubProgram == subProgram)) + { + auto callingSrcFile = callingSubProgram->GetLineSrcFile(*callingLineData); + auto srcFile = callingSrcFile; + *outFile = srcFile->GetLocalPath(); + + if (*outLine == callingLineData->mLine) + *outColumn = callingLineData->mColumn; + } + return; + } + } + if (subProgram != NULL) { + if ((subProgram->mInlineeInfo != NULL) && ((addr_target)addr >= subProgram->mBlock.mHighPC)) + callingLineData = &subProgram->mInlineeInfo->mLastLineData; + *outHotIdx = subProgram->mCompileUnit->mDbgModule->mHotIdx; *outFile = subProgram->GetLineSrcFile(*callingLineData)->GetLocalPath(); *outLine = callingLineData->mLine; @@ -11500,6 +11597,9 @@ String WinDebugger::GetStackFrameInfo(int stackFrameIdx, intptr* addr, String* o DbgSubprogram* specificSubprogram = dwSubprogram; dwLineData = dwSubprogram->FindClosestLine(findAddress, &specificSubprogram); + if ((dwLineData == NULL) && (dwSubprogram->mInlineeInfo != NULL) && (findAddress >= dwSubprogram->mBlock.mHighPC)) + dwLineData = &dwSubprogram->mInlineeInfo->mLastLineData; + if (dwLineData != NULL) dwSrcFile = dwSubprogram->GetLineSrcFile(*dwLineData); diff --git a/IDEHelper/WinDebugger.h b/IDEHelper/WinDebugger.h index ce7dbb7b..e157ccfa 100644 --- a/IDEHelper/WinDebugger.h +++ b/IDEHelper/WinDebugger.h @@ -632,7 +632,7 @@ public: addr_target GetTLSOffset(int tlsIndex); virtual void UpdateRegisterUsage(int stackFrameIdx) override; virtual void UpdateCallStackMethod(int stackFrameIdx) override; - virtual void GetCodeAddrInfo(intptr addr, String* outFile, int* outHotIdx, int* outDefLineStart, int* outDefLineEnd, int* outLine, int* outColumn) override; + virtual void GetCodeAddrInfo(intptr addr, intptr inlineCallAddr, String* outFile, int* outHotIdx, int* outDefLineStart, int* outDefLineEnd, int* outLine, int* outColumn) override; virtual void GetStackAllocInfo(intptr addr, int* outThreadId, int* outStackIdx) override; virtual String GetStackFrameInfo(int stackFrameIdx, intptr* addr, String* outFile, int* outHotIdx, int* outDefLineStart, int* outDefLineEnd, int* outLine, int* outColumn, int* outLanguage, int* outStackSize, int8* outFlags) override; virtual String GetStackFrameId(int stackFrameIdx) override;