LoadOEMResource crash [Was: Re: Problem report: SHRINKER.ERR, fix to DEVICE_Open/CreateFileA? ]

Robert Baruch autophile at starband.net
Sat Dec 8 18:52:40 CST 2001


Hooray, I got gdb to do what I need, to skip the first exception and 
break before the second.

The key commands are:

gdb (winepath)/bin/wine

Set the arguments:

 > set args --winver nt40 yourapp

Tell gdb to pass segmentation faults to the program:

 > handle SIGSEGV nostop pass

Set a breakpoint at main:

 > b main

Run the program:

 > run

This loads all the shared libraries, and now we can set more breakpoints 
in those libraries. Set a breakpoint where wine handles exceptions, and 
continue the program:

 > break EXC_RtlRaiseException
 > cont

Now the first exception should be hit. We continue again to hit the 
second exception:

 > cont

And now I have a trace where the second exception will be called:

Continuing.

Program received signal SIGSEGV, Segmentation fault.

Breakpoint 3, EXC_RtlRaiseException (rec=0x404f3c60, context=0x404f3cdc) 
at exception.c:176
176         TRACE( "code=%lx flags=%lx\n", rec->ExceptionCode, 
rec->ExceptionFlags );
(gdb) where
#0  EXC_RtlRaiseException (rec=0x404f3c60, context=0x404f3cdc) at 
exception.c:176
#1  0x40076748 in do_segv (context=0x404f3cdc, trap_code=14, 
cr2=0x45f00c, err_code=4)
     at signal_i386.c:711
#2  0x40076ada in segv_handler (__signal=11, __context=
       {sc_gs = 0, __gsh = 0, sc_fs = 143, __fsh = 0, sc_es = 43, __esh 
= 0, sc_ds = 43, __dsh = 0, sc_edi = 4583440, sc_esi = 4583424, sc_ebp = 
1078935716, sc_esp = 1078935700, sc_ebx = 1074829380, sc_edx = 4583424, 
sc_ecx = 3117568, sc_eax = 14, sc_trapno = 14, sc_err = 4, sc_eip = 
1074344288, sc_cs = 35, __csh = 0, sc_eflags = 66050, esp_at_signal = 
1078935700, sc_ss = 43, __ssh = 0, i387 = 0, oldmask = 0, cr2 = 
4583436}) at signal_i386.c:882
#3  <signal handler called>
#4  find_entry_by_id (dir=0x45f000, id=14, root=0x45f000) at 
pe_resource.c:83
#5  0x4009322e in find_entry_by_nameW (dir=0x45f000, name=0xe, 
root=0x45f000)
     at pe_resource.c:115
#6  0x400934b4 in PE_FindResourceW (hmod=4194304, name=0x4074c30e, type=0xe)
     at pe_resource.c:239
#7  0x40094083 in RES_FindResource2 (hModule=4194304, type=0xe "", 
name=0x4074c30e "",
     lang=0, bUnicode=1, bRet16=0) at resource.c:197
#8  0x40093f4d in RES_FindResource2 (hModule=182, type=0xe "", 
name=0x4074c30e "", lang=0,
     bUnicode=1, bRet16=0) at resource.c:171
#9  0x40094140 in RES_FindResource (hModule=182, type=0xe "", 
name=0x4074c30e "", lang=0,
     bUnicode=1, bRet16=0) at resource.c:220
#10 0x40094453 in FindResourceW (hModule=182, name=0x4074c30e, type=0xe) 
at resource.c:360
#11 0x40718664 in CURSORICON_Load (hInstance=182, name=0x4074c30e, 
width=32, height=32,
     colors=256, fCursor=0, loadflags=32832) at cursoricon.c:735
#12 0x4071ade0 in LoadImageW (hinst=4194304, name=0x4074c30e, type=1, 
desiredx=32,
     desiredy=0, loadflags=32832) at cursoricon.c:2261
#13 0x4071a086 in LoadIconW (hInstance=4194304, name=0x4074c30e) at 
cursoricon.c:1765
#14 0x4070ff55 in STATIC_LoadIconW (hwnd=65570, name=0x4074c30e) at 
static.c:146
#15 0x40710278 in StaticWndProc_common (hwnd=65570, uMsg=129, wParam=0, 
lParam=1078937708,
     unicode=1) at static.c:254
#16 0x407104b1 in StaticWndProcW (hWnd=65570, uMsg=129, wParam=0, 
lParam=1078937708)
     at static.c:347
#17 0x4074070b in WINPROC_wrapper () at winproc.c:120
#18 0x40740796 in WINPROC_CallWndProc (proc=0x4071047c <StaticWndProcW>, 
hwnd=65570, msg=129,
     wParam=0, lParam=1078937708) at winproc.c:173
