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 */