Esempio n. 1
0
        private Header LoadHeader(LeImageReader rdr)
        {
            var header = new Header
            {
                HdrSize      = rdr.ReadLeUInt16(),
                RvaTaa       = rdr.ReadLeUInt16(),
                RvaSymbols   = rdr.ReadLeUInt16(),
                RvaIdent     = rdr.ReadLeUInt16(),
                RvaPatchData = rdr.ReadLeUInt16(),
                Spare0A      = rdr.ReadLeUInt16(),
                IdMajor      = rdr.ReadLeUInt16(),
                IdMinor      = rdr.ReadLeUInt16(),

                HeaderBlocks = rdr.ReadByte(),
                ImageType    = rdr.ReadByte(),
                Spare12      = rdr.ReadLeUInt16(),

                RequestedPrivilegeMask = rdr.ReadLeUInt64(),
                IoChannels             = rdr.ReadLeUInt16(),
                IoSegPages             = rdr.ReadLeUInt16(),
                ImageFlags             = rdr.ReadLeUInt32(),
                GlobalSectionID        = rdr.ReadLeUInt32(),
                SystemVersionNumber    = rdr.ReadLeUInt32(),
            };

            return(header);
        }
Esempio n. 2
0
        public List <ImageSymbol> LoadEntryPoints(Dictionary <int, string> names)
        {
            var rdr     = new LeImageReader(RawImage, this.lfaNew + this.offEntryTable);
            var entries = new List <ImageSymbol>();

            for (;;)
            {
                var cEntries = rdr.ReadByte();
                if (cEntries == 0)
                {
                    break;
                }
                var segNum = rdr.ReadByte();
                var seg    = this.segments[segNum - 1];
                for (int i = 0; i < cEntries; ++i)
                {
                    var    flags  = rdr.ReadByte();
                    var    offset = rdr.ReadUInt16();
                    string name;
                    var    addr  = seg.Address + offset;
                    var    state = arch.CreateProcessorState();

                    ImageSymbol ep = new ImageSymbol(addr);
                    if (names.TryGetValue(entries.Count, out name))
                    {
                        ep.Name = name;
                    }
                    ep.Type                  = SymbolType.Procedure;
                    ep.ProcessorState        = state;
                    imageSymbols[ep.Address] = ep;
                    entries.Add(ep);
                }
            }
            return(entries);
        }
Esempio n. 3
0
        public List <EntryPoint> LoadEntryPoints(Dictionary <int, string> names)
        {
            var rdr     = new LeImageReader(RawImage, this.lfaNew + this.offEntryTable);
            var entries = new List <EntryPoint>();

            for (;;)
            {
                var cEntries = rdr.ReadByte();
                if (cEntries == 0)
                {
                    break;
                }
                var segNum = rdr.ReadByte();
                var seg    = this.segments[segNum - 1];
                for (int i = 0; i < cEntries; ++i)
                {
                    var        flags  = rdr.ReadByte();
                    var        offset = rdr.ReadUInt16();
                    string     name;
                    var        addr  = seg.Address + offset;
                    var        state = arch.CreateProcessorState();
                    EntryPoint ep;
                    if (names.TryGetValue(entries.Count, out name))
                    {
                        ep = new EntryPoint(addr, name, state);
                    }
                    else
                    {
                        ep = new EntryPoint(addr, state);
                    }
                    entries.Add(ep);
                }
            }
            return(entries);
        }
