From eccfabbad2bc542828f7a205b1bef17197255e34 Mon Sep 17 00:00:00 2001 From: Brian Fiete Date: Mon, 23 May 2022 08:48:55 -0700 Subject: [PATCH] Watch lock fixes, add watch pointee/pointer address --- IDE/src/IDEApp.bf | 2 +- IDE/src/ui/WatchPanel.bf | 137 ++++++++++++++++++++++++------ IDEHelper/Compiler/CeDebugger.cpp | 2 +- IDEHelper/DbgExprEvaluator.cpp | 38 +++++++-- IDEHelper/DbgModule.cpp | 2 +- IDEHelper/DebugTarget.cpp | 19 +++-- IDEHelper/DebugTarget.h | 4 +- IDEHelper/WinDebugger.cpp | 63 +++++++++++--- IDEHelper/WinDebugger.h | 2 + 9 files changed, 214 insertions(+), 55 deletions(-) diff --git a/IDE/src/IDEApp.bf b/IDE/src/IDEApp.bf index 4c7c2e74..70c8425c 100644 --- a/IDE/src/IDEApp.bf +++ b/IDE/src/IDEApp.bf @@ -4598,7 +4598,7 @@ namespace IDE DebuggerUnpaused(); } - else + else if (sourceViewPanel != null) { var activePanel = sourceViewPanel.GetActivePanel(); diff --git a/IDE/src/ui/WatchPanel.bf b/IDE/src/ui/WatchPanel.bf index edcca3d5..5ac94bb6 100644 --- a/IDE/src/ui/WatchPanel.bf +++ b/IDE/src/ui/WatchPanel.bf @@ -44,6 +44,8 @@ namespace IDE.ui public String mStackFrameId ~ delete _; public bool mWantsStackFrameId; public String mEvalStr ~ delete _; + public String mAddrValueExpr ~ delete _; + public String mPointeeExpr ~ delete _; public bool mCanEdit; public String mEditInitialize ~ delete _; public bool mHadValue; @@ -2577,6 +2579,8 @@ namespace IDE.ui watch.mLanguage = .NotSet; DeleteAndNullify!(watch.mEditInitialize); DeleteAndNullify!(watch.mAction); + DeleteAndNullify!(watch.mAddrValueExpr); + DeleteAndNullify!(watch.mPointeeExpr); watch.mCanEdit = false; watch.mAction = null; @@ -2764,6 +2768,14 @@ namespace IDE.ui if (int32 stackIdx = int32.Parse(memberVals[1])) watch.mCurStackIdx = stackIdx; } + else if (memberVals0 == ":addrValueExpr") + { + watch.mAddrValueExpr = new .(memberVals[1]); + } + else if (memberVals0 == ":pointeeExpr") + { + watch.mPointeeExpr = new .(memberVals[1]); + } else watch.ParseCmd(memberVals); continue; @@ -2808,7 +2820,7 @@ namespace IDE.ui { watch.mWantsStackFrameId = false; watch.mStackFrameId = gApp.mDebugger.GetStackFrameId((watch.mCurStackIdx != -1) ? watch.mCurStackIdx : gApp.mDebugger.mActiveCallStackIdx, .. new .()); - if (gApp.mDebugger.mActiveCallStackIdx != watch.mCurStackIdx) + if ((gApp.mDebugger.mActiveCallStackIdx != watch.mCurStackIdx) && (watch.mCurStackIdx != -1)) watch.mUsedLock = true; } @@ -3061,7 +3073,7 @@ namespace IDE.ui return true; } - protected static void WithSelectedWatchEntries(WatchListView listView, delegate void(WatchEntry) dlg) + protected static void WithSelectedWatchEntries(WatchListView listView, delegate void(WatchEntry watchEntry) dlg) { listView.GetRoot().WithSelectedItems(scope (item) => { @@ -3082,28 +3094,12 @@ namespace IDE.ui Menu menu = new Menu(); Menu anItem; - - /*if (listViewItem.mParent != mListView.GetRoot()) - { - anItem = menu.AddItem("Add Watch"); - }*/ - if (listViewItem != null) { var clickedHoverItem = listViewItem.GetSubItem(0) as HoverWatch.HoverListViewItem; var watchEntry = listViewItem.mWatchEntry; - if (listViewItem.mParentItem != listView.GetRoot()) - { - anItem = menu.AddItem("Add Watch"); - anItem.mOnMenuItemSelected.Add(new (menu) => - { - String compactEvalStr = scope String(); - CompactChildExpression(listViewItem, compactEvalStr); - gApp.AddWatch(compactEvalStr); - }); - } - + AddDisplayTypeMenu("Default Display", menu, listViewItem.mWatchEntry.mResultType, null, false); //Debug.WriteLine(String.Format("RefType: {0}", watchEntry.mReferenceId)); @@ -3178,11 +3174,95 @@ namespace IDE.ui } anItem = menu.AddItem("Add Watch"); - anItem.mOnMenuItemSelected.Add(new (menu) => + var addWatchNew = anItem.AddItem("Duplicate"); + addWatchNew.mOnMenuItemSelected.Add(new (menu) => { - IDEApp.sApp.AddWatch(watchEntry.mEvalStr); + List pendingEvalStrs = scope .(); + + listView.GetRoot().WithSelectedItems(scope (item) => + { + var watchListViewItem = item as WatchListViewItem; + if (watchListViewItem.mWatchEntry != null) + { + if (watchListViewItem.mParentItem != listView.GetRoot()) + { + String compactEvalStr = new String(); + CompactChildExpression(watchListViewItem, compactEvalStr); + pendingEvalStrs.Add(compactEvalStr); + } + else + { + pendingEvalStrs.Add(new .(watchEntry.mEvalStr)); + } + } + }); + + for (var str in pendingEvalStrs) + { + gApp.AddWatch(str); + delete str; + } }); + String pointeeExpr = null; + String addrValueExpr = null; + WithSelectedWatchEntries(listView, scope [&] (selectedWatchEntry) => + { + if (selectedWatchEntry.mPointeeExpr != null) + { + if (pointeeExpr != null) + pointeeExpr = ""; + else + pointeeExpr = selectedWatchEntry.mPointeeExpr; + } + if (selectedWatchEntry.mAddrValueExpr != null) + { + if (addrValueExpr != null) + addrValueExpr = ""; + else + addrValueExpr = selectedWatchEntry.mAddrValueExpr; + } + }); + + + if (pointeeExpr != null) + { + var addWatchPointee = anItem.AddItem(scope $"Pointee Address {pointeeExpr}"); + addWatchPointee.mOnMenuItemSelected.Add(new (menu) => + { + WithSelectedWatchEntries(listView, scope (selectedWatchEntry) => + { + if (selectedWatchEntry.mPointeeExpr != null) + gApp.AddWatch(selectedWatchEntry.mPointeeExpr); + }); + }); + + if (addrValueExpr != null) + { + var addWatchPointer = anItem.AddItem(scope $"Pointer Address {addrValueExpr}"); + addWatchPointer.mOnMenuItemSelected.Add(new (menu) => + { + WithSelectedWatchEntries(listView, scope (selectedWatchEntry) => + { + if (selectedWatchEntry.mAddrValueExpr != null) + gApp.AddWatch(selectedWatchEntry.mAddrValueExpr); + }); + }); + } + } + else if (addrValueExpr != null) + { + var addValuePointer = anItem.AddItem(scope $"Value Address {addrValueExpr}"); + addValuePointer.mOnMenuItemSelected.Add(new (menu) => + { + WithSelectedWatchEntries(listView, scope (selectedWatchEntry) => + { + if (selectedWatchEntry.mAddrValueExpr != null) + gApp.AddWatch(selectedWatchEntry.mAddrValueExpr); + }); + }); + } + if (!watchEntry.IsConstant) { anItem = menu.AddItem("Break When Value Changes"); @@ -3192,10 +3272,19 @@ namespace IDE.ui { String evalStr = scope String(); CompactChildExpression(listViewItem, evalStr); - if (evalStr.StartsWith("*")) - evalStr.Remove(0, 1); + + int valStart = 0; + if (evalStr.StartsWith('{')) + { + int endPos = evalStr.IndexOf('}'); + valStart = endPos + 1; + while ((valStart < evalStr.Length) && (evalStr[valStart].IsWhiteSpace)) + valStart++; + } + if ((valStart < evalStr.Length) && (evalStr[valStart] == '*')) + evalStr.Remove(valStart, 1); else - evalStr.Insert(0, "&"); + evalStr.Insert(valStart, "&"); gApp.mBreakpointPanel.CreateMemoryBreakpoint(evalStr); gApp.MarkDirty(); }); diff --git a/IDEHelper/Compiler/CeDebugger.cpp b/IDEHelper/Compiler/CeDebugger.cpp index 95409936..b33e8b5e 100644 --- a/IDEHelper/Compiler/CeDebugger.cpp +++ b/IDEHelper/Compiler/CeDebugger.cpp @@ -4137,7 +4137,7 @@ void CeDebugger::HandleCustomExpandedItems(String& retVal, DebugVisualizerEntry* if (!valueType->IsPointer()) ptrType = ceModule->CreatePointerType(valueType); evalStr = StrFormat("(comptype(%d)", ptrType->mTypeId); - evalStr += ")0x{1}";; + evalStr += ")0x{1}"; } else { diff --git a/IDEHelper/DbgExprEvaluator.cpp b/IDEHelper/DbgExprEvaluator.cpp index 123be413..604c5790 100644 --- a/IDEHelper/DbgExprEvaluator.cpp +++ b/IDEHelper/DbgExprEvaluator.cpp @@ -970,10 +970,20 @@ DbgType* DbgExprEvaluator::ResolveTypeRef(BfTypeReference* typeRef) String name = typeRef->ToString(); if (name.StartsWith("_T_")) - { - int idx = atoi(name.c_str() + 3); - if ((idx >= 0) && (idx < (int)mDbgModule->mTypes.size())) - return mDbgModule->mTypes[idx]; + { + auto dbgModule = mDbgModule; + + char* endPtr = NULL; + int typeIdx = strtol(name.c_str() + 3, &endPtr, 10); + if ((endPtr != NULL) && (*endPtr == '_')) + { + int moduleIdx = typeIdx; + typeIdx = atoi(endPtr + 1); + mDebugTarget->mDbgModuleMap.TryGetValue(moduleIdx, &dbgModule); + } + + if ((dbgModule != NULL) && (typeIdx >= 0) && (typeIdx < (int)dbgModule->mTypes.size())) + return dbgModule->mTypes[typeIdx]; } auto entry = mDbgModule->mTypeMap.Find(name.c_str(), GetLanguage()); @@ -1023,23 +1033,33 @@ DbgType* DbgExprEvaluator::ResolveTypeRef(BfAstNode* typeRef, BfAstNode** parent for (int i = 3; i < (int)name.length(); i++) { char c = name[i]; - if ((c < '0') || (c > '9')) + if (((c < '0') || (c > '9')) && (c != '_')) { endIdx = i; break; } } - int idx = atoi(name.c_str() + 3); - if ((idx >= 0) && (idx < (int)mDbgModule->mTypes.size())) + auto dbgModule = mDbgModule; + + char* endPtr = NULL; + int typeIdx = strtol(name.c_str() + 3, &endPtr, 10); + if ((endPtr != NULL) && (*endPtr == '_')) + { + int moduleIdx = typeIdx; + typeIdx = atoi(endPtr + 1); + mDebugTarget->mDbgModuleMap.TryGetValue(moduleIdx, &dbgModule); + } + + if ((dbgModule != NULL) && (typeIdx >= 0) && (typeIdx < (int)dbgModule->mTypes.size())) { if ((mExplicitThisExpr != NULL) && (parentChildRef != NULL)) mDeferredInsertExplicitThisVector.push_back(NodeReplaceRecord(typeRef, parentChildRef, true)); - DbgType* dbgType = mDbgModule->mTypes[idx]; + DbgType* dbgType = dbgModule->mTypes[typeIdx]; for (int i = endIdx; i < (int)name.length(); i++) { if (name[i] == '*') - dbgType = mDbgModule->GetPointerType(dbgType); + dbgType = dbgModule->GetPointerType(dbgType); } return dbgType; } diff --git a/IDEHelper/DbgModule.cpp b/IDEHelper/DbgModule.cpp index e4599d43..99b6267c 100644 --- a/IDEHelper/DbgModule.cpp +++ b/IDEHelper/DbgModule.cpp @@ -1547,7 +1547,7 @@ DbgType* DbgType::RemoveModifiers(bool* hadRef) String DbgType::ToStringRaw(DbgLanguage language) { if (mTypeIdx != -1) - return StrFormat("_T_%d", mTypeIdx); + return StrFormat("_T_%d_%d", mCompileUnit->mDbgModule->mId, mTypeIdx); return ToString(language); } diff --git a/IDEHelper/DebugTarget.cpp b/IDEHelper/DebugTarget.cpp index b08795a8..6e25838d 100644 --- a/IDEHelper/DebugTarget.cpp +++ b/IDEHelper/DebugTarget.cpp @@ -33,6 +33,7 @@ DebugTarget::DebugTarget(WinDebugger* debugger) mLastHotHeapCleanIdx = 0; mIsEmpty = false; mWasLocallyBuilt = false; + mCurModuleId = 0; /*dbgType = new DbgType(); dbgType->mName = "int"; @@ -252,9 +253,12 @@ String DebugTarget::UnloadDyn(addr_target imageBase) if (mTargetBinary == dwarf) mTargetBinary = NULL; + + mDbgModules.RemoveAt(i); + bool success = mDbgModuleMap.Remove(dwarf->mId); + BF_ASSERT_REL(success); delete dwarf; - mDbgModules.erase(mDbgModules.begin() + i); return filePath; } } @@ -292,9 +296,11 @@ void DebugTarget::CleanupHotHeap() { DbgModule* dbgModule = mDbgModules[dwarfIdx]; if (dbgModule->mDeleting) - { + { + mDbgModules.RemoveAt(dwarfIdx); + bool success = mDbgModuleMap.Remove(dbgModule->mId); + BF_ASSERT_REL(success); delete dbgModule; - mDbgModules.erase(mDbgModules.begin() + dwarfIdx); dwarfIdx--; } } @@ -906,10 +912,11 @@ void DebugTarget::GetCompilerSettings() } void DebugTarget::AddDbgModule(DbgModule* dbgModule) -{ - static int id = 0; - dbgModule->mId = ++id; +{ + dbgModule->mId = ++mCurModuleId; mDbgModules.Add(dbgModule); + bool success = mDbgModuleMap.TryAdd(dbgModule->mId, dbgModule); + BF_ASSERT_REL(success); } #if 1 diff --git a/IDEHelper/DebugTarget.h b/IDEHelper/DebugTarget.h index 369238a2..0a486ee8 100644 --- a/IDEHelper/DebugTarget.h +++ b/IDEHelper/DebugTarget.h @@ -38,7 +38,8 @@ public: String mTargetPath; DbgModule* mLaunchBinary; DbgModule* mTargetBinary; - Array mDbgModules; + Array mDbgModules; + Dictionary mDbgModuleMap; HashSet mPendingSrcFileRehup; // Waiting to remove old/invalid line info BumpAllocator mAlloc; @@ -51,6 +52,7 @@ public: bool mBfHasLargeCollections; int mBfObjectVDataIntefaceSlotCount; int mBfObjectSize; + int mCurModuleId; Array mCommonFrameDescriptors; std::map mDwFrameDescriptorMap; diff --git a/IDEHelper/WinDebugger.cpp b/IDEHelper/WinDebugger.cpp index 4dc3521f..891eada0 100644 --- a/IDEHelper/WinDebugger.cpp +++ b/IDEHelper/WinDebugger.cpp @@ -389,6 +389,8 @@ DbgPendingExpr::DbgPendingExpr() mIdleTicks = 0; mExplitType = NULL; mExpressionFlags = DwEvalExpressionFlag_None; + mUsedSpecifiedLock = false; + mStackIdxOverride = -1; } DbgPendingExpr::~DbgPendingExpr() @@ -8727,7 +8729,7 @@ void WinDebugger::HandleCustomExpandedItems(String& retVal, DbgCompileUnit* dbgC } } else if (debugVis->mCollectionType == DebugVisualizerEntry::CollectionType_Dictionary) - { + { DbgTypedValue sizeValue = EvaluateInContext(dbgCompileUnit, useTypedValue, debugVisualizers->DoStringReplace(debugVis->mSize, dbgVisWildcardCaptures), &formatInfo); DbgTypedValue entriesPtrValue = EvaluateInContext(dbgCompileUnit, useTypedValue, debugVisualizers->DoStringReplace(debugVis->mEntries, dbgVisWildcardCaptures), &formatInfo); @@ -9461,6 +9463,25 @@ String WinDebugger::EvaluateContinue(DbgPendingExpr* pendingExpr, BfPassInstance if (exprResult.mIsReadOnly) canEdit = false; + const char* langStr = (pendingExpr->mFormatInfo.mLanguage == DbgLanguage_Beef) ? "@Beef:" : "@C:"; + + if (exprResult.mSrcAddress != 0) + { + val += StrFormat("\n:addrValueExpr\t%s(%s*)", langStr, exprResult.mType->ToString(pendingExpr->mFormatInfo.mLanguage).c_str()); + val += EncodeDataPtr(exprResult.mSrcAddress, true); + } + + if (exprResult.mType->IsPointerOrRef()) + { + auto underlyingType = exprResult.mType->mTypeParam; + if (underlyingType != NULL) + { + val += StrFormat("\n:pointeeExpr\t%s(%s%s)", langStr, underlyingType->ToString(pendingExpr->mFormatInfo.mLanguage).c_str(), + underlyingType->IsBfObject() ? "" : "*"); + val += EncodeDataPtr(exprResult.mPtr, true); + } + } + if (val[0] == '!') { // Already has an error embedded, can't edit @@ -9504,6 +9525,15 @@ String WinDebugger::EvaluateContinue(DbgPendingExpr* pendingExpr, BfPassInstance if (pendingExpr->mFormatInfo.mRawString) return ""; + if (val[0] != '!') + { + if (pendingExpr->mUsedSpecifiedLock) + val += "\n:usedLock"; + + if (pendingExpr->mStackIdxOverride != -1) + val += StrFormat("\n:stackIdx\t%d", pendingExpr->mStackIdxOverride); + } + if (pendingExpr->mCursorPos != -1) val += GetAutocompleteOutput(autoComplete); @@ -9642,8 +9672,10 @@ String WinDebugger::Evaluate(const StringImpl& expr, DwFormatInfo formatInfo, in if (terminatedExpr.StartsWith('{')) { + String locString; int closeIdx = terminatedExpr.IndexOf('}'); - String locString = terminatedExpr.Substring(1, closeIdx - 1); + if (closeIdx != -1) + locString = terminatedExpr.Substring(1, closeIdx - 1); for (int i = 0; i <= closeIdx; i++) terminatedExpr[i] = ' '; @@ -9728,7 +9760,7 @@ String WinDebugger::Evaluate(const StringImpl& expr, DwFormatInfo formatInfo, in foundLockMatch = true; } } - } + } } } } @@ -9995,6 +10027,8 @@ String WinDebugger::Evaluate(const StringImpl& expr, DwFormatInfo formatInfo, in return result; } + pendingExpr->mUsedSpecifiedLock = usedSpecifiedLock; + pendingExpr->mStackIdxOverride = stackIdxOverride; pendingExpr->mExplitType = explicitType; pendingExpr->mFormatInfo = formatInfo; String result = EvaluateContinue(pendingExpr, bfPassInstance); @@ -10012,13 +10046,7 @@ String WinDebugger::Evaluate(const StringImpl& expr, DwFormatInfo formatInfo, in mActiveThread->mBreakpointAddressContinuing = 0; } else - delete pendingExpr; - - if ((!formatInfo.mRawString) && (usedSpecifiedLock)) - result += "\n:usedLock"; - - if ((!formatInfo.mRawString) && (stackIdxOverride != -1)) - result += StrFormat("\n:stackIdx\t%d", stackIdxOverride); + delete pendingExpr; return result; } @@ -10579,8 +10607,17 @@ String WinDebugger::CompactChildExpression(const StringImpl& expr, const StringI parser.SetSource(terminatedExpr.c_str(), terminatedExpr.length()); parser.Parse(&bfPassInstance); - BfParser parentParser(mBfSystem); auto terminatedParentExpr = parentExpr + ";"; + + String parentPrefix; + if (terminatedParentExpr.StartsWith('{')) + { + int prefixEnd = terminatedParentExpr.IndexOf('}'); + parentPrefix = terminatedParentExpr.Substring(0, prefixEnd + 1); + terminatedParentExpr.Remove(0, prefixEnd + 1); + } + + BfParser parentParser(mBfSystem); parentParser.mCompatMode = language != DbgLanguage_Beef; parentParser.SetSource(terminatedParentExpr.c_str(), terminatedParentExpr.length()); parentParser.Parse(&bfPassInstance); @@ -10633,7 +10670,9 @@ String WinDebugger::CompactChildExpression(const StringImpl& expr, const StringI printer.mIgnoreTrivia = true; printer.mReformatting = true; printer.VisitChild(headNode); - auto result = printer.mOutString; + String result; + result += parentPrefix; + result += printer.mOutString; if (formatInfo.mNoVisualizers) result += ", nv"; if (formatInfo.mNoMembers) diff --git a/IDEHelper/WinDebugger.h b/IDEHelper/WinDebugger.h index 482fec06..ce7dbb7b 100644 --- a/IDEHelper/WinDebugger.h +++ b/IDEHelper/WinDebugger.h @@ -288,6 +288,8 @@ public: Array mCallResults; int mIdleTicks; String mException; + bool mUsedSpecifiedLock; + int mStackIdxOverride; DbgPendingExpr(); ~DbgPendingExpr();