2 * Wine debugger utility routines
4 * Copyright 1993 Eric Youngdale
5 * Copyright 1995 Alexandre Julliard
18 /***********************************************************************
21 * Implementation of the 'print' command.
23 void DEBUG_PrintBasic( const DBG_ADDR *addr, int count, char format )
25 char * default_format;
28 if( addr->type == NULL )
30 fprintf(stderr, "Unable to evaluate expression\n");
34 default_format = NULL;
35 value = DEBUG_GetExprValue(addr, &default_format);
42 DEBUG_nchar += fprintf( stderr, "0x%04lx", (long unsigned int) value );
46 DEBUG_nchar += fprintf( stderr, "0x%08lx", (long unsigned int) value );
51 DEBUG_nchar += fprintf( stderr, "%ld\n", (long int) value );
55 DEBUG_nchar += fprintf( stderr, "%d = '%c'",
56 (char)(value & 0xff), (char)(value & 0xff) );
63 fprintf( stderr, "Format specifier '%c' is meaningless in 'print' command\n", format );
65 if( default_format != NULL )
67 DEBUG_nchar += fprintf( stderr, default_format, value );
74 /***********************************************************************
77 * Print an 16- or 32-bit address, with the nearest symbol if any.
80 DEBUG_PrintAddress( const DBG_ADDR *addr, int addrlen, int flag )
82 struct symbol_info rtn;
84 const char *name = DEBUG_FindNearestSymbol( addr, flag, &rtn.sym, 0,
87 if (addr->seg) fprintf( stderr, "0x%04lx:", addr->seg&0xFFFF );
88 if (addrlen == 16) fprintf( stderr, "0x%04lx", addr->off );
89 else fprintf( stderr, "0x%08lx", addr->off );
90 if (name) fprintf( stderr, " (%s)", name );
93 /***********************************************************************
94 * DEBUG_PrintAddressAndArgs
96 * Print an 16- or 32-bit address, with the nearest symbol if any.
97 * Similar to DEBUG_PrintAddress, but we print the arguments to
98 * each function (if known). This is useful in a backtrace.
101 DEBUG_PrintAddressAndArgs( const DBG_ADDR *addr, int addrlen,
102 unsigned int ebp, int flag )
104 struct symbol_info rtn;
106 const char *name = DEBUG_FindNearestSymbol( addr, flag, &rtn.sym, ebp,
109 if (addr->seg) fprintf( stderr, "0x%04lx:", addr->seg );
110 if (addrlen == 16) fprintf( stderr, "0x%04lx", addr->off );
111 else fprintf( stderr, "0x%08lx", addr->off );
112 if (name) fprintf( stderr, " (%s)", name );
118 /***********************************************************************
121 * Implementation of the 'help' command.
123 void DEBUG_Help(void)
126 static const char * const helptext[] =
128 "The commands accepted by the Wine debugger are a reasonable",
129 "subset of the commands that gdb accepts.",
130 "The commands currently are:",
132 " break [*<addr>] delete break bpnum",
133 " disable bpnum enable bpnum",
134 " condition <bpnum> [<expr>] pass",
136 " step [N] next [N]",
137 " stepi [N] nexti [N]",
138 " x <addr> print <expr>",
139 " set <reg> = <expr> set *<addr> = <expr>",
141 " list <lines> disassemble [<addr>][,<addr>]",
143 " show dir dir <path>",
144 " display <expr> undisplay <disnum>",
145 " delete display <disnum> debugmsg <class>[-+]<type>\n",
146 " mode [16,32] walk [wnd,class,queue,module,",
147 " process,modref <pid>]",
148 " info (see 'help info' for options)\n",
150 "The 'x' command accepts repeat counts and formats (including 'i') in the",
151 "same way that gdb does.\n",
153 " The following are examples of legal expressions:",
154 " $eax $eax+0x3 0x1000 ($eip + 256) *$eax *($esp + 3)",
155 " Also, a nm format symbol table can be read from a file using the",
156 " symbolfile command. Symbols can also be defined individually with",
157 " the define command.",
162 while(helptext[i]) fprintf(stderr,"%s\n", helptext[i++]);
166 /***********************************************************************
169 * Implementation of the 'help info' command.
171 void DEBUG_HelpInfo(void)
174 static const char * const infotext[] =
176 "The info commands allow you to get assorted bits of interesting stuff",
177 "to be displayed. The options are:",
178 " info break Dumps information about breakpoints",
179 " info display Shows auto-display expressions in use",
180 " info locals Displays values of all local vars for current frame",
181 " info maps Dumps all virtual memory mappings",
182 " info module <handle> Displays internal module state",
183 " info queue <handle> Displays internal queue state",
184 " info reg Displays values in all registers at top of stack",
185 " info segments Dumps information about all known segments",
186 " info share Dumps information about shared libraries",
187 " info stack Dumps information about top of stack",
188 " info wnd <handle> Displays internal window state",
193 while(infotext[i]) fprintf(stderr,"%s\n", infotext[i++]);
196 /* FIXME: merge InfoClass and InfoClass2 */
197 void DEBUG_InfoClass(const char* name)
201 if (!GetClassInfoExA(0, name, &wca)) {
202 fprintf(stderr, "Cannot find class '%s'\n", name);
206 fprintf(stderr, "Class '%s':\n", name);
208 "style=%08x wndProc=%08lx\n"
209 "inst=%04x icon=%04x cursor=%04x bkgnd=%04x\n"
210 "clsExtra=%d winExtra=%d\n",
211 wca.style, (DWORD)wca.lpfnWndProc, wca.hInstance,
212 wca.hIcon, wca.hCursor, wca.hbrBackground,
213 wca.cbClsExtra, wca.cbWndExtra);
216 * + print #windows (or even list of windows...)
217 * + print extra bytes => this requires a window handle on this very class...
221 static void DEBUG_InfoClass2(HWND hWnd, const char* name)
225 if (!GetClassInfoExA(GetWindowLongA(hWnd, GWL_HINSTANCE), name, &wca)) {
226 fprintf(stderr, "Cannot find class '%s'\n", name);
230 fprintf(stderr, "Class '%s':\n", name);
232 "style=%08x wndProc=%08lx\n"
233 "inst=%04x icon=%04x cursor=%04x bkgnd=%04x\n"
234 "clsExtra=%d winExtra=%d\n",
235 wca.style, (DWORD)wca.lpfnWndProc, wca.hInstance,
236 wca.hIcon, wca.hCursor, wca.hbrBackground,
237 wca.cbClsExtra, wca.cbWndExtra);
239 if (wca.cbClsExtra) {
243 fprintf(stderr, "Extra bytes:" );
244 for (i = 0; i < wca.cbClsExtra / 2; i++) {
245 w = GetClassWord(hWnd, i * 2);
246 /* FIXME: depends on i386 endian-ity */
247 fprintf(stderr, " %02x", HIBYTE(w));
248 fprintf(stderr, " %02x", LOBYTE(w));
250 fprintf(stderr, "\n" );
252 fprintf(stderr, "\n" );
255 struct class_walker {
261 static void DEBUG_WalkClassesHelper(HWND hWnd, struct class_walker* cw)
268 if (!GetClassNameA(hWnd, clsName, sizeof(clsName)))
270 if ((atom = FindAtomA(clsName)) == 0)
273 for (i = 0; i < cw->used; i++) {
274 if (cw->table[i] == atom)
278 if (cw->used >= cw->alloc) {
280 cw->table = DBG_realloc(cw->table, cw->alloc * sizeof(ATOM));
282 cw->table[cw->used++] = atom;
283 DEBUG_InfoClass2(hWnd, clsName);
286 if ((child = GetWindow(hWnd, GW_CHILD)) != 0)
287 DEBUG_WalkClassesHelper(child, cw);
288 } while ((hWnd = GetWindow(hWnd, GW_HWNDNEXT)) != 0);
291 void DEBUG_WalkClasses(void)
293 struct class_walker cw;
296 cw.used = cw.alloc = 0;
297 DEBUG_WalkClassesHelper(GetDesktopWindow(), &cw);
301 void DEBUG_DumpModule(DWORD mod)
303 fprintf(stderr, "No longer doing info module '0x%08lx'\n", mod);
306 void DEBUG_WalkModules(void)
308 fprintf(stderr, "No longer walking modules list\n");
311 void DEBUG_DumpQueue(DWORD q)
313 fprintf(stderr, "No longer doing info queue '0x%08lx'\n", q);
316 void DEBUG_WalkQueues(void)
318 fprintf(stderr, "No longer walking queues list\n");
321 void DEBUG_InfoWindow(HWND hWnd)
330 if (!GetClassNameA(hWnd, clsName, sizeof(clsName)))
331 strcpy(clsName, "-- Unknown --");
332 if (!GetWindowTextA(hWnd, wndName, sizeof(wndName)))
333 strcpy(wndName, "-- Empty --");
334 if (!GetClientRect(hWnd, &clientRect))
335 SetRectEmpty(&clientRect);
336 if (!GetWindowRect(hWnd, &windowRect))
337 SetRectEmpty(&windowRect);
339 /* FIXME missing fields: hmemTaskQ, hrgnUpdate, dce, flags, pProp, scroll */
341 "next=0x%04x child=0x%04x parent=0x%04x owner=0x%04x class='%s'\n"
342 "inst=%08lx active=%04x idmenu=%08lx\n"
343 "style=%08lx exstyle=%08lx wndproc=%08lx text='%s'\n"
344 "client=%d,%d-%d,%d window=%d,%d-%d,%d sysmenu=%04x\n",
345 GetWindow(hWnd, GW_HWNDNEXT),
346 GetWindow(hWnd, GW_CHILD),
348 GetWindow(hWnd, GW_OWNER),
350 GetWindowLongA(hWnd, GWL_HINSTANCE),
351 GetLastActivePopup(hWnd),
352 GetWindowLongA(hWnd, GWL_ID),
353 GetWindowLongA(hWnd, GWL_STYLE),
354 GetWindowLongA(hWnd, GWL_EXSTYLE),
355 GetWindowLongA(hWnd, GWL_WNDPROC),
357 clientRect.left, clientRect.top, clientRect.right, clientRect.bottom,
358 windowRect.left, windowRect.top, windowRect.right, windowRect.bottom,
359 GetSystemMenu(hWnd, FALSE));
361 if (GetClassLongA(hWnd, GCL_CBWNDEXTRA)) {
362 fprintf(stderr, "Extra bytes:" );
363 for (i = 0; i < GetClassLongA(hWnd, GCL_CBWNDEXTRA) / 2; i++) {
364 w = GetWindowWord(hWnd, i * 2);
365 /* FIXME: depends on i386 endian-ity */
366 fprintf(stderr, " %02x", HIBYTE(w));
367 fprintf(stderr, " %02x", LOBYTE(w));
369 fprintf(stderr, "\n");
371 fprintf(stderr, "\n");
374 void DEBUG_WalkWindows(HWND hWnd, int indent)
381 hWnd = GetDesktopWindow();
383 if (!indent) /* first time around */
385 "%-16.16s %-17.17s %-8.8s %s\n",
386 "hwnd", "Class Name", " Style", " WndProc Text");
389 if (!GetClassNameA(hWnd, clsName, sizeof(clsName)))
390 strcpy(clsName, "-- Unknown --");
391 if (!GetWindowTextA(hWnd, wndName, sizeof(wndName)))
392 strcpy(wndName, "-- Empty --");
394 /* FIXME: missing hmemTaskQ */
395 fprintf(stderr, "%*s%04x%*s", indent, "", hWnd, 13-indent,"");
396 fprintf(stderr, "%-17.17s %08lx %08lx %.14s\n",
397 clsName, GetWindowLongA(hWnd, GWL_STYLE),
398 GetWindowLongA(hWnd, GWL_WNDPROC), wndName);
400 if ((child = GetWindow(hWnd, GW_CHILD)) != 0)
401 DEBUG_WalkWindows(child, indent + 1 );
402 } while ((hWnd = GetWindow(hWnd, GW_HWNDNEXT)) != 0);
405 void DEBUG_WalkProcess(void)
407 fprintf(stderr, "No longer walking processes list\n");
410 void DEBUG_WalkModref(DWORD p)
412 fprintf(stderr, "No longer walking module references list\n");
415 void DEBUG_InfoSegments(DWORD start, int length)
421 if (length == -1) length = (8192 - start);
423 for (i = start; i < start + length; i++)
425 if (!GetThreadSelectorEntry(DEBUG_CurrThread->handle, (i << 3)|7, &le))
428 if (le.HighWord.Bits.Type & 0x08)
430 flags[0] = (le.HighWord.Bits.Type & 0x2) ? 'r' : '-';
437 flags[1] = (le.HighWord.Bits.Type & 0x2) ? 'w' : '-';
441 "%04lx: sel=%04lx base=%08x limit=%08x %d-bit %c%c%c\n",
443 (le.HighWord.Bits.BaseHi << 24) +
444 (le.HighWord.Bits.BaseMid << 16) + le.BaseLow,
445 ((le.HighWord.Bits.LimitHi << 8) + le.LimitLow) <<
446 (le.HighWord.Bits.Granularity ? 12 : 0),
447 le.HighWord.Bits.Default_Big ? 32 : 16,
448 flags[0], flags[1], flags[2] );
452 void DEBUG_InfoVirtual(void)
454 fprintf(stderr, "No longer providing virtual mapping information\n");