Esempio n. 4
0
        public List <ImageSymbol> LoadEntryPoints(
            uint offEntryTable,
            NeSegment [] segments,
            Dictionary <int, string> names,
            IProcessorArchitecture arch)
        {
            DebugEx.PrintIf(trace.TraceInfo, "== Loading entry points from offset {0:X}", offEntryTable);
            var rdr = new LeImageReader(RawImage, offEntryTable);

            var entries           = new List <ImageSymbol>();
            int bundleOrdinal     = 1;
            int nextbundleOrdinal = 1;

            for (; ;)
            {
                var cBundleEntries = rdr.ReadByte();
                if (cBundleEntries == 0)
                {
                    break;
                }
                nextbundleOrdinal = bundleOrdinal + cBundleEntries;
                var segNum = rdr.ReadByte();
                for (int i = 0; i < cBundleEntries; ++i)
                {
                    byte flags = rdr.ReadByte();
                    if (flags == 0)
                    {
                        break;
                    }
                    (byte iSeg, ushort offset)entry;
                    if (segNum == 0xFF)
                    {
                        entry = ReadMovableSegmentEntry(rdr);
                    }
                    else
                    {
                        entry = ReadFixedSegmentEntry(rdr, segNum);
                    }
                    var         state = arch.CreateProcessorState();
                    var         seg   = segments[entry.iSeg - 1];
                    var         addr  = seg.Address + entry.offset;
                    ImageSymbol ep    = new ImageSymbol(addr);
                    if (names.TryGetValue(bundleOrdinal + i, out string name))
                    {
                        ep.Name = name;
                    }
                    ep.Type                  = SymbolType.Procedure;
                    ep.ProcessorState        = state;
                    imageSymbols[ep.Address] = ep;
                    entries.Add(ep);
                    DebugEx.PrintIf(trace.TraceVerbose, "   {0}", ep);
                }
                bundleOrdinal = nextbundleOrdinal;
            }
            return(entries);
        }
Esempio n. 5
0
        public List<ImageSymbol> LoadEntryPoints(
            uint offEntryTable, 
            NeSegment [] segments, 
            Dictionary<int, string> names,
            IProcessorArchitecture arch)
        {
            DebugEx.Inform(trace, "== Loading entry points from offset {0:X}", offEntryTable);
            var rdr = new LeImageReader(RawImage, offEntryTable);

            var entries = new List<ImageSymbol>();
            int bundleOrdinal = 1;
            int nextbundleOrdinal = 1;
            for (; ; )
            {
                var cBundleEntries = rdr.ReadByte();
                if (cBundleEntries == 0)
                    break;
                nextbundleOrdinal = bundleOrdinal + cBundleEntries;
                var segNum = rdr.ReadByte();
                if (segNum != 0)
                {
                    // If segNum had been 0, it would have 
                    // meant that all we want to do is allocate 
                    // (skip) some ordinal numbers. Since it wasn't 0,
                    // we proceed to generate entry points.
                    for (int i = 0; i < cBundleEntries; ++i)
                    {
                        byte flags = rdr.ReadByte();
                        (byte iSeg, ushort offset) entry;
                        if (segNum == 0xFF)
                        {
                            entry = ReadMovableSegmentEntry(rdr);
                        }
                        else
                        {
                            entry = ReadFixedSegmentEntry(rdr, segNum);
                        }
                        var seg = segments[entry.iSeg - 1];
                        var addr = seg.Address + entry.offset;
                        var ep = ImageSymbol.Procedure(arch, addr);
                        if (names.TryGetValue(bundleOrdinal + i, out string name))
                        {
                            ep.Name = name;
                        }
                        ep.Type = SymbolType.Procedure;
                        ep.ProcessorState = arch.CreateProcessorState();
                        imageSymbols[ep.Address] = ep;
                        entries.Add(ep);
                        DebugEx.Verbose(trace, "   {0:X2} {1} {2} - {3}", segNum, ep.Address, ep.Name, bundleOrdinal + i);
                    }
                }
                bundleOrdinal = nextbundleOrdinal;
            }
            return entries; 
        }
Esempio n. 6
0
		public PeImageLoader(IServiceProvider services, string filename, byte [] img, uint peOffset) : base(services, filename, img)
		{
			ImageReader rdr = new LeImageReader(RawImage, peOffset);
			if (rdr.ReadByte() != 'P' ||
				rdr.ReadByte() != 'E' ||
				rdr.ReadByte() != 0x0 ||
				rdr.ReadByte() != 0x0)
			{
				throw new BadImageFormatException("Not a valid PE header.");
			}
            importThunks = new Dictionary<uint, PseudoProcedure>();
            importReferences = new Dictionary<Address, ImportReference>();
			short expectedMagic = ReadCoffHeader(rdr);
			ReadOptionalHeader(rdr, expectedMagic);
		}
