private void LoadPEImage() { long fileDataSize = rdr.Bytes.Length - xexData.header.exe_offset; BeImageReader memRdr = new BeImageReader(xexData.memoryData); DOSHeader dosHeader = new StructureReader <DOSHeader>(memRdr).Read(); 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 = new StructureReader <COFFHeader>(memRdr).Read(); 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 = new StructureReader <PEOptHeader>(memRdr).Read(); 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 = new StructureReader <COFFSection>(memRdr).Read(); 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); } } } }