Example #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;
        }
Example #2
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);
		}
Example #3
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();
            }
Example #4
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;
     }
 }
Example #5
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;
 }
Example #6
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);
     }
 }
Example #7
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;
        }
Example #8
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;
 }
Example #9
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;
 }
Example #10
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;
        }
Example #11
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();
            }
        }
Example #12
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; 
        }