Esempio n. 7
0
        private List <ImageSectionDescriptor> LoadImageSectionDescriptors(ushort rvaIsds)
        {
            var sections = new List <ImageSectionDescriptor>();
            var rdr      = new LeImageReader(RawImage, rvaIsds);

            Debug.WriteLine("Isd: Size Pges Start    Flags    Rva      GsId     Name");

            for (;;)
            {
                var isd = new ImageSectionDescriptor();
                isd.Size = rdr.ReadLeUInt16();
                if (isd.Size == 0)
                {
                    break;
                }
                isd.NumPages   = rdr.ReadLeUInt16();
                isd.StartVPage = rdr.ReadLeUInt32();
                isd.Flags      = rdr.ReadLeUInt32();
                if (isd.Size > 0x0C)
                {
                    isd.RvaFile = rdr.ReadLeUInt32();
                    if (isd.Size > 0x010)
                    {
                        isd.GlobalSectionIdent = rdr.ReadLeUInt32();
                        var count       = rdr.ReadByte();
                        var sectionName = rdr.ReadBytes(count);
                        isd.SectionName = Encoding.ASCII.GetString(sectionName);
                    }
                }
                sections.Add(isd);
                Debug.WriteLine("{0}", isd);
            }
            return(sections);
        }
Esempio n. 8
0
 private (byte, ushort) ReadMovableSegmentEntry(LeImageReader rdr)
 {
     var int3f = rdr.ReadLeUInt16();
     var iSeg = rdr.ReadByte();
     var offset = rdr.ReadLeUInt16();
     return (iSeg, offset);
 }
Esempio n. 9
0
 public static object ReadNumericLeaf(LeImageReader rdr)
 {
     var b = rdr.PeekByte(0);
     if (0 <= b && b <= 0x7F)
         return rdr.ReadByte();
     else
         return ReadLeaf(rdr);
 }
Esempio n. 10
0
            public sstModules(SST sst, int module, byte[] data)
                : base(sst, module, data)
            {
                var _tup_1 = new LeImageReader(data);

                // @struct.unpack_from("<HHHHHBBB", data);
                this.csBase  = _tup_1.ReadLeUInt16();
                this.csOfs   = _tup_1.ReadLeUInt16();
                this.csLen   = _tup_1.ReadLeUInt16();
                this.ovl     = _tup_1.ReadLeUInt16();
                this.libIndx = _tup_1.ReadLeUInt16();
                this.nsegs   = _tup_1.ReadByte();
                _tup_1.ReadByte();
                var strlen = _tup_1.ReadByte();

                this.@string = Encoding.ASCII.GetString(data, data.Length - strlen, strlen);
            }
Esempio n. 11
0
        public List <ArchiveDirectoryEntry> LoadDiskDirectory()
        {
            var  entries = new List <ArchiveDirectoryEntry>();
            var  rdr     = new LeImageReader(RawImage, (uint)SectorOffset(18, 0));
            byte track   = rdr.ReadByte();

            if (track == 0)
            {
                return(entries);
            }
            byte sector = rdr.ReadByte();

            rdr.Offset = (uint)D64Loader.SectorOffset(track, sector);
            while (ReadDirectorySector(rdr, entries))
            {
                ;
            }
            return(entries);
        }
Esempio n. 12
0
        public void ImrBounded_ReadByte()
        {
            // The memarea is 2 bytes...
            var mem = new MemoryArea(Address.Ptr32(0x1213), new byte[] { 0x12, 0x34 });
            // ...but we wish to limit it to 1 byte
            var rdr = new LeImageReader(mem, mem.BaseAddress, mem.BaseAddress + 1);

            Assert.IsTrue(rdr.IsValid);
            Assert.AreEqual((byte)0x12, rdr.ReadByte());
            Assert.IsFalse(rdr.IsValid, "Should have respected the limit.");
        }
Esempio n. 13
0
        public static object ReadNumericLeaf(LeImageReader rdr)
        {
            var b = rdr.PeekByte(0);

            if (0 <= b && b <= 0x7F)
            {
                return(rdr.ReadByte());
            }
            else
            {
                return(ReadLeaf(rdr));
            }
        }
Esempio n. 14
0
            public byte[] GetBytes()
            {
                byte[] data;
                var    stm       = new MemoryStream();
                var    rdr       = new LeImageReader(image, (uint)offset);
                byte   trackNext = rdr.ReadByte();

                while (trackNext != 0)
                {
                    byte sectorNext = rdr.ReadByte();
                    data = rdr.ReadBytes(0xFE);
                    stm.Write(data, 0, data.Length);

                    rdr.Offset = (uint)SectorOffset(trackNext, sectorNext);
                    trackNext  = rdr.ReadByte();
                }
                byte lastUsed = rdr.ReadByte();

                data = rdr.ReadBytes(lastUsed - 2);
                stm.Write(data, 0, data.Length);
                return(stm.ToArray());
            }
