Example #1
0
        public CEXTDEFRecord(RecordReader reader, RecordContext context)
            : base(reader, context)
        {
            int startIndex = context.ExternalNames.Count;

            while (!reader.IsEOF)
            {
                UInt16 nameIndex = reader.ReadIndex();
                if (nameIndex == 0 || nameIndex > context.Names.Count)
                {
                    throw new InvalidDataException("LogicalNameIndex is out of range.");
                }
                UInt16 typeIndex = reader.ReadIndex();

                ExternalNameDefinition def = new ExternalNameDefinition();

                def.Name      = context.Names[nameIndex - 1];
                def.TypeIndex = typeIndex;
                def.DefinedBy = reader.RecordNumber;
                context.ExternalNames.Add(def);
            }
            int endIndex = context.ExternalNames.Count;

            this.Definitions = context.ExternalNames.Slice(
                startIndex, endIndex - startIndex);
        }
Example #2
0
        /// <summary>
        /// Loads a LIB file from a BinaryReader.
        /// </summary>
        /// <param name="reader"></param>
        /// <returns></returns>
        public static IEnumerable <Records.RecordContext> LoadLibrary(BinaryReader reader)
        {
            if (reader == null)
            {
                throw new ArgumentNullException("reader");
            }

            LibraryHeaderRecord r = (LibraryHeaderRecord)
                                    Record.ReadRecord(reader, null, RecordNumber.LibraryHeader);
            int pageSize = r.PageSize;

            while (true)
            {
                Records.RecordContext module = LoadObject(reader);
                if (module == null) // LibraryEndRecord encountered
                {
                    yield break;
                }
                yield return(module);

                // Since a LIB file consists of multiple object modules
                // aligned on page boundary, we need to consume the padding
                // bytes if present.
                int mod = (int)(reader.BaseStream.Position % pageSize);
                if (mod != 0)
                {
                    reader.ReadBytes(pageSize - mod);
                }
            }
        }
Example #3
0
        public COMDEFRecord(RecordReader reader, RecordContext context)
            : base(reader, context)
        {
            int startIndex = context.ExternalNames.Count;

            while (!reader.IsEOF)
            {
                CommunalNameDefinition def = new CommunalNameDefinition();
                def.DefinedBy    = reader.RecordNumber;
                def.Name         = reader.ReadPrefixedString();
                def.TypeIndex    = reader.ReadIndex();
                def.DataType     = reader.ReadByte();
                def.ElementCount = ReadEncodedInteger(reader);
                if (def.DataType == 0x61) // FAR data: count, elemsize
                {
                    def.ElementSize = ReadEncodedInteger(reader);
                }
                else
                {
                    def.ElementSize = 1;
                }
                context.ExternalNames.Add(def);
            }
            int endIndex = context.ExternalNames.Count;

            this.Definitions = context.ExternalNames.Slice(
                startIndex, endIndex - startIndex);
        }
Example #4
0
        public GRPDEFRecord(RecordReader reader, RecordContext context)
            : base(reader, context)
        {
            this.Definition = new GroupDefinition();

            UInt16 groupNameIndex = reader.ReadIndex();

            if (groupNameIndex == 0 || groupNameIndex > context.Names.Count)
            {
                throw new InvalidDataException("GroupNameIndex is out of range.");
            }
            this.Definition.Name = context.Names[groupNameIndex - 1];

            while (!reader.IsEOF)
            {
                reader.ReadByte(); // 'type' ignored
                UInt16 segmentIndex = reader.ReadIndex();
                if (segmentIndex == 0 || segmentIndex > context.Segments.Count)
                {
                    throw new InvalidDataException("SegmentIndex is out of range.");
                }
                this.Definition.Segments.Add(context.Segments[segmentIndex - 1]);
            }

            context.Groups.Add(Definition);
        }
Example #5
0
        public LibraryHeaderRecord(RecordReader reader, RecordContext context)
            : base(reader, context)
        {
            this.PageSize = reader.Data.Length + 4;

            // Record data consists of 7 bytes of dictionary information
            // (which we ignore), followed by padding bytes to make the next
            // record (which should be THEADR) aligned on page boundary.
        }
Example #6
0
        public MODENDRecord(RecordReader reader, RecordContext context)
            : base(reader, context)
        {
            byte type = reader.ReadByte();

            this.IsMainModule              = (type & 0x80) != 0;
            this.IsStartAddressPresent     = (type & 0x40) != 0;
            this.IsStartAddressRelocatable = (type & 0x01) != 0;

            // TODO: read the start address field...
        }
Example #7
0
        internal ListOfNamesRecord(RecordReader reader, RecordContext context)
            : base(reader, context)
        {
            List <string> names = new List <string>();

            while (!reader.IsEOF)
            {
                names.Add(reader.ReadPrefixedString());
            }
            this.Names = names.ToArray();
            context.Names.AddRange(Names);
        }
Example #8
0
        public LIDATARecord(RecordReader reader, RecordContext context)
            : base(reader, context)
        {
            this.SegmentIndex = reader.ReadIndex();
            if (SegmentIndex == 0 || SegmentIndex > context.Segments.Count)
            {
                throw new InvalidDataException("SegmentIndex is out of range.");
            }

            this.DataOffset = reader.ReadUInt16Or32();
            this.Data       = reader.ReadToEnd();

            // TODO: parse LIDATA (recursive; a bit messy)
        }
Example #9
0
        public FixupRecord(RecordReader reader, RecordContext context)
            : base(reader, context)
        {
            List <FixupThreadDefinition> threads = new List <FixupThreadDefinition>();
            List <FixupDefinition>       fixups  = new List <FixupDefinition>();

            while (!reader.IsEOF)
            {
                byte b = reader.PeekByte();
                if ((b & 0x80) == 0)
                {
                    FixupThreadDefinition thread = ParseThreadSubrecord(reader);
                    threads.Add(thread);
                    if (thread.Kind == FixupThreadKind.Target)
                    {
                        context.TargetThreads[thread.ThreadNumber] = thread;
                    }
                    else
                    {
                        context.FrameThreads[thread.ThreadNumber] = thread;
                    }
                }
                else
                {
                    FixupDefinition fixup = ParseFixupSubrecord(reader, context);
                    fixups.Add(fixup);

                    if (context.LastRecord is LEDATARecord)
                    {
                        var r = (LEDATARecord)context.LastRecord;
                        fixup.DataOffset += (ushort)r.DataOffset;
                        r.Segment.Fixups.Add(fixup);
                    }
                    else if (context.LastRecord is LIDATARecord)
                    {
                    }
                    else if (context.LastRecord is COMDATRecord)
                    {
                    }
                    else
                    {
                        throw new InvalidDataException("FIXUPP record must follow LEDATA, LIDATA, or COMDAT record.");
                    }
                }
            }

            this.Threads = threads.ToArray();
            this.Fixups  = fixups.ToArray();
        }
Example #10
0
        public PUBDEFRecord(RecordReader reader, RecordContext context)
            : base(reader, context)
        {
            int baseGroupIndex = reader.ReadIndex();

            if (baseGroupIndex > context.Groups.Count)
            {
                throw new InvalidDataException("GroupIndex is out of range.");
            }
            if (baseGroupIndex > 0)
            {
                this.BaseGroup = context.Groups[baseGroupIndex - 1];
            }

            int baseSegmentIndex = reader.ReadIndex();

            if (baseSegmentIndex > context.Segments.Count)
            {
                throw new InvalidDataException("SegmentIndex is out of range.");
            }
            if (baseSegmentIndex == 0)
            {
                this.BaseFrame = reader.ReadUInt16();
            }
            else
            {
                this.BaseSegment = context.Segments[baseSegmentIndex - 1];
            }

            int startIndex = context.PublicNames.Count;

            while (!reader.IsEOF)
            {
                PublicNameDefinition def = new PublicNameDefinition();
                def.DefinedBy   = reader.RecordNumber;
                def.BaseGroup   = BaseGroup;
                def.BaseSegment = BaseSegment;
                def.BaseFrame   = BaseFrame;
                def.Name        = reader.ReadPrefixedString();
                def.Offset      = (int)reader.ReadUInt16Or32();
                def.TypeIndex   = reader.ReadIndex();
                context.PublicNames.Add(def);
            }
            int endIndex = context.PublicNames.Count;

            this.Definitions = context.PublicNames.Slice(
                startIndex, endIndex - startIndex);
        }
Example #11
0
        public ALIASRecord(RecordReader reader, RecordContext context)
            : base(reader, context)
        {
            int startIndex = context.Aliases.Count;

            while (!reader.IsEOF)
            {
                AliasDefinition def = new AliasDefinition();
                def.AliasName      = reader.ReadPrefixedString();
                def.SubstituteName = reader.ReadPrefixedString();
                context.Aliases.Add(def);
            }
            int endIndex = context.Aliases.Count;

            this.Definitions = context.Aliases.Slice(startIndex, endIndex - startIndex);
        }
Example #12
0
        public EXTDEFRecord(RecordReader reader, RecordContext context)
            : base(reader, context)
        {
            int startIndex = context.ExternalNames.Count;

            while (!reader.IsEOF)
            {
                ExternalNameDefinition def = new ExternalNameDefinition();
                def.Name      = reader.ReadPrefixedString();
                def.TypeIndex = reader.ReadIndex();
                def.DefinedBy = reader.RecordNumber;
                context.ExternalNames.Add(def);
            }
            int endIndex = context.ExternalNames.Count;

            this.Definitions = context.ExternalNames.Slice(
                startIndex, endIndex - startIndex);
        }
Example #13
0
        public FixupRecord(RecordReader reader, RecordContext context)
            : base(reader, context)
        {
            List<FixupThreadDefinition> threads = new List<FixupThreadDefinition>();
            List<FixupDefinition> fixups = new List<FixupDefinition>();
            while (!reader.IsEOF)
            {
                byte b = reader.PeekByte();
                if ((b & 0x80) == 0)
                {
                    FixupThreadDefinition thread = ParseThreadSubrecord(reader);
                    threads.Add(thread);
                    if (thread.Kind == FixupThreadKind.Target)
                        context.TargetThreads[thread.ThreadNumber] = thread;
                    else
                        context.FrameThreads[thread.ThreadNumber] = thread;
                }
                else
                {
                    FixupDefinition fixup = ParseFixupSubrecord(reader, context);
                    fixups.Add(fixup);

                    if (context.LastRecord is LEDATARecord)
                    {
                        var r = (LEDATARecord)context.LastRecord;
                        fixup.DataOffset += (ushort)r.DataOffset;
                        r.Segment.Fixups.Add(fixup);
                    }
                    else if (context.LastRecord is LIDATARecord)
                    {
                    }
                    else if (context.LastRecord is COMDATRecord)
                    {
                    }
                    else
                    {
                        throw new InvalidDataException("FIXUPP record must follow LEDATA, LIDATA, or COMDAT record.");
                    }
                }
            }

            this.Threads = threads.ToArray();
            this.Fixups = fixups.ToArray();
        }
