OSDN Git Service

* aoutx.h (aout_get_external_symbols): Declare 'amt' locally.
[pf3gnuchains/pf3gnuchains3x.git] / rda / win32 / win32-strace.cc
1 /* win32-strace.cc
2
3    Copyright 2000, 2002 Red Hat, Inc.
4
5    This file is part of RDA, the Red Hat Debug Agent (and library).
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 59 Temple Place - Suite 330,
20    Boston, MA 02111-1307, USA.
21    
22    Alternative licenses for RDA may be arranged by contacting Red Hat,
23    Inc.  */
24
25 #include "config.h"
26
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <sys/strace.h>
31
32 #if !HAVE_WINDOWS_H
33 #error The windows.h header is required when compiling for a Win32 target.
34 #endif
35 #include <windows.h>
36 #include <sys/cygwin.h>
37
38 #include "server.h"
39
40 static int
41 output_winerror (FILE *ofile, char *s)
42 {
43   char *winerr = strstr (s, "Win32 error ");
44   if (!winerr)
45     return 0;
46
47   DWORD errnum = atoi (winerr + sizeof ("Win32 error ") - 1);
48   if (!errnum)
49     return 0;
50
51   /*
52    * NOTE: Currently there is no policy for how long the
53    * the buffers are, and looks like 256 is a smallest one
54    * (dlfcn.cc). Other than error 1395 (length 213) and
55    * error 1015 (length 249), the rest are all under 188
56    * characters, and so I'll use 189 as the buffer length.
57    * For those longer error messages, FormatMessage will
58    * return FALSE, and we'll get the old behaviour such as
59    * ``Win32 error 1395'' etc.
60    */
61   char buf[4096];
62   if (!FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM
63                       | FORMAT_MESSAGE_IGNORE_INSERTS,
64                       NULL,
65                       errnum,
66                       MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
67                       (LPTSTR) buf, sizeof (buf), NULL))
68     return 0;
69
70   /* Get rid the trailing CR/NL pair. */
71   char *p = strchr (buf, '\0');
72   p[-2] = '\n';
73   p[-1] = '\0';
74
75   *winerr = '\0';
76   fputs (s, ofile);
77   fputs (buf, ofile);
78   return 1;
79 }
80
81 static SYSTEMTIME *
82 syst (long long t)
83 {
84   FILETIME n;
85   static SYSTEMTIME st;
86   long long now = t + ((long long) 1/*usecs*/ * 10);
87   n.dwHighDateTime = now >> 32;
88   n.dwLowDateTime = now & 0xffffffff;
89   FileTimeToSystemTime (&n, &st);
90   return &st;
91 }
92
93 #define CYGWIN_SIGNAL_STRING "cygwin: signal"
94 #define INTROLEN (3 + 8)
95
96 int
97 win32_output_debug_string (child_process *process, DEBUG_EVENT &ev)
98 {
99   /* This includes the terminating null character already. */
100   DWORD size = ev.u.DebugString.nDebugStringLength;
101   BOOL unicode = ev.u.DebugString.fUnicode;
102
103   char *s = (char *) alloca (unicode ? 2 * size : size);
104
105   if (!ReadProcessMemory (process->process_hdl,
106                           ev.u.DebugString.lpDebugStringData,
107                           s, unicode ? 2 * size : size, NULL))
108     {
109       process->debug ("\nReadProcessMemory failed with error %d\n",
110                       GetLastError ());
111       return 0;
112     }
113   if (!strncmp (s, CYGWIN_SIGNAL_STRING, sizeof CYGWIN_SIGNAL_STRING - 1))
114     {
115       /* Cygwin raised a signal. */
116       process->set_break (strtol (s + sizeof CYGWIN_SIGNAL_STRING - 1, NULL,0));
117
118       process->debug ("Win32: Cygwin raised a signal %d\n",
119                       process->stop_signal ());
120
121       return process->stop_signal ();
122     }
123
124   char *str = s;
125   if (unicode)
126     {
127       str = (char *) alloca (size);
128       WideCharToMultiByte (CP_ACP, 0, (const WCHAR *) s, -1,
129                            str, size, NULL, NULL);
130     }
131
132   if (strncmp (s, "cYg", 3) && process->debug_process ())
133     {
134       fprintf (stderr, "%s\n", s);
135       return 0;
136     }
137
138   if (!process->trace ())
139     return 0;
140
141   int len = (int) strtoul (s + 3, NULL, 16);
142   if (!len)
143     return 0;
144
145   int special;
146   if (len > 0)
147     special = 0;
148   else
149     {
150       special = len;
151       if (special == _STRACE_INTERFACE_ACTIVATE_ADDR)
152         len = 17;
153     }
154   char *buf = s + INTROLEN;
155   buf[len] = '\0';
156
157   s = strtok (buf, " ");
158
159   unsigned n = strtoul (s, NULL, 16);
160
161   s = strchr (s, '\0') + 1;
162
163   if (special == _STRACE_INTERFACE_ACTIVATE_ADDR)
164     {
165       DWORD nbytes;
166       DWORD new_flag = 1;
167       if (!WriteProcessMemory (process->process_hdl, (LPVOID) n, &new_flag,
168                                sizeof (new_flag), &nbytes))
169         process->debug ("Win32: couldn't write strace flag to child, "
170                        "windows error %d", GetLastError ());
171       return 0;
172     }
173
174   char *origs = s;
175
176   if (process->trace () & n)
177     /* got it */ ;
178   else if (!(process->trace () & _STRACE_ALL) || (n & _STRACE_NOTALL))
179     return 0;                   /* This should not be included in "all" output */
180
181   DWORD dusecs, usecs;
182   char *ptusec, *ptrest;
183
184   dusecs = strtoul (s, &ptusec, 10);
185   char *q = ptusec;
186   while (*q == ' ')
187     q++;
188   if (*q != '[')
189     {
190       usecs = strtoul (q, &ptrest, 10);
191       while (*ptrest == ' ')
192         ptrest++;
193     }
194   else
195     {
196       ptrest = q;
197       ptusec = s;
198       usecs = dusecs;
199     }
200
201   if (process->saw_stars == 0)
202     {
203       FILETIME st;
204       char *news;
205
206       GetSystemTimeAsFileTime (&st);
207       FileTimeToLocalFileTime (&st, &st);
208       process->start_time = st.dwHighDateTime;
209       process->start_time <<= 32;
210       process->start_time |= st.dwLowDateTime;
211       if (*(news = ptrest) != '[')
212         process->saw_stars = 2;
213       else
214         {
215           process->saw_stars++;
216           while ((news = strchr (news, ' ')) != NULL && *++news != '*')
217             process->nfields++;
218           if (news == NULL)
219             process->saw_stars++;
220           else
221             {
222               s = news;
223               process->nfields++;
224             }
225         }
226     }
227   else if (process->saw_stars < 2)
228     {
229       int i;
230       char *news;
231       if (*(news = ptrest) != '[')
232         process->saw_stars = 2;
233       else
234         {
235           for (i = 0; i < process->nfields; i++)
236             if ((news = strchr (news, ' ')) == NULL)
237               break;            // Should never happen
238             else
239               news++;
240
241           if (news == NULL)
242             process->saw_stars = 2;
243           else
244             {
245               s = news;
246               if (*s == '*')
247                 {
248                   SYSTEMTIME *st = syst (process->start_time);
249                   fprintf (stderr,
250                            "Date/Time:    %d-%02d-%02d %02d:%02d:%02d\n",
251                            st->wYear, st->wMonth, st->wDay, st->wHour,
252                            st->wMinute, st->wSecond);
253                   process->saw_stars++;
254                 }
255             }
256         }
257     }
258
259   long long d = usecs - process->last_usecs;
260   char intbuf[40];
261
262   s = ptusec;
263   sprintf (intbuf, "%5d ", (int) d);
264   len = strlen (intbuf);
265
266   memcpy ((s -= len), intbuf, len);
267
268   process->last_usecs = usecs;
269   if (!output_winerror (stderr, s))
270     fputs (s, stderr);
271
272   return 0;
273 }