On Tue, May 28, 2002 at 12:08:46AM +0200, Laurent Pinchart wrote:
Hi everybody,
I noticed that, when a builtin dll (.so) is loaded, the SizeOfImage field in the OptionalHeader is not updated and stays equal to page_size (see winebuild, spec32).
I need to get the correct value in SizeOfImage.
I thought about updating that field in map_dll@library/loader.c, but don't know how to get the size of the image.
Could anyone help me ? I'm not familiar with the PE loader.
You can't find out the size of the image from the libdl API calls except going into heavy ELF parsing.
winebuild does not really know either.
My suggestion would be to use a heuristic like the one below. However it is not perfect, the sizes are too large sometimes.
Ciao, Marcus
Copyright: LGPL
Index: loader.c =================================================================== RCS file: /home/wine/wine/library/loader.c,v retrieving revision 1.15 diff -u -r1.15 loader.c --- loader.c 22 May 2002 21:32:49 -0000 1.15 +++ loader.c 29 May 2002 07:54:16 -0000 @@ -21,6 +21,7 @@ #include "config.h" #include "wine/port.h"
+#include <stdio.h> #include <assert.h> #include <ctype.h> #include <stdlib.h> @@ -155,19 +156,23 @@
/* adjust an array of pointers to make them into RVAs */ -static inline void fixup_rva_ptrs( void *array, void *base, int count ) +static inline void fixup_rva_ptrs( void *array, void *base, int count, int *rmax) { void **ptr = (void **)array; while (count--) { - if (*ptr) *ptr = (void *)((char *)*ptr - (char *)base); + if (*ptr) { + int diff = ((char *)*ptr - (char *)base); + *ptr = (void *)diff; + if (diff > *rmax) *rmax = diff; + } ptr++; } }
/* fixup RVAs in the resource directory */ -static void fixup_resources( IMAGE_RESOURCE_DIRECTORY *dir, char *root, void *base ) +static void fixup_resources( IMAGE_RESOURCE_DIRECTORY *dir, char *root, void *base, int *rmax ) { IMAGE_RESOURCE_DIRECTORY_ENTRY *entry; int i; @@ -176,11 +181,11 @@ for (i = 0; i < dir->NumberOfNamedEntries + dir->NumberOfIdEntries; i++, entry++) { void *ptr = root + entry->u2.s3.OffsetToDirectory; - if (entry->u2.s3.DataIsDirectory) fixup_resources( ptr, root, base ); + if (entry->u2.s3.DataIsDirectory) fixup_resources( ptr, root, base, rmax ); else { IMAGE_RESOURCE_DATA_ENTRY *data = ptr; - fixup_rva_ptrs( &data->OffsetToData, base, 1 ); + fixup_rva_ptrs( &data->OffsetToData, base, 1, rmax ); } } } @@ -197,6 +202,7 @@ BYTE *addr, *code_start, *data_start; size_t page_size = getpagesize(); int nb_sections = 2; /* code + data */ + int rmax = 0;
size_t size = (sizeof(IMAGE_DOS_HEADER) + sizeof(IMAGE_NT_HEADERS) @@ -238,7 +244,7 @@ nt->OptionalHeader.SizeOfUninitializedData = 0; nt->OptionalHeader.ImageBase = (DWORD)addr;
- fixup_rva_ptrs( &nt->OptionalHeader.AddressOfEntryPoint, addr, 1 ); + fixup_rva_ptrs( &nt->OptionalHeader.AddressOfEntryPoint, addr, 1, &rmax );
/* Build the code section */
@@ -267,9 +273,9 @@ if (dir->Size) { IMAGE_IMPORT_DESCRIPTOR *imports = (void *)dir->VirtualAddress; - fixup_rva_ptrs( &dir->VirtualAddress, addr, 1 ); + fixup_rva_ptrs( &dir->VirtualAddress, addr, 1 , &rmax); /* we can fixup everything at once since we only have pointers and 0 values */ - fixup_rva_ptrs( imports, addr, dir->Size / sizeof(void*) ); + fixup_rva_ptrs( imports, addr, dir->Size / sizeof(void*), &rmax ); }
/* Build the resource directory */ @@ -278,8 +284,8 @@ if (dir->Size) { void *ptr = (void *)dir->VirtualAddress; - fixup_rva_ptrs( &dir->VirtualAddress, addr, 1 ); - fixup_resources( ptr, ptr, addr ); + fixup_rva_ptrs( &dir->VirtualAddress, addr, 1 , &rmax); + fixup_resources( ptr, ptr, addr, &rmax ); }
/* Build the export directory */ @@ -288,14 +294,17 @@ 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 ); + fixup_rva_ptrs( &dir->VirtualAddress, addr, 1, &rmax ); + fixup_rva_ptrs( (void *)exports->AddressOfFunctions, addr, exports->NumberOfFunctions, &rmax ); + fixup_rva_ptrs( (void *)exports->AddressOfNames, addr, exports->NumberOfNames, &rmax ); + fixup_rva_ptrs( &exports->Name, addr, 1, &rmax ); + fixup_rva_ptrs( &exports->AddressOfFunctions, addr, 1, &rmax ); + fixup_rva_ptrs( &exports->AddressOfNames, addr, 1, &rmax ); + fixup_rva_ptrs( &exports->AddressOfNameOrdinals, addr, 1, &rmax ); } + + fprintf(stderr,"rmax (sizeofimage) is %ld\n",rmax); + return addr; #else /* HAVE_MMAP */ return NULL;