예제 #1
0
        /// <summary>
        /// Load a Basic PRG.
        /// </summary>
        /// <param name="imageBytes"></param>
        /// <returns></returns>
        private Program LoadPrg(byte[] imageBytes)
        {
            var    stm = new MemoryStream();
            ushort preferredAddress = LoadedImage.ReadLeUInt16(imageBytes, 0);
            ushort alignedAddress   = (ushort)(preferredAddress & ~0xF);
            int    pad = preferredAddress - alignedAddress;

            while (pad-- > 0)
            {
                stm.WriteByte(0);
            }
            stm.Write(imageBytes, 2, imageBytes.Length - 2);
            var loadedBytes = stm.ToArray();
            var image       = new LoadedImage(
                Address.Ptr16(alignedAddress),
                loadedBytes);
            var rdr  = new C64BasicReader(image, 0x0801);
            var prog = rdr.ToSortedList(line => (ushort)line.Address.ToLinear(), line => line);
            var arch = new C64Basic(prog);

            image = new LoadedImage(
                Address.Ptr16(prog.Keys[0]),
                new byte[0xFFFF]);
            var program = new Program(
                image,
                image.CreateImageMap(),
                arch,
                new C64Platform(Services, null));

            program.EntryPoints.Add(new EntryPoint(image.BaseAddress, arch.CreateProcessorState()));
            return(program);
        }
예제 #2
0
        public PkLiteUnpacker(IServiceProvider services, string filename, byte [] rawImg) : base(services, filename, rawImg)
        {
            var exe = new ExeImageLoader(services, filename, rawImg);

            arch     = new IntelArchitecture(ProcessorMode.Real);
            platform = services.RequireService <IConfigurationService>()
                       .GetEnvironment("ms-dos")
                       .Load(services, arch);

            uint pkLiteHdrOffset = (uint)(exe.e_cparHeader * 0x10);

            if (RawImage[pkLiteHdrOffset] != 0xB8)
            {
                throw new ApplicationException(string.Format("Expected MOV AX,XXXX at offset 0x{0:X4}.", pkLiteHdrOffset));
            }
            uint cparUncompressed = LoadedImage.ReadLeUInt16(RawImage, pkLiteHdrOffset + 1);

            abU = new byte[cparUncompressed * 0x10U];

            if (RawImage[pkLiteHdrOffset + 0x04C] != 0x83)
            {
                throw new ApplicationException(string.Format("Expected ADD BX,+XX at offset 0x{0:X4}.", pkLiteHdrOffset + 0x04C));
            }
            uint offCompressedData = pkLiteHdrOffset + RawImage[pkLiteHdrOffset + 0x04E] * 0x10u - PspSize;

            bitStm = new BitStream(RawImage, (int)offCompressedData);
        }
예제 #3
0
        // Unpacks the relocation entries in a LzExe 0.91 binary

        private ImageMap Relocate91(byte [] abUncompressed, ushort segReloc, LoadedImage pgmImgNew, RelocationDictionary relocations)
        {
            const int CompressedRelocationTableAddress = 0x0158;
            int       ifile = lzHdrOffset + CompressedRelocationTableAddress;

            int rel_off = 0;

            for (;;)
            {
                ushort span = abUncompressed[ifile++];
                if (span == 0)
                {
                    span  = abUncompressed[ifile++];
                    span |= (ushort)(abUncompressed[ifile++] << 8);
                    if (span == 0)
                    {
                        rel_off += 0x0FFF0;
                        continue;
                    }
                    else if (span == 1)
                    {
                        break;
                    }
                }

                rel_off += span;
                ushort seg = (ushort)(pgmImgNew.ReadLeUInt16((uint)rel_off) + segReloc);
                pgmImgNew.WriteLeUInt16((uint)rel_off, seg);
                relocations.AddSegmentReference((uint)rel_off, seg);
                imageMap.AddSegment(Address.SegPtr(seg, 0), seg.ToString("X4"), AccessMode.ReadWriteExecute);
            }
            return(imageMap);
        }
예제 #4
0
        public override RelocationResults Relocate(Address addrLoad)
        {
            ImageMap    imageMap    = imgLoadedMap;
            ImageReader rdr         = new LeImageReader(exe.RawImage, (uint)exe.e_lfaRelocations);
            var         relocations = new RelocationDictionary();
            int         i           = exe.e_cRelocations;

            while (i != 0)
            {
                uint   offset    = rdr.ReadLeUInt16();
                ushort segOffset = rdr.ReadLeUInt16();
                offset += segOffset * 0x0010u;

                ushort seg = (ushort)(imgLoaded.ReadLeUInt16(offset) + addrLoad.Selector);
                imgLoaded.WriteLeUInt16(offset, seg);
                relocations.AddSegmentReference(offset, seg);

                imageMap.AddSegment(Address.SegPtr(seg, 0), seg.ToString("X4"), AccessMode.ReadWriteExecute);
                --i;
            }

            // Found the start address.

            Address addrStart = Address.SegPtr((ushort)(exe.e_cs + addrLoad.Selector), exe.e_ip);

            imageMap.AddSegment(Address.SegPtr(addrStart.Selector, 0), addrStart.Selector.ToString("X4"), AccessMode.ReadWriteExecute);
            return(new RelocationResults(
                       new List <EntryPoint> {
                new EntryPoint(addrStart, arch.CreateProcessorState())
            },
                       relocations));
        }
예제 #5
0
        public override RelocationResults Relocate(Program program, Address addrLoad)
        {
            var    relocations = new RelocationDictionary();
            ushort segCode     = (ushort)(addrLoad.Selector.Value + (PspSize >> 4));

            for (;;)
            {
                int relocs = (ushort)bitStm.GetByte();
                if (relocs == 0)
                {
                    break;
                }

                uint relocBase = PspSize + bitStm.GetWord() * 0x10u;
                do
                {
                    ushort relocOff = bitStm.GetWord();
                    ushort seg      = imgU.ReadLeUInt16(relocBase + relocOff);
                    seg = (ushort)(seg + segCode);

                    imgU.WriteLeUInt16(relocBase + relocOff, seg);
                    relocations.AddSegmentReference(relocBase + relocOff, seg);
                    imageMap.AddSegment(Address.SegPtr(seg, 0), seg.ToString("X4"), AccessMode.ReadWriteExecute, 0);
                } while (--relocs != 0);
            }

            ushort pklSs = (ushort)(bitStm.GetWord() + segCode);
            ushort pklSp = (ushort)bitStm.GetWord();

            pklCs = (ushort)(bitStm.GetWord() + segCode);
            pklIp = bitStm.GetWord();

            var state = arch.CreateProcessorState();

            state.SetRegister(Registers.ds, Constant.Word16(addrLoad.Selector.Value));
            state.SetRegister(Registers.es, Constant.Word16(addrLoad.Selector.Value));
            state.SetRegister(Registers.cs, Constant.Word16(pklCs));
            state.SetRegister(Registers.ax, Constant.Word16(0));
            state.SetRegister(Registers.bx, Constant.Word16(0));
            state.SetRegister(Registers.cx, Constant.Word16(0));
            state.SetRegister(Registers.dx, Constant.Word16(0));
            state.SetRegister(Registers.bp, Constant.Word16(0));
            state.SetRegister(Registers.sp, Constant.Word16(pklSp));
            state.SetRegister(Registers.si, Constant.Word16(0));
            state.SetRegister(Registers.di, Constant.Word16(0));

            return(new RelocationResults(
                       new List <EntryPoint> {
                new EntryPoint(Address.SegPtr(pklCs, pklIp), state)
            },
                       relocations,
                       new List <Address>()));
        }
예제 #6
0
        public override Program Load(Address addr)
        {
            byte[] abC = RawImage;
            byte[] abU = new byte[cpUncompressed * 0x10U + ExeImageLoader.CbPsp];
            Array.Copy(abC, exeHdrSize, abU, ExeImageLoader.CbPsp, abC.Length - exeHdrSize);
            imgU = new LoadedImage(addr, abU);

            uint SI = hdrOffset - 1;

            while (abC[SI] == 0xFF)
            {
                --SI;
            }

            int  DI = abU.Length - 1;
            byte op;

            do
            {
                op = abC[SI];
                int cx = LoadedImage.ReadLeUInt16(abC, SI - 2);
                SI -= 3;
                if ((op & 0xFE) == 0xB0)
                {
                    byte b = abC[SI--];
                    while (cx != 0)
                    {
                        abU[DI--] = b;
                        --cx;
                    }
                }
                else
                {
                    if ((op & 0xFE) != 0xB2)
                    {
                        throw new ApplicationException("Packed file is corrupt.");
                    }
                    while (cx != 0)
                    {
                        abU[DI--] = abC[SI--];
                        --cx;
                    }
                }
            } while ((op & 1) == 0);
            imageMap = imgU.CreateImageMap();
            return(new Program(imgU, imageMap, new X86ArchitectureReal(), platform));
        }
예제 #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);
        }