Example #14
0
        public SEGDEFRecord(RecordReader reader, RecordContext context)
            : base(reader, context)
        {
            SegmentDefinition def = new SegmentDefinition();

            // Read the record.
            byte acbp = reader.ReadByte();
            def.Alignment = GetAlignment(acbp);
            def.Combination = GetCombination(acbp);
            def.IsUse32 = GetUse32(acbp);

            if (def.Alignment == SegmentAlignment.Absolute)
            {
                def.Frame = reader.ReadUInt16();
                def.Offset = reader.ReadByte();
            }

            UInt32 storedLength=reader.ReadUInt16Or32();
            def.Length = GetLength(acbp, storedLength, reader.RecordNumber);

            UInt16 segmentNameIndex = reader.ReadIndex();
            if (segmentNameIndex > context.Names.Count)
                throw new InvalidDataException("SegmentNameIndex is out of range.");
            if (segmentNameIndex > 0)
                def.SegmentName = context.Names[segmentNameIndex - 1];

            UInt16 classNameIndex = reader.ReadIndex();
            if (classNameIndex > context.Names.Count)
                throw new InvalidDataException("ClassNameIndex is out of range.");
            if (classNameIndex > 0)
                def.ClassName = context.Names[classNameIndex - 1];

            UInt16 overlayNameIndex = reader.ReadIndex();
            if (overlayNameIndex > context.Names.Count)
                throw new InvalidDataException("OverlayNameIndex is out of range.");
            if (overlayNameIndex > 0)
                def.OverlayName = context.Names[overlayNameIndex - 1];

            def.Data = new byte[def.Length];
            //def.Fixups = new List<FixupDefinition>();

            this.Definition = def;
            context.Segments.Add(def);
        }
Example #15
0
        /// <summary>
        /// Loads an object module from binary reader.
        /// </summary>
        /// <param name="reader"></param>
        /// <returns>
        /// The loaded module if successful, or null if LibraryEndRecord is
        /// encountered before MODEND or MODEND32 record is encountered.
        /// </returns>
        public static RecordContext LoadObject(BinaryReader reader)
        {
            List<Record> records = new List<Record>();
            RecordContext context = new RecordContext();

            while (true)
            {
                Record record = Record.ReadRecord(reader, context);
                records.Add(record);

                if (record.RecordNumber == RecordNumber.MODEND ||
                    record.RecordNumber == RecordNumber.MODEND32)
                {
                    break;
                }
                if (record.RecordNumber == RecordNumber.LibraryEnd)
                {
                    return null;
                }
            }
            context.Records = records.ToArray();
            return context;
        }
Example #16
0
        public LEDATARecord(RecordReader reader, RecordContext context)
            : base(reader, context)
        {
            UInt16 segmentIndex = reader.ReadIndex();

            if (segmentIndex == 0 || segmentIndex > context.Segments.Count)
            {
                throw new InvalidDataException("SegmentIndex is out of range.");
            }
            this.Segment = context.Segments[segmentIndex - 1];

            this.DataOffset = reader.ReadUInt16Or32();
            this.Data       = reader.ReadToEnd(); // TBD: this can be optimized to
                                                  // reduce extra data copy

            // Fill the segment's data.
            if (Data.Length + DataOffset > Segment.Length)
            {
                throw new InvalidDataException("The LEDATA overflows the segment.");
            }

            Array.Copy(Data, 0, Segment.Data, DataOffset, Data.Length);
        }
Example #17
0
        private static object ResolveFixupReferent(
            RecordContext context, FixupTargetMethod method, UInt16 indexOrFrame)
        {
            switch (method)
            {
            case FixupTargetMethod.Absolute:
                return(indexOrFrame);

            case FixupTargetMethod.SegmentPlusDisplacement:
            case FixupTargetMethod.SegmentWithoutDisplacement:
                return(context.Segments[indexOrFrame - 1]);

            case FixupTargetMethod.GroupPlusDisplacement:
            case FixupTargetMethod.GroupWithoutDisplacement:
                return(context.Groups[indexOrFrame - 1]);

            case FixupTargetMethod.ExternalPlusDisplacement:
            case FixupTargetMethod.ExternalWithoutDisplacement:
                return(context.ExternalNames[indexOrFrame - 1]);

            default:
                throw new InvalidDataException("Invalid fixup target method: " + method);
            }
        }
Example #18
0
 public THEADRRecord(RecordReader reader, RecordContext context)
     : base(reader, context)
 {
     this.Name = reader.ReadPrefixedString();
     context.SourceName = Name;
 }
Example #19
0
        public MODENDRecord(RecordReader reader, RecordContext context)
            : base(reader, context)
        {
            byte type = reader.ReadByte();
            this.IsMainModule = (type & 0x80) != 0;
            this.IsStartAddressPresent = (type & 0x40) != 0;
            this.IsStartAddressRelocatable = (type & 0x01) != 0;

            // TODO: read the start address field...
        }
Example #20
0
        public LIDATARecord(RecordReader reader, RecordContext context)
            : base(reader, context)
        {
            this.SegmentIndex = reader.ReadIndex();
            if (SegmentIndex == 0 || SegmentIndex > context.Segments.Count)
                throw new InvalidDataException("SegmentIndex is out of range.");

            this.DataOffset = reader.ReadUInt16Or32();
            this.Data = reader.ReadToEnd();

            // TODO: parse LIDATA (recursive; a bit messy)
        }
Example #21
0
 public LibraryEndRecord(RecordReader reader, RecordContext context)
     : base(reader, context)
 {
     // Record data serves as padding to align the dictionary that
     // follows at 512-byte boundary.
 }
Example #22
0
        public LEDATARecord(RecordReader reader, RecordContext context)
            : base(reader, context)
        {
            UInt16 segmentIndex = reader.ReadIndex();
            if (segmentIndex == 0 || segmentIndex > context.Segments.Count)
            {
                throw new InvalidDataException("SegmentIndex is out of range.");
            }
            this.Segment = context.Segments[segmentIndex - 1];

            this.DataOffset = reader.ReadUInt16Or32();
            this.Data = reader.ReadToEnd(); // TBD: this can be optimized to
                                            // reduce extra data copy

            // Fill the segment's data.
            if (Data.Length + DataOffset > Segment.Length)
                throw new InvalidDataException("The LEDATA overflows the segment.");

            Array.Copy(Data, 0, Segment.Data, DataOffset, Data.Length);
        }
