OSDN Git Service

36dcae533f4b62a3ee3030bc11234708df38223e
[pf3gnuchains/pf3gnuchains3x.git] / winsup / cygwin / strace.cc
1 /* strace.cc: system/windows tracing
2
3    Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
4    2006, 2007, 2008 Red Hat, Inc.
5
6 This file is part of Cygwin.
7
8 This software is a copyrighted work licensed under the terms of the
9 Cygwin license.  Please consult the file "CYGWIN_LICENSE" for
10 details. */
11
12 #include "winsup.h"
13 #include <stdlib.h>
14 #include <time.h>
15 #include <wingdi.h>
16 #include <winuser.h>
17 #include <ctype.h>
18 #include "cygerrno.h"
19 #include "pinfo.h"
20 #include "perprocess.h"
21 #include "cygwin_version.h"
22 #include "hires.h"
23 #include "security.h"
24 #include "cygthread.h"
25 #include "path.h"
26 #include "fhandler.h"
27 #include "dtable.h"
28 #include "cygheap.h"
29 #include "child_info.h"
30
31 #define PROTECT(x) x[sizeof (x)-1] = 0
32 #define CHECK(x) if (x[sizeof (x)-1] != 0) { small_printf ("array bound exceeded %d\n", __LINE__); ExitProcess (1); }
33
34 class strace NO_COPY strace;
35
36 #ifndef NOSTRACE
37
38 void
39 strace::hello ()
40 {
41   if (_active || !being_debugged ())
42     return;
43
44   char buf[30];
45   __small_sprintf (buf, "cYg%8x %x", _STRACE_INTERFACE_ACTIVATE_ADDR, &_active);
46   OutputDebugString (buf);
47
48   if (active ())
49     {
50       char pidbuf[40];
51       if (myself->progname[0])
52         __small_sprintf (pidbuf, "(pid %d, ppid %d)", myself->pid, myself->ppid ?: 1);
53       else
54         {
55           GetModuleFileName (NULL, myself->progname, sizeof (myself->progname));
56           __small_sprintf (pidbuf, "(windows pid %d)", GetCurrentProcessId ());
57         }
58       prntf (1, NULL, "**********************************************");
59       prntf (1, NULL, "Program name: %s %s", myself->progname, pidbuf);
60       prntf (1, NULL, "App version:  %d.%d, api: %d.%d",
61              user_data->dll_major, user_data->dll_minor,
62              user_data->api_major, user_data->api_minor);
63       prntf (1, NULL, "DLL version:  %d.%d, api: %d.%d",
64              cygwin_version.dll_major, cygwin_version.dll_minor,
65              cygwin_version.api_major, cygwin_version.api_minor);
66       prntf (1, NULL, "DLL build:    %s", cygwin_version.dll_build_date);
67       prntf (1, NULL, "OS version:   Windows %s", wincap.osname ());
68       if (cygheap)
69         prntf (1, NULL, "Heap size:    %u", cygheap->user_heap.chunk);
70       prntf (1, NULL, "**********************************************");
71     }
72 }
73
74 int
75 strace::microseconds ()
76 {
77   static hires_us now;
78   return (int) now.usecs (true);
79 }
80
81 static int __stdcall
82 getfunc (char *in_dst, const char *func)
83 {
84   const char *p;
85   const char *pe;
86   char *dst = in_dst;
87   for (p = func; (pe = strchr (p, '(')); p = pe + 1)
88     if (isalnum ((int)pe[-1]) || pe[-1] == '_')
89       break;
90     else if (isspace ((int)pe[-1]))
91       {
92         pe--;
93         break;
94       }
95   if (!pe)
96     pe = strchr (func, '\0');
97   for (p = pe; p > func; p--)
98     if (p != pe && *p == ' ')
99       {
100         p++;
101         break;
102       }
103   if (*p == '*')
104     p++;
105   while (p < pe)
106     *dst++ = *p++;
107
108   *dst++ = ':';
109   *dst++ = ' ';
110   *dst = '\0';
111
112   return dst - in_dst;
113 }
114
115 static char *
116 mypid (char *buf)
117 {
118   if (myself && myself->pid)
119     __small_sprintf (buf, "%d", myself->pid);
120   else
121     __small_sprintf (buf, "(%d)", cygwin_pid (GetCurrentProcessId ()));
122   return buf;
123 }
124
125 extern "C" char *__progname;
126
127 /* sprintf analog for use by output routines. */
128 int
129 strace::vsprntf (char *buf, const char *func, const char *infmt, va_list ap)
130 {
131   int count;
132   char fmt[80];
133   static NO_COPY bool nonewline = false;
134   DWORD err = GetLastError ();
135   const char *tn = cygthread::name ();
136
137   int microsec = microseconds ();
138   lmicrosec = microsec;
139
140   __small_sprintf (fmt, "%7d [%s] %s ", microsec, tn, "%s %s%s");
141
142   SetLastError (err);
143
144   if (nonewline)
145     count = 0;
146   else
147     {
148       char *pn;
149       if (!cygwin_finished_initializing)
150         pn = myself ? myself->progname : NULL;
151       else if (__progname)
152         pn = __progname;
153       else
154         pn = NULL;
155
156       char *p;
157       char progname[NT_MAX_PATH];
158       if (!pn)
159         GetModuleFileName (NULL, pn = progname, sizeof (progname));
160       if (!pn)
161         /* hmm */;
162       else if ((p = strrchr (pn, '\\')) != NULL)
163         p++;
164       else if ((p = strrchr (pn, '/')) != NULL)
165         p++;
166       else
167         p = pn;
168       if (p != progname)
169         strcpy (progname, p);
170       if ((p = strrchr (progname, '.')) != NULL
171           && ascii_strcasematch (p, ".exe"))
172         *p = '\000';
173       p = progname;
174       char tmpbuf[20];
175       count = __small_sprintf (buf, fmt, p && *p ? p : "?", mypid (tmpbuf),
176                                execing ? "!" : "");
177       if (func)
178         count += getfunc (buf + count, func);
179     }
180
181   count += __small_vsprintf (buf + count, infmt, ap);
182   char *p;
183   for (p = buf + count; p > buf; p--)
184     switch (p[-1])
185       {
186         case '\n':
187           p[-1] = '\0';
188           break;
189         case '\b':
190           *--p = '\0';
191            nonewline = true;
192           goto done;
193         default:
194           goto addnl;
195       }
196
197 addnl:
198   *p++ = '\n';
199   *p = '\0';
200   nonewline = false;
201
202 done:
203   return p - buf;
204 }
205
206 /* Write to strace file or strace queue. */
207 void
208 strace::write (unsigned category, const char *buf, int count)
209 {
210 # define PREFIX (3 + 8 + 1 + 8 + 1)
211   char outbuf[PREFIX + 1 + count + 1];
212 # define outstuff (outbuf + 12)
213   __small_sprintf (outstuff, "%x %s", category, buf);
214   __small_sprintf (outbuf, "cYg%08x", strlen (outstuff) + 1);
215   outstuff[-1] = ' ';
216   OutputDebugString (outbuf);
217 #undef outstuff
218 #undef PREFIX
219 }
220
221 void
222 strace::write_childpid (child_info& ch, DWORD pid)
223 {
224   char buf[30];
225
226   if (!attached () || !being_debugged ())
227     return;
228   WaitForSingleObject (ch.subproc_ready, 30000);
229   __small_sprintf (buf, "cYg%8x %x", _STRACE_CHILD_PID, pid);
230   OutputDebugString (buf);
231 }
232
233 /* Printf function used when tracing system calls.
234    Warning: DO NOT SET ERRNO HERE! */
235
236 void
237 strace::vprntf (unsigned category, const char *func, const char *fmt, va_list ap)
238 {
239   DWORD err = GetLastError ();
240   int len;
241   char buf[10000];
242
243   PROTECT (buf);
244   SetLastError (err);
245
246   len = vsprntf (buf, func, fmt, ap);
247   CHECK (buf);
248   if (category & _STRACE_SYSTEM)
249     {
250       DWORD done;
251       WriteFile (GetStdHandle (STD_ERROR_HANDLE), buf, len, &done, 0);
252       FlushFileBuffers (GetStdHandle (STD_ERROR_HANDLE));
253       /* Make sure that the message shows up on the screen, too, since this is
254          a serious error. */
255       if (GetFileType (GetStdHandle (STD_ERROR_HANDLE)) != FILE_TYPE_CHAR)
256         {
257           HANDLE h = CreateFile ("CONOUT$", GENERIC_READ | GENERIC_WRITE,
258                                  FILE_SHARE_WRITE | FILE_SHARE_WRITE,
259                                  &sec_none, OPEN_EXISTING, 0, 0);
260           if (h != INVALID_HANDLE_VALUE)
261             WriteFile (h, buf, len, &done, 0);
262           CloseHandle (h);
263         }
264     }
265
266 #ifndef NOSTRACE
267   if (active ())
268     write (category, buf, len);
269 #endif
270   SetLastError (err);
271 }
272
273 void
274 strace::prntf (unsigned category, const char *func, const char *fmt, ...)
275 {
276   va_list ap;
277
278   va_start (ap, fmt);
279   vprntf (category, func, fmt, ap);
280 }
281
282 extern "C" void
283 strace_printf (unsigned category, const char *func, const char *fmt, ...)
284 {
285   va_list ap;
286
287   if ((category & _STRACE_SYSTEM) || strace.active ())
288     {
289       va_start (ap, fmt);
290       strace.vprntf (category, func, fmt, ap);
291     }
292 }
293
294 static NO_COPY struct tab
295 {
296   int v;
297   const char *n;
298 }
299 ta[] =
300 {
301   {  WM_NULL, "WM_NULL"  },
302   {  WM_CREATE, "WM_CREATE"  },
303   {  WM_DESTROY, "WM_DESTROY"  },
304   {  WM_MOVE, "WM_MOVE"  },
305   {  WM_SIZE, "WM_SIZE"  },
306   {  WM_ACTIVATE, "WM_ACTIVATE"  },
307   {  WM_SETFOCUS, "WM_SETFOCUS"  },
308   {  WM_KILLFOCUS, "WM_KILLFOCUS"  },
309   {  WM_ENABLE, "WM_ENABLE"  },
310   {  WM_SETREDRAW, "WM_SETREDRAW"  },
311   {  WM_SETTEXT, "WM_SETTEXT"  },
312   {  WM_GETTEXT, "WM_GETTEXT"  },
313   {  WM_GETTEXTLENGTH, "WM_GETTEXTLENGTH"  },
314   {  WM_PAINT, "WM_PAINT"  },
315   {  WM_CLOSE, "WM_CLOSE"  },
316   {  WM_QUERYENDSESSION, "WM_QUERYENDSESSION"  },
317   {  WM_QUIT, "WM_QUIT"  },
318   {  WM_QUERYOPEN, "WM_QUERYOPEN"  },
319   {  WM_ERASEBKGND, "WM_ERASEBKGND"  },
320   {  WM_SYSCOLORCHANGE, "WM_SYSCOLORCHANGE"  },
321   {  WM_ENDSESSION, "WM_ENDSESSION"  },
322   {  WM_SHOWWINDOW, "WM_SHOWWINDOW"  },
323   {  WM_WININICHANGE, "WM_WININICHANGE"  },
324   {  WM_DEVMODECHANGE, "WM_DEVMODECHANGE"  },
325   {  WM_ACTIVATEAPP, "WM_ACTIVATEAPP"  },
326   {  WM_FONTCHANGE, "WM_FONTCHANGE"  },
327   {  WM_TIMECHANGE, "WM_TIMECHANGE"  },
328   {  WM_CANCELMODE, "WM_CANCELMODE"  },
329   {  WM_SETCURSOR, "WM_SETCURSOR"  },
330   {  WM_MOUSEACTIVATE, "WM_MOUSEACTIVATE"  },
331   {  WM_CHILDACTIVATE, "WM_CHILDACTIVATE"  },
332   {  WM_QUEUESYNC, "WM_QUEUESYNC"  },
333   {  WM_GETMINMAXINFO, "WM_GETMINMAXINFO"  },
334   {  WM_PAINTICON, "WM_PAINTICON"  },
335   {  WM_ICONERASEBKGND, "WM_ICONERASEBKGND"  },
336   {  WM_NEXTDLGCTL, "WM_NEXTDLGCTL"  },
337   {  WM_SPOOLERSTATUS, "WM_SPOOLERSTATUS"  },
338   {  WM_DRAWITEM, "WM_DRAWITEM"  },
339   {  WM_MEASUREITEM, "WM_MEASUREITEM"  },
340   {  WM_DELETEITEM, "WM_DELETEITEM"  },
341   {  WM_VKEYTOITEM, "WM_VKEYTOITEM"  },
342   {  WM_CHARTOITEM, "WM_CHARTOITEM"  },
343   {  WM_SETFONT, "WM_SETFONT"  },
344   {  WM_GETFONT, "WM_GETFONT"  },
345   {  WM_SETHOTKEY, "WM_SETHOTKEY"  },
346   {  WM_GETHOTKEY, "WM_GETHOTKEY"  },
347   {  WM_QUERYDRAGICON, "WM_QUERYDRAGICON"  },
348   {  WM_COMPAREITEM, "WM_COMPAREITEM"  },
349   {  WM_COMPACTING, "WM_COMPACTING"  },
350   {  WM_WINDOWPOSCHANGING, "WM_WINDOWPOSCHANGING"  },
351   {  WM_WINDOWPOSCHANGED, "WM_WINDOWPOSCHANGED"  },
352   {  WM_POWER, "WM_POWER"  },
353   {  WM_COPYDATA, "WM_COPYDATA"  },
354   {  WM_CANCELJOURNAL, "WM_CANCELJOURNAL"  },
355   {  WM_NCCREATE, "WM_NCCREATE"  },
356   {  WM_NCDESTROY, "WM_NCDESTROY"  },
357   {  WM_NCCALCSIZE, "WM_NCCALCSIZE"  },
358   {  WM_NCHITTEST, "WM_NCHITTEST"  },
359   {  WM_NCPAINT, "WM_NCPAINT"  },
360   {  WM_NCACTIVATE, "WM_NCACTIVATE"  },
361   {  WM_GETDLGCODE, "WM_GETDLGCODE"  },
362   {  WM_NCMOUSEMOVE, "WM_NCMOUSEMOVE"  },
363   {  WM_NCLBUTTONDOWN, "WM_NCLBUTTONDOWN"  },
364   {  WM_NCLBUTTONUP, "WM_NCLBUTTONUP"  },
365   {  WM_NCLBUTTONDBLCLK, "WM_NCLBUTTONDBLCLK"  },
366   {  WM_NCRBUTTONDOWN, "WM_NCRBUTTONDOWN"  },
367   {  WM_NCRBUTTONUP, "WM_NCRBUTTONUP"  },
368   {  WM_NCRBUTTONDBLCLK, "WM_NCRBUTTONDBLCLK"  },
369   {  WM_NCMBUTTONDOWN, "WM_NCMBUTTONDOWN"  },
370   {  WM_NCMBUTTONUP, "WM_NCMBUTTONUP"  },
371   {  WM_NCMBUTTONDBLCLK, "WM_NCMBUTTONDBLCLK"  },
372   {  WM_KEYFIRST, "WM_KEYFIRST"  },
373   {  WM_KEYDOWN, "WM_KEYDOWN"  },
374   {  WM_KEYUP, "WM_KEYUP"  },
375   {  WM_CHAR, "WM_CHAR"  },
376   {  WM_DEADCHAR, "WM_DEADCHAR"  },
377   {  WM_SYSKEYDOWN, "WM_SYSKEYDOWN"  },
378   {  WM_SYSKEYUP, "WM_SYSKEYUP"  },
379   {  WM_SYSCHAR, "WM_SYSCHAR"  },
380   {  WM_SYSDEADCHAR, "WM_SYSDEADCHAR"  },
381   {  WM_KEYLAST, "WM_KEYLAST"  },
382   {  WM_INITDIALOG, "WM_INITDIALOG"  },
383   {  WM_COMMAND, "WM_COMMAND"  },
384   {  WM_SYSCOMMAND, "WM_SYSCOMMAND"  },
385   {  WM_TIMER, "WM_TIMER"  },
386   {  WM_HSCROLL, "WM_HSCROLL"  },
387   {  WM_VSCROLL, "WM_VSCROLL"  },
388   {  WM_INITMENU, "WM_INITMENU"  },
389   {  WM_INITMENUPOPUP, "WM_INITMENUPOPUP"  },
390   {  WM_MENUSELECT, "WM_MENUSELECT"  },
391   {  WM_MENUCHAR, "WM_MENUCHAR"  },
392   {  WM_ENTERIDLE, "WM_ENTERIDLE"  },
393   {  WM_CTLCOLORMSGBOX, "WM_CTLCOLORMSGBOX"  },
394   {  WM_CTLCOLOREDIT, "WM_CTLCOLOREDIT"  },
395   {  WM_CTLCOLORLISTBOX, "WM_CTLCOLORLISTBOX"  },
396   {  WM_CTLCOLORBTN, "WM_CTLCOLORBTN"  },
397   {  WM_CTLCOLORDLG, "WM_CTLCOLORDLG"  },
398   {  WM_CTLCOLORSCROLLBAR, "WM_CTLCOLORSCROLLBAR"  },
399   {  WM_CTLCOLORSTATIC, "WM_CTLCOLORSTATIC"  },
400   {  WM_MOUSEFIRST, "WM_MOUSEFIRST"  },
401   {  WM_MOUSEMOVE, "WM_MOUSEMOVE"  },
402   {  WM_LBUTTONDOWN, "WM_LBUTTONDOWN"  },
403   {  WM_LBUTTONUP, "WM_LBUTTONUP"  },
404   {  WM_LBUTTONDBLCLK, "WM_LBUTTONDBLCLK"  },
405   {  WM_RBUTTONDOWN, "WM_RBUTTONDOWN"  },
406   {  WM_RBUTTONUP, "WM_RBUTTONUP"  },
407   {  WM_RBUTTONDBLCLK, "WM_RBUTTONDBLCLK"  },
408   {  WM_MBUTTONDOWN, "WM_MBUTTONDOWN"  },
409   {  WM_MBUTTONUP, "WM_MBUTTONUP"  },
410   {  WM_MBUTTONDBLCLK, "WM_MBUTTONDBLCLK"  },
411   {  WM_MOUSELAST, "WM_MOUSELAST"  },
412   {  WM_PARENTNOTIFY, "WM_PARENTNOTIFY"  },
413   {  WM_ENTERMENULOOP, "WM_ENTERMENULOOP"  },
414   {  WM_EXITMENULOOP, "WM_EXITMENULOOP"  },
415   {  WM_MDICREATE, "WM_MDICREATE"  },
416   {  WM_MDIDESTROY, "WM_MDIDESTROY"  },
417   {  WM_MDIACTIVATE, "WM_MDIACTIVATE"  },
418   {  WM_MDIRESTORE, "WM_MDIRESTORE"  },
419   {  WM_MDINEXT, "WM_MDINEXT"  },
420   {  WM_MDIMAXIMIZE, "WM_MDIMAXIMIZE"  },
421   {  WM_MDITILE, "WM_MDITILE"  },
422   {  WM_MDICASCADE, "WM_MDICASCADE"  },
423   {  WM_MDIICONARRANGE, "WM_MDIICONARRANGE"  },
424   {  WM_MDIGETACTIVE, "WM_MDIGETACTIVE"  },
425   {  WM_MDISETMENU, "WM_MDISETMENU"  },
426   {  WM_DROPFILES, "WM_DROPFILES"  },
427   {  WM_MDIREFRESHMENU, "WM_MDIREFRESHMENU"  },
428   {  WM_CUT, "WM_CUT"  },
429   {  WM_COPY, "WM_COPY"  },
430   {  WM_PASTE, "WM_PASTE"  },
431   {  WM_CLEAR, "WM_CLEAR"  },
432   {  WM_UNDO, "WM_UNDO"  },
433   {  WM_RENDERFORMAT, "WM_RENDERFORMAT"  },
434   {  WM_RENDERALLFORMATS, "WM_RENDERALLFORMATS"  },
435   {  WM_DESTROYCLIPBOARD, "WM_DESTROYCLIPBOARD"  },
436   {  WM_DRAWCLIPBOARD, "WM_DRAWCLIPBOARD"  },
437   {  WM_PAINTCLIPBOARD, "WM_PAINTCLIPBOARD"  },
438   {  WM_VSCROLLCLIPBOARD, "WM_VSCROLLCLIPBOARD"  },
439   {  WM_SIZECLIPBOARD, "WM_SIZECLIPBOARD"  },
440   {  WM_ASKCBFORMATNAME, "WM_ASKCBFORMATNAME"  },
441   {  WM_CHANGECBCHAIN, "WM_CHANGECBCHAIN"  },
442   {  WM_HSCROLLCLIPBOARD, "WM_HSCROLLCLIPBOARD"  },
443   {  WM_QUERYNEWPALETTE, "WM_QUERYNEWPALETTE"  },
444   {  WM_PALETTEISCHANGING, "WM_PALETTEISCHANGING"  },
445   {  WM_PALETTECHANGED, "WM_PALETTECHANGED"  },
446   {  WM_HOTKEY, "WM_HOTKEY"  },
447   {  WM_PENWINFIRST, "WM_PENWINFIRST"  },
448   {  WM_PENWINLAST, "WM_PENWINLAST"  },
449   {  WM_ASYNCIO, "ASYNCIO"  },
450   {  0, 0  }};
451
452 void
453 strace::wm (int message, int word, int lon)
454 {
455   if (active ())
456     {
457       int i;
458
459       for (i = 0; ta[i].n; i++)
460         {
461           if (ta[i].v == message)
462             {
463               prntf (_STRACE_WM, NULL, "wndproc %d %s %d %d", message, ta[i].n, word, lon);
464               return;
465             }
466         }
467       prntf (_STRACE_WM, NULL, "wndproc %d unknown  %d %d", message, word, lon);
468     }
469 }
470 #endif /*NOSTRACE*/