Beispiel #1
0
        /// <summary>
        /// Merges regions of a given set of normalized regions using a fast stack based algorithm O(nlogn + n).
        /// </summary>
        /// <param name="regions">The regions to merge and sort.</param>
        /// <returns>The merged and sorted regions.</returns>
        private IEnumerable <NormalizedRegion> MergeAndSortRegions(IEnumerable <NormalizedRegion> regions)
        {
            if (regions == null || regions.Count() <= 0)
            {
                return(null);
            }

            // First, sort by start address
            IList <NormalizedRegion> sortedRegions = regions.OrderBy(x => x.BaseAddress.ToUInt64()).ToList();

            // Create and initialize the stack with the first region
            Stack <NormalizedRegion> combinedRegions = new Stack <NormalizedRegion>();

            combinedRegions.Push(sortedRegions[0]);

            // Build the remaining regions
            for (Int32 index = combinedRegions.Count; index < sortedRegions.Count; index++)
            {
                NormalizedRegion top = combinedRegions.Peek();

                if (top.EndAddress.ToUInt64() < sortedRegions[index].BaseAddress.ToUInt64())
                {
                    // If the interval does not overlap, put it on the top of the stack
                    combinedRegions.Push(sortedRegions[index]);
                }
                else if (top.EndAddress.ToUInt64() == sortedRegions[index].BaseAddress.ToUInt64())
                {
                    // The regions are adjacent; merge them
                    top.RegionSize = sortedRegions[index].EndAddress.Subtract(top.BaseAddress).ToInt32();
                }
                else if (top.EndAddress.ToUInt64() <= sortedRegions[index].EndAddress.ToUInt64())
                {
                    // The regions overlap
                    top.RegionSize = sortedRegions[index].EndAddress.Subtract(top.BaseAddress).ToInt32();
                }
            }

            return(combinedRegions.ToList().OrderBy(x => x.BaseAddress.ToUInt64()).ToList());
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="RegionProperties" /> class.
 /// </summary>
 /// <param name="region">The region that this chunk spans.</param>
 public RegionProperties(NormalizedRegion region) : this(region.BaseAddress, region.RegionSize)
 {
 }
        /// <summary>
        /// Queries virtual pages from the OS to dertermine if any allocations or deallocations have happened.
        /// </summary>
        /// <returns>The collected pages.</returns>
        private IEnumerable <RegionProperties> CollectNewPages()
        {
            List <RegionProperties> newRegions = new List <RegionProperties>();

            // Gather current regions from the target process
            IEnumerable <NormalizedRegion> queriedVirtualRegions = SnapshotManager.GetInstance().CollectSnapshotRegions();
            List <NormalizedRegion>        queriedChunkedRegions = new List <NormalizedRegion>();

            // Chunk all virtual regions into a standardized size
            queriedVirtualRegions.ForEach(x => queriedChunkedRegions.AddRange(x.ChunkNormalizedRegion(ChunkLinkedListPrefilter.ChunkSize)));

            // Sort our lists (descending)
            IOrderedEnumerable <NormalizedRegion> queriedRegionsSorted = queriedChunkedRegions.OrderByDescending(x => x.BaseAddress.ToUInt64());
            IOrderedEnumerable <RegionProperties> currentRegionsSorted;

            lock (this.ChunkLock)
            {
                currentRegionsSorted = this.ChunkList.OrderByDescending(x => x.BaseAddress.ToUInt64());
            }

            // Create comparison stacks
            Stack <RegionProperties> currentRegionStack = new Stack <RegionProperties>();
            Stack <NormalizedRegion> queriedRegionStack = new Stack <NormalizedRegion>();

            currentRegionsSorted.ForEach(x => currentRegionStack.Push(x));
            queriedRegionsSorted.ForEach(x => queriedRegionStack.Push(x));

            // Begin stack based comparison algorithm to resolve our chunk processing queue
            NormalizedRegion queriedRegion = queriedRegionStack.Count == 0 ? null : queriedRegionStack.Pop();
            RegionProperties currentRegion = currentRegionStack.Count == 0 ? null : currentRegionStack.Pop();

            while (queriedRegionStack.Count > 0 && currentRegionStack.Count > 0)
            {
                if (queriedRegion < currentRegion)
                {
                    // New region we have not seen yet
                    newRegions.Add(new RegionProperties(queriedRegion));
                    queriedRegion = queriedRegionStack.Pop();
                }
                else if (queriedRegion > currentRegion)
                {
                    // Region that went missing (deallocated)
                    currentRegion = currentRegionStack.Pop();
                }
                else
                {
                    // Region we have already seen
                    queriedRegion = queriedRegionStack.Pop();
                    currentRegion = currentRegionStack.Pop();
                }
            }

            // Add remaining queried regions
            while (queriedRegionStack.Count > 0)
            {
                newRegions.Add(new RegionProperties(queriedRegion));
                queriedRegion = queriedRegionStack.Pop();
            }

            return(newRegions);
        }
Beispiel #4
0
        /// <summary>
        /// Masks the given memory regions against the given memory regions, keeping the common elements of the two in O(n).
        /// </summary>
        /// <param name="groundTruth">The snapshot regions to mask the target regions against.</param>
        public void MaskRegions(IEnumerable <NormalizedRegion> groundTruth)
        {
            List <SnapshotRegion> resultRegions = new List <SnapshotRegion>();

            groundTruth = this.MergeAndSortRegions(groundTruth);

            // if (this.SnapshotRegions == null || groundTruth == null || this.SnapshotRegions.Count <= 0 || groundTruth.Count() <= 0)
            {
                // this.SnapshotRegions = resultRegions;
                // return;
            }

            this.MergeAndSortRegions();

            // TODO: Resolve the masking issues below:
            return;

            // Initialize stacks with regions and masking regions
            Queue <SnapshotRegion>   candidateRegions = new Queue <SnapshotRegion>();
            Queue <NormalizedRegion> maskingRegions   = new Queue <NormalizedRegion>();

            // Build candidate region queue from target region array
            foreach (SnapshotRegion region in this.SnapshotRegions.OrderBy(x => x.BaseAddress.ToUInt64()))
            {
                candidateRegions.Enqueue(region);
            }

            // Build masking region queue from snapshot
            foreach (NormalizedRegion maskRegion in groundTruth.OrderBy(x => x.BaseAddress.ToUInt64()))
            {
                maskingRegions.Enqueue(maskRegion);
            }

            if (candidateRegions.Count <= 0 || maskingRegions.Count <= 0)
            {
                this.SnapshotRegions = resultRegions;
                return;
            }

            SnapshotRegion   currentRegion;
            NormalizedRegion currentMask = maskingRegions.Dequeue();

            while (candidateRegions.Count > 0)
            {
                // Grab next region
                currentRegion = candidateRegions.Dequeue();

                // Grab the next mask following the current region
                while (currentMask.EndAddress.ToUInt64() < currentRegion.BaseAddress.ToUInt64() && maskingRegions.Count > 0)
                {
                    currentMask = maskingRegions.Dequeue();
                }

                // Check for mask completely removing this region
                if (currentMask.EndAddress.ToUInt64() < currentRegion.BaseAddress.ToUInt64() || currentMask.BaseAddress.ToUInt64() > currentRegion.EndAddress.ToUInt64())
                {
                    continue;
                }

                // Mask completely overlaps, just use the original region
                if (currentMask.BaseAddress == currentRegion.BaseAddress && currentMask.EndAddress == currentRegion.EndAddress)
                {
                    resultRegions.Add(currentRegion);
                    continue;
                }

                // Mask is within bounds; Grab the masked portion of this region
                Int32 baseOffset = currentMask.BaseAddress.ToUInt64() <= currentRegion.BaseAddress.ToUInt64() ? 0 : currentMask.BaseAddress.Subtract(currentRegion.BaseAddress).ToInt32();

                SnapshotRegion newRegion = new SnapshotRegion(currentRegion as NormalizedRegion);
                newRegion.BaseAddress = currentRegion.BaseAddress + baseOffset;
                newRegion.BaseAddress = Math.Min(currentMask.EndAddress.ToUInt64(), currentRegion.EndAddress.ToUInt64()).ToIntPtr();
                newRegion.SetCurrentValues(currentRegion.GetCurrentValues().LargestSubArray(baseOffset, newRegion.RegionSize));
                newRegion.SetPreviousValues(currentRegion.GetPreviousValues().LargestSubArray(baseOffset, newRegion.RegionSize));
                newRegion.SetElementLabels(currentRegion.GetElementLabels().LargestSubArray(baseOffset, newRegion.RegionSize));
                newRegion.ElementType = currentRegion.ElementType;
                newRegion.Alignment   = currentRegion.Alignment;
                resultRegions.Add(newRegion);
            }

            this.SnapshotRegions = resultRegions;
        }
Beispiel #5
0
        /// <summary>
        /// Combines the given memory regions with the given memory regions, only keeping the common elements of the two in O(nlogn + n).
        /// </summary>
        /// <param name="otherSnapshot">The snapshot regions to mask the target regions against.</param>
        private void Intersect(Snapshot otherSnapshot)
        {
            List <SnapshotRegion> resultRegions = new List <SnapshotRegion>();

            otherSnapshot.MergeAndSortRegions();
            IEnumerable <NormalizedRegion> otherRegions = otherSnapshot.GetSnapshotRegions();

            if (this.SnapshotRegions.IsNullOrEmpty() || otherRegions.IsNullOrEmpty())
            {
                this.SnapshotRegions = resultRegions;
                return;
            }

            this.MergeAndSortRegions();

            // Initialize stacks with regions and masking regions
            Queue <SnapshotRegion>   snapshotRegionQueue = new Queue <SnapshotRegion>();
            Queue <NormalizedRegion> groundTruthQueue    = new Queue <NormalizedRegion>();

            // Build candidate region queue from snapshot region array
            foreach (SnapshotRegion region in this.SnapshotRegions.OrderBy(x => x.BaseAddress.ToUInt64()))
            {
                snapshotRegionQueue.Enqueue(region);
            }

            // Build masking region queue from snapshot
            foreach (NormalizedRegion maskRegion in otherRegions.OrderBy(x => x.BaseAddress.ToUInt64()))
            {
                groundTruthQueue.Enqueue(maskRegion);
            }

            if (snapshotRegionQueue.Count <= 0 || groundTruthQueue.Count <= 0)
            {
                this.SnapshotRegions = resultRegions;
                return;
            }

            SnapshotRegion   nextSnapshotRegion;
            NormalizedRegion groundTruthMask = groundTruthQueue.Dequeue();

            while (snapshotRegionQueue.Count > 0)
            {
                // Grab next region
                nextSnapshotRegion = snapshotRegionQueue.Dequeue();

                // Grab the next mask following the current region
                while (groundTruthMask.EndAddress.ToUInt64() < nextSnapshotRegion.BaseAddress.ToUInt64() && groundTruthQueue.Count > 0)
                {
                    groundTruthMask = groundTruthQueue.Dequeue();
                }

                // Check for mask completely removing this region
                if (groundTruthMask.EndAddress.ToUInt64() < nextSnapshotRegion.BaseAddress.ToUInt64() || groundTruthMask.BaseAddress.ToUInt64() > nextSnapshotRegion.EndAddress.ToUInt64())
                {
                    continue;
                }
                // Check for mask completely engulfing this region
                else if (groundTruthMask.BaseAddress.ToUInt64() <= nextSnapshotRegion.BaseAddress.ToUInt64() && groundTruthMask.EndAddress.ToUInt64() >= nextSnapshotRegion.EndAddress.ToUInt64())
                {
                    resultRegions.Add(nextSnapshotRegion);
                    continue;
                }
                // There are no edge cases, we must mask and copy the valid portion of this region
                else
                {
                    UInt64 baseAddress = Math.Max(groundTruthMask.BaseAddress.ToUInt64(), nextSnapshotRegion.BaseAddress.ToUInt64());
                    UInt64 endAddress  = Math.Min(groundTruthMask.EndAddress.ToUInt64(), nextSnapshotRegion.EndAddress.ToUInt64());
                    Int64  baseOffset  = unchecked ((Int64)(baseAddress - nextSnapshotRegion.BaseAddress.ToUInt64()));

                    SnapshotRegion newRegion = new SnapshotRegion(nextSnapshotRegion as NormalizedRegion);
                    newRegion.BaseAddress = baseAddress.ToIntPtr();
                    newRegion.EndAddress  = endAddress.ToIntPtr();
                    newRegion.SetCurrentValues(nextSnapshotRegion.CurrentValues.LargestSubArray(baseOffset, newRegion.RegionSize.ToInt64()));
                    newRegion.SetPreviousValues(nextSnapshotRegion.PreviousValues.LargestSubArray(baseOffset, newRegion.RegionSize.ToInt64()));
                    newRegion.SetElementLabels(nextSnapshotRegion.ElementLabels.LargestSubArray(baseOffset, newRegion.RegionSize.ToInt64()));
                    newRegion.ElementType = nextSnapshotRegion.ElementType;
                    newRegion.Alignment   = nextSnapshotRegion.Alignment;
                    resultRegions.Add(newRegion);
                }
            }

            this.SnapshotRegions = resultRegions;
        }
Beispiel #6
0
 /// <summary>
 /// Initializes a new instance of the <see cref="SnapshotRegion" /> class.
 /// </summary>
 /// <param name="normalizedRegion">The region on which to base this snapshot region.</param>
 public SnapshotRegion(NormalizedRegion normalizedRegion) :
     this(normalizedRegion == null ? IntPtr.Zero : normalizedRegion.BaseAddress, normalizedRegion == null ? 0 : normalizedRegion.RegionSize)
 {
 }