Example #23
0
 public EXTDEFRecord(RecordReader reader, RecordContext context)
     : base(reader, context)
 {
     int startIndex = context.ExternalNames.Count;
     while (!reader.IsEOF)
     {
         ExternalNameDefinition def = new ExternalNameDefinition();
         def.Name = reader.ReadPrefixedString();
         def.TypeIndex = reader.ReadIndex();
         def.DefinedBy = reader.RecordNumber;
         context.ExternalNames.Add(def);
     }
     int endIndex = context.ExternalNames.Count;
     this.Definitions = context.ExternalNames.Slice(
         startIndex, endIndex - startIndex);
 }
Example #24
0
        private FixupDefinition ParseFixupSubrecord(RecordReader reader, RecordContext context)
        {
            FixupDefinition fixup = new FixupDefinition();

            byte b1 = reader.ReadByte();
            byte b2 = reader.ReadByte();
            UInt16 w = (UInt16)((b1 << 8) | b2); // big endian

            fixup.Mode = (w & 0x4000) != 0 ? FixupMode.SegmentRelative : FixupMode.SelfRelative;
            fixup.Location = (FixupLocation)((w >> 10) & 0x0F);
            fixup.DataOffset = (UInt16)(w & 0x03FF);

            byte b = reader.ReadByte();
            bool useFrameThread = (b & 0x80) != 0;
            if (useFrameThread)
            {
                int frameNumber = (b >> 4) & 0x3;
                FixupThreadDefinition thread = context.FrameThreads[frameNumber];
                if (!thread.IsDefined)
                    throw new InvalidDataException("Frame thread " + frameNumber + " is not defined.");

                FixupFrame spec = new FixupFrame();
                spec.Method = (FixupFrameMethod)thread.Method;
                spec.IndexOrFrame = thread.IndexOrFrame;
                fixup.Frame = spec;
            }
            else
            {
                FixupFrame spec = new FixupFrame();
                spec.Method = (FixupFrameMethod)((b >> 4) & 7);
                if ((int)spec.Method <= 3)
                {
                    spec.IndexOrFrame = reader.ReadIndex();
                }
                fixup.Frame = spec;
            }

            bool useTargetThread = (b & 0x08) != 0;
            if (useTargetThread)
            {
                bool hasTargetDisplacement = (b & 0x04) != 0;
                int targetNumber = b & 3;
                FixupThreadDefinition thread = context.TargetThreads[targetNumber];
                if (!thread.IsDefined)
                    throw new InvalidDataException("Target thread " + targetNumber + " is not defined.");

                FixupTargetMethod method = (FixupTargetMethod)((int)thread.Method & 3);
                if (hasTargetDisplacement)
                    method |= (FixupTargetMethod)4;

                FixupTarget spec = new FixupTarget();
                spec.Referent = ResolveFixupReferent(context, method, thread.IndexOrFrame);
                if ((int)method <= 3)
                {
                    spec.Displacement = reader.ReadUInt16Or32();
                }
                fixup.Target = spec;
            }
            else
            {
                FixupTargetMethod method = (FixupTargetMethod)(b & 7);
                UInt16 indexOrFrame = reader.ReadIndex();

                FixupTarget spec = new FixupTarget();
                spec.Referent = ResolveFixupReferent(context, method, indexOrFrame);
                if ((int)method <= 3)
                {
                    spec.Displacement = reader.ReadUInt16Or32();
                }
                fixup.Target = spec;
            }
            return fixup;
        }
Example #25
0
 public LIBMODComment(RecordReader reader, RecordContext context)
 {
     this.ModuleName = reader.ReadPrefixedString();
     context.ObjectName = ModuleName;
 }
Example #26
0
        internal static Record ReadRecord(
            BinaryReader binaryReader,
            RecordContext context,
            RecordNumber expectedRecord)
        {
            RecordReader reader = new RecordReader(binaryReader);

            if (expectedRecord != RecordNumber.None &&
                reader.RecordNumber != expectedRecord)
            {
                throw new InvalidDataException(string.Format(
                                                   "Expecting record {0}, but got record {1}.",
                                                   expectedRecord, reader.RecordNumber));
            }

            Record r;

            switch (reader.RecordNumber)
            {
            case RecordNumber.LibraryHeader:
                r = new LibraryHeaderRecord(reader, context);
                break;

            case RecordNumber.LibraryEnd:
                r = new LibraryEndRecord(reader, context);
                break;

            case RecordNumber.ALIAS:
                r = new ALIASRecord(reader, context);
                break;

            case RecordNumber.CEXTDEF:
                r = new CEXTDEFRecord(reader, context);
                break;

            case RecordNumber.COMDAT:
            case RecordNumber.COMDAT32:
                r = new COMDATRecord(reader, context);
                break;

            case RecordNumber.COMDEF:
                r = new COMDEFRecord(reader, context);
                break;

            case RecordNumber.COMENT:
                r = new CommentRecord(reader, context);
                break;

            case RecordNumber.EXTDEF:
                r = new EXTDEFRecord(reader, context);
                break;

            case RecordNumber.FIXUPP:
            case RecordNumber.FIXUPP32:
                r = new FixupRecord(reader, context);
                break;

            case RecordNumber.GRPDEF:
                r = new GRPDEFRecord(reader, context);
                break;

            case RecordNumber.LCOMDEF:
                r = new LCOMDEFRecord(reader, context);
                break;

            case RecordNumber.LEDATA:
            case RecordNumber.LEDATA32:
                r = new LEDATARecord(reader, context);
                break;

            case RecordNumber.LEXTDEF:
            case RecordNumber.LEXTDEF32:
                r = new LEXTDEFRecord(reader, context);
                break;

            case RecordNumber.LHEADR:
                r = new LHEADRRecord(reader, context);
                break;

            case RecordNumber.LIDATA:
            case RecordNumber.LIDATA32:
                r = new LIDATARecord(reader, context);
                break;

            case RecordNumber.LNAMES:
                r = new ListOfNamesRecord(reader, context);
                break;

            case RecordNumber.LPUBDEF:
            case RecordNumber.LPUBDEF32:
                r = new LPUBDEFRecord(reader, context);
                break;

            case RecordNumber.MODEND:
                r = new MODENDRecord(reader, context);
                break;

            case RecordNumber.PUBDEF:
            case RecordNumber.PUBDEF32:
                r = new PUBDEFRecord(reader, context);
                break;

            case RecordNumber.SEGDEF:
            case RecordNumber.SEGDEF32:
                r = new SEGDEFRecord(reader, context);
                break;

            case RecordNumber.THEADR:
                r = new THEADRRecord(reader, context);
                break;

            default:
                r = new UnknownRecord(reader, context);
                break;
            }

            // TODO: check all bytes are consumed.
            // ...

            // Update RecordContext.LastRecord. This is necessary so that
            // a FIXUPP record knows which record to fix up.
            if (context != null)
            {
                context.LastRecord = r;
            }

            return(r);
        }
