} // end constructor public static DbgSystemInfo[] BuildSystemTree(DbgEngDebugger debugger) { uint originalSysId = DEBUG_ANY_ID; uint[] sysIds = debugger.GetDbgEngSystemIds(); DbgSystemInfo[] sysInfos = new DbgSystemInfo[sysIds.Length]; if (0 != sysIds.Length) { originalSysId = debugger.GetCurrentDbgEngSystemId(); } for (int i = 0; i < sysIds.Length; i++) { debugger.SetCurrentDbgEngSystemId(sysIds[i]); if (debugger.IsKernelMode) { sysInfos[i] = new DbgKmSystemInfo(sysIds[i]); } else { // User-mode uint[] dbgEngProcIds; uint[] osPids; debugger.GetProcessIds(out dbgEngProcIds, out osPids); sysInfos[i] = new DbgUmSystemInfo(sysIds[i], dbgEngProcIds, osPids); } } if (originalSysId != DEBUG_ANY_ID) { debugger.SetCurrentDbgEngSystemId(originalSysId); } return(sysInfos); } // end BuildSystemTree()
} // end BuildSystemTree() public static void CompareTrees(DbgSystemInfo[] oldTree, DbgSystemInfo[] newTree, out List <DbgUmSystemInfo> umProcessesRemoved, out List <DbgUmSystemInfo> umProcessesAdded, out List <DbgKmSystemInfo> kmTargetsRemoved, out List <DbgKmSystemInfo> kmTargetsAdded) { umProcessesRemoved = new List <DbgUmSystemInfo>(); umProcessesAdded = new List <DbgUmSystemInfo>(); kmTargetsRemoved = new List <DbgKmSystemInfo>(); kmTargetsAdded = new List <DbgKmSystemInfo>(); List <uint> sysIdsRemoved; List <uint> sysIdsAdded; List <uint> sysIdsBoth; DiffCompactSet(oldTree.Select((si) => si.SystemIndex).ToArray(), newTree.Select((si) => si.SystemIndex).ToArray(), out sysIdsAdded, out sysIdsRemoved, out sysIdsBoth); // This dictionary maps a system id to "before" and "after" DbgSystemInfos. // (the values will be an array of 2 DbgSystemInfo objects: [0] is "before" // and [1] is "after") var both = new Dictionary <uint, DbgSystemInfo[]>(); const int idxBefore = 0; const int idxAfter = 1; foreach (var newInfo in newTree) { if (sysIdsAdded.Contains(newInfo.SystemIndex)) { if (newInfo.IsKernelTarget) { kmTargetsAdded.Add((DbgKmSystemInfo)newInfo); } else { umProcessesAdded.Add((DbgUmSystemInfo)newInfo); } } else { Util.Assert(sysIdsBoth.Contains(newInfo.SystemIndex)); var bothArray = new DbgSystemInfo[] { null, newInfo }; both.Add(newInfo.SystemIndex, bothArray); } } // end foreach( newInfo ) foreach (var oldInfo in oldTree) { if (sysIdsRemoved.Contains(oldInfo.SystemIndex)) { if (oldInfo.IsKernelTarget) { kmTargetsRemoved.Add((DbgKmSystemInfo)oldInfo); } else { umProcessesRemoved.Add((DbgUmSystemInfo)oldInfo); } } else { Util.Assert(sysIdsBoth.Contains(oldInfo.SystemIndex)); both[oldInfo.SystemIndex][idxBefore] = oldInfo; } } // end foreach( oldInfo ) foreach (var kvp in both) { if (kvp.Value[idxBefore].IsKernelTarget) { // We don't have to peer into kernel targets to look for added/removed // user-mode processes. Util.Assert(kvp.Value[idxAfter].IsKernelTarget); continue; } DbgUmSystemInfo beforeInfo = (DbgUmSystemInfo)kvp.Value[idxBefore]; DbgUmSystemInfo afterInfo = (DbgUmSystemInfo)kvp.Value[idxAfter]; List <uint> procIdsRemoved; List <uint> procIdsAdded; List <uint> procIdsBoth; DiffCompactSet(beforeInfo.ProcessIds, afterInfo.ProcessIds, out procIdsAdded, out procIdsRemoved, out procIdsBoth); if (0 != procIdsAdded.Count) { // TODO: If we have to deal with a lot of processes, this could be // optimized in a few ways: 1) we could take advantage of the fact // that DiffCompactSet returns things in sorted order, so that we // don't have to search the entire OS pid list each time; or 2) we // could just use an array of DEBUG_ANY_ID and get the OS ids // on-demand. // // For the removed processes, though... we might not have any other // way to get the OS pid. uint[] osPids = new uint[procIdsAdded.Count]; for (int i = 0; i < osPids.Length; i++) { bool found = false; for (int j = 0; j < afterInfo.ProcessIds.Count; j++) { if (afterInfo.ProcessIds[j] == procIdsAdded[i]) { osPids[i] = afterInfo.ProcessOsIds[j]; found = true; } } Util.Assert(found); } umProcessesAdded.Add(new DbgUmSystemInfo(kvp.Key, procIdsAdded, osPids)); } if (0 != procIdsRemoved.Count) { uint[] osPids = new uint[procIdsRemoved.Count]; for (int i = 0; i < osPids.Length; i++) { bool found = false; for (int j = 0; j < beforeInfo.ProcessIds.Count; j++) { if (beforeInfo.ProcessIds[j] == procIdsRemoved[i]) { osPids[i] = beforeInfo.ProcessOsIds[j]; found = true; } } Util.Assert(found); } umProcessesRemoved.Add(new DbgUmSystemInfo(kvp.Key, procIdsRemoved, osPids)); } } // end foreach( sameInfo ) } // end CompareTrees()