Esempio n. 15
0
        public static object ReadLeaf(LeImageReader rdr)
        {
            var b  = rdr.ReadByte();
            var lt = (LeafType)b;

            switch (lt)
            {
            default:
                throw new NotImplementedException($"CodeView leaf type {lt} {(int)lt:X2} not implemented yet.");

            case LeafType.Int8:
                return(rdr.ReadSByte());

            case LeafType.UInt16:
                return(rdr.ReadLeUInt16());

            case LeafType.ARRAY:
                return(ReadArray(rdr));

            case LeafType.INDEX:    // Type index
                return(rdr.ReadLeUInt16());

            case LeafType.LABEL:
                return(ReadLabel(rdr));

            case LeafType.LIST:
                return(ReadList(rdr));

            case LeafType.POINTER:
                return(ReadPointer(rdr));

            case LeafType.PROCEDURE:
                return(ReadProcedure(rdr));

            case LeafType.STRING:
                return(ReadString(rdr));

            case LeafType.STRUCTURE:
                return(ReadStructure(rdr));

            case LeafType.Nil:
            case LeafType.C_FAR:
            case LeafType.C_NEAR:
            case LeafType.FAR:
            case LeafType.NEAR:
            case LeafType.UNPACKED:
            case (LeafType)0x81:    //$REVIEW: void?
                return(lt);
            }
        }
Esempio n. 16
0
 public Dictionary<int, string> LoadEntryNames(uint offset, Dictionary<int, string> dict)
 {
     var rdr = new LeImageReader(RawImage, offset);
     for (;;)
     {
         var cChar = rdr.ReadByte();
         if (cChar == 0)
             break;
         var abName = rdr.ReadBytes(cChar);
         var name = Encoding.ASCII.GetString(abName);
         int ordinal = rdr.ReadLeInt16();
         dict[ordinal] = name;
     }
     return dict;
 }
Esempio n. 17
0
        public bool ReadDirectorySector(LeImageReader rdr, List <ArchiveDirectoryEntry> entries)
        {
            byte nextDirTrack  = 0;
            byte nextDirSector = 0;

            for (int i = 0; i < 8; ++i)
            {
                if (i == 0)
                {
                    nextDirTrack  = rdr.ReadByte();
                    nextDirSector = rdr.ReadByte();
                }
                else
                {
                    rdr.Seek(2);
                }
                var fileType   = (FileType)rdr.ReadByte();
                var fileTrack  = rdr.ReadByte();
                var fileSector = rdr.ReadByte();
                var sName      = Encoding.ASCII.GetString(rdr.ReadBytes(16))
                                 .TrimEnd((char)0xA0);
                var relTrack  = rdr.ReadByte();
                var relSector = rdr.ReadByte();
                var rel       = rdr.ReadByte();
                rdr.Seek(6);
                var sectorSize = rdr.ReadLeInt16();
                if ((fileType & FileType.FileTypeMask) != FileType.DEL)
                {
                    entries.Add(new D64FileEntry(
                                    sName,
                                    RawImage,
                                    SectorOffset(fileTrack, fileSector),
                                    fileType));
                }
            }
            if (nextDirTrack != 0)
            {
                rdr.Offset = (uint)SectorOffset(nextDirTrack, nextDirSector);
                return(true);
            }
            else
            {
                return(false);
            }
        }
Esempio n. 18
0
 public TypeDefinition ReadTypeDefinition()
 {
     var linkage = rdr.ReadByte();
     var length = rdr.ReadLeUInt16();
     var rdrLeaves = new LeImageReader(rdr.ReadBytes(length));
     var leaves = new List<object>();
     while (rdrLeaves.IsValid)
     {
         leaves.Add(ReadLeaf(rdrLeaves));
     }
     return new TypeDefinition
     {
         linkage = linkage,
         Leaves = leaves.ToArray()
     };
 }
Esempio n. 19
0
 void LoadModuleTable(uint offset, int cModules)
 {
     var rdr = new LeImageReader(RawImage, offset);
     this.moduleNames = new List<string>();
     for (int i = 0; i < cModules; ++i)
     {
         uint nameOffset = rdr.ReadLeUInt16();
         if (nameOffset == 0)
             break;
         nameOffset += lfaNew + this.offImportedNamesTable;
         var rdrName = new LeImageReader(RawImage, nameOffset);
         byte length = rdrName.ReadByte();
         byte[] abModuleName = rdrName.ReadBytes(length);
         var moduleName = Encoding.ASCII.GetString(abModuleName);
         moduleNames.Add(moduleName);
     }
 }