Example #27
0
 public COMDATRecord(RecordReader reader, RecordContext context)
     : base(reader, context)
 {
     // TODO: parse contents.
 }
Example #28
0
 public UnknownRecord(RecordReader reader, RecordContext context)
     : base(reader, context)
 {
     this.Data = reader.Data;
 }
Example #29
0
 public LibraryEndRecord(RecordReader reader, RecordContext context)
     : base(reader, context)
 {
     // Record data serves as padding to align the dictionary that
     // follows at 512-byte boundary.
 }
Example #30
0
 public THEADRRecord(RecordReader reader, RecordContext context)
     : base(reader, context)
 {
     this.Name          = reader.ReadPrefixedString();
     context.SourceName = Name;
 }
Example #31
0
 internal static Record ReadRecord(BinaryReader binaryReader, RecordContext context)
 {
     return(ReadRecord(binaryReader, context, RecordNumber.None));
 }
Example #32
0
        private FixupDefinition ParseFixupSubrecord(RecordReader reader, RecordContext context)
        {
            FixupDefinition fixup = new FixupDefinition();

            byte   b1 = reader.ReadByte();
            byte   b2 = reader.ReadByte();
            UInt16 w  = (UInt16)((b1 << 8) | b2); // big endian

            fixup.Mode       = (w & 0x4000) != 0 ? FixupMode.SegmentRelative : FixupMode.SelfRelative;
            fixup.Location   = (FixupLocation)((w >> 10) & 0x0F);
            fixup.DataOffset = (UInt16)(w & 0x03FF);

            byte b = reader.ReadByte();
            bool useFrameThread = (b & 0x80) != 0;

            if (useFrameThread)
            {
                int frameNumber = (b >> 4) & 0x3;
                FixupThreadDefinition thread = context.FrameThreads[frameNumber];
                if (!thread.IsDefined)
                {
                    throw new InvalidDataException("Frame thread " + frameNumber + " is not defined.");
                }

                FixupFrame spec = new FixupFrame();
                spec.Method       = (FixupFrameMethod)thread.Method;
                spec.IndexOrFrame = thread.IndexOrFrame;
                fixup.Frame       = spec;
            }
            else
            {
                FixupFrame spec = new FixupFrame();
                spec.Method = (FixupFrameMethod)((b >> 4) & 7);
                if ((int)spec.Method <= 3)
                {
                    spec.IndexOrFrame = reader.ReadIndex();
                }
                fixup.Frame = spec;
            }

            bool useTargetThread = (b & 0x08) != 0;

            if (useTargetThread)
            {
                bool hasTargetDisplacement   = (b & 0x04) != 0;
                int  targetNumber            = b & 3;
                FixupThreadDefinition thread = context.TargetThreads[targetNumber];
                if (!thread.IsDefined)
                {
                    throw new InvalidDataException("Target thread " + targetNumber + " is not defined.");
                }

                FixupTargetMethod method = (FixupTargetMethod)((int)thread.Method & 3);
                if (hasTargetDisplacement)
                {
                    method |= (FixupTargetMethod)4;
                }

                FixupTarget spec = new FixupTarget();
                spec.Referent = ResolveFixupReferent(context, method, thread.IndexOrFrame);
                if ((int)method <= 3)
                {
                    spec.Displacement = reader.ReadUInt16Or32();
                }
                fixup.Target = spec;
            }
            else
            {
                FixupTargetMethod method       = (FixupTargetMethod)(b & 7);
                UInt16            indexOrFrame = reader.ReadIndex();

                FixupTarget spec = new FixupTarget();
                spec.Referent = ResolveFixupReferent(context, method, indexOrFrame);
                if ((int)method <= 3)
                {
                    spec.Displacement = reader.ReadUInt16Or32();
                }
                fixup.Target = spec;
            }
            return(fixup);
        }
Example #33
0
 public LCOMDEFRecord(RecordReader reader, RecordContext context)
     : base(reader, context)
 {
 }
