Investigating a crash at startup
Filip Navara
navaraf at reactos.com
Sun Jun 13 15:26:18 CDT 2004
Now with the correct patch...
- Filip
Filip Navara wrote:
> Hi!
>
> One insteresting thing is that OpenOffice does the same and was
> reported to work under Wine. Anyway, an experimental patch is attached
> (it's completely untested).
>
> Regards,
> Filip
>
> Phil Krylov wrote:
>
>> Hello,
>>
>> I have a program here (IBM Translation Manager v.6.0.4) which crashes
>> wine at startup. The program loads a DLL, and Wine starts importing
>> this DLL's imports from kernel32.dll. It crashes on the first import
>> in dlls/ntdll/loader.c:453, which says:
>>
>> thunk_list->u1.Function = (PDWORD)find_named_export( imp_mod,
>> exports, exp_size,
>> pe_name->Name,
>> pe_name->Hint );
>>
>> This causes an exception because thunk_list happens to be located in
>> .rdata section of the DLL, which is readonly.
>>
>> Currently I have hacked this around by making all PE sections
>> read-write in map_image() in dlls/ntdll/virtual.c, and the program
>> works.
>>
>> If a Wine guru would like to investigate this problem, I can give any
>> support (e.g., ssh access to my computer with the program).
>> If not - I will be using this hacked version of Wine.
>>
-------------- next part --------------
--- dlls/ntdll/loader.c Tue Apr 20 00:36:30 2004
+++ dlls/ntdll/loader.c Sat Jun 12 16:23:34 2004
@@ -371,6 +371,9 @@
WCHAR buffer[32];
char *name = get_rva( module, descr->Name );
DWORD len = strlen(name) + 1;
+ PVOID protect_base;
+ DWORD protect_size = 0;
+ DWORD protect_old;
thunk_list = get_rva( module, (DWORD)descr->FirstThunk );
if (descr->u.OriginalFirstThunk)
@@ -403,6 +406,20 @@
return NULL;
}
+ /* unprotect the import address table since it can be located in
+ * readonly section */
+ while (import_list[protect_size].u1.Ordinal)
+ protect_size++;
+ protect_base = thunk_list;
+ protect_size *= sizeof(PVOID *);
+ status = NtProtectVirtualMemory( GetCurrentProcess(), &protect_base,
+ &protect_size, PAGE_READWRITE, &protect_old );
+ if (status)
+ {
+ ERR("Can't unprotect IAT for %s\n", name);
+ return NULL;
+ }
+
imp_mod = wmImp->ldr.BaseAddress;
exports = RtlImageDirectoryEntryToData( imp_mod, TRUE, IMAGE_DIRECTORY_ENTRY_EXPORT, &exp_size );
@@ -427,6 +444,11 @@
import_list++;
thunk_list++;
}
+
+ /* restore old protection of the import address table */
+ NtProtectVirtualMemory( GetCurrentProcess(), &protect_base,
+ &protect_size, protect_old, NULL );
+
return wmImp;
}
@@ -463,6 +485,11 @@
import_list++;
thunk_list++;
}
+
+ /* restore old protection of the import address table */
+ NtProtectVirtualMemory( GetCurrentProcess(), &protect_base,
+ &protect_size, protect_old, NULL );
+
return wmImp;
}
--- dlls/ntdll/virtual.c Tue Apr 6 23:13:48 2004
+++ dlls/ntdll/virtual.c Sat Jun 12 17:10:06 2004
@@ -511,6 +511,10 @@
int delta, DWORD total_size )
{
IMAGE_BASE_RELOCATION *rel;
+ NTSTATUS status;
+ PVOID protect_base;
+ DWORD protect_size = page_size;
+ DWORD protect_old;
TRACE_(module)( "relocating from %p-%p to %p-%p\n",
base - delta, base - delta + total_size, base, base + total_size );
@@ -537,6 +541,16 @@
TRACE_(module)("%ld relocations for page %lx\n", rel->SizeOfBlock, rel->VirtualAddress);
+ /* unprotect the page we're about to relocate */
+ protect_base = page;
+ status = NtProtectVirtualMemory( GetCurrentProcess(), &protect_base,
+ &protect_size, PAGE_READWRITE, &protect_old );
+ if (status)
+ {
+ ERR("Can't unprotect page during relocation\n");
+ return 0;
+ }
+
/* patching in reverse order */
for (i = 0 ; i < count; i++)
{
@@ -561,6 +575,10 @@
break;
}
}
+
+ /* restore old protection */
+ NtProtectVirtualMemory( GetCurrentProcess(), &protect_base,
+ &protect_size, protect_old, NULL );
}
return 1;
}
More information about the wine-devel
mailing list