Alexandre Julliard | 01d6346 | 1997-01-20 19:43:45 +0000 | [diff] [blame] | 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. |
Alexandre Julliard | f0b2354 | 1993-09-29 12:21:49 +0000 | [diff] [blame] | 5 | |
Alexandre Julliard | c6c0944 | 1997-01-12 18:32:19 +0000 | [diff] [blame] | 6 | NEWS: |
Alexandre Julliard | f0b2354 | 1993-09-29 12:21:49 +0000 | [diff] [blame] | 7 | |
Alexandre Julliard | c6c0944 | 1997-01-12 18:32:19 +0000 | [diff] [blame] | 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: |
Alexandre Julliard | f0b2354 | 1993-09-29 12:21:49 +0000 | [diff] [blame] | 11 | |
Alexandre Julliard | c6c0944 | 1997-01-12 18:32:19 +0000 | [diff] [blame] | 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. |
Alexandre Julliard | f0b2354 | 1993-09-29 12:21:49 +0000 | [diff] [blame] | 15 | |
Alexandre Julliard | c6c0944 | 1997-01-12 18:32:19 +0000 | [diff] [blame] | 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 | |
Alexandre Julliard | 01d6346 | 1997-01-20 19:43:45 +0000 | [diff] [blame] | 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 | |
Alexandre Julliard | c6c0944 | 1997-01-12 18:32:19 +0000 | [diff] [blame] | 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 | |
Alexandre Julliard | c6c0944 | 1997-01-12 18:32:19 +0000 | [diff] [blame] | 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. |
Andreas Mohr | c9ec884 | 2001-01-24 19:37:13 +0000 | [diff] [blame] | 110 | Note that this example is rather old and does not necessarily use current |
| 111 | syntax ! |
Alexandre Julliard | c6c0944 | 1997-01-12 18:32:19 +0000 | [diff] [blame] | 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 (KERNEL32_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) )
|
| 159 | 0x081a00fb (DumpFile+0x8c [dumpexe.c:2749]): cmpl $-1,0xffffffe8(%ebp) |
| 160 | Wine-dbg>x/d dwFileSize |
| 161 | x/d dwFileSize
|
| 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
|
| 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
|
| 196 | 0x40007000 (KERNEL32_NULL_THUNK_DATA+0x37e4fe74): *** Invalid address 0x40007000 (KERNEL32_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 (KERNEL32_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
|
| 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
|
| 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
|
| 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]
|
| 340 | {type=STRUCT, next=0x00000000, name="LOGPALETTE", un={basic={basic_type=8, output_format=" V M", 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 | |
Alexandre Julliard | c6c0944 | 1997-01-12 18:32:19 +0000 | [diff] [blame] | 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> |