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); }
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)); } }
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); } } } }