- 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;
}
VOID
ULONG
NTAPI
FrLdrReMapImage(IN PIMAGE_NT_HEADERS NtHeader,
IN PVOID Base)
FrLdrReMapImage(IN PVOID Base,
IN PVOID LoadBase)
{
PIMAGE_NT_HEADERS NtHeader;
PIMAGE_SECTION_HEADER Section;
ULONG SectionCount, SectionSize;
PVOID SourceSection, TargetSection;
INT i;
ULONG i, Size, DriverSize = 0;
/* Load the first section */
/* Get the first section */
NtHeader = RtlImageNtHeader(Base);
Section = IMAGE_FIRST_SECTION(NtHeader);
SectionCount = NtHeader->FileHeader.NumberOfSections - 1;
/* Now go to the last section */
Section += SectionCount;
/* Walk each section backwards */
for (i = SectionCount; i >= 0; i--, Section--)
/* Determine the size of the module */
for (i = 0; i < NtHeader->FileHeader.NumberOfSections; i++)
{
/* Get the disk location and the memory location, and the size */
SourceSection = RVA(Base, Section->PointerToRawData);
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)
/* Skip this section if we're not supposed to load it */
if (!(Section[i].Characteristics & IMAGE_SCN_TYPE_NOLOAD))
{
/* Zero it out */
RtlZeroMemory(RVA(Base, Section->VirtualAddress +
Section->SizeOfRawData),
Section->Misc.VirtualSize - Section->SizeOfRawData);
/* Add the size of this section into the total size */
Size = Section[i].VirtualAddress + Section[i].Misc.VirtualSize;
DriverSize = max(DriverSize, Size);
}
}
/* 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
@ -646,32 +664,40 @@ FrLdrMapImage(IN FILE *Image,
IN PCHAR Name,
IN ULONG ImageType)
{
PIMAGE_NT_HEADERS NtHeader;
PVOID ImageBase, LoadBase;
ULONG ImageSize;
PVOID ImageBase, LoadBase, ReadBuffer;
ULONG ImageId = LoaderBlock.ModsCount;
ULONG ImageSize;
/* Set the virtual (image) and physical (load) addresses */
LoadBase = (PVOID)NextModuleBase;
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 */
ImageSize = NtHeader->OptionalHeader.SizeOfImage;
ImageSize = FsGetFileSize(Image);
/* Set the file pointer to zero */
FsSetFilePointer(Image, 0);
/* Load the file image */
FsReadFile(Image, ImageSize, NULL, LoadBase);
if (ImageType != 2)
{
/* Allocate a temporary buffer for the read */
ReadBuffer = MmAllocateMemory(ImageSize);
/* Map it into virtual memory */
if (ImageType != 2) FrLdrReMapImage(NtHeader, LoadBase);
/* Load the file image */
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*/
if (ImageType != 2) LdrRelocateImageWithBias(LoadBase,
@ -698,6 +724,8 @@ FrLdrMapImage(IN FILE *Image,
/* Load HAL if this is the kernel */
if (ImageType == 1)
{
PIMAGE_NT_HEADERS NtHeader;
NtHeader = RtlImageNtHeader(LoadBase);
KernelBase = NtHeader->OptionalHeader.ImageBase;
KernelEntry = RaToPa(NtHeader->OptionalHeader.AddressOfEntryPoint);
FrLdrLoadImage("hal.dll", 10, FALSE);

View file

@ -839,7 +839,9 @@ IopInitializeBuiltinDriver(IN PLDR_DATA_TABLE_ENTRY LdrEntry)
PWCHAR FileNameWithoutPath;
LPWSTR FileExtension;
PUNICODE_STRING ModuleName = &LdrEntry->BaseDllName;
#if 1 // Disable for FreeLDR 2.5
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);
#if 1 // Remove for FreeLDR 2.5.
Status = LdrProcessDriverModule(LdrEntry, &DeviceNode->ServiceName, &ModuleObject);
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);
return Status;
}
#endif
/* Load symbols */
KDB_SYMBOLFILE_HOOK(ModuleName);
@ -900,7 +905,7 @@ IopInitializeBuiltinDriver(IN PLDR_DATA_TABLE_ENTRY LdrEntry)
/*
* Initialize the driver
*/
Status = IopInitializeDriverModule(DeviceNode, ModuleObject,
Status = IopInitializeDriverModule(DeviceNode, LdrEntry,
&DeviceNode->ServiceName, FALSE, &DriverObject);
if (!NT_SUCCESS(Status))

View file

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