Example #1
0
        public override Program LoadProgram(Address?addrLoad)
        {
            var rdr = new BeImageReader(RawImage);

            if (!TryLoadHeader(rdr, out var hdr))
            {
                throw new BadImageFormatException();
            }

            addrLoad ??= PreferredBaseAddress;
            var cfgSvc   = Services.RequireService <IConfigurationService>();
            var arch     = cfgSvc.GetArchitecture("m68k") !;
            var env      = cfgSvc.GetEnvironment("atariTOS");
            var platform = env.Load(Services, arch);

            var bytes = new byte[hdr.TextSize + hdr.DataSize + hdr.BssSize];
            var mem   = arch.CreateMemoryArea(addrLoad, bytes);
            int cRead = rdr.ReadBytes(bytes, 0, hdr.TextSize + hdr.DataSize);

            if (cRead != hdr.TextSize + hdr.DataSize)
            {
                throw new BadImageFormatException();
            }

            var text = new ImageSegment(".text", addrLoad, mem, AccessMode.ReadExecute)
            {
                Size = hdr.TextSize
            };
            var data = new ImageSegment(".data", addrLoad + hdr.TextSize, mem, AccessMode.ReadWrite)
            {
                Size = hdr.DataSize
            };
            var bss = new ImageSegment(".bss", addrLoad + hdr.TextSize + hdr.DataSize, mem, AccessMode.ReadWrite)
            {
                Size = hdr.BssSize
            };

            //$TODO: Implement symbols. For now just skip over them.
            rdr.Offset += hdr.SymbolsSize;

            PerformRelocations(mem, rdr);

            var map = new SegmentMap(
                addrLoad,
                text, data, bss);
            var program = new Program(map, arch, platform);

            program.EntryPoints[addrLoad] = ImageSymbol.Location(program.Architecture, addrLoad);
            return(program);
        }
Example #2
0
        public string ReadSizedString(int num_longs)
        {
            int size = (num_longs & 0xFFFFFF) * 4;
            var data = f.ReadBytes(size);

            if (data.Length < size)
            {
                return(null);
            }
            int endpos = Array.IndexOf(data, (byte)0);

            if (endpos < 0)
            {
                endpos = data.Length;
            }
            if (endpos == 0)
            {
                return("");
            }
            else
            {
                return(this.textEncoding.GetString(data, 0, endpos));
            }
        }
Example #3
0
        private void LoadPEImage()
        {
            long fileDataSize = rdr.Bytes.Length - xexData.header.header_size;

            BeImageReader memRdr    = new BeImageReader(xexData.memoryData);
            DOSHeader     dosHeader = memRdr.ReadStruct <DOSHeader>();

            dosHeader.Validate();

            memRdr.Offset = dosHeader.e_lfanew;

            UInt32 peSignature = memRdr.ReadUInt32();

            if (peSignature != 0x50450000)
            {
                throw new BadImageFormatException("PE: Invalid or Missing PE Signature");
            }

            COFFHeader coffHeader = memRdr.ReadStruct <COFFHeader>();

            if (coffHeader.Machine != 0x1F2)
            {
                throw new BadImageFormatException($"PE: Machine type does not match Xbox360 (found 0x{coffHeader.Machine:X})");
            }

            if ((coffHeader.Characteristics & 0x0100) == 0)
            {
                throw new BadImageFormatException("PE: Only 32-bit images are supported");
            }

            if (coffHeader.SizeOfOptionalHeader != 224)
            {
                throw new BadImageFormatException($"PE: Invalid size of optional header (got {coffHeader.SizeOfOptionalHeader}");
            }

            PEOptHeader optHeader = memRdr.ReadStruct <PEOptHeader>();

            if (optHeader.signature != 0x10b)
            {
                throw new BadImageFormatException($"PE: Invalid signature of optional header (got 0x{optHeader.signature})");
            }

            if (optHeader.Subsystem != IMAGE_SUBSYSTEM_XBOX)
            {
                throw new BadImageFormatException($"PE: Invalid subsystem (got {optHeader.Subsystem})");
            }

            xexData.peHeader = optHeader;

            uint extendedMemorySize = 0;
            uint numSections        = coffHeader.NumberOfSections;

            List <PESection> peSections = new List <PESection>();

            for (uint i = 0; i < numSections; i++)
            {
                COFFSection section = memRdr.ReadStruct <COFFSection>();

                string sectionName = Encoding.ASCII.GetString(section.Name).Trim('\0');

                uint lastMemoryAddress = section.VirtualAddress + section.VirtualSize;
                if (lastMemoryAddress > extendedMemorySize)
                {
                    extendedMemorySize = lastMemoryAddress;
                }

                if (section.SizeOfRawData == 0)
                {
                    decompilerEventListener.Info(new NullCodeLocation(""),
                                                 $"Skipping empty section {sectionName}"
                                                 );
                    continue;
                }

                byte[] sectionData = memRdr.ReadAt <byte[]>(section.PointerToRawData, rdr => rdr.ReadBytes(section.SizeOfRawData));

                AccessMode acc = AccessMode.Read;
                if (section.Flags.HasFlag(PESectionFlags.IMAGE_SCN_MEM_WRITE))
                {
                    acc |= AccessMode.Write;
                }
                if (section.Flags.HasFlag(PESectionFlags.IMAGE_SCN_MEM_EXECUTE))
                {
                    acc |= AccessMode.Execute;
                }

                PESection managedSection = new PESection(section);
                peSections.Add(managedSection);

                ImageSegment seg = new ImageSegment(sectionName, new MemoryArea(
                                                        new Address32(managedSection.PhysicalOffset + xexData.exe_address), sectionData
                                                        ), acc);
                segments.Add(seg);
            }

            if (extendedMemorySize > xexData.memorySize)
            {
                decompilerEventListener.Info(new NullCodeLocation(""),
                                             $"PE: Image sections extend beyond virtual memory range loaded from file ({extendedMemorySize} > {xexData.memorySize}). Extending by {extendedMemorySize - xexData.memorySize} bytes."
                                             );

                UInt32 oldMemorySize = xexData.memorySize;

                byte[] newMemoryData = new byte[extendedMemorySize];
                Array.Copy(xexData.memoryData, newMemoryData, xexData.memorySize);
                xexData.memorySize = extendedMemorySize;
                xexData.memoryData = newMemoryData;

                for (int i = 0; i < peSections.Count; i++)
                {
                    PESection section = peSections[i];

                    if (section.PhysicalSize == 0)
                    {
                        continue;
                    }

                    if (section.PhysicalSize + section.PhysicalOffset > fileDataSize)
                    {
                        decompilerEventListener.Warn(new NullCodeLocation(""),
                                                     $"PE: Section '{section.Name}' lies outside any phyisical data we have {section.PhysicalOffset} (size {section.PhysicalSize})"
                                                     );
                        continue;
                    }

                    if (section.VirtualOffset >= oldMemorySize)
                    {
                        uint sizeToCopy = section.PhysicalSize;
                        if (section.VirtualSize < sizeToCopy)
                        {
                            sizeToCopy = section.VirtualSize;
                        }

                        Array.Copy(
                            xexData.memoryData, section.PhysicalOffset,
                            newMemoryData, section.VirtualOffset,
                            sizeToCopy);
                    }
                }
            }
        }