From 978da5c0aff5a31ff94b50ec253026403ad58086 Mon Sep 17 00:00:00 2001 From: Alex Ionescu Date: Tue, 12 Sep 2006 05:21:27 +0000 Subject: [PATCH] - Revert 24020 (good code, but buggy) and 24041 (bad code/revision). - This gets us as far as 24061(+24048) for booting. svn path=/trunk/; revision=24078 --- reactos/dll/ntdll/ldr/utils.c | 208 +++++++++++++------------ reactos/lib/rtl/image.c | 140 +++++++---------- reactos/ntoskrnl/include/internal/po.h | 58 +++++-- reactos/ntoskrnl/ke/thrdobj.c | 6 + reactos/ntoskrnl/ke/thrdschd.c | 2 + 5 files changed, 225 insertions(+), 189 deletions(-) diff --git a/reactos/dll/ntdll/ldr/utils.c b/reactos/dll/ntdll/ldr/utils.c index 5fbb7d9aca0..f7a94cd4d07 100644 --- a/reactos/dll/ntdll/ldr/utils.c +++ b/reactos/dll/ntdll/ldr/utils.c @@ -1198,89 +1198,126 @@ LdrGetExportByName(PVOID BaseAddress, return (PVOID)NULL; } -/*++ -* @name LdrpSetProtection -* -* Local routine, used to set or reset pages protection. -* Used during PE relocation process. -* -* @param BaseAddress -* Base address of the image. -* -* @param Protection -* FALSE to disable protection, TRUE to enable it -* -* @return Usual NTSTATUS. -* -* @remarks None. -* -*--*/ -NTSTATUS -LdrpSetProtection(IN PVOID BaseAddress, - IN BOOLEAN Protection) + +/********************************************************************** + * NAME LOCAL + * LdrPerformRelocations + * + * DESCRIPTION + * Relocate a DLL's memory image. + * + * ARGUMENTS + * + * RETURN VALUE + * + * REVISIONS + * + * NOTE + * + */ +static NTSTATUS +LdrPerformRelocations(PIMAGE_NT_HEADERS NTHeaders, + PVOID ImageBase) { - PIMAGE_NT_HEADERS NtHeaders; - PIMAGE_SECTION_HEADER SectionHeader; - ULONG i; - PVOID Address; - SIZE_T Size; - NTSTATUS Status; - ULONG NewAccess, OldAccess; + PIMAGE_DATA_DIRECTORY RelocationDDir; + PIMAGE_BASE_RELOCATION RelocationDir, RelocationEnd; + ULONG Count, ProtectSize, OldProtect, OldProtect2; + PVOID Page, ProtectPage, ProtectPage2; + PUSHORT TypeOffset; + ULONG_PTR Delta; + NTSTATUS Status; - NtHeaders = RtlImageNtHeader(BaseAddress); - - /* Ensure image is valid */ - if (NtHeaders == NULL) - return STATUS_INVALID_IMAGE_FORMAT; - - /* Get the first section header */ - SectionHeader = IMAGE_FIRST_SECTION(NtHeaders); - - /* Loop through every section */ - for (i = 0; i < NtHeaders->FileHeader.NumberOfSections; i++, SectionHeader++) + if (NTHeaders->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED) { - /* If section has no data - just skip to the next section */ - if (SectionHeader->SizeOfRawData == 0) - continue; + return STATUS_UNSUCCESSFUL; + } - /* We need to act only if section isn't RW */ - if (!(SectionHeader->Characteristics & IMAGE_SCN_MEM_WRITE)) + RelocationDDir = + &NTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC]; + + if (RelocationDDir->VirtualAddress == 0 || RelocationDDir->Size == 0) + { + return STATUS_SUCCESS; + } + + ProtectSize = PAGE_SIZE; + Delta = (ULONG_PTR)ImageBase - NTHeaders->OptionalHeader.ImageBase; + RelocationDir = (PIMAGE_BASE_RELOCATION)((ULONG_PTR)ImageBase + + RelocationDDir->VirtualAddress); + RelocationEnd = (PIMAGE_BASE_RELOCATION)((ULONG_PTR)ImageBase + + RelocationDDir->VirtualAddress + RelocationDDir->Size); + + while (RelocationDir < RelocationEnd && + RelocationDir->SizeOfBlock > 0) + { + Count = (RelocationDir->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / + sizeof(USHORT); + Page = (PVOID)((ULONG_PTR)ImageBase + (ULONG_PTR)RelocationDir->VirtualAddress); + TypeOffset = (PUSHORT)(RelocationDir + 1); + + /* Unprotect the page(s) we're about to relocate. */ + ProtectPage = Page; + Status = NtProtectVirtualMemory(NtCurrentProcess(), + &ProtectPage, + &ProtectSize, + PAGE_READWRITE, + &OldProtect); + if (!NT_SUCCESS(Status)) { - if (Protection) + DPRINT1("Failed to unprotect relocation target.\n"); + return Status; + } + + if (RelocationDir->VirtualAddress + PAGE_SIZE < + NTHeaders->OptionalHeader.SizeOfImage) + { + ProtectPage2 = (PVOID)((ULONG_PTR)ProtectPage + PAGE_SIZE); + Status = NtProtectVirtualMemory(NtCurrentProcess(), + &ProtectPage2, + &ProtectSize, + PAGE_READWRITE, + &OldProtect2); + if (!NT_SUCCESS(Status)) { - /* Check if the section was also executable, then we should - give it PAGE_EXECUTE, otherwise just PAGE_READONLY */ - NewAccess = (SectionHeader->Characteristics & IMAGE_SCN_MEM_EXECUTE) ? PAGE_EXECUTE : PAGE_READONLY; - - /* Also check caching */ - NewAccess |= (SectionHeader->Characteristics & IMAGE_SCN_MEM_NOT_CACHED) ? PAGE_NOCACHE : 0; - } - else - { - /* Set access to RW */ - NewAccess = PAGE_READWRITE; + DPRINT1("Failed to unprotect relocation target (2).\n"); + NtProtectVirtualMemory(NtCurrentProcess(), + &ProtectPage, + &ProtectSize, + OldProtect, + &OldProtect); + return Status; } + } + else + { + ProtectPage2 = NULL; + } - /* Get the address and size of the section, and set protectin accordingly */ - Address = (PVOID)((ULONG_PTR)BaseAddress + SectionHeader->VirtualAddress); - Size = SectionHeader->SizeOfRawData; + RelocationDir = LdrProcessRelocationBlock((ULONG_PTR)Page, + Count, + TypeOffset, + Delta); + if (RelocationDir == NULL) + return STATUS_UNSUCCESSFUL; - Status = NtProtectVirtualMemory(NtCurrentProcess(), - &Address, - &Size, - NewAccess, - &OldAccess); + /* Restore old page protection. */ + NtProtectVirtualMemory(NtCurrentProcess(), + &ProtectPage, + &ProtectSize, + OldProtect, + &OldProtect); - if (!NT_SUCCESS(Status)) - return Status; + if (ProtectPage2 != NULL) + { + NtProtectVirtualMemory(NtCurrentProcess(), + &ProtectPage2, + &ProtectSize, + OldProtect2, + &OldProtect2); } } - /* Instruction cache should be flushed if we enabled protection */ - if (Protection) - NtFlushInstructionCache(NtCurrentProcess(), NULL, 0); - - return STATUS_SUCCESS; + return STATUS_SUCCESS; } static NTSTATUS @@ -1861,32 +1898,12 @@ PEPFUNC LdrPEStartup (PVOID ImageBase, if (ImageBase != (PVOID) NTHeaders->OptionalHeader.ImageBase) { DPRINT("LDR: Performing relocations\n"); - - /* Remove protection */ - Status = LdrpSetProtection(ImageBase, FALSE); + Status = LdrPerformRelocations(NTHeaders, ImageBase); if (!NT_SUCCESS(Status)) { - DPRINT1("LdrpSetProtection() failed with Status=0x%08X\n", Status); + DPRINT1("LdrPerformRelocations() failed\n"); return NULL; } - - /* Relocate */ - Status = LdrRelocateImageWithBias(ImageBase, 0, "", STATUS_SUCCESS, - STATUS_CONFLICTING_ADDRESSES, STATUS_INVALID_IMAGE_FORMAT); - if (!NT_SUCCESS(Status)) - { - DPRINT1("LdrRelocateImageWithBias() failed with Status=0x%08X\n", Status); - return NULL; - } - - /* Set protection back */ - Status = LdrpSetProtection(ImageBase, TRUE); - if (!NT_SUCCESS(Status)) - { - DPRINT1("LdrpSetProtection() failed with Status=0x%08X\n", Status); - return NULL; - } - } if (Module != NULL) @@ -2061,13 +2078,10 @@ LdrpLoadModule(IN PWSTR SearchPath OPTIONAL, { DPRINT1("Relocating (%lx -> %p) %wZ\n", NtHeaders->OptionalHeader.ImageBase, ImageBase, &FullDosName); - - Status = LdrRelocateImageWithBias(ImageBase, 0, "", STATUS_SUCCESS, - STATUS_CONFLICTING_ADDRESSES, STATUS_INVALID_IMAGE_FORMAT); - + Status = LdrPerformRelocations(NtHeaders, ImageBase); if (!NT_SUCCESS(Status)) { - DPRINT1("LdrRelocateImageWithBias() failed\n"); + DPRINT1("LdrPerformRelocations() failed\n"); NtUnmapViewOfSection (NtCurrentProcess (), ImageBase); NtClose (SectionHandle); RtlFreeUnicodeString(&FullDosName); diff --git a/reactos/lib/rtl/image.c b/reactos/lib/rtl/image.c index 388e3acac47..97b5a9b4643 100644 --- a/reactos/lib/rtl/image.c +++ b/reactos/lib/rtl/image.c @@ -3,10 +3,8 @@ * FILE: lib/rtl/image.c * PURPOSE: Image handling functions * Relocate functions were previously located in - * ntoskrnl/ldr/loader.c and - * dll/ntdll/ldr/utils.c files - * PROGRAMMER: Eric Kohl + original authors from loader.c and utils.c file - * Aleksey Bragin + * ntoskrnl/ldr/loader.c + * PROGRAMMER: Eric Kohl + original authors from loader.c file */ /* INCLUDES *****************************************************************/ @@ -151,76 +149,12 @@ RtlImageRvaToVa ( (ULONG_PTR)Section->VirtualAddress); } -PIMAGE_BASE_RELOCATION -LdrProcessRelocationBlockLongLong( - IN ULONG_PTR Address, - IN ULONG Count, - IN PUSHORT TypeOffset, - IN LONGLONG Delta - ) -{ - SHORT Offset; - USHORT Type; - USHORT i; - PUSHORT ShortPtr; - PULONG LongPtr; - - for (i = 0; i < Count; i++) - { - Offset = *TypeOffset & 0xFFF; - Type = *TypeOffset >> 12; - ShortPtr = (PUSHORT)(RVA(Address, Offset)); - - /* - * Don't relocate within the relocation section itself. - * GCC/LD generates sometimes relocation records for the relocation section. - * This is a bug in GCC/LD. - * Fix for it disabled, since it was only in ntoskrnl and not in ntdll - */ - /* - if ((ULONG_PTR)ShortPtr < (ULONG_PTR)RelocationDir || - (ULONG_PTR)ShortPtr >= (ULONG_PTR)RelocationEnd) - {*/ - switch (Type) - { - /* case IMAGE_REL_BASED_SECTION : */ - /* case IMAGE_REL_BASED_REL32 : */ - case IMAGE_REL_BASED_ABSOLUTE: - break; - - case IMAGE_REL_BASED_HIGH: - *ShortPtr += HIWORD(Delta); - break; - - case IMAGE_REL_BASED_LOW: - *ShortPtr += LOWORD(Delta); - break; - - case IMAGE_REL_BASED_HIGHLOW: - LongPtr = (PULONG)RVA(Address, Offset); - *LongPtr += Delta; - break; - - case IMAGE_REL_BASED_HIGHADJ: - case IMAGE_REL_BASED_MIPS_JMPADDR: - default: - DPRINT1("Unknown/unsupported fixup type %hu.\n", Type); - DPRINT1("Address %x, Current %d, Count %d, *TypeOffset %x\n", Address, i, Count, *TypeOffset); - return (PIMAGE_BASE_RELOCATION)NULL; - } - - TypeOffset++; - } - - return (PIMAGE_BASE_RELOCATION)TypeOffset; -} - ULONG NTAPI LdrRelocateImageWithBias( IN PVOID BaseAddress, IN LONGLONG AdditionalBias, - IN PCCH LoaderName, + IN PCCH LoaderName, IN ULONG Success, IN ULONG Conflict, IN ULONG Invalid @@ -229,10 +163,14 @@ LdrRelocateImageWithBias( PIMAGE_NT_HEADERS NtHeaders; PIMAGE_DATA_DIRECTORY RelocationDDir; PIMAGE_BASE_RELOCATION RelocationDir, RelocationEnd; - ULONG Count; - ULONG_PTR Address; + ULONG Count, i; + PVOID Address;//, MaxAddress; PUSHORT TypeOffset; - LONGLONG Delta; + ULONG_PTR Delta; + SHORT Offset; + USHORT Type; + PUSHORT ShortPtr; + PULONG LongPtr; NtHeaders = RtlImageNtHeader(BaseAddress); @@ -254,24 +192,64 @@ LdrRelocateImageWithBias( Delta = (ULONG_PTR)BaseAddress - NtHeaders->OptionalHeader.ImageBase + AdditionalBias; RelocationDir = (PIMAGE_BASE_RELOCATION)((ULONG_PTR)BaseAddress + RelocationDDir->VirtualAddress); RelocationEnd = (PIMAGE_BASE_RELOCATION)((ULONG_PTR)RelocationDir + RelocationDDir->Size); + //MaxAddress = RVA(BaseAddress, DriverSize); while (RelocationDir < RelocationEnd && RelocationDir->SizeOfBlock > 0) { Count = (RelocationDir->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(USHORT); - Address = (ULONG_PTR)RVA(BaseAddress, RelocationDir->VirtualAddress); + Address = RVA(BaseAddress, RelocationDir->VirtualAddress); TypeOffset = (PUSHORT)(RelocationDir + 1); - RelocationDir = LdrProcessRelocationBlockLongLong(Address, - Count, - TypeOffset, - Delta); - - if (RelocationDir == NULL) + for (i = 0; i < Count; i++) { - DPRINT1("Error during call to LdrProcessRelocationBlockLongLong()!\n"); - return Invalid; + Offset = *TypeOffset & 0xFFF; + Type = *TypeOffset >> 12; + ShortPtr = (PUSHORT)(RVA(Address, Offset)); + + /* Don't relocate after the end of the loaded driver */ + /*if ((PVOID)ShortPtr >= MaxAddress) + { + break; + }*/ + + /* + * Don't relocate within the relocation section itself. + * GCC/LD generates sometimes relocation records for the relocation section. + * This is a bug in GCC/LD. + */ + if ((ULONG_PTR)ShortPtr < (ULONG_PTR)RelocationDir || + (ULONG_PTR)ShortPtr >= (ULONG_PTR)RelocationEnd) + { + switch (Type) + { + case IMAGE_REL_BASED_ABSOLUTE: + break; + + case IMAGE_REL_BASED_HIGH: + *ShortPtr += HIWORD(Delta); + break; + + case IMAGE_REL_BASED_LOW: + *ShortPtr += LOWORD(Delta); + break; + + case IMAGE_REL_BASED_HIGHLOW: + LongPtr = (PULONG)ShortPtr; + *LongPtr += Delta; + break; + + case IMAGE_REL_BASED_HIGHADJ: + case IMAGE_REL_BASED_MIPS_JMPADDR: + default: + DPRINT1("Unknown/unsupported fixup type %hu.\n", Type); + DPRINT1("Address %x, Current %d, Count %d, *TypeOffset %x\n", Address, i, Count, *TypeOffset); + return Invalid; + } + } + TypeOffset++; } + RelocationDir = (PIMAGE_BASE_RELOCATION)((ULONG_PTR)RelocationDir + RelocationDir->SizeOfBlock); } return Success; diff --git a/reactos/ntoskrnl/include/internal/po.h b/reactos/ntoskrnl/include/internal/po.h index 6d6ce241f4e..5677d28cc8a 100644 --- a/reactos/ntoskrnl/include/internal/po.h +++ b/reactos/ntoskrnl/include/internal/po.h @@ -1,15 +1,54 @@ -#ifndef __NTOSKRNL_INCLUDE_INTERNAL_PO_H -#define __NTOSKRNL_INCLUDE_INTERNAL_PO_H +/* +* PROJECT: ReactOS Kernel +* LICENSE: GPL - See COPYING in the top level directory +* FILE: ntoskrnl/include/po.h +* PURPOSE: Internal header for the Power Manager +* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) +*/ -extern PDEVICE_NODE PopSystemPowerDeviceNode; +// +// Define this if you want debugging support +// +#define _PO_DEBUG_ 0x00 +// +// These define the Debug Masks Supported +// +#define PO_STATE_DEBUG 0x01 + +// +// Debug/Tracing support +// +#if _PO_DEBUG_ +#ifdef NEW_DEBUG_SYSTEM_IMPLEMENTED // enable when Debug Filters are implemented +#define POTRACE DbgPrintEx +#else +#define POTRACE(x, ...) \ + if (x & PopTraceLevel) DbgPrint(__VA_ARGS__) +#endif +#else +#define POTRACE(x, ...) DPRINT(__VA_ARGS__) +#endif + +// +// Initialization routines +// VOID NTAPI PoInit( - PROS_LOADER_PARAMETER_BLOCK LoaderBlock, + PROS_LOADER_PARAMETER_BLOCK LoaderBlock, BOOLEAN ForceAcpiDisable ); +VOID +NTAPI +PoInitializePrcb( + IN PKPRCB Prcb +); + +// +// Power State routines +// NTSTATUS NTAPI PopSetSystemPowerState( @@ -22,10 +61,7 @@ PopCleanupPowerState( IN PPOWER_STATE PowerState ); -VOID -NTAPI -PoInitializePrcb( - IN PKPRCB Prcb -); - -#endif /* __NTOSKRNL_INCLUDE_INTERNAL_PO_H */ +// +// Global data inside the Power Manager +// +extern PDEVICE_NODE PopSystemPowerDeviceNode; diff --git a/reactos/ntoskrnl/ke/thrdobj.c b/reactos/ntoskrnl/ke/thrdobj.c index 15d94351899..3841656a4a2 100644 --- a/reactos/ntoskrnl/ke/thrdobj.c +++ b/reactos/ntoskrnl/ke/thrdobj.c @@ -697,6 +697,12 @@ KeInitThread(IN OUT PKTHREAD Thread, Thread->StackLimit = (ULONG_PTR)KernelStack - KERNEL_STACK_SIZE; Thread->KernelStackResident = TRUE; + /* ROS Mm HACK */ + MmUpdatePageDir((PEPROCESS)Process, + (PVOID)Thread->StackLimit, + KERNEL_STACK_SIZE); + MmUpdatePageDir((PEPROCESS)Process, (PVOID)Thread, sizeof(ETHREAD)); + /* Enter SEH to avoid crashes due to user mode */ Status = STATUS_SUCCESS; _SEH_TRY diff --git a/reactos/ntoskrnl/ke/thrdschd.c b/reactos/ntoskrnl/ke/thrdschd.c index 9bda109f51f..942530724f8 100644 --- a/reactos/ntoskrnl/ke/thrdschd.c +++ b/reactos/ntoskrnl/ke/thrdschd.c @@ -150,6 +150,8 @@ KiDispatchThreadNoLock(ULONG NewThreadStatus) KiIdleSummary |= Affinity; } + MmUpdatePageDir((PEPROCESS)PsGetCurrentProcess(),((PETHREAD)CurrentThread)->ThreadsProcess, sizeof(EPROCESS)); + /* Special note for Filip: This will release the Dispatcher DB Lock ;-) -- Alex */ DPRINT("You are : %x, swapping to: %x.\n", OldThread, CurrentThread); ApcState = KiSwapContext(OldThread, CurrentThread);