mirror of
https://github.com/beefytech/Beef.git
synced 2025-07-04 23:36:00 +02:00
Added diagnostics panel
This commit is contained in:
parent
efa9566f88
commit
f034880723
12 changed files with 1017 additions and 51 deletions
|
@ -9874,15 +9874,10 @@ void BfModule::CurrentAddToConstHolder(BfIRValue& irVal)
|
|||
newVals.push_back(newVal);
|
||||
}
|
||||
|
||||
irVal = mCurTypeInstance->mConstHolder->CreateConstArray(constArray->mType, newVals);
|
||||
irVal = mCurTypeInstance->GetOrCreateConstHolder()->CreateConstArray(constArray->mType, newVals);
|
||||
return;
|
||||
}
|
||||
|
||||
if (constant->mConstType == BfConstType_GlobalVar)
|
||||
{
|
||||
NOP;
|
||||
}
|
||||
|
||||
auto origConst = irVal;
|
||||
if ((constant->mConstType == BfConstType_BitCast) || (constant->mConstType == BfConstType_BitCastNull))
|
||||
{
|
||||
|
|
|
@ -732,10 +732,19 @@ DbgExprEvaluator::DbgExprEvaluator(WinDebugger* winDebugger, DbgModule* dbgModul
|
|||
mCapturingChildRef = true;
|
||||
mPassInstance = passInstance;
|
||||
mDebugger = winDebugger;
|
||||
mLanguage = DbgLanguage_NotSet;
|
||||
mDebugTarget = dbgModule->mDebugTarget;
|
||||
mLanguage = DbgLanguage_NotSet;
|
||||
mOrigDbgModule = dbgModule;
|
||||
mDbgModule = dbgModule->GetLinkedModule();
|
||||
if (dbgModule != NULL)
|
||||
{
|
||||
mDebugTarget = dbgModule->mDebugTarget;
|
||||
mDbgModule = dbgModule->GetLinkedModule();
|
||||
}
|
||||
else
|
||||
{
|
||||
mDebugTarget = NULL;
|
||||
mDbgModule = NULL;
|
||||
}
|
||||
|
||||
mDbgCompileUnit = NULL;
|
||||
mExplicitThisExpr = NULL;
|
||||
mExpectingType = NULL;
|
||||
|
@ -1125,12 +1134,14 @@ DbgTypedValue DbgExprEvaluator::GetBeefTypeById(int typeId)
|
|||
if (mDebugTarget->mTargetBinary == NULL)
|
||||
return DbgTypedValue();
|
||||
|
||||
mDebugTarget->mTargetBinary->ParseTypeData();
|
||||
auto typeTypeEntry = mDebugTarget->mTargetBinary->FindType("System.Type", DbgLanguage_Beef);
|
||||
if ((typeTypeEntry == NULL) || (typeTypeEntry->mValue == NULL))
|
||||
return DbgTypedValue();
|
||||
|
||||
auto typeType = typeTypeEntry->mValue;
|
||||
mDbgModule->PopulateTypeGlobals(typeType);
|
||||
if (typeType->mNeedsGlobalsPopulated)
|
||||
typeType->mCompileUnit->mDbgModule->PopulateTypeGlobals(typeType);
|
||||
for (auto member : typeType->mMemberList)
|
||||
{
|
||||
if ((member->mIsStatic) && (member->mName != NULL) && (strcmp(member->mName, "sTypes") == 0) && (member->mLocationData != NULL))
|
||||
|
@ -1232,6 +1243,12 @@ void DbgExprEvaluator::BeefTypeToString(const DbgTypedValue& val, String& outStr
|
|||
_TypeCode mElementType;
|
||||
};
|
||||
|
||||
struct _SizedArrayType : _Type
|
||||
{
|
||||
_TypeId mElementType;
|
||||
int32 mElementCount;
|
||||
};
|
||||
|
||||
struct _String
|
||||
{
|
||||
|
||||
|
@ -1267,16 +1284,27 @@ void DbgExprEvaluator::BeefTypeToString(const DbgTypedValue& val, String& outStr
|
|||
uint8 mInterfaceCount;
|
||||
int16 mMethodDataCount;
|
||||
int16 mPropertyDataCount;
|
||||
int16 mFieldDataCount;
|
||||
int16 mConstructorDataCount;
|
||||
int16 mFieldDataCount;
|
||||
|
||||
void* mInterfaceDataPtr;
|
||||
_MethodData* mMethodDataPtr;
|
||||
void* mPropertyDataPtr;
|
||||
_FieldData* mFieldDataPtr;
|
||||
void* mConstructorDataPtr;
|
||||
_FieldData* mFieldDataPtr;
|
||||
void** mCustomAttrDataPtr;
|
||||
};
|
||||
|
||||
struct _SpecializedGenericType : _TypeInstance
|
||||
{
|
||||
_TypeId mUnspecializedType;
|
||||
_TypeId* mResolvedTypeRefs;
|
||||
};
|
||||
|
||||
struct _ArrayType : _SpecializedGenericType
|
||||
{
|
||||
int32 mElementSize;
|
||||
uint8 mRank;
|
||||
uint8 mElemensDataOffset;
|
||||
};
|
||||
|
||||
int typeIdSize = sizeof(_TypeId);
|
||||
int ptrSize = (int)sizeof(addr_target);
|
||||
|
@ -1284,12 +1312,54 @@ void DbgExprEvaluator::BeefTypeToString(const DbgTypedValue& val, String& outStr
|
|||
int typeSize = sizeof(_Type);
|
||||
|
||||
int typeInstanceSize = objectSize + sizeof(_TypeInstance);
|
||||
|
||||
|
||||
auto addr = useVal.mSrcAddress;
|
||||
auto typeAddr = addr + objectSize;
|
||||
|
||||
_TypeFlags typeFlags = mDebugger->ReadMemory<_TypeFlags>(typeAddr + offsetof(_Type, mTypeFlags));
|
||||
if (((typeFlags & BfTypeFlags_Struct) != 0) || ((typeFlags & BfTypeFlags_TypedPrimitive) != 0) || ((typeFlags & BfTypeFlags_Object) != 0))
|
||||
|
||||
if ((typeFlags & BfTypeFlags_Array) != 0)
|
||||
{
|
||||
_TypeId unspecializedTypeId = mDebugger->ReadMemory<_TypeId>(typeAddr + offsetof(_SpecializedGenericType, mUnspecializedType));
|
||||
addr_target elementsArrayAddr = mDebugger->ReadMemory<addr_target>(typeAddr + offsetof(_SpecializedGenericType, mResolvedTypeRefs));
|
||||
_TypeId elementTypeId = mDebugger->ReadMemory<_TypeId>(elementsArrayAddr);
|
||||
|
||||
auto elementType = GetBeefTypeById(elementTypeId);
|
||||
BeefTypeToString(elementType, outStr);
|
||||
|
||||
outStr += "[";
|
||||
int rank = mDebugger->ReadMemory<uint8>(typeAddr + offsetof(_ArrayType, mRank));
|
||||
for (int commaIdx = 0; commaIdx < rank - 1; commaIdx++)
|
||||
outStr += ",";
|
||||
outStr += "]";
|
||||
}
|
||||
else if ((typeFlags & BfTypeFlags_Pointer) != 0)
|
||||
{
|
||||
_TypeId elementTypeId = mDebugger->ReadMemory<_TypeId>(typeAddr + offsetof(_PointerType, mElementType));
|
||||
auto elementType = GetBeefTypeById(elementTypeId);
|
||||
BeefTypeToString(elementType, outStr);
|
||||
}
|
||||
else if ((typeFlags & BfTypeFlags_Delegate) != 0)
|
||||
{
|
||||
outStr += "delegate";
|
||||
}
|
||||
else if ((typeFlags & BfTypeFlags_Function) != 0)
|
||||
{
|
||||
outStr += "function";
|
||||
}
|
||||
// else if ((typeFlags & BfTypeFlags_Tuple) != 0)
|
||||
// {
|
||||
// outStr += "function";
|
||||
// }
|
||||
else if ((typeFlags & BfTypeFlags_SizedArray) != 0)
|
||||
{
|
||||
_TypeId elementTypeId = mDebugger->ReadMemory<_TypeId>(typeAddr + objectSize + offsetof(_SizedArrayType, mElementType));
|
||||
auto elementType = GetBeefTypeById(elementTypeId);
|
||||
BeefTypeToString(elementType, outStr);
|
||||
int elementCount = mDebugger->ReadMemory<int32>(typeAddr + objectSize + offsetof(_SizedArrayType, mElementCount));
|
||||
outStr += StrFormat("[%d]", elementCount);
|
||||
}
|
||||
else if (((typeFlags & BfTypeFlags_Struct) != 0) || ((typeFlags & BfTypeFlags_TypedPrimitive) != 0) || ((typeFlags & BfTypeFlags_Object) != 0))
|
||||
{
|
||||
addr_target namePtr = mDebugger->ReadMemory<addr_target>(typeAddr + offsetof(_TypeInstance, mName));
|
||||
addr_target namespacePtr = mDebugger->ReadMemory<addr_target>(typeAddr + offsetof(_TypeInstance, mNamespace));
|
||||
|
|
|
@ -1535,6 +1535,22 @@ BF_EXPORT void BF_CALLTYPE Debugger_InitiateHotResolve(int flags)
|
|||
gDebugger->InitiateHotResolve((DbgHotResolveFlags)flags);
|
||||
}
|
||||
|
||||
|
||||
BF_EXPORT intptr BF_CALLTYPE Debugger_GetDbgAllocHeapSize()
|
||||
{
|
||||
AutoCrit autoCrit(gDebugManager->mCritSect);
|
||||
return gDebugger->GetDbgAllocHeapSize();
|
||||
}
|
||||
|
||||
BF_EXPORT const char* BF_CALLTYPE Debugger_GetDbgAllocInfo()
|
||||
{
|
||||
AutoCrit autoCrit(gDebugManager->mCritSect);
|
||||
|
||||
String& outString = *gTLStrReturn.Get();
|
||||
outString = gDebugger->GetDbgAllocInfo();
|
||||
return outString.c_str();
|
||||
}
|
||||
|
||||
BF_EXPORT const char* BF_CALLTYPE Debugger_GetHotResolveData(uint8* outTypeData, int* outTypeDataSize)
|
||||
{
|
||||
AutoCrit autoCrit(gDebugManager->mCritSect);
|
||||
|
@ -1554,7 +1570,10 @@ BF_EXPORT const char* BF_CALLTYPE Debugger_GetHotResolveData(uint8* outTypeData,
|
|||
|
||||
*outTypeDataSize = dataSize;
|
||||
if (dataSize > 0)
|
||||
memcpy(outTypeData, &gDebugger->mHotResolveData->mTypeData[0], dataSize);
|
||||
{
|
||||
for (int i = 0; i < dataSize; i++)
|
||||
outTypeData[i] = (gDebugger->mHotResolveData->mTypeData[i].mCount > 0) ? 1 : 0;
|
||||
}
|
||||
|
||||
String& outString = *gTLStrReturn.Get();
|
||||
outString.Clear();
|
||||
|
|
|
@ -215,7 +215,20 @@ public:
|
|||
class DbgHotResolveData
|
||||
{
|
||||
public:
|
||||
Array<uint8> mTypeData;
|
||||
struct TypeData
|
||||
{
|
||||
intptr mCount;
|
||||
intptr mSize;
|
||||
|
||||
TypeData()
|
||||
{
|
||||
mCount = 0;
|
||||
mSize = 0;
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
Array<TypeData> mTypeData;
|
||||
Beefy::HashSet<String> mBeefCallStackEntries;
|
||||
};
|
||||
|
||||
|
@ -248,6 +261,8 @@ public:
|
|||
virtual void Run() = 0;
|
||||
virtual void HotLoad(const Array<String>& objectFiles, int hotIdx) = 0;
|
||||
virtual void InitiateHotResolve(DbgHotResolveFlags flags) = 0;
|
||||
virtual intptr GetDbgAllocHeapSize() = 0;
|
||||
virtual String GetDbgAllocInfo() = 0;
|
||||
virtual void Update() = 0;
|
||||
virtual void ContinueDebugEvent() = 0;
|
||||
virtual void ForegroundTarget() = 0;
|
||||
|
|
|
@ -169,11 +169,15 @@ void DbgHotScanner::ScanSpan(TCFake::Span* span, int expectedStartPage, int memK
|
|||
elementSize = spanSize;
|
||||
//BF_LOGASSERT(elementSize >= sizeof(bf::System::Object));
|
||||
|
||||
auto _MarkTypeUsed = [&](int typeId)
|
||||
auto _MarkTypeUsed = [&](int typeId, intptr size)
|
||||
{
|
||||
if (typeId < 0)
|
||||
return;
|
||||
while (mDebugger->mHotResolveData->mTypeData.size() <= typeId)
|
||||
mDebugger->mHotResolveData->mTypeData.Add(0);
|
||||
mDebugger->mHotResolveData->mTypeData[typeId] = 1;
|
||||
mDebugger->mHotResolveData->mTypeData.Add(DbgHotResolveData::TypeData());
|
||||
auto& typeData = mDebugger->mHotResolveData->mTypeData[typeId];
|
||||
typeData.mSize += size;
|
||||
typeData.mCount++;
|
||||
};
|
||||
|
||||
int objectSize = ((mDbgGCData.mDbgFlags & BfRtFlags_ObjectHasDebugFlags) != 0) ? sizeof(addr_target)*2 : sizeof(addr_target);
|
||||
|
@ -206,36 +210,68 @@ void DbgHotScanner::ScanSpan(TCFake::Span* span, int expectedStartPage, int memK
|
|||
if ((mDbgGCData.mDbgFlags & BfRtFlags_ObjectHasDebugFlags) != 0)
|
||||
classVDataAddr = classVDataAddr & ~0xFF;
|
||||
}
|
||||
else if (mFoundRawAllocDataAddrs.Add(rawAllocDataAddr))
|
||||
else
|
||||
{
|
||||
Fake_DbgRawAllocData rawAllocData = mDebugger->ReadMemory<Fake_DbgRawAllocData>(rawAllocDataAddr);
|
||||
if ((rawAllocData.mType != NULL) && (mFoundTypeAddrs.Add(rawAllocData.mType)))
|
||||
|
||||
int* rawTypeIdPtr = NULL;
|
||||
if (mFoundRawAllocDataAddrs.TryAdd(rawAllocDataAddr, NULL, &rawTypeIdPtr))
|
||||
{
|
||||
Fake_Type_Data typeData;
|
||||
if (mDebugger->ReadMemory(rawAllocData.mType + objectSize, sizeof(typeData), &typeData))
|
||||
_MarkTypeUsed(typeData.mTypeId);
|
||||
*rawTypeIdPtr = -1;
|
||||
Fake_DbgRawAllocData rawAllocData = mDebugger->ReadMemory<Fake_DbgRawAllocData>(rawAllocDataAddr);
|
||||
if (rawAllocData.mType != NULL)
|
||||
{
|
||||
int* typeAddrIdPtr = NULL;
|
||||
if (mFoundTypeAddrs.TryAdd(rawAllocData.mType, NULL, &typeAddrIdPtr))
|
||||
{
|
||||
*typeAddrIdPtr = -1;
|
||||
Fake_Type_Data typeData;
|
||||
if (mDebugger->ReadMemory(rawAllocData.mType + objectSize, sizeof(typeData), &typeData))
|
||||
{
|
||||
*typeAddrIdPtr = typeData.mTypeId;
|
||||
*rawTypeIdPtr = typeData.mTypeId;
|
||||
_MarkTypeUsed(typeData.mTypeId, elementSize);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_MarkTypeUsed(*typeAddrIdPtr, elementSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_MarkTypeUsed(*rawTypeIdPtr, elementSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((classVDataAddr != 0) && (mFoundClassVDataAddrs.Add(classVDataAddr)))
|
||||
if (classVDataAddr != 0)
|
||||
{
|
||||
addr_target typeAddr = mDebugger->ReadMemory<addr_target>(classVDataAddr);
|
||||
Fake_Type_Data typeData;
|
||||
mDebugger->ReadMemory(typeAddr + objectSize, sizeof(typeData), &typeData);
|
||||
|
||||
_MarkTypeUsed(typeData.mTypeId);
|
||||
if ((typeData.mTypeFlags & BfTypeFlags_Delegate) != 0)
|
||||
int* typeIdPtr = NULL;
|
||||
if (mFoundClassVDataAddrs.TryAdd(classVDataAddr, NULL, &typeIdPtr))
|
||||
{
|
||||
Fake_Delegate_Data* dlg = (Fake_Delegate_Data*)((uint8*)spanPtr + objectSize);
|
||||
if (mFoundFuncPtrs.Add(dlg->mFuncPtr))
|
||||
addr_target typeAddr = mDebugger->ReadMemory<addr_target>(classVDataAddr);
|
||||
Fake_Type_Data typeData;
|
||||
mDebugger->ReadMemory(typeAddr + objectSize, sizeof(typeData), &typeData);
|
||||
|
||||
*typeIdPtr = typeData.mTypeId;
|
||||
_MarkTypeUsed(typeData.mTypeId, elementSize);
|
||||
if ((typeData.mTypeFlags & BfTypeFlags_Delegate) != 0)
|
||||
{
|
||||
auto subProgram = mDebugger->mDebugTarget->FindSubProgram(dlg->mFuncPtr, DbgOnDemandKind_None);
|
||||
if ((subProgram != NULL) && (subProgram->GetLanguage() == DbgLanguage_Beef))
|
||||
AddSubProgram(subProgram, true, "D ");
|
||||
Fake_Delegate_Data* dlg = (Fake_Delegate_Data*)((uint8*)spanPtr + objectSize);
|
||||
if (mFoundFuncPtrs.Add(dlg->mFuncPtr))
|
||||
{
|
||||
auto subProgram = mDebugger->mDebugTarget->FindSubProgram(dlg->mFuncPtr, DbgOnDemandKind_None);
|
||||
if ((subProgram != NULL) && (subProgram->GetLanguage() == DbgLanguage_Beef))
|
||||
AddSubProgram(subProgram, true, "D ");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_MarkTypeUsed(*typeIdPtr, elementSize);
|
||||
}
|
||||
}
|
||||
|
||||
spanPtr = (void*)((intptr)spanPtr + elementSize);
|
||||
|
|
|
@ -84,9 +84,9 @@ class DbgHotScanner
|
|||
public:
|
||||
WinDebugger* mDebugger;
|
||||
DbgGCData mDbgGCData;
|
||||
Beefy::HashSet<addr_target> mFoundClassVDataAddrs;
|
||||
Beefy::HashSet<addr_target> mFoundRawAllocDataAddrs;
|
||||
Beefy::HashSet<addr_target> mFoundTypeAddrs;
|
||||
Beefy::Dictionary<addr_target, int> mFoundClassVDataAddrs;
|
||||
Beefy::Dictionary<addr_target, int> mFoundRawAllocDataAddrs;
|
||||
Beefy::Dictionary<addr_target, int> mFoundTypeAddrs;
|
||||
Beefy::HashSet<addr_target> mFoundFuncPtrs;
|
||||
|
||||
#ifdef BF_DBG_32
|
||||
|
|
|
@ -523,6 +523,7 @@ WinDebugger::WinDebugger(DebugManager* debugManager) : mDbgSymSrv(this)
|
|||
mDbgProcessHandle = 0;
|
||||
mDbgThreadHandle = 0;
|
||||
mDbgProcessId = 0;
|
||||
mDbgHeapData = NULL;
|
||||
mIsPartialCallStack = true;
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
|
@ -1174,6 +1175,76 @@ void WinDebugger::InitiateHotResolve(DbgHotResolveFlags flags)
|
|||
delete hotScanner;
|
||||
}
|
||||
|
||||
intptr WinDebugger::GetDbgAllocHeapSize()
|
||||
{
|
||||
if (mDbgHeapData == NULL)
|
||||
{
|
||||
Beefy::String memName = StrFormat("BFGC_stats_%d", mProcessInfo.dwProcessId);
|
||||
|
||||
mDbgHeapData = new WinDbgHeapData();
|
||||
mDbgHeapData->mFileMapping = ::OpenFileMappingA(FILE_MAP_ALL_ACCESS, FALSE, memName.c_str());
|
||||
if (mDbgHeapData->mFileMapping == 0)
|
||||
{
|
||||
delete mDbgHeapData;
|
||||
mDbgHeapData = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
mDbgHeapData->mStats = (WinDbgHeapData::Stats*)MapViewOfFile(mDbgHeapData->mFileMapping, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(WinDbgHeapData::Stats));
|
||||
}
|
||||
|
||||
if (mDbgHeapData->mStats == NULL)
|
||||
return 0;
|
||||
|
||||
return mDbgHeapData->mStats->mHeapSize;
|
||||
}
|
||||
|
||||
String WinDebugger::GetDbgAllocInfo()
|
||||
{
|
||||
AutoCrit autoCrit(mDebugManager->mCritSect);
|
||||
|
||||
for (auto threadInfo : mThreadList)
|
||||
::SuspendThread(threadInfo->mHThread);
|
||||
|
||||
delete mHotResolveData;
|
||||
mHotResolveData = NULL;
|
||||
|
||||
mHotResolveData = new DbgHotResolveData();
|
||||
DbgHotScanner* hotScanner = new DbgHotScanner(this);
|
||||
hotScanner->Scan(DbgHotResolveFlag_Allocations);
|
||||
delete hotScanner;
|
||||
|
||||
String result;
|
||||
|
||||
if (mHotResolveData != NULL)
|
||||
{
|
||||
DbgExprEvaluator exprEvaluator(this, NULL, NULL, -1, -1);
|
||||
exprEvaluator.mDebugTarget = mDebugTarget;
|
||||
|
||||
String typeName;
|
||||
|
||||
result += ":types\n";
|
||||
|
||||
for (int typeId = 0; typeId < mHotResolveData->mTypeData.size(); typeId++)
|
||||
{
|
||||
auto& typeData = mHotResolveData->mTypeData[typeId];
|
||||
if (typeData.mCount > 0)
|
||||
{
|
||||
auto type = exprEvaluator.GetBeefTypeById(typeId);
|
||||
typeName.Clear();
|
||||
exprEvaluator.BeefTypeToString(type, typeName);
|
||||
|
||||
result += StrFormat("type\t%d\t%s\t%lld\t%lld\n", typeId, typeName.c_str(), typeData.mCount, typeData.mSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto threadInfo : mThreadList)
|
||||
::ResumeThread(threadInfo->mHThread);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool WinDebugger::DoOpenFile(const StringImpl& fileName, const StringImpl& args, const StringImpl& workingDir, const Array<uint8>& envBlock)
|
||||
{
|
||||
BP_ZONE("WinDebugger::DoOpenFile");
|
||||
|
@ -1398,6 +1469,8 @@ void WinDebugger::Detach()
|
|||
|
||||
mDbgAttachFlags = BfDbgAttachFlag_None;
|
||||
mDbgProcessId = 0;
|
||||
delete mDbgHeapData;
|
||||
mDbgHeapData = NULL;
|
||||
mDbgProcessHandle = 0;
|
||||
ClearCallStack();
|
||||
mWantsDebugContinue = false;
|
||||
|
@ -10208,21 +10281,27 @@ String WinDebugger::GetProcessInfo()
|
|||
if ((mActiveThread == NULL) && (!mIsRunning))
|
||||
return "";
|
||||
|
||||
SYSTEM_INFO sysinfo = { 0 };
|
||||
GetSystemInfo(&sysinfo);
|
||||
|
||||
FILETIME creationTime = { 0 };
|
||||
FILETIME exitTime = { 0 };
|
||||
FILETIME kernelTime = { 0 };
|
||||
FILETIME userTime = { 0 };
|
||||
GetProcessTimes(mProcessInfo.hProcess, &creationTime, &exitTime, &kernelTime, &userTime);
|
||||
::GetProcessTimes(mProcessInfo.hProcess, &creationTime, &exitTime, &kernelTime, &userTime);
|
||||
|
||||
String retStr;
|
||||
PROCESS_MEMORY_COUNTERS memInfo = { 0 };
|
||||
GetProcessMemoryInfo(mProcessInfo.hProcess, &memInfo, sizeof(PROCESS_MEMORY_COUNTERS));
|
||||
::GetProcessMemoryInfo(mProcessInfo.hProcess, &memInfo, sizeof(PROCESS_MEMORY_COUNTERS));
|
||||
|
||||
FILETIME currentTime = { 0 };
|
||||
::GetSystemTimeAsFileTime(¤tTime);
|
||||
|
||||
retStr += StrFormat("VirtualMemory\t%d\n", memInfo.PagefileUsage);
|
||||
retStr += StrFormat("WorkingMemory\t%d\n", memInfo.WorkingSetSize);
|
||||
retStr += StrFormat("RunningTime\t%lld\n", *(int64*)&creationTime);
|
||||
retStr += StrFormat("KernelTime\t%lld\n", *(int64*)&kernelTime);
|
||||
retStr += StrFormat("UserTime\t%lld\n", *(int64*)&userTime);
|
||||
retStr += StrFormat("RunningTime\t%lld\n", *(int64*)¤tTime - *(int64*)&creationTime);
|
||||
retStr += StrFormat("KernelTime\t%lld\n", *(int64*)&kernelTime / sysinfo.dwNumberOfProcessors);
|
||||
retStr += StrFormat("UserTime\t%lld\n", *(int64*)&userTime / sysinfo.dwNumberOfProcessors);
|
||||
|
||||
return retStr;
|
||||
}
|
||||
|
|
|
@ -384,6 +384,31 @@ struct WinHotThreadState
|
|||
int mThreadId;
|
||||
};
|
||||
|
||||
class WinDbgHeapData
|
||||
{
|
||||
public:
|
||||
struct Stats
|
||||
{
|
||||
intptr mHeapSize;
|
||||
};
|
||||
|
||||
public:
|
||||
HANDLE mFileMapping;
|
||||
Stats* mStats;
|
||||
|
||||
WinDbgHeapData()
|
||||
{
|
||||
mFileMapping = 0;
|
||||
mStats = NULL;
|
||||
}
|
||||
|
||||
~WinDbgHeapData()
|
||||
{
|
||||
if (mFileMapping != 0)
|
||||
::CloseHandle(mFileMapping);
|
||||
}
|
||||
};
|
||||
|
||||
class WinDebugger : public Debugger
|
||||
{
|
||||
public:
|
||||
|
@ -407,6 +432,7 @@ public:
|
|||
CPU* mCPU;
|
||||
PROCESS_INFORMATION mProcessInfo;
|
||||
BfDbgAttachFlags mDbgAttachFlags;
|
||||
WinDbgHeapData* mDbgHeapData;
|
||||
DWORD mDbgProcessId;
|
||||
HANDLE mDbgProcessHandle;
|
||||
HANDLE mDbgThreadHandle;
|
||||
|
@ -593,6 +619,8 @@ public:
|
|||
virtual void Run() override;
|
||||
virtual void HotLoad(const Array<String>& objectFiles, int hotIdx) override;
|
||||
virtual void InitiateHotResolve(DbgHotResolveFlags flags) override;
|
||||
virtual intptr GetDbgAllocHeapSize() override;
|
||||
virtual String GetDbgAllocInfo() override;
|
||||
virtual void Update() override;
|
||||
virtual void ContinueDebugEvent() override;
|
||||
virtual void ForegroundTarget() override;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue