Пример #1
0
 /// <summary>
 /// Initializes a new instance of the <see cref="SnapshotElementIndexer" /> class.
 /// </summary>
 /// <param name="region">The parent region that contains this element.</param>
 /// <param name="elementIndex">The index of the element to begin pointing to.</param>
 public unsafe SnapshotElementIndexer(
     SnapshotRegion region,
     Int32 elementIndex = 0)
 {
     this.Region       = region;
     this.ElementIndex = elementIndex;
 }
Пример #2
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();
        }
Пример #3
0
        /// <summary>
        /// Indexer to allow the retrieval of the element at the specified index. Notes: This does NOT index into a region.
        /// </summary>
        /// <param name="elementIndex">The index of the snapshot element.</param>
        /// <returns>Returns the snapshot element at the specified index.</returns>
        public SnapshotElementIndexer this[UInt64 elementIndex]
        {
            get
            {
                SnapshotRegion region = this.BinaryRegionSearch(elementIndex);

                if (region == null)
                {
                    return(null);
                }

                return(region[(elementIndex - region.BaseElementIndex).ToInt32()]);
            }
        }
Пример #4
0
        /// <summary>
        /// Initializes a new instance of the <see cref="SnapshotElementComparer" /> class.
        /// </summary>
        /// <param name="region">The parent region that contains this element.</param>
        /// <param name="elementIndex">The index of the element to begin pointing to.</param>
        /// <param name="compareActionConstraint">The constraint to use for the element quick action.</param>
        /// <param name="compareActionValue">The value to use for the element quick action.</param>
        /// <param name="pointerIncrementMode">The method by which to increment element pointers.</param>
        public unsafe SnapshotElementComparer(
            SnapshotRegion region,
            PointerIncrementMode pointerIncrementMode,
            ScanConstraintManager scanConstraintManager)
        {
            this.Region = region;

            // The garbage collector can relocate variables at runtime. Since we use unsafe pointers, we need to keep these pinned
            this.CurrentValuesHandle  = GCHandle.Alloc(this.Region.ReadGroup.CurrentValues, GCHandleType.Pinned);
            this.PreviousValuesHandle = GCHandle.Alloc(this.Region.ReadGroup.PreviousValues, GCHandleType.Pinned);

            this.InitializePointers();
            this.SetConstraintFunctions();
            this.SetPointerFunction(pointerIncrementMode);
            this.SetCompareAction(scanConstraintManager);
        }
Пример #5
0
        /// <summary>
        /// Initializes a new instance of the <see cref="SnapshotElementVectorComparer" /> class.
        /// </summary>
        /// <param name="region">The parent region that contains this element.</param>
        /// <param name="vectorSize">The size of vectors on the system.</param>
        /// <param name="scanConstraints">The set of constraints to use for the element comparisons.</param>
        public unsafe SnapshotElementVectorComparer(
            SnapshotRegion region,
            ScanConstraintManager scanConstraints)
        {
            this.Region          = region;
            this.VectorSize      = EngineCore.GetInstance().Architecture.GetVectorSize();
            this.VectorReadBase  = this.Region.ReadGroupOffset - this.Region.ReadGroupOffset % this.VectorSize;
            this.VectorReadIndex = 0;
            this.DataTypeSize    = Conversions.SizeOf(this.Region.ReadGroup.ElementDataType);

            // Initialize capacity to 1/16 elements
            this.ResultRegions = new List <SnapshotRegion>(unchecked ((Int32)(this.Region.ElementCount)) / 16);

            this.SetConstraintFunctions();
            this.SetCompareAction(scanConstraints);
        }
Пример #6
0
        /// <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);
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="SnapshotElementIterator" /> class.
        /// </summary>
        /// <param name="parent">The parent region that contains this element.</param>
        /// <param name="elementIndex">The index of the element to begin pointing to.</param>
        /// <param name="compareActionConstraint">The constraint to use for the element quick action.</param>
        /// <param name="compareActionValue">The value to use for the element quick action.</param>
        /// <param name="pointerIncrementMode">The method by which to increment element pointers.</param>
        public unsafe SnapshotElementIterator(
            SnapshotRegion parent,
            Int32 elementIndex = 0,
            PointerIncrementMode pointerIncrementMode = PointerIncrementMode.AllPointers,
            ConstraintsEnum compareActionConstraint   = ConstraintsEnum.Changed,
            Object compareActionValue = null)
        {
            this.Parent = parent;

            // The garbage collector can relocate variables at runtime. Since we use unsafe pointers, we need to keep these pinned
            this.CurrentValuesHandle  = GCHandle.Alloc(this.Parent.CurrentValues, GCHandleType.Pinned);
            this.PreviousValuesHandle = GCHandle.Alloc(this.Parent.PreviousValues, GCHandleType.Pinned);

            this.InitializePointers(elementIndex);
            this.SetConstraintFunctions();
            this.SetPointerFunction(pointerIncrementMode);
            this.SetCompareAction(compareActionConstraint, compareActionValue);
        }
Пример #8
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;
        }
Пример #9
0
        /// <summary>
        /// Finalizes any leftover snapshot regions and returns them.
        /// </summary>
        public IList <SnapshotRegion> GatherCollectedRegions()
        {
            // Create the final region if we are still encoding
            if (this.Encoding)
            {
                this.ResultRegions.Add(new SnapshotRegion(this.Region.ReadGroup, this.VectorReadBase + this.VectorReadIndex - this.RunLength, this.RunLength));
                this.RunLength = 0;
                this.Encoding  = false;
            }

            // Remove vector misaligned leading regions
            SnapshotRegion firstRegion   = this.ResultRegions.FirstOrDefault();
            Int32          adjustedIndex = 0;

            while (firstRegion != null)
            {
                // Exit if not misaligned
                if (firstRegion.ReadGroupOffset >= this.Region.ReadGroupOffset)
                {
                    break;
                }

                Int32 misalignment = this.Region.ReadGroupOffset - firstRegion.ReadGroupOffset;

                if (firstRegion.RegionSize <= misalignment)
                {
                    // The region is totally eclipsed -- remove it
                    this.ResultRegions.Remove(firstRegion);
                }
                else
                {
                    // The region is partially eclipsed -- adjust the size
                    firstRegion.ReadGroupOffset += misalignment;
                    firstRegion.RegionSize      -= misalignment;
                    adjustedIndex++;
                }

                firstRegion = this.ResultRegions.Skip(adjustedIndex).FirstOrDefault();
            }

            // Remove vector overreading trailing regions
            SnapshotRegion lastRegion = this.ResultRegions.LastOrDefault();

            adjustedIndex = 0;

            while (lastRegion != null)
            {
                // Exit if not overreading
                if (lastRegion.EndAddress.ToUInt64() <= this.Region.EndAddress.ToUInt64())
                {
                    break;
                }

                Int32 overread = (lastRegion.EndAddress.ToUInt64() - this.Region.EndAddress.ToUInt64()).ToInt32();

                if (lastRegion.RegionSize <= overread)
                {
                    // The region is totally eclipsed -- remove it
                    this.ResultRegions.Remove(lastRegion);
                }
                else
                {
                    lastRegion.RegionSize -= overread;
                    adjustedIndex++;
                }

                lastRegion = this.ResultRegions.Reverse().Skip(adjustedIndex).FirstOrDefault();
            }

            return(this.ResultRegions);
        }