Do builtin modules fixups in library/loader.c before calling the
load_dll callback.
diff --git a/library/loader.c b/library/loader.c
index 95922d0..4d202ac 100644
--- a/library/loader.c
+++ b/library/loader.c
@@ -11,13 +11,17 @@
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
-
+#include <unistd.h>
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
#ifdef HAVE_DL_API
#include <dlfcn.h>
#endif
-#include "windef.h"
+#include "winnt.h"
#include "wine/library.h"
+#include "wine/port.h"
#define MAX_DLLS 100
@@ -116,6 +120,151 @@
}
+/* adjust an array of pointers to make them into RVAs */
+static inline void fixup_rva_ptrs( void *array, void *base, int count )
+{
+ void **ptr = (void **)array;
+ while (count--)
+ {
+ if (*ptr) *ptr = (void *)((char *)*ptr - (char *)base);
+ ptr++;
+ }
+}
+
+
+/* fixup RVAs in the resource directory */
+static void fixup_resources( IMAGE_RESOURCE_DIRECTORY *dir, char *root, void *base )
+{
+ IMAGE_RESOURCE_DIRECTORY_ENTRY *entry;
+ int i;
+
+ entry = (IMAGE_RESOURCE_DIRECTORY_ENTRY *)(dir + 1);
+ for (i = 0; i < dir->NumberOfNamedEntries + dir->NumberOfIdEntries; i++, entry++)
+ {
+ void *ptr = root + entry->u2.s.OffsetToDirectory;
+ if (entry->u2.s.DataIsDirectory) fixup_resources( ptr, root, base );
+ else
+ {
+ IMAGE_RESOURCE_DATA_ENTRY *data = ptr;
+ fixup_rva_ptrs( &data->OffsetToData, base, 1 );
+ }
+ }
+}
+
+
+/* map a builtin dll in memory and fixup RVAs */
+static void *map_dll( const IMAGE_NT_HEADERS *nt_descr )
+{
+ IMAGE_DATA_DIRECTORY *dir;
+ IMAGE_DOS_HEADER *dos;
+ IMAGE_NT_HEADERS *nt;
+ IMAGE_SECTION_HEADER *sec;
+ BYTE *addr, *code_start, *data_start;
+ size_t page_size = getpagesize();
+ int nb_sections = 2; /* code + data */
+
+ size_t size = (sizeof(IMAGE_DOS_HEADER)
+ + sizeof(IMAGE_NT_HEADERS)
+ + nb_sections * sizeof(IMAGE_SECTION_HEADER));
+
+ assert( size <= page_size );
+
+ if (nt_descr->OptionalHeader.ImageBase)
+ {
+ addr = wine_anon_mmap( (void *)nt_descr->OptionalHeader.ImageBase,
+ page_size, PROT_READ|PROT_WRITE, MAP_FIXED );
+ if (addr != (BYTE *)nt_descr->OptionalHeader.ImageBase) return NULL;
+ }
+ else
+ {
+ /* this will leak memory; but it should never happen */
+ addr = wine_anon_mmap( NULL, page_size, PROT_READ|PROT_WRITE, 0 );
+ if (addr == (BYTE *)-1) return NULL;
+ }
+
+ dos = (IMAGE_DOS_HEADER *)addr;
+ nt = (IMAGE_NT_HEADERS *)(dos + 1);
+ sec = (IMAGE_SECTION_HEADER *)(nt + 1);
+ code_start = addr + page_size;
+
+ /* HACK! */
+ data_start = code_start + page_size;
+
+ /* Build the DOS and NT headers */
+
+ dos->e_magic = IMAGE_DOS_SIGNATURE;
+ dos->e_lfanew = sizeof(*dos);
+
+ *nt = *nt_descr;
+
+ nt->FileHeader.NumberOfSections = nb_sections;
+ nt->OptionalHeader.SizeOfCode = data_start - code_start;
+ nt->OptionalHeader.SizeOfInitializedData = 0;
+ nt->OptionalHeader.SizeOfUninitializedData = 0;
+ nt->OptionalHeader.ImageBase = (DWORD)addr;
+
+ fixup_rva_ptrs( &nt->OptionalHeader.AddressOfEntryPoint, addr, 1 );
+
+ /* Build the code section */
+
+ strcpy( sec->Name, ".text" );
+ sec->SizeOfRawData = data_start - code_start;
+ sec->Misc.VirtualSize = sec->SizeOfRawData;
+ sec->VirtualAddress = code_start - addr;
+ sec->PointerToRawData = code_start - addr;
+ sec->Characteristics = (IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ);
+ sec++;
+
+ /* Build the data section */
+
+ strcpy( sec->Name, ".data" );
+ sec->SizeOfRawData = 0;
+ sec->Misc.VirtualSize = sec->SizeOfRawData;
+ sec->VirtualAddress = data_start - addr;
+ sec->PointerToRawData = data_start - addr;
+ sec->Characteristics = (IMAGE_SCN_CNT_INITIALIZED_DATA |
+ IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_READ);
+ sec++;
+
+ /* Build the import directory */
+
+ dir = &nt->OptionalHeader.DataDirectory[IMAGE_FILE_IMPORT_DIRECTORY];
+ if (dir->Size)
+ {
+ IMAGE_IMPORT_DESCRIPTOR *imports = (void *)dir->VirtualAddress;
+ fixup_rva_ptrs( &dir->VirtualAddress, addr, 1 );
+ /* we can fixup everything at once since we only have pointers and 0 values */
+ fixup_rva_ptrs( imports, addr, dir->Size / sizeof(void*) );
+ }
+
+ /* Build the resource directory */
+
+ dir = &nt->OptionalHeader.DataDirectory[IMAGE_FILE_RESOURCE_DIRECTORY];
+ if (dir->Size)
+ {
+ void *ptr = (void *)dir->VirtualAddress;
+ fixup_rva_ptrs( &dir->VirtualAddress, addr, 1 );
+ fixup_resources( ptr, ptr, addr );
+ }
+
+ /* Build the export directory */
+
+ dir = &nt->OptionalHeader.DataDirectory[IMAGE_FILE_EXPORT_DIRECTORY];
+ if (dir->Size)
+ {
+ IMAGE_EXPORT_DIRECTORY *exports = (void *)dir->VirtualAddress;
+ fixup_rva_ptrs( &dir->VirtualAddress, addr, 1 );
+ fixup_rva_ptrs( (void *)exports->AddressOfFunctions, addr, exports->NumberOfFunctions );
+ fixup_rva_ptrs( (void *)exports->AddressOfNames, addr, exports->NumberOfNames );
+ fixup_rva_ptrs( &exports->Name, addr, 1 );
+ fixup_rva_ptrs( &exports->AddressOfFunctions, addr, 1 );
+ fixup_rva_ptrs( &exports->AddressOfNames, addr, 1 );
+ fixup_rva_ptrs( &exports->AddressOfNameOrdinals, addr, 1 );
+ }
+ return addr;
+}
+
+
/***********************************************************************
* __wine_dll_register
*
@@ -123,7 +272,7 @@
*/
void __wine_dll_register( const IMAGE_NT_HEADERS *header, const char *filename )
{
- if (load_dll_callback) load_dll_callback( header, filename );
+ if (load_dll_callback) load_dll_callback( map_dll(header), filename );
else
{
if (!(header->FileHeader.Characteristics & IMAGE_FILE_DLL))
@@ -154,10 +303,10 @@
const IMAGE_NT_HEADERS *nt = builtin_dlls[i].nt;
if (!nt) continue;
builtin_dlls[i].nt = NULL;
- load_dll_callback( nt, builtin_dlls[i].filename );
+ load_dll_callback( map_dll(nt), builtin_dlls[i].filename );
}
nb_dlls = 0;
- if (main_exe) load_dll_callback( main_exe, "" );
+ if (main_exe) load_dll_callback( map_dll(main_exe), "" );
}
@@ -182,7 +331,7 @@
{
const IMAGE_NT_HEADERS *nt = builtin_dlls[i].nt;
builtin_dlls[i].nt = NULL;
- load_dll_callback( nt, builtin_dlls[i].filename );
+ load_dll_callback( map_dll(nt), builtin_dlls[i].filename );
return (void *)1;
}
}