mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-08 11:38:21 +02:00
Beefy::String changes, lambda hotswap fixes
Changed some string internals related to StringViewsma Added an "incompatible capture" error for lambdas when the captures change
This commit is contained in:
parent
767a3fafd9
commit
2f01cc14dd
25 changed files with 544 additions and 180 deletions
|
@ -405,7 +405,7 @@ namespace std
|
|||
{
|
||||
size_t operator()(const NS_BF_DBG::CvModuleInfoNameEntry& val) const
|
||||
{
|
||||
return NS_BF_DBG::CvModuleInfoNameEntry::GetHashCode(val.mModuleInfo->mModuleName);
|
||||
return NS_BF_DBG::CvModuleInfoNameEntry::GetHashCode(Beefy::StringImpl::MakeRef(val.mModuleInfo->mModuleName));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -9553,7 +9553,9 @@ BfLambdaInstance* BfExprEvaluator::GetLambdaInstance(BfLambdaBindExpression* lam
|
|||
mModule->mBfIRBuilder->PopulateType(useTypeInstance);
|
||||
mModule->PopulateType(useTypeInstance);
|
||||
|
||||
methodDef->mIsStatic = closureTypeInst == NULL;
|
||||
// If we are allowing hot swapping, we need to always mangle the name to non-static because if we add a capture
|
||||
// later then we need to have the mangled names match
|
||||
methodDef->mIsStatic = (closureTypeInst == NULL) && (!mModule->mCompiler->mOptions.mAllowHotSwapping);
|
||||
|
||||
SizedArray<BfIRType, 3> newTypes;
|
||||
SizedArray<BfIRType, 8> origParamTypes;
|
||||
|
@ -9598,12 +9600,12 @@ BfLambdaInstance* BfExprEvaluator::GetLambdaInstance(BfLambdaBindExpression* lam
|
|||
methodDef->mName.RemoveToEnd(prevSepPos);
|
||||
}
|
||||
|
||||
if (closureTypeInst != NULL)
|
||||
{
|
||||
StringT<128> typeInstName;
|
||||
BfMangler::Mangle(typeInstName,mModule->mCompiler->GetMangleKind(), closureTypeInst);
|
||||
closureHashCtx.MixinStr(typeInstName);
|
||||
}
|
||||
// if (closureTypeInst != NULL)
|
||||
// {
|
||||
// StringT<128> typeInstName;
|
||||
// BfMangler::Mangle(typeInstName,mModule->mCompiler->GetMangleKind(), closureTypeInst);
|
||||
// closureHashCtx.MixinStr(typeInstName);
|
||||
// }
|
||||
|
||||
auto checkMethodState = mModule->mCurMethodState;
|
||||
while (checkMethodState != NULL)
|
||||
|
|
|
@ -778,11 +778,7 @@ BfModule* gLastCreatedModule = NULL;
|
|||
BfModule::BfModule(BfContext* context, const StringImpl& moduleName)
|
||||
{
|
||||
BfLogSys(context->mSystem, "BfModule::BFModule %p %s\n", this, moduleName.c_str());
|
||||
if (moduleName.Contains("_Comparison_"))
|
||||
{
|
||||
NOP;
|
||||
}
|
||||
|
||||
|
||||
gLastCreatedModule = this;
|
||||
|
||||
mContext = context;
|
||||
|
@ -14930,7 +14926,10 @@ void BfModule::ProcessMethod_ProcessDeferredLocals(int startIdx)
|
|||
mCurMethodState->mClosureState = &closureState;
|
||||
//closureState.mConstLocals = deferredLocalMethod->mConstLocals;
|
||||
closureState.mReturnType = lambdaInstance->mMethodInstance->mReturnType;
|
||||
closureState.mClosureType = lambdaInstance->mClosureTypeInstance;
|
||||
if (lambdaInstance->mClosureTypeInstance != NULL)
|
||||
closureState.mClosureType = lambdaInstance->mClosureTypeInstance;
|
||||
else
|
||||
closureState.mClosureType = lambdaInstance->mDelegateTypeInstance;
|
||||
closureState.mClosureInstanceInfo = lambdaInstance->mMethodInstance->mMethodInfoEx->mClosureInstanceInfo;
|
||||
mCurMethodState->mMixinState = lambdaInstance->mDeclMixinState;
|
||||
|
||||
|
|
|
@ -1773,7 +1773,7 @@ public:
|
|||
HashSet<int> mDefinedStrings;
|
||||
|
||||
public:
|
||||
BfVDataModule(BfContext* context) : BfModule(context, "vdata")
|
||||
BfVDataModule(BfContext* context) : BfModule(context, StringImpl::MakeRef("vdata"))
|
||||
{
|
||||
}
|
||||
};
|
||||
|
|
|
@ -59,10 +59,10 @@ void MemReporter::Report(int depth, Entry* entry)
|
|||
}
|
||||
}
|
||||
|
||||
void MemReporter::BeginSection(const StringImpl& name)
|
||||
void MemReporter::BeginSection(const StringView& name)
|
||||
{
|
||||
Entry** entryPtr;
|
||||
if (!mCurEntry->mChildren.TryAdd(name, NULL, &entryPtr))
|
||||
if (!mCurEntry->mChildren.TryAdd(StringImpl::MakeRef(name), NULL, &entryPtr))
|
||||
{
|
||||
mCurEntry = *entryPtr;
|
||||
mCurEntry->mCount++;
|
||||
|
@ -82,7 +82,7 @@ void MemReporter::Add(int size)
|
|||
mCurEntry->mSize += size;
|
||||
}
|
||||
|
||||
void MemReporter::Add(const StringImpl& name, int size)
|
||||
void MemReporter::Add(const StringView& name, int size)
|
||||
{
|
||||
BeginSection(name);
|
||||
Add(size);
|
||||
|
|
|
@ -44,9 +44,9 @@ public:
|
|||
MemReporter();
|
||||
~MemReporter();
|
||||
|
||||
void BeginSection(const StringImpl& name);
|
||||
void BeginSection(const StringView& name);
|
||||
void Add(int size);
|
||||
void Add(const StringImpl& name, int size);
|
||||
void Add(const StringView& name, int size);
|
||||
|
||||
template <typename T>
|
||||
void AddVec(const T& vec, bool addContainerSize = true)
|
||||
|
@ -55,7 +55,7 @@ public:
|
|||
}
|
||||
|
||||
template <typename T>
|
||||
void AddVec(const StringImpl& name, const T& vec, bool addContainerSize = true)
|
||||
void AddVec(const StringView& name, const T& vec, bool addContainerSize = true)
|
||||
{
|
||||
BeginSection(name);
|
||||
Add((addContainerSize ? sizeof(T) : 0) + (int)vec.mAllocSize * sizeof(typename T::value_type));
|
||||
|
@ -79,7 +79,7 @@ public:
|
|||
}
|
||||
|
||||
template <typename T>
|
||||
void AddVecPtr(const StringImpl& name, const Array<T>& vec, bool addContainerSize = true)
|
||||
void AddVecPtr(const StringView& name, const Array<T>& vec, bool addContainerSize = true)
|
||||
{
|
||||
Add(name, (addContainerSize ? sizeof(T) : 0) +
|
||||
(int)vec.mAllocSize * sizeof(T) +
|
||||
|
@ -87,7 +87,7 @@ public:
|
|||
}
|
||||
|
||||
template <typename T>
|
||||
void AddMap(const StringImpl& name, const T& map, bool addContainerSize = true)
|
||||
void AddMap(const StringView& name, const T& map, bool addContainerSize = true)
|
||||
{
|
||||
Add(name, (addContainerSize ? sizeof(T) : 0) + map.mAllocSize * (sizeof(typename T::EntryPair) + sizeof(typename T::int_cosize)));
|
||||
}
|
||||
|
@ -99,7 +99,7 @@ public:
|
|||
}
|
||||
|
||||
template <typename T>
|
||||
void AddHashSet(const StringImpl& name, const T& map, bool addContainerSize = true)
|
||||
void AddHashSet(const StringView& name, const T& map, bool addContainerSize = true)
|
||||
{
|
||||
Add(name, (addContainerSize ? sizeof(T) : 0) + map.mAllocSize * (sizeof(typename T::Entry) + sizeof(typename T::int_cosize)));
|
||||
}
|
||||
|
@ -115,7 +115,7 @@ public:
|
|||
Add((addContainerSize ? sizeof(StringImpl) : 0) + (int)str.GetAllocSize());
|
||||
}
|
||||
|
||||
void AddStr(const StringImpl& name, const StringImpl& str, bool addContainerSize = true)
|
||||
void AddStr(const StringView& name, const StringImpl& str, bool addContainerSize = true)
|
||||
{
|
||||
Add(name, (addContainerSize ? sizeof(StringImpl) : 0) + (int)str.GetAllocSize());
|
||||
}
|
||||
|
@ -125,7 +125,7 @@ public:
|
|||
|
||||
|
||||
template <typename T>
|
||||
void AddBumpAlloc(const StringImpl& name, const T& alloc)
|
||||
void AddBumpAlloc(const StringView& name, const T& alloc)
|
||||
{
|
||||
BeginSection(name);
|
||||
|
||||
|
|
|
@ -390,7 +390,7 @@ String DbgSubprogram::ToString()
|
|||
{
|
||||
if (mLinkName[0] == '<')
|
||||
return mLinkName;
|
||||
str = BfDemangler::Demangle(mLinkName, language);
|
||||
str = BfDemangler::Demangle(StringImpl::MakeRef(mLinkName), language);
|
||||
// Strip off the params since we need to generate those ourselves
|
||||
int parenPos = (int)str.IndexOf('(');
|
||||
if (parenPos != -1)
|
||||
|
@ -776,6 +776,13 @@ bool DbgSubprogram::ThisIsSplat()
|
|||
return strncmp(mBlock.mVariables.mHead->mName, "$this$", 6) == 0;
|
||||
}
|
||||
|
||||
bool DbgSubprogram::IsLambda()
|
||||
{
|
||||
if (mName == NULL)
|
||||
return false;
|
||||
return StringView(mName).Contains('$');
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DbgSubprogram::~DbgSubprogram()
|
||||
|
@ -863,7 +870,7 @@ void DbgSrcFile::RehupLineData()
|
|||
for (int idx = 0; idx < (int)mLineDataRefs.size(); idx++)
|
||||
{
|
||||
auto dbgSubprogram = mLineDataRefs[idx];
|
||||
if (dbgSubprogram->mWasModuleHotReplaced)
|
||||
if (dbgSubprogram->mHotReplaceKind != DbgSubprogram::HotReplaceKind_None)
|
||||
{
|
||||
mLineDataRefs.RemoveAtFast(idx);
|
||||
idx--;
|
||||
|
@ -1548,6 +1555,7 @@ String DbgType::ToString(DbgLanguage language, bool allowDirectBfObject)
|
|||
else
|
||||
return mParent->ToString(language) + "::" + nameP;
|
||||
}
|
||||
|
||||
|
||||
switch (mTypeCode)
|
||||
{
|
||||
|
@ -1999,6 +2007,39 @@ DbgModule::~DbgModule()
|
|||
delete data;
|
||||
}
|
||||
|
||||
DbgSubprogram* DbgModule::FindSubprogram(DbgType* dbgType, const char * methodName)
|
||||
{
|
||||
dbgType = dbgType->GetPrimaryType();
|
||||
dbgType->PopulateType();
|
||||
|
||||
if (dbgType->mNeedsGlobalsPopulated)
|
||||
PopulateTypeGlobals(dbgType);
|
||||
|
||||
for (auto methodNameEntry : dbgType->mMethodNameList)
|
||||
{
|
||||
if ((methodNameEntry->mCompileUnitId != -1) && (strcmp(methodNameEntry->mName, methodName) == 0))
|
||||
{
|
||||
// If we hot-replaced this type then we replaced and parsed all the methods too
|
||||
if (!dbgType->mCompileUnit->mDbgModule->mIsHotObjectFile)
|
||||
dbgType->mCompileUnit->mDbgModule->MapCompileUnitMethods(methodNameEntry->mCompileUnitId);
|
||||
methodNameEntry->mCompileUnitId = -1;
|
||||
}
|
||||
}
|
||||
|
||||
DbgSubprogram* result = NULL;
|
||||
for (auto method : dbgType->mMethodList)
|
||||
{
|
||||
if (strcmp(method->mName, methodName) == 0)
|
||||
{
|
||||
method->PopulateSubprogram();
|
||||
if ((result == NULL) || (method->mBlock.mLowPC != 0))
|
||||
result = method;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void DbgModule::Fail(const StringImpl& error)
|
||||
{
|
||||
if (mFailMsgPtr != NULL)
|
||||
|
@ -4960,7 +5001,8 @@ void DbgModule::HotReplaceType(DbgType* newType)
|
|||
HashSet<DbgSrcFile*> checkedFiles;
|
||||
for (auto method : primaryType->mMethodList)
|
||||
{
|
||||
method->mWasModuleHotReplaced = true;
|
||||
//method->mWasModuleHotReplaced = true;
|
||||
method->mHotReplaceKind = DbgSubprogram::HotReplaceKind_Orphaned; // May be temporarily orphaned
|
||||
|
||||
if (method->mLineInfo == NULL)
|
||||
continue;
|
||||
|
@ -5014,35 +5056,154 @@ void DbgModule::HotReplaceType(DbgType* newType)
|
|||
primaryType->mHotReplacedMethodList.PushFront(method);
|
||||
mHotPrimaryTypes.Add(primaryType);
|
||||
}
|
||||
|
||||
|
||||
Dictionary<StringView, DbgSubprogram*> oldProgramMap;
|
||||
for (auto oldMethod : primaryType->mHotReplacedMethodList)
|
||||
{
|
||||
oldMethod->PopulateSubprogram();
|
||||
if (oldMethod->mBlock.IsEmpty())
|
||||
continue;
|
||||
auto symInfo = mDebugTarget->mSymbolMap.Get(oldMethod->mBlock.mLowPC);
|
||||
if (symInfo != NULL)
|
||||
{
|
||||
oldProgramMap.TryAdd(symInfo->mName, oldMethod);
|
||||
}
|
||||
}
|
||||
|
||||
bool setHotJumpFailed = false;
|
||||
while (!newType->mMethodList.IsEmpty())
|
||||
{
|
||||
DbgSubprogram* newMethod = newType->mMethodList.PopFront();
|
||||
if (!newMethod->mBlock.IsEmpty())
|
||||
{
|
||||
newMethod->PopulateSubprogram();
|
||||
newMethod->PopulateSubprogram();
|
||||
|
||||
bool found = false;
|
||||
for (auto oldMethod : primaryType->mHotReplacedMethodList)
|
||||
auto symInfo = mDebugTarget->mSymbolMap.Get(newMethod->mBlock.mLowPC);
|
||||
if (symInfo != NULL)
|
||||
{
|
||||
if (oldMethod->mBlock.IsEmpty())
|
||||
continue;
|
||||
if (oldMethod->Equals(newMethod))
|
||||
DbgSubprogram* oldMethod = NULL;
|
||||
if (oldProgramMap.TryGetValue(symInfo->mName, &oldMethod))
|
||||
{
|
||||
if (!setHotJumpFailed)
|
||||
bool doHotJump = false;
|
||||
|
||||
if (oldMethod->Equals(newMethod))
|
||||
{
|
||||
if (!mDebugger->SetHotJump(oldMethod, newMethod))
|
||||
setHotJumpFailed = true;
|
||||
oldMethod->mWasHotReplaced = true;
|
||||
}
|
||||
doHotJump = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// When mangles match but the actual signatures don't match, that can mean that the call signature was changed
|
||||
// and thus it's actually a different method and shouldn't hot jump OR it could be lambda whose captures changed.
|
||||
// When the lambda captures change, the user didn't actually enter a different signature so we want to do a hard
|
||||
// fail if the old code gets called to avoid confusion of "why aren't my changes working?"
|
||||
|
||||
// If we removed captures then we can still do the hot jump. Otherwise we have to fail...
|
||||
doHotJump = false;
|
||||
if ((oldMethod->IsLambda()) && (oldMethod->GetParamCount() == 0) && (newMethod->GetParamCount() == 0) &&
|
||||
(oldMethod->mHasThis) && (newMethod->mHasThis))
|
||||
{
|
||||
auto oldParam = oldMethod->mParams.front();
|
||||
auto newParam = newMethod->mParams.front();
|
||||
|
||||
if ((oldParam->mType->IsPointer()) && (newParam->mType->IsPointer()))
|
||||
{
|
||||
auto oldType = oldParam->mType->mTypeParam->GetPrimaryType();
|
||||
auto newType = newParam->mType->mTypeParam->GetPrimaryType();
|
||||
if ((oldType->IsStruct()) && (newType->IsStruct()))
|
||||
{
|
||||
bool wasMatch = true;
|
||||
|
||||
auto oldMember = oldType->mMemberList.front();
|
||||
auto newMember = newType->mMemberList.front();
|
||||
while (newMember != NULL)
|
||||
{
|
||||
if (oldMember == NULL)
|
||||
{
|
||||
wasMatch = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((oldMember->mName == NULL) || (newMember->mName == NULL))
|
||||
{
|
||||
wasMatch = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (strcmp(oldMember->mName, newMember->mName) != 0)
|
||||
{
|
||||
wasMatch = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!oldMember->mType->Equals(newMember->mType))
|
||||
{
|
||||
wasMatch = false;
|
||||
break;
|
||||
}
|
||||
|
||||
oldMember = oldMember->mNext;
|
||||
newMember = newMember->mNext;
|
||||
}
|
||||
|
||||
if (wasMatch)
|
||||
doHotJump = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!doHotJump)
|
||||
{
|
||||
mDebugTarget->mDebugger->PhysSetBreakpoint(oldMethod->mBlock.mLowPC);
|
||||
oldMethod->mHotReplaceKind = DbgSubprogram::HotReplaceKind_Invalid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (doHotJump)
|
||||
{
|
||||
if (!setHotJumpFailed)
|
||||
{
|
||||
if (!mDebugger->SetHotJump(oldMethod, newMethod->mBlock.mLowPC, (int)(newMethod->mBlock.mHighPC - newMethod->mBlock.mLowPC)))
|
||||
setHotJumpFailed = true;
|
||||
}
|
||||
oldMethod->mHotReplaceKind = DbgSubprogram::HotReplaceKind_Replaced;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
newMethod->mParentType = primaryType;
|
||||
primaryType->mMethodList.PushBack(newMethod);
|
||||
}
|
||||
|
||||
//mDebugTarget->mSymbolMap.Get()
|
||||
|
||||
// bool setHotJumpFailed = false;
|
||||
// while (!newType->mMethodList.IsEmpty())
|
||||
// {
|
||||
// DbgSubprogram* newMethod = newType->mMethodList.PopFront();
|
||||
// if (!newMethod->mBlock.IsEmpty())
|
||||
// {
|
||||
// newMethod->PopulateSubprogram();
|
||||
//
|
||||
// bool found = false;
|
||||
// for (auto oldMethod : primaryType->mHotReplacedMethodList)
|
||||
// {
|
||||
// if (oldMethod->mBlock.IsEmpty())
|
||||
// continue;
|
||||
// if (oldMethod->Equals(newMethod))
|
||||
// {
|
||||
// if (!setHotJumpFailed)
|
||||
// {
|
||||
// if (!mDebugger->SetHotJump(oldMethod, newMethod))
|
||||
// setHotJumpFailed = true;
|
||||
// oldMethod->mWasHotReplaced = true;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// newMethod->mParentType = primaryType;
|
||||
// primaryType->mMethodList.PushBack(newMethod);
|
||||
// }
|
||||
|
||||
primaryType->mCompileUnit->mWasHotReplaced = true;
|
||||
|
||||
primaryType->mNeedsGlobalsPopulated = newType->mNeedsGlobalsPopulated;
|
||||
|
|
|
@ -358,6 +358,14 @@ public:
|
|||
};
|
||||
#endif
|
||||
|
||||
enum HotReplaceKind : uint8
|
||||
{
|
||||
HotReplaceKind_None = 0,
|
||||
HotReplaceKind_Replaced = 1,
|
||||
HotReplaceKind_Orphaned = 2, // Module was hot replaced but a new version of the subprogram wasn't found
|
||||
HotReplaceKind_Invalid = 3 // Mangles matched but arguments were incompatible
|
||||
};
|
||||
|
||||
const char* mName;
|
||||
const char* mLinkName;
|
||||
int mTemplateNameIdx;
|
||||
|
@ -376,8 +384,7 @@ public:
|
|||
bool mVirtual;
|
||||
bool mHasThis;
|
||||
bool mNeedLineDataFixup;
|
||||
bool mWasHotReplaced;
|
||||
bool mWasModuleHotReplaced; // Module was hot replaced but a new version of the subprogram wasn't found
|
||||
HotReplaceKind mHotReplaceKind;
|
||||
bool mIsOptimized;
|
||||
bool mHasLineAddrGaps; // There are gaps of addresses which are not covered by lineinfo
|
||||
DbgLineInfo* mLineInfo;
|
||||
|
@ -397,8 +404,7 @@ public:
|
|||
mLinkName = NULL;
|
||||
mHasThis = false;
|
||||
mNeedLineDataFixup = true;
|
||||
mWasHotReplaced = false;
|
||||
mWasModuleHotReplaced = false;
|
||||
mHotReplaceKind = HotReplaceKind_None;
|
||||
mHasLineAddrGaps = false;
|
||||
mPrologueSize = -1;
|
||||
mParentType = NULL;
|
||||
|
@ -427,6 +433,7 @@ public:
|
|||
String GetParamName(int paramIdx);
|
||||
bool IsGenericMethod();
|
||||
bool ThisIsSplat();
|
||||
bool IsLambda();
|
||||
|
||||
DbgSubprogram* GetRootInlineParent()
|
||||
{
|
||||
|
@ -1201,6 +1208,7 @@ public:
|
|||
virtual String GetOldSourceCommand(const StringImpl& path) { return ""; }
|
||||
virtual bool DbgIsStrMutable(const char* str) { return true; } // Always assume its a copy
|
||||
virtual addr_target LocateSymbol(const StringImpl& name) { return 0; }
|
||||
virtual DbgSubprogram* FindSubprogram(DbgType* dbgType, const char* methodName);
|
||||
|
||||
void Fail(const StringImpl& error);
|
||||
void FindTemplateStr(const char*& name, int& templateNameIdx);
|
||||
|
|
|
@ -128,7 +128,7 @@ void DbgHotScanner::PopulateHotCallstacks()
|
|||
{
|
||||
auto subProgram = stackFrame->mSubProgram;
|
||||
|
||||
if (subProgram->mWasHotReplaced)
|
||||
if (subProgram->mHotReplaceKind == DbgSubprogram::HotReplaceKind_Replaced)
|
||||
subProgram = mDebugger->TryFollowHotJump(subProgram, stackFrame->mRegisters.GetPC());
|
||||
|
||||
AddSubProgram(subProgram, false, "");
|
||||
|
|
|
@ -2052,14 +2052,14 @@ void BlCodeView::CreateLinkerSymStream()
|
|||
|
||||
ENVBLOCKSYM envBlock = { 0 };
|
||||
envBlock.rectyp = S_ENVBLOCK;
|
||||
str = "cwd"; str.Append(0);
|
||||
str += cwd; str.Append(0);
|
||||
str += "exe"; str.Append(0);
|
||||
str += moduleFileName; str.Append(0);
|
||||
str += "pdb"; str.Append(0);
|
||||
str += mMsf.mFileName; str.Append(0);
|
||||
str += "cmd"; str.Append(0);
|
||||
str += GetCommandLineA(); str.Append(0);
|
||||
str = "cwd"; str.Append('\0');
|
||||
str += cwd; str.Append('\0');
|
||||
str += "exe"; str.Append('\0');
|
||||
str += moduleFileName; str.Append('\0');
|
||||
str += "pdb"; str.Append('\0');
|
||||
str += mMsf.mFileName; str.Append('\0');
|
||||
str += "cmd"; str.Append('\0');
|
||||
str += GetCommandLineA(); str.Append('\0');
|
||||
OUT_WITH_STR(ENVBLOCKSYM, envBlock, rgsz);
|
||||
|
||||
for (auto segment : mContext->mSegments)
|
||||
|
|
|
@ -1863,10 +1863,20 @@ bool WinDebugger::DoUpdate()
|
|||
bool isNonDebuggerBreak = false;
|
||||
|
||||
if (wasDebugBreakpoint)
|
||||
{
|
||||
{
|
||||
// Go ahead and set EIP back one instruction
|
||||
BF_CONTEXT_IP(lcContext)--;
|
||||
BF_SetThreadContext(threadInfo->mHThread, &lcContext);
|
||||
|
||||
if ((dwSubprogram != NULL) && (dwSubprogram->mHotReplaceKind == DbgSubprogram::HotReplaceKind_Invalid) &&
|
||||
(pcAddress == dwSubprogram->mBlock.mLowPC))
|
||||
{
|
||||
BfLogDbg("Hit HotReplaceKind_Invalid breakpoint\n");
|
||||
mRunState = RunState_Paused;
|
||||
mDebugManager->mOutMessages.push_back("error This lambda was replaced by a new version that has incompatible captures. A program restart is required.");
|
||||
PhysRemoveBreakpoint(pcAddress);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2223,9 +2233,9 @@ bool WinDebugger::DoUpdate()
|
|||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
BfLogDbg("Ignoring break (old or ignored breakpoint)\n");
|
||||
mRunState = RunState_Running;
|
||||
mRunState = RunState_Running;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2363,7 +2373,7 @@ bool WinDebugger::DoUpdate()
|
|||
DbgSubprogram* dwSubprogram = NULL;
|
||||
DbgLineData* dwLineData = FindLineDataAtAddress(pcAddress, &dwSubprogram, NULL, NULL, DbgOnDemandKind_LocalOnly);
|
||||
|
||||
if ((dwSubprogram != NULL) && (pcAddress == dwSubprogram->mBlock.mLowPC) && (dwSubprogram->mWasHotReplaced))
|
||||
if ((dwSubprogram != NULL) && (pcAddress == dwSubprogram->mBlock.mLowPC) && (dwSubprogram->mHotReplaceKind == DbgSubprogram::HotReplaceKind_Replaced))
|
||||
{
|
||||
BfLogDbg("Stepping through hot thunk\n");
|
||||
mRunState = RunState_Running;
|
||||
|
@ -2413,7 +2423,7 @@ bool WinDebugger::DoUpdate()
|
|||
}
|
||||
else if (dwSubprogram != NULL)
|
||||
{
|
||||
if ((dwSubprogram->mWasHotReplaced) && ((mStepType == StepType_StepInto) || (mStepType == StepType_StepInto_Unfiltered)))
|
||||
if ((dwSubprogram->mHotReplaceKind == DbgSubprogram::HotReplaceKind_Replaced) && ((mStepType == StepType_StepInto) || (mStepType == StepType_StepInto_Unfiltered)))
|
||||
{
|
||||
SingleStepX86();
|
||||
}
|
||||
|
@ -2963,7 +2973,7 @@ void WinDebugger::CheckBreakpoint(WdBreakpoint* wdBreakpoint, DbgSrcFile* srcFil
|
|||
if ((foundInSequence) && (subProgram != lastFoundSubprogram))
|
||||
foundInSequence = false;
|
||||
|
||||
if ((subProgram->mWasHotReplaced) && (address < subProgram->mBlock.mLowPC + sizeof(HotJumpOp)))
|
||||
if ((subProgram->mHotReplaceKind == DbgSubprogram::HotReplaceKind_Replaced) && (address < subProgram->mBlock.mLowPC + sizeof(HotJumpOp)))
|
||||
{
|
||||
// If this breakpoint ends up on the hot jmp instruction
|
||||
continue;
|
||||
|
@ -2973,7 +2983,7 @@ void WinDebugger::CheckBreakpoint(WdBreakpoint* wdBreakpoint, DbgSrcFile* srcFil
|
|||
{
|
||||
lastFoundSubprogram = subProgram;
|
||||
|
||||
if ((subProgram != NULL) && (subProgram->mWasHotReplaced) && (address == subProgram->mBlock.mLowPC))
|
||||
if ((subProgram != NULL) && (subProgram->mHotReplaceKind == DbgSubprogram::HotReplaceKind_Replaced) && (address == subProgram->mBlock.mLowPC))
|
||||
{
|
||||
// This instruction is actually the hot jump, we don't need a breakpoint here
|
||||
foundInSequence = true;
|
||||
|
@ -4957,7 +4967,7 @@ bool WinDebugger::RollBackStackFrame(CPURegisters* registers, bool isStackStart)
|
|||
return mDebugTarget->RollBackStackFrame(registers, NULL, isStackStart);
|
||||
}
|
||||
|
||||
bool WinDebugger::SetHotJump(DbgSubprogram* oldSubprogram, DbgSubprogram* newSubprogram)
|
||||
bool WinDebugger::SetHotJump(DbgSubprogram* oldSubprogram, addr_target newTarget, int newTargetSize)
|
||||
{
|
||||
//AutoCrit autoCrit(mDebugManager->mCritSect);
|
||||
BF_ASSERT(mDebugManager->mCritSect.mLockCount == 1);
|
||||
|
@ -4968,14 +4978,14 @@ bool WinDebugger::SetHotJump(DbgSubprogram* oldSubprogram, DbgSubprogram* newSub
|
|||
if (jmpInstEnd > oldSubprogram->mBlock.mHighPC)
|
||||
{
|
||||
if ((oldSubprogram->mBlock.mHighPC - oldSubprogram->mBlock.mLowPC == 1) &&
|
||||
(newSubprogram->mBlock.mHighPC - newSubprogram->mBlock.mLowPC == 1))
|
||||
(newTargetSize == 1))
|
||||
return true; // Special case for just stub 'ret' methods
|
||||
String err = StrFormat("Failed to hot replace method, method '%s' too small to insert hot thunk", newSubprogram->ToString().c_str());
|
||||
String err = StrFormat("Failed to hot replace method, method '%s' too small to insert hot thunk", oldSubprogram->ToString().c_str());
|
||||
Fail(err);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!oldSubprogram->mWasHotReplaced)
|
||||
if (oldSubprogram->mHotReplaceKind != DbgSubprogram::HotReplaceKind_Replaced)
|
||||
{
|
||||
for (int threadIdx = 0; threadIdx < (int)mThreadList.size(); threadIdx++)
|
||||
{
|
||||
|
@ -5068,7 +5078,7 @@ bool WinDebugger::SetHotJump(DbgSubprogram* oldSubprogram, DbgSubprogram* newSub
|
|||
|
||||
HotJumpOp jumpOp;
|
||||
jumpOp.mOpCode = 0xE9;
|
||||
jumpOp.mRelTarget = newSubprogram->mBlock.mLowPC - oldSubprogram->mBlock.mLowPC - sizeof(HotJumpOp);
|
||||
jumpOp.mRelTarget = newTarget - oldSubprogram->mBlock.mLowPC - sizeof(HotJumpOp);
|
||||
WriteMemory(oldSubprogram->mBlock.mLowPC, jumpOp);
|
||||
::FlushInstructionCache(mProcessInfo.hProcess, (void*)(intptr)oldSubprogram->mBlock.mLowPC, sizeof(HotJumpOp));
|
||||
return true;
|
||||
|
@ -5076,7 +5086,7 @@ bool WinDebugger::SetHotJump(DbgSubprogram* oldSubprogram, DbgSubprogram* newSub
|
|||
|
||||
DbgSubprogram* WinDebugger::TryFollowHotJump(DbgSubprogram* subprogram, addr_target addr)
|
||||
{
|
||||
if (!subprogram->mWasHotReplaced)
|
||||
if (subprogram->mHotReplaceKind != DbgSubprogram::HotReplaceKind_Replaced)
|
||||
return subprogram;
|
||||
|
||||
if (addr != subprogram->mBlock.mLowPC)
|
||||
|
@ -10794,14 +10804,14 @@ String WinDebugger::GetStackFrameInfo(int stackFrameIdx, intptr* addr, String* o
|
|||
if (!dbgModule->mDisplayName.empty())
|
||||
demangledName = dbgModule->mDisplayName + "!" + demangledName;
|
||||
|
||||
if (dwSubprogram->mWasHotReplaced)
|
||||
if ((dwSubprogram->mHotReplaceKind == DbgSubprogram::HotReplaceKind_Replaced) || (dwSubprogram->mHotReplaceKind == DbgSubprogram::HotReplaceKind_Invalid))
|
||||
demangledName = "#" + demangledName;
|
||||
|
||||
if (dbgModule->HasPendingDebugInfo())
|
||||
*outFlags |= FrameFlags_HasPendingDebugInfo;
|
||||
if (dbgModule->CanGetOldSource())
|
||||
*outFlags |= FrameFlags_CanGetOldSource;
|
||||
if (dwSubprogram->mWasHotReplaced)
|
||||
if ((dwSubprogram->mHotReplaceKind == DbgSubprogram::HotReplaceKind_Replaced) || (dwSubprogram->mHotReplaceKind == DbgSubprogram::HotReplaceKind_Invalid))
|
||||
*outFlags |= FrameFlags_WasHotReplaced;
|
||||
|
||||
if ((dwLineData != NULL) && (dwSrcFile != NULL))
|
||||
|
|
|
@ -479,7 +479,7 @@ public:
|
|||
bool PopulateRegisters(CPURegisters* registers, BF_CONTEXT& lcContext);
|
||||
virtual bool PopulateRegisters(CPURegisters* registers);
|
||||
bool RollBackStackFrame(CPURegisters* registers, bool isStackStart);
|
||||
bool SetHotJump(DbgSubprogram* oldSubprogram, DbgSubprogram* newSubprogram);
|
||||
bool SetHotJump(DbgSubprogram* oldSubprogram, addr_target newTarget, int newTargetSize);
|
||||
DbgSubprogram* TryFollowHotJump(DbgSubprogram* subprogram, addr_target addr);
|
||||
|
||||
bool ParseFormatInfo(DbgModule* dbgModule, const StringImpl& formatInfoStr, DwFormatInfo* formatInfo, BfPassInstance* bfPassInstance, int* assignExprOffset, String* assignExpr = NULL, String* errorString = NULL, DbgTypedValue contextTypedValue = DbgTypedValue());
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue