📄 memtrk.c
字号:
if (dwFlags&PRINT_TRACE)
{
DWORD Index, temp;
LPWSTR lpsz;
LPMODULE lpm;
for (Cnt=0; Cnt < NUM_TRACK_STACK_FRAMES; Cnt++)
{
#ifdef WINCEPROFILE
PROFentry *pProfEntry = NULL;
ULONG ulAddr = pn->Frames[Cnt] & ((1<<VA_SECTION) - 1);
#endif
if (!(temp = pn->Frames[Cnt] & ~((1<<VA_SECTION) - 1)))
break;
for (Index=0; (Index< MAX_PROCESSES) && (ProcArray[Index].dwVMBase != temp); Index++)
;
if (Index>= MAX_PROCESSES)
{
lpsz=L"Bad Frame";
temp=pn->Frames[Cnt];
}
else if (lpm=MEMTR_ModuleFromAddress(pn->Frames[Cnt]))
{
//This is a DLL
lpsz=lpm->lpszModName;
temp=ZeroPtr(pn->Frames[Cnt])-ZeroPtr(lpm->BasePtr);
#ifdef WINCEPROFILE
pProfEntry = GetFixedProfEntry(ulAddr);
#endif
}
else
{
lpsz=MEMTR_GetWin32ExeName((PPROCESS)&ProcArray[Index]);
temp=(DWORD)ZeroPtr(pn->Frames[Cnt])-(DWORD)ZeroPtr(ProcArray[Index].BasePtr);
#ifdef WINCEPROFILE
pProfEntry = GetEXEProfEntry(Index);
#endif
}
#ifdef WINCEPROFILE
{
ULONG ulFuncAddr;
LPSTR szSymbol;
if(pProfEntry && (szSymbol = GetSymbol(pProfEntry, ulAddr, &ulFuncAddr))) {
RETAILMSG(1, (L"%12.12s!%a+0x%04lx\r\n", lpsz, szSymbol, ulAddr - ulFuncAddr));
} else {
RETAILMSG(1, (L"%12.12s!0x%8.8lx\r\n", lpsz, temp));
}
}
#else
if (Cnt)
RETAILMSG(1, (L", "));
else
RETAILMSG(1, (L" "));
if (Cnt && (Cnt%3==2))
RETAILMSG(1, (L"\r\n"));
RETAILMSG(1, (L"%12.12s!0x%8.8lx", lpsz, temp));
#endif
}
RETAILMSG(1,(L"\r\n\r\n"));
}
SETCURKEY(ulOldKey);
}
#pragma optimize ("", on)
#define SKIP_FRAMES 2
BOOL MEMTR_GetStackFrames(DWORD lpFrames[])
{
CONTEXT CurrentContext;
CONTEXT ContextRecord1;
ULONG ControlPc;
ULONG EstablisherFrame;
PRUNTIME_FUNCTION FunctionEntry;
BOOLEAN InFunction;
ULONG HighLimit;
ULONG LowLimit;
ULONG NestedFrame;
ULONG NextPc;
ULONG PrevSp;
ULONG Cnt;
PCALLSTACK pcstk;
PPROCESS pprcSave;
ACCESSKEY akySave;
RtlCaptureContext(&CurrentContext);
pprcSave = pCurProc;
akySave = pCurThread->aky;
NKGetStackLimits(pCurThread, &LowLimit, &HighLimit);
memcpy(&ContextRecord1, &CurrentContext, sizeof(CONTEXT));
ControlPc = CONTEXT_TO_PROGRAM_COUNTER(&ContextRecord1);
NestedFrame = 0;
pcstk = pCurThread->pcstkTop;
Cnt = 0;
// RETAILMSG(1,(L"Frames requested\r\n"));
do {
PrevSp = ContextRecord1.STACKPTR;
FunctionEntry = LookupFunctionEntry(pCurProc, ControlPc);
// RETAILMSG(1,(L"Frame %d: %8.8lx\r\n",Cnt,MapPtrProc(ControlPc,pCurProc)));
if (Cnt >= SKIP_FRAMES)
lpFrames[Cnt-SKIP_FRAMES] = (DWORD)MapPtrProc(ControlPc,pCurProc);
Cnt++;
if (FunctionEntry != NULL) {
NextPc = RtlVirtualUnwind(ControlPc,
FunctionEntry,
&ContextRecord1,
&InFunction,
&EstablisherFrame);
if ((EstablisherFrame < LowLimit) || (EstablisherFrame > HighLimit) ||
((EstablisherFrame & STK_ALIGN) != 0))
break;
else if ((!InFunction || !FunctionEntry->ExceptionHandler) && (NextPc != ControlPc))
PrevSp = 0; // don't terminate loop because sp didn't change.
} else {
NextPc = ContextRecord1.RETADDR - INST_SIZE;
PrevSp = 0; // don't terminate loop because sp didn't change.
if (NextPc == ControlPc)
break;
}
ControlPc = NextPc;
if (pcstk && (ControlPc == SYSCALL_RETURN || ControlPc+INST_SIZE == SYSCALL_RETURN
|| ControlPc == DIRECT_RETURN || ControlPc+INST_SIZE == DIRECT_RETURN)) {
PPROCESS pProc = pcstk->pprcLast;
ContextRecord1.RETADDR = (ULONG)pcstk->retAddr;
if ((ulong)pProc < 0x10000)
SetContextMode(&ContextRecord1, (ULONG)pProc);
else
UpdateASID(pCurThread, pProc, pcstk->akyLast ? pcstk->akyLast : pCurThread->aky);
ControlPc = ContextRecord1.RETADDR - INST_SIZE;
pcstk = pcstk->pcstkNext;
}
else if (pcstk && (DWORD)pcstk < ContextRecord1.STACKPTR && !pcstk->retAddr)
{
PPROCESS pProc = pcstk->pprcLast;
ContextRecord1.RETADDR = (DWORD)ZeroPtr(ControlPc);
// RETAILMSG(1,(L"*** CallBack4 ControlPc %8.8l ZeroPtr %08x\r\n",ControlPc,ContextRecord1.RETADDR));
if ((ulong)pProc < 0x10000)
SetContextMode(&ContextRecord1, (ULONG)pProc);
else
UpdateASID(pCurThread, pProc, pcstk->akyLast ? pcstk->akyLast : pCurThread->aky);
ControlPc = ContextRecord1.RETADDR - INST_SIZE;
pcstk=pcstk->pcstkNext;
}
} while ((ContextRecord1.STACKPTR < HighLimit) && (ContextRecord1.STACKPTR > PrevSp) && (Cnt < NUM_TRACK_STACK_FRAMES + SKIP_FRAMES));
UpdateASID(pCurThread, pprcSave, akySave);
return TRUE;
}
extern PROCESS *kdProcArray;
LPMODULE MEMTR_ModuleFromAddress(DWORD dwAdd)
{
DWORD fa; //Fixedup address
DWORD ModZa; //Module's zero based address
LPMODULE pMod;
//Make the given address zero based
fa=ZeroPtr(dwAdd);
//Walk module list to find this address
pMod=pModList;
while (pMod) {
ModZa = (DWORD)pMod->BasePtr-kdProcArray[0].dwVMBase;
if (fa >= ModZa && fa < ModZa+pMod->e32.e32_vsize) {
return pMod;
}
pMod=pMod->pMod;
}
return NULL;
}
static LPWSTR lpszUnknown=L"UNKNOWN";
LPWSTR MEMTR_GetWin32ExeName(PPROCESS pProc)
{
if (pProc->lpszProcName)
return pProc->lpszProcName;
return lpszUnknown;
}
#endif
/*
@func BOOL | PrintTrackedItem | Prints tracked items
@parm DWORD | dwFlags | Flags controlling what gets printed. Can be a combination of:
@flag PRINT_RECENT | Only prints resources allocated or freed since the last checkpoint
@flag PRINT_SETCHECKPOINT | Sets a checkpoint for all resources dumped in this call
@flag PRINT_DETAILS | Prints details for the resource items
@flag PRINT_TRACE | Prints a stack trace for resource items
@flag PRINT_FILTERTYPE | Only prints resources of this type
@flag PRINT_FILTERPROCID | Only prints resources for this process id
@flag PRINT_FILTERHANDLE | Only prints resources with this handle. Typically used while
specifying the PRINT_FILTERTYPE flag also, since both are required for the handle to
be unique. The high word is reserved for application defined values.
@parm DWORD | dwType | TypeID to filter for if PRINT_FILTERTYPE is specified
@parm DWORD | dwProcID | ProcID to filter for if PRINT_FILTERPROCID is specified
@parm HANDLE | handle | Handle to filter for if PRINT_FILTERHANDLE is specified
@comm For the incremental flag to be useful you must make sure to checkpoint at the appropriate
points. Note that only resources which meet the filter requirements are checkpointed -
in other words if you call this function with the checkpoint flag set and a filter set
on type 4, then only resource items of that type will be checkpointed. To keep things
simple you should probably not use any filters when you are checkpointing. A typical mode
of usage would be to checkpoint, do some operation, and then do an incremental dump to
see if the last operation caused any leaks in the system. Once you feel there is a leak,
you can use the PRINT_DETAILS flag to see what specific items might have been leaked, and
then print stack traces for them by using the PRINT_FILTERHANDLE and PRINT_TRACE flags.
@xref <f RegisterTrackedItem> <f AddTrackedItem> <f DeleteTrackedItem> <f FilterTrackedItem> <f TrackerCallBack>
*/
BOOL SC_PrintTrackedItem(DWORD dwFlags, DWORD dwType, DWORD dwProcID, HANDLE handle)
{
#ifdef MEMTRACKING
pTrack_Node pnCur, pnFree;
DWORD dwCurType;
DWORD dwSize, dwCount;
EnterCriticalSection(&Trackcs);
if (!pTOC->ulTrackingLen || !pTOC->ulTrackingStart)
{
ERRORMSG(1, (L"No resource tracking memory!!\r\n"));
goto errret;
}
if (!uiTablesize && !PerformCallBack4(&cbi,0)){
ERRORMSG(1, (L"MEMTR: Out of resource tracking memory!\r\n"));
SetLastError(ERROR_NOT_ENOUGH_SERVER_MEMORY);
goto errret;
}
DEBUGCHK(table);
// Go through all nodes and print as required
RETAILMSG(dwFlags&PRINT_DETAILS,(L"LEGEND:- Process:Handle(AllocTime):Size::dwCustom1:dwCustom2\r\n"));
for (dwCurType=0; rgRegTypes[dwCurType].dwFlags®TYPE_INUSE; dwCurType++) {
if ((dwFlags&PRINT_FILTERTYPE) && (dwCurType!=dwType)) continue;
if (rgRegTypes[dwCurType].dwFlags®TYPE_MASKED) continue;
RETAILMSG(1, (L"Resource Name: %s(%d)\r\n",
rgRegTypes[dwCurType].szName, dwCurType));
RETAILMSG(1, (L" Allocated:"));
RETAILMSG(dwFlags&PRINT_DETAILS, (L"\r\n"));
dwCount = dwSize = 0;
for (pnCur = pnFirst; pnCur; pnCur = pnCur->pnNext) {
// do all the filtering
if (pnCur->dwType != dwCurType) continue;
if ((dwFlags&PRINT_FILTERHANDLE) && (pnCur->handle!=handle)) continue;
if ((dwFlags&PRINT_FILTERPROCID) && (pnCur->dwProcID!=dwProcID)) continue;
if ((dwFlags&PRINT_RECENT) && (pnCur->dwFlags&ITEM_SHOWN)) continue;
if (!(pnCur->dwFlags&ITEM_DELETED)) {
// print the item
if ((dwFlags&PRINT_DETAILS) || (dwFlags&PRINT_TRACE)) {
MEMTR_printnode(dwFlags, pnCur);
}
dwSize += pnCur->dwSize;
dwCount++;
}
if (dwFlags&PRINT_SETCHECKPOINT) {
pnCur->dwFlags |= ITEM_SHOWN;
}
}
RETAILMSG(1, (L" Total size: %6.6lu, Num items:%u\r\n", dwSize, dwCount));
RETAILMSG(1, (L" Freed :"));
RETAILMSG(dwFlags&PRINT_DETAILS, (L"\r\n"));
dwCount = dwSize = 0;
pnFree = NULL;
for (pnCur = pnFirst; pnCur; pnCur=pnCur->pnNext) {
// free the last node if necessary
if ((dwFlags&PRINT_SETCHECKPOINT) && pnFree) {
DEBUGMSG(ZONE_MEMTRACKER, (L"X"));
MEMTR_deletenode(pnFree);
pnFree = NULL;
}
// do all the filtering
if (pnCur->dwType != dwCurType) continue;
if ((dwFlags&PRINT_FILTERHANDLE) && (pnCur->handle!=handle)) continue;
if ((dwFlags&PRINT_FILTERPROCID) && (pnCur->dwProcID!=dwProcID)) continue;
if (pnCur->dwFlags&ITEM_DELETED) {
// print the item
if ((dwFlags&PRINT_DETAILS) || (dwFlags&PRINT_TRACE)) {
MEMTR_printnode(dwFlags, pnCur);
}
dwSize += pnCur->dwSize;
dwCount++;
pnFree = pnCur;
}
}
RETAILMSG(1, (L" Total size: %6.6lu, Num items %u\r\n", dwSize, dwCount));
}
LeaveCriticalSection(&Trackcs);
return TRUE;
errret:
LeaveCriticalSection(&Trackcs);
#endif
return FALSE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -