mirror of
https://github.com/reactos/reactos.git
synced 2025-02-23 08:55:19 +00:00
- 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:
parent
8ccd7405b6
commit
9969d07b68
3 changed files with 82 additions and 47 deletions
|
@ -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);
|
||||||
|
|
||||||
|
if (ImageType != 2)
|
||||||
|
{
|
||||||
|
/* Allocate a temporary buffer for the read */
|
||||||
|
ReadBuffer = MmAllocateMemory(ImageSize);
|
||||||
|
|
||||||
/* Load the file image */
|
/* Load the file image */
|
||||||
FsReadFile(Image, ImageSize, NULL, LoadBase);
|
FsReadFile(Image, ImageSize, NULL, ReadBuffer);
|
||||||
|
|
||||||
/* Map it into virtual memory */
|
/* Map it into virtual memory */
|
||||||
if (ImageType != 2) FrLdrReMapImage(NtHeader, LoadBase);
|
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);
|
||||||
|
|
|
@ -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))
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Loading…
Reference in a new issue