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)
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
17 /* INCLUDES *****************************************************************/
21 #include <internal/i386/segment.h>
22 #include <internal/linkage.h>
23 #include <internal/module.h>
24 #include <internal/ntoskrnl.h>
25 #include <internal/ob.h>
26 #include <internal/ps.h>
28 #include <internal/string.h>
29 #include <internal/symbol.h>
31 #include <ddk/ntddk.h>
34 #include <internal/debug.h>
36 /* FIXME: this should appear in a kernel header file */
37 NTSTATUS
IoInitializeDriver(PDRIVER_INITIALIZE DriverEntry
);
39 /* MACROS ********************************************************************/
41 /* GLOBALS *******************************************************************/
43 POBJECT_TYPE ObModuleType
= NULL
;
45 /* FORWARD DECLARATIONS ******************************************************/
47 NTSTATUS
LdrLoadDriver(PUNICODE_STRING Filename
);
48 NTSTATUS
LdrProcessDriver(PVOID ModuleLoadBase
);
50 /* PE Driver load support */
51 static NTSTATUS
LdrPEProcessDriver(PVOID ModuleLoadBase
);
52 static unsigned int LdrGetKernelSymbolAddr(char *Name
);
54 /* COFF Driver load support */
55 static NTSTATUS
LdrCOFFProcessDriver(PVOID ModuleLoadBase
);
56 static BOOLEAN
LdrCOFFDoRelocations(module
*Module
, unsigned int SectionIndex
);
57 static BOOLEAN
LdrCOFFDoAddr32Reloc(module
*Module
, SCNHDR
*Section
, RELOC
*Relocation
);
58 static BOOLEAN
LdrCOFFDoReloc32Reloc(module
*Module
, SCNHDR
*Section
, RELOC
*Relocation
);
59 static void LdrCOFFGetSymbolName(module
*Module
, unsigned int Idx
, char *Name
);
60 static unsigned int LdrCOFFGetSymbolValue(module
*Module
, unsigned int Idx
);
61 static unsigned int LdrCOFFGetSymbolValueByName(module
*Module
, char *SymbolName
, unsigned int Idx
);
63 /* FUNCTIONS *****************************************************************/
65 VOID
LdrInitModuleManagement(VOID
)
67 ANSI_STRING AnsiString
;
69 /* Register the process object type */
70 ObModuleType
= ExAllocatePool(NonPagedPool
, sizeof(OBJECT_TYPE
));
71 ObModuleType
->TotalObjects
= 0;
72 ObModuleType
->TotalHandles
= 0;
73 ObModuleType
->MaxObjects
= ULONG_MAX
;
74 ObModuleType
->MaxHandles
= ULONG_MAX
;
75 ObModuleType
->PagedPoolCharge
= 0;
76 ObModuleType
->NonpagedPoolCharge
= sizeof(MODULE
);
77 ObModuleType
->Dump
= NULL
;
78 ObModuleType
->Open
= NULL
;
79 ObModuleType
->Close
= NULL
;
80 ObModuleType
->Delete
= NULL
;
81 ObModuleType
->Parse
= NULL
;
82 ObModuleType
->Security
= NULL
;
83 ObModuleType
->QueryName
= NULL
;
84 ObModuleType
->OkayToClose
= NULL
;
85 RtlInitAnsiString(&AnsiString
, "Module");
86 RtlAnsiStringToUnicodeString(&ObModuleType
->TypeName
, &AnsiString
, TRUE
);
90 * load the auto config drivers.
92 VOID
LdrLoadAutoConfigDrivers(VOID
)
95 ANSI_STRING AnsiDriverName
;
96 UNICODE_STRING DriverName
;
98 RtlInitAnsiString(&AnsiDriverName
,"\\??\\C:\\reactos\\system\\drivers\\keyboard.sys");
99 RtlAnsiStringToUnicodeString(&DriverName
, &AnsiDriverName
, TRUE
);
100 Status
= LdrLoadDriver(&DriverName
);
101 RtlFreeUnicodeString(&DriverName
);
102 if (!NT_SUCCESS(Status
))
104 DbgPrint("driver load failed, status;%d(%x)\n", Status
, Status
);
105 DbgPrintErrorMessage(Status
);
107 RtlInitAnsiString(&AnsiDriverName
,"\\??\\C:\\reactos\\system\\drivers\\blue.sys");
108 RtlAnsiStringToUnicodeString(&DriverName
, &AnsiDriverName
, TRUE
);
109 Status
= LdrLoadDriver(&DriverName
);
110 RtlFreeUnicodeString(&DriverName
);
111 if (!NT_SUCCESS(Status
))
113 DbgPrint("driver load failed, status;%d(%x)\n", Status
, Status
);
114 DbgPrintErrorMessage(Status
);
120 * FUNCTION: Loads a kernel driver
122 * FileName = Driver to load
127 LdrLoadDriver(PUNICODE_STRING Filename
)
129 PVOID ModuleLoadBase
;
132 OBJECT_ATTRIBUTES FileObjectAttributes
;
133 FILE_STANDARD_INFORMATION FileStdInfo
;
135 DbgPrint("Loading Driver %W...\n", Filename
);
137 /* Open the Driver */
138 InitializeObjectAttributes(&FileObjectAttributes
,
144 Status
= ZwOpenFile(&FileHandle
,
146 &FileObjectAttributes
,
149 if (!NT_SUCCESS(Status
))
155 /* Get the size of the file */
156 Status
= ZwQueryInformationFile(FileHandle
,
160 FileStandardInformation
);
161 if (!NT_SUCCESS(Status
))
167 /* Allocate nonpageable memory for driver */
168 ModuleLoadBase
= ExAllocatePool(NonPagedPool
,
169 FileStdInfo
.EndOfFile
.LowPart
);
170 if (ModuleLoadBase
== NULL
)
172 return STATUS_INSUFFICIENT_RESOURCES
;
176 /* Load driver into memory chunk */
177 Status
= ZwReadFile(FileHandle
,
180 FileStdInfo
.EndOfFile
.LowPart
,
182 if (!NT_SUCCESS(Status
))
184 ExFreePool(ModuleLoadBase
);
191 Status
= LdrProcessDriver(ModuleLoadBase
);
194 ExFreePool(ModuleLoadBase
);
196 return STATUS_SUCCESS
;
200 LdrProcessDriver(PVOID ModuleLoadBase
)
202 PIMAGE_DOS_HEADER PEDosHeader
;
204 /* If MZ header exists */
205 PEDosHeader
= (PIMAGE_DOS_HEADER
) ModuleLoadBase
;
206 if (PEDosHeader
->e_magic
== IMAGE_DOS_MAGIC
&& PEDosHeader
->e_lfanew
!= 0L)
208 return LdrPEProcessDriver(ModuleLoadBase
);
210 if (PEDosHeader
->e_magic
== IMAGE_DOS_MAGIC
)
212 return STATUS_NOT_IMPLEMENTED
;
214 else /* Assume COFF format and load */
216 return LdrCOFFProcessDriver(ModuleLoadBase
);
221 LdrPEProcessDriver(PVOID ModuleLoadBase
)
223 unsigned int DriverSize
, Idx
;
224 ULONG RelocDelta
, NumRelocs
;
225 DWORD CurrentSize
, TotalRelocs
;
226 PVOID DriverBase
, CurrentBase
, EntryPoint
;
228 PIMAGE_DOS_HEADER PEDosHeader
;
229 PIMAGE_FILE_HEADER PEFileHeader
;
230 PIMAGE_OPTIONAL_HEADER PEOptionalHeader
;
231 PIMAGE_SECTION_HEADER PESectionHeaders
;
232 PRELOCATION_DIRECTORY RelocDir
;
233 PRELOCATION_ENTRY RelocEntry
;
235 PVOID
*ImportAddressList
;
236 PULONG FunctionNameList
;
237 PCHAR pName
, SymbolNameBuf
;
240 /* FIXME: this could be used to load kernel DLLs also, however */
241 /* the image headers should be preserved in such a case */
243 DPRINT("Processing PE Driver at module base:%08lx\n", ModuleLoadBase
);
245 /* Get header pointers */
246 PEDosHeader
= (PIMAGE_DOS_HEADER
) ModuleLoadBase
;
247 PEMagic
= (PULONG
) ((unsigned int) ModuleLoadBase
+
248 PEDosHeader
->e_lfanew
);
249 PEFileHeader
= (PIMAGE_FILE_HEADER
) ((unsigned int) ModuleLoadBase
+
250 PEDosHeader
->e_lfanew
+ sizeof(ULONG
));
251 PEOptionalHeader
= (PIMAGE_OPTIONAL_HEADER
) ((unsigned int) ModuleLoadBase
+
252 PEDosHeader
->e_lfanew
+ sizeof(ULONG
) + sizeof(IMAGE_FILE_HEADER
));
253 PESectionHeaders
= (PIMAGE_SECTION_HEADER
) ((unsigned int) ModuleLoadBase
+
254 PEDosHeader
->e_lfanew
+ sizeof(ULONG
) + sizeof(IMAGE_FILE_HEADER
) +
255 sizeof(IMAGE_OPTIONAL_HEADER
));
258 /* Check file magic numbers */
259 if (PEDosHeader
->e_magic
!= IMAGE_DOS_MAGIC
)
261 DPRINT("Incorrect MZ magic: %04x\n", PEDosHeader
->e_magic
);
262 return STATUS_UNSUCCESSFUL
;
264 if (PEDosHeader
->e_lfanew
== 0)
266 DPRINT("Invalid lfanew offset: %08x\n", PEDosHeader
->e_lfanew
);
267 return STATUS_UNSUCCESSFUL
;
269 if (*PEMagic
!= IMAGE_PE_MAGIC
)
271 DPRINT("Incorrect PE magic: %08x\n", *PEMagic
);
272 return STATUS_UNSUCCESSFUL
;
274 if (PEFileHeader
->Machine
!= IMAGE_FILE_MACHINE_I386
)
276 DPRINT("Incorrect Architechture: %04x\n", PEFileHeader
->Machine
);
277 return STATUS_UNSUCCESSFUL
;
281 /* FIXME: if image is fixed-address load, then fail */
283 /* FIXME: check/verify OS version number */
285 DPRINT("OptionalHdrMagic:%04x LinkVersion:%d.%d\n",
286 PEOptionalHeader
->Magic
,
287 PEOptionalHeader
->MajorLinkerVersion
,
288 PEOptionalHeader
->MinorLinkerVersion
);
289 DPRINT("Entry Point:%08lx\n", PEOptionalHeader
->AddressOfEntryPoint
);
292 /* Determine the size of the module */
294 DriverSize
= PEOptionalHeader
->SizeOfImage
;
295 DPRINT("DriverSize %x\n",DriverSize
);
297 /* Allocate a virtual section for the module */
298 DriverBase
= MmAllocateSection(DriverSize
);
301 DbgPrint("Failed to allocate a virtual section for driver\n");
302 return STATUS_INSUFFICIENT_RESOURCES
;
305 DbgPrint("Module is at base %x\n",DriverBase
);
307 /* Copy image sections into virtual section */
308 memcpy(DriverBase
, ModuleLoadBase
, PESectionHeaders
[0].PointerToRawData
);
309 CurrentBase
= (PVOID
) ((DWORD
)DriverBase
+ PESectionHeaders
[0].PointerToRawData
);
311 for (Idx
= 0; Idx
< PEFileHeader
->NumberOfSections
; Idx
++)
313 /* Copy current section into current offset of virtual section */
314 if (PESectionHeaders
[Idx
].Characteristics
&
315 (IMAGE_SECTION_CHAR_CODE
| IMAGE_SECTION_CHAR_DATA
))
317 DPRINT("PESectionHeaders[Idx].VirtualAddress + DriverBase %x\n",
318 PESectionHeaders
[Idx
].VirtualAddress
+ DriverBase
);
319 memcpy(PESectionHeaders
[Idx
].VirtualAddress
+ DriverBase
,
320 (PVOID
)(ModuleLoadBase
+ PESectionHeaders
[Idx
].PointerToRawData
),
321 PESectionHeaders
[Idx
].SizeOfRawData
);
325 DPRINT("PESectionHeaders[Idx].VirtualAddress + DriverBase %x\n",
326 PESectionHeaders
[Idx
].VirtualAddress
+ DriverBase
);
327 memset(PESectionHeaders
[Idx
].VirtualAddress
+ DriverBase
,
328 '\0', PESectionHeaders
[Idx
].SizeOfRawData
);
330 CurrentSize
+= ROUND_UP(PESectionHeaders
[Idx
].SizeOfRawData
,
331 PEOptionalHeader
->SectionAlignment
);
332 CurrentBase
= (PVOID
)((DWORD
)CurrentBase
+
333 ROUND_UP(PESectionHeaders
[Idx
].SizeOfRawData
,
334 PEOptionalHeader
->SectionAlignment
));
337 /* Perform relocation fixups */
338 RelocDelta
= (DWORD
) DriverBase
- PEOptionalHeader
->ImageBase
;
339 RelocDir
= (PRELOCATION_DIRECTORY
)(PEOptionalHeader
->DataDirectory
[
340 IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
);
341 DPRINT("DrvrBase:%08lx ImgBase:%08lx RelocDelta:%08lx\n",
343 PEOptionalHeader
->ImageBase
,
345 DPRINT("RelocDir %x\n",RelocDir
);
346 for (Idx
= 0; Idx
< PEFileHeader
->NumberOfSections
; Idx
++)
348 if (PESectionHeaders
[Idx
].VirtualAddress
== (DWORD
)RelocDir
)
350 DPRINT("Name %.8s PESectionHeader[Idx].PointerToRawData %x\n",
351 PESectionHeaders
[Idx
].Name
,
352 PESectionHeaders
[Idx
].PointerToRawData
);
353 RelocDir
= PESectionHeaders
[Idx
].PointerToRawData
+
355 CurrentSize
= PESectionHeaders
[Idx
].Misc
.VirtualSize
;
359 DPRINT("RelocDir %08lx CurrentSize %08lx\n", RelocDir
, CurrentSize
);
361 while (TotalRelocs
< CurrentSize
&& RelocDir
->SizeOfBlock
!= 0)
363 NumRelocs
= (RelocDir
->SizeOfBlock
- sizeof(RELOCATION_DIRECTORY
)) /
365 /* DPRINT("RelocDir at %08lx for VA %08lx with %08lx relocs\n",
367 RelocDir->VirtualAddress,
369 RelocEntry
= (PRELOCATION_ENTRY
) ((DWORD
)RelocDir
+
370 sizeof(RELOCATION_DIRECTORY
));
371 for (Idx
= 0; Idx
< NumRelocs
; Idx
++)
377 Offset
= RelocEntry
[Idx
].TypeOffset
& 0xfff;
378 Type
= (RelocEntry
[Idx
].TypeOffset
>> 12) & 0xf;
379 RelocItem
= (PDWORD
)(DriverBase
+ RelocDir
->VirtualAddress
+
381 /* DPRINT(" reloc at %08lx %x %s old:%08lx new:%08lx\n",
384 Type ? "HIGHLOW" : "ABS",
386 (*RelocItem) + RelocDelta); */
389 (*RelocItem
) += RelocDelta
;
393 DPRINT("Unknown relocation type %x\n",Type
);
394 return STATUS_UNSUCCESSFUL
;
397 TotalRelocs
+= RelocDir
->SizeOfBlock
;
398 RelocDir
= (PRELOCATION_DIRECTORY
)((DWORD
)RelocDir
+
399 RelocDir
->SizeOfBlock
);
400 // DPRINT("TotalRelocs: %08lx CurrentSize: %08lx\n", TotalRelocs, CurrentSize);
403 DPRINT("PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] %x\n",
404 PEOptionalHeader
->DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT
]
406 /* Perform import fixups */
407 if (PEOptionalHeader
->DataDirectory
[
408 IMAGE_DIRECTORY_ENTRY_IMPORT
].VirtualAddress
)
410 PIMAGE_IMPORT_MODULE_DIRECTORY ImportModuleDirectory
;
412 SymbolNameBuf
= ExAllocatePool(NonPagedPool
, 512);
414 /* Process each import module */
415 ImportModuleDirectory
= (PIMAGE_IMPORT_MODULE_DIRECTORY
)
416 ((DWORD
)DriverBase
+ PEOptionalHeader
->
417 DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT
].VirtualAddress
);
418 while (ImportModuleDirectory
->dwRVAModuleName
)
420 /* FIXME: handle kernel mode DLLs */
422 /* Check to make sure that import lib is kernel */
424 pName
= (PCHAR
) DriverBase
+
425 ImportModuleDirectory
->dwRVAModuleName
;
426 // DPRINT("Import module: %s\n", pName);
427 if (strcmp(pName
, "ntoskrnl.exe")!=0 &&
428 strcmp(pName
, "HAL.dll")!=0)
430 DPRINT("Kernel mode DLLs are currently unsupported\n");
433 /* Get the import address list */
434 ImportAddressList
= (PVOID
*) ((DWORD
)DriverBase
+
435 ImportModuleDirectory
->dwRVAFunctionAddressList
);
437 /* Get the list of functions to import */
438 if (ImportModuleDirectory
->dwRVAFunctionNameList
!= 0)
440 FunctionNameList
= (PULONG
) ((DWORD
)DriverBase
+
441 ImportModuleDirectory
->dwRVAFunctionNameList
);
445 FunctionNameList
= (PULONG
) ((DWORD
)DriverBase
+
446 ImportModuleDirectory
->dwRVAFunctionAddressList
);
449 /* Walk through function list and fixup addresses */
450 while(*FunctionNameList
!= 0L)
452 if ((*FunctionNameList
) & 0x80000000) // hint
454 // DPRINT(" Hint: %08lx\n", *FunctionNameList);
457 DPRINT("Hints for kernel symbols are not handled.\n");
458 *ImportAddressList
= 0;
463 pName
= (PCHAR
)((DWORD
)DriverBase
+
464 *FunctionNameList
+ 2);
465 pHint
= (PWORD
)((DWORD
)DriverBase
+ *FunctionNameList
);
466 // DPRINT(" Hint:%04x Name:%s\n", pHint, pName);
468 /* Get address for symbol */
471 *SymbolNameBuf
= '_';
472 strcpy(SymbolNameBuf
+ 1, pName
);
473 *ImportAddressList
= (PVOID
) LdrGetKernelSymbolAddr(SymbolNameBuf
); if (*ImportAddressList
== 0L)
475 DPRINT("Unresolved kernel symbol: %s\n", pName
);
482 ImportModuleDirectory
++;
485 ExFreePool(SymbolNameBuf
);
488 /* Compute address of entry point */
489 EntryPoint
= (PVOID
) ((DWORD
)DriverBase
+ PEOptionalHeader
->AddressOfEntryPoint
);
490 DbgPrint("Calling entrypoint at %x\n",EntryPoint
);
492 return IoInitializeDriver(EntryPoint
);
496 LdrCOFFProcessDriver(PVOID ModuleLoadBase
)
499 char SymbolName
[255];
505 PDRIVER_INITIALIZE EntryRoutine
;
507 /* Get header pointers */
508 FileHeader
= ModuleLoadBase
;
509 AOUTHeader
= ModuleLoadBase
+ FILHSZ
;
512 /* Check COFF magic value */
513 if (I386BADMAG(*FileHeader
))
515 DbgPrint("Module has bad magic value (%x)\n",
516 FileHeader
->f_magic
);
517 return STATUS_UNSUCCESSFUL
;
521 /* Allocate and initialize a module definition structure */
522 Module
= (module
*) ExAllocatePool(NonPagedPool
, sizeof(module
));
525 return STATUS_INSUFFICIENT_RESOURCES
;
527 Module
->sym_list
= (SYMENT
*)(ModuleLoadBase
+ FileHeader
->f_symptr
);
528 Module
->str_tab
= (char *)(ModuleLoadBase
+ FileHeader
->f_symptr
+
529 FileHeader
->f_nsyms
* SYMESZ
);
530 Module
->scn_list
= (SCNHDR
*)(ModuleLoadBase
+ FILHSZ
+
531 FileHeader
->f_opthdr
);
533 Module
->raw_data_off
= (ULONG
) ModuleLoadBase
;
534 Module
->nsyms
= FileHeader
->f_nsyms
;
537 /* Determine the length of the module */
538 for (i
= 0; i
< FileHeader
->f_nscns
; i
++)
540 DPRINT("Section name: %.8s\n", Module
->scn_list
[i
].s_name
);
541 DPRINT("size %x vaddr %x size %x\n",
543 Module
->scn_list
[i
].s_vaddr
,
544 Module
->scn_list
[i
].s_size
);
545 if (Module
->scn_list
[i
].s_flags
& STYP_TEXT
)
547 Module
->text_base
= Module
->scn_list
[i
].s_vaddr
;
549 if (Module
->scn_list
[i
].s_flags
& STYP_DATA
)
551 Module
->data_base
= Module
->scn_list
[i
].s_vaddr
;
553 if (Module
->scn_list
[i
].s_flags
& STYP_BSS
)
555 Module
->bss_base
= Module
->scn_list
[i
].s_vaddr
;
558 (Module
->scn_list
[i
].s_vaddr
+ Module
->scn_list
[i
].s_size
))
560 Module
->size
= Module
->size
+ Module
->scn_list
[i
].s_vaddr
+
561 Module
->scn_list
[i
].s_size
;
566 /* Allocate a section for the module */
567 Module
->base
= (unsigned int) MmAllocateSection(Module
->size
);
568 if (Module
->base
== 0)
570 DbgPrint("Failed to alloc section for module\n");
572 return STATUS_INSUFFICIENT_RESOURCES
;
576 /* Adjust section vaddrs for allocated area */
577 Module
->data_base
= Module
->data_base
+ Module
->base
;
578 Module
->text_base
= Module
->text_base
+ Module
->base
;
579 Module
->bss_base
= Module
->bss_base
+ Module
->base
;
581 /* Relocate module and fixup imports */
582 for (i
= 0; i
< FileHeader
->f_nscns
; i
++)
584 if (Module
->scn_list
[i
].s_flags
& STYP_TEXT
||
585 Module
->scn_list
[i
].s_flags
& STYP_DATA
)
587 memcpy((PVOID
)(Module
->base
+ Module
->scn_list
[i
].s_vaddr
),
588 (PVOID
)(ModuleLoadBase
+ Module
->scn_list
[i
].s_scnptr
),
589 Module
->scn_list
[i
].s_size
);
590 if (!LdrCOFFDoRelocations(Module
, i
))
592 DPRINT("Relocation failed for section %s\n",
593 Module
->scn_list
[i
].s_name
);
595 /* FIXME: unallocate all sections here */
599 return STATUS_UNSUCCESSFUL
;
602 if (Module
->scn_list
[i
].s_flags
& STYP_BSS
)
604 memset((PVOID
)(Module
->base
+ Module
->scn_list
[i
].s_vaddr
),
606 Module
->scn_list
[i
].s_size
);
610 DbgPrint("Module base: %x\n", Module
->base
);
612 /* Find the entry point */
615 for (i
= 0; i
< FileHeader
->f_nsyms
; i
++)
617 LdrCOFFGetSymbolName(Module
, i
, SymbolName
);
618 if (!strcmp(SymbolName
, "_DriverEntry"))
620 EntryOffset
= Module
->sym_list
[i
].e_value
;
622 DPRINT("Found entry at %x\n", EntryOffset
);
627 DbgPrint("No module entry point defined\n");
630 /* FIXME: unallocate all sections here */
632 return STATUS_UNSUCCESSFUL
;
635 /* Get the address of the module initalization routine */
636 EntryRoutine
= (PDRIVER_INITIALIZE
)(Module
->base
+ EntryOffset
);
641 return IoInitializeDriver(EntryRoutine
);
644 /* LdrCOFFDoRelocations
645 * FUNCTION: Do the relocations for a module section
647 * Module = Pointer to the module
648 * SectionIndex = Index of the section to be relocated
649 * RETURNS: Success or failure
653 LdrCOFFDoRelocations(module
*Module
, unsigned int SectionIndex
)
655 SCNHDR
*Section
= &Module
->scn_list
[SectionIndex
];
656 RELOC
*Relocation
= (RELOC
*)(Module
->raw_data_off
+ Section
->s_relptr
);
659 DPRINT("SectionIndex %d Name %.8s Relocs %d\n",
661 Module
->scn_list
[SectionIndex
].s_name
,
664 for (j
= 0; j
< Section
->s_nreloc
; j
++)
666 DPRINT("vaddr %x symndex %x",
668 Relocation
->r_symndx
);
670 switch (Relocation
->r_type
)
673 if (!LdrCOFFDoAddr32Reloc(Module
, Section
, Relocation
))
680 if (!LdrCOFFDoReloc32Reloc(Module
, Section
, Relocation
))
687 DPRINT("%.8s: Unknown relocation type %x at %d in module\n",
688 Module
->scn_list
[SectionIndex
].s_name
,
695 DPRINT("%.8s: relocations done\n", Module
->scn_list
[SectionIndex
].s_name
);
701 * FUNCTION: Performs a addr32 relocation on a loaded module
703 * mod = module to perform the relocation on
704 * scn = Section to perform the relocation in
705 * reloc = Pointer to a data structure describing the relocation
706 * RETURNS: Success or failure
707 * NOTE: This fixes up a relocation needed when changing the base address of a
712 LdrCOFFDoAddr32Reloc(module
*Module
, SCNHDR
*Section
, RELOC
*Relocation
)
715 unsigned int *Location
;
717 Value
= LdrCOFFGetSymbolValue(Module
, Relocation
->r_symndx
);
718 Location
= (unsigned int *)(Module
->base
+ Relocation
->r_vaddr
);
719 DPRINT("ADDR32 loc %x value %x *loc %x\n", Location
, Value
, *Location
);
720 *Location
= (*Location
) + Module
->base
;
726 * FUNCTION: Performs a reloc32 relocation on a loaded module
728 * mod = module to perform the relocation on
729 * scn = Section to perform the relocation in
730 * reloc = Pointer to a data structure describing the relocation
731 * RETURNS: Success or failure
732 * NOTE: This fixes up an undefined reference to a kernel function in a module
736 LdrCOFFDoReloc32Reloc(module
*Module
, SCNHDR
*Section
, RELOC
*Relocation
)
740 unsigned int *Location
;
742 memset(Name
, 0, 255);
743 LdrCOFFGetSymbolName(Module
, Relocation
->r_symndx
, Name
);
744 Value
= (unsigned int) LdrGetKernelSymbolAddr(Name
);
747 Value
= LdrCOFFGetSymbolValueByName(Module
, Name
, Relocation
->r_symndx
);
750 DbgPrint("Undefined symbol %s in module\n", Name
);
753 Location
= (unsigned int *)(Module
->base
+ Relocation
->r_vaddr
);
754 // (*Location) = (*Location) + Value + Module->base - Section->s_vaddr;
755 (*Location
) = (*Location
);
756 DPRINT("Module->base %x Section->s_vaddr %x\n",
762 DPRINT("REL32 value %x name %s\n", Value
, Name
);
763 Location
= (unsigned int *)(Module
->base
+ Relocation
->r_vaddr
);
764 DPRINT("old %x ", *Location
);
765 DPRINT("Module->base %x Section->s_vaddr %x\n",
768 (*Location
) = (*Location
) + Value
- Module
->base
+ Section
->s_vaddr
;
769 DPRINT("new %x\n", *Location
);
776 * FUNCTION: Get the name of a symbol from a loaded module by ordinal
779 * i = index of symbol
780 * name (OUT) = pointer to a string where the symbol name will be
785 LdrCOFFGetSymbolName(module
*Module
, unsigned int Idx
, char *Name
)
787 if (Module
->sym_list
[Idx
].e
.e_name
[0] != 0)
789 strncpy(Name
, Module
->sym_list
[Idx
].e
.e_name
, 8);
794 strcpy(Name
, &Module
->str_tab
[Module
->sym_list
[Idx
].e
.e
.e_offset
]);
799 * FUNCTION: Get the value of a module defined symbol
802 * i = index of symbol
803 * RETURNS: The value of the symbol
804 * NOTE: This fixes up references to known sections
808 LdrCOFFGetSymbolValue(module
*Module
, unsigned int Idx
)
812 LdrCOFFGetSymbolName(Module
, Idx
, Name
);
813 DPRINT("name %s ", Name
);
815 /* Check if the symbol is a section we have relocated */
816 if (strcmp(Name
, ".text") == 0)
818 return Module
->text_base
;
820 if (strcmp(Name
, ".data") == 0)
822 return Module
->data_base
;
824 if (strcmp(Name
, ".bss") == 0)
826 return Module
->bss_base
;
829 return Module
->sym_list
[Idx
].e_value
;
833 * FUNCTION: Get the address of a kernel symbol
836 * RETURNS: The address of the symbol on success
841 LdrGetKernelSymbolAddr(char *Name
)
846 if ((s
=strchr(Name
,'@'))!=NULL
)
849 DbgPrint("Name %s ",Name
);
851 while (symbol_table
[i
].name
!= NULL
)
853 if (strcmp(symbol_table
[i
].name
, Name
) == 0)
858 DbgPrint("Matched with %s\n",symbol_table
[i
].name
);
860 return symbol_table
[i
].value
;
872 LdrCOFFGetSymbolValueByName(module
*Module
,
879 DPRINT("LdrCOFFGetSymbolValueByName(sname %s, idx %x)\n", SymbolName
, Idx
);
881 for (i
= 0; i
< Module
->nsyms
; i
++)
883 LdrCOFFGetSymbolName(Module
, i
, Name
);
884 DPRINT("Scanning %s Value %x\n", Name
, Module
->sym_list
[i
].e_value
);
885 if (strcmp(Name
, SymbolName
) == 0)
887 DPRINT("Returning %x\n", Module
->sym_list
[i
].e_value
);
888 return Module
->sym_list
[i
].e_value
;