Esempio n. 20
0
        public Dictionary <int, string> LoadEntryNames()
        {
            var rdr  = new LeImageReader(RawImage, this.lfaNew + this.offResidentNameTable);
            var dict = new Dictionary <int, string>();

            for (;;)
            {
                var cChar = rdr.ReadByte();
                if (cChar == 0)
                {
                    break;
                }
                var abName  = rdr.ReadBytes(cChar);
                var name    = Encoding.ASCII.GetString(abName);
                int ordinal = rdr.ReadLeInt16();
                dict[ordinal] = name;
            }
            return(dict);
        }
Esempio n. 21
0
        void LoadModuleTable()
        {
            var rdr = new LeImageReader(RawImage, lfaNew + hdr.import_module_table_off);

            moduleNames = new List <string>();

            if (hdr.import_module_table_off == 0 || hdr.import_module_entries == 0)
            {
                return;
            }

            for (int i = 0; i < hdr.import_module_entries; i++)
            {
                int len          = rdr.ReadByte();
                var abModuleName = rdr.ReadBytes(len);
                var moduleName   = Encoding.ASCII.GetString(abModuleName);
                moduleNames.Add(moduleName);
            }
        }
Esempio n. 22
0
            public sstPublics(SST sst, int module, byte[] data)
                : base(sst, module, data)
            {
                var syms = new List <PublicSymbol>();

                var rdr = new LeImageReader(data);

                while (rdr.IsValid)
                {
                    var off     = rdr.ReadLeUInt16();
                    var seg     = rdr.ReadLeUInt16();
                    var typeidx = rdr.ReadLeUInt16();
                    var namelen = rdr.ReadByte();
                    var name    = Encoding.ASCII.GetString(data, (int)rdr.Offset, namelen);
                    rdr.Offset += namelen;
                    syms.Add(new PublicSymbol(Address.SegPtr(seg, off), typeidx, name));
                }
                this.symbols = syms;
            }
Esempio n. 23
0
        public ArchiveDirectoryEntry[] LoadDirectory()
        {
            var rdr = new LeImageReader(this.RawImage);

            rdr.Offset += 8;  // Skip title
            var entries = new DFSEntry[31];

            for (int i = 0; i < 31; ++i)
            {
                var bytes  = rdr.ReadBytes(7);
                var fname  = new string(bytes.Select(b => (char)b).ToArray());
                var bDir   = rdr.ReadByte();
                var dir    = (char)bDir & 0x7F;
                var locked = (bDir & 0x80) != 0;
                var de     = new DFSEntry
                {
                    Name = fname
                };
                entries[i] = de;
            }

            // Sector 1
            Debug.Assert(rdr.Offset == 0x0100);
            rdr.Offset += 4; // Skip last 4 bytes of title
            rdr.ReadByte();  // # of writes
            int  cEntries = rdr.ReadByte() / 8;
            byte cSectHi  = rdr.ReadByte();
            byte cSectLo  = rdr.ReadByte();

            for (int i = 0; i < 31; ++i)
            {
                var uAddrLoad = rdr.ReadUInt16();
                var uAddrExec = rdr.ReadUInt16();
                var cbLength  = rdr.ReadUInt16();
                var sectHi    = rdr.ReadByte();
                var sectLo    = rdr.ReadByte();
                var de        = entries[i];
                de.LoadAddress = Address.Ptr16(uAddrLoad);
                de.ExecAddress = Address.Ptr16(uAddrLoad);
                de.Length      = cbLength;
            }
            return(entries.Take(cEntries).ToArray());
        }
Esempio n. 24
0
            public sstPublics(SST sst, object module, byte[] data)
                : base(sst, module, data)
            {
                //using (var fo = open("pub", "wb")) {
                //    fo.write(data);
                //}
                var syms = new List <PublicSymbol>();

                var rdr = new LeImageReader(data);

                while (rdr.IsValid)
                {
                    //var _tup_1 = @struct.unpack_from("<HHHB", data, dofs);
                    var ofs     = rdr.ReadLeUInt16();
                    var seg     = rdr.ReadLeUInt16();
                    var typeidx = rdr.ReadLeUInt16();
                    var namelen = rdr.ReadByte();
                    var name    = Encoding.ASCII.GetString(data, (int)rdr.Offset, namelen);
                    syms.Add(new PublicSymbol(ofs, seg, typeidx, name));
                }
                this.symbols = syms;
            }
