How to fix SizeOfImage when loading a builtin dll ?

Marcus Meissner marcus at jet.franken.de
Wed May 29 01:46:39 CDT 2002


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 at 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;



More information about the wine-devel mailing list