#19 0x4074635e in CallWindowProcW (func=0x4071047c <StaticWndProcW>, 
hwnd=65570, msg=129,
     wParam=0, lParam=1078937708) at winproc.c:2659
#20 0x406e6509 in call_window_proc (hwnd=65570, msg=129, wparam=0, 
lparam=1078937708,
     unicode=1) at message.c:1141
#21 0x406e700a in SendMessageTimeoutW (hwnd=65570, msg=129, wparam=0, 
lparam=1078937708,
     flags=0, timeout=4294967295, res_ptr=0x404f4540) at message.c:1529
#22 0x406e7277 in SendMessageW (hwnd=65570, msg=129, wparam=0, 
lparam=1078937708)
     at message.c:1610
#23 0x40b1b62e in X11DRV_CreateWindow (hwnd=65570, cs=0x404f486c, 
unicode=1) at window.c:882
#24 0x4073abec in WIN_CreateWindowEx (cs=0x404f486c, classAtom=49159, 
type=WIN_PROC_32W)
     at win.c:1177
#25 0x4073b154 in CreateWindowExW (exStyle=4, className=0x4074e8e8, 
windowName=0x4074c30e,
     style=1342177283, x=16, y=40, width=32, height=32, parent=65569, 
menu=1088,
     instance=4194304, data=0x0) at win.c:1392
#26 0x4071ed0c in DIALOG_CreateControls (hwnd=65569, template=0x4074c314 "",
     dlgTemplate=0x404f4958, hInst=0, win32=1) at dialog.c:487
#27 0x4071f891 in DIALOG_CreateIndirect (hInst=0, dlgTemplate=0x4074c2f8 
"\003", owner=0,
     dlgProc=0x4072bae0 <MSGBOX_DlgProc>, param=1078938108, 
procType=WIN_PROC_32A, modal=1)
     at dialog.c:874
#28 0x4071ffb5 in DialogBoxIndirectParamA (hInstance=0, 
template=0x4074c2e0, owner=0,
     dlgProc=0x4072bae0 <MSGBOX_DlgProc>, param=1078938108) at dialog.c:1189
#29 0x4072bc2f in MessageBoxA (hWnd=0,
     text=0x75d4e0 "C:\\My Documents\\power-structure-demo.exe (3.4) 
12/08/01 18:31:47 - Dispatcher initialisation error trapping 
exceptions", title=0x75b3e8 "SHRINKER.ERR", type=8240)
     at msgbox.c:294
#30 0x0075fc1a in ?? ()
#31 0x007604e6 in ?? ()
#32 0x6f442079 in ?? ()
Cannot access memory at address 0x4d5c3a43
(gdb)


That's pretty cool. So the second exception gets thrown while the 
program is trying to pop up the message box caused by the first 
exception. I can crawl up the stack trace to list out the line that the 
exception occurs:

(gdb) up
#1  0x40076748 in do_segv (context=0x404f3cdc, trap_code=14, 
cr2=0x45f00c, err_code=4)
     at signal_i386.c:711
711         EXC_RtlRaiseException( &rec, context );
(gdb) up
#2  0x40076ada in segv_handler (__signal=11, __context=
       {sc_gs = 0, __gsh = 0, sc_fs = 143, __fsh = 0, sc_es = 43, __esh 
= 0, sc_ds = 43, __dsh = 0, sc_edi = 4583440, sc_esi = 4583424, sc_ebp = 
1078935716, sc_esp = 1078935700, sc_ebx = 1074829380, sc_edx = 4583424, 
sc_ecx = 3117568, sc_eax = 14, sc_trapno = 14, sc_err = 4, sc_eip = 
1074344288, sc_cs = 35, __csh = 0, sc_eflags = 66050, esp_at_signal = 
1078935700, sc_ss = 43, __ssh = 0, i387 = 0, oldmask = 0, cr2 = 
4583436}) at signal_i386.c:882
882                  get_cr2_value(HANDLER_CONTEXT), 
get_error_code(HANDLER_CONTEXT) );
(gdb) up
#3  <signal handler called>
(gdb) up
#4  find_entry_by_id (dir=0x45f000, id=14, root=0x45f000) at 
pe_resource.c:83
83          min = dir->NumberOfNamedEntries;
(gdb)


That's what I thought in the first place. I'll try to print out dir:

(gdb) p dir
$14 = (IMAGE_RESOURCE_DIRECTORY *) 0xc0000005


Huh? The stack trace says the argument is 0x45f000, not 0xc0000005.

