public static void InitializeMpAbi() { // Note: When mapping the abi stub (MpSyscalls.x86), we must // map it with writable flag! as we want to resolve the stub's // imports IoMemory mpPages = IoMemory.MapPhysicalMemory(Platform.MP_ABI_BASE, 4096, true, true); mpAbi = new PEImage(mpPages); mpPages = IoMemory.MapPhysicalMemory(Platform.MP_ABI_BASE, mpAbi.loadedSize, true, true); mpAbiExports = mpAbi.GetExportTable(mpPages); // Resolve imports in abi shim dll with the kernel exports // which are the real stub that will do IPI stuffs ImportTable mpAbiIt = mpAbi.GetImportTable(mpPages); DebugStub.WriteLine("HSG: ** Resolving Imports"); mpAbiIt.ResolveImports(kernelExports); }
public static PEImage Load(Process process, IoMemory rawMemory, out IoMemory loadedMemory, bool isForMp, bool inKernelSpace) { UIntPtr entryPoint = UIntPtr.Zero; loadedMemory = null; DiagnosisService.DeferedUpdateNotification(); if (null == rawMemory || 0 == rawMemory.Length) { DebugStub.WriteLine("No PXE image to load!"); return(null); } // // Allocate memory and copy the PXE image from memory to memory // #if verbose Tracing.Log(Tracing.Debug, " PXE at {0:x8}, Length ={1:x8}", (uint)rawMemory.VirtualAddress, rawMemory.Length); #endif Kernel.Waypoint(580); Tracing.Log(Tracing.Debug, "Loading:"); PEImage image = new PEImage(rawMemory); image.DumpLimitedToStream(); #if verbose Tracing.Log(Tracing.Debug, " Loaded Size={0:x8}", image.loadedSize); #endif Kernel.Waypoint(581); if (0 == image.loadedSize) { throw new BadImageFormatException("Invalid PE, no content"); } try { if (inKernelSpace) { loadedMemory = IoMemory.AllocateFixed( (UIntPtr)image.loadedSize, process, PageType.System); } else { // Situate the process image in the user range loadedMemory = IoMemory.AllocateUserFixed( (UIntPtr)image.loadedSize, process, PageType.System); } Kernel.Waypoint(582); #if verbose Tracing.Log(Tracing.Debug, " loaded at {0:x8}, Length ={1:x8}", (uint)loadedMemory.VirtualAddress, loadedMemory.Length); #endif // Copy the header so the debugger can find it. IoMemory.Copy(rawMemory, 0, loadedMemory, 0, (int)image.sizeOfHeaders); #if verbose image.DumpLimitedToStream(); #endif Kernel.Waypoint(583); // load sections into memory where they belong. for (int i = 0; i < image.numberOfSections; i++) { if (image.sections[i].IsDiscardable || image.sections[i].sizeOfRawData == 0) { continue; } int targetOffset = (int)image.sections[i].virtualAddress; int sourceOffset = (int)image.sections[i].pointerToRawData; uint rawSize = Math.Min(image.sections[i].sizeOfRawData, image.sections[i].virtualSize); #if verbose Tracing.Log(Tracing.Debug, "section[{0}] source={1:x8}..{2:x8} target={3:x8}..{4:x8}", i, sourceOffset, sourceOffset + rawSize, targetOffset, targetOffset + rawSize); #endif if (image.sections[i].virtualSize > image.sections[i].sizeOfRawData) { // The memory allocated for the new image is not zeroed, therefore // we need to clear the remaining region of a section that is not getting // copied from the source. NOTE BSS sections rely on this to be zeroed // This is fixing some random bugs with uninitialized variables in unmanaged code unsafe { byte *dest = (byte *)loadedMemory.VirtualAddress + targetOffset + image.sections[i].sizeOfRawData; uint length = image.sections[i].virtualSize - image.sections[i].sizeOfRawData; Buffer.ZeroMemory(dest, length); } } IoMemory.Copy(rawMemory, sourceOffset, loadedMemory, targetOffset, (int)rawSize); } Kernel.Waypoint(584); // // Handle Relocations // int relocationTableOffset = (int)image.GetRelocationsRaw(); UIntPtr diff = (UIntPtr)loadedMemory.VirtualAddress - (UIntPtr)image.imageBase; image.VirtualAddress = loadedMemory.VirtualAddress; #if verbose Tracing.Log(Tracing.Debug, " Base loaded={0:x8}, relocated ={1:x8} diff={2:x8}", image.imageBase, (uint)loadedMemory.VirtualAddress, diff); Tracing.Log(Tracing.Debug, " relocationTableOffset ={0:x8} ", relocationTableOffset); #endif if (relocationTableOffset > 0) { Relocations.FixupBlocks(rawMemory, (int)relocationTableOffset, loadedMemory, diff); // TODO: We should probably zero the relocation table. } Kernel.Waypoint(585); // // Resolve Imports // ImportTable it = image.GetImportTable(loadedMemory); Kernel.Waypoint(586); #if !PAGING #if GENERATE_ABI_SHIM if (it != null) { #endif //it.DumpIAT("Import directory"); // if this is loading for remote processor // then solve the imports with abi stub if (isForMp) { it.ResolveImports(mpAbiExports); } else { it.ResolveImports(kernelExports); } //DumpIAT(loadedMemory, "Import Address Table", // ref image.directory[12]); #if GENERATE_ABI_SHIM } #endif #else if (it != null) { // Ring-3 protection domains come with a set of // stubs that accomplish the ring3-to-ring0 ABI // transitions. Use these when called for. ExportTable abiStubs = process.Domain.ABIStubs; if (abiStubs != null) { it.ResolveImports(abiStubs); } else { it.ResolveImports(kernelExports); } } #endif Kernel.Waypoint(587); // // Dump Exports // ExportTable et = image.GetExportTable(loadedMemory); if (et != null) { et.Dump(); } Kernel.Waypoint(588); entryPoint = (UIntPtr)loadedMemory.VirtualAddress + image.addressOfEntryPoint; Tracing.Log(Tracing.Debug, " Loaded: {0:x8}..{1:x8}, Entry: {2:x8}", (ulong)loadedMemory.VirtualAddress, (ulong)(loadedMemory.VirtualAddress + loadedMemory.Length), (ulong)(entryPoint)); } finally { if (entryPoint == UIntPtr.Zero && loadedMemory != null) { // TODO: Need to dispose of target Range. loadedMemory = null; } } return(image); }