Example #34
0
        internal CommentRecord(RecordReader reader, RecordContext context)
            : base(reader, context)
        {
            byte commentType = reader.ReadByte();

            this.IsPreserved = (commentType & 0x80) != 0;
            this.IsHidden    = (commentType & 0x40) != 0;

            byte commentClass = reader.ReadByte();

            switch (commentClass)
            {
            case 0:
                Comment = new TextComment(reader, "Translator");
                break;

            case 1:
                Comment = new TextComment(reader, "Copyright");
                break;

            case 0x81:
            case 0x9F:
                Comment = new TextComment(reader, "DefaultLibrarySearchName");
                break;

            case 0x9C:     // not supported
                break;

            case 0x9D:
                Comment = new MemoryModelComment(reader);
                break;

            case 0x9E:
                Comment = new DOSSEGComment(reader);
                break;

            case 0xA0:     // OMF Extensions
                Comment = ParseOmfExtensions(reader);
                break;

            case 0xA1:     // debug symbol type, such as CV; ignored
                break;

            case 0xA2:
                Comment = new LinkPassSeparatorComment(reader);
                break;

            case 0xA3:
                Comment = new LIBMODComment(reader, context);
                break;

            case 0xA4:     // EXESTR
                break;

            case 0xA6:     // INCERR
                break;

            case 0xA7:     // NOPAD
                break;

            case 0xA8:     // WKEXT
                Comment = new WKEXTComment(reader);
                break;

            case 0xA9:     // LZEXT
                break;

            case 0xDA:
                Comment = new TextComment(reader, "Comment");
                break;

            case 0xDB:
                Comment = new TextComment(reader, "Compiler");
                break;

            case 0xDC:
                Comment = new TextComment(reader, "Date");
                break;

            case 0xDD:
                Comment = new TextComment(reader, "Timestamp");
                break;

            case 0xDF:
                Comment = new TextComment(reader, "User");
                break;

            case 0xE9:     // borland
                Comment = new TextComment(reader, "Dependencies");
                break;

            case 0xFF:     // MS QuickC
                Comment = new TextComment(reader, "CommandLine");
                break;
            }
            if (Comment == null)
            {
                Comment = new UnknownComment(reader, commentClass);
            }
        }
Example #35
0
        public GRPDEFRecord(RecordReader reader, RecordContext context)
            : base(reader, context)
        {
            this.Definition = new GroupDefinition();

            UInt16 groupNameIndex = reader.ReadIndex();
            if (groupNameIndex == 0 || groupNameIndex > context.Names.Count)
            {
                throw new InvalidDataException("GroupNameIndex is out of range.");
            }
            this.Definition.Name = context.Names[groupNameIndex - 1];

            while (!reader.IsEOF)
            {
                reader.ReadByte(); // 'type' ignored
                UInt16 segmentIndex = reader.ReadIndex();
                if (segmentIndex == 0 || segmentIndex > context.Segments.Count)
                {
                    throw new InvalidDataException("SegmentIndex is out of range.");
                }
                this.Definition.Segments.Add(context.Segments[segmentIndex - 1]);
            }

            context.Groups.Add(Definition);
        }
Example #36
0
 public LIBMODComment(RecordReader reader, RecordContext context)
 {
     this.ModuleName    = reader.ReadPrefixedString();
     context.ObjectName = ModuleName;
 }
Example #37
0
 public LHEADRRecord(RecordReader reader, RecordContext context)
     : base(reader, context)
 {
     this.Name = reader.ReadPrefixedString();
 }
Example #38
0
 internal ListOfNamesRecord(RecordReader reader, RecordContext context)
     : base(reader, context)
 {
     List<string> names = new List<string>();
     while (!reader.IsEOF)
     {
         names.Add(reader.ReadPrefixedString());
     }
     this.Names = names.ToArray();
     context.Names.AddRange(Names);
 }
Example #39
0
        public LibraryHeaderRecord(RecordReader reader, RecordContext context)
            : base(reader, context)
        {
            this.PageSize = reader.Data.Length + 4;

            // Record data consists of 7 bytes of dictionary information
            // (which we ignore), followed by padding bytes to make the next
            // record (which should be THEADR) aligned on page boundary.
        }
Example #40
0
 internal Record(RecordReader reader, RecordContext context)
 {
     this.Position     = reader.Position;
     this.RecordNumber = reader.RecordNumber;
 }
Example #41
0
 public LPUBDEFRecord(RecordReader reader, RecordContext context)
     : base(reader, context)
 {
 }
Example #42
0
 internal static Record ReadRecord(BinaryReader binaryReader, RecordContext context)
 {
     return ReadRecord(binaryReader, context, RecordNumber.None);
 }
Example #43
0
        public PUBDEFRecord(RecordReader reader, RecordContext context)
            : base(reader, context)
        {
            int baseGroupIndex = reader.ReadIndex();
            if (baseGroupIndex > context.Groups.Count)
                throw new InvalidDataException("GroupIndex is out of range.");
            if (baseGroupIndex > 0)
                this.BaseGroup = context.Groups[baseGroupIndex - 1];

            int baseSegmentIndex = reader.ReadIndex();
            if (baseSegmentIndex > context.Segments.Count)
                throw new InvalidDataException("SegmentIndex is out of range.");
            if (baseSegmentIndex == 0)
                this.BaseFrame = reader.ReadUInt16();
            else
                this.BaseSegment = context.Segments[baseSegmentIndex - 1];

            int startIndex = context.PublicNames.Count;
            while (!reader.IsEOF)
            {
                PublicNameDefinition def = new PublicNameDefinition();
                def.DefinedBy = reader.RecordNumber;
                def.BaseGroup = BaseGroup;
                def.BaseSegment = BaseSegment;
                def.BaseFrame = BaseFrame;
                def.Name = reader.ReadPrefixedString();
                def.Offset = (int)reader.ReadUInt16Or32();
                def.TypeIndex = reader.ReadIndex();
                context.PublicNames.Add(def);
            }
            int endIndex = context.PublicNames.Count;
            this.Definitions = context.PublicNames.Slice(
                startIndex, endIndex - startIndex);
        }
