OSDN Git Service

ChangeLog rotation for 2010.
[pf3gnuchains/pf3gnuchains3x.git] / rda / win32 / server.h
1 /* server.h
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 extern "C" {
26 #include "gdbserv.h" 
27 #include "gdbserv-target.h" 
28 #include "gdbserv-utils.h"
29 #include "gdbsocket.h"
30 #include "gdbloop.h"
31 };
32
33 /* Various possibilities for alloca.  */
34 #ifndef alloca
35 #ifdef __GNUC__
36 #define alloca __builtin_alloca
37 #else /* Not GNU C */
38 #ifdef HAVE_ALLOCA_H
39 #include <alloca.h>
40 #else
41 #ifdef _AIX
42 #pragma alloca
43 #else
44
45 /* We need to be careful not to declare this in a way which conflicts with
46    bison.  Bison never declares it as char *, but under various circumstances
47    (like __hpux) we need to use void *.  */
48 extern void *alloca ();
49 #endif /* Not _AIX */
50 #endif /* Not HAVE_ALLOCA_H */
51 #endif /* Not GNU C */
52 #endif /* alloca not defined */
53
54 /* Sequence of bytes for breakpoint instruction.  */
55 #define SIZEOF_BP  1
56 #define BREAKPOINT {0xcc}
57
58 #define FLAG_TRACE_BIT 0x100
59
60 enum proc_state {
61   Running,
62   Break,
63   Exit,
64   Terminate
65 };
66
67 class breakpoint {
68   BOOL  used;
69   DWORD bp_address;
70   char  bp_instruction[SIZEOF_BP];
71
72 public:
73   breakpoint () : used (FALSE), bp_address(0)
74     {
75       memset (bp_instruction, 0, SIZEOF_BP);
76     }
77   breakpoint (DWORD naddress, char *nbp_inst)
78   : used (TRUE), bp_address(naddress)
79     {
80       memcpy (bp_instruction, nbp_inst, SIZEOF_BP);
81     }
82   virtual ~breakpoint () {}
83
84   BOOL in_use () const { return used; }
85   DWORD address () const { return used ? bp_address : 0L; }
86   const char *instruction () const { return used ? bp_instruction : NULL; }
87   operator DWORD() const { return used ? bp_address : 0L; }
88
89   void set_in_use (BOOL nin_use) { used = nin_use; }
90 };
91
92 class bp_array {
93   breakpoint  *bp;
94   int          max_cnt;
95   int          cur_cnt;
96
97 public:
98   bp_array () : bp (NULL), max_cnt (0), cur_cnt (0) {}
99   virtual ~bp_array () {}
100
101   int add (breakpoint &new_bp)
102     {
103       for (int i = 0; i < cur_cnt; ++i)
104         if (new_bp.address () == bp[i].address ())
105           return i;
106       if (cur_cnt == max_cnt)
107         {
108           breakpoint *tmp = (breakpoint *)
109                         realloc (bp, (max_cnt += 5) * sizeof (breakpoint));
110           if (!tmp)
111             return -1;
112           bp = tmp;
113         }
114       bp[cur_cnt] = new_bp;
115       return cur_cnt++;
116     }
117   int add (DWORD address, char *instruction)
118     {
119       breakpoint new_bp (address, instruction);
120       return add (new_bp);
121     }
122   BOOL remove (DWORD address)
123     {
124       for (int i = 0; i < cur_cnt; ++i)
125         if (bp[i].address () == address && bp[i].in_use ())
126           {
127             bp[i].set_in_use (FALSE);
128             return TRUE;
129           }
130       return FALSE;
131     }
132   BOOL remove (int bp_id)
133     {
134       if (bp_id >= cur_cnt || !bp[bp_id].in_use ())
135         return FALSE;
136       bp[bp_id].set_in_use (FALSE);
137       return TRUE;
138     }
139   const char *instruction (DWORD address) const
140     {
141       for (int i = 0; i < cur_cnt; ++i)
142         if (bp[i].address () == address)
143           return bp[i].instruction ();
144       return NULL;
145     }
146
147   void operator +=(breakpoint &new_bp) { add (new_bp); }
148   void operator -=(DWORD address) { remove (address); }
149   const char *operator [](DWORD address) const { return instruction (address); }
150 };
151
152 class thread_slot {
153   BOOL                     used;
154   DWORD                    id;
155   CREATE_THREAD_DEBUG_INFO info;
156
157 public:
158   thread_slot () : used (FALSE), id (0) {}
159   thread_slot (DEBUG_EVENT &ev)
160     {
161       used = TRUE;
162       id = ev.dwThreadId;
163       switch (ev.dwDebugEventCode)
164         {
165         case CREATE_THREAD_DEBUG_EVENT:
166           info = ev.u.CreateThread;
167           break;
168         case CREATE_PROCESS_DEBUG_EVENT:
169           info.hThread = ev.u.CreateProcessInfo.hThread;
170           info.lpThreadLocalBase = ev.u.CreateProcessInfo.lpThreadLocalBase;
171           info.lpStartAddress = ev.u.CreateProcessInfo.lpStartAddress;
172           break;
173         default:
174           used = 0;
175           break;
176         }
177     }
178   virtual ~thread_slot () {}
179
180   BOOL in_use () { return used; }
181   DWORD get_id () { return id; }
182   HANDLE get_hdl () { return info.hThread; }
183
184   void set_in_use (BOOL nin_use) { used = nin_use; }
185 };
186
187 class thread_array {
188   thread_slot *thread;
189   int          max_cnt;
190   int          cur_cnt;
191
192 public:
193   thread_array () : thread (NULL), max_cnt (0), cur_cnt (0) {}
194   virtual ~thread_array () {}
195
196   BOOL add (thread_slot &new_slot)
197     {
198       if (cur_cnt == max_cnt)
199         {
200           thread_slot *tmp = (thread_slot *)
201                         realloc (thread, (max_cnt += 5) * sizeof (thread_slot));
202           if (!tmp)
203             return FALSE;
204           thread = tmp;
205         }
206       thread[cur_cnt++] = new_slot;
207       return TRUE;
208     }
209   BOOL add (DEBUG_EVENT &ev)
210     {
211       thread_slot new_slot (ev);
212       return add (new_slot);
213     }
214   BOOL remove (DWORD thread_id)
215     {
216       for (int i = 0; i < cur_cnt; ++i)
217         if (thread[i].get_id () == thread_id)
218           {
219             memcpy (thread + i, thread + i + 1,
220                     (cur_cnt - i - 1) * sizeof (thread_slot));
221             --cur_cnt;
222             return TRUE;
223           }
224       return FALSE;
225     }
226   BOOL remove (DEBUG_EVENT &ev)
227     {
228       if (ev.dwDebugEventCode == EXIT_THREAD_DEBUG_EVENT)
229         return remove (ev.dwThreadId);
230       return FALSE;
231     }
232   HANDLE get_hdl (DWORD thread_id)
233     {
234       for (int i = 0; i < cur_cnt; ++i)
235         if (thread[i].get_id () == thread_id)
236           return thread[i].get_hdl ();
237       return INVALID_HANDLE_VALUE;
238     }
239   DWORD get_id (HANDLE thread_hdl)
240     {
241       for (int i = 0; i < cur_cnt; ++i)
242         if (thread[i].get_hdl () == thread_hdl)
243           return thread[i].get_id ();
244       return 0L;
245     }
246
247   void operator +=(thread_slot &new_slot) { add (new_slot); }
248   void operator +=(DEBUG_EVENT &ev) { add (ev); }
249   void operator -=(DWORD thread_id) { remove (thread_id); }
250   void operator -=(DEBUG_EVENT &ev) { remove (ev); }
251   HANDLE operator [](DWORD thread_id) { get_hdl (thread_id); }
252   DWORD operator [](HANDLE thread_hdl) { get_id (thread_hdl); }
253 };
254
255 class child_process {
256   BOOL            debug_backend;
257   BOOL            debug_child;
258   DWORD           trace_child;
259   proc_state      stop_status;
260   int             stop_sig;
261   BOOL            server_quit_p;
262
263 public:
264   struct gdbserv *serv;
265   char           *executable;
266   int             argc;
267   char          **argv;
268   BOOL            new_group;
269   BOOL            new_console;
270   DWORD           process_id;
271   HANDLE          process_hdl;
272   DWORD           cur_process_id;
273   DWORD           cur_thread_id;
274   thread_array    threads;
275   bp_array        breakpoints;
276   CONTEXT         context;
277   int             suspend_cnt;
278   long            signal_to_send;
279
280   int             saw_stars;
281   char            nfields;
282   long long       start_time;
283   DWORD           last_usecs;
284
285   child_process () 
286   : serv (NULL),
287     executable (NULL),
288     argc (0),
289     argv (NULL),
290     new_group (FALSE),
291     new_console (FALSE),
292     process_id (0),
293     cur_process_id (0),
294     cur_thread_id (0),
295     suspend_cnt (0),
296     signal_to_send (0),
297     debug_backend (FALSE),
298     debug_child (FALSE),
299     trace_child (0),
300     stop_status (Running),
301     stop_sig (0),
302     server_quit_p (FALSE),
303     saw_stars (0),
304     nfields (0),
305     start_time (0),
306     last_usecs (0)
307     {
308       memset (&context, 0, sizeof context);
309     }
310
311   void set_debug (BOOL ndebug = TRUE) { debug_backend = ndebug ? TRUE : FALSE; }
312   BOOL debug () const { return debug_backend; }
313   void debug (const char *format, ...);
314
315   void set_debug_process (BOOL ndebug = TRUE)
316                                       { debug_child = ndebug ? TRUE : FALSE; }
317   int debug_process () const { return debug_child; }
318
319   void set_trace (DWORD ntrace = 1) { trace_child = ntrace; }
320   DWORD trace () const { return trace_child; }
321
322   void set_running ()           { stop_status = Running; stop_sig = 0; }
323   void set_break (int nsignal)  { stop_status = Break; stop_sig = nsignal; }
324   void set_exit (int nexitcode) { stop_status = Exit; stop_sig = nexitcode; }
325   void set_term (int nsignal)   { stop_status = Terminate; stop_sig = nsignal;}
326
327   proc_state status () const { return stop_status; }
328   int stop_signal () const { return stop_sig; }
329   int term_signal () const { return stop_sig; }
330   int exit_code () const { return stop_sig; }
331
332   void quit_server (BOOL quit) { server_quit_p = quit ? TRUE : FALSE; }
333   BOOL quit_server () const { return server_quit_p; }
334
335   void handle_exception (DEBUG_EVENT &ev);
336   void fetch_regs ();
337   void store_regs ();
338   BOOL resume_program (BOOL step);
339   void load_dll_event (DEBUG_EVENT &ev);
340   BOOL create_child ();
341
342   int check_state ();
343   void fromtarget_break ();
344   void fromtarget_exit ();
345   void fromtarget_terminate ();
346 };
347
348 /* win32-strace.cc */
349 extern int win32_output_debug_string (child_process *, DEBUG_EVENT &);
350
351 /* win32-target.cc */
352 extern "C" struct gdbserv_target *win32_attach (struct gdbserv *, void *);