Lots of changes to the kernel
[reactos.git] / reactos / ntoskrnl / ldr / loader.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/ldr/loader.c
5 * PURPOSE: Loaders for PE executables
6 * PROGRAMMERS: Jean Michault
7 * Rex Jolliff (rex@lvcablemodem.com)
8 * UPDATE HISTORY:
9 * DW 22/05/98 Created
10 * RJJ 10/12/98 Completed image loader function and added hooks for MZ/PE
11 * RJJ 10/12/98 Built driver loader function and added hooks for PE/COFF
12 * RJJ 10/12/98 Rolled in David's code to load COFF drivers
13 * JM 14/12/98 Built initial PE user module loader
14 * RJJ 06/03/99 Moved user PE loader into NTDLL
15 */
16
17 /* INCLUDES *****************************************************************/
18
19 #include <windows.h>
20
21 #include <internal/i386/segment.h>
22 #include <internal/linkage.h>
23 #include <internal/module.h>
24 #include <internal/ntoskrnl.h>
25 #include <internal/mmhal.h>
26 #include <internal/ob.h>
27 #include <internal/ps.h>
28 #include <string.h>
29 #include <internal/string.h>
30 #include <internal/symbol.h>
31
32 #include <ddk/ntddk.h>
33
34 #define NDEBUG
35 #include <internal/debug.h>
36
37 /* FIXME: this should appear in a kernel header file */
38 NTSTATUS IoInitializeDriver(PDRIVER_INITIALIZE DriverEntry);
39
40 /* MACROS ********************************************************************/
41
42 #define MODULE_ROOT_NAME L"\\Modules\\"
43
44 /* GLOBALS *******************************************************************/
45
46 POBJECT_TYPE ObModuleType = NULL;
47
48 /* FORWARD DECLARATIONS ******************************************************/
49
50 NTSTATUS LdrLoadDriver(PUNICODE_STRING Filename);
51 NTSTATUS LdrProcessDriver(PVOID ModuleLoadBase);
52
53 PMODULE_OBJECT LdrLoadModule(PUNICODE_STRING Filename);
54 PMODULE_OBJECT LdrProcessModule(PVOID ModuleLoadBase);
55 PVOID LdrGetExportAddress(PMODULE_OBJECT ModuleObject, char *Name, unsigned short Hint);
56 static PIMAGE_SECTION_HEADER LdrPEGetEnclosingSectionHeader(DWORD RVA,
57 PMODULE_OBJECT ModuleObject);
58 static NTSTATUS LdrCreateModule(PVOID ObjectBody,
59 PVOID Parent,
60 PWSTR RemainingPath,
61 POBJECT_ATTRIBUTES ObjectAttributes);
62
63 /* PE Driver load support */
64 static PMODULE_OBJECT LdrPEProcessModule(PVOID ModuleLoadBase);
65 static PVOID LdrPEGetExportAddress(PMODULE_OBJECT ModuleObject,
66 char *Name,
67 unsigned short Hint);
68 static unsigned int LdrGetKernelSymbolAddr(char *Name);
69
70 /* COFF Driver load support */
71 static PMODULE_OBJECT LdrCOFFProcessModule(PVOID ModuleLoadBase);
72 static BOOLEAN LdrCOFFDoRelocations(module *Module, unsigned int SectionIndex);
73 static BOOLEAN LdrCOFFDoAddr32Reloc(module *Module, SCNHDR *Section, RELOC *Relocation);
74 static BOOLEAN LdrCOFFDoReloc32Reloc(module *Module, SCNHDR *Section, RELOC *Relocation);
75 static void LdrCOFFGetSymbolName(module *Module, unsigned int Idx, char *Name);
76 static unsigned int LdrCOFFGetSymbolValue(module *Module, unsigned int Idx);
77 static unsigned int LdrCOFFGetSymbolValueByName(module *Module, char *SymbolName, unsigned int Idx);
78
79 /* FUNCTIONS *****************************************************************/
80
81 VOID LdrInitModuleManagement(VOID)
82 {
83 HANDLE DirHandle, ModuleHandle;
84 NTSTATUS Status;
85 WCHAR NameBuffer[60];
86 ANSI_STRING AnsiString;
87 UNICODE_STRING ModuleName;
88 OBJECT_ATTRIBUTES ObjectAttributes;
89 PIMAGE_DOS_HEADER DosHeader;
90 PMODULE_OBJECT ModuleObject;
91
92 /* Register the process object type */
93 ObModuleType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
94 ObModuleType->TotalObjects = 0;
95 ObModuleType->TotalHandles = 0;
96 ObModuleType->MaxObjects = ULONG_MAX;
97 ObModuleType->MaxHandles = ULONG_MAX;
98 ObModuleType->PagedPoolCharge = 0;
99 ObModuleType->NonpagedPoolCharge = sizeof(MODULE);
100 ObModuleType->Dump = NULL;
101 ObModuleType->Open = NULL;
102 ObModuleType->Close = NULL;
103 ObModuleType->Delete = NULL;
104 ObModuleType->Parse = NULL;
105 ObModuleType->Security = NULL;
106 ObModuleType->QueryName = NULL;
107 ObModuleType->OkayToClose = NULL;
108 ObModuleType->Create = LdrCreateModule;
109 RtlInitAnsiString(&AnsiString, "Module");
110 RtlAnsiStringToUnicodeString(&ObModuleType->TypeName, &AnsiString, TRUE);
111
112 /* Create Modules object directory */
113 wcscpy(NameBuffer, MODULE_ROOT_NAME);
114 *(wcsrchr(NameBuffer, L'\\')) = 0;
115 ModuleName.Length = ModuleName.MaximumLength = wcslen(NameBuffer);
116 ModuleName.Buffer = NameBuffer;
117 InitializeObjectAttributes(&ObjectAttributes,
118 &ModuleName,
119 0,
120 NULL,
121 NULL);
122 DPRINT("Create dir: %W\n", &ModuleName);
123 Status = ZwCreateDirectoryObject(&DirHandle, 0, &ObjectAttributes);
124 assert(NT_SUCCESS(Status));
125
126 /* Add module entry for NTOSKRNL */
127 wcscpy(NameBuffer, MODULE_ROOT_NAME);
128 wcscat(NameBuffer, L"ntoskrnl.exe");
129 ModuleName.Length = ModuleName.MaximumLength = wcslen(NameBuffer);
130 ModuleName.Buffer = NameBuffer;
131 DPRINT("Kernel's Module name is: %W\n", &ModuleName);
132
133 /* Initialize ObjectAttributes for ModuleObject */
134 InitializeObjectAttributes(&ObjectAttributes,
135 &ModuleName,
136 0,
137 NULL,
138 NULL);
139
140 /* Create module object */
141 ModuleHandle = 0;
142 ModuleObject = ObCreateObject(&ModuleHandle,
143 STANDARD_RIGHTS_REQUIRED,
144 &ObjectAttributes,
145 ObModuleType);
146 assert(ModuleObject != NULL);
147
148 /* Initialize ModuleObject data */
149 ModuleObject->Base = (PVOID) KERNEL_BASE;
150 ModuleObject->Flags = MODULE_FLAG_PE;
151 DosHeader = (PIMAGE_DOS_HEADER) KERNEL_BASE;
152 ModuleObject->Image.PE.FileHeader =
153 (PIMAGE_FILE_HEADER) ((DWORD) ModuleObject->Base +
154 DosHeader->e_lfanew + sizeof(ULONG));
155 ModuleObject->Image.PE.OptionalHeader = (PIMAGE_OPTIONAL_HEADER)
156 ((DWORD)ModuleObject->Image.PE.FileHeader + sizeof(IMAGE_FILE_HEADER));
157 ModuleObject->Image.PE.SectionList = (PIMAGE_SECTION_HEADER)
158 ((DWORD)ModuleObject->Image.PE.OptionalHeader + sizeof(IMAGE_OPTIONAL_HEADER));
159 ModuleObject->EntryPoint = (PVOID) ((DWORD) ModuleObject->Base +
160 ModuleObject->Image.PE.OptionalHeader->AddressOfEntryPoint);
161 DPRINT("ModuleObject:%08x entrypoint at %x\n", ModuleObject, ModuleObject->EntryPoint);
162
163 /* FIXME: Add fake module entry for HAL */
164
165 }
166
167 static NTSTATUS
168 LdrCreateModule(PVOID ObjectBody,
169 PVOID Parent,
170 PWSTR RemainingPath,
171 POBJECT_ATTRIBUTES ObjectAttributes)
172 {
173 DPRINT("LdrCreateModule(ObjectBody %x, Parent %x, RemainingPath %w)\n",
174 ObjectBody,
175 Parent,
176 RemainingPath);
177 if (RemainingPath != NULL && wcschr(RemainingPath + 1, '\\') != NULL)
178 {
179 return STATUS_UNSUCCESSFUL;
180 }
181 if (Parent != NULL && RemainingPath != NULL)
182 {
183 ObAddEntryDirectory(Parent, ObjectBody, RemainingPath + 1);
184 }
185
186 return STATUS_SUCCESS;
187 }
188
189 /*
190 * load the auto config drivers.
191 */
192 VOID LdrLoadAutoConfigDrivers(VOID)
193 {
194 NTSTATUS Status;
195 ANSI_STRING AnsiDriverName;
196 UNICODE_STRING DriverName;
197
198 RtlInitAnsiString(&AnsiDriverName,"\\??\\C:\\reactos\\system\\drivers\\keyboard.sys");
199 RtlAnsiStringToUnicodeString(&DriverName, &AnsiDriverName, TRUE);
200 Status = LdrLoadDriver(&DriverName);
201 RtlFreeUnicodeString(&DriverName);
202 if (!NT_SUCCESS(Status))
203 {
204 DbgPrint("driver load failed, status;%d(%x)\n", Status, Status);
205 DbgPrintErrorMessage(Status);
206 }
207 RtlInitAnsiString(&AnsiDriverName,"\\??\\C:\\reactos\\system\\drivers\\blue.sys");
208 RtlAnsiStringToUnicodeString(&DriverName, &AnsiDriverName, TRUE);
209 Status = LdrLoadDriver(&DriverName);
210 RtlFreeUnicodeString(&DriverName);
211 if (!NT_SUCCESS(Status))
212 {
213 DbgPrint("driver load failed, status;%d(%x)\n", Status, Status);
214 DbgPrintErrorMessage(Status);
215 }
216
217 }
218
219 /*
220 * FUNCTION: Loads a kernel driver
221 * ARGUMENTS:
222 * FileName = Driver to load
223 * RETURNS: Status
224 */
225
226 NTSTATUS
227 LdrLoadDriver(PUNICODE_STRING Filename)
228 {
229 PMODULE_OBJECT ModuleObject;
230
231 ModuleObject = LdrLoadModule(Filename);
232 if (ModuleObject == 0)
233 {
234 return STATUS_UNSUCCESSFUL;
235 }
236
237 /* FIXME: should we dereference the ModuleObject here? */
238
239 return IoInitializeDriver(ModuleObject->EntryPoint);
240 }
241
242 PMODULE_OBJECT
243 LdrLoadModule(PUNICODE_STRING Filename)
244 {
245 PVOID ModuleLoadBase;
246 NTSTATUS Status;
247 HANDLE FileHandle;
248 OBJECT_ATTRIBUTES ObjectAttributes;
249 PMODULE_OBJECT ModuleObject;
250 FILE_STANDARD_INFORMATION FileStdInfo;
251 WCHAR NameBuffer[60];
252 PWSTR RemainingPath;
253 UNICODE_STRING ModuleName;
254
255 DPRINT("Loading Module %W...\n", Filename);
256
257 /* Check for module already loaded */
258 wcscpy(NameBuffer, MODULE_ROOT_NAME);
259 if (wcsrchr(Filename->Buffer, '\\') != 0)
260 {
261 wcscat(NameBuffer, wcsrchr(Filename->Buffer, '\\') + 1);
262 }
263 else
264 {
265 wcscat(NameBuffer, Filename->Buffer);
266 }
267 ModuleName.Length = ModuleName.MaximumLength = wcslen(NameBuffer);
268 ModuleName.Buffer = NameBuffer;
269 InitializeObjectAttributes(&ObjectAttributes,
270 &ModuleName,
271 0,
272 NULL,
273 NULL);
274 Status = ObFindObject(&ObjectAttributes,
275 (PVOID *) &ModuleObject,
276 &RemainingPath);
277 CHECKPOINT;
278 if (NT_SUCCESS(Status) && *RemainingPath == 0)
279 {
280 return ModuleObject;
281 }
282 CHECKPOINT;
283 if (!wcsncmp(Filename->Buffer, MODULE_ROOT_NAME, wcslen(MODULE_ROOT_NAME)))
284 {
285 return 0;
286 }
287
288 /* Open the Module */
289 InitializeObjectAttributes(&ObjectAttributes,
290 Filename,
291 0,
292 NULL,
293 NULL);
294 CHECKPOINT;
295 Status = ZwOpenFile(&FileHandle,
296 FILE_ALL_ACCESS,
297 &ObjectAttributes,
298 NULL, 0, 0);
299 CHECKPOINT;
300 if (!NT_SUCCESS(Status))
301 {
302 DbgPrint("Could not open module file: %W\n", Filename);
303 return 0;
304 }
305 CHECKPOINT;
306
307 /* Get the size of the file */
308 Status = ZwQueryInformationFile(FileHandle,
309 NULL,
310 &FileStdInfo,
311 sizeof(FileStdInfo),
312 FileStandardInformation);
313 if (!NT_SUCCESS(Status))
314 {
315 DbgPrint("Could not get file size\n");
316 return 0;
317 }
318 CHECKPOINT;
319
320 /* Allocate nonpageable memory for driver */
321 ModuleLoadBase = ExAllocatePool(NonPagedPool,
322 FileStdInfo.EndOfFile.u.LowPart);
323 if (ModuleLoadBase == NULL)
324 {
325 DbgPrint("could not allocate memory for module");
326 return 0;
327 }
328 CHECKPOINT;
329
330 /* Load driver into memory chunk */
331 Status = ZwReadFile(FileHandle,
332 0, 0, 0, 0,
333 ModuleLoadBase,
334 FileStdInfo.EndOfFile.u.LowPart,
335 0, 0);
336 if (!NT_SUCCESS(Status))
337 {
338 DbgPrint("could not read module file into memory");
339 ExFreePool(ModuleLoadBase);
340
341 return 0;
342 }
343 CHECKPOINT;
344
345 ZwClose(FileHandle);
346
347 ModuleObject = LdrProcessModule(ModuleLoadBase);
348
349 /* Cleanup */
350 ExFreePool(ModuleLoadBase);
351
352 return ModuleObject;
353 }
354
355 NTSTATUS
356 LdrProcessDriver(PVOID ModuleLoadBase)
357 {
358 PMODULE_OBJECT ModuleObject;
359
360 ModuleObject = LdrProcessModule(ModuleLoadBase);
361 if (ModuleObject == 0)
362 {
363 return STATUS_UNSUCCESSFUL;
364 }
365
366 /* FIXME: should we dereference the ModuleObject here? */
367
368 return IoInitializeDriver(ModuleObject->EntryPoint);
369 }
370
371 PMODULE_OBJECT
372 LdrProcessModule(PVOID ModuleLoadBase)
373 {
374 PIMAGE_DOS_HEADER PEDosHeader;
375
376 /* If MZ header exists */
377 PEDosHeader = (PIMAGE_DOS_HEADER) ModuleLoadBase;
378 if (PEDosHeader->e_magic == IMAGE_DOS_MAGIC && PEDosHeader->e_lfanew != 0L)
379 {
380 return LdrPEProcessModule(ModuleLoadBase);
381 }
382 #if 0
383 if (PEDosHeader->e_magic == IMAGE_DOS_MAGIC)
384 {
385 return 0;
386 }
387 else /* Assume COFF format and load */
388 {
389 return LdrCOFFProcessModule(ModuleLoadBase);
390 }
391 #endif
392
393 return 0;
394 }
395
396 PVOID
397 LdrGetExportAddress(PMODULE_OBJECT ModuleObject,
398 char *Name,
399 unsigned short Hint)
400 {
401 if (ModuleObject->Flags & MODULE_FLAG_PE)
402 {
403 return LdrPEGetExportAddress(ModuleObject, Name, Hint);
404 }
405 else
406 {
407 return 0;
408 }
409 }
410
411 /* ---------------------------------------------- PE Module support */
412
413 PMODULE_OBJECT
414 LdrPEProcessModule(PVOID ModuleLoadBase)
415 {
416 unsigned int DriverSize, Idx, Idx2;
417 ULONG RelocDelta, NumRelocs;
418 DWORD CurrentSize, TotalRelocs;
419 PVOID DriverBase, CurrentBase;
420 PULONG PEMagic;
421 PIMAGE_DOS_HEADER PEDosHeader;
422 PIMAGE_FILE_HEADER PEFileHeader;
423 PIMAGE_OPTIONAL_HEADER PEOptionalHeader;
424 PIMAGE_SECTION_HEADER PESectionHeaders;
425 PIMAGE_EXPORT_DIRECTORY ExportDirectory;
426 PRELOCATION_DIRECTORY RelocDir;
427 PRELOCATION_ENTRY RelocEntry;
428 PMODULE_OBJECT LibraryModuleObject;
429 HANDLE ModuleHandle;
430 PMODULE_OBJECT ModuleObject;
431 PVOID *ImportAddressList;
432 PULONG FunctionNameList;
433 PCHAR pName, SymbolNameBuf;
434 WORD Hint;
435 OBJECT_ATTRIBUTES ObjectAttributes;
436 UNICODE_STRING ModuleName;
437 WCHAR NameBuffer[60];
438
439 DPRINT("Processing PE Module at module base:%08lx\n", ModuleLoadBase);
440
441 /* Get header pointers */
442 PEDosHeader = (PIMAGE_DOS_HEADER) ModuleLoadBase;
443 PEMagic = (PULONG) ((unsigned int) ModuleLoadBase +
444 PEDosHeader->e_lfanew);
445 PEFileHeader = (PIMAGE_FILE_HEADER) ((unsigned int) ModuleLoadBase +
446 PEDosHeader->e_lfanew + sizeof(ULONG));
447 PEOptionalHeader = (PIMAGE_OPTIONAL_HEADER) ((unsigned int) ModuleLoadBase +
448 PEDosHeader->e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER));
449 PESectionHeaders = (PIMAGE_SECTION_HEADER) ((unsigned int) ModuleLoadBase +
450 PEDosHeader->e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER) +
451 sizeof(IMAGE_OPTIONAL_HEADER));
452 CHECKPOINT;
453
454 /* Check file magic numbers */
455 if (PEDosHeader->e_magic != IMAGE_DOS_MAGIC)
456 {
457 DbgPrint("Incorrect MZ magic: %04x\n", PEDosHeader->e_magic);
458 return 0;
459 }
460 if (PEDosHeader->e_lfanew == 0)
461 {
462 DbgPrint("Invalid lfanew offset: %08x\n", PEDosHeader->e_lfanew);
463 return 0;
464 }
465 if (*PEMagic != IMAGE_PE_MAGIC)
466 {
467 DbgPrint("Incorrect PE magic: %08x\n", *PEMagic);
468 return 0;
469 }
470 if (PEFileHeader->Machine != IMAGE_FILE_MACHINE_I386)
471 {
472 DbgPrint("Incorrect Architechture: %04x\n", PEFileHeader->Machine);
473 return 0;
474 }
475 CHECKPOINT;
476
477 /* FIXME: if image is fixed-address load, then fail */
478
479 /* FIXME: check/verify OS version number */
480
481 DPRINT("OptionalHdrMagic:%04x LinkVersion:%d.%d\n",
482 PEOptionalHeader->Magic,
483 PEOptionalHeader->MajorLinkerVersion,
484 PEOptionalHeader->MinorLinkerVersion);
485 DPRINT("Entry Point:%08lx\n", PEOptionalHeader->AddressOfEntryPoint);
486 CHECKPOINT;
487
488 /* Determine the size of the module */
489
490 DriverSize = PEOptionalHeader->SizeOfImage;
491 DPRINT("DriverSize %x\n",DriverSize);
492
493 /* Allocate a virtual section for the module */
494 DriverBase = MmAllocateSection(DriverSize);
495 if (DriverBase == 0)
496 {
497 DbgPrint("Failed to allocate a virtual section for driver\n");
498 return 0;
499 }
500 CHECKPOINT;
501 DPRINT("Module is at base %x\n",DriverBase);
502
503 /* Copy image sections into virtual section */
504 memcpy(DriverBase, ModuleLoadBase, PESectionHeaders[0].PointerToRawData);
505 CurrentBase = (PVOID) ((DWORD)DriverBase + PESectionHeaders[0].PointerToRawData);
506 CurrentSize = 0;
507 for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++)
508 {
509 /* Copy current section into current offset of virtual section */
510 if (PESectionHeaders[Idx].Characteristics &
511 (IMAGE_SECTION_CHAR_CODE | IMAGE_SECTION_CHAR_DATA))
512 {
513 DPRINT("PESectionHeaders[Idx].VirtualAddress + DriverBase %x\n",
514 PESectionHeaders[Idx].VirtualAddress + DriverBase);
515 memcpy(PESectionHeaders[Idx].VirtualAddress + DriverBase,
516 (PVOID)(ModuleLoadBase + PESectionHeaders[Idx].PointerToRawData),
517 PESectionHeaders[Idx].SizeOfRawData);
518 }
519 else
520 {
521 DPRINT("PESectionHeaders[Idx].VirtualAddress + DriverBase %x\n",
522 PESectionHeaders[Idx].VirtualAddress + DriverBase);
523 memset(PESectionHeaders[Idx].VirtualAddress + DriverBase,
524 '\0', PESectionHeaders[Idx].SizeOfRawData);
525 }
526 CurrentSize += ROUND_UP(PESectionHeaders[Idx].SizeOfRawData,
527 PEOptionalHeader->SectionAlignment);
528 CurrentBase = (PVOID)((DWORD)CurrentBase +
529 ROUND_UP(PESectionHeaders[Idx].SizeOfRawData,
530 PEOptionalHeader->SectionAlignment));
531 }
532
533 /* Perform relocation fixups */
534 RelocDelta = (DWORD) DriverBase - PEOptionalHeader->ImageBase;
535 RelocDir = (PRELOCATION_DIRECTORY)(PEOptionalHeader->DataDirectory[
536 IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
537 DPRINT("DrvrBase:%08lx ImgBase:%08lx RelocDelta:%08lx\n",
538 DriverBase,
539 PEOptionalHeader->ImageBase,
540 RelocDelta);
541 DPRINT("RelocDir %x\n",RelocDir);
542 for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++)
543 {
544 if (PESectionHeaders[Idx].VirtualAddress == (DWORD)RelocDir)
545 {
546 DPRINT("Name %.8s PESectionHeader[Idx].PointerToRawData %x\n",
547 PESectionHeaders[Idx].Name,
548 PESectionHeaders[Idx].PointerToRawData);
549 RelocDir = PESectionHeaders[Idx].PointerToRawData +
550 ModuleLoadBase;
551 CurrentSize = PESectionHeaders[Idx].Misc.VirtualSize;
552 break;
553 }
554 }
555 DPRINT("RelocDir %08lx CurrentSize %08lx\n", RelocDir, CurrentSize);
556 TotalRelocs = 0;
557 while (TotalRelocs < CurrentSize && RelocDir->SizeOfBlock != 0)
558 {
559 NumRelocs = (RelocDir->SizeOfBlock - sizeof(RELOCATION_DIRECTORY)) /
560 sizeof(WORD);
561 /* DPRINT("RelocDir at %08lx for VA %08lx with %08lx relocs\n",
562 RelocDir,
563 RelocDir->VirtualAddress,
564 NumRelocs);*/
565 RelocEntry = (PRELOCATION_ENTRY) ((DWORD)RelocDir +
566 sizeof(RELOCATION_DIRECTORY));
567 for (Idx = 0; Idx < NumRelocs; Idx++)
568 {
569 ULONG Offset;
570 ULONG Type;
571 PDWORD RelocItem;
572
573 Offset = RelocEntry[Idx].TypeOffset & 0xfff;
574 Type = (RelocEntry[Idx].TypeOffset >> 12) & 0xf;
575 RelocItem = (PDWORD)(DriverBase + RelocDir->VirtualAddress +
576 Offset);
577 /* DPRINT(" reloc at %08lx %x %s old:%08lx new:%08lx\n",
578 RelocItem,
579 Type,
580 Type ? "HIGHLOW" : "ABS",
581 *RelocItem,
582 (*RelocItem) + RelocDelta); */
583 if (Type == 3)
584 {
585 (*RelocItem) += RelocDelta;
586 }
587 else if (Type != 0)
588 {
589 DbgPrint("Unknown relocation type %x\n",Type);
590 return 0;
591 }
592 }
593 TotalRelocs += RelocDir->SizeOfBlock;
594 RelocDir = (PRELOCATION_DIRECTORY)((DWORD)RelocDir +
595 RelocDir->SizeOfBlock);
596 // DPRINT("TotalRelocs: %08lx CurrentSize: %08lx\n", TotalRelocs, CurrentSize);
597 }
598
599 DPRINT("PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] %x\n",
600 PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]
601 .VirtualAddress);
602 /* Perform import fixups */
603 if (PEOptionalHeader->DataDirectory[
604 IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)
605 {
606 PIMAGE_IMPORT_MODULE_DIRECTORY ImportModuleDirectory;
607
608 SymbolNameBuf = ExAllocatePool(NonPagedPool, 512);
609
610 /* Process each import module */
611 ImportModuleDirectory = (PIMAGE_IMPORT_MODULE_DIRECTORY)
612 ((DWORD)DriverBase + PEOptionalHeader->
613 DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
614 DPRINT("Processeing import directory at %p\n", ImportModuleDirectory);
615 while (ImportModuleDirectory->dwRVAModuleName)
616 {
617 /* Check to make sure that import lib is kernel */
618 pName = (PCHAR) DriverBase +
619 ImportModuleDirectory->dwRVAModuleName;
620 if (!strcmp(pName, "ntoskrnl.exe") || !strcmp(pName, "HAL.dll"))
621 {
622 LibraryModuleObject = NULL;
623 DPRINT("Kernel imports\n");
624 }
625 else
626 {
627 wcscpy(NameBuffer, MODULE_ROOT_NAME);
628 for (Idx = 0; NameBuffer[Idx] != 0; Idx++)
629 ;
630 for (Idx2 = 0; pName[Idx2] != '\0'; Idx2++)
631 {
632 NameBuffer[Idx + Idx2] = (WCHAR) pName[Idx2];
633 }
634 NameBuffer[Idx + Idx2] = 0;
635 ModuleName.Length = ModuleName.MaximumLength = wcslen(NameBuffer);
636 ModuleName.Buffer = NameBuffer;
637 DPRINT("Import module: %W\n", &ModuleName);
638 LibraryModuleObject = LdrLoadModule(&ModuleName);
639 if (LibraryModuleObject == 0)
640 {
641 DbgPrint("Unknown import module: %W\n", &ModuleName);
642 }
643 }
644 /* Get the import address list */
645 ImportAddressList = (PVOID *) ((DWORD)DriverBase +
646 ImportModuleDirectory->dwRVAFunctionAddressList);
647
648 /* Get the list of functions to import */
649 if (ImportModuleDirectory->dwRVAFunctionNameList != 0)
650 {
651 FunctionNameList = (PULONG) ((DWORD)DriverBase +
652 ImportModuleDirectory->dwRVAFunctionNameList);
653 }
654 else
655 {
656 FunctionNameList = (PULONG) ((DWORD)DriverBase +
657 ImportModuleDirectory->dwRVAFunctionAddressList);
658 }
659 /* Walk through function list and fixup addresses */
660 while (*FunctionNameList != 0L)
661 {
662 if ((*FunctionNameList) & 0x80000000) // hint
663 {
664 pName = NULL;
665 Hint = (*FunctionNameList) & 0xffff;
666 }
667 else // hint-name
668 {
669 pName = (PCHAR)((DWORD)DriverBase +
670 *FunctionNameList + 2);
671 Hint = *(PWORD)((DWORD)DriverBase + *FunctionNameList);
672 }
673 DPRINT(" Hint:%04x Name:%s\n", Hint, pName);
674
675 /* Fixup the current import symbol */
676 if (LibraryModuleObject != NULL)
677 {
678 *ImportAddressList = LdrGetExportAddress(LibraryModuleObject,
679 pName,
680 Hint);
681 }
682 else
683 {
684 /* Get address for symbol */
685 *SymbolNameBuf = '_';
686 strcpy(SymbolNameBuf + 1, pName);
687 *ImportAddressList = (PVOID) LdrGetKernelSymbolAddr(SymbolNameBuf);
688 if (*ImportAddressList == 0L)
689 {
690 DbgPrint("Unresolved kernel symbol: %s\n", pName);
691 }
692 }
693 ImportAddressList++;
694 FunctionNameList++;
695 }
696 ImportModuleDirectory++;
697 }
698
699 ExFreePool(SymbolNameBuf);
700 }
701
702 /* Create ModuleName string */
703 wcscpy(NameBuffer, MODULE_ROOT_NAME);
704 if (PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]
705 .VirtualAddress != 0)
706 {
707 ExportDirectory = (PIMAGE_EXPORT_DIRECTORY) (DriverBase +
708 PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]
709 .VirtualAddress);
710 wcscat(NameBuffer, DriverBase + ExportDirectory->Name);
711 }
712 else
713 {
714 char buf[12];
715
716 sprintf(buf, "%08X", (DWORD) DriverBase);
717 for (Idx = 0; NameBuffer[Idx] != 0; Idx++)
718 ;
719 Idx2 = 0;
720 while ((NameBuffer[Idx + Idx2] = (WCHAR) buf[Idx2]) != 0)
721 Idx2++;
722 }
723 ModuleName.Length = ModuleName.MaximumLength = wcslen(NameBuffer);
724 ModuleName.Buffer = NameBuffer;
725 DPRINT("Module name is: %W\n", &ModuleName);
726
727 /* Initialize ObjectAttributes for ModuleObject */
728 InitializeObjectAttributes(&ObjectAttributes,
729 &ModuleName,
730 0,
731 NULL,
732 NULL);
733
734 /* Create module object */
735 ModuleHandle = 0;
736 ModuleObject = ObCreateObject(&ModuleHandle,
737 STANDARD_RIGHTS_REQUIRED,
738 &ObjectAttributes,
739 ObModuleType);
740
741 /* Initialize ModuleObject data */
742 ModuleObject->Base = DriverBase;
743 ModuleObject->Flags = MODULE_FLAG_PE;
744 ModuleObject->EntryPoint = (PVOID) ((DWORD)DriverBase +
745 PEOptionalHeader->AddressOfEntryPoint);
746 DPRINT("entrypoint at %x\n", ModuleObject->EntryPoint);
747 ModuleObject->Image.PE.FileHeader =
748 (PIMAGE_FILE_HEADER) ((unsigned int) DriverBase +
749 PEDosHeader->e_lfanew + sizeof(ULONG));
750 DPRINT("FileHeader at %x\n", ModuleObject->Image.PE.FileHeader);
751 ModuleObject->Image.PE.OptionalHeader =
752 (PIMAGE_OPTIONAL_HEADER) ((unsigned int) DriverBase +
753 PEDosHeader->e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER));
754 DPRINT("OptionalHeader at %x\n", ModuleObject->Image.PE.OptionalHeader);
755 ModuleObject->Image.PE.SectionList =
756 (PIMAGE_SECTION_HEADER) ((unsigned int) DriverBase +
757 PEDosHeader->e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER) +
758 sizeof(IMAGE_OPTIONAL_HEADER));
759 DPRINT("SectionList at %x\n", ModuleObject->Image.PE.SectionList);
760
761 return ModuleObject;
762 }
763
764 static PVOID
765 LdrPEGetExportAddress(PMODULE_OBJECT ModuleObject,
766 char *Name,
767 unsigned short Hint)
768 {
769 WORD Idx;
770 DWORD ExportsStartRVA, ExportsEndRVA, Delta;
771 PVOID ExportAddress;
772 PWORD OrdinalList;
773 PDWORD FunctionList, NameList;
774 PIMAGE_SECTION_HEADER SectionHeader;
775 PIMAGE_EXPORT_DIRECTORY ExportDirectory;
776
777 ExportsStartRVA = ModuleObject->Image.PE.OptionalHeader->DataDirectory
778 [IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
779 ExportsEndRVA = ExportsStartRVA +
780 ModuleObject->Image.PE.OptionalHeader->DataDirectory
781 [IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
782 /* Get the IMAGE_SECTION_HEADER that contains the exports. This is
783 usually the .edata section, but doesn't have to be. */
784 SectionHeader = LdrPEGetEnclosingSectionHeader(ExportsStartRVA, ModuleObject);
785 if (!SectionHeader)
786 {
787 return 0;
788 }
789 Delta = (DWORD)(SectionHeader->VirtualAddress -
790 SectionHeader->PointerToRawData);
791 ExportDirectory = MakePtr(PIMAGE_EXPORT_DIRECTORY,
792 ModuleObject->Base,
793 ExportsStartRVA - Delta);
794
795 FunctionList = (PDWORD)((DWORD)ExportDirectory->AddressOfFunctions -
796 Delta + ModuleObject->Base);
797 NameList = (PDWORD)((DWORD)ExportDirectory->AddressOfNames -
798 Delta + ModuleObject->Base);
799 OrdinalList = (PWORD)((DWORD)ExportDirectory->AddressOfNameOrdinals -
800 Delta + ModuleObject->Base);
801 DPRINT("Delta:%08x\n", Delta);
802 DPRINT("Func:%08x RVA:%08x Name:%08x RVA:%08x Ord:%08x RVA:%08x\n", FunctionList,
803 ExportDirectory->AddressOfFunctions, NameList,
804 ExportDirectory->AddressOfNames, OrdinalList,
805 ExportDirectory->AddressOfNameOrdinals);
806 DPRINT("NumNames:%d NumFuncs:%d\n", ExportDirectory->NumberOfNames,
807 ExportDirectory->NumberOfFunctions);
808 for(;;);
809 ExportAddress = 0;
810 if (Name != NULL)
811 {
812 for (Idx = 0; Idx < ExportDirectory->NumberOfNames; Idx++)
813 {
814 DPRINT(" Name:%s NameList[%d]:%s\n", Name, Idx, NameList[Idx]);
815 if (!strcmp(Name, (PCHAR) ((DWORD)ModuleObject->Base + NameList[Idx])))
816 {
817 ExportAddress = (PVOID) ((DWORD)ModuleObject->Base +
818 FunctionList[OrdinalList[Idx]]);
819 break;
820 }
821 }
822 }
823 else /* use hint */
824 {
825 ExportAddress = (PVOID) ((DWORD)ModuleObject->Base +
826 FunctionList[Hint - ExportDirectory->Base]);
827 }
828 if (ExportAddress == 0)
829 {
830 DbgPrint("Export not found for %d:%s\n", Hint, Name != NULL ? Name : "(Ordinal)");
831 }
832
833 return ExportAddress;
834 }
835
836 static PIMAGE_SECTION_HEADER
837 LdrPEGetEnclosingSectionHeader(DWORD RVA,
838 PMODULE_OBJECT ModuleObject)
839 {
840 PIMAGE_SECTION_HEADER SectionHeader = SECHDROFFSET(ModuleObject->Base);
841 unsigned i;
842
843 for (i = 0; i < ModuleObject->Image.PE.FileHeader->NumberOfSections;
844 i++, SectionHeader++)
845 {
846 /* Is the RVA within this section? */
847 if ((RVA >= SectionHeader->VirtualAddress) &&
848 (RVA < (SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize)))
849 {
850 return SectionHeader;
851 }
852 }
853
854 return 0;
855 }
856
857 /* ------------------------------------------- COFF Module support */
858
859 PMODULE_OBJECT
860 LdrCOFFProcessModule(PVOID ModuleLoadBase)
861 {
862 BOOLEAN FoundEntry;
863 char SymbolName[255];
864 int i;
865 ULONG EntryOffset;
866 FILHDR *FileHeader;
867 AOUTHDR *AOUTHeader;
868 module *Module;
869 PVOID EntryRoutine;
870 HANDLE ModuleHandle;
871 PMODULE_OBJECT ModuleObject;
872 OBJECT_ATTRIBUTES ObjectAttributes;
873 UNICODE_STRING ModuleName;
874 WCHAR NameBuffer[60];
875
876 /* Get header pointers */
877 FileHeader = ModuleLoadBase;
878 AOUTHeader = ModuleLoadBase + FILHSZ;
879 CHECKPOINT;
880
881 /* Check COFF magic value */
882 if (I386BADMAG(*FileHeader))
883 {
884 DbgPrint("Module has bad magic value (%x)\n",
885 FileHeader->f_magic);
886 return 0;
887 }
888 CHECKPOINT;
889
890 /* Allocate and initialize a module definition structure */
891 Module = (module *) ExAllocatePool(NonPagedPool, sizeof(module));
892 if (Module == NULL)
893 {
894 return 0;
895 }
896 Module->sym_list = (SYMENT *)(ModuleLoadBase + FileHeader->f_symptr);
897 Module->str_tab = (char *)(ModuleLoadBase + FileHeader->f_symptr +
898 FileHeader->f_nsyms * SYMESZ);
899 Module->scn_list = (SCNHDR *)(ModuleLoadBase + FILHSZ +
900 FileHeader->f_opthdr);
901 Module->size = 0;
902 Module->raw_data_off = (ULONG) ModuleLoadBase;
903 Module->nsyms = FileHeader->f_nsyms;
904 CHECKPOINT;
905
906 /* Determine the length of the module */
907 for (i = 0; i < FileHeader->f_nscns; i++)
908 {
909 DPRINT("Section name: %.8s\n", Module->scn_list[i].s_name);
910 DPRINT("size %x vaddr %x size %x\n",
911 Module->size,
912 Module->scn_list[i].s_vaddr,
913 Module->scn_list[i].s_size);
914 if (Module->scn_list[i].s_flags & STYP_TEXT)
915 {
916 Module->text_base = Module->scn_list[i].s_vaddr;
917 }
918 if (Module->scn_list[i].s_flags & STYP_DATA)
919 {
920 Module->data_base = Module->scn_list[i].s_vaddr;
921 }
922 if (Module->scn_list[i].s_flags & STYP_BSS)
923 {
924 Module->bss_base = Module->scn_list[i].s_vaddr;
925 }
926 if (Module->size <
927 (Module->scn_list[i].s_vaddr + Module->scn_list[i].s_size))
928 {
929 Module->size = Module->size + Module->scn_list[i].s_vaddr +
930 Module->scn_list[i].s_size;
931 }
932 }
933 CHECKPOINT;
934
935 /* Allocate a section for the module */
936 Module->base = (unsigned int) MmAllocateSection(Module->size);
937 if (Module->base == 0)
938 {
939 DbgPrint("Failed to alloc section for module\n");
940 ExFreePool(Module);
941 return 0;
942 }
943 CHECKPOINT;
944
945 /* Adjust section vaddrs for allocated area */
946 Module->data_base = Module->data_base + Module->base;
947 Module->text_base = Module->text_base + Module->base;
948 Module->bss_base = Module->bss_base + Module->base;
949
950 /* Relocate module and fixup imports */
951 for (i = 0; i < FileHeader->f_nscns; i++)
952 {
953 if (Module->scn_list[i].s_flags & STYP_TEXT ||
954 Module->scn_list[i].s_flags & STYP_DATA)
955 {
956 memcpy((PVOID)(Module->base + Module->scn_list[i].s_vaddr),
957 (PVOID)(ModuleLoadBase + Module->scn_list[i].s_scnptr),
958 Module->scn_list[i].s_size);
959 if (!LdrCOFFDoRelocations(Module, i))
960 {
961 DbgPrint("Relocation failed for section %s\n",
962 Module->scn_list[i].s_name);
963
964 /* FIXME: unallocate all sections here */
965
966 ExFreePool(Module);
967
968 return 0;
969 }
970 }
971 if (Module->scn_list[i].s_flags & STYP_BSS)
972 {
973 memset((PVOID)(Module->base + Module->scn_list[i].s_vaddr),
974 0,
975 Module->scn_list[i].s_size);
976 }
977 }
978
979 DPRINT("Module base: %x\n", Module->base);
980
981 /* Find the entry point */
982 EntryOffset = 0L;
983 FoundEntry = FALSE;
984 for (i = 0; i < FileHeader->f_nsyms; i++)
985 {
986 LdrCOFFGetSymbolName(Module, i, SymbolName);
987 if (!strcmp(SymbolName, "_DriverEntry"))
988 {
989 EntryOffset = Module->sym_list[i].e_value;
990 FoundEntry = TRUE;
991 DPRINT("Found entry at %x\n", EntryOffset);
992 }
993 }
994 if (!FoundEntry)
995 {
996 DbgPrint("No module entry point defined\n");
997 ExFreePool(Module);
998
999 /* FIXME: unallocate all sections here */
1000
1001 return 0;
1002 }
1003
1004 /* Get the address of the module initalization routine */
1005 EntryRoutine = (PVOID)(Module->base + EntryOffset);
1006
1007 /* Create ModuleName string */
1008 wcscpy(NameBuffer, MODULE_ROOT_NAME);
1009 /* FIXME: someone who is interested needs to fix this. */
1010 wcscat(NameBuffer, L"BOGUS.o");
1011 ModuleName.Length = ModuleName.MaximumLength = wcslen(NameBuffer);
1012 ModuleName.Buffer = NameBuffer;
1013 DPRINT("Module name is: %w", NameBuffer);
1014
1015 /* Initialize ObjectAttributes for ModuleObject */
1016 InitializeObjectAttributes(&ObjectAttributes,
1017 &ModuleName,
1018 0,
1019 NULL,
1020 NULL);
1021
1022 /* Create module object */
1023 ModuleHandle = 0;
1024 ModuleObject = ObCreateObject(&ModuleHandle,
1025 OBJECT_TYPE_ALL_ACCESS,
1026 &ObjectAttributes,
1027 ObModuleType);
1028
1029 /* Initialize ModuleObject data */
1030 ModuleObject->Base = (PVOID) Module->base;
1031 ModuleObject->Flags = MODULE_FLAG_COFF;
1032 ModuleObject->EntryPoint = (PVOID) (Module->base + EntryOffset);
1033 DPRINT("entrypoint at %x\n", ModuleObject->EntryPoint);
1034 /* FIXME: the COFF headers need to be copied into the module
1035 space, and the ModuleObject needs to be set to point to them */
1036
1037 /* Cleanup */
1038 ExFreePool(Module);
1039
1040 return ModuleObject;
1041 }
1042
1043 /* LdrCOFFDoRelocations
1044 * FUNCTION: Do the relocations for a module section
1045 * ARGUMENTS:
1046 * Module = Pointer to the module
1047 * SectionIndex = Index of the section to be relocated
1048 * RETURNS: Success or failure
1049 */
1050
1051 static BOOLEAN
1052 LdrCOFFDoRelocations(module *Module, unsigned int SectionIndex)
1053 {
1054 SCNHDR *Section = &Module->scn_list[SectionIndex];
1055 RELOC *Relocation = (RELOC *)(Module->raw_data_off + Section->s_relptr);
1056 int j;
1057
1058 DPRINT("SectionIndex %d Name %.8s Relocs %d\n",
1059 SectionIndex,
1060 Module->scn_list[SectionIndex].s_name,
1061 Section->s_nreloc);
1062
1063 for (j = 0; j < Section->s_nreloc; j++)
1064 {
1065 DPRINT("vaddr %x symndex %x",
1066 Relocation->r_vaddr,
1067 Relocation->r_symndx);
1068
1069 switch (Relocation->r_type)
1070 {
1071 case RELOC_ADDR32:
1072 if (!LdrCOFFDoAddr32Reloc(Module, Section, Relocation))
1073 {
1074 return FALSE;
1075 }
1076 break;
1077
1078 case RELOC_REL32:
1079 if (!LdrCOFFDoReloc32Reloc(Module, Section, Relocation))
1080 {
1081 return FALSE;
1082 }
1083 break;
1084
1085 default:
1086 DbgPrint("%.8s: Unknown relocation type %x at %d in module\n",
1087 Module->scn_list[SectionIndex].s_name,
1088 Relocation->r_type,
1089 j);
1090 return FALSE;
1091 }
1092 Relocation++;
1093 }
1094 DPRINT("%.8s: relocations done\n", Module->scn_list[SectionIndex].s_name);
1095
1096 return TRUE;
1097 }
1098
1099 /*
1100 * FUNCTION: Performs a addr32 relocation on a loaded module
1101 * ARGUMENTS:
1102 * mod = module to perform the relocation on
1103 * scn = Section to perform the relocation in
1104 * reloc = Pointer to a data structure describing the relocation
1105 * RETURNS: Success or failure
1106 * NOTE: This fixes up a relocation needed when changing the base address of a
1107 * module
1108 */
1109
1110 static BOOLEAN
1111 LdrCOFFDoAddr32Reloc(module *Module, SCNHDR *Section, RELOC *Relocation)
1112 {
1113 unsigned int Value;
1114 unsigned int *Location;
1115
1116 Value = LdrCOFFGetSymbolValue(Module, Relocation->r_symndx);
1117 Location = (unsigned int *)(Module->base + Relocation->r_vaddr);
1118 DPRINT("ADDR32 loc %x value %x *loc %x\n", Location, Value, *Location);
1119 *Location = (*Location) + Module->base;
1120
1121 return TRUE;
1122 }
1123
1124 /*
1125 * FUNCTION: Performs a reloc32 relocation on a loaded module
1126 * ARGUMENTS:
1127 * mod = module to perform the relocation on
1128 * scn = Section to perform the relocation in
1129 * reloc = Pointer to a data structure describing the relocation
1130 * RETURNS: Success or failure
1131 * NOTE: This fixes up an undefined reference to a kernel function in a module
1132 */
1133
1134 static BOOLEAN
1135 LdrCOFFDoReloc32Reloc(module *Module, SCNHDR *Section, RELOC *Relocation)
1136 {
1137 char Name[255];
1138 unsigned int Value;
1139 unsigned int *Location;
1140
1141 memset(Name, 0, 255);
1142 LdrCOFFGetSymbolName(Module, Relocation->r_symndx, Name);
1143 Value = (unsigned int) LdrGetKernelSymbolAddr(Name);
1144 if (Value == 0L)
1145 {
1146 Value = LdrCOFFGetSymbolValueByName(Module, Name, Relocation->r_symndx);
1147 if (Value == 0L)
1148 {
1149 DbgPrint("Undefined symbol %s in module\n", Name);
1150 return FALSE;
1151 }
1152 Location = (unsigned int *)(Module->base + Relocation->r_vaddr);
1153 // (*Location) = (*Location) + Value + Module->base - Section->s_vaddr;
1154 (*Location) = (*Location);
1155 DPRINT("Module->base %x Section->s_vaddr %x\n",
1156 Module->base,
1157 Section->s_vaddr);
1158 }
1159 else
1160 {
1161 DPRINT("REL32 value %x name %s\n", Value, Name);
1162 Location = (unsigned int *)(Module->base + Relocation->r_vaddr);
1163 DPRINT("old %x ", *Location);
1164 DPRINT("Module->base %x Section->s_vaddr %x\n",
1165 Module->base,
1166 Section->s_vaddr);
1167 (*Location) = (*Location) + Value - Module->base + Section->s_vaddr;
1168 DPRINT("new %x\n", *Location);
1169 }
1170
1171 return TRUE;
1172 }
1173
1174 /*
1175 * FUNCTION: Get the name of a symbol from a loaded module by ordinal
1176 * ARGUMENTS:
1177 * mod = module
1178 * i = index of symbol
1179 * name (OUT) = pointer to a string where the symbol name will be
1180 * stored
1181 */
1182
1183 static void
1184 LdrCOFFGetSymbolName(module *Module, unsigned int Idx, char *Name)
1185 {
1186 if (Module->sym_list[Idx].e.e_name[0] != 0)
1187 {
1188 strncpy(Name, Module->sym_list[Idx].e.e_name, 8);
1189 Name[8] = '\0';
1190 }
1191 else
1192 {
1193 strcpy(Name, &Module->str_tab[Module->sym_list[Idx].e.e.e_offset]);
1194 }
1195 }
1196
1197 /*
1198 * FUNCTION: Get the value of a module defined symbol
1199 * ARGUMENTS:
1200 * mod = module
1201 * i = index of symbol
1202 * RETURNS: The value of the symbol
1203 * NOTE: This fixes up references to known sections
1204 */
1205
1206 static unsigned int
1207 LdrCOFFGetSymbolValue(module *Module, unsigned int Idx)
1208 {
1209 char Name[255];
1210
1211 LdrCOFFGetSymbolName(Module, Idx, Name);
1212 DPRINT("name %s ", Name);
1213
1214 /* Check if the symbol is a section we have relocated */
1215 if (strcmp(Name, ".text") == 0)
1216 {
1217 return Module->text_base;
1218 }
1219 if (strcmp(Name, ".data") == 0)
1220 {
1221 return Module->data_base;
1222 }
1223 if (strcmp(Name, ".bss") == 0)
1224 {
1225 return Module->bss_base;
1226 }
1227
1228 return Module->sym_list[Idx].e_value;
1229 }
1230
1231 /*
1232 * FUNCTION: Get the address of a kernel symbol
1233 * ARGUMENTS:
1234 * name = symbol name
1235 * RETURNS: The address of the symbol on success
1236 * NULL on failure
1237 */
1238
1239 static unsigned int
1240 LdrGetKernelSymbolAddr(char *Name)
1241 {
1242 int i = 0;
1243 char* s;
1244
1245 if ((s=strchr(Name,'@'))!=NULL)
1246 {
1247 *s=0;
1248 DPRINT("Name %s ",Name);
1249 }
1250 while (symbol_table[i].name != NULL)
1251 {
1252 if (strcmp(symbol_table[i].name, Name) == 0)
1253 {
1254 if (s!=NULL)
1255 {
1256 *s=0;
1257 DPRINT("Matched with %s\n",symbol_table[i].name);
1258 }
1259 return symbol_table[i].value;
1260 }
1261 i++;
1262 }
1263 if (s!=NULL)
1264 {
1265 *s=0;
1266 }
1267 return 0L;
1268 }
1269
1270 static unsigned int
1271 LdrCOFFGetSymbolValueByName(module *Module,
1272 char *SymbolName,
1273 unsigned int Idx)
1274 {
1275 unsigned int i;
1276 char Name[255];
1277
1278 DPRINT("LdrCOFFGetSymbolValueByName(sname %s, idx %x)\n", SymbolName, Idx);
1279
1280 for (i = 0; i < Module->nsyms; i++)
1281 {
1282 LdrCOFFGetSymbolName(Module, i, Name);
1283 DPRINT("Scanning %s Value %x\n", Name, Module->sym_list[i].e_value);
1284 if (strcmp(Name, SymbolName) == 0)
1285 {
1286 DPRINT("Returning %x\n", Module->sym_list[i].e_value);
1287 return Module->sym_list[i].e_value;
1288 }
1289 }
1290
1291 return 0L;
1292 }
1293