2 * Wine debugger utility routines
4 * Copyright 1993 Eric Youngdale
5 * Copyright 1995 Alexandre Julliard
19 /***********************************************************************
22 * Implementation of the 'print' command.
24 void DEBUG_PrintBasic( const DBG_VALUE
* value
, int count
, char format
)
26 char * default_format
;
29 assert(value
->cookie
== DV_TARGET
|| value
->cookie
== DV_HOST
);
30 if( value
->type
== NULL
)
32 fprintf(stderr
, "Unable to evaluate expression\n");
36 default_format
= NULL
;
37 res
= DEBUG_GetExprValue(value
, &default_format
);
44 DEBUG_nchar
+= fprintf( stderr
, "0x%04lx", (long unsigned int) res
);
48 DEBUG_nchar
+= fprintf( stderr
, "0x%08lx", (long unsigned int) res
);
53 DEBUG_nchar
+= fprintf( stderr
, "%ld\n", (long int) res
);
57 DEBUG_nchar
+= fprintf( stderr
, "%d = '%c'",
58 (char)(res
& 0xff), (char)(res
& 0xff) );
65 fprintf( stderr
, "Format specifier '%c' is meaningless in 'print' command\n", format
);
67 if( default_format
!= NULL
)
69 if (strstr(default_format
, "%S") == NULL
)
71 DEBUG_nchar
+= fprintf( stderr
, default_format
, res
);
78 /* FIXME: simplistic implementation for default_format being
79 * foo%Sbar => will print foo, then string then bar
81 for (ptr
= default_format
; *ptr
; ptr
++)
83 fprintf(stderr
, "[%c]", *ptr
);
85 if (*ptr
== '%') state
++;
91 char* str
= (char*)(long)res
;
93 for (; DEBUG_READ_MEM(str
, &ch
, 1) && ch
; str
++) {
100 /* shouldn't happen */
120 /***********************************************************************
123 * Print an 16- or 32-bit address, with the nearest symbol if any.
126 DEBUG_PrintAddress( const DBG_ADDR
*addr
, int addrlen
, int flag
)
128 struct symbol_info rtn
;
130 const char *name
= DEBUG_FindNearestSymbol( addr
, flag
, &rtn
.sym
, 0,
133 if (addr
->seg
) fprintf( stderr
, "0x%04lx:", addr
->seg
&0xFFFF );
134 if (addrlen
== 16) fprintf( stderr
, "0x%04lx", addr
->off
);
135 else fprintf( stderr
, "0x%08lx", addr
->off
);
136 if (name
) fprintf( stderr
, " (%s)", name
);
139 /***********************************************************************
140 * DEBUG_PrintAddressAndArgs
142 * Print an 16- or 32-bit address, with the nearest symbol if any.
143 * Similar to DEBUG_PrintAddress, but we print the arguments to
144 * each function (if known). This is useful in a backtrace.
147 DEBUG_PrintAddressAndArgs( const DBG_ADDR
*addr
, int addrlen
,
148 unsigned int ebp
, int flag
)
150 struct symbol_info rtn
;
152 const char *name
= DEBUG_FindNearestSymbol( addr
, flag
, &rtn
.sym
, ebp
,
155 if (addr
->seg
) fprintf( stderr
, "0x%04lx:", addr
->seg
);
156 if (addrlen
== 16) fprintf( stderr
, "0x%04lx", addr
->off
);
157 else fprintf( stderr
, "0x%08lx", addr
->off
);
158 if (name
) fprintf( stderr
, " (%s)", name
);
164 /***********************************************************************
167 * Implementation of the 'help' command.
169 void DEBUG_Help(void)
172 static const char * const helptext
[] =
174 "The commands accepted by the Wine debugger are a reasonable",
175 "subset of the commands that gdb accepts.",
176 "The commands currently are:",
178 " break [*<addr>] delete break bpnum",
179 " disable bpnum enable bpnum",
180 " condition <bpnum> [<expr>] pass",
182 " step [N] next [N]",
183 " stepi [N] nexti [N]",
184 " x <addr> print <expr>",
185 " set <reg> = <expr> set *<addr> = <expr>",
187 " list <lines> disassemble [<addr>][,<addr>]",
189 " show dir dir <path>",
190 " display <expr> undisplay <disnum>",
191 " delete display <disnum> debugmsg <class>[-+]<type>\n",
192 " mode [16,32] walk [wnd,class,queue,module,",
193 " whatis process,modref <pid>]",
194 " info (see 'help info' for options)\n",
196 "The 'x' command accepts repeat counts and formats (including 'i') in the",
197 "same way that gdb does.\n",
199 " The following are examples of legal expressions:",
200 " $eax $eax+0x3 0x1000 ($eip + 256) *$eax *($esp + 3)",
201 " Also, a nm format symbol table can be read from a file using the",
202 " symbolfile command. Symbols can also be defined individually with",
203 " the define command.",
208 while(helptext
[i
]) fprintf(stderr
,"%s\n", helptext
[i
++]);
212 /***********************************************************************
215 * Implementation of the 'help info' command.
217 void DEBUG_HelpInfo(void)
220 static const char * const infotext
[] =
222 "The info commands allow you to get assorted bits of interesting stuff",
223 "to be displayed. The options are:",
224 " info break Dumps information about breakpoints",
225 " info display Shows auto-display expressions in use",
226 " info locals Displays values of all local vars for current frame",
227 " info maps Dumps all virtual memory mappings",
228 " info module <handle> Displays internal module state",
229 " info queue <handle> Displays internal queue state",
230 " info reg Displays values in all registers at top of stack",
231 " info segments Dumps information about all known segments",
232 " info share Dumps information about shared libraries",
233 " info stack Dumps information about top of stack",
234 " info wnd <handle> Displays internal window state",
239 while(infotext
[i
]) fprintf(stderr
,"%s\n", infotext
[i
++]);
242 /* FIXME: merge InfoClass and InfoClass2 */
243 void DEBUG_InfoClass(const char* name
)
247 if (!GetClassInfoExA(0, name
, &wca
)) {
248 fprintf(stderr
, "Cannot find class '%s'\n", name
);
252 fprintf(stderr
, "Class '%s':\n", name
);
254 "style=%08x wndProc=%08lx\n"
255 "inst=%04x icon=%04x cursor=%04x bkgnd=%04x\n"
256 "clsExtra=%d winExtra=%d\n",
257 wca
.style
, (DWORD
)wca
.lpfnWndProc
, wca
.hInstance
,
258 wca
.hIcon
, wca
.hCursor
, wca
.hbrBackground
,
259 wca
.cbClsExtra
, wca
.cbWndExtra
);
262 * + print #windows (or even list of windows...)
263 * + print extra bytes => this requires a window handle on this very class...
267 static void DEBUG_InfoClass2(HWND hWnd
, const char* name
)
271 if (!GetClassInfoExA(GetWindowLongA(hWnd
, GWL_HINSTANCE
), name
, &wca
)) {
272 fprintf(stderr
, "Cannot find class '%s'\n", name
);
276 fprintf(stderr
, "Class '%s':\n", name
);
278 "style=%08x wndProc=%08lx\n"
279 "inst=%04x icon=%04x cursor=%04x bkgnd=%04x\n"
280 "clsExtra=%d winExtra=%d\n",
281 wca
.style
, (DWORD
)wca
.lpfnWndProc
, wca
.hInstance
,
282 wca
.hIcon
, wca
.hCursor
, wca
.hbrBackground
,
283 wca
.cbClsExtra
, wca
.cbWndExtra
);
285 if (wca
.cbClsExtra
) {
289 fprintf(stderr
, "Extra bytes:" );
290 for (i
= 0; i
< wca
.cbClsExtra
/ 2; i
++) {
291 w
= GetClassWord(hWnd
, i
* 2);
292 /* FIXME: depends on i386 endian-ity */
293 fprintf(stderr
, " %02x", HIBYTE(w
));
294 fprintf(stderr
, " %02x", LOBYTE(w
));
296 fprintf(stderr
, "\n" );
298 fprintf(stderr
, "\n" );
301 struct class_walker
{
307 static void DEBUG_WalkClassesHelper(HWND hWnd
, struct class_walker
* cw
)
314 if (!GetClassNameA(hWnd
, clsName
, sizeof(clsName
)))
316 if ((atom
= FindAtomA(clsName
)) == 0)
319 for (i
= 0; i
< cw
->used
; i
++) {
320 if (cw
->table
[i
] == atom
)
324 if (cw
->used
>= cw
->alloc
) {
326 cw
->table
= DBG_realloc(cw
->table
, cw
->alloc
* sizeof(ATOM
));
328 cw
->table
[cw
->used
++] = atom
;
329 DEBUG_InfoClass2(hWnd
, clsName
);
332 if ((child
= GetWindow(hWnd
, GW_CHILD
)) != 0)
333 DEBUG_WalkClassesHelper(child
, cw
);
334 } while ((hWnd
= GetWindow(hWnd
, GW_HWNDNEXT
)) != 0);
337 void DEBUG_WalkClasses(void)
339 struct class_walker cw
;
342 cw
.used
= cw
.alloc
= 0;
343 DEBUG_WalkClassesHelper(GetDesktopWindow(), &cw
);
347 void DEBUG_DumpQueue(DWORD q
)
349 fprintf(stderr
, "No longer doing info queue '0x%08lx'\n", q
);
352 void DEBUG_WalkQueues(void)
354 fprintf(stderr
, "No longer walking queues list\n");
357 void DEBUG_InfoWindow(HWND hWnd
)
366 if (!GetClassNameA(hWnd
, clsName
, sizeof(clsName
)))
367 strcpy(clsName
, "-- Unknown --");
368 if (!GetWindowTextA(hWnd
, wndName
, sizeof(wndName
)))
369 strcpy(wndName
, "-- Empty --");
370 if (!GetClientRect(hWnd
, &clientRect
))
371 SetRectEmpty(&clientRect
);
372 if (!GetWindowRect(hWnd
, &windowRect
))
373 SetRectEmpty(&windowRect
);
375 /* FIXME missing fields: hmemTaskQ, hrgnUpdate, dce, flags, pProp, scroll */
377 "next=0x%04x child=0x%04x parent=0x%04x owner=0x%04x class='%s'\n"
378 "inst=%08lx active=%04x idmenu=%08lx\n"
379 "style=%08lx exstyle=%08lx wndproc=%08lx text='%s'\n"
380 "client=%d,%d-%d,%d window=%d,%d-%d,%d sysmenu=%04x\n",
381 GetWindow(hWnd
, GW_HWNDNEXT
),
382 GetWindow(hWnd
, GW_CHILD
),
384 GetWindow(hWnd
, GW_OWNER
),
386 GetWindowLongA(hWnd
, GWL_HINSTANCE
),
387 GetLastActivePopup(hWnd
),
388 GetWindowLongA(hWnd
, GWL_ID
),
389 GetWindowLongA(hWnd
, GWL_STYLE
),
390 GetWindowLongA(hWnd
, GWL_EXSTYLE
),
391 GetWindowLongA(hWnd
, GWL_WNDPROC
),
393 clientRect
.left
, clientRect
.top
, clientRect
.right
, clientRect
.bottom
,
394 windowRect
.left
, windowRect
.top
, windowRect
.right
, windowRect
.bottom
,
395 GetSystemMenu(hWnd
, FALSE
));
397 if (GetClassLongA(hWnd
, GCL_CBWNDEXTRA
)) {
398 fprintf(stderr
, "Extra bytes:" );
399 for (i
= 0; i
< GetClassLongA(hWnd
, GCL_CBWNDEXTRA
) / 2; i
++) {
400 w
= GetWindowWord(hWnd
, i
* 2);
401 /* FIXME: depends on i386 endian-ity */
402 fprintf(stderr
, " %02x", HIBYTE(w
));
403 fprintf(stderr
, " %02x", LOBYTE(w
));
405 fprintf(stderr
, "\n");
407 fprintf(stderr
, "\n");
410 void DEBUG_WalkWindows(HWND hWnd
, int indent
)
417 hWnd
= GetDesktopWindow();
419 if (!indent
) /* first time around */
421 "%-16.16s %-17.17s %-8.8s %s\n",
422 "hwnd", "Class Name", " Style", " WndProc Text");
425 if (!GetClassNameA(hWnd
, clsName
, sizeof(clsName
)))
426 strcpy(clsName
, "-- Unknown --");
427 if (!GetWindowTextA(hWnd
, wndName
, sizeof(wndName
)))
428 strcpy(wndName
, "-- Empty --");
430 /* FIXME: missing hmemTaskQ */
431 fprintf(stderr
, "%*s%04x%*s", indent
, "", hWnd
, 13-indent
,"");
432 fprintf(stderr
, "%-17.17s %08lx %08lx %.14s\n",
433 clsName
, GetWindowLongA(hWnd
, GWL_STYLE
),
434 GetWindowLongA(hWnd
, GWL_WNDPROC
), wndName
);
436 if ((child
= GetWindow(hWnd
, GW_CHILD
)) != 0)
437 DEBUG_WalkWindows(child
, indent
+ 1 );
438 } while ((hWnd
= GetWindow(hWnd
, GW_HWNDNEXT
)) != 0);
441 void DEBUG_WalkProcess(void)
443 fprintf(stderr
, "No longer walking processes list\n");
446 void DEBUG_WalkModref(DWORD p
)
448 fprintf(stderr
, "No longer walking module references list\n");
451 void DEBUG_InfoSegments(DWORD start
, int length
)
457 if (length
== -1) length
= (8192 - start
);
459 for (i
= start
; i
< start
+ length
; i
++)
461 if (!GetThreadSelectorEntry(DEBUG_CurrThread
->handle
, (i
<< 3)|7, &le
))
464 if (le
.HighWord
.Bits
.Type
& 0x08)
466 flags
[0] = (le
.HighWord
.Bits
.Type
& 0x2) ? 'r' : '-';
473 flags
[1] = (le
.HighWord
.Bits
.Type
& 0x2) ? 'w' : '-';
477 "%04lx: sel=%04lx base=%08x limit=%08x %d-bit %c%c%c\n",
479 (le
.HighWord
.Bits
.BaseHi
<< 24) +
480 (le
.HighWord
.Bits
.BaseMid
<< 16) + le
.BaseLow
,
481 ((le
.HighWord
.Bits
.LimitHi
<< 8) + le
.LimitLow
) <<
482 (le
.HighWord
.Bits
.Granularity
? 12 : 0),
483 le
.HighWord
.Bits
.Default_Big
? 32 : 16,
484 flags
[0], flags
[1], flags
[2] );
488 void DEBUG_InfoVirtual(void)
490 fprintf(stderr
, "No longer providing virtual mapping information\n");