-/* $Id: loader.c,v 1.64 2000/10/08 16:32:53 dwelch Exp $
+/* $Id: loader.c,v 1.74 2001/04/23 22:00:28 ea Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* PROGRAMMERS: Jean Michault
* Rex Jolliff (rex@lvcablemodem.com)
* Jason Filby (jasonfilby@yahoo.com)
+ * Casper S. Hornstrup (chorns@users.sourceforge.net)
* UPDATE HISTORY:
* DW 22/05/98 Created
* RJJ 10/12/98 Completed image loader function and added hooks for MZ/PE
* JM 14/12/98 Built initial PE user module loader
* RJJ 06/03/99 Moved user PE loader into NTDLL
* JF 26/01/2000 Recoded some parts to retrieve export details correctly
- * DW 27/06/00 Removed redundant header files
+ * DW 27/06/2000 Removed redundant header files
+ * CSH 11/04/2001 Added automatic loading of module symbols if they exist
*/
+
/* INCLUDES *****************************************************************/
#include <limits.h>
#include <ddk/ntddk.h>
+#include <internal/config.h>
#include <internal/module.h>
#include <internal/ntoskrnl.h>
#include <internal/mm.h>
-#include <internal/mmhal.h>
#include <internal/ob.h>
#include <internal/ps.h>
-#include <string.h>
-#include <internal/string.h>
+#include <internal/ldr.h>
+#include <internal/pool.h>
#define NDEBUG
#include <internal/debug.h>
LIST_ENTRY ModuleListHead;
POBJECT_TYPE EXPORTED IoDriverObjectType = NULL;
+LIST_ENTRY ModuleTextListHead;
+STATIC MODULE_TEXT_SECTION NtoskrnlTextSection;
+/* STATIC MODULE_TEXT_SECTION HalTextSection; */
-/* FORWARD DECLARATIONS ******************************************************/
+#define TAG_DRIVER_MEM TAG('D', 'R', 'V', 'M')
+#define TAG_SYM_BUF TAG('S', 'Y', 'M', 'B')
-NTSTATUS LdrLoadDriver(PUNICODE_STRING Filename);
-NTSTATUS LdrProcessDriver(PVOID ModuleLoadBase);
+/* FORWARD DECLARATIONS ******************************************************/
PMODULE_OBJECT LdrLoadModule(PUNICODE_STRING Filename);
PMODULE_OBJECT LdrProcessModule(PVOID ModuleLoadBase, PUNICODE_STRING ModuleName);
PVOID Parent,
PWSTR RemainingPath,
POBJECT_ATTRIBUTES ObjectAttributes);
+static VOID LdrpBuildModuleBaseName(PUNICODE_STRING BaseName,
+ PUNICODE_STRING FullName);
/* PE Driver load support */
-static PMODULE_OBJECT LdrPEProcessModule(PVOID ModuleLoadBase, PUNICODE_STRING ModuleName);
+static PMODULE_OBJECT LdrPEProcessModule(PVOID ModuleLoadBase, PUNICODE_STRING FileName);
static PVOID LdrPEGetExportAddress(PMODULE_OBJECT ModuleObject,
char *Name,
unsigned short Hint);
-#if 0
-static unsigned int LdrGetKernelSymbolAddr(char *Name);
-#endif
-static PIMAGE_SECTION_HEADER LdrPEGetEnclosingSectionHeader(DWORD RVA,
- PMODULE_OBJECT ModuleObject);
+static PMODULE_OBJECT LdrPEGetModuleObject(PUNICODE_STRING ModuleName);
+static PVOID LdrPEFixupForward(PCHAR ForwardName);
+
/* FUNCTIONS *****************************************************************/
+VOID
+LdrInitDebug(PLOADER_MODULE Module, PWCH Name)
+{
+ PLIST_ENTRY current_entry;
+ MODULE_TEXT_SECTION* current;
+
+ current_entry = ModuleTextListHead.Flink;
+ while (current_entry != &ModuleTextListHead)
+ {
+ current =
+ CONTAINING_RECORD(current_entry, MODULE_TEXT_SECTION, ListEntry);
+ if (wcscmp(current->Name, Name) == 0)
+ {
+ break;
+ }
+ current_entry = current_entry->Flink;
+ }
+
+ if (current_entry == &ModuleTextListHead)
+ {
+ return;
+ }
+
+ current->SymbolsBase = (PVOID)Module->ModStart;
+ current->SymbolsLength = Module->ModEnd - Module->ModStart;
+}
+
+VOID
+LdrInit1(VOID)
+{
+ PIMAGE_DOS_HEADER DosHeader;
+ PIMAGE_FILE_HEADER FileHeader;
+ PIMAGE_OPTIONAL_HEADER OptionalHeader;
+ PIMAGE_SECTION_HEADER SectionList;
+
+ InitializeListHead(&ModuleTextListHead);
+
+ DosHeader = (PIMAGE_DOS_HEADER) KERNEL_BASE;
+ FileHeader =
+ (PIMAGE_FILE_HEADER) ((DWORD)KERNEL_BASE +
+ DosHeader->e_lfanew + sizeof(ULONG));
+ OptionalHeader = (PIMAGE_OPTIONAL_HEADER)
+ ((DWORD)FileHeader + sizeof(IMAGE_FILE_HEADER));
+ SectionList = (PIMAGE_SECTION_HEADER)
+ ((DWORD)OptionalHeader + sizeof(IMAGE_OPTIONAL_HEADER));
+ NtoskrnlTextSection.Base = KERNEL_BASE;
+ NtoskrnlTextSection.Length = SectionList[0].Misc.VirtualSize +
+ SectionList[0].VirtualAddress;
+ NtoskrnlTextSection.Name = L"ntoskrnl.exe";
+ NtoskrnlTextSection.SymbolsBase = NULL;
+ NtoskrnlTextSection.SymbolsLength = 0;
+ InsertTailList(&ModuleTextListHead, &NtoskrnlTextSection.ListEntry);
+}
+
VOID LdrInitModuleManagement(VOID)
{
HANDLE DirHandle, ModuleHandle;
NTSTATUS Status;
WCHAR NameBuffer[60];
- ANSI_STRING AnsiString;
UNICODE_STRING ModuleName;
OBJECT_ATTRIBUTES ObjectAttributes;
PIMAGE_DOS_HEADER DosHeader;
/* Register the process object type */
IoDriverObjectType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
+ IoDriverObjectType->Tag = TAG('D', 'R', 'V', 'T');
IoDriverObjectType->TotalObjects = 0;
IoDriverObjectType->TotalHandles = 0;
IoDriverObjectType->MaxObjects = ULONG_MAX;
IoDriverObjectType->QueryName = NULL;
IoDriverObjectType->OkayToClose = NULL;
IoDriverObjectType->Create = LdrCreateModule;
- RtlInitAnsiString(&AnsiString, "Module");
- RtlAnsiStringToUnicodeString(&IoDriverObjectType->TypeName, &AnsiString, TRUE);
+ RtlInitUnicodeString(&IoDriverObjectType->TypeName, L"Driver");
/* Create Modules object directory */
wcscpy(NameBuffer, MODULE_ROOT_NAME);
IoDriverObjectType);
assert(ModuleObject != NULL);
- InitializeListHead(&ModuleListHead);
+ InitializeListHead(&ModuleListHead);
+
+ /* Initialize ModuleObject data */
+ ModuleObject->Base = (PVOID) KERNEL_BASE;
+ ModuleObject->Flags = MODULE_FLAG_PE;
+ InsertTailList(&ModuleListHead,
+ &ModuleObject->ListEntry);
+ RtlCreateUnicodeString(&ModuleObject->FullName,
+ L"ntoskrnl.exe");
+ LdrpBuildModuleBaseName(&ModuleObject->BaseName,
+ &ModuleObject->FullName);
- /* Initialize ModuleObject data */
- ModuleObject->Base = (PVOID) KERNEL_BASE;
- ModuleObject->Flags = MODULE_FLAG_PE;
- InsertTailList(&ModuleListHead, &ModuleObject->ListEntry);
- ModuleObject->Name = wcsdup(L"ntoskrnl.exe");
DosHeader = (PIMAGE_DOS_HEADER) KERNEL_BASE;
ModuleObject->Image.PE.FileHeader =
(PIMAGE_FILE_HEADER) ((DWORD) ModuleObject->Base +
}
}
+#ifdef KDBG
+
+BOOLEAN LdrReadLine(PCHAR Line,
+ PVOID *Buffer,
+ PULONG Size)
+{
+ CHAR ch;
+ PCHAR Block;
+
+ if (*Size == 0)
+ return FALSE;
+
+ Block = *Buffer;
+ while ((*Size > 0) && ((ch = *Block) != (CHAR)13))
+ {
+ *Line = ch;
+ Line++;
+ Block++;
+ *Size -= 1;
+ }
+ *Line = (CHAR)0;
+
+ Block++;
+ *Size -= 1;
+
+ if ((*Size > 0) && (*Block == (CHAR)10))
+ {
+ Block++;
+ *Size -= 1;
+ }
+
+ *Buffer = Block;
+
+ return TRUE;
+}
+
+ULONG HexL(PCHAR Buffer)
+{
+ CHAR ch;
+ UINT i, j;
+ ULONG Value;
+
+ j = 32;
+ i = 0;
+ Value = 0;
+ while ((j > 0) && ((ch = Buffer[i]) != ' '))
+ {
+ j -= 4;
+ if ((ch >= '0') && (ch <= '9'))
+ Value |= ((ch - '0') << j);
+ if ((ch >= 'A') && (ch <= 'F'))
+ Value |= ((10 + (ch - 'A')) << j);
+ else
+ if ((ch >= 'a') && (ch <= 'f'))
+ Value |= ((10 + (ch - 'a')) << j);
+ i++;
+ }
+ return Value;
+}
+
+PSYMBOL LdrParseLine(PCHAR Line,
+ PULONG ImageBase,
+ PBOOLEAN ImageBaseValid)
+/*
+ Line format: [ADDRESS] <TYPE> <NAME>
+ TYPE:
+ U = ?
+ A = Image information
+ t = Symbol in text segment
+ T = Symbol in text segment
+ d = Symbol in data segment
+ D = Symbol in data segment
+ b = Symbol in BSS segment
+ B = Symbol in BSS segment
+ ? = Unknown segment or symbol in unknown segment
+*/
+{
+ ANSI_STRING AnsiString;
+ CHAR Buffer[128];
+ PSYMBOL Symbol;
+ ULONG Address;
+ PCHAR Str;
+ CHAR Type;
+
+ *ImageBaseValid = FALSE;
+
+ if ((Line[0] == (CHAR)0) || (Line[0] == ' '))
+ return NULL;
+
+ Address = HexL(Line);
+
+ Line = strchr(Line, ' ');
+ if (Line == NULL)
+ return NULL;
+
+ Line++;
+ Type = *Line;
+
+ Line = strchr(Line, ' ');
+ if (Line == NULL)
+ return NULL;
+
+ Line++;
+ Str = strchr(Line, ' ');
+ if (Str == NULL)
+ strcpy((char*)&Buffer, Line);
+ else
+ strncpy((char*)&Buffer, Line, Str - Line);
+
+ if ((Type == 'A') && (strcmp((char*)&Buffer, "__image_base__")) == 0)
+ {
+ *ImageBase = Address;
+ *ImageBaseValid = TRUE;
+ return NULL;
+ }
+
+ /* We only want symbols in the .text segment */
+ if ((Type != 't') && (Type != 'T'))
+ return NULL;
+
+ /* Discard other symbols we can't use */
+ if ((Buffer[0] != '_') || ((Buffer[0] == '_') && (Buffer[1] == '_')))
+ return NULL;
+
+ Symbol = ExAllocatePool(NonPagedPool, sizeof(SYMBOL));
+ if (!Symbol)
+ return NULL;
+
+ Symbol->Next = NULL;
+
+ Symbol->RelativeAddress = Address;
+
+ RtlInitAnsiString(&AnsiString, (PCSZ)&Buffer);
+ RtlAnsiStringToUnicodeString(&Symbol->Name, &AnsiString, TRUE);
+
+ return Symbol;
+}
+
+VOID LdrLoadModuleSymbols(PMODULE_OBJECT ModuleObject,
+ MODULE_TEXT_SECTION* ModuleTextSection)
+/*
+ Symbols must be sorted by address, e.g.
+ "nm --numeric-sort module.sys > module.sym"
+ */
+{
+ WCHAR TmpFileName[MAX_PATH];
+ LPWSTR Start, Ext;
+ ULONG Length, Tmp;
+ UNICODE_STRING Filename;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ NTSTATUS Status;
+ HANDLE FileHandle;
+ PVOID FileBuffer, FilePtr;
+ CHAR Line[256];
+ FILE_STANDARD_INFORMATION FileStdInfo;
+ BOOLEAN ImageBaseValid;
+ ULONG ImageBase = 0;
+ PSYMBOL Symbol, CurrentSymbol = NULL;
+
+ /* Get the path to the symbol store */
+ wcscpy(TmpFileName, L"\\SystemRoot\\symbols\\");
+
+ /* Get the symbol filename from the module name */
+ Start = wcsrchr(ModuleObject->BaseName.Buffer, L'\\');
+ if (Start == NULL)
+ Start = ModuleObject->BaseName.Buffer;
+ else
+ Start++;
+
+ Ext = wcsrchr(ModuleObject->BaseName.Buffer, L'.');
+ if (Ext != NULL)
+ Length = Ext - Start;
+ else
+ Length = wcslen(Start);
+
+ wcsncat(TmpFileName, Start, Length);
+ wcscat(TmpFileName, L".sym");
+ RtlInitUnicodeString(&Filename, TmpFileName);
+
+ /* Open the file */
+ InitializeObjectAttributes(&ObjectAttributes,
+ &Filename,
+ 0,
+ NULL,
+ NULL);
+
+ Status = ZwOpenFile(&FileHandle,
+ FILE_ALL_ACCESS,
+ &ObjectAttributes,
+ NULL, 0, 0);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("Could not open symbol file: %wZ\n", &Filename);
+ return;
+ }
+
+ DbgPrint("Loading symbols from %wZ...\n", &Filename);
+
+ /* Get the size of the file */
+ Status = ZwQueryInformationFile(FileHandle,
+ NULL,
+ &FileStdInfo,
+ sizeof(FileStdInfo),
+ FileStandardInformation);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("Could not get file size\n");
+ return;
+ }
+
+ /* Allocate nonpageable memory for symbol file */
+ FileBuffer = ExAllocatePool(NonPagedPool,
+ FileStdInfo.EndOfFile.u.LowPart);
+
+ if (FileBuffer == NULL)
+ {
+ DPRINT("Could not allocate memory for symbol file\n");
+ return;
+ }
+
+ /* Load file into memory chunk */
+ Status = ZwReadFile(FileHandle,
+ 0, 0, 0, 0,
+ FileBuffer,
+ FileStdInfo.EndOfFile.u.LowPart,
+ 0, 0);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("Could not read symbol file into memory\n");
+ ExFreePool(FileBuffer);
+ return;
+ }
+
+ ZwClose(FileHandle);
+
+ ModuleTextSection->Symbols.SymbolCount = 0;
+ ModuleTextSection->Symbols.Symbols = NULL;
+
+ FilePtr = FileBuffer;
+ Length = FileStdInfo.EndOfFile.u.LowPart;
+
+ while (LdrReadLine((PCHAR)&Line, &FilePtr, &Length))
+ {
+ Symbol = LdrParseLine((PCHAR)&Line, &Tmp, &ImageBaseValid);
+
+ if (ImageBaseValid)
+ ImageBase = Tmp;
+
+ if (Symbol != NULL)
+ {
+ Symbol->RelativeAddress -= ImageBase;
+
+ if (ModuleTextSection->Symbols.Symbols == NULL)
+ ModuleTextSection->Symbols.Symbols = Symbol;
+ else
+ CurrentSymbol->Next = Symbol;
+
+ CurrentSymbol = Symbol;
+
+ ModuleTextSection->Symbols.SymbolCount++;
+ }
+ }
+
+ ExFreePool(FileBuffer);
+}
+
+#endif /* KDBG */
VOID LdrLoadAutoConfigDrivers (VOID)
{
+
+#ifdef KDBG
+
+ NTSTATUS Status;
+ WCHAR NameBuffer[60];
+ UNICODE_STRING ModuleName;
+ PMODULE_OBJECT ModuleObject;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ UNICODE_STRING RemainingPath;
+
+ /* Load symbols for ntoskrnl.exe and hal.dll because \SystemRoot
+ is created after their module entries */
+
+ wcscpy(NameBuffer, MODULE_ROOT_NAME);
+ wcscat(NameBuffer, L"ntoskrnl.exe");
+ RtlInitUnicodeString(&ModuleName, NameBuffer);
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &ModuleName,
+ 0,
+ NULL,
+ NULL);
+
+ Status = ObFindObject(&ObjectAttributes,
+ (PVOID*)&ModuleObject,
+ &RemainingPath,
+ NULL);
+ if (NT_SUCCESS(Status)) {
+ RtlFreeUnicodeString(&RemainingPath);
+
+ LdrLoadModuleSymbols(ModuleObject, &NtoskrnlTextSection);
+ }
+
+ /* FIXME: Load symbols for hal.dll */
+
+#endif /* KDBG */
+
/*
* Keyboard driver
*/
* Minix filesystem driver
*/
LdrLoadAutoConfigDriver(L"minixfs.sys");
+
+ /*
+ * Networking
+ */
+#if 0
+ /*
+ * NDIS library
+ */
+ LdrLoadAutoConfigDriver(L"ndis.sys");
+
+ /*
+ * Novell Eagle 2000 driver
+ */
+ LdrLoadAutoConfigDriver(L"ne2000.sys");
+
+ /*
+ * TCP/IP protocol driver
+ */
+ LdrLoadAutoConfigDriver(L"tcpip.sys");
+
+ /*
+ * TDI test driver
+ */
+ LdrLoadAutoConfigDriver(L"tditest.sys");
+
+ /*
+ * Ancillary Function Driver
+ */
+ LdrLoadAutoConfigDriver(L"afd.sys");
+#endif
}
OBJECT_ATTRIBUTES ObjectAttributes;
PMODULE_OBJECT ModuleObject;
FILE_STANDARD_INFORMATION FileStdInfo;
- WCHAR NameBuffer[60];
-// PWSTR RemainingPath;
- UNICODE_STRING ModuleName;
/* Check for module already loaded */
if ((ModuleObject = LdrOpenModule(Filename)) != NULL)
CHECKPOINT;
/* Allocate nonpageable memory for driver */
- ModuleLoadBase = ExAllocatePool(NonPagedPool,
- FileStdInfo.EndOfFile.u.LowPart);
+ ModuleLoadBase = ExAllocatePoolWithTag(NonPagedPool,
+ FileStdInfo.EndOfFile.u.LowPart,
+ TAG_DRIVER_MEM);
if (ModuleLoadBase == NULL)
{
NtClose(FileHandle);
- /* Build module object name */
- wcscpy(NameBuffer, MODULE_ROOT_NAME);
- if (wcsrchr(Filename->Buffer, '\\') != 0)
- {
- wcscat(NameBuffer, wcsrchr(Filename->Buffer, '\\') + 1);
- }
- else
- {
- wcscat(NameBuffer, Filename->Buffer);
- }
- RtlInitUnicodeString (&ModuleName, NameBuffer);
-
- ModuleObject = LdrProcessModule(ModuleLoadBase, &ModuleName);
+ ModuleObject = LdrProcessModule(ModuleLoadBase, Filename);
/* Cleanup */
ExFreePool(ModuleLoadBase);
}
NTSTATUS
-LdrProcessDriver(PVOID ModuleLoadBase)
+LdrProcessDriver(PVOID ModuleLoadBase, PCHAR FileName)
{
- PMODULE_OBJECT ModuleObject;
-
- ModuleObject = LdrProcessModule(ModuleLoadBase, 0);
- if (ModuleObject == 0)
- {
- return STATUS_UNSUCCESSFUL;
- }
+ PMODULE_OBJECT ModuleObject;
+ UNICODE_STRING ModuleName;
+
+ RtlCreateUnicodeStringFromAsciiz(&ModuleName,
+ FileName);
+ ModuleObject = LdrProcessModule(ModuleLoadBase,
+ &ModuleName);
+ RtlFreeUnicodeString(&ModuleName);
+ if (ModuleObject == NULL)
+ {
+ DPRINT1("Driver load was unsuccessful\n");
+ return(STATUS_UNSUCCESSFUL);
+ }
- /* FIXME: should we dereference the ModuleObject here? */
+ /* FIXME: should we dereference the ModuleObject here? */
- return IoInitializeDriver(ModuleObject->EntryPoint);
+ return(IoInitializeDriver(ModuleObject->EntryPoint));
}
PMODULE_OBJECT
return LdrPEProcessModule(ModuleLoadBase, ModuleName);
}
+ DPRINT1("Module wasn't PE\n");
return 0;
}
OBJECT_ATTRIBUTES ObjectAttributes;
PMODULE_OBJECT ModuleObject;
UNICODE_STRING RemainingPath;
-// PWSTR RemainingPath;
wcscpy(NameBuffer, MODULE_ROOT_NAME);
if (wcsrchr(Filename->Buffer, '\\') != 0)
}
}
+NTSTATUS
+LdrpQueryModuleInformation(PVOID Buffer,
+ ULONG Size,
+ PULONG ReqSize)
+{
+ PLIST_ENTRY current_entry;
+ PMODULE_OBJECT current;
+ ULONG ModuleCount = 0;
+ PSYSTEM_MODULE_INFORMATION Smi;
+ ANSI_STRING AnsiName;
+ PCHAR p;
+
+// KeAcquireSpinLock(&ModuleListLock,&oldlvl);
+
+ /* calculate required size */
+ current_entry = ModuleListHead.Flink;
+ while (current_entry != (&ModuleListHead))
+ {
+ ModuleCount++;
+ current_entry = current_entry->Flink;
+ }
+
+ *ReqSize = sizeof(SYSTEM_MODULE_INFORMATION)+
+ (ModuleCount - 1) * sizeof(SYSTEM_MODULE_ENTRY);
+
+ if (Size < *ReqSize)
+ {
+// KeReleaseSpinLock(&ModuleListLock,oldlvl);
+ return STATUS_INFO_LENGTH_MISMATCH;
+ }
+
+ /* fill the buffer */
+ memset(Buffer, '=', Size);
+
+ Smi = (PSYSTEM_MODULE_INFORMATION)Buffer;
+ Smi->Count = ModuleCount;
+
+ ModuleCount = 0;
+ current_entry = ModuleListHead.Flink;
+ while (current_entry != (&ModuleListHead))
+ {
+ current = CONTAINING_RECORD(current_entry,MODULE_OBJECT,ListEntry);
+
+ Smi->Module[ModuleCount].Unknown2 = 0; /* Always 0 */
+ Smi->Module[ModuleCount].BaseAddress = current->Base;
+ Smi->Module[ModuleCount].Size = current->Length;
+ Smi->Module[ModuleCount].Flags = 0; /* Flags ??? (GN) */
+ Smi->Module[ModuleCount].EntryIndex = ModuleCount;
+
+ AnsiName.Length = 0;
+ AnsiName.MaximumLength = 256;
+ AnsiName.Buffer = Smi->Module[ModuleCount].Name;
+ RtlUnicodeStringToAnsiString(&AnsiName,
+ ¤t->FullName,
+ FALSE);
+
+ p = strrchr (AnsiName.Buffer, '\\');
+ if (p == NULL)
+ {
+ Smi->Module[ModuleCount].PathLength = 0;
+ Smi->Module[ModuleCount].NameLength = strlen(AnsiName.Buffer);
+ }
+ else
+ {
+ p++;
+ Smi->Module[ModuleCount].PathLength = p - AnsiName.Buffer;
+ Smi->Module[ModuleCount].NameLength = strlen(p);
+ }
+
+ ModuleCount++;
+ current_entry = current_entry->Flink;
+ }
+
+// KeReleaseSpinLock(&ModuleListLock,oldlvl);
+
+ return STATUS_SUCCESS;
+}
+
+
+static VOID
+LdrpBuildModuleBaseName(PUNICODE_STRING BaseName,
+ PUNICODE_STRING FullName)
+{
+ UNICODE_STRING Name;
+ PWCHAR p;
+ PWCHAR q;
+
+ DPRINT("LdrpBuildModuleBaseName()\n");
+ DPRINT("FullName %wZ\n", FullName);
+
+ p = wcsrchr(FullName->Buffer, '\\');
+ if (p == NULL)
+ {
+ p = FullName->Buffer;
+ }
+ else
+ {
+ p++;
+ }
+
+ DPRINT("p %S\n", p);
+
+ RtlCreateUnicodeString(&Name, p);
+
+ q = wcschr(p, '.');
+ if (q != NULL)
+ {
+ *q = (WCHAR)0;
+ }
+
+ DPRINT("p %S\n", p);
+
+ RtlCreateUnicodeString(BaseName, p);
+ RtlFreeUnicodeString(&Name);
+}
+
+
/* ---------------------------------------------- PE Module support */
PMODULE_OBJECT
-LdrPEProcessModule(PVOID ModuleLoadBase, PUNICODE_STRING pModuleName)
+LdrPEProcessModule(PVOID ModuleLoadBase, PUNICODE_STRING FileName)
{
unsigned int DriverSize, Idx, Idx2;
ULONG RelocDelta, NumRelocs;
PIMAGE_FILE_HEADER PEFileHeader;
PIMAGE_OPTIONAL_HEADER PEOptionalHeader;
PIMAGE_SECTION_HEADER PESectionHeaders;
- PIMAGE_EXPORT_DIRECTORY ExportDirectory;
PRELOCATION_DIRECTORY RelocDir;
PRELOCATION_ENTRY RelocEntry;
PMODULE_OBJECT LibraryModuleObject;
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING ModuleName;
WCHAR NameBuffer[60];
+ MODULE_TEXT_SECTION* ModuleTextSection;
DPRINT("Processing PE Module at module base:%08lx\n", ModuleLoadBase);
{
PIMAGE_IMPORT_MODULE_DIRECTORY ImportModuleDirectory;
- SymbolNameBuf = ExAllocatePool(NonPagedPool, 512);
+ SymbolNameBuf = ExAllocatePoolWithTag(NonPagedPool, 512, TAG_SYM_BUF);
/* Process each import module */
ImportModuleDirectory = (PIMAGE_IMPORT_MODULE_DIRECTORY)
}
/* Create ModuleName string */
- if (pModuleName != 0)
+ wcscpy(NameBuffer, MODULE_ROOT_NAME);
+ if (wcsrchr(FileName->Buffer, '\\') != 0)
{
- wcscpy(NameBuffer, pModuleName->Buffer);
+ wcscat(NameBuffer, wcsrchr(FileName->Buffer, '\\') + 1);
}
else
{
- wcscpy(NameBuffer, MODULE_ROOT_NAME);
- if (PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]
- .VirtualAddress != 0)
- {
- ExportDirectory = (PIMAGE_EXPORT_DIRECTORY) (DriverBase +
- PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]
- .VirtualAddress);
- wcscat(NameBuffer, DriverBase + ExportDirectory->Name);
- }
- else
- {
- char buf[12];
-
- sprintf(buf, "%08X", (DWORD) DriverBase);
- for (Idx = 0; NameBuffer[Idx] != 0; Idx++)
- ;
- Idx2 = 0;
- while ((NameBuffer[Idx + Idx2] = (WCHAR) buf[Idx2]) != 0)
- Idx2++;
- }
+ wcscat(NameBuffer, FileName->Buffer);
}
RtlInitUnicodeString (&ModuleName, NameBuffer);
DbgPrint("Module name is: %wZ\n", &ModuleName);
&ObjectAttributes,
IoDriverObjectType);
- /* Initialize ModuleObject data */
- ModuleObject->Base = DriverBase;
- ModuleObject->Flags = MODULE_FLAG_PE;
- InsertTailList(&ModuleListHead, &ModuleObject->ListEntry);
- ModuleObject->Name = wcsdup(NameBuffer);
+ /* Initialize ModuleObject data */
+ ModuleObject->Base = DriverBase;
+ ModuleObject->Flags = MODULE_FLAG_PE;
+ InsertTailList(&ModuleListHead,
+ &ModuleObject->ListEntry);
+ RtlCreateUnicodeString(&ModuleObject->FullName,
+ FileName->Buffer);
+ LdrpBuildModuleBaseName(&ModuleObject->BaseName,
+ &ModuleObject->FullName);
+
ModuleObject->EntryPoint = (PVOID) ((DWORD)DriverBase +
PEOptionalHeader->AddressOfEntryPoint);
ModuleObject->Length = DriverSize;
sizeof(IMAGE_FILE_HEADER) + sizeof(IMAGE_OPTIONAL_HEADER));
DPRINT("SectionList at %x\n", ModuleObject->Image.PE.SectionList);
+ ModuleTextSection = ExAllocatePool(NonPagedPool,
+ sizeof(MODULE_TEXT_SECTION));
+ ModuleTextSection->Base = (ULONG)DriverBase;
+ ModuleTextSection->Length = DriverSize;
+ ModuleTextSection->SymbolsBase = NULL;
+ ModuleTextSection->SymbolsLength = 0;
+ ModuleTextSection->Name =
+ ExAllocatePool(NonPagedPool,
+ (wcslen(NameBuffer) + 1) * sizeof(WCHAR));
+ wcscpy(ModuleTextSection->Name, NameBuffer);
+ InsertTailList(&ModuleTextListHead, &ModuleTextSection->ListEntry);
+
+#ifdef KDBG
+
+ /* Load symbols for module if available */
+ LdrLoadModuleSymbols(ModuleObject, ModuleTextSection);
+
+#endif /* KDBG */
+
return ModuleObject;
}
-static PVOID
+static PVOID
LdrPEGetExportAddress(PMODULE_OBJECT ModuleObject,
char *Name,
unsigned short Hint)
{
WORD Idx;
- DWORD ExportsStartRVA, ExportsEndRVA;
PVOID ExportAddress;
PWORD OrdinalList;
PDWORD FunctionList, NameList;
- PIMAGE_SECTION_HEADER SectionHeader;
- PIMAGE_EXPORT_DIRECTORY ExportDirectory;
-
- ExportsStartRVA = ModuleObject->Image.PE.OptionalHeader->DataDirectory
- [IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
- ExportsEndRVA = ExportsStartRVA +
- ModuleObject->Image.PE.OptionalHeader->DataDirectory
- [IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
-
- /* Get the IMAGE_SECTION_HEADER that contains the exports. This is
- usually the .edata section, but doesn't have to be. */
- SectionHeader = LdrPEGetEnclosingSectionHeader(ExportsStartRVA, ModuleObject);
-
- if (!SectionHeader)
- {
- return 0;
- }
+ PIMAGE_EXPORT_DIRECTORY ExportDir;
+ ULONG ExportDirSize;
+
+ ExportDir = (PIMAGE_EXPORT_DIRECTORY)
+ RtlImageDirectoryEntryToData(ModuleObject->Base,
+ TRUE,
+ IMAGE_DIRECTORY_ENTRY_EXPORT,
+ &ExportDirSize);
+ DPRINT("ExportDir %p ExportDirSize %lx\n", ExportDir, ExportDirSize);
+ if (ExportDir == NULL)
+ {
+ return NULL;
+ }
- ExportDirectory = MakePtr(PIMAGE_EXPORT_DIRECTORY,
- ModuleObject->Base,
- SectionHeader->VirtualAddress);
- FunctionList = (PDWORD)((DWORD)ExportDirectory->AddressOfFunctions + ModuleObject->Base);
- NameList = (PDWORD)((DWORD)ExportDirectory->AddressOfNames + ModuleObject->Base);
- OrdinalList = (PWORD)((DWORD)ExportDirectory->AddressOfNameOrdinals + ModuleObject->Base);
+ FunctionList = (PDWORD)((DWORD)ExportDir->AddressOfFunctions + ModuleObject->Base);
+ NameList = (PDWORD)((DWORD)ExportDir->AddressOfNames + ModuleObject->Base);
+ OrdinalList = (PWORD)((DWORD)ExportDir->AddressOfNameOrdinals + ModuleObject->Base);
ExportAddress = 0;
if (Name != NULL)
{
- for (Idx = 0; Idx < ExportDirectory->NumberOfNames; Idx++)
+ for (Idx = 0; Idx < ExportDir->NumberOfNames; Idx++)
{
#if 0
DPRINT(" Name:%s NameList[%d]:%s\n",
{
ExportAddress = (PVOID) ((DWORD)ModuleObject->Base +
FunctionList[OrdinalList[Idx]]);
+ if (((ULONG)ExportAddress >= (ULONG)ExportDir) &&
+ ((ULONG)ExportAddress < (ULONG)ExportDir + ExportDirSize))
+ {
+ DPRINT("Forward: %s\n", (PCHAR)ExportAddress);
+ ExportAddress = LdrPEFixupForward((PCHAR)ExportAddress);
+ DPRINT("ExportAddress: %p\n", ExportAddress);
+ }
+
break;
}
}
else /* use hint */
{
ExportAddress = (PVOID) ((DWORD)ModuleObject->Base +
- FunctionList[Hint - ExportDirectory->Base]);
- }
- if (ExportAddress == 0)
- {
- DbgPrint("Export not found for %d:%s\n", Hint,
- Name != NULL ? Name : "(Ordinal)");
- KeBugCheck(0);
+ FunctionList[Hint - ExportDir->Base]);
}
- return ExportAddress;
+ if (ExportAddress == 0)
+ {
+ DbgPrint("Export not found for %d:%s\n",
+ Hint,
+ Name != NULL ? Name : "(Ordinal)");
+ KeBugCheck(0);
+ }
+
+ return ExportAddress;
}
-static PIMAGE_SECTION_HEADER
-LdrPEGetEnclosingSectionHeader(DWORD RVA,
- PMODULE_OBJECT ModuleObject)
+
+static PMODULE_OBJECT
+LdrPEGetModuleObject(PUNICODE_STRING ModuleName)
{
- PIMAGE_SECTION_HEADER SectionHeader = SECHDROFFSET(ModuleObject->Base);
- unsigned i;
+ PLIST_ENTRY Entry;
+ PMODULE_OBJECT Module;
- for (i = 0; i < ModuleObject->Image.PE.FileHeader->NumberOfSections;
- i++, SectionHeader++)
- {
- /* Is the RVA within this section? */
- if ((RVA >= SectionHeader->VirtualAddress) &&
- (RVA < (SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize)))
- {
- return SectionHeader;
- }
- }
+ DPRINT("LdrPEGetModuleObject (ModuleName %wZ)\n",
+ ModuleName);
- return 0;
+ Entry = ModuleListHead.Flink;
+
+ while (Entry != &ModuleListHead)
+ {
+ Module = CONTAINING_RECORD(Entry, MODULE_OBJECT, ListEntry);
+
+ DPRINT("Comparing %wZ and %wZ\n",
+ &Module->BaseName,
+ ModuleName);
+
+ if (!RtlCompareUnicodeString(&Module->BaseName, ModuleName, TRUE))
+ {
+ DPRINT("Module %x\n", Module);
+ return Module;
+ }
+
+ Entry = Entry->Flink;
+ }
+
+ DbgPrint("LdrPEGetModuleObject: Failed to find dll %wZ\n", ModuleName);
+
+ return NULL;
+}
+
+
+static PVOID
+LdrPEFixupForward(PCHAR ForwardName)
+{
+ CHAR NameBuffer[128];
+ UNICODE_STRING ModuleName;
+ PCHAR p;
+ PMODULE_OBJECT ModuleObject;
+
+ DPRINT("LdrPEFixupForward (%s)\n", ForwardName);
+
+ strcpy(NameBuffer, ForwardName);
+ p = strchr(NameBuffer, '.');
+ if (p == NULL)
+ {
+ return NULL;
+ }
+
+ *p = 0;
+
+ DPRINT("Driver: %s Function: %s\n", NameBuffer, p+1);
+
+ RtlCreateUnicodeStringFromAsciiz(&ModuleName,
+ NameBuffer);
+ ModuleObject = LdrPEGetModuleObject(&ModuleName);
+ RtlFreeUnicodeString(&ModuleName);
+
+ DPRINT("ModuleObject: %p\n", ModuleObject);
+
+ if (ModuleObject == NULL)
+ {
+ DbgPrint("LdrPEFixupForward: failed to find module %s\n", NameBuffer);
+ return NULL;
+ }
+
+ return LdrPEGetExportAddress(ModuleObject, p+1, 0);
}
+
/* EOF */