- Update FreeLDR PE Loading to actually use its Mm routines to allocate a buffer to read an image file into, then to allocate the actual load base and use the same code as in sysldr.c right now to PE-load the image into memory, then free the original read buffer. Not yet enabled for drivers!

- This means that:
  - 1) FreeLDR now keeps memory accounting information for the image files it loads, instead of us randomly writing to memory.
  - 2) We now skip sections marked as NO_LOAD. The kernel already re-mapped drivers doing this, but it didn't remap the kernel/hal, plus we still had to map the drivers once in FreeLDR, so we're saving a meg+ of kernel memory.

svn path=/trunk/; revision=25894
This commit is contained in:
Alex Ionescu 2007-02-23 19:48:25 +00:00
parent 8ccd7405b6
commit 9969d07b68
3 changed files with 82 additions and 47 deletions

View file

@ -598,46 +598,64 @@ LdrPEFixupImports(IN PVOID DllBase,
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
VOID ULONG
NTAPI NTAPI
FrLdrReMapImage(IN PIMAGE_NT_HEADERS NtHeader, FrLdrReMapImage(IN PVOID Base,
IN PVOID Base) IN PVOID LoadBase)
{ {
PIMAGE_NT_HEADERS NtHeader;
PIMAGE_SECTION_HEADER Section; PIMAGE_SECTION_HEADER Section;
ULONG SectionCount, SectionSize; ULONG i, Size, DriverSize = 0;
PVOID SourceSection, TargetSection;
INT i;
/* Load the first section */ /* Get the first section */
NtHeader = RtlImageNtHeader(Base);
Section = IMAGE_FIRST_SECTION(NtHeader); Section = IMAGE_FIRST_SECTION(NtHeader);
SectionCount = NtHeader->FileHeader.NumberOfSections - 1;
/* Now go to the last section */ /* Determine the size of the module */
Section += SectionCount; for (i = 0; i < NtHeader->FileHeader.NumberOfSections; i++)
/* Walk each section backwards */
for (i = SectionCount; i >= 0; i--, Section--)
{ {
/* Get the disk location and the memory location, and the size */ /* Skip this section if we're not supposed to load it */
SourceSection = RVA(Base, Section->PointerToRawData); if (!(Section[i].Characteristics & IMAGE_SCN_TYPE_NOLOAD))
TargetSection = RVA(Base, Section->VirtualAddress);
SectionSize = Section->SizeOfRawData;
/* If the section is already mapped correctly, go to the next */
if (SourceSection == TargetSection) continue;
/* Load it into memory */
RtlMoveMemory(TargetSection, SourceSection, SectionSize);
/* Check for uninitialized data */
if (Section->SizeOfRawData < Section->Misc.VirtualSize)
{ {
/* Zero it out */ /* Add the size of this section into the total size */
RtlZeroMemory(RVA(Base, Section->VirtualAddress + Size = Section[i].VirtualAddress + Section[i].Misc.VirtualSize;
Section->SizeOfRawData), DriverSize = max(DriverSize, Size);
Section->Misc.VirtualSize - Section->SizeOfRawData);
} }
} }
/* Round up the driver size to section alignment */
DriverSize = ROUND_UP(DriverSize, NtHeader->OptionalHeader.SectionAlignment);
/* Allocate memory for the driver */
LoadBase = MmAllocateMemoryAtAddress(DriverSize, LoadBase);
ASSERT(LoadBase);
/* Copy headers over */
RtlMoveMemory(LoadBase,
Base,
NtHeader->OptionalHeader.SizeOfHeaders);
/* Copy image sections into virtual section */
for (i = 0; i < NtHeader->FileHeader.NumberOfSections; i++)
{
/* Get the size of this section and check if it's valid and on-disk */
Size = Section[i].VirtualAddress + Section[i].Misc.VirtualSize;
if ((Size <= DriverSize) && (Section[i].SizeOfRawData))
{
/* Copy the data from the disk to the image */
RtlCopyMemory((PVOID)((ULONG_PTR)LoadBase +
Section[i].VirtualAddress),
(PVOID)((ULONG_PTR)Base +
Section[i].PointerToRawData),
Section[i].Misc.VirtualSize >
Section[i].SizeOfRawData ?
Section[i].SizeOfRawData :
Section[i].Misc.VirtualSize);
}
}
/* Return the size of the mapped driver */
return DriverSize;
} }
BOOLEAN BOOLEAN
@ -646,32 +664,40 @@ FrLdrMapImage(IN FILE *Image,
IN PCHAR Name, IN PCHAR Name,
IN ULONG ImageType) IN ULONG ImageType)
{ {
PIMAGE_NT_HEADERS NtHeader; PVOID ImageBase, LoadBase, ReadBuffer;
PVOID ImageBase, LoadBase;
ULONG ImageSize;
ULONG ImageId = LoaderBlock.ModsCount; ULONG ImageId = LoaderBlock.ModsCount;
ULONG ImageSize;
/* Set the virtual (image) and physical (load) addresses */ /* Set the virtual (image) and physical (load) addresses */
LoadBase = (PVOID)NextModuleBase; LoadBase = (PVOID)NextModuleBase;
ImageBase = RVA(LoadBase , -KERNEL_BASE_PHYS + KSEG0_BASE); ImageBase = RVA(LoadBase , -KERNEL_BASE_PHYS + KSEG0_BASE);
/* Load the first 1024 bytes of the HAL image so we can read the PE header */
if (!FsReadFile(Image, 1024, NULL, LoadBase)) return FALSE;
/* Now read the MZ header to get the offset to the PE Header */
NtHeader = RtlImageNtHeader(LoadBase);
/* Save the Image Size */ /* Save the Image Size */
ImageSize = NtHeader->OptionalHeader.SizeOfImage; ImageSize = FsGetFileSize(Image);
/* Set the file pointer to zero */ /* Set the file pointer to zero */
FsSetFilePointer(Image, 0); FsSetFilePointer(Image, 0);
/* Load the file image */ if (ImageType != 2)
FsReadFile(Image, ImageSize, NULL, LoadBase); {
/* Allocate a temporary buffer for the read */
ReadBuffer = MmAllocateMemory(ImageSize);
/* Map it into virtual memory */ /* Load the file image */
if (ImageType != 2) FrLdrReMapImage(NtHeader, LoadBase); FsReadFile(Image, ImageSize, NULL, ReadBuffer);
/* Map it into virtual memory */
ImageSize = FrLdrReMapImage(ReadBuffer, LoadBase);
/* Free the temporary buffer */
MmFreeMemory(ReadBuffer);
}
else
{
/* Load the file image */
FsReadFile(Image, ImageSize, NULL, LoadBase);
ImageSize = RtlImageNtHeader(LoadBase)->OptionalHeader.SizeOfImage;
}
/* Calculate Difference between Real Base and Compiled Base*/ /* Calculate Difference between Real Base and Compiled Base*/
if (ImageType != 2) LdrRelocateImageWithBias(LoadBase, if (ImageType != 2) LdrRelocateImageWithBias(LoadBase,
@ -698,6 +724,8 @@ FrLdrMapImage(IN FILE *Image,
/* Load HAL if this is the kernel */ /* Load HAL if this is the kernel */
if (ImageType == 1) if (ImageType == 1)
{ {
PIMAGE_NT_HEADERS NtHeader;
NtHeader = RtlImageNtHeader(LoadBase);
KernelBase = NtHeader->OptionalHeader.ImageBase; KernelBase = NtHeader->OptionalHeader.ImageBase;
KernelEntry = RaToPa(NtHeader->OptionalHeader.AddressOfEntryPoint); KernelEntry = RaToPa(NtHeader->OptionalHeader.AddressOfEntryPoint);
FrLdrLoadImage("hal.dll", 10, FALSE); FrLdrLoadImage("hal.dll", 10, FALSE);

View file

@ -839,7 +839,9 @@ IopInitializeBuiltinDriver(IN PLDR_DATA_TABLE_ENTRY LdrEntry)
PWCHAR FileNameWithoutPath; PWCHAR FileNameWithoutPath;
LPWSTR FileExtension; LPWSTR FileExtension;
PUNICODE_STRING ModuleName = &LdrEntry->BaseDllName; PUNICODE_STRING ModuleName = &LdrEntry->BaseDllName;
#if 1 // Disable for FreeLDR 2.5
PLDR_DATA_TABLE_ENTRY ModuleObject; PLDR_DATA_TABLE_ENTRY ModuleObject;
#endif
/* /*
@ -873,9 +875,11 @@ IopInitializeBuiltinDriver(IN PLDR_DATA_TABLE_ENTRY LdrEntry)
} }
/* /*
* Load the module. Remove for FreeLDR 2.5. * Load the module.
*/ */
RtlCreateUnicodeString(&DeviceNode->ServiceName, FileNameWithoutPath); RtlCreateUnicodeString(&DeviceNode->ServiceName, FileNameWithoutPath);
#if 1 // Remove for FreeLDR 2.5.
Status = LdrProcessDriverModule(LdrEntry, &DeviceNode->ServiceName, &ModuleObject); Status = LdrProcessDriverModule(LdrEntry, &DeviceNode->ServiceName, &ModuleObject);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
@ -883,6 +887,7 @@ IopInitializeBuiltinDriver(IN PLDR_DATA_TABLE_ENTRY LdrEntry)
CPRINT("Driver '%wZ' load failed, status (%x)\n", ModuleName, Status); CPRINT("Driver '%wZ' load failed, status (%x)\n", ModuleName, Status);
return Status; return Status;
} }
#endif
/* Load symbols */ /* Load symbols */
KDB_SYMBOLFILE_HOOK(ModuleName); KDB_SYMBOLFILE_HOOK(ModuleName);
@ -900,7 +905,7 @@ IopInitializeBuiltinDriver(IN PLDR_DATA_TABLE_ENTRY LdrEntry)
/* /*
* Initialize the driver * Initialize the driver
*/ */
Status = IopInitializeDriverModule(DeviceNode, ModuleObject, Status = IopInitializeDriverModule(DeviceNode, LdrEntry,
&DeviceNode->ServiceName, FALSE, &DriverObject); &DeviceNode->ServiceName, FALSE, &DriverObject);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))

View file

@ -1063,8 +1063,10 @@ MiReloadBootLoadedDrivers(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
PIMAGE_DATA_DIRECTORY DataDirectory; PIMAGE_DATA_DIRECTORY DataDirectory;
PVOID DllBase, NewImageAddress; PVOID DllBase, NewImageAddress;
NTSTATUS Status; NTSTATUS Status;
#if 1 // Disable for FreeLDR 2.5
ULONG DriverSize = 0, Size; ULONG DriverSize = 0, Size;
PIMAGE_SECTION_HEADER Section; PIMAGE_SECTION_HEADER Section;
#endif
/* Loop driver list */ /* Loop driver list */
for (NextEntry = LoaderBlock->LoadOrderListHead.Flink; for (NextEntry = LoaderBlock->LoadOrderListHead.Flink;
@ -1157,7 +1159,7 @@ MiReloadBootLoadedDrivers(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
#if 0 // Enable for FreeLDR 2.5 #if 0 // Enable for FreeLDR 2.5
/* Now copy the entire driver over */ /* Now copy the entire driver over */
RtlCopyMemory(NewImageAddress, DllBase, DriverSize); RtlCopyMemory(NewImageAddress, DllBase, LdrEntry->SizeOfImage);
#else #else
/* Copy headers over */ /* Copy headers over */
RtlCopyMemory(NewImageAddress, RtlCopyMemory(NewImageAddress,