public override void ApplyRelocation(Address baseOfImage, uint page, ImageReader rdr, RelocationDictionary relocations) { ushort fixup = rdr.ReadLeUInt16(); Address offset = baseOfImage + page + (fixup & 0x0FFFu); var imgR = program.CreateImageReader(offset); var imgW = program.CreateImageWriter(offset); switch (fixup >> 12) { case RelocationAbsolute: // Used for padding to 4-byte boundary, ignore. break; case RelocationHighLow: { uint n = (uint) (imgR.ReadUInt32() + (baseOfImage - program.ImageMap.BaseAddress)); imgW.WriteUInt32(n); relocations.AddPointerReference(offset.ToLinear() - imgW.MemoryArea.BaseAddress.ToLinear(), n); break; } case 0xA: break; default: dcSvc.Warn( dcSvc.CreateAddressNavigator(program, offset), string.Format( "Unsupported i386 PE fixup type: {0:X}", fixup >> 12)); break; } }
protected Address ReadSegmentedCodeAddress(int byteSize, ImageReader rdr, ProcessorState state) { if (byteSize == PrimitiveType.Word16.Size) { return Address.SegPtr(state.GetRegister(Registers.cs).ToUInt16(), rdr.ReadLeUInt16()); } else { ushort off = rdr.ReadLeUInt16(); ushort seg = rdr.ReadLeUInt16(); return Address.SegPtr(seg, off); } }
// 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; }
public void ApplyRelocation(uint baseOfImage, uint page, ImageReader rdr, RelocationDictionary relocations) { ushort fixup = rdr.ReadLeUInt16(); uint offset = page + (fixup & 0x0FFFu); switch (fixup >> 12) { case RelocationAbsolute: // Used for padding to 4-byte boundary, ignore. break; case RelocationHighLow: { uint n = (uint) (imgLoaded.ReadLeUInt32(offset) + (baseOfImage - preferredBaseOfImage.ToLinear())); imgLoaded.WriteLeUInt32(offset, n); relocations.AddPointerReference(offset, n); break; } case 0xA: break; default: var dcSvc = Services.RequireService<DecompilerEventListener>(); dcSvc.Warn( dcSvc.CreateAddressNavigator(program, Address.Ptr32(offset)), string.Format( "Unsupported PE fixup type: {0:X}", fixup >> 12)); break; } #if I386 // // I386 relocation types. // const static final ushort IMAGE_REL_I386_ABSOLUTE = 0x0000; // Reference is absolute, no relocation is necessary const static final ushort IMAGE_REL_I386_DIR16 = 0x0001; // Direct 16-bit reference to the symbols virtual address const static final ushort IMAGE_REL_I386_REL16 = 0x0002; // PC-relative 16-bit reference to the symbols virtual address const static final ushort IMAGE_REL_I386_DIR32 = 0x0006; // Direct 32-bit reference to the symbols virtual address const static final ushort IMAGE_REL_I386_DIR32NB = 0x0007; // Direct 32-bit reference to the symbols virtual address, base not included const static final ushort IMAGE_REL_I386_SEG12 = 0x0009; // Direct 16-bit reference to the segment-selector bits of a 32-bit virtual address const static final ushort IMAGE_REL_I386_SECTION = 0x000A; const static final ushort IMAGE_REL_I386_SECREL = 0x000B; const static final ushort IMAGE_REL_I386_TOKEN = 0x000C; // clr token const static final ushort IMAGE_REL_I386_SECREL7 = 0x000D; // 7 bit offset from base of section containing target const static final ushort IMAGE_REL_I386_REL32 = 0x0014; // PC-relative 32-bit reference to the symbols virtual address
public void ReadOptionalHeader(ImageReader rdr, short expectedMagic) { if (optionalHeaderSize <= 0) throw new BadImageFormatException("Optional header size should be larger than 0 in a PE executable image file."); short magic = rdr.ReadLeInt16(); if (magic != expectedMagic) throw new BadImageFormatException("Not a valid PE Header."); rdr.ReadByte(); // Linker major version rdr.ReadByte(); // Linker minor version rdr.ReadLeUInt32(); // code size (== .text section size) rdr.ReadLeUInt32(); // size of initialized data rdr.ReadLeUInt32(); // size of uninitialized data rvaStartAddress = rdr.ReadLeUInt32(); uint rvaBaseOfCode = rdr.ReadLeUInt32(); preferredBaseOfImage = innerLoader.ReadPreferredImageBase(rdr); rdr.ReadLeUInt32(); // section alignment rdr.ReadLeUInt32(); // file alignment rdr.ReadLeUInt16(); // OS major version rdr.ReadLeUInt16(); // OS minor version rdr.ReadLeUInt16(); // Image major version rdr.ReadLeUInt16(); // Image minor version rdr.ReadLeUInt16(); // Subsystem major version rdr.ReadLeUInt16(); // Subsystem minor version rdr.ReadLeUInt32(); // reserved uint sizeOfImage = rdr.ReadLeUInt32(); uint sizeOfHeaders = rdr.ReadLeUInt32(); uint checksum = rdr.ReadLeUInt32(); ushort subsystem = rdr.ReadLeUInt16(); ushort dllFlags = rdr.ReadLeUInt16(); var stackReserve = rdr.Read(arch.WordWidth); var stackCommit = rdr.Read(arch.WordWidth); var heapReserve = rdr.Read(arch.WordWidth); var heapCommit = rdr.Read(arch.WordWidth); rdr.ReadLeUInt32(); // loader flags uint dictionaryCount = rdr.ReadLeUInt32(); if (dictionaryCount == 0) return; rvaExportTable = rdr.ReadLeUInt32(); sizeExportTable = rdr.ReadLeUInt32(); if (--dictionaryCount == 0) return; rvaImportTable = rdr.ReadLeUInt32(); uint importTableSize = rdr.ReadLeUInt32(); if (--dictionaryCount == 0) return; rvaResources = rdr.ReadLeUInt32(); // resource address rdr.ReadLeUInt32(); // resource size if (--dictionaryCount == 0) return; rvaExceptionTable = rdr.ReadLeUInt32(); // exception address sizeExceptionTable = rdr.ReadLeUInt32(); // exception size if (--dictionaryCount == 0) return; rdr.ReadLeUInt32(); // certificate address rdr.ReadLeUInt32(); // certificate size if (--dictionaryCount == 0) return; uint rvaBaseRelocAddress = rdr.ReadLeUInt32(); uint baseRelocSize = rdr.ReadLeUInt32(); if (--dictionaryCount == 0) return; uint rvaDebug = rdr.ReadLeUInt32(); uint cbDebug = rdr.ReadLeUInt32(); if (--dictionaryCount == 0) return; uint rvaArchitecture = rdr.ReadLeUInt32(); uint cbArchitecture = rdr.ReadLeUInt32(); if (--dictionaryCount == 0) return; uint rvaGlobalPointer = rdr.ReadLeUInt32(); uint cbGlobalPointer = rdr.ReadLeUInt32(); if (--dictionaryCount == 0) return; uint rvaTls = rdr.ReadLeUInt32(); uint cbTls = rdr.ReadLeUInt32(); if (--dictionaryCount == 0) return; uint rvaLoadConfig = rdr.ReadLeUInt32(); uint cbLoadConfig = rdr.ReadLeUInt32(); if (--dictionaryCount == 0) return; uint rvaBoundImport = rdr.ReadLeUInt32(); uint cbBoundImport = rdr.ReadLeUInt32(); if (--dictionaryCount == 0) return; uint rvaIat = rdr.ReadLeUInt32(); uint cbIat = rdr.ReadLeUInt32(); if (--dictionaryCount == 0) return; this.rvaDelayImportDescriptor = rdr.ReadLeUInt32(); uint cbDelayImportDescriptor = rdr.ReadLeUInt32(); }
public short ReadCoffHeader(ImageReader rdr) { this.machine = rdr.ReadLeUInt16(); short expectedMagic = GetExpectedMagic(machine); arch = CreateArchitecture(machine); platform = CreatePlatform(machine, Services, arch); innerLoader = CreateInnerLoader(machine); sections = rdr.ReadLeInt16(); rdr.ReadLeUInt32(); // timestamp. rdr.ReadLeUInt32(); // COFF symbol table. rdr.ReadLeUInt32(); // #of symbols. optionalHeaderSize = rdr.ReadLeInt16(); this.fileFlags = rdr.ReadLeUInt16(); rvaSectionTable = (uint) ((int)rdr.Offset + optionalHeaderSize); return expectedMagic; }
public void ApplyRelocation(uint baseOfImage, uint page, ImageReader rdr, RelocationDictionary relocations) { ushort fixup = rdr.ReadLeUInt16(); uint offset = page + (fixup & 0x0FFFu); switch (fixup >> 12) { case RelocationAbsolute: // Used for padding to 4-byte boundary, ignore. break; case RelocationHighLow: { uint n = (uint) (imgLoaded.ReadLeUInt32(offset) + (baseOfImage - preferredBaseOfImage.ToLinear())); imgLoaded.WriteLeUInt32(offset, n); relocations.AddPointerReference(offset, n); break; } case 0xA: break; default: var dcSvc = Services.RequireService<DecompilerEventListener>(); dcSvc.Warn( dcSvc.CreateAddressNavigator(program, Address.Ptr32(offset)), string.Format( "Unsupported PE fixup type: {0:X}", fixup >> 12)); break; } }
public void ApplyRelocation(uint baseOfImage, uint page, ImageReader rdr, RelocationDictionary relocations) { ushort fixup = rdr.ReadLeUInt16(); switch (fixup >> 12) { case RelocationAbsolute: // Used for padding to 4-byte boundary, ignore. break; case RelocationHighLow: { uint offset = page + (fixup & 0x0FFFu); uint n = (uint) (imgLoaded.ReadLeUInt32(offset) + (baseOfImage - preferredBaseOfImage.ToLinear())); imgLoaded.WriteLeUInt32(offset, n); relocations.AddPointerReference(offset, n); break; } case 0xA: break; default: throw new NotImplementedException(string.Format("Fixup type: {0:X}", fixup >> 12)); } }
public override Address ReadCodeAddress(int size, ImageReader rdr, ProcessorState state) { ushort uAddr = rdr.ReadLeUInt16(); return Address.Ptr16(uAddr); }
// Read a section of the file, considering endian issues void readFileSection(ushort[] p, int len, ImageReader rdr) { int pp = 0; for (int i = 0; i < len; i += 2) { p[pp++] = rdr.ReadLeUInt16(); } }