private void ExtendSegmentCoverage(int segmentIndex, int startOffset, int endOffset)
        {
            ExecutableSegment segment = GetSegment(segmentIndex);

            if (segment.OffsetCoverage.IsSupersetOf(new Range <int>(startOffset, endOffset)))
            {
                return;
            }

            // Extend the segment's offset coverage.
            if (segment.OffsetCoverage.IsEmpty)
            {
                segment.OffsetCoverage = new Range <int>(startOffset, endOffset);
            }
            else
            {
                segment.OffsetCoverage = new Range <int>(
                    Math.Min(segment.OffsetCoverage.Begin, startOffset),
                    Math.Max(segment.OffsetCoverage.End, endOffset));
            }

            // Shrink the offset bounds of its neighboring segments.
            if (segmentIndex > 0)
            {
                ExecutableSegment segBefore = GetSegment(segmentIndex - 1);
                int numBytesOverlap         =
                    (segBefore.Frame * 16 + segBefore.OffsetBounds.End) -
                    (segment.Frame * 16 + segment.OffsetCoverage.Begin);
                if (numBytesOverlap > 0)
                {
                    segBefore.SetOffsetBounds(new Range <int>(
                                                  segBefore.OffsetBounds.Begin,
                                                  segBefore.OffsetBounds.End - numBytesOverlap));
                }
            }
            if (segmentIndex < base.Segments.Count - 1)
            {
                ExecutableSegment segAfter = GetSegment(segmentIndex + 1);
                int numBytesOverlap        =
                    (segment.Frame * 16 + segment.OffsetCoverage.End) -
                    (segAfter.Frame * 16 + segAfter.OffsetBounds.Begin);
                if (numBytesOverlap > 0)
                {
                    segAfter.SetOffsetBounds(new Range <int>(
                                                 segAfter.OffsetBounds.Begin + numBytesOverlap,
                                                 segAfter.OffsetBounds.End));
                }
            }
        }
        public ExecutableImage(MZFile file)
        {
            if (file == null)
                throw new ArgumentNullException("file");

            this.bytes = file.Image;

            // Store relocatable locations for future use.
            List<int> relocs = new List<int>();
            foreach (FarPointer location in file.RelocatableLocations)
            {
                int index = location.Segment * 16 + location.Offset;
                if (index >= 0 && index < bytes.Length - 1)
                    relocs.Add(index);
            }
            relocs.Sort();
            this.relocatableLocations = relocs.ToArray();

            // Guess segmentation info from the segment values to be
            // relocated. For example, if a relocatable location contains the
            // word 0x1790, it means that 0x1790 will be a segment that will
            // be accessed some time during the program's execution.
            //
            // Although the SEG:OFF addresses of the relocatable locations
            // themselves also provide clue about the program's segmentation,
            // it is less important because they are not directly referenced
            // in the program. Therefore we ignore them for the moment.
            foreach (int index in relocatableLocations)
            {
                UInt16 frame = BitConverter.ToUInt16(bytes, index);
                mapFrameToSegment[frame] = -1;
            }
            mapFrameToSegment[file.EntryPoint.Segment] = -1;

            // Create a dummy segment for each of the guessed segments.
            // Initially, we set segment.OffsetCoverage to an empty range to
            // indicate that we have no knowledge about the start and end
            // offset of each segment.
            for (int i = 0; i < mapFrameToSegment.Count; i++)
            {
                UInt16 frameNumber = mapFrameToSegment.Keys[i];
                ExecutableSegment segment = new ExecutableSegment(this, i, frameNumber);

                // Compute offset bounds for this segment.
                // The lower bound is off course zero.
                // The upper bound is 15 bytes into the next segment.
                int startIndex = frameNumber * 16;
                if (startIndex < bytes.Length)
                {
                    int offsetLowerBound = 0;
                    int offsetUpperBound = Math.Min(bytes.Length - startIndex, 0x10000);
                    if (i < mapFrameToSegment.Count - 1)
                    {
                        offsetUpperBound = Math.Min(
                            offsetUpperBound,
                            mapFrameToSegment.Keys[i + 1] * 16 + 15 - startIndex);
                    }
                    segment.SetOffsetBounds(
                        new Range<int>(offsetLowerBound, offsetUpperBound));
                }

                mapFrameToSegment[frameNumber] = i;
                base.Segments.Add(segment);
            }

            this.entryPoint = new Address(
                MapFrameToSegment(file.EntryPoint.Segment), file.EntryPoint.Offset);
        }
        public ExecutableImage(MZFile file)
        {
            if (file == null)
            {
                throw new ArgumentNullException("file");
            }

            this.bytes = file.Image;

            // Store relocatable locations for future use.
            List <int> relocs = new List <int>();

            foreach (FarPointer location in file.RelocatableLocations)
            {
                int index = location.Segment * 16 + location.Offset;
                if (index >= 0 && index < bytes.Length - 1)
                {
                    relocs.Add(index);
                }
            }
            relocs.Sort();
            this.relocatableLocations = relocs.ToArray();

            // Guess segmentation info from the segment values to be
            // relocated. For example, if a relocatable location contains the
            // word 0x1790, it means that 0x1790 will be a segment that will
            // be accessed some time during the program's execution.
            //
            // Although the SEG:OFF addresses of the relocatable locations
            // themselves also provide clue about the program's segmentation,
            // it is less important because they are not directly referenced
            // in the program. Therefore we ignore them for the moment.
            foreach (int index in relocatableLocations)
            {
                UInt16 frame = BitConverter.ToUInt16(bytes, index);
                mapFrameToSegment[frame] = -1;
            }
            mapFrameToSegment[file.EntryPoint.Segment] = -1;

            // Create a dummy segment for each of the guessed segments.
            // Initially, we set segment.OffsetCoverage to an empty range to
            // indicate that we have no knowledge about the start and end
            // offset of each segment.
            for (int i = 0; i < mapFrameToSegment.Count; i++)
            {
                UInt16            frameNumber = mapFrameToSegment.Keys[i];
                ExecutableSegment segment     = new ExecutableSegment(this, i, frameNumber);

                // Compute offset bounds for this segment.
                // The lower bound is off course zero.
                // The upper bound is 15 bytes into the next segment.
                int startIndex = frameNumber * 16;
                if (startIndex < bytes.Length)
                {
                    int offsetLowerBound = 0;
                    int offsetUpperBound = Math.Min(bytes.Length - startIndex, 0x10000);
                    if (i < mapFrameToSegment.Count - 1)
                    {
                        offsetUpperBound = Math.Min(
                            offsetUpperBound,
                            mapFrameToSegment.Keys[i + 1] * 16 + 15 - startIndex);
                    }
                    segment.SetOffsetBounds(
                        new Range <int>(offsetLowerBound, offsetUpperBound));
                }

                mapFrameToSegment[frameNumber] = i;
                base.Segments.Add(segment);
            }

            this.entryPoint = new Address(
                MapFrameToSegment(file.EntryPoint.Segment), file.EntryPoint.Offset);
        }