mirror of
https://github.com/reactos/reactos.git
synced 2025-08-04 09:46:18 +00:00
Dmitry Gorbachev:
- FreeLoader first reads entire ntoskrnl.exe (about 20M) into memory, then copies it to other address. Now, freeldr reads it straight to the place, not allocating extra memory for buffer. - Aleksey: This changes should be eventually adopted and merged into winldr's peloader.c. See issue #3447 for more details. svn path=/trunk/; revision=34292
This commit is contained in:
parent
97f94beafc
commit
b33ec42e10
4 changed files with 185 additions and 3 deletions
|
@ -111,6 +111,14 @@ FrLdrMapImage(
|
||||||
IN ULONG ImageType
|
IN ULONG ImageType
|
||||||
);
|
);
|
||||||
|
|
||||||
|
PVOID
|
||||||
|
NTAPI
|
||||||
|
FrLdrReadAndMapImage(
|
||||||
|
IN FILE *Image,
|
||||||
|
IN PCHAR ShortName,
|
||||||
|
IN ULONG ImageType
|
||||||
|
);
|
||||||
|
|
||||||
PVOID
|
PVOID
|
||||||
NTAPI
|
NTAPI
|
||||||
FrLdrLoadImage(
|
FrLdrLoadImage(
|
||||||
|
|
|
@ -434,6 +434,174 @@ LdrPEFixupImports(IN PVOID DllBase,
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PVOID
|
||||||
|
NTAPI
|
||||||
|
FrLdrReadAndMapImage(IN FILE *Image,
|
||||||
|
IN PCHAR Name,
|
||||||
|
IN ULONG ImageType)
|
||||||
|
{
|
||||||
|
PVOID ImageBase, LoadBase, ReadBuffer;
|
||||||
|
ULONG ImageId = LoaderBlock.ModsCount;
|
||||||
|
ULONG i, Size, ImageSize, SizeOfHeaders;
|
||||||
|
PIMAGE_NT_HEADERS NtHeader;
|
||||||
|
PIMAGE_SECTION_HEADER Section;
|
||||||
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
/* Try to see, maybe it's loaded already */
|
||||||
|
if (LdrGetModuleObject(Name) != NULL)
|
||||||
|
{
|
||||||
|
/* It's loaded, return NULL. It would be wise to return
|
||||||
|
correct LoadBase, but it seems to be ignored almost everywhere */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the virtual (image) and physical (load) addresses */
|
||||||
|
LoadBase = (PVOID)NextModuleBase;
|
||||||
|
ImageBase = RVA(LoadBase, KSEG0_BASE);
|
||||||
|
|
||||||
|
/* Allocate a temporary buffer for the read */
|
||||||
|
ReadBuffer = MmHeapAlloc(MM_PAGE_SIZE);
|
||||||
|
if (!ReadBuffer)
|
||||||
|
{
|
||||||
|
/* Fail */
|
||||||
|
DbgPrint("Failed to allocate a temporary buffer for the read\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the file pointer to zero */
|
||||||
|
FsSetFilePointer(Image, 0);
|
||||||
|
|
||||||
|
/* Load first page of the file image */
|
||||||
|
if (!FsReadFile(Image, MM_PAGE_SIZE, NULL, ReadBuffer))
|
||||||
|
{
|
||||||
|
/* Fail */
|
||||||
|
DbgPrint("Failed to read image: %s\n", Name);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get image headers */
|
||||||
|
NtHeader = RtlImageNtHeader(ReadBuffer);
|
||||||
|
|
||||||
|
/* Allocate memory for the driver */
|
||||||
|
ImageSize = NtHeader->OptionalHeader.SizeOfImage;
|
||||||
|
LoadBase = MmAllocateMemoryAtAddress(ImageSize, LoadBase, LoaderSystemCode);
|
||||||
|
ASSERT(LoadBase);
|
||||||
|
|
||||||
|
/* Copy headers over */
|
||||||
|
SizeOfHeaders = NtHeader->OptionalHeader.SizeOfHeaders;
|
||||||
|
if (SizeOfHeaders < MM_PAGE_SIZE)
|
||||||
|
{
|
||||||
|
RtlMoveMemory(LoadBase, ReadBuffer, SizeOfHeaders);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RtlMoveMemory(LoadBase, ReadBuffer, MM_PAGE_SIZE);
|
||||||
|
if (!FsReadFile(Image, SizeOfHeaders - MM_PAGE_SIZE, NULL,
|
||||||
|
(PVOID)((ULONG_PTR)LoadBase + MM_PAGE_SIZE)))
|
||||||
|
{
|
||||||
|
DbgPrint("Failed to read image: %s\n", Name);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Free the temporary buffer */
|
||||||
|
MmHeapFree(ReadBuffer);
|
||||||
|
|
||||||
|
/* Get the first section */
|
||||||
|
NtHeader = RtlImageNtHeader(LoadBase);
|
||||||
|
Section = IMAGE_FIRST_SECTION(NtHeader);
|
||||||
|
|
||||||
|
/* Read 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 */
|
||||||
|
Size = Section[i].VirtualAddress + Section[i].Misc.VirtualSize;
|
||||||
|
if (Size <= ImageSize)
|
||||||
|
{
|
||||||
|
if (Section[i].SizeOfRawData)
|
||||||
|
{
|
||||||
|
/* Copy the data from the disk to the image */
|
||||||
|
FsSetFilePointer(Image, Section[i].PointerToRawData);
|
||||||
|
if (!FsReadFile(Image,
|
||||||
|
Section[i].Misc.VirtualSize >
|
||||||
|
Section[i].SizeOfRawData ?
|
||||||
|
Section[i].SizeOfRawData :
|
||||||
|
Section[i].Misc.VirtualSize,
|
||||||
|
NULL,
|
||||||
|
(PVOID)((ULONG_PTR)LoadBase +
|
||||||
|
Section[i].VirtualAddress)))
|
||||||
|
{
|
||||||
|
DbgPrint("Failed to read image: %s\n", Name);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Clear the BSS area */
|
||||||
|
RtlZeroMemory((PVOID)((ULONG_PTR)LoadBase +
|
||||||
|
Section[i].VirtualAddress),
|
||||||
|
Section[i].Misc.VirtualSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Calculate Difference between Real Base and Compiled Base*/
|
||||||
|
Status = LdrRelocateImageWithBias(LoadBase,
|
||||||
|
(ULONG_PTR)ImageBase -
|
||||||
|
(ULONG_PTR)LoadBase,
|
||||||
|
"FreeLdr",
|
||||||
|
STATUS_SUCCESS,
|
||||||
|
STATUS_UNSUCCESSFUL,
|
||||||
|
STATUS_UNSUCCESSFUL);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* Fail */
|
||||||
|
DbgPrint("Failed to relocate image: %s\n", Name);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fill out Module Data Structure */
|
||||||
|
reactos_modules[ImageId].ModStart = (ULONG_PTR)ImageBase;
|
||||||
|
reactos_modules[ImageId].ModEnd = (ULONG_PTR)ImageBase + ImageSize;
|
||||||
|
strcpy(reactos_module_strings[ImageId], Name);
|
||||||
|
reactos_modules[ImageId].String = (ULONG_PTR)reactos_module_strings[ImageId];
|
||||||
|
LoaderBlock.ModsCount++;
|
||||||
|
|
||||||
|
/* Detect kernel or HAL */
|
||||||
|
if (!_stricmp(Name, "ntoskrnl.exe"))
|
||||||
|
{
|
||||||
|
KernelData = (PVOID)NextModuleBase;
|
||||||
|
KernelSize = ImageSize;
|
||||||
|
}
|
||||||
|
else if (!_stricmp(Name, "hal.dll"))
|
||||||
|
{
|
||||||
|
HalData = (PVOID)NextModuleBase;
|
||||||
|
HalSize = ImageSize;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DriverName[Drivers] = reactos_module_strings[ImageId];
|
||||||
|
DriverData[Drivers] = (PVOID)NextModuleBase;
|
||||||
|
DriverSize[Drivers] = ImageSize;
|
||||||
|
Drivers++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Increase the next Load Base */
|
||||||
|
NextModuleBase = ROUND_UP(NextModuleBase + ImageSize, PAGE_SIZE);
|
||||||
|
|
||||||
|
/* Perform import fixups */
|
||||||
|
if (!NT_SUCCESS(LdrPEFixupImports(LoadBase, Name)))
|
||||||
|
{
|
||||||
|
/* Fixup failed, just don't include it in the list */
|
||||||
|
// NextModuleBase = OldNextModuleBase;
|
||||||
|
LoaderBlock.ModsCount = ImageId;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the final mapped address */
|
||||||
|
return LoadBase;
|
||||||
|
}
|
||||||
|
|
||||||
ULONG
|
ULONG
|
||||||
NTAPI
|
NTAPI
|
||||||
FrLdrReMapImage(IN PVOID Base,
|
FrLdrReMapImage(IN PVOID Base,
|
||||||
|
@ -519,6 +687,12 @@ FrLdrMapImage(IN FILE *Image,
|
||||||
|
|
||||||
/* Allocate a temporary buffer for the read */
|
/* Allocate a temporary buffer for the read */
|
||||||
ReadBuffer = MmHeapAlloc(ImageSize);
|
ReadBuffer = MmHeapAlloc(ImageSize);
|
||||||
|
if (!ReadBuffer)
|
||||||
|
{
|
||||||
|
/* Fail */
|
||||||
|
DbgPrint("Failed to allocate a temporary buffer for the read\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* Load the file image */
|
/* Load the file image */
|
||||||
if (!FsReadFile(Image, ImageSize, NULL, ReadBuffer))
|
if (!FsReadFile(Image, ImageSize, NULL, ReadBuffer))
|
||||||
|
|
|
@ -120,7 +120,7 @@ FrLdrLoadDriver(PCHAR szFileName,
|
||||||
UiDrawStatusText(value);
|
UiDrawStatusText(value);
|
||||||
|
|
||||||
/* Load the driver */
|
/* Load the driver */
|
||||||
FrLdrMapImage(FilePointer, szFileName, 0);
|
FrLdrReadAndMapImage(FilePointer, szFileName, 0);
|
||||||
|
|
||||||
/* Update status and return */
|
/* Update status and return */
|
||||||
UiDrawProgressBarCenter(nPos, 100, szLoadingMsg);
|
UiDrawProgressBarCenter(nPos, 100, szLoadingMsg);
|
||||||
|
@ -182,7 +182,7 @@ FrLdrLoadImage(IN PCHAR szFileName,
|
||||||
UiDrawStatusText(szBuffer);
|
UiDrawStatusText(szBuffer);
|
||||||
|
|
||||||
/* Do the actual loading */
|
/* Do the actual loading */
|
||||||
LoadBase = FrLdrMapImage(FilePointer, szShortName, ImageType);
|
LoadBase = FrLdrReadAndMapImage(FilePointer, szShortName, ImageType);
|
||||||
|
|
||||||
/* Update Processbar and return success */
|
/* Update Processbar and return success */
|
||||||
if (!FrLdrBootType) UiDrawProgressBarCenter(nPos, 100, szLoadingMsg);
|
if (!FrLdrBootType) UiDrawProgressBarCenter(nPos, 100, szLoadingMsg);
|
||||||
|
|
|
@ -82,7 +82,7 @@ static FrLdrLoadKernel(IN PCHAR szFileName,
|
||||||
UiDrawStatusText(szBuffer);
|
UiDrawStatusText(szBuffer);
|
||||||
|
|
||||||
/* Do the actual loading */
|
/* Do the actual loading */
|
||||||
LoadBase = FrLdrMapImage(FilePointer, szShortName, 1);
|
LoadBase = FrLdrReadAndMapImage(FilePointer, szShortName, 1);
|
||||||
|
|
||||||
/* Get the NT header, kernel base and kernel entry */
|
/* Get the NT header, kernel base and kernel entry */
|
||||||
NtHeader = RtlImageNtHeader(LoadBase);
|
NtHeader = RtlImageNtHeader(LoadBase);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue