CVS: winex/loader pe_image.c,1.21,1.22

[email protected] 31 Jul 2007 19:49:32 -0000
Newsgroups gmane.comp.emulators.winex.cvs
Message-ID <[email protected]>
Subject: winex/loader pe_image.c,1.21,1.22Update of /var/lib/cvsd/cvsroot/winex/loader
In directory agravaine:/tmp/cvs-serv879/loader

Modified Files:
	pe_image.c 
Log Message:

- modify segment permissions to allow import fixups to be done
- do relocations prior to setting segment permissions


Index: pe_image.c
===================================================================
RCS file: /var/lib/cvsd/cvsroot/winex/loader/pe_image.c,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -d -r1.21 -r1.22
--- pe_image.c	31 Jul 2007 19:49:02 -0000	1.21
+++ pe_image.c	31 Jul 2007 19:49:30 -0000	1.22
@@ -298,6 +298,8 @@
 	IMAGE_IMPORT_BY_NAME	*pe_name;
 	PIMAGE_THUNK_DATA	import_list,thunk_list;
  	char			*name = (char *) RVA(pe_imp->Name);
+        int   prot_size = 0;
+        DWORD prot_old = 0;
 
 	if (characteristics_detection && !pe_imp->u.Characteristics)
 		break;
@@ -321,6 +323,18 @@
         else
            import_list = thunk_list;
 
+        /* We need to unprotect the imports table in case it's in a
+           read-only section */
+        while (import_list[prot_size].u1.Ordinal)
+           prot_size++;
+        prot_size *= sizeof (IMAGE_THUNK_DATA);
+        if (prot_size)
+        {
+           if (!VirtualProtect (thunk_list, prot_size, PAGE_WRITECOPY,
+                                &prot_old))
+              ERR ("Unable to change protections on import list!\n");
+        }
+
         while (import_list->u1.Ordinal)
         {
            if (IMAGE_SNAP_BY_ORDINAL(import_list->u1.Ordinal))
@@ -359,93 +373,18 @@
            import_list++;
            thunk_list++;
         }
-    }
-    return r;
-}
-
-/***********************************************************************
- *           do_relocations
- *
- * Apply the relocations to a mapped PE image
- */
-static int do_relocations( char *base, const IMAGE_NT_HEADERS *nt, const char *filename )
-{
-    const IMAGE_DATA_DIRECTORY *dir;
-    const IMAGE_BASE_RELOCATION *rel;
-    int delta = base - (char *)nt->OptionalHeader.ImageBase;
-
-    dir = &nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
-    rel = (IMAGE_BASE_RELOCATION *)(base + dir->VirtualAddress);
-
-    WARN("Info: base relocations needed for %s\n", filename);
-    if (!dir->VirtualAddress || !dir->Size)
-    {
-        if (nt->OptionalHeader.ImageBase == 0x400000)
-            ERR("Standard load address for a Win32 program (0x00400000) not available - security-patched kernel ?\n");
-        ERR( "FATAL: Need to relocate %s, but no relocation records present (%s). Try to run that file directly !\n",
-             filename,
-             (nt->FileHeader.Characteristics&IMAGE_FILE_RELOCS_STRIPPED)?
-             "stripped during link" : "unknown reason" );
-        return 0;
-    }
-
-    /* FIXME: If we need to relocate a system DLL (base > 2GB) we should
-     *        really make sure that the *new* base address is also > 2GB.
-     *        Some DLLs really check the MSB of the module handle :-/
-     */
-    if ((nt->OptionalHeader.ImageBase & 0x80000000) && !((DWORD)base & 0x80000000))
-        ERR( "Forced to relocate system DLL (base > 2GB). This is not good.\n" );
-
-    for ( ; ((char *)rel < base + dir->VirtualAddress + dir->Size) && rel->SizeOfBlock;
-          rel = (IMAGE_BASE_RELOCATION*)((char*)rel + rel->SizeOfBlock))
-    {
-        char *page = base + rel->VirtualAddress;
-        WORD *TypeOffset = (WORD *)(rel + 1);
-        int i, count = (rel->SizeOfBlock - sizeof(*rel)) / sizeof(*TypeOffset);
-
-        if (!count) continue;
-
-        /* sanity checks */
-        if ((char *)rel + rel->SizeOfBlock > base + dir->VirtualAddress + dir->Size ||
-            page > base + nt->OptionalHeader.SizeOfImage)
-        {
-            ERR_(module)("invalid relocation %p,%lx,%ld at %p,%lx,%lx\n",
-                         rel, rel->VirtualAddress, rel->SizeOfBlock,
-                         base, dir->VirtualAddress, dir->Size );
-            return 0;
-        }
 
-        TRACE_(module)("%ld relocations for page %lx\n", rel->SizeOfBlock, rel->VirtualAddress);
-
-        /* patching in reverse order */
-        for (i = 0 ; i < count; i++)
+        if (prot_size)
         {
-            int offset = TypeOffset[i] & 0xFFF;
-            int type = TypeOffset[i] >> 12;
-            switch(type)
-            {
-            case IMAGE_REL_BASED_ABSOLUTE:
-                break;
-            case IMAGE_REL_BASED_HIGH:
-                *(short*)(page+offset) += HIWORD(delta);
-                break;
-            case IMAGE_REL_BASED_LOW:
-                *(short*)(page+offset) += LOWORD(delta);
-                break;
-            case IMAGE_REL_BASED_HIGHLOW:
-                *(int*)(page+offset) += delta;
-                /* FIXME: if this is an exported address, fire up enhanced logic */
-                break;
-            default:
-                FIXME_(module)("Unknown/unsupported fixup type %d.\n", type);
-                break;
-            }
+           if (!VirtualProtect (thunk_list, prot_size, prot_old, NULL))
+              ERR ("Unable to restore protections on import list!\n");
         }
     }
-    return 1;
+    return r;
 }
 
 
+
 /**********************************************************************
  *			PE_LoadImage
  * Load one PE format DLL/EXE into memory
@@ -473,18 +412,7 @@
 
     hModule = (HMODULE)base;
 
-    /* perform base relocation, if necessary */
-
     nt = PE_HEADER( hModule );
-    if (hModule != nt->OptionalHeader.ImageBase)
-    {
-        if (!do_relocations( base, nt, filename ))
-        {
-            UnmapViewOfFile( base );
-            SetLastError( ERROR_BAD_EXE_FORMAT );
-            return 0;
-        }
-    }
 
     /* virus check */