Exemple #1
0
        /// <summary>
        /// Merges regions in the current list of memory regions using a fast stack based algorithm O(nlogn + n).
        /// </summary>
        private void MergeAndSortRegions()
        {
            if (this.SnapshotRegions.IsNullOrEmpty())
            {
                return;
            }

            // First, sort by start address
            IEnumerable <SnapshotRegion> sortedRegions = this.SnapshotRegions.OrderBy(x => x.BaseAddress.ToUInt64());

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

            combinedRegions.Push(sortedRegions.First());

            // Build the remaining regions
            foreach (SnapshotRegion region in sortedRegions.Skip(1))
            {
                SnapshotRegion top = combinedRegions.Peek();

                // If the regions do not overlap, the new region is the top region
                if (top.EndAddress.ToUInt64() < region.BaseAddress.ToUInt64())
                {
                    combinedRegions.Push(region);
                }
                // The regions are exactly adjacent; merge them
                else if (top.EndAddress.ToUInt64() == region.BaseAddress.ToUInt64())
                {
                    top.RegionSize = region.EndAddress.Subtract(top.BaseAddress).ToUInt64();

                    // Combine values and labels
                    top.SetElementLabels(top.ElementLabels?.Concat(region.ElementLabels));
                    top.SetCurrentValues(top.CurrentValues?.Concat(region.CurrentValues));
                    top.SetPreviousValues(top.PreviousValues?.Concat(region.PreviousValues));
                }
                // The regions overlap
                else if (top.EndAddress.ToUInt64() <= region.EndAddress.ToUInt64())
                {
                    top.RegionSize = region.EndAddress.Subtract(top.BaseAddress).ToUInt64();

                    Int32 overlapSize = unchecked ((Int32)(region.EndAddress.ToUInt64() - top.EndAddress.ToUInt64()));

                    // Overlap has conflicting values, so we prioritize the top region and trim the current region
                    region.SetElementLabels(region.ElementLabels?.SubArray(overlapSize, region.RegionSize.ToInt32() - overlapSize));
                    region.SetCurrentValues(region.CurrentValues?.SubArray(overlapSize, region.RegionSize.ToInt32() - overlapSize));
                    region.SetPreviousValues(region.PreviousValues?.SubArray(overlapSize, region.RegionSize.ToInt32() - overlapSize));

                    // Combine values and labels
                    top.SetElementLabels(top.ElementLabels?.Concat(region.ElementLabels));
                    top.SetCurrentValues(top.CurrentValues?.Concat(region.CurrentValues));
                    top.SetPreviousValues(top.PreviousValues?.Concat(region.PreviousValues));
                }
            }

            this.SnapshotRegions = combinedRegions.ToList().OrderBy(x => x.BaseAddress.ToUInt64()).ToList();
        }
        /// <summary>
        /// Gets the regions in this snapshot with a valid bit set.
        /// </summary>
        /// <returns>The regions in this snapshot with a valid bit set.</returns>
        public IEnumerable <SnapshotRegion> GetValidRegions()
        {
            List <SnapshotRegion> validRegions = new List <SnapshotRegion>();
            Int32 elementSize = this.GetElementSize();

            if (this.ValidBits == null)
            {
                return(validRegions);
            }

            for (Int32 startIndex = 0; startIndex < this.ValidBits.Length; startIndex += this.Alignment)
            {
                if (!this.ValidBits[startIndex])
                {
                    continue;
                }

                // Get the length of this valid segment
                Int32 validRegionSize = 0;
                do
                {
                    // We only care if the aligned elements are valid
                    validRegionSize += elementSize;
                }while (startIndex + validRegionSize < this.ValidBits.Length && this.ValidBits[startIndex + validRegionSize]);

                // Create new subregion from this valid region
                SnapshotRegion subRegion = new SnapshotRegion(this.BaseAddress + startIndex, validRegionSize.ToUInt64());

                // Ensure region size is worth keeping. This can happen if we grab a misaligned segment
                if (subRegion.RegionSize < Conversions.GetTypeSize(this.ElementType).ToUInt64())
                {
                    continue;
                }

                // Copy the current values and labels.
                subRegion.SetCurrentValues(this.CurrentValues.LargestSubArray(startIndex, subRegion.RegionSize.ToInt64()));
                subRegion.SetPreviousValues(this.PreviousValues.LargestSubArray(startIndex, subRegion.RegionSize.ToInt64()));
                subRegion.SetElementLabels(this.ElementLabels.LargestSubArray(startIndex, subRegion.RegionSize.ToInt64()));

                validRegions.Add(subRegion);
                startIndex += validRegionSize;
            }

            this.ValidBits = null;
            return(validRegions);
        }
Exemple #3
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;
        }