Esempio n. 25
0
        /*  DCCLIBS.DAT is a data file sorted on function name containing names and
            return types of functions found in include files, and the names and types
            of arguements. Only functions in this list will be considered library
            functions; others (like LXMUL@) are helper files, and need to be analysed
            by dcc, rather than considered as known functions. When a prototype is
            found (in searchPList()), the parameter info is written to the proc struct.
        */
        void readProtoFile(IServiceProvider services)
        {
            var diagSvc = services.RequireService<IDiagnosticsService>();
            var cfgSvc = services.RequireService<IConfigurationService>();
            var szProFName = cfgSvc.GetInstallationRelativePath("msdos", DCCLIBS); /* Full name of dclibs.lst */
            var fsSvc = services.RequireService<IFileSystemService>();
            if (fsSvc.FileExists(szProFName))
            {
                diagSvc.Warn(string.Format("Cannot open library prototype data file {0}.", szProFName));
                return;
            }
            var bytes = fsSvc.ReadAllBytes(szProFName);
            var fProto = new LeImageReader(bytes);
            int i;

            uint fileSig = fProto.ReadLeUInt32();
            if (fileSig != 0x70636364)      // "dccp"
            {
                diagSvc.Warn(string.Format("{0} is not a dcc prototype file.", szProFName));
                return;
            }

            ushort sectionID = fProto.ReadLeUInt16();
            if (sectionID != 0x4E46)        // "FN"
            {
                Debug.Print("FN (Function) subsection expected in {0}", szProFName);
                diagSvc.Warn(string.Format("{0} is not a dcc prototype file.", szProFName));
                return;
            }
            numFunc = fProto.ReadLeUInt16();    /* Num of entries to allocate */

            /* Allocate exactly correct # entries */
            pFunc = new PH_FUNC_STRUCT[numFunc];

            for (i = 0; i < numFunc; i++)
            {
                var symbuf = fProto.ReadBytes(SYMLEN);
                if (symbuf.Length != SYMLEN)
                    break;
                pFunc[i].typ = (hlType)fProto.ReadLeUInt16();
                pFunc[i].numArg = fProto.ReadLeUInt16();
                pFunc[i].firstArg = fProto.ReadLeUInt16();
                int c = fProto.ReadByte();
                pFunc[i].bVararg = (c != 0); //fread(&pFunc[i].bVararg, 1, 1, fProto);
            }

            sectionID = fProto.ReadLeUInt16();
            if (sectionID != 0x4D50)    // "PM"
            {
                Debug.Print("PM (Parameter) subsection expected in {0}", szProFName);
                return;
            }

            numArg = fProto.ReadLeUInt16();     /* Num of entries to allocate */

            /* Allocate exactly correct # entries */
            pArg = new hlType[numArg];

            for (i = 0; i < numArg; i++)
            {
                //      fread(&pArg[i], 1, SYMLEN, fProto);     /* No names to read as yet */
                pArg[i] = (hlType)fProto.ReadLeUInt16();
            }
        }
Esempio n. 26
0
        private static string ReadString(LeImageReader rdr)
        {
            var len = rdr.ReadByte();

            return(Encoding.ASCII.GetString(rdr.ReadBytes(len)));
        }