Example #44
0
        internal static Record ReadRecord(
            BinaryReader binaryReader,
            RecordContext context,
            RecordNumber expectedRecord)
        {
            RecordReader reader = new RecordReader(binaryReader);
            if (expectedRecord != RecordNumber.None &&
                reader.RecordNumber != expectedRecord)
            {
                throw new InvalidDataException(string.Format(
                    "Expecting record {0}, but got record {1}.",
                    expectedRecord, reader.RecordNumber));
            }

            Record r;
            switch (reader.RecordNumber)
            {
                case RecordNumber.LibraryHeader:
                    r = new LibraryHeaderRecord(reader, context);
                    break;
                case RecordNumber.LibraryEnd:
                    r = new LibraryEndRecord(reader, context);
                    break;
                case RecordNumber.ALIAS:
                    r = new ALIASRecord(reader, context);
                    break;
                case RecordNumber.CEXTDEF:
                    r = new CEXTDEFRecord(reader, context);
                    break;
                case RecordNumber.COMDAT:
                case RecordNumber.COMDAT32:
                    r = new COMDATRecord(reader, context);
                    break;
                case RecordNumber.COMDEF:
                    r = new COMDEFRecord(reader, context);
                    break;
                case RecordNumber.COMENT:
                    r = new CommentRecord(reader, context);
                    break;
                case RecordNumber.EXTDEF:
                    r = new EXTDEFRecord(reader, context);
                    break;
                case RecordNumber.FIXUPP:
                case RecordNumber.FIXUPP32:
                    r = new FixupRecord(reader, context);
                    break;
                case RecordNumber.GRPDEF:
                    r = new GRPDEFRecord(reader, context);
                    break;
                case RecordNumber.LCOMDEF:
                    r = new LCOMDEFRecord(reader, context);
                    break;
                case RecordNumber.LEDATA:
                case RecordNumber.LEDATA32:
                    r = new LEDATARecord(reader, context);
                    break;
                case RecordNumber.LEXTDEF:
                case RecordNumber.LEXTDEF32:
                    r = new LEXTDEFRecord(reader, context);
                    break;
                case RecordNumber.LHEADR:
                    r = new LHEADRRecord(reader, context);
                    break;
                case RecordNumber.LIDATA:
                case RecordNumber.LIDATA32:
                    r = new LIDATARecord(reader, context);
                    break;
                case RecordNumber.LNAMES:
                    r = new ListOfNamesRecord(reader, context);
                    break;
                case RecordNumber.LPUBDEF:
                case RecordNumber.LPUBDEF32:
                    r = new LPUBDEFRecord(reader, context);
                    break;
                case RecordNumber.MODEND:
                    r = new MODENDRecord(reader, context);
                    break;
                case RecordNumber.PUBDEF:
                case RecordNumber.PUBDEF32:
                    r = new PUBDEFRecord(reader, context);
                    break;
                case RecordNumber.SEGDEF:
                case RecordNumber.SEGDEF32:
                    r = new SEGDEFRecord(reader, context);
                    break;
                case RecordNumber.THEADR:
                    r = new THEADRRecord(reader, context);
                    break;
                default:
                    r = new UnknownRecord(reader, context);
                    break;
            }

            // TODO: check all bytes are consumed.
            // ...

            // Update RecordContext.LastRecord. This is necessary so that
            // a FIXUPP record knows which record to fix up.
            if (context != null)
            {
                context.LastRecord = r;
            }

            return r;
        }
Example #45
0
 public UnknownRecord(RecordReader reader, RecordContext context)
     : base(reader, context)
 {
     this.Data = reader.Data;
 }
Example #46
0
 public ALIASRecord(RecordReader reader, RecordContext context)
     : base(reader, context)
 {
     int startIndex = context.Aliases.Count;
     while (!reader.IsEOF)
     {
         AliasDefinition def = new AliasDefinition();
         def.AliasName = reader.ReadPrefixedString();
         def.SubstituteName = reader.ReadPrefixedString();
         context.Aliases.Add(def);
     }
     int endIndex = context.Aliases.Count;
     this.Definitions = context.Aliases.Slice(startIndex, endIndex - startIndex);
 }
Example #47
0
        public SEGDEFRecord(RecordReader reader, RecordContext context)
            : base(reader, context)
        {
            SegmentDefinition def = new SegmentDefinition();

            // Read the record.
            byte acbp = reader.ReadByte();

            def.Alignment   = GetAlignment(acbp);
            def.Combination = GetCombination(acbp);
            def.IsUse32     = GetUse32(acbp);

            if (def.Alignment == SegmentAlignment.Absolute)
            {
                def.Frame  = reader.ReadUInt16();
                def.Offset = reader.ReadByte();
            }

            UInt32 storedLength = reader.ReadUInt16Or32();

            def.Length = GetLength(acbp, storedLength, reader.RecordNumber);

            UInt16 segmentNameIndex = reader.ReadIndex();

            if (segmentNameIndex > context.Names.Count)
            {
                throw new InvalidDataException("SegmentNameIndex is out of range.");
            }
            if (segmentNameIndex > 0)
            {
                def.SegmentName = context.Names[segmentNameIndex - 1];
            }

            UInt16 classNameIndex = reader.ReadIndex();

            if (classNameIndex > context.Names.Count)
            {
                throw new InvalidDataException("ClassNameIndex is out of range.");
            }
            if (classNameIndex > 0)
            {
                def.ClassName = context.Names[classNameIndex - 1];
            }

            UInt16 overlayNameIndex = reader.ReadIndex();

            if (overlayNameIndex > context.Names.Count)
            {
                throw new InvalidDataException("OverlayNameIndex is out of range.");
            }
            if (overlayNameIndex > 0)
            {
                def.OverlayName = context.Names[overlayNameIndex - 1];
            }

            def.Data = new byte[def.Length];
            //def.Fixups = new List<FixupDefinition>();

            this.Definition = def;
            context.Segments.Add(def);
        }
