📄 logger.c
字号:
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void
CeLogThreadMigrate(
HANDLE hProcess,
DWORD dwReserved
)
{
DEBUGCHK(IsCeLogStatus(CELOGSTATUS_ENABLED_GENERAL));
if (IsCeLogZoneEnabled(CELZONE_MIGRATE)) {
CEL_THREAD_MIGRATE cl;
cl.hProcess = hProcess;
// Ignore the reserved DWORD for now
g_pfnCeLogData(TRUE, CELID_THREAD_MIGRATE, &cl, sizeof(CEL_THREAD_MIGRATE),
0, CELZONE_MIGRATE, 0, FALSE);
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void
SC_CeLogData(
BOOL fTimeStamp,
WORD wID,
VOID *pData,
WORD wLen,
DWORD dwZoneUser,
DWORD dwZoneCE,
WORD wFlag,
BOOL fFlagged
)
{
if (IsCeLogStatus(CELOGSTATUS_ENABLED_GENERAL)) { // Do not log during profiling
// Check caller buffer access
if ((KERN_TRUST_FULL != pCurProc->bTrustLevel)
&& pData && wLen) {
pData = SC_MapPtrWithSize(pData, wLen, SC_GetCallerProcess());
DEBUGCHK(pData);
if (!pData) {
// Caller does not have access to the buffer. Allow the event
// to be logged, but without any data.
wLen = 0;
}
}
g_pfnCeLogData(fTimeStamp, wID, pData, wLen, dwZoneUser, dwZoneCE, wFlag, fFlagged);
}
}
// CeLog zones available in all builds
#define AVAILABLE_ZONES_ALL_BUILDS \
(CELZONE_RESCHEDULE | CELZONE_MIGRATE | CELZONE_DEMANDPAGE | CELZONE_THREAD \
| CELZONE_PROCESS | CELZONE_PRIORITYINV | CELZONE_CRITSECT | CELZONE_SYNCH \
| CELZONE_HEAP | CELZONE_VIRTMEM | CELZONE_LOADER | CELZONE_MEMTRACKING \
| CELZONE_ALWAYSON | CELZONE_MISC | CELZONE_BOOT_TIME)
// CeLog zones available only in profiling builds
#define AVAILABLE_ZONES_PROFILING \
(CELZONE_INTERRUPT | CELZONE_TLB | CELZONE_KCALL | CELZONE_PROFILER)
// Define the zones available on this kernel
#ifdef NKPROF
#define AVAILABLE_ZONES (AVAILABLE_ZONES_ALL_BUILDS | AVAILABLE_ZONES_PROFILING)
#else
#define AVAILABLE_ZONES (AVAILABLE_ZONES_ALL_BUILDS)
#endif // NKPROF
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void
SC_CeLogSetZones(
DWORD dwZoneUser,
DWORD dwZoneCE,
DWORD dwZoneProcess
)
{
if (IsCeLogStatus(CELOGSTATUS_ENABLED_ANY)) {
BroadcastCeLogSetZones(dwZoneUser, dwZoneCE, dwZoneProcess);
// Set the new zones in UserKData
CeLogEnableZones(g_dwZoneCE);
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
BOOL
SC_CeLogGetZones(
LPDWORD lpdwZoneUser, // User-defined zones
LPDWORD lpdwZoneCE, // Predefined zones
LPDWORD lpdwZoneProcess, // Process zones
LPDWORD lpdwAvailableZones // Zones supported by this kernel
)
{
BOOL fResult = FALSE;
if (IsCeLogStatus(CELOGSTATUS_ENABLED_ANY)) {
// Check caller buffer access
if (KERN_TRUST_FULL != pCurProc->bTrustLevel) {
lpdwZoneUser = SC_MapPtrWithSize(lpdwZoneUser, sizeof(DWORD), SC_GetCallerProcess());
lpdwZoneCE = SC_MapPtrWithSize(lpdwZoneCE, sizeof(DWORD), SC_GetCallerProcess());
lpdwZoneProcess = SC_MapPtrWithSize(lpdwZoneProcess, sizeof(DWORD), SC_GetCallerProcess());
lpdwAvailableZones = SC_MapPtrWithSize(lpdwAvailableZones, sizeof(DWORD), SC_GetCallerProcess());
}
// Supply the available zones for this kernel
if (lpdwAvailableZones) {
*lpdwAvailableZones = AVAILABLE_ZONES;
}
// No need to call the CeLog DLLs to get current zones; we know already
if (lpdwZoneUser) {
*lpdwZoneUser = g_dwZoneUser;
}
if (lpdwZoneCE) {
*lpdwZoneCE = g_dwZoneCE;
}
if (lpdwZoneProcess) {
*lpdwZoneProcess = g_dwZoneProcess;
}
fResult = TRUE;
}
return fResult;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// CELOG RESYNC API: This function generates a series of calls to CeLogData,
// to log all currently-existing processes and threads.
//
// This buffer is used during resync to minimize stack usage
union { // Union so that the buffer is the max of all these and aligned properly
struct {
union {
CEL_PROCESS_CREATE ProcessBase;
CEL_EXTRA_PROCESS_INFO ProcessExtra;
CEL_THREAD_CREATE ThreadBase;
CEL_MODULE_LOAD ModuleBase;
CEL_EXTRA_MODULE_INFO ModuleExtra;
CEL_SYSTEM_INVERT Invert;
};
WCHAR _sz[MAX_PATH]; // Not used directly; string starts at end of data above
};
struct {
CEL_MODULE_REFERENCES ModuleRef;
CEL_PROCESS_REFCOUNT _ref[MAX_PROCESSES-1]; // Not used directly; list starts at end of ModuleRef
};
} g_CeLogSyncBuffer;
// Cause the scheduler's default thread quantum to be visible
extern DWORD dwDefaultThreadQuantum;
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Helper func to generate CeLog process events, minimizing stack usage.
_inline static void
CELOG_SyncProcess(
PPROCESS pProc
)
{
PCEL_PROCESS_CREATE pclBase = &g_CeLogSyncBuffer.ProcessBase;
PCEL_EXTRA_PROCESS_INFO pclExtra = &g_CeLogSyncBuffer.ProcessExtra;
DWORD dwVMBase;
WORD wLen;
// Special case: fixup nk.exe to tell where the code lives, not the VM
dwVMBase = pProc->dwVMBase;
if (dwVMBase == (SECURE_SECTION << VA_SECTION)) {
dwVMBase = pTOC->physfirst;
}
// Log base process info
wLen = 0;
pclBase->hProcess = pProc->hProc;
pclBase->dwVMBase = dwVMBase;
if (pProc->lpszProcName) {
wLen = strlenW(pProc->lpszProcName) + 1;
if (wLen <= MAX_PATH) {
kstrcpyW(pclBase->szName, pProc->lpszProcName);
} else {
wLen = 0;
}
}
g_pfnCeLogData(TRUE, CELID_PROCESS_CREATE, (PVOID) pclBase,
(WORD) (sizeof(CEL_PROCESS_CREATE) + (wLen * sizeof(WCHAR))),
0, CELZONE_PROCESS | CELZONE_THREAD | CELZONE_MEMTRACKING | CELZONE_PROFILER, // CELZONE_THREAD necessary for getting thread names
0, FALSE);
// Log extra process info
pclExtra->hProcess = pProc->hProc;
pclExtra->dwVMLen = pProc->e32.e32_vsize;
wLen = CELOG_FileInfoFromOE(&pProc->oe, &pclExtra->dwOID,
pclExtra->szFullPath);
g_pfnCeLogData(TRUE, CELID_EXTRA_PROCESS_INFO, (PVOID) pclExtra,
(WORD) (sizeof(CEL_EXTRA_PROCESS_INFO) + (wLen * sizeof(WCHAR))),
0, CELZONE_PROCESS | CELZONE_LOADER | CELZONE_PROFILER,
0, FALSE);
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Helper func to generate a CeLog thread create event, minimizing stack usage.
_inline static void
CELOG_SyncThread(
PTHREAD pThread,
HANDLE hProcess
)
{
PCEL_THREAD_CREATE pcl = &g_CeLogSyncBuffer.ThreadBase;
WORD wLen = 0;
pcl->hProcess = hProcess;
pcl->hThread = pThread->hTh;
pcl->hModule = (HANDLE)0; // The reader can figure out hModule from dwStartAddr
pcl->dwStartAddr = pThread->dwStartAddr;
pcl->nPriority = pThread->bBPrio;
if (pThread == pThread->pOwnerProc->pMainTh) {
// Main thread gets the process' name
pcl->hModule = hProcess;
wLen = strlenW(pThread->pOwnerProc->lpszProcName) + 1;
if (wLen <= MAX_PATH) {
kstrcpyW(pcl->szName, pThread->pOwnerProc->lpszProcName);
} else {
wLen = 0;
}
#ifdef NKPROF // GetThreadName only available in profiling builds
} else {
GetThreadName(pThread, &(pcl->hModule), pcl->szName);
if (pcl->szName[0] != 0) {
wLen = strlenW(pcl->szName) + 1;
}
#endif // NKPROF
}
g_pfnCeLogData(TRUE, CELID_THREAD_CREATE, (PVOID) pcl,
(WORD)(sizeof(CEL_THREAD_CREATE) + (wLen * sizeof(WCHAR))),
0, CELZONE_THREAD | CELZONE_PROFILER, 0, FALSE);
// Log priority inversion if necessary
if (IsCeLogZoneEnabled(CELZONE_PRIORITYINV)
&& (pThread->bBPrio != pThread->bCPrio)) {
PCEL_SYSTEM_INVERT pclInvert = &g_CeLogSyncBuffer.Invert;
pclInvert->hThread = pThread->hTh;
pclInvert->nPriority = pThread->bCPrio;
g_pfnCeLogData(TRUE, CELID_SYSTEM_INVERT, (PVOID) pclInvert,
sizeof(CEL_SYSTEM_INVERT), 0, CELZONE_PRIORITYINV,
0, FALSE);
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Helper func to generate CeLog module events, minimizing stack usage.
_inline static void
CELOG_SyncModule(
HANDLE hProcess,
PMODULE pMod
)
{
PCEL_MODULE_LOAD pclBase = &g_CeLogSyncBuffer.ModuleBase;
PCEL_EXTRA_MODULE_INFO pclExtra = &g_CeLogSyncBuffer.ModuleExtra;
PCEL_MODULE_REFERENCES pclRef = &g_CeLogSyncBuffer.ModuleRef;
WORD wLen;
WORD wProc;
// Log base module info
wLen = 0;
pclBase->hProcess = hProcess;
pclBase->hModule = (HANDLE) pMod;
pclBase->dwBase = ZeroPtr(pMod->BasePtr);
if (pMod->lpszModName) {
wLen = strlenW(pMod->lpszModName) + 1;
if (wLen <= MAX_PATH) {
kstrcpyW(pclBase->szName, pMod->lpszModName);
} else {
wLen = 0;
}
}
g_pfnCeLogData(TRUE, CELID_MODULE_LOAD, (PVOID) pclBase,
(WORD)(sizeof(CEL_MODULE_LOAD) + (wLen * sizeof(WCHAR))),
0, CELZONE_LOADER | CELZONE_THREAD | CELZONE_MEMTRACKING | CELZONE_PROFILER, // CELZONE_THREAD necessary for getting thread names
0, FALSE);
// Log extra module info
pclExtra->hModule = (HANDLE) pMod;
pclExtra->dwVMLen = pMod->e32.e32_vsize;
pclExtra->dwModuleFlags = CELOG_ModuleFlags((DWORD)pMod->BasePtr);
wLen = CELOG_FileInfoFromOE(&pMod->oe, &pclExtra->dwOID,
pclExtra->szFullPath);
g_pfnCeLogData(TRUE, CELID_EXTRA_MODULE_INFO, (PVOID) pclExtra,
(WORD)(sizeof(CEL_EXTRA_MODULE_INFO) + (wLen * sizeof(WCHAR))),
0, CELZONE_LOADER | CELZONE_PROFILER,
0, FALSE);
// Log per-process refcounts for the module
wLen = 0;
pclRef->hModule = (HANDLE) pMod;
for (wProc = 0; wProc < MAX_PROCESSES; wProc++) {
if (pMod->refcnt[wProc] > 0) {
pclRef->ref[wLen].hProcess = ProcArray[wProc].hProc;
pclRef->ref[wLen].dwRefCount = pMod->refcnt[wProc];
wLen++;
}
}
if (wLen > 0) {
g_pfnCeLogData(TRUE, CELID_MODULE_REFERENCES, (PVOID) pclRef,
(WORD) (sizeof(CEL_MODULE_REFERENCES) + ((wLen - 1) * sizeof(CEL_PROCESS_REFCOUNT))),
0, CELZONE_LOADER | CELZONE_PROFILER, 0, FALSE);
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
BOOL
SC_CeLogReSync()
{
CEL_LOG_MARKER marker;
// KCall so nobody changes ProcArray or pModList out from under us
if (!InSysCall()) {
return KCall((PKFN)SC_CeLogReSync);
}
KCALLPROFON(74);
if (IsCeLogStatus(CELOGSTATUS_ENABLED_ANY)) {
// Send a marker
marker.dwFrequency = g_dwCeLogTimerFrequency;
marker.dwDefaultQuantum = dwDefaultThreadQuantum;
marker.dwVersion = CELOG_VERSION;
g_pfnCeLogData(FALSE, CELID_LOG_MARKER, &marker, sizeof(CEL_LOG_MARKER),
0, CELZONE_ALWAYSON, 0, FALSE);
// Log the list of processes and threads
if (IsCeLogEnabled(CELOGSTATUS_ENABLED_ANY,
CELZONE_PROCESS | CELZONE_THREAD
| CELZONE_MEMTRACKING | CELZONE_PROFILER)) {
ACCESSKEY ulOldKey;
int nProc;
// Since we're in a KCall, we must limit stack usage, so we can't
// call CELOG_ProcessCreate, CELOG_ThreadCreate, CELOG_ModuleLoad
// -- instead use CELOG_Sync*.
SWITCHKEY(ulOldKey, 0xffffffff); // Need access to touch procnames
for (nProc = 0; nProc < 32; nProc++) {
if (ProcArray[nProc].dwVMBase) {
THREAD* pThread;
// Log the process
CELOG_SyncProcess(&ProcArray[nProc]);
// Log each of the process' threads
if (IsCeLogEnabled(CELOGSTATUS_ENABLED_ANY,
CELZONE_THREAD | CELZONE_PROFILER)) {
pThread = ProcArray[nProc].pTh;
while (pThread != NULL) {
CELOG_SyncThread(pThread, pThread->pOwnerProc->hProc);
pThread = pThread->pNextInProc;
}
}
}
}
SETCURKEY(ulOldKey);
}
// Log the list of modules
if (IsCeLogEnabled(CELOGSTATUS_ENABLED_ANY,
CELZONE_LOADER | CELZONE_THREAD
| CELZONE_MEMTRACKING | CELZONE_PROFILER)) {
PMODULE pMod;
for (pMod = pModList; pMod; pMod = pMod->pMod) {
CELOG_SyncModule(INVALID_HANDLE_VALUE, pMod);
}
}
// Send a sync end marker
g_pfnCeLogData(FALSE, CELID_SYNC_END, NULL, 0, 0, CELZONE_ALWAYSON,
0, FALSE);
}
KCALLPROFOFF(74);
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -