1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-08 03:28:20 +02:00

Added watch lock, watch stack offsets (ie: {1}, {Func^2})

This commit is contained in:
Brian Fiete 2022-05-21 11:58:01 -07:00
parent 6833c12fc8
commit 56cc35f266
10 changed files with 558 additions and 35 deletions

View file

@ -131,6 +131,14 @@ namespace Beefy.theme.dark
CloseSubMenu();
}
}
if (mMenuItem.mTooltip != null)
{
if (DarkTooltipManager.CheckMouseover(this, 20, var mousePoint))
{
DarkTooltipManager.ShowTooltip(mMenuItem.mTooltip, this, mWidth + GS!(8), GS!(-8));
}
}
}
public override void Submit()

View file

@ -564,6 +564,7 @@ namespace Beefy.widgets
{
public Menu mParent;
public String mLabel ~ delete _;
public String mTooltip ~ delete _;
public List<Menu> mItems = new List<Menu>() ~ DeleteContainerAndItems!(_);
public Event<delegate void(Menu menu)> mOnMenuItemSelected ~ _.Dispose();

View file

@ -268,6 +268,9 @@ namespace IDE.Debugger
[CallingConvention(.Stdcall),CLink]
static extern char8* CallStack_GetStackFrameInfo(int32 stackFrameIdx, out int addr, out char8* outFile, out int32 hotIdx, out int32 defLineStart, out int32 defLineEnd, out int32 outLine, out int32 outColumn, out int32 outLanguage, out int32 outStackSize, out FrameFlags flags);
[CallingConvention(.Stdcall),CLink]
static extern char8* CallStack_GetStackFrameId(int32 stackFrameIdx);
[CallingConvention(.Stdcall),CLink]
static extern char8* Callstack_GetStackFrameOldFileInfo(int32 stackFrameIdx);
@ -1256,5 +1259,14 @@ namespace IDE.Debugger
outText.Append(str);
return true;
}
public bool GetStackFrameId(int32 callStackIdx, String outString)
{
char8* stackId = CallStack_GetStackFrameId(callStackIdx);
if (stackId == null)
return false;
outString.Append(stackId);
return true;
}
}
}

View file

