Include <stdlib.h> needed by exit().
[wine] / debugger / README
1         This is the core of the Wine debugger.  The reverse assember
2 was stolen from Mach more or less intact.  It turns out that there are
3 two variables that are set differently if you are reverse assembling
4 16 bit code, and on the whole it seems to work.
5
6 NEWS:
7
8         The internal debugger has *tons* more capability than it did before.
9 I have enclosed some examples that show usage at the end of this file.
10 New features include:
11
12         1) Ability of debugger to read debug information from wine executable
13 *and* from Win32 executables.  Local variable and line number information is
14 also read and processed.
15
16         2) The internal debugger is capable of 'stepping' to the next
17 line number, just like gdb.  Examples of the commands are:
18
19         step
20         stepi
21         si
22         step 3
23         si 5
24         next
25         nexti
26         cont 4
27         finish
28
29 All of these should be exactly like how gdb does things.
30
31         3) The internal debugger now has a sense of what source file and line
32 number a given PC is at.  New commands to support this are just like gdb,
33 and include:
34
35         list
36         dir
37         show dir
38
39 there are a variety of formats of arguments for the list command.  All
40 permutations supported by gdb should also be supported.
41
42         4) The internal debugger knows about datatypes of various objects,
43 for both Win32 *and* the debugging information in the wine executable itself.
44 I have enclosed an example of how this works at the end.
45
46         5) There are more ways the 'b' command can be used to set breakpoints.
47 Examples are:
48
49         b *0x8190000
50         b 1100
51         b Usage
52         b
53
54 I don't think this covers all of the permutations that gdb accepts (this should
55 be cleaned up someday so that all possibilities are acceptable).
56
57         6)  The 'print' and 'x' commands should behave more or less exactly
58 as they do under gdb.  The difference is that the way the data is presented
59 will be slightly different, but the content should be fundamentally the same.
60
61         7) The internal debugger now supports conditional breakpoints, and
62 automatic display expressions.  An example is at the end of this file.  The
63 syntax and usage should be identical to that of gdb.
64
65         8) Type casts can be made from within the debugger, but they currently
66 don't work with typedef'ed types.  They only work with builtin types and
67 named structures unions, etc.  The problem is that internally we don't always
68 record the typedefed names of structures, so we have no guarantee that we
69 would know what each type is.  This can be fixed, of course -  it just takes
70 more memory.  Note that in some cases, typedefed structures could be cast
71 using '(struct typedfname)' instead of '(typedfname)'.   Technically this
72 isn't quite correct, but if and when the rest of this stuff gets fixed,
73 this would need to get corrected too.
74
75 NOTES:
76
77         If it weren't for the fact that gdb doesn't grok the Win32 debug
78 information, you could just use gdb.  The internal debugger should be able
79 to read and use debugging information for both Win32 and also for the
80 Wine executable, making it possible to debug the combination of the two
81 together as if it were one large (very large) entity.
82
83 LIMITATIONS AND DIFFERENCES FROM GDB:
84
85         You cannot set a breakpoint by file and line number as you can
86 with gdb.  Adding support for this wouldn't be all that tough, I guess, but
87 it would be a nuisance.   You can set a breakpoint given a function and
88 line number, however.  An example would be 'b main:2993'.  It turns out
89 that the way the internal data structures are arranged it is a whole lot
90 easier to do things in this way than it would be to try and get the
91 source:line type of breakpoint working, but it would probably be worth it
92 to try.
93
94         Getting stack traces through Wine itself can be a bit tricky.
95 This is because by default the thing is built with optimization
96 enabled, and as a result sometimes functions don't get frames, and
97 lots of variables are optimized into registers.  You can turn off
98 optimization for a few key source files if it will help you.
99
100         Memory consumption is getting to be a real problem.  I think 32Mb is
101 no longer sufficient to debug wine - 48 or 64 is probably a whole lot better.
102 Unfortunately I cannot shut down X to save memory :-).
103
104 *************************************************************************
105 EXAMPLES:
106
107         Here is an example of how I tracked down a bug in Wine.  The program
108 is something that just maps and dumps the contents of a Win32 executable.
109 It was dying for some reason.
110 Note that this example is rather old and does not necessarily use current
111 syntax !
112
113 Start the first time through.
114
115 bash$ ls -l dumpexe.exe 
116 -rw-rw-r--   1 eric     devel      168448 Jan  4 13:51 dumpexe.exe
117 bash$ ./wine -debug './dumpexe.exe -symbol ./dumpexe.exe'
118 Warning: invalid dir 'e:\test' in path, deleting it.
119 Win32 task 'W32SXXXX': Breakpoint 1 at 0x081a3450
120 Loading symbols from ELF file ./wine...
121 Loading symbols from ELF file /usr/X11R6/lib/libXpm.so.4.6...
122 Loading symbols from ELF file /usr/X11R6/lib/libSM.so.6.0...
123 Loading symbols from ELF file /usr/X11R6/lib/libICE.so.6.0...
124 Loading symbols from ELF file /usr/X11R6/lib/libXext.so.6.0...
125 Loading symbols from ELF file /usr/X11R6/lib/libX11.so.6.0...
126 Loading symbols from ELF file /lib/libm.so.5.0.5...
127 Loading symbols from ELF file /lib/libc.so.5.2.18...
128 Loading symbols from ELF file /lib/ld-linux.so.1...
129 Loading symbols from Win32 file ./dumpexe.exe...
130 Stopped on breakpoint 1 at 0x081a3450 (_mainCRTStartup)
131 In 32 bit mode.
132 *** Invalid address 0x414c5ff8 (\7fKERNEL32_NULL_THUNK_DATA+0x3930ee6c)
133 0x081a3450 (_mainCRTStartup):  movl     %fs:0,%eax
134 Wine-dbg>b DumpFile
135 Breakpoint 2 at 0x081a0078 (DumpFile+0x9 [dumpexe.c:2723])
136 Wine-dbg>c
137 Dump File: ./dumpexe.exe
138 Stopped on breakpoint 2 at 0x081a0078 (DumpFile+0x9 [dumpexe.c:2723])
139 Enter path to file dumpexe.c: ../de
140 2723            HANDLE                    hFile = NULL;
141 0x081a0078 (DumpFile+0x9 [dumpexe.c:2723]):  movl       $0x0,0xfffffff4(%ebp)
142 Wine-dbg>list
143 2723            HANDLE                    hFile = NULL;
144 2724            HANDLE                    hMap  = NULL;
145 2725            PSTR                      lpMap = NULL;
146 2726            DWORD                     dwFileSize     = 0;
147 2727            DWORD                     dwFileSizeHigh = 0;
148 2728    
149 2729            PIMAGE_DOS_HEADER         lpImageDOS  = NULL;
150 2730            PIMAGE_FILE_HEADER        lpImageFile = NULL;
151 2731            PIMAGE_NT_HEADERS         lpImageNT   = NULL;
152 2732    
153 2733            /*
154 Wine-dbg>n 10
155 2747            dwFileSize = GetFileSize(hFile, &dwFileSizeHigh);
156 0x081a00ea (DumpFile+0x7b [dumpexe.c:2747]):  leal      0xfffffff0(%ebp),%eax
157 Wine-dbg>n
158 2749                && (GetLastError() != NO_ERROR) )\r
159 0x081a00fb (DumpFile+0x8c [dumpexe.c:2749]):  cmpl      $-1,0xffffffe8(%ebp)
160 Wine-dbg>x/d dwFileSize
161 x/d dwFileSize\r
162  168448
163 Wine-dbg>n
164 2758                                     PAGE_READONLY, 0, 0, (LPSTR) NULL);
165 0x081a0124 (DumpFile+0xb5 [dumpexe.c:2758]):  pushl     $0x0
166 Wine-dbg>list 2750
167 list 2750\r
168 2750            {
169 2751                    Fatal("Cannot get size of file %s", lpFileName);
170 2752            }
171 2753            
172 2754            /*
173 2755             * map the file
174 2756             */
175 2757            hMap = CreateFileMapping(hFile, (LPSECURITY_ATTRIBUTES) NULL,
176 2758                                     PAGE_READONLY, 0, 0, (LPSTR) NULL);
177 2759            if( hMap == NULL )
178 2760            {
179 Wine-dbg>n
180 2759            if( hMap == NULL )
181 0x081a013b (DumpFile+0xcc [dumpexe.c:2759]):  cmpl      $0,0xfffffffc(%ebp)
182 Wine-dbg>x hMap
183  08e48c30
184 Wine-dbg>n
185 2767            lpMap = (LPSTR) MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0);
186 0x081a0156 (DumpFile+0xe7 [dumpexe.c:2767]):  pushl     $0x0
187 Wine-dbg>n
188 2768            if( lpMap == NULL )
189 0x081a016b (DumpFile+0xfc [dumpexe.c:2768]):  cmpl      $0,0xffffffe0(%ebp)
190 Wine-dbg>print lpMap
191 0x414c5f40
192 Wine-dbg>x lpMap
193  40007000
194 Wine-dbg> x/10x 0x40007000
195  x/10x 0x40007000\r
196 0x40007000 (\7fKERNEL32_NULL_THUNK_DATA+0x37e4fe74): *** Invalid address 0x40007000 (\7fKERNEL32_NULL_THUNK_DATA+0x37e4fe74)
197 Wine-dbg>quit
198 $
199
200 *******************************************************************
201 The first time through, we find that MapViewOfFile isn't mapping the file
202 correctly into the virtual address space.  Try running again, and step into
203 MapViewOfFile to figure out what went wrong.
204 *******************************************************************
205
206
207 bash$ ./wine -debug './dumpexe.exe -symbol ./dumpexe.exe'
208 Warning: invalid dir 'e:\test' in path, deleting it.
209 Win32 task 'W32SXXXX': Breakpoint 1 at 0x081a3450
210 Loading symbols from ELF file ./wine...
211 Loading symbols from ELF file /usr/X11R6/lib/libXpm.so.4.6...
212 Loading symbols from ELF file /usr/X11R6/lib/libSM.so.6.0...
213 Loading symbols from ELF file /usr/X11R6/lib/libICE.so.6.0...
214 Loading symbols from ELF file /usr/X11R6/lib/libXext.so.6.0...
215 Loading symbols from ELF file /usr/X11R6/lib/libX11.so.6.0...
216 Loading symbols from ELF file /lib/libm.so.5.0.5...
217 Loading symbols from ELF file /lib/libc.so.5.2.18...
218 Loading symbols from ELF file /lib/ld-linux.so.1...
219 Loading symbols from Win32 file ./dumpexe.exe...
220 Stopped on breakpoint 1 at 0x081a3450 (_mainCRTStartup)
221 In 32 bit mode.
222 *** Invalid address 0x414c5ff8 (\7fKERNEL32_NULL_THUNK_DATA+0x3930ee6c)
223 0x081a3450 (_mainCRTStartup):  movl     %fs:0,%eax
224 Wine-dbg>b DumpFile:2767
225 Breakpoint 2 at 0x081a0156 (DumpFile+0xe7 [dumpexe.c:2767])
226 Wine-dbg>c
227 Dump File: ./dumpexe.exe\r
228 Stopped on breakpoint 2 at 0x081a0156 (DumpFile+0xe7 [dumpexe.c:2767])
229 Enter path to file dumpexe.c: ../de
230 2767            lpMap = (LPSTR) MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0);
231 0x081a0156 (DumpFile+0xe7 [dumpexe.c:2767]):  pushl     $0x0
232 Wine-dbg>step
233 390     0385 stdcall MapViewOfFile(long long long long long) MapViewOfFile
234 0x080d793c (KERNEL32_385 [kernel32.spec:390]):  pushl   %ebp
235 Wine-dbg>step
236 223         if (!debugging_relay) return;
237 0x080c83dc (RELAY_DebugCallFrom32+0xc [relay.c:223]):  cmpw     $0,0x644a
238 Wine-dbg>
239 244     }
240 0x080c848e (RELAY_DebugCallFrom32+0xbe [relay.c:244]):  leal    0xfffffff4(%ebp),%esp
241 Wine-dbg>
242 103         return MapViewOfFileEx(handle,access,offhi,offlo,size,0);
243 0x080911a4 (MapViewOfFile+0x14 [file.c:103]):  pushl    $0x0
244 Wine-dbg>
245 113         FILEMAP_OBJECT *fmap = (FILEMAP_OBJECT*)handle;
246 0x080911cf (MapViewOfFileEx+0xf [file.c:113]):  movl    0x8(%ebp),%esi
247 Wine-dbg>n
248 115         if (!size) size = fmap->size;
249 0x080911d2 (MapViewOfFileEx+0x12 [file.c:115]):  testl  %ebx,%ebx
250 Wine-dbg>list
251 list\r
252 115         if (!size) size = fmap->size;
253 116         if (!size) size = 1;
254 117         return mmap ((caddr_t)st, size, fmap->prot, 
255 118                      MAP_ANON|MAP_PRIVATE, 
256 119                      FILE_GetUnixHandle(fmap->hfile),
257 120                      offlo);
258 121     }
259 122     
260 123     /***********************************************************************
261 124      *           UnmapViewOfFile                  (KERNEL32.385)
262 125      */
263 Wine-dbg>x size
264  00000000
265 Wine-dbg>n
266 116         if (!size) size = 1;
267 0x080911d9 (MapViewOfFileEx+0x19 [file.c:116]):  testl  %ebx,%ebx
268 Wine-dbg>x size
269  00000000
270 Wine-dbg>n
271 117         return mmap ((caddr_t)st, size, fmap->prot, 
272 0x080911e2 (MapViewOfFileEx+0x22 [file.c:117]):  pushl  %eax
273 Wine-dbg>x size
274  00000000
275 Wine-dbg>info local
276 MapViewOfFileEx:handle == 0x08e48c90
277 MapViewOfFileEx:access == 0x00000004
278 MapViewOfFileEx:offhi == 0x00000000
279 MapViewOfFileEx:offlo == 0x00000000
280 MapViewOfFileEx:size == 0x00000000
281 MapViewOfFileEx:st == 0x00000000
282 MapViewOfFileEx:offlo optimized into register $eax 
283 MapViewOfFileEx:size optimized into register $ebx 
284 MapViewOfFileEx:st optimized into register $edi 
285 MapViewOfFileEx:fmap optimized into register $esi 
286 Wine-dbg>print $ebx
287 0x0001
288 Wine-dbg>bt
289 bt\r
290 Backtrace:
291 =>0 0x080911e2 (MapViewOfFileEx+0x22 [file.c:117])
292   1 0x080911b0 (MapViewOfFile+0x20(handle=0x8e48c90, access=0x4, offhi=0x0, offlo=0x0, size=0x0) [file.c:104])
293   2 0x08104ab5 (CallFrom32_stdcall_5+0x25 [callfrom32.s])
294   3 0x081a0168 (DumpFile+0xf9(lpFileName=0x414c61ed) [dumpexe.c:2767])
295   4 0x081a0c35 (main+0x410(argc=0x3, argv=0x414c61cc) [dumpexe.c:3078])
296   5 0x081a3514 (_mainCRTStartup+0xc4)
297   6 0x0810549f (Code_Start+0x13 [callto32.s])
298   7 0x0802fdac (TASK_CallToStart+0x8c [task.c:373])
299
300 Wine-dbg>
301
302 *******************************************************************
303 Notice that you can step through the thunks into our own transfer
304 routines.   You will notice that the source line displays as something
305 like:
306
307 390     0385 stdcall MapViewOfFile(long long long long long) MapViewOfFile
308
309 This is just the source line from the spec file that caused the transfer
310 routine to be generated.  From this you can step again, and you step
311 into the relay logging code - keep stepping and you eventually step into
312 the actual function that does the dirty work.
313
314         At this point an examination of the source to the Win32 program
315 and an examination of the source to win32/file.s showed where the problem
316 was.  When you specify 0 for the size of the object in CreateFileMapping,
317 it is supposed to use the entire size of the file as the size of the
318 object.  Instead we were just blindly copying the number over.
319
320 *******************************************************************
321
322 Wine-dbg>b main
323 Breakpoint 1 at 0x080108c0 (main [dbgmain.c:213])
324 Wine-dbg>print breakpoints[1]
325 {addr={type=0x08043000, seg=0, off=134285504}, addrlen=' ', opcode='U', enabled=1, skipcount=0, in_use=1}
326
327 Wine-dbg> print breakpoints[1].enabled
328 1
329 Wine-dbg>set breakpoints[0].enabled = 0
330 Wine-dbg>print breakpoints[0].enabled
331 0
332
333 Wine-dbg>print type_hash_table[1]->type
334 STRUCT
335
336 Wine-dbg>print type_hash_table[1]
337 0x08072020
338 Wine-dbg>print *type_hash_table[1]
339 print *type_hash_table[1]\r
340 {type=STRUCT, next=0x00000000, name="LOGPALETTE", un={basic={basic_type=8, output_format=" V\1d\b M\1d\b", basic_size=-128, b_signed=0}, bitfield={bitoff=8, nbits=0, basetype=0x081d56c0}, pointer={pointsto=0x00000008}, funct={rettype=0x00000008}, array={start=8, end=136140480, basictype=0x08043e80}, structure={size=8, members=0x081d56c0}, enumeration={members=0x00000008}}}
341 Wine-dbg>
342
343 *******************************************************************
344
345         This example shows how you can print out various data structures.
346 Note that enumerated types are displayed in the symbolic form, and strings
347 are displayed in the expected manner.
348
349         You can use the set command to set more or less anything.  Note
350 however that you cannot use enumerated types on the RHS of the expression.
351
352 *******************************************************************
353
354
355 Wine-dbg>list
356 2986            if( argc <= 1 )
357 2987            {
358 2988                    Usage(argv[0]);
359 2989            }
360 2990
361 2991            for( i = 1; i < argc; i++ )
362 2992            {
363 2993                    if( strncmp(argv[i], "-dos", sizeof("-dos") - 1) == 0 )
364 2994                    {
365 2995                            DmpCtrl.bDumpDOSHeader = TRUE;
366 2996                    }
367 Wine-dbg>b 2993
368 Breakpoint 3 at 0x081a8861 (main+0x3c [dumpexe.c:2993])
369 Wine-dbg>condition 3 i == 2
370 Wine-dbg>c
371 Stopped on breakpoint 3 at 0x081a8861 (main+0x3c [dumpexe.c:2993])
372 2993                    if( strncmp(argv[i], "-dos", sizeof("-dos") - 1) == 0 )
373 0x081a8861 (main+0x3c [dumpexe.c:2993]):  pushl $0x4
374 Wine-dbg>print i
375 2
376 Wine-dbg>print argv[i]
377 "./dumpexe.exe"
378
379 *******************************************************************
380
381         This example shows how to use conditional breakpoints.
382         Here is another one that demonstrates another cool feature
383         conditional breakpoints that involve a function call:
384
385                 condition 3 strcmp(argv[i], "./dumpexe.exe") == 0
386
387 *******************************************************************
388
389
390 Wine-dbg>list
391 2986            if( argc <= 1 )
392 2987            {
393 2988                    Usage(argv[0]);
394 2989            }
395 2990
396 2991            for( i = 1; i < argc; i++ )
397 2992            {
398 2993                    if( strncmp(argv[i], "-dos", sizeof("-dos") - 1) == 0 )
399 2994                    {
400 2995                            DmpCtrl.bDumpDOSHeader = TRUE;
401 2996                    }
402 Wine-dbg>b 2993
403 Breakpoint 3 at 0x081a8861 (main+0x3c [dumpexe.c:2993])
404 Wine-dbg>condition 3 strcmp(argv[i], "./dumpexe.exe") == 0
405 Wine-dbg>info break
406 Breakpoints:
407 1: y 0x081ab450 (_mainCRTStartup)
408 2: y 0x081a882e (main+0x9 [dumpexe.c:2986])
409 3: y 0x081a8861 (main+0x3c [dumpexe.c:2993])
410                 stop when  ( strcmp(( argv[i] ), "./dumpexe.exe") == 0 )
411 Wine-dbg>c
412 Stopped on breakpoint 3 at 0x081a8861 (main+0x3c [dumpexe.c:2993])
413 2993                    if( strncmp(argv[i], "-dos", sizeof("-dos") - 1) == 0 )
414 0x081a8861 (main+0x3c [dumpexe.c:2993]):  pushl $0x4
415 Wine-dbg>print i
416 2
417 Wine-dbg>print argv[i]  
418 "./dumpexe.exe"
419 Wine-dbg>