📄 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 2BOOL 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 + -