@ -11,6 +11,7 @@ using Beefy.theme.dark;
using Beefy.events;
using Beefy.utils;
using IDE.Debugger;
using Beefy.geom;
namespace IDE.ui
{
@ -40,6 +41,8 @@ namespace IDE.ui
public DebugManager.Language mLanguage = .NotSet;
public String mName ~ delete _;
public String mStackFrameId ~ delete _;
public bool mWantsStackFrameId;
public String mEvalStr ~ delete _;
public bool mCanEdit;
public String mEditInitialize ~ delete _;
@ -47,6 +50,8 @@ namespace IDE.ui
public bool mHasValue;
public bool mIsNewExpression;
public bool mIsPending;
public bool mUsedLock;
public int32 mCurStackIdx;
public int mMemoryBreakpointAddr;
public int32 mHadStepCount;
public String mStringView ~ delete _;
@ -512,21 +517,6 @@ namespace IDE.ui
DarkTooltipManager.CloseTooltip();
}
/*public override void RecalcSize()
{
base.RecalcSize();
if (mWatchStringEdit.mMoreButton != null)
mHeight += GS!(32);
}*/
public override void GetTextData()
{
base.GetTextData();
}
public override void CheckLineCoords()
{
bool changed = (mLineCoordTextVersionId != mData.mCurTextVersionId);
@ -1325,6 +1315,28 @@ namespace IDE.ui
}
}
}
if (mColumnIdx == 1)
{
var headItem = GetSubItem(0) as WatchListViewItem;
if (headItem.mWatchEntry?.mStackFrameId != null)
{
float drawX = mWidth - GS!(16);
if (headItem.mWatchRefreshButton != null)
drawX -= GS!(16);
uint32 color = Color.White;
if (headItem.mDisabled)
color = 0x80FFFFFF;
else if (mFailed)
color = 0xFFFF4040;
else if (headItem.mWatchEntry.mUsedLock)
color = 0xFFE39C39;
using (g.PushColor(color))
g.Draw(DarkTheme.sDarkTheme.GetImage(.LockIcon), drawX, GS!(-1));
}
}
base.DrawAll(g);
}
@ -1757,6 +1769,34 @@ namespace IDE.ui
}
}
if (mColumnIdx == 1)
{
var nameItem = GetSubItem(0) as WatchListViewItem;
if (nameItem.mWatchEntry?.mStackFrameId != null)
{
if (DarkTooltipManager.CheckMouseover(this, 20, var mousePoint))
{
float drawX = mWidth - GS!(16);
if (nameItem.mWatchRefreshButton != null)
drawX -= GS!(16);
if (Rect(drawX, 0, GS!(16), GS!(20)).Contains(mousePoint))
{
String tooltip = scope String();
tooltip.Append(nameItem.mWatchEntry.mStackFrameId);
int lastColon = nameItem.mWatchEntry.mStackFrameId.LastIndexOf(':');
if ((lastColon > -1) && (var addr = int64.Parse(nameItem.mWatchEntry.mStackFrameId.Substring(lastColon + 1), .HexNumber)))
{
tooltip.Append("\n");
gApp.mDebugger.GetAddressSymbolName(addr, true, tooltip);
}
DarkTooltipManager.ShowTooltip(tooltip, this, mousePoint.x, mousePoint.y);
}
}
}
}
base.Update();
}
@ -2428,7 +2468,14 @@ namespace IDE.ui
}
else if (watch.mEvalStr.Length > 0)
{
String evalStr = scope String(watch.mEvalStr);
String evalStr = scope String(1024);
if (watch.mStackFrameId != null)
{
evalStr.Append("{");
evalStr.Append(watch.mStackFrameId);
evalStr.Append("}");
}
evalStr.Append(watch.mEvalStr);
if ((watch.mReferenceId != null) && (watch.mReferenceId.StartsWith("0", StringComparison.Ordinal)))
evalStr.Append(",refid=", watch.mReferenceId);
//gApp.DebugEvaluate(watch.mResultTypeStr, evalStr, val, -1, watch.mIsNewExpression, watch.mIsNewExpression);
@ -2478,6 +2525,13 @@ namespace IDE.ui
listViewItem.mErrorStart = int32.Parse(scope String(errorVals[0]));
listViewItem.mErrorEnd = listViewItem.mErrorStart + int32.Parse(scope String(errorVals[1])).Get();
valueSubItem.Label = errorVals[2];
if (watch.mStackFrameId != null)
{
int32 idPrefixLen = (.)watch.mStackFrameId.Length + 2;
listViewItem.mErrorStart -= idPrefixLen;
listViewItem.mErrorEnd -= idPrefixLen;
}
}
else
valueSubItem.Label = errorVals[0];
@ -2518,6 +2572,8 @@ namespace IDE.ui
watch.mIsDeleted = false;
watch.mIsAppendAlloc = false;
watch.mIsStackAlloc = false;
watch.mUsedLock = false;
watch.mCurStackIdx = -1;
watch.mLanguage = .NotSet;
DeleteAndNullify!(watch.mEditInitialize);
DeleteAndNullify!(watch.mAction);
@ -2699,6 +2755,15 @@ namespace IDE.ui
if (memberVals.Count > 1)
watch.mStringView = memberVals[1].Unescape(.. new .());
}
else if (memberVals0 == ":usedLock")
{
watch.mUsedLock = true;
}
else if (memberVals0 == ":stackIdx")
{
if (int32 stackIdx = int32.Parse(memberVals[1]))
watch.mCurStackIdx = stackIdx;
}
else
watch.ParseCmd(memberVals);
continue;
@ -2739,6 +2804,14 @@ namespace IDE.ui
}
}
if (watch.mWantsStackFrameId)
{
watch.mWantsStackFrameId = false;
watch.mStackFrameId = gApp.mDebugger.GetStackFrameId((watch.mCurStackIdx != -1) ? watch.mCurStackIdx : gApp.mDebugger.mActiveCallStackIdx, .. new .());
if (gApp.mDebugger.mActiveCallStackIdx != watch.mCurStackIdx)
watch.mUsedLock = true;
}
if ((watch.mReferenceId == null) && (watch.mEvalStr.Length > 0) && (!valueSubItem.mFailed))
{
// Allocate a referenceId if we didn't get one (was a temporary expression)
@ -2988,6 +3061,16 @@ namespace IDE.ui
return true;
}
protected static void WithSelectedWatchEntries(WatchListView listView, delegate void(WatchEntry) dlg)
{
listView.GetRoot().WithSelectedItems(scope (item) =>
{
var watchListViewItem = item as WatchListViewItem;
if (watchListViewItem.mWatchEntry != null)
dlg(watchListViewItem.mWatchEntry);
});
}
public static void ShowRightClickMenu(WatchPanel watchPanel, WatchListView listView, WatchListViewItem listViewItem, float x, float y)
{
if (watchPanel != null)
@ -3039,6 +3122,60 @@ namespace IDE.ui
AddDisplayTypeMenu("Series Watch Display", menu, listViewItem.mWatchEntry.mResultType, refId, true);
}
}
var lockMenu = menu.AddItem("Lock");
var lockUnlockedItem = lockMenu.AddItem("Unlocked");
lockUnlockedItem.mOnMenuItemSelected.Add(new (menu) =>
{
WithSelectedWatchEntries(listView, scope (selectedWatchEntry) =>
{
DeleteAndNullify!(selectedWatchEntry.mStackFrameId);
});
gApp.RefreshWatches();
});
var lockNewItem = lockMenu.AddItem("Current Stack Frame");
lockNewItem.mOnMenuItemSelected.Add(new (menu) =>
{
WithSelectedWatchEntries(listView, scope (selectedWatchEntry) =>
{
int32 callStackIdx = gApp.mDebugger.mActiveCallStackIdx;
if (selectedWatchEntry.mCurStackIdx != -1)
callStackIdx = selectedWatchEntry.mCurStackIdx;
DeleteAndNullify!(selectedWatchEntry.mStackFrameId);
selectedWatchEntry.mWantsStackFrameId = true;
});
gApp.RefreshWatches();
});
if (watchEntry.mStackFrameId != null)
{
var lockCurItem = lockMenu.AddItem(watchEntry.mStackFrameId);
lockCurItem.mIconImage = DarkTheme.sDarkTheme.GetImage(.Check);
int lastColon = watchEntry.mStackFrameId.LastIndexOf(':');
if ((lastColon > -1) && (var addr = int64.Parse(watchEntry.mStackFrameId.Substring(lastColon + 1), .HexNumber)))
{
lockCurItem.mTooltip = gApp.mDebugger.GetAddressSymbolName(addr, true, .. new .());
if (lockCurItem.mTooltip.IsEmpty)
DeleteAndNullify!(lockCurItem.mTooltip);
}
String stackFrameId = new String(watchEntry.mStackFrameId);
lockCurItem.mOnMenuItemSelected.Add(new (menu) =>
{
WithSelectedWatchEntries(listView, scope (selectedWatchEntry) =>
{
DeleteAndNullify!(selectedWatchEntry.mStackFrameId);
selectedWatchEntry.mStackFrameId = new .(stackFrameId);
});
gApp.RefreshWatches();
}
~ delete stackFrameId);
}
else
{
lockUnlockedItem.mIconImage = DarkTheme.sDarkTheme.GetImage(.Check);
}
anItem = menu.AddItem("Add Watch");
anItem.mOnMenuItemSelected.Add(new (menu) =>

View file

@ -761,8 +761,9 @@ DbgExprEvaluator::DbgExprEvaluator(WinDebugger* winDebugger, DbgModule* dbgModul
mBlockedSideEffects = false;
mReferenceId = NULL;
mIsComplexExpression = false;
mHadMemberReference = false;
mHadMemberReference = false;
mCreatedPendingCall = false;
mStackSearch = NULL;
mValidateOnly = false;
mReceivingValue = NULL;
mCallResults = NULL;
@ -770,11 +771,12 @@ DbgExprEvaluator::DbgExprEvaluator(WinDebugger* winDebugger, DbgModule* dbgModul
mCallStackPreservePos = 0;
mPropGet = NULL;
mPropSet = NULL;
mPropSrc = NULL;
mPropSrc = NULL;
}
DbgExprEvaluator::~DbgExprEvaluator()
{
delete mStackSearch;
}
DbgTypedValue DbgExprEvaluator::GetInt(int value)
@ -2526,6 +2528,15 @@ bool DbgExprEvaluator::HasField(DbgType* curCheckType, const StringImpl& fieldNa
DbgTypedValue DbgExprEvaluator::DoLookupField(BfAstNode* targetSrc, DbgTypedValue target, DbgType* curCheckType, const StringImpl& fieldName, CPUStackFrame* stackFrame, bool allowImplicitThis)
{
if (mStackSearch != NULL)
{
if (mStackSearch->mIdentifier == targetSrc)
{
if (!mStackSearch->mSearchedTypes.Add(curCheckType))
return DbgTypedValue();
}
}
bool wantsStatic = (!target) || (target.mHasNoValue);
auto flavor = GetFlavor();
auto language = GetLanguage();
@ -3548,7 +3559,7 @@ void DbgExprEvaluator::AutocompleteAddTopLevelTypes(const StringImpl& filter)
}*/
}
DbgTypedValue DbgExprEvaluator::LookupIdentifier(BfAstNode* identifierNode, bool ignoreInitialError, bool* hadError)
DbgTypedValue DbgExprEvaluator::DoLookupIdentifier(BfAstNode* identifierNode, bool ignoreInitialError, bool* hadError)
{
if (!mDebugger->mIsRunning)
return DbgTypedValue();
@ -3963,6 +3974,92 @@ DbgTypedValue DbgExprEvaluator::LookupIdentifier(BfAstNode* identifierNode, bool
return DbgTypedValue();
}
DbgTypedValue DbgExprEvaluator::LookupIdentifier(BfAstNode* identifierNode, bool ignoreInitialError, bool* hadError)
{
if ((mStackSearch != NULL) && (mStackSearch->mIdentifier == NULL))
{
mStackSearch->mIdentifier = identifierNode;
mStackSearch->mStartingStackIdx = mCallStackIdx;
int skipCount = 0;
StringT<256> findStr;
for (int i = 0; i < mStackSearch->mSearchStr.mLength; i++)
{
char c = mStackSearch->mSearchStr[i];
if (c == '^')
{
skipCount = atoi(mStackSearch->mSearchStr.c_str() + i + 1);
break;
}
if (c == '.')
{
findStr += ':';
findStr += ':';
}
else
findStr += c;
}
while (true)
{
auto stackFrame = GetStackFrame();
bool matches = true;
if (mStackSearch->mSearchStr != "*")
{
mDebugger->UpdateCallStackMethod(mCallStackIdx);
if (stackFrame->mSubProgram != NULL)
{
int strLen = strlen(stackFrame->mSubProgram->mName);
if (strLen >= findStr.mLength)
{
if (strncmp(stackFrame->mSubProgram->mName + strLen - findStr.mLength, findStr.c_str(), findStr.mLength) == 0)
{
if (strLen > findStr.mLength)
{
char endC = stackFrame->mSubProgram->mName[strLen - findStr.mLength - 1];
if (endC != ':')
matches = false;
}
}
else
matches = false;
}
else
matches = false;
}
else
matches = false;
}
if (matches)
{
if (skipCount > 0)
{
skipCount--;
}
else
{
auto result = DoLookupIdentifier(identifierNode, ignoreInitialError, hadError);
if (result)
return result;
}
}
mCallStackIdx++;
if (mCallStackIdx >= mDebugger->mCallStack.mSize)
mDebugger->UpdateCallStack();
if (mCallStackIdx >= mDebugger->mCallStack.mSize)
return DbgTypedValue();
}
}
return DoLookupIdentifier(identifierNode, ignoreInitialError, hadError);
}
void DbgExprEvaluator::Visit(BfAssignmentExpression* assignExpr)
{
mHadSideEffects = true;
@ -4295,6 +4392,12 @@ void DbgExprEvaluator::AutocompleteAddMethod(const char* methodName, const Strin
void DbgExprEvaluator::AutocompleteAddMembers(DbgType* dbgType, bool wantsStatic, bool wantsNonStatic, const StringImpl& filter, bool isCapture)
{
if (mStackSearch != NULL)
{
if (!mStackSearch->mAutocompleteSearchedTypes.Add(dbgType))
return;
}
DbgLanguage language = GetLanguage();
DbgFlavor flavor = GetFlavor();
if ((mDbgCompileUnit != NULL) && (dbgType->mLanguage != DbgLanguage_Unknown) && (dbgType->mLanguage != language))
@ -7609,7 +7712,7 @@ DbgTypedValue DbgExprEvaluator::MatchMethod(BfAstNode* targetSrc, DbgTypedValue
}
else if (mDebugTarget->FindSymbolAt(funcPtr, &symbolName, &offset, &dwarf))
{
demangledName = BfDemangler::Demangle(symbolName, DbgLanguage_Beef);
demangledName = BfDemangler::Demangle(symbolName, GetLanguage());
}
else
{
@ -7634,7 +7737,7 @@ DbgTypedValue DbgExprEvaluator::MatchMethod(BfAstNode* targetSrc, DbgTypedValue
DbgModule* dwarf;
if (mDebugTarget->FindSymbolAt(funcPtr, &symbolName, &offset, &dwarf))
{
String firstParamType = BfDemangler::Demangle(symbolName, DbgLanguage_Beef, BfDemangler::Flag_CaptureTargetType);
String firstParamType = BfDemangler::Demangle(symbolName, GetLanguage(), BfDemangler::Flag_CaptureTargetType);
auto targetType = mDbgModule->FindType(firstParamType, NULL, DbgLanguage_BeefUnfixed);
if (targetType)
{

View file

@ -194,6 +194,7 @@ struct DwFormatInfo
bool mRawString;
bool mAllowStringView;
bool mNoEdit;
String mStackSearchStr;
DbgTypeKindFlags mTypeKindFlags;
intptr mArrayLength;
intptr mOverrideCount;
@ -283,6 +284,23 @@ public:
Array<uint8> mSRetData;
};
class DbgStackSearch
{
public:
String mSearchStr;
BfAstNode* mIdentifier;
HashSet<DbgType*> mSearchedTypes;
HashSet<DbgType*> mAutocompleteSearchedTypes;
int mStartingStackIdx;
public:
DbgStackSearch()
{
mIdentifier = NULL;
mStartingStackIdx = -1;
}
};
class DbgExprEvaluator : public BfStructuralVisitor
{
public:
@ -351,11 +369,12 @@ public:
bool mBlockedSideEffects;
bool mIgnoreErrors;
bool mCreatedPendingCall;
bool mValidateOnly;
bool mValidateOnly;
int mCallStackIdx;
int mCursorPos;
DwAutoComplete* mAutoComplete;
DbgStackSearch* mStackSearch;
Array<Array<uint8>> mTempStorage;
Array<NodeReplaceRecord> mDeferredInsertExplicitThisVector;
@ -431,6 +450,7 @@ public:
bool HasField(DbgType* type, const StringImpl& fieldName);
DbgTypedValue DoLookupField(BfAstNode* targetSrc, DbgTypedValue target, DbgType* curCheckType, const StringImpl& fieldName, CPUStackFrame* stackFrame, bool allowImplicitThis);
DbgTypedValue LookupField(BfAstNode* targetSrc, DbgTypedValue target, const StringImpl& fieldName);
DbgTypedValue DoLookupIdentifier(BfAstNode* identifierNode, bool ignoreInitialError, bool* hadError);
DbgTypedValue LookupIdentifier(BfAstNode* identifierNode, bool ignoreInitialError = false, bool* hadError = NULL);
void LookupSplatMember(const DbgTypedValue& target, const StringImpl& fieldName);
void LookupSplatMember(BfAstNode* srcNode, BfAstNode* lookupNode, const DbgTypedValue& target, const StringImpl& fieldName, String* outFindName = NULL, bool* outIsConst = NULL, StringImpl* forceName = NULL);

View file

@ -1403,6 +1403,13 @@ BF_EXPORT const char* BF_CALLTYPE CallStack_GetStackFrameInfo(int stackFrameIdx,
return outString.c_str();
}
BF_EXPORT const char* BF_CALLTYPE CallStack_GetStackFrameId(int stackFrameIdx)
{
String& outString = *gTLStrReturn.Get();
outString = gDebugger->GetStackFrameId(stackFrameIdx);
return outString.c_str();
}
BF_EXPORT const char* BF_CALLTYPE Callstack_GetStackFrameOldFileInfo(int stackFrameIdx)
{
String& outString = *gTLStrReturn.Get();

View file

@ -329,6 +329,7 @@ public:
virtual void GetCodeAddrInfo(intptr addr, 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 ""; }
virtual String Callstack_GetStackFrameOldFileInfo(int stackFrameIdx) = 0;
virtual int GetJmpState(int stackFrameIdx) = 0;
virtual intptr GetStackFrameCalleeAddr(int stackFrameIdx) = 0;

View file

@ -6371,12 +6371,7 @@ String WinDebugger::ReadString(DbgTypeCode charType, intptr addr, bool isLocalAd
bool wasTerminated = false;
String valString;
intptr maxShowSize = 255;
if (wantStringView)
{
NOP;
}
if (maxLength == -1)
maxLength = formatInfo.mOverrideCount;
else if (formatInfo.mOverrideCount != -1)
@ -6771,7 +6766,7 @@ String WinDebugger::DbgTypedValueToString(const DbgTypedValue& origTypedValue, c
return retVal;
}
}
switch (dwValueType->mTypeCode)
{
case DbgType_Void:
@ -9239,6 +9234,11 @@ String WinDebugger::EvaluateContinue(DbgPendingExpr* pendingExpr, BfPassInstance
}
DbgExprEvaluator dbgExprEvaluator(this, dbgModule, &bfPassInstance, pendingExpr->mCallStackIdx, pendingExpr->mCursorPos);
if (!pendingExpr->mFormatInfo.mStackSearchStr.IsEmpty())
{
dbgExprEvaluator.mStackSearch = new DbgStackSearch();
dbgExprEvaluator.mStackSearch->mSearchStr = pendingExpr->mFormatInfo.mStackSearchStr;
}
dbgExprEvaluator.mLanguage = pendingExpr->mFormatInfo.mLanguage;
dbgExprEvaluator.mReferenceId = &pendingExpr->mReferenceId;
dbgExprEvaluator.mExpressionFlags = pendingExpr->mExpressionFlags;
@ -9446,6 +9446,8 @@ String WinDebugger::EvaluateContinue(DbgPendingExpr* pendingExpr, BfPassInstance
if (dbgExprEvaluator.mHadSideEffects)
val += "\n:sideeffects";
if ((dbgExprEvaluator.mStackSearch != NULL) && (dbgExprEvaluator.mStackSearch->mStartingStackIdx != dbgExprEvaluator.mCallStackIdx))
val += StrFormat("\n:stackIdx\t%d", dbgExprEvaluator.mCallStackIdx);
auto underlyingType = exprResult.mType->RemoveModifiers();
bool canEdit = true;
@ -9625,13 +9627,172 @@ String WinDebugger::Evaluate(const StringImpl& expr, DwFormatInfo formatInfo, in
formatInfo.mAllowStringView = true;
}
auto terminatedExpr = expr + ";";
auto prevActiveThread = mActiveThread;
bool restoreActiveThread = false;
defer(
{
if (restoreActiveThread)
SetActiveThread(prevActiveThread->mThreadId);
});
bool usedSpecifiedLock = false;
int stackIdxOverride = -1;
if (terminatedExpr.StartsWith('{'))
{
int closeIdx = terminatedExpr.IndexOf('}');
String locString = terminatedExpr.Substring(1, closeIdx - 1);
for (int i = 0; i <= closeIdx; i++)
terminatedExpr[i] = ' ';
locString.Trim();
if (locString.StartsWith("Thread:", StringImpl::CompareKind_OrdinalIgnoreCase))
{
bool foundLockMatch = true;
locString.Remove(0, 7);
char* endPtr = NULL;
int64 threadId = (int64)strtoll(locString.c_str(), &endPtr, 10);
if (endPtr != NULL)
{
locString.Remove(0, endPtr - locString.c_str());
locString.Trim();
if (locString.StartsWith("SP:", StringImpl::CompareKind_OrdinalIgnoreCase))
{
locString.Remove(0, 3);
char* endPtr = NULL;
uint64 sp = (uint64)strtoll(locString.c_str(), &endPtr, 16);
if (endPtr != NULL)
{
locString.Remove(0, endPtr - locString.c_str());
locString.Trim();
if (locString.StartsWith("Func:", StringImpl::CompareKind_OrdinalIgnoreCase))
{
locString.Remove(0, 5);
char* endPtr = NULL;
int64 funcAddr = (int64)strtoll(locString.c_str(), &endPtr, 16);
if (endPtr != NULL)
{
// Actually do it
if ((mActiveThread != NULL) && (mActiveThread->mThreadId != threadId))
restoreActiveThread = true;
if ((mActiveThread == NULL) || (mActiveThread->mThreadId != threadId))
SetActiveThread(threadId);
if ((mActiveThread != NULL) && (mActiveThread->mThreadId == threadId))
{
int foundStackIdx = -1;
int checkStackIdx = 0;
while (true)
{
if (checkStackIdx >= mCallStack.mSize)
UpdateCallStack();
if (checkStackIdx >= mCallStack.mSize)
break;
auto stackFrame = mCallStack[checkStackIdx];
if (stackFrame->mRegisters.GetSP() == sp)
{
foundStackIdx = checkStackIdx;
break;
}
if (stackFrame->mRegisters.GetSP() > sp)
{
foundStackIdx = checkStackIdx - 1;
break;
}
checkStackIdx++;
}
if (foundStackIdx != -1)
{
UpdateCallStackMethod(foundStackIdx);
auto stackFrame = mCallStack[foundStackIdx];
if ((stackFrame->mSubProgram != NULL) && ((int64)stackFrame->mSubProgram->mBlock.mLowPC == funcAddr))
{
if ((callStackIdx != foundStackIdx) || (mActiveThread != prevActiveThread))
usedSpecifiedLock = true;
callStackIdx = foundStackIdx;
foundLockMatch = true;
}
}
}
}
}
}
}
}
if (!foundLockMatch)
return "!Locked stack frame not found";
bool doClear = false;
for (int i = closeIdx; i < terminatedExpr.mLength; i++)
{
char c = terminatedExpr[i];
if (doClear)
{
terminatedExpr[i] = ' ';
if (c == '}')
break;
}
else
{
if (c == '{')
{
int endIdx = terminatedExpr.IndexOf('}');
if (endIdx == -1)
break;
terminatedExpr[i] = ' ';
doClear = true;
}
else if (!::isspace((uint8)c))
break;
}
}
}
else if (!locString.IsEmpty())
{
const char* checkPtr = locString.c_str();
if ((*checkPtr == '^') || (*checkPtr == '@'))
checkPtr++;
char* endPtr = NULL;
int useCallStackIdx = strtol(checkPtr, &endPtr, 10);
if (endPtr == locString.c_str() + locString.length())
{
if (locString[0] == '@')
callStackIdx = useCallStackIdx;
else
callStackIdx += useCallStackIdx;
stackIdxOverride = callStackIdx;
}
else
{
formatInfo.mStackSearchStr = locString;
}
}
}
auto dbgModule = GetCallStackDbgModule(callStackIdx);
auto dbgSubprogram = GetCallStackSubprogram(callStackIdx);
DbgCompileUnit* dbgCompileUnit = NULL;
if (dbgSubprogram != NULL)
dbgCompileUnit = dbgSubprogram->mCompileUnit;
auto terminatedExpr = expr + ";";
if ((expr.length() > 0) && (expr[0] == '!'))
{
if (expr.StartsWith("!step "))
@ -9688,7 +9849,7 @@ String WinDebugger::Evaluate(const StringImpl& expr, DwFormatInfo formatInfo, in
parser->mCompatMode = true;
BfPassInstance bfPassInstance(mBfSystem);
if ((terminatedExpr.length() > 2) && (terminatedExpr[0] == '@'))
{
if (terminatedExpr[1] == '!') // Return string as error
@ -9852,6 +10013,13 @@ String WinDebugger::Evaluate(const StringImpl& expr, DwFormatInfo formatInfo, in
}
else
delete pendingExpr;
if ((!formatInfo.mRawString) && (usedSpecifiedLock))
result += "\n:usedLock";
if ((!formatInfo.mRawString) && (stackIdxOverride != -1))
result += StrFormat("\n:stackIdx\t%d", stackIdxOverride);
return result;
}
@ -10663,10 +10831,33 @@ void WinDebugger::SetActiveThread(int threadId)
{
AutoCrit autoCrit(mDebugManager->mCritSect);
if ((mActiveThread != NULL) && (mActiveThread->mThreadId == threadId))
return;
auto prevThread = mActiveThread;
if (mThreadMap.TryGetValue(threadId, &mActiveThread))
{
BfLogDbg("SetActiveThread %d\n", threadId);
ClearCallStack();
if (prevThread != NULL)
{
Array<WdStackFrame*>* prevFrameArray = NULL;
mSavedCallStacks.TryAdd(prevThread, NULL, &prevFrameArray);
for (auto frameInfo : *prevFrameArray)
delete frameInfo;
*prevFrameArray = mCallStack;
mCallStack.Clear();
}
DoClearCallStack(false);
Array<WdStackFrame*>* newFrameArray = NULL;
if (mSavedCallStacks.TryGetValue(mActiveThread, &newFrameArray))
{
mCallStack = *newFrameArray;
newFrameArray->Clear();
}
}
else
{
@ -10718,8 +10909,8 @@ bool WinDebugger::IsActiveThreadWaiting()
return mActiveThread == mDebuggerWaitingThread;
}
void WinDebugger::ClearCallStack()
{
void WinDebugger::DoClearCallStack(bool clearSavedStacks)
{
AutoCrit autoCrit(mDebugManager->mCritSect);
BfLogDbg("ClearCallstack\n");
@ -10728,10 +10919,25 @@ void WinDebugger::ClearCallStack()
for (auto wdStackFrame : mCallStack)
delete wdStackFrame;
if (clearSavedStacks)
{
for (auto& kv : mSavedCallStacks)
{
for (auto wdStackFrame : kv.mValue)
delete wdStackFrame;
}
mSavedCallStacks.Clear();
}
mCallStack.Clear();
mIsPartialCallStack = true;
}
void WinDebugger::ClearCallStack()
{
DoClearCallStack(true);
}
void WinDebugger::UpdateCallStack(bool slowEarlyOut)
{
AutoCrit autoCrit(mDebugManager->mCritSect);
@ -11356,6 +11562,27 @@ String WinDebugger::GetStackFrameInfo(int stackFrameIdx, intptr* addr, String* o
return outName;
}
String WinDebugger::GetStackFrameId(int stackFrameIdx)
{
AutoCrit autoCrit(mDebugManager->mCritSect);
if (!FixCallStackIdx(stackFrameIdx))
return "";
int actualStackFrameIdx = BF_MAX(0, stackFrameIdx);
UpdateCallStackMethod(actualStackFrameIdx);
WdStackFrame* wdStackFrame = mCallStack[actualStackFrameIdx];
intptr addr = 0;
if (wdStackFrame->mSubProgram != NULL)
addr = wdStackFrame->mSubProgram->mBlock.mLowPC;
else
addr = wdStackFrame->mRegisters.GetPC();
String str = StrFormat("Thread:%d SP:%llX Func:%llX", mActiveThread->mThreadId, wdStackFrame->mRegisters.GetSP(), addr);
return str;
}
String WinDebugger::Callstack_GetStackFrameOldFileInfo(int stackFrameIdx)
{
AutoCrit autoCrit(mDebugManager->mCritSect);
@ -11550,6 +11777,10 @@ String WinDebugger::GetAddressSourceLocation(intptr address)
String WinDebugger::GetAddressSymbolName(intptr address, bool demangle)
{
auto subProgram = mDebugTarget->FindSubProgram(address);
if (subProgram != NULL)
return subProgram->ToString();
String outSymbol;
addr_target offset = 0;
DbgModule* dbgModule;

View file

@ -416,6 +416,7 @@ public:
Dictionary<addr_target, WdBreakpoint*> mBreakpointAddrMap;
Array<int> mFreeMemoryBreakIndices;
Array<WdStackFrame*> mCallStack;
Dictionary<WdThreadInfo*, Array<WdStackFrame*>> mSavedCallStacks;
bool mIsPartialCallStack;
int mRequestedStackFrameIdx; // -1 means to show mShowPCOverride, -2 means "auto" stop, -3 means breakpoint - normally 0 but during inlining the address can be ambiguous
int mBreakStackFrameIdx;
@ -560,6 +561,7 @@ public:
bool CheckConditionalBreakpoint(WdBreakpoint* breakpoint, DbgSubprogram* dbgSubprogram, addr_target pcAddress);
void CleanupDebugEval(bool restoreRegisters = true);
bool FixCallStackIdx(int& callStackIdx);
void DoClearCallStack(bool clearSavedStacks);
int LoadDebugInfoForModule(DbgModule* dbgModule);
@ -631,6 +633,7 @@ public:
virtual void GetCodeAddrInfo(intptr addr, 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;
virtual String Callstack_GetStackFrameOldFileInfo(int stackFrameIdx) override;
virtual int GetJmpState(int stackFrameIdx) override;
virtual intptr GetStackFrameCalleeAddr(int stackFrameIdx) override;