So I'll re-run the program, but this time I'll add a breakpoint at 
pe_resource.c:find_entry_by_id (just entering "find_entry_by_id" results 
in gdb setting the breakpoint in a file other than pe_resource):

(gdb) run
The program being debugged has been started already.
Start it from the beginning? (y or n) y

Starting program: /usr/local/wine/bin/wine --winver nt40 
"/home/baruch/wine-c/My Documents/power-structure-demo.exe"

Program received signal SIGSEGV, Segmentation fault.

Breakpoint 3, EXC_RtlRaiseException (rec=0x404f4bc8, context=0x404f4c44) 
at exception.c:176
176         TRACE( "code=%lx flags=%lx\n", rec->ExceptionCode, 
rec->ExceptionFlags );
(gdb) break pe_resource.c:find_entry_by_id
Breakpoint 7 at 0x40093156: file pe_resource.c, line 82.
(gdb) cont
Continuing.

Breakpoint 7, find_entry_by_id (dir=0x40768240, id=0, root=0x40768240) 
at pe_resource.c:82
82          entry = (const IMAGE_RESOURCE_DIRECTORY_ENTRY *)(dir + 1);
(gdb)
Continuing.

Breakpoint 7, find_entry_by_id (dir=0x40768790, id=16393, 
root=0x40768240) at pe_resource.c:82
82          entry = (const IMAGE_RESOURCE_DIRECTORY_ENTRY *)(dir + 1);
(gdb)
Continuing.

Breakpoint 7, find_entry_by_id (dir=0x40768790, id=0, root=0x40768240) 
at pe_resource.c:82
82          entry = (const IMAGE_RESOURCE_DIRECTORY_ENTRY *)(dir + 1);
(gdb)
Continuing.

Breakpoint 7, find_entry_by_id (dir=0x40768790, id=1024, 
root=0x40768240) at pe_resource.c:82
82          entry = (const IMAGE_RESOURCE_DIRECTORY_ENTRY *)(dir + 1);
(gdb)
Continuing.

Breakpoint 7, find_entry_by_id (dir=0x45f000, id=0, root=0x45f000) at 
pe_resource.c:82
82          entry = (const IMAGE_RESOURCE_DIRECTORY_ENTRY *)(dir + 1);

(gdb) p dir
$16 = (IMAGE_RESOURCE_DIRECTORY *) 0x45f000


Better.

(gdb) p *dir
$17 = {Characteristics = 0, TimeDateStamp = 0, MajorVersion = 0, 
MinorVersion = 0,
   NumberOfNamedEntries = 0, NumberOfIdEntries = 0}

Hmm. gdb is able to dereference dir. So what's going on?


(gdb) step
78      {
(gdb) step
82          entry = (const IMAGE_RESOURCE_DIRECTORY_ENTRY *)(dir + 1);
(gdb) step
83          min = dir->NumberOfNamedEntries;
(gdb) p dir
$18 = (IMAGE_RESOURCE_DIRECTORY *) 0x45f000

So far so good.


(gdb) step

Program received signal SIGSEGV, Segmentation fault.

Breakpoint 3, EXC_RtlRaiseException (rec=0x404f3c60, context=0x404f3cdc) 
at exception.c:176
176         TRACE( "code=%lx flags=%lx\n", rec->ExceptionCode, 
rec->ExceptionFlags );


What the #&@*#?!

Looking at the assembly listing for find_entry_by_id, I can see that dir 
is stored in edx, and that edx contains 0xc0000005 at the time the 
signal handler breaks. So maybe that explains why gdb reported dir as 
0xc0000005:

(gdb) info scope pe_resource.c:find_entry_by_id
Scope for pe_resource.c:find_entry_by_id:
Symbol dir is an argument at stack/frame offset 8, length 4.
Symbol id is an argument at stack/frame offset 12, length 4.
Symbol root is an argument at stack/frame offset 16, length 4.
Symbol dir is a local variable in register $edx, length 4.
Symbol id is a local variable at frame offset -14, length 2.
Symbol entry is a local variable at frame offset -12, length 4.
Symbol min is a local variable in register $ecx, length 4.
Symbol max is a local variable in register $esi, length 4.
Symbol pos is a local variable in register $eax, length 4.


So for some reason gdb duplicates the arguments as local variables, and 
then uses the local variable reference to print arguments :P Maybe this 
is the general optimized-code-trace problem.

Anyway, we still haven't explained why the segfault in the first place!

At this point I'm out of ideas. Why would gdb be able to deference dir 
manually, but generate a segfault when running that line?

--Rob






More information about the wine-users mailing list