1 /* strace.cc: system/windows tracing
3 This file is part of Cygwin.
5 This software is a copyrighted work licensed under the terms of the
6 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
13 #include "perprocess.h"
14 #include "cygwin_version.h"
15 #include "cygthread.h"
20 #include "child_info.h"
23 #define PROTECT(x) {x[NT_MAX_PATH - 1] = '\0';}
24 #define CHECK(x) if (x[NT_MAX_PATH - 1] != '\0') \
25 { small_printf ("array bound exceeded %d\n", __LINE__); \
29 class strace NO_COPY strace
;
34 strace::activate (bool isfork
)
36 if (!_active
&& being_debugged ())
39 __small_sprintf (buf
, "cYg%8x %lx %d",
40 _STRACE_INTERFACE_ACTIVATE_ADDR
, &_active
, isfork
);
41 OutputDebugString (buf
);
48 __small_sprintf (pidbuf
, "(pid %d, ppid %d, windows pid %u)",
49 myself
->pid
, myself
->ppid
?: 1,
50 GetCurrentProcessId ());
51 progname
= myself
->progname
;
55 __small_sprintf (pidbuf
, "(windows pid %u)",
56 GetCurrentProcessId ());
57 progname
= global_progname
;
59 prntf (1, NULL
, "**********************************************");
60 prntf (1, NULL
, "Program name: %W %s", progname
, pidbuf
);
61 prntf (1, NULL
, "OS version: Windows %s", wincap
.osname ());
62 prntf (1, NULL
, "**********************************************");
72 prntf (1, NULL
, "App version: %d.%d, api: %d.%d",
73 user_data
->dll_major
, user_data
->dll_minor
,
74 user_data
->api_major
, user_data
->api_minor
);
75 prntf (1, NULL
, "DLL version: %d.%d, api: %d.%d",
76 cygwin_version
.dll_major
, cygwin_version
.dll_minor
,
77 cygwin_version
.api_major
, cygwin_version
.api_minor
);
78 prntf (1, NULL
, "DLL build: %s", cygwin_version
.dll_build_date
);
83 strace::microseconds ()
85 static LONGLONG process_start NO_COPY
;
86 clk_monotonic_t
*clk
= (clk_monotonic_t
*) get_clock (CLOCK_MONOTONIC
);
89 process_start
= clk
->strace_usecs ();
90 return (int) (clk
->strace_usecs () - process_start
);
94 getfunc (char *in_dst
, const char *func
)
99 for (p
= func
; (pe
= strchr (p
, '(')); p
= pe
+ 1)
100 if (isalnum ((int)pe
[-1]) || pe
[-1] == '_')
102 else if (isspace ((int)pe
[-1]))
108 pe
= strchr (func
, '\0');
109 for (p
= pe
; p
> func
; p
--)
110 if (p
!= pe
&& *p
== ' ')
130 if (myself
&& myself
->pid
)
131 __small_sprintf (buf
, "%d", myself
->pid
);
133 __small_sprintf (buf
, "(%d)", GetCurrentProcessId ());
137 /* sprintf analog for use by output routines. */
139 strace::vsprntf (char *buf
, const char *func
, const char *infmt
, va_list ap
)
143 static NO_COPY
bool nonewline
= false;
144 DWORD err
= GetLastError ();
145 const char *tn
= mythreadname ();
147 int microsec
= microseconds ();
148 lmicrosec
= microsec
;
150 __small_sprintf (fmt
, "%7d [%s] %s ", microsec
, tn
, "%W %s%s");
159 WCHAR progname
[NAME_MAX
];
160 if (cygwin_finished_initializing
&& program_invocation_short_name
)
162 char *p
= strrchr (program_invocation_short_name
, '/');
166 p
= program_invocation_short_name
;
167 char *pe
= strrchr (p
, '.');
168 if (!pe
|| !ascii_strcasematch (pe
, ".exe"))
169 pe
= strrchr (p
, '\0');
170 sys_mbstowcs (pn
= progname
, NAME_MAX
, p
, pe
- p
);
174 PWCHAR p
= wcsrchr (global_progname
, L
'\\');
176 PWCHAR pe
= wcsrchr (p
, '.');
177 if (!pe
|| wcscasecmp (pe
, L
".exe"))
178 pe
= wcsrchr (p
, L
'\0');
179 pe
= wcpncpy (progname
, p
, pe
- p
);
184 count
= __small_sprintf (buf
, fmt
, pn
, mypid (tmpbuf
),
187 count
+= getfunc (buf
+ count
, func
);
190 count
+= __small_vsprintf (buf
+ count
, infmt
, ap
);
192 for (p
= buf
+ count
; p
> buf
; p
--)
215 /* Write to strace file or strace queue. */
217 strace::write (unsigned category
, const char *buf
, int count
)
219 # define PREFIX (3 + 8 + 1 + 8 + 1)
220 char outbuf
[PREFIX
+ 1 + count
+ 1];
221 # define outstuff (outbuf + 12)
222 __small_sprintf (outstuff
, "%x %s", category
, buf
);
223 __small_sprintf (outbuf
, "cYg%08x", strlen (outstuff
) + 1);
225 OutputDebugString (outbuf
);
231 strace::write_childpid (pid_t pid
)
235 if (!attached () || !being_debugged ())
237 __small_sprintf (buf
, "cYg%8x %x", _STRACE_CHILD_PID
, pid
);
238 OutputDebugString (buf
);
241 /* Printf function used when tracing system calls.
242 Warning: DO NOT SET ERRNO HERE! */
243 static NO_COPY muto strace_buf_guard
;
244 static NO_COPY
char *buf
;
247 strace::vprntf (unsigned category
, const char *func
, const char *fmt
, va_list ap
)
249 DWORD err
= GetLastError ();
252 strace_buf_guard
.init ("smallprint_buf")->acquire ();
253 /* Creating buffer on Windows process heap to drop stack pressure and
254 keeping our .bss small. */
256 buf
= (char *) HeapAlloc (GetProcessHeap (), 0, NT_MAX_PATH
);
262 len
= vsprntf (buf
, func
, fmt
, ap
);
264 if (category
& _STRACE_SYSTEM
)
267 WriteFile (GetStdHandle (STD_ERROR_HANDLE
), buf
, len
, &done
, 0);
268 FlushFileBuffers (GetStdHandle (STD_ERROR_HANDLE
));
269 /* Make sure that the message shows up on the screen, too, since this is
271 if (GetFileType (GetStdHandle (STD_ERROR_HANDLE
)) != FILE_TYPE_CHAR
)
273 HANDLE h
= CreateFile ("CONOUT$", GENERIC_READ
| GENERIC_WRITE
,
274 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
275 &sec_none
, OPEN_EXISTING
, 0, 0);
276 if (h
!= INVALID_HANDLE_VALUE
)
278 WriteFile (h
, buf
, len
, &done
, 0);
286 write (category
, buf
, len
);
288 strace_buf_guard
.release ();
293 strace::prntf (unsigned category
, const char *func
, const char *fmt
, ...)
298 vprntf (category
, func
, fmt
, ap
);
303 strace_printf (unsigned category
, const char *func
, const char *fmt
, ...)
307 if ((category
& _STRACE_SYSTEM
) || strace
.active ())
310 strace
.vprntf (category
, func
, fmt
, ap
);
315 static NO_COPY
struct tab
322 { WM_NULL
, "WM_NULL" },
323 { WM_CREATE
, "WM_CREATE" },
324 { WM_DESTROY
, "WM_DESTROY" },
325 { WM_MOVE
, "WM_MOVE" },
326 { WM_SIZE
, "WM_SIZE" },
327 { WM_ACTIVATE
, "WM_ACTIVATE" },
328 { WM_SETFOCUS
, "WM_SETFOCUS" },
329 { WM_KILLFOCUS
, "WM_KILLFOCUS" },
330 { WM_ENABLE
, "WM_ENABLE" },
331 { WM_SETREDRAW
, "WM_SETREDRAW" },
332 { WM_SETTEXT
, "WM_SETTEXT" },
333 { WM_GETTEXT
, "WM_GETTEXT" },
334 { WM_GETTEXTLENGTH
, "WM_GETTEXTLENGTH" },
335 { WM_PAINT
, "WM_PAINT" },
336 { WM_CLOSE
, "WM_CLOSE" },
337 { WM_QUERYENDSESSION
, "WM_QUERYENDSESSION" },
338 { WM_QUIT
, "WM_QUIT" },
339 { WM_QUERYOPEN
, "WM_QUERYOPEN" },
340 { WM_ERASEBKGND
, "WM_ERASEBKGND" },
341 { WM_SYSCOLORCHANGE
, "WM_SYSCOLORCHANGE" },
342 { WM_ENDSESSION
, "WM_ENDSESSION" },
343 { WM_SHOWWINDOW
, "WM_SHOWWINDOW" },
344 { WM_WININICHANGE
, "WM_WININICHANGE" },
345 { WM_DEVMODECHANGE
, "WM_DEVMODECHANGE" },
346 { WM_ACTIVATEAPP
, "WM_ACTIVATEAPP" },
347 { WM_FONTCHANGE
, "WM_FONTCHANGE" },
348 { WM_TIMECHANGE
, "WM_TIMECHANGE" },
349 { WM_CANCELMODE
, "WM_CANCELMODE" },
350 { WM_SETCURSOR
, "WM_SETCURSOR" },
351 { WM_MOUSEACTIVATE
, "WM_MOUSEACTIVATE" },
352 { WM_CHILDACTIVATE
, "WM_CHILDACTIVATE" },
353 { WM_QUEUESYNC
, "WM_QUEUESYNC" },
354 { WM_GETMINMAXINFO
, "WM_GETMINMAXINFO" },
355 { WM_PAINTICON
, "WM_PAINTICON" },
356 { WM_ICONERASEBKGND
, "WM_ICONERASEBKGND" },
357 { WM_NEXTDLGCTL
, "WM_NEXTDLGCTL" },
358 { WM_SPOOLERSTATUS
, "WM_SPOOLERSTATUS" },
359 { WM_DRAWITEM
, "WM_DRAWITEM" },
360 { WM_MEASUREITEM
, "WM_MEASUREITEM" },
361 { WM_DELETEITEM
, "WM_DELETEITEM" },
362 { WM_VKEYTOITEM
, "WM_VKEYTOITEM" },
363 { WM_CHARTOITEM
, "WM_CHARTOITEM" },
364 { WM_SETFONT
, "WM_SETFONT" },
365 { WM_GETFONT
, "WM_GETFONT" },
366 { WM_SETHOTKEY
, "WM_SETHOTKEY" },
367 { WM_GETHOTKEY
, "WM_GETHOTKEY" },
368 { WM_QUERYDRAGICON
, "WM_QUERYDRAGICON" },
369 { WM_COMPAREITEM
, "WM_COMPAREITEM" },
370 { WM_COMPACTING
, "WM_COMPACTING" },
371 { WM_WINDOWPOSCHANGING
, "WM_WINDOWPOSCHANGING" },
372 { WM_WINDOWPOSCHANGED
, "WM_WINDOWPOSCHANGED" },
373 { WM_POWER
, "WM_POWER" },
374 { WM_COPYDATA
, "WM_COPYDATA" },
375 { WM_CANCELJOURNAL
, "WM_CANCELJOURNAL" },
376 { WM_NCCREATE
, "WM_NCCREATE" },
377 { WM_NCDESTROY
, "WM_NCDESTROY" },
378 { WM_NCCALCSIZE
, "WM_NCCALCSIZE" },
379 { WM_NCHITTEST
, "WM_NCHITTEST" },
380 { WM_NCPAINT
, "WM_NCPAINT" },
381 { WM_NCACTIVATE
, "WM_NCACTIVATE" },
382 { WM_GETDLGCODE
, "WM_GETDLGCODE" },
383 { WM_NCMOUSEMOVE
, "WM_NCMOUSEMOVE" },
384 { WM_NCLBUTTONDOWN
, "WM_NCLBUTTONDOWN" },
385 { WM_NCLBUTTONUP
, "WM_NCLBUTTONUP" },
386 { WM_NCLBUTTONDBLCLK
, "WM_NCLBUTTONDBLCLK" },
387 { WM_NCRBUTTONDOWN
, "WM_NCRBUTTONDOWN" },
388 { WM_NCRBUTTONUP
, "WM_NCRBUTTONUP" },
389 { WM_NCRBUTTONDBLCLK
, "WM_NCRBUTTONDBLCLK" },
390 { WM_NCMBUTTONDOWN
, "WM_NCMBUTTONDOWN" },
391 { WM_NCMBUTTONUP
, "WM_NCMBUTTONUP" },
392 { WM_NCMBUTTONDBLCLK
, "WM_NCMBUTTONDBLCLK" },
393 { WM_KEYFIRST
, "WM_KEYFIRST" },
394 { WM_KEYDOWN
, "WM_KEYDOWN" },
395 { WM_KEYUP
, "WM_KEYUP" },
396 { WM_CHAR
, "WM_CHAR" },
397 { WM_DEADCHAR
, "WM_DEADCHAR" },
398 { WM_SYSKEYDOWN
, "WM_SYSKEYDOWN" },
399 { WM_SYSKEYUP
, "WM_SYSKEYUP" },
400 { WM_SYSCHAR
, "WM_SYSCHAR" },
401 { WM_SYSDEADCHAR
, "WM_SYSDEADCHAR" },
402 { WM_KEYLAST
, "WM_KEYLAST" },
403 { WM_INITDIALOG
, "WM_INITDIALOG" },
404 { WM_COMMAND
, "WM_COMMAND" },
405 { WM_SYSCOMMAND
, "WM_SYSCOMMAND" },
406 { WM_TIMER
, "WM_TIMER" },
407 { WM_HSCROLL
, "WM_HSCROLL" },
408 { WM_VSCROLL
, "WM_VSCROLL" },
409 { WM_INITMENU
, "WM_INITMENU" },
410 { WM_INITMENUPOPUP
, "WM_INITMENUPOPUP" },
411 { WM_MENUSELECT
, "WM_MENUSELECT" },
412 { WM_MENUCHAR
, "WM_MENUCHAR" },
413 { WM_ENTERIDLE
, "WM_ENTERIDLE" },
414 { WM_CTLCOLORMSGBOX
, "WM_CTLCOLORMSGBOX" },
415 { WM_CTLCOLOREDIT
, "WM_CTLCOLOREDIT" },
416 { WM_CTLCOLORLISTBOX
, "WM_CTLCOLORLISTBOX" },
417 { WM_CTLCOLORBTN
, "WM_CTLCOLORBTN" },
418 { WM_CTLCOLORDLG
, "WM_CTLCOLORDLG" },
419 { WM_CTLCOLORSCROLLBAR
, "WM_CTLCOLORSCROLLBAR" },
420 { WM_CTLCOLORSTATIC
, "WM_CTLCOLORSTATIC" },
421 { WM_MOUSEFIRST
, "WM_MOUSEFIRST" },
422 { WM_MOUSEMOVE
, "WM_MOUSEMOVE" },
423 { WM_LBUTTONDOWN
, "WM_LBUTTONDOWN" },
424 { WM_LBUTTONUP
, "WM_LBUTTONUP" },
425 { WM_LBUTTONDBLCLK
, "WM_LBUTTONDBLCLK" },
426 { WM_RBUTTONDOWN
, "WM_RBUTTONDOWN" },
427 { WM_RBUTTONUP
, "WM_RBUTTONUP" },
428 { WM_RBUTTONDBLCLK
, "WM_RBUTTONDBLCLK" },
429 { WM_MBUTTONDOWN
, "WM_MBUTTONDOWN" },
430 { WM_MBUTTONUP
, "WM_MBUTTONUP" },
431 { WM_MBUTTONDBLCLK
, "WM_MBUTTONDBLCLK" },
432 { WM_MOUSELAST
, "WM_MOUSELAST" },
433 { WM_PARENTNOTIFY
, "WM_PARENTNOTIFY" },
434 { WM_ENTERMENULOOP
, "WM_ENTERMENULOOP" },
435 { WM_EXITMENULOOP
, "WM_EXITMENULOOP" },
436 { WM_MDICREATE
, "WM_MDICREATE" },
437 { WM_MDIDESTROY
, "WM_MDIDESTROY" },
438 { WM_MDIACTIVATE
, "WM_MDIACTIVATE" },
439 { WM_MDIRESTORE
, "WM_MDIRESTORE" },
440 { WM_MDINEXT
, "WM_MDINEXT" },
441 { WM_MDIMAXIMIZE
, "WM_MDIMAXIMIZE" },
442 { WM_MDITILE
, "WM_MDITILE" },
443 { WM_MDICASCADE
, "WM_MDICASCADE" },
444 { WM_MDIICONARRANGE
, "WM_MDIICONARRANGE" },
445 { WM_MDIGETACTIVE
, "WM_MDIGETACTIVE" },
446 { WM_MDISETMENU
, "WM_MDISETMENU" },
447 { WM_DROPFILES
, "WM_DROPFILES" },
448 { WM_MDIREFRESHMENU
, "WM_MDIREFRESHMENU" },
449 { WM_CUT
, "WM_CUT" },
450 { WM_COPY
, "WM_COPY" },
451 { WM_PASTE
, "WM_PASTE" },
452 { WM_CLEAR
, "WM_CLEAR" },
453 { WM_UNDO
, "WM_UNDO" },
454 { WM_RENDERFORMAT
, "WM_RENDERFORMAT" },
455 { WM_RENDERALLFORMATS
, "WM_RENDERALLFORMATS" },
456 { WM_DESTROYCLIPBOARD
, "WM_DESTROYCLIPBOARD" },
457 { WM_DRAWCLIPBOARD
, "WM_DRAWCLIPBOARD" },
458 { WM_PAINTCLIPBOARD
, "WM_PAINTCLIPBOARD" },
459 { WM_VSCROLLCLIPBOARD
, "WM_VSCROLLCLIPBOARD" },
460 { WM_SIZECLIPBOARD
, "WM_SIZECLIPBOARD" },
461 { WM_ASKCBFORMATNAME
, "WM_ASKCBFORMATNAME" },
462 { WM_CHANGECBCHAIN
, "WM_CHANGECBCHAIN" },
463 { WM_HSCROLLCLIPBOARD
, "WM_HSCROLLCLIPBOARD" },
464 { WM_QUERYNEWPALETTE
, "WM_QUERYNEWPALETTE" },
465 { WM_PALETTEISCHANGING
, "WM_PALETTEISCHANGING" },
466 { WM_PALETTECHANGED
, "WM_PALETTECHANGED" },
467 { WM_HOTKEY
, "WM_HOTKEY" },
468 { WM_PENWINFIRST
, "WM_PENWINFIRST" },
469 { WM_PENWINLAST
, "WM_PENWINLAST" },
470 { WM_ASYNCIO
, "ASYNCIO" },
474 strace::wm (int message
, int word
, int lon
)
480 for (i
= 0; ta
[i
].n
; i
++)
482 if (ta
[i
].v
== message
)
484 prntf (_STRACE_WM
, NULL
, "wndproc %d %s %d %d", message
, ta
[i
].n
, word
, lon
);
488 prntf (_STRACE_WM
, NULL
, "wndproc %d unknown %d %d", message
, word
, lon
);