Esempio n. 27
0
        // Apply relocations to a segment.
        bool ApplyRelocations(ImageReader rdr, int cRelocations, NeSegment seg)
        {
            string            module  = "";
            Address           address = null;
            NeRelocationEntry rep     = null;

            for (int i = 0; i < cRelocations; i++)
            {
                rep = new NeRelocationEntry
                {
                    address_type    = rdr.ReadByte(),
                    relocation_type = rdr.ReadByte(),
                    offset          = rdr.ReadLeUInt16(),
                    target1         = rdr.ReadLeUInt16(),
                    target2         = rdr.ReadLeUInt16(),
                };

                // Get the target address corresponding to this entry.

                // If additive, there is no target chain list. Instead, add source
                //  and target.
                bool additive = (rep.relocation_type & NE_RELFLAG_ADDITIVE) != 0;
                Tuple <Address, ImportReference> impRef;
                uint lp;
                switch (rep.relocation_type & 3)
                {
                case NE_RELTYPE_ORDINAL:
                    module = moduleNames[rep.target1 - 1];
                    // Synthesize an import
                    lp = ((uint)rep.target1 << 16) | rep.target2;
                    if (importStubs.TryGetValue(lp, out impRef))
                    {
                        address = impRef.Item1;
                    }
                    else
                    {
                        address = addrImportStubs;
                        importStubs.Add(lp, new Tuple <Address, ImportReference>(
                                            address,
                                            new OrdinalImportReference(address, module, rep.target2)));
                        addrImportStubs += 8;
                    }
                    break;

                case NE_RELTYPE_NAME:
                    module = moduleNames[rep.target1 - 1];
                    uint offName      = lfaNew + this.offImportedNamesTable + rep.target2;
                    var  nameRdr      = new LeImageReader(RawImage, offName);
                    byte fnNameLength = nameRdr.ReadByte();
                    var  abFnName     = nameRdr.ReadBytes(fnNameLength);
                    lp = ((uint)rep.target1 << 16) | rep.target2;
                    if (importStubs.TryGetValue(lp, out impRef))
                    {
                        address = impRef.Item1;
                    }
                    else
                    {
                        address = addrImportStubs;
                        string fnName = Encoding.ASCII.GetString(abFnName);
                        importStubs.Add(lp, new Tuple <Address, ImportReference>(
                                            address,
                                            new NamedImportReference(address, module, fnName)));
                    }
                    break;

                case NE_RELTYPE_INTERNAL:
                    if ((rep.target1 & 0xff) == 0xff)
                    {
                        throw new NotImplementedException();
                    }
                    else
                    {
                        address = segments[rep.target1 - 1].Address + rep.target2;
                    }
                    Debug.Print("{0}: {1:X4}:{2:X4} {3}",
                                i + 1,
                                address.Selector.Value,
                                address.Selector.Value,
                                "");
                    break;

                case NE_RELTYPE_OSFIXUP:
                    /* Relocation type 7:
                     *
                     *    These appear to be used as fixups for the Windows
                     * floating point emulator.  Let's just ignore them and
                     * try to use the hardware floating point.  Linux should
                     * successfully emulate the coprocessor if it doesn't
                     * exist.
                     */
                    /*
                     * TRACE("%d: TYPE %d, OFFSET %04x, TARGET %04x %04x %s\n",
                     *   i + 1, rep->relocation_type, rep->offset,
                     *   rep->target1, rep->target2,
                     *   NE_GetRelocAddrName( rep->address_type, additive ) );
                     */
                    continue;
                }
                ushort offset = rep.offset;

                // Apparently, high bit of address_type is sometimes set;
                // we ignore it for now.
                if (rep.address_type > NE_RADDR_OFFSET32)
                {
                    diags.Error(
                        string.Format(
                            "Module {0}: unknown relocation address type {1:X2}. Please report",
                            module, rep.address_type));
                    return(false);
                }

                if (additive)
                {
                    var sp = seg.Address + offset;
                    Debug.Print("    {0:X4}:{0:X4}", offset, offset);
                    byte   b;
                    ushort w;
                    switch (rep.address_type & 0x7f)
                    {
                    case NE_RADDR_LOWBYTE:
                        b = image.ReadByte(sp);
                        image.WriteByte(sp, (byte)(b + address.Offset));
                        break;

                    case NE_RADDR_OFFSET16:
                        w = image.ReadLeUInt16(sp);
                        image.WriteLeUInt16(sp, (ushort)(w + address.Offset));
                        break;

                    case NE_RADDR_POINTER32:
                        w = image.ReadLeUInt16(sp);
                        image.WriteLeUInt16(sp, (ushort)(w + address.Offset));
                        image.WriteLeUInt16(sp + 2, address.Selector.Value);
                        break;

                    case NE_RADDR_SELECTOR:
                        // Borland creates additive records with offset zero. Strange, but OK.
                        w = image.ReadLeUInt16(sp);
                        if (w != 0)
                        {
                            diags.Error(string.Format("Additive selector to {0:X4}. Please report.", w));
                        }
                        else
                        {
                            image.WriteLeUInt16(sp, address.Selector.Value);
                        }
                        break;

                    default:
                        goto unknown;
                    }
                }
                else
                {
                    // Non-additive fixup.
                    do
                    {
                        var    sp          = seg.Address + offset;
                        ushort next_offset = image.ReadLeUInt16(sp);
                        Debug.Print("    {0:X4}:{0:X4}", offset, next_offset);
                        switch (rep.address_type & 0x7f)
                        {
                        case NE_RADDR_LOWBYTE:
                            image.WriteByte(sp, (byte)address.Offset);
                            break;

                        case NE_RADDR_OFFSET16:
                            image.WriteLeUInt16(sp, (ushort)address.Offset);
                            break;

                        case NE_RADDR_POINTER32:
                            image.WriteLeUInt16(sp, (ushort)address.Offset);
                            image.WriteLeUInt16(sp + 2, address.Selector.Value);
                            break;

                        case NE_RADDR_SELECTOR:
                            image.WriteLeUInt16(sp, address.Selector.Value);
                            break;

                        default:
                            goto unknown;
                        }
                        if (next_offset == offset)
                        {
                            break;                         // avoid infinite loop
                        }
                        if (next_offset >= seg.Alloc)
                        {
                            break;
                        }
                        offset = next_offset;
                    } while (offset != 0xffff);
                }
            }
            return(true);

unknown:
            var svc = Services.RequireService <IDiagnosticsService>();

            svc.Warn(string.Format("{0}: unknown ADDR TYPE {1},  " +
                                   "TYPE {2},  OFFSET {3:X4},  TARGET {4:X4} {5:X4}",
                                   seg.Address.Selector, rep.address_type, rep.relocation_type,
                                   rep.offset, rep.target1, rep.target2));
            return(false);
        }