Example #48
0
        public CEXTDEFRecord(RecordReader reader, RecordContext context)
            : base(reader, context)
        {
            int startIndex = context.ExternalNames.Count;
            while (!reader.IsEOF)
            {
                UInt16 nameIndex = reader.ReadIndex();
                if (nameIndex == 0 || nameIndex > context.Names.Count)
                {
                    throw new InvalidDataException("LogicalNameIndex is out of range.");
                }
                UInt16 typeIndex = reader.ReadIndex();

                ExternalNameDefinition def = new ExternalNameDefinition();

                def.Name = context.Names[nameIndex - 1];
                def.TypeIndex = typeIndex;
                def.DefinedBy = reader.RecordNumber;
                context.ExternalNames.Add(def);
            }
            int endIndex = context.ExternalNames.Count;
            this.Definitions = context.ExternalNames.Slice(
                startIndex, endIndex - startIndex);
        }
Example #49
0
        internal CommentRecord(RecordReader reader, RecordContext context)
            : base(reader, context)
        {
            byte commentType = reader.ReadByte();
            this.IsPreserved = (commentType & 0x80) != 0;
            this.IsHidden = (commentType & 0x40) != 0;

            byte commentClass = reader.ReadByte();
            switch (commentClass)
            {
                case 0:
                    Comment = new TextComment(reader, "Translator");
                    break;
                case 1:
                    Comment = new TextComment(reader, "Copyright");
                    break;
                case 0x81:
                case 0x9F:
                    Comment = new TextComment(reader, "DefaultLibrarySearchName");
                    break;
                case 0x9C: // not supported
                    break;
                case 0x9D:
                    Comment = new MemoryModelComment(reader);
                    break;
                case 0x9E:
                    Comment = new DOSSEGComment(reader);
                    break;
                case 0xA0: // OMF Extensions
                    Comment = ParseOmfExtensions(reader);
                    break;
                case 0xA1: // debug symbol type, such as CV; ignored
                    break;
                case 0xA2:
                    Comment = new LinkPassSeparatorComment(reader);
                    break;
                case 0xA3:
                    Comment = new LIBMODComment(reader, context);
                    break;
                case 0xA4: // EXESTR
                    break;
                case 0xA6: // INCERR
                    break;
                case 0xA7: // NOPAD
                    break;
                case 0xA8: // WKEXT
                    Comment = new WKEXTComment(reader);
                    break;
                case 0xA9: // LZEXT
                    break;
                case 0xDA:
                    Comment = new TextComment(reader, "Comment");
                    break;
                case 0xDB:
                    Comment = new TextComment(reader, "Compiler");
                    break;
                case 0xDC:
                    Comment = new TextComment(reader, "Date");
                    break;
                case 0xDD:
                    Comment = new TextComment(reader, "Timestamp");
                    break;
                case 0xDF:
                    Comment = new TextComment(reader, "User");
                    break;
                case 0xE9: // borland
                    Comment = new TextComment(reader, "Dependencies");
                    break;
                case 0xFF: // MS QuickC
                    Comment = new TextComment(reader, "CommandLine");
                    break;
            }
            if (Comment == null)
            {
                Comment = new UnknownComment(reader, commentClass);
            }
        }
Example #50
0
 public COMDATRecord(RecordReader reader, RecordContext context)
     : base(reader, context)
 {
     // TODO: parse contents.
 }
Example #51
0
 private static object ResolveFixupReferent(
     RecordContext context, FixupTargetMethod method, UInt16 indexOrFrame)
 {
     switch (method)
     {
         case FixupTargetMethod.Absolute:
             return indexOrFrame;
         case FixupTargetMethod.SegmentPlusDisplacement:
         case FixupTargetMethod.SegmentWithoutDisplacement:
             return context.Segments[indexOrFrame - 1];
         case FixupTargetMethod.GroupPlusDisplacement:
         case FixupTargetMethod.GroupWithoutDisplacement:
             return context.Groups[indexOrFrame - 1];
         case FixupTargetMethod.ExternalPlusDisplacement:
         case FixupTargetMethod.ExternalWithoutDisplacement:
             return context.ExternalNames[indexOrFrame - 1];
         default:
             throw new InvalidDataException("Invalid fixup target method: " + method);
     }
 }
Example #52
0
 public COMDEFRecord(RecordReader reader, RecordContext context)
     : base(reader, context)
 {
     int startIndex = context.ExternalNames.Count;
     while (!reader.IsEOF)
     {
         CommunalNameDefinition def = new CommunalNameDefinition();
         def.DefinedBy = reader.RecordNumber;
         def.Name = reader.ReadPrefixedString();
         def.TypeIndex = reader.ReadIndex();
         def.DataType = reader.ReadByte();
         def.ElementCount = ReadEncodedInteger(reader);
         if (def.DataType == 0x61) // FAR data: count, elemsize
             def.ElementSize = ReadEncodedInteger(reader);
         else
             def.ElementSize = 1;
         context.ExternalNames.Add(def);
     }
     int endIndex = context.ExternalNames.Count;
     this.Definitions = context.ExternalNames.Slice(
         startIndex, endIndex - startIndex);
 }
Example #53
0
 internal Record(RecordReader reader, RecordContext context)
 {
     this.Position = reader.Position;
     this.RecordNumber = reader.RecordNumber;
 }
Example #54
0
 public LHEADRRecord(RecordReader reader, RecordContext context)
     : base(reader, context)
 {
     this.Name = reader.ReadPrefixedString();
 }