CVS: winex/memory virtual.c,1.38,1.39
[email protected] 31 Jul 2007 19:49:41 -0000
| Newsgroups | gmane.comp.emulators.winex.cvs |
|---|---|
| Message-ID | <[email protected]> |
Subject: winex/memory virtual.c,1.38,1.39Update of /var/lib/cvsd/cvsroot/winex/memory
In directory agravaine:/tmp/cvs-serv918/memory
Modified Files:
virtual.c
Log Message:
- modify segment permissions to allow import fixups to be done
- do relocations prior to setting segment permissions
Index: virtual.c
===================================================================
RCS file: /var/lib/cvsd/cvsroot/winex/memory/virtual.c,v
retrieving revision 1.38
retrieving revision 1.39
diff -u -d -r1.38 -r1.39
--- virtual.c 31 Jul 2007 19:49:15 -0000 1.38
+++ virtual.c 31 Jul 2007 19:49:39 -0000 1.39
@@ -791,6 +791,89 @@
/***********************************************************************
+ * do_relocations
+ *
+ * Apply the relocations to a mapped PE image
+ */
+static int do_relocations( char *base, const IMAGE_NT_HEADERS *nt )
+{
+ 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_(module)("Info: base relocations needed\n");
+ 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, but no relocation records present (%s). Try to run the file directly !\n",
+ (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);
+
+ TRACE_(module) ("Count: %d\n", count);
+ 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++)
+ {
+ 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;
+ }
+ }
+ }
+ return 1;
+}
+
+
+/***********************************************************************
* map_image
*
* Map an executable (PE format) image into memory.
@@ -947,6 +1030,10 @@
}
}
+ /* Do relocations if necessary */
+ if (ptr != base)
+ do_relocations (ptr, nt);
+
/* Set the protection on the PE header READONLY rather than what we just set when we created the view */
VIRTUAL_SetProt( view, ptr, header_size, VPROT_READ|VPROT_COMMITTED );