Esempio n. 28
0
        public List <ImageSymbol?> LoadEntryPoints(
            uint offEntryTable,
            NeSegment [] segments,
            Dictionary <int, string> names,
            IProcessorArchitecture arch)
        {
            trace.Inform("== Loading entry points from offset {0:X}", offEntryTable);
            var rdr = new LeImageReader(RawImage, offEntryTable);

            var entries           = new List <ImageSymbol?>();
            int bundleOrdinal     = 1;
            int nextbundleOrdinal = 1;

            for (; ;)
            {
                var cBundleEntries = rdr.ReadByte();
                if (cBundleEntries == 0)
                {
                    break;
                }
                nextbundleOrdinal = bundleOrdinal + cBundleEntries;
                var segNum = rdr.ReadByte();
                if (segNum != 0)
                {
                    // If segNum had been 0, it would have
                    // meant that all we want to do is allocate
                    // (skip) some ordinal numbers. Since it wasn't 0,
                    // we proceed to generate entry points.
                    for (int i = 0; i < cBundleEntries; ++i)
                    {
                        byte flags = rdr.ReadByte();
                        (byte iSeg, ushort offset)entry;
                        if (segNum == 0xFF)
                        {
                            entry = ReadMovableSegmentEntry(rdr);
                        }
                        else
                        {
                            entry = ReadFixedSegmentEntry(rdr, segNum);
                        }
                        var seg  = segments[entry.iSeg - 1];
                        var addr = seg.Address !+entry.offset;

                        if (!names.TryGetValue(bundleOrdinal + i, out string?name))
                        {
                            name = null;
                        }
                        ImageSymbol ep;
                        if (seg.IsData)
                        {
                            ep = ImageSymbol.DataObject(arch, addr, name, new UnknownType());
                        }
                        else
                        {
                            ep                = ImageSymbol.Procedure(arch, addr, name);
                            ep.Ordinal        = bundleOrdinal + i;
                            ep.Type           = SymbolType.Procedure;
                            ep.ProcessorState = arch.CreateProcessorState();
                        }
                        entries.Add(ep);
                        imageSymbols[ep.Address] = ep;
                        trace.Verbose("   {0:X2} {1} {2} - {3}", segNum, ep.Address, ep.Name !, ep.Ordinal.HasValue ? ep.Ordinal.Value.ToString() : "");
                    }
                }
                else
                {
                    // We have unused entries, they have to occupy a space in the resulting entries table.
                    entries.AddRange(Enumerable.Range(0, cBundleEntries).Select(x => (ImageSymbol?)null));
                }
                bundleOrdinal = nextbundleOrdinal;
            }
            return(entries);
        }