mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-09 03:52:19 +02:00
Fixed dbg evaluation issue with chained sret calls
This commit is contained in:
parent
79d13a3626
commit
95c603ada5
2 changed files with 90 additions and 15 deletions
|
@ -765,6 +765,7 @@ DbgExprEvaluator::DbgExprEvaluator(WinDebugger* winDebugger, DbgModule* dbgModul
|
||||||
mReceivingValue = NULL;
|
mReceivingValue = NULL;
|
||||||
mCallResults = NULL;
|
mCallResults = NULL;
|
||||||
mCallResultIdx = 0;
|
mCallResultIdx = 0;
|
||||||
|
mCallStackPreservePos = 0;
|
||||||
mPropGet = NULL;
|
mPropGet = NULL;
|
||||||
mPropSet = NULL;
|
mPropSet = NULL;
|
||||||
mPropSrc = NULL;
|
mPropSrc = NULL;
|
||||||
|
@ -6684,7 +6685,7 @@ bool DbgExprEvaluator::ResolveArgValues(const BfSizedArray<ASTREF(BfExpression*)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
DbgTypedValue DbgExprEvaluator::CreateCall(DbgSubprogram* method, DbgTypedValue thisVal, bool bypassVirtual, CPURegisters* registers)
|
DbgTypedValue DbgExprEvaluator::CreateCall(DbgSubprogram* method, DbgTypedValue thisVal, DbgTypedValue structRetVal, bool bypassVirtual, CPURegisters* registers)
|
||||||
{
|
{
|
||||||
// Why did we have the Not Runing thing for Exception? It means that when we crash we can't execute functions anymore.
|
// Why did we have the Not Runing thing for Exception? It means that when we crash we can't execute functions anymore.
|
||||||
// That doesn't seem good
|
// That doesn't seem good
|
||||||
|
@ -6694,9 +6695,32 @@ DbgTypedValue DbgExprEvaluator::CreateCall(DbgSubprogram* method, DbgTypedValue
|
||||||
return DbgTypedValue();
|
return DbgTypedValue();
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
|
#ifdef BF_WANTS_LOG_DBGEXPR
|
||||||
|
auto _GetResultString = [&](DbgTypedValue val)
|
||||||
|
{
|
||||||
|
String result;
|
||||||
|
if (val.mSrcAddress != 0)
|
||||||
|
{
|
||||||
|
result += StrFormat("0x%p ", val.mSrcAddress);
|
||||||
|
|
||||||
|
int64 vals[4] = { 0 };
|
||||||
|
mDebugger->ReadMemory(val.mSrcAddress, 4 * 8, vals);
|
||||||
|
|
||||||
|
result += StrFormat("%lld %lld %lld %lld", vals[0], vals[1], vals[2], vals[3]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result += StrFormat("%lld", val.mInt64);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
int curCallResultIdx = mCallResultIdx++;
|
int curCallResultIdx = mCallResultIdx++;
|
||||||
if (((mExpressionFlags & DwEvalExpressionFlag_AllowCalls) == 0) || (mCreatedPendingCall))
|
if (((mExpressionFlags & DwEvalExpressionFlag_AllowCalls) == 0) || (mCreatedPendingCall))
|
||||||
{
|
{
|
||||||
|
BfLogDbgExpr(" BlockedSideEffects\n");
|
||||||
|
|
||||||
mBlockedSideEffects = true;
|
mBlockedSideEffects = true;
|
||||||
return GetDefaultTypedValue(method->mReturnType);
|
return GetDefaultTypedValue(method->mReturnType);
|
||||||
}
|
}
|
||||||
|
@ -6706,16 +6730,32 @@ DbgTypedValue DbgExprEvaluator::CreateCall(DbgSubprogram* method, DbgTypedValue
|
||||||
// entire expression using the actual returned results for each of those calls until we can finally evaluate it as a whole
|
// entire expression using the actual returned results for each of those calls until we can finally evaluate it as a whole
|
||||||
if (curCallResultIdx < (int)mCallResults->size() - 1)
|
if (curCallResultIdx < (int)mCallResults->size() - 1)
|
||||||
{
|
{
|
||||||
return (*mCallResults)[curCallResultIdx].mResult;
|
auto callResult = (*mCallResults)[curCallResultIdx];
|
||||||
|
auto result = callResult.mResult;
|
||||||
|
|
||||||
|
if (!callResult.mSRetData.IsEmpty())
|
||||||
|
{
|
||||||
|
result = structRetVal;
|
||||||
|
mDebugger->WriteMemory(result.mSrcAddress, &callResult.mSRetData[0], (int)callResult.mSRetData.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
BfLogDbgExpr(" using cached results %s\n", _GetResultString(result).c_str());
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
else if (curCallResultIdx == (int)mCallResults->size() - 1)
|
else if (curCallResultIdx == (int)mCallResults->size() - 1)
|
||||||
{
|
{
|
||||||
|
auto& callResult = (*mCallResults)[curCallResultIdx];
|
||||||
|
|
||||||
CPURegisters newPhysRegisters;
|
CPURegisters newPhysRegisters;
|
||||||
mDebugger->PopulateRegisters(&newPhysRegisters);
|
mDebugger->PopulateRegisters(&newPhysRegisters);
|
||||||
|
|
||||||
DbgTypedValue returnVal;
|
DbgTypedValue returnVal;
|
||||||
if (method->mReturnType != 0)
|
if (method->mReturnType != 0)
|
||||||
{
|
{
|
||||||
|
if (callResult.mStructRetVal)
|
||||||
|
returnVal = callResult.mStructRetVal;
|
||||||
|
else
|
||||||
returnVal = mDebugger->ReadReturnValue(&newPhysRegisters, method->mReturnType);
|
returnVal = mDebugger->ReadReturnValue(&newPhysRegisters, method->mReturnType);
|
||||||
bool hadRef = false;
|
bool hadRef = false;
|
||||||
auto returnType = method->mReturnType->RemoveModifiers(&hadRef);
|
auto returnType = method->mReturnType->RemoveModifiers(&hadRef);
|
||||||
|
@ -6730,10 +6770,23 @@ DbgTypedValue DbgExprEvaluator::CreateCall(DbgSubprogram* method, DbgTypedValue
|
||||||
returnVal.mType = mDbgModule->GetPrimitiveType(DbgType_Void, GetLanguage());
|
returnVal.mType = mDbgModule->GetPrimitiveType(DbgType_Void, GetLanguage());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BfLogDbgExpr(" using new results %s\n", _GetResultString(returnVal).c_str());
|
||||||
|
|
||||||
mDebugger->RestoreAllRegisters();
|
mDebugger->RestoreAllRegisters();
|
||||||
(*mCallResults)[curCallResultIdx].mResult = returnVal;
|
|
||||||
|
if ((method->mReturnType->IsCompositeType()) && (mDebugger->CheckNeedsSRetArgument(method->mReturnType)))
|
||||||
|
{
|
||||||
|
callResult.mSRetData.Resize(method->mReturnType->GetByteCount());
|
||||||
|
mDebugger->ReadMemory(returnVal.mSrcAddress, method->mReturnType->GetByteCount(), &callResult.mSRetData[0]);
|
||||||
|
}
|
||||||
|
callResult.mResult = returnVal;
|
||||||
|
|
||||||
return returnVal;
|
return returnVal;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BfLogDbgExpr(" new call\n");
|
||||||
|
}
|
||||||
|
|
||||||
// It's a new call
|
// It's a new call
|
||||||
|
|
||||||
|
@ -6831,6 +6884,7 @@ DbgTypedValue DbgExprEvaluator::CreateCall(DbgSubprogram* method, DbgTypedValue
|
||||||
|
|
||||||
DbgCallResult callResult;
|
DbgCallResult callResult;
|
||||||
callResult.mSubProgram = method;
|
callResult.mSubProgram = method;
|
||||||
|
callResult.mStructRetVal = structRetVal;
|
||||||
mCallResults->push_back(callResult);
|
mCallResults->push_back(callResult);
|
||||||
|
|
||||||
mCreatedPendingCall = true;
|
mCreatedPendingCall = true;
|
||||||
|
@ -7160,6 +7214,8 @@ DbgTypedValue DbgExprEvaluator::CreateCall(BfAstNode* targetSrc, DbgTypedValue t
|
||||||
|
|
||||||
DbgTypedValue DbgExprEvaluator::CreateCall(DbgSubprogram* method, SizedArrayImpl<DbgMethodArgument>& argPushQueue, bool bypassVirtual)
|
DbgTypedValue DbgExprEvaluator::CreateCall(DbgSubprogram* method, SizedArrayImpl<DbgMethodArgument>& argPushQueue, bool bypassVirtual)
|
||||||
{
|
{
|
||||||
|
BfLogDbgExpr("CreateCall #%d %s", mCallResultIdx, method->mName);
|
||||||
|
|
||||||
if (mDebugger->IsMiniDumpDebugger())
|
if (mDebugger->IsMiniDumpDebugger())
|
||||||
{
|
{
|
||||||
Fail("Cannot call functions in a minidump", NULL);
|
Fail("Cannot call functions in a minidump", NULL);
|
||||||
|
@ -7178,6 +7234,11 @@ DbgTypedValue DbgExprEvaluator::CreateCall(DbgSubprogram* method, SizedArrayImpl
|
||||||
bool canSetRegisters = mDebugger->PopulateRegisters(®isters);
|
bool canSetRegisters = mDebugger->PopulateRegisters(®isters);
|
||||||
|
|
||||||
auto* regSP = registers.GetSPRegisterRef();
|
auto* regSP = registers.GetSPRegisterRef();
|
||||||
|
if (mCallStackPreservePos != 0)
|
||||||
|
{
|
||||||
|
if (mCallStackPreservePos <= *regSP)
|
||||||
|
*regSP = mCallStackPreservePos;
|
||||||
|
}
|
||||||
|
|
||||||
int paramIdx = argPushQueue.size() - 1;
|
int paramIdx = argPushQueue.size() - 1;
|
||||||
if (method->mHasThis)
|
if (method->mHasThis)
|
||||||
|
@ -7191,13 +7252,16 @@ DbgTypedValue DbgExprEvaluator::CreateCall(DbgSubprogram* method, SizedArrayImpl
|
||||||
thisByValue = true;
|
thisByValue = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
DbgTypedValue compositeRetVal;
|
DbgTypedValue structRetVal;
|
||||||
if (mDebugger->CheckNeedsSRetArgument(method->mReturnType))
|
if (mDebugger->CheckNeedsSRetArgument(method->mReturnType))
|
||||||
{
|
{
|
||||||
int retSize = BF_ALIGN(method->mReturnType->GetByteCount(), 16);
|
int retSize = BF_ALIGN(method->mReturnType->GetByteCount(), 16);
|
||||||
*regSP -= retSize;
|
*regSP -= retSize;
|
||||||
compositeRetVal.mType = method->mReturnType;
|
structRetVal.mType = method->mReturnType;
|
||||||
compositeRetVal.mSrcAddress = *regSP;
|
structRetVal.mSrcAddress = *regSP;
|
||||||
|
|
||||||
|
// For chained calls we need to leave the sret form the previous calls intact
|
||||||
|
mCallStackPreservePos = *regSP;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = (int)argPushQueue.size() - 1; i >= 0; i--)
|
for (int i = (int)argPushQueue.size() - 1; i >= 0; i--)
|
||||||
|
@ -7227,9 +7291,10 @@ DbgTypedValue DbgExprEvaluator::CreateCall(DbgSubprogram* method, SizedArrayImpl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (compositeRetVal.mSrcAddress != 0)
|
if (structRetVal.mSrcAddress != 0)
|
||||||
{
|
{
|
||||||
mDebugger->AddParamValue(0, method->mHasThis && !thisByValue, ®isters, compositeRetVal);
|
BfLogDbgExpr(" SRet:0x%p", structRetVal.mSrcAddress);
|
||||||
|
mDebugger->AddParamValue(0, method->mHasThis && !thisByValue, ®isters, structRetVal);
|
||||||
paramIdx++;
|
paramIdx++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7253,6 +7318,9 @@ DbgTypedValue DbgExprEvaluator::CreateCall(DbgSubprogram* method, SizedArrayImpl
|
||||||
else
|
else
|
||||||
thisAddr = thisVal.mPtr;
|
thisAddr = thisVal.mPtr;
|
||||||
mDebugger->SetThisRegister(®isters, thisAddr);
|
mDebugger->SetThisRegister(®isters, thisAddr);
|
||||||
|
|
||||||
|
if (padCount == 0)
|
||||||
|
BfLogDbgExpr(" This:0x%p", thisAddr);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -7275,7 +7343,7 @@ DbgTypedValue DbgExprEvaluator::CreateCall(DbgSubprogram* method, SizedArrayImpl
|
||||||
BF_ASSERT(padCount < 3);
|
BF_ASSERT(padCount < 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
return CreateCall(method, thisVal, bypassVirtual, ®isters);
|
return CreateCall(method, thisVal, structRetVal, bypassVirtual, ®isters);
|
||||||
}
|
}
|
||||||
|
|
||||||
DbgTypedValue DbgExprEvaluator::MatchMethod(BfAstNode* targetSrc, DbgTypedValue target, bool allowImplicitThis, bool bypassVirtual, const StringImpl& methodName,
|
DbgTypedValue DbgExprEvaluator::MatchMethod(BfAstNode* targetSrc, DbgTypedValue target, bool allowImplicitThis, bool bypassVirtual, const StringImpl& methodName,
|
||||||
|
@ -8106,8 +8174,12 @@ void DbgExprEvaluator::Visit(BfTupleExpression* tupleExpr)
|
||||||
|
|
||||||
DbgTypedValue DbgExprEvaluator::Resolve(BfExpression* expr, DbgType* wantType)
|
DbgTypedValue DbgExprEvaluator::Resolve(BfExpression* expr, DbgType* wantType)
|
||||||
{
|
{
|
||||||
|
//BfLogDbgExpr("Dbg Evaluate %s\n", expr->ToString().c_str());
|
||||||
|
|
||||||
BF_ASSERT(!HasPropResult());
|
BF_ASSERT(!HasPropResult());
|
||||||
|
|
||||||
|
mCallStackPreservePos = 0;
|
||||||
|
|
||||||
SetAndRestoreValue<DbgType*> prevType(mExpectingType, wantType);
|
SetAndRestoreValue<DbgType*> prevType(mExpectingType, wantType);
|
||||||
SetAndRestoreValue<DbgTypedValue> prevResult(mResult, DbgTypedValue());
|
SetAndRestoreValue<DbgTypedValue> prevResult(mResult, DbgTypedValue());
|
||||||
|
|
||||||
|
|
|
@ -234,6 +234,8 @@ class DbgCallResult
|
||||||
public:
|
public:
|
||||||
DbgSubprogram* mSubProgram;
|
DbgSubprogram* mSubProgram;
|
||||||
DbgTypedValue mResult;
|
DbgTypedValue mResult;
|
||||||
|
DbgTypedValue mStructRetVal;
|
||||||
|
Array<uint8> mSRetData;
|
||||||
};
|
};
|
||||||
|
|
||||||
class DbgExprEvaluator : public BfStructuralVisitor
|
class DbgExprEvaluator : public BfStructuralVisitor
|
||||||
|
@ -285,6 +287,7 @@ public:
|
||||||
DbgTypedValue mExplicitThis;
|
DbgTypedValue mExplicitThis;
|
||||||
BfExpression* mExplicitThisExpr;
|
BfExpression* mExplicitThisExpr;
|
||||||
Array<DbgCallResult>* mCallResults;
|
Array<DbgCallResult>* mCallResults;
|
||||||
|
addr_target mCallStackPreservePos;
|
||||||
int mCallResultIdx;
|
int mCallResultIdx;
|
||||||
String mNamespaceSearchStr;
|
String mNamespaceSearchStr;
|
||||||
Array<DbgType*> mNamespaceSearch;
|
Array<DbgType*> mNamespaceSearch;
|
||||||
|
@ -322,7 +325,7 @@ public:
|
||||||
DbgTypedValue CheckEnumCreation(BfAstNode* targetSrc, DbgType* enumType, const StringImpl& caseName, const BfSizedArray<BfExpression*>& argValues);
|
DbgTypedValue CheckEnumCreation(BfAstNode* targetSrc, DbgType* enumType, const StringImpl& caseName, const BfSizedArray<BfExpression*>& argValues);
|
||||||
void DoInvocation(BfAstNode* target, BfSizedArray<ASTREF(BfExpression*)>& args, BfSizedArray<ASTREF(BfTypeReference*)>* methodGenericArguments);
|
void DoInvocation(BfAstNode* target, BfSizedArray<ASTREF(BfExpression*)>& args, BfSizedArray<ASTREF(BfTypeReference*)>* methodGenericArguments);
|
||||||
bool ResolveArgValues(const BfSizedArray<ASTREF(BfExpression*)>& arguments, SizedArrayImpl<DbgTypedValue>& outArgValues);
|
bool ResolveArgValues(const BfSizedArray<ASTREF(BfExpression*)>& arguments, SizedArrayImpl<DbgTypedValue>& outArgValues);
|
||||||
DbgTypedValue CreateCall(DbgSubprogram* method, DbgTypedValue thisVal, bool bypassVirtual, CPURegisters* registers);
|
DbgTypedValue CreateCall(DbgSubprogram* method, DbgTypedValue thisVal, DbgTypedValue structRetVal, bool bypassVirtual, CPURegisters* registers);
|
||||||
DbgTypedValue CreateCall(DbgSubprogram* method, SizedArrayImpl<DbgMethodArgument>& argPushQueue, bool bypassVirtual);
|
DbgTypedValue CreateCall(DbgSubprogram* method, SizedArrayImpl<DbgMethodArgument>& argPushQueue, bool bypassVirtual);
|
||||||
DbgTypedValue CreateCall(BfAstNode* targetSrc, DbgTypedValue target, DbgSubprogram* methodDef, bool bypassVirtual, const BfSizedArray<ASTREF(BfExpression*)>& arguments, SizedArrayImpl<DbgTypedValue>& argValues);
|
DbgTypedValue CreateCall(BfAstNode* targetSrc, DbgTypedValue target, DbgSubprogram* methodDef, bool bypassVirtual, const BfSizedArray<ASTREF(BfExpression*)>& arguments, SizedArrayImpl<DbgTypedValue>& argValues);
|
||||||
DbgTypedValue MatchMethod(BfAstNode* targetSrc, DbgTypedValue target, bool allowImplicitThis, bool bypassVirtual, const StringImpl& methodName,
|
DbgTypedValue MatchMethod(BfAstNode* targetSrc, DbgTypedValue target, bool allowImplicitThis, bool bypassVirtual, const StringImpl& methodName,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue