3 Copyright 2000, 2002 Red Hat, Inc.
5 This file is part of RDA, the Red Hat Debug Agent (and library).
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.
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.
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.
22 Alternative licenses for RDA may be arranged by contacting Red Hat,
27 #include "gdbserv-target.h"
28 #include "gdbserv-utils.h"
29 #include "gdbsocket.h"
33 /* Various possibilities for alloca. */
36 #define alloca __builtin_alloca
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 ();
50 #endif /* Not HAVE_ALLOCA_H */
51 #endif /* Not GNU C */
52 #endif /* alloca not defined */
54 /* Sequence of bytes for breakpoint instruction. */
56 #define BREAKPOINT {0xcc}
58 #define FLAG_TRACE_BIT 0x100
70 char bp_instruction[SIZEOF_BP];
73 breakpoint () : used (FALSE), bp_address(0)
75 memset (bp_instruction, 0, SIZEOF_BP);
77 breakpoint (DWORD naddress, char *nbp_inst)
78 : used (TRUE), bp_address(naddress)
80 memcpy (bp_instruction, nbp_inst, SIZEOF_BP);
82 virtual ~breakpoint () {}
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; }
89 void set_in_use (BOOL nin_use) { used = nin_use; }
98 bp_array () : bp (NULL), max_cnt (0), cur_cnt (0) {}
99 virtual ~bp_array () {}
101 int add (breakpoint &new_bp)
103 for (int i = 0; i < cur_cnt; ++i)
104 if (new_bp.address () == bp[i].address ())
106 if (cur_cnt == max_cnt)
108 breakpoint *tmp = (breakpoint *)
109 realloc (bp, (max_cnt += 5) * sizeof (breakpoint));
114 bp[cur_cnt] = new_bp;
117 int add (DWORD address, char *instruction)
119 breakpoint new_bp (address, instruction);
122 BOOL remove (DWORD address)
124 for (int i = 0; i < cur_cnt; ++i)
125 if (bp[i].address () == address && bp[i].in_use ())
127 bp[i].set_in_use (FALSE);
132 BOOL remove (int bp_id)
134 if (bp_id >= cur_cnt || !bp[bp_id].in_use ())
136 bp[bp_id].set_in_use (FALSE);
139 const char *instruction (DWORD address) const
141 for (int i = 0; i < cur_cnt; ++i)
142 if (bp[i].address () == address)
143 return bp[i].instruction ();
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); }
155 CREATE_THREAD_DEBUG_INFO info;
158 thread_slot () : used (FALSE), id (0) {}
159 thread_slot (DEBUG_EVENT &ev)
163 switch (ev.dwDebugEventCode)
165 case CREATE_THREAD_DEBUG_EVENT:
166 info = ev.u.CreateThread;
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;
178 virtual ~thread_slot () {}
180 BOOL in_use () { return used; }
181 DWORD get_id () { return id; }
182 HANDLE get_hdl () { return info.hThread; }
184 void set_in_use (BOOL nin_use) { used = nin_use; }
193 thread_array () : thread (NULL), max_cnt (0), cur_cnt (0) {}
194 virtual ~thread_array () {}
196 BOOL add (thread_slot &new_slot)
198 if (cur_cnt == max_cnt)
200 thread_slot *tmp = (thread_slot *)
201 realloc (thread, (max_cnt += 5) * sizeof (thread_slot));
206 thread[cur_cnt++] = new_slot;
209 BOOL add (DEBUG_EVENT &ev)
211 thread_slot new_slot (ev);
212 return add (new_slot);
214 BOOL remove (DWORD thread_id)
216 for (int i = 0; i < cur_cnt; ++i)
217 if (thread[i].get_id () == thread_id)
219 memcpy (thread + i, thread + i + 1,
220 (cur_cnt - i - 1) * sizeof (thread_slot));
226 BOOL remove (DEBUG_EVENT &ev)
228 if (ev.dwDebugEventCode == EXIT_THREAD_DEBUG_EVENT)
229 return remove (ev.dwThreadId);
232 HANDLE get_hdl (DWORD thread_id)
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;
239 DWORD get_id (HANDLE thread_hdl)
241 for (int i = 0; i < cur_cnt; ++i)
242 if (thread[i].get_hdl () == thread_hdl)
243 return thread[i].get_id ();
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); }
255 class child_process {
259 proc_state stop_status;
264 struct gdbserv *serv;
272 DWORD cur_process_id;
274 thread_array threads;
275 bp_array breakpoints;
282 long long start_time;
297 debug_backend (FALSE),
300 stop_status (Running),
302 server_quit_p (FALSE),
308 memset (&context, 0, sizeof context);
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, ...);
315 void set_debug_process (BOOL ndebug = TRUE)
316 { debug_child = ndebug ? TRUE : FALSE; }
317 int debug_process () const { return debug_child; }
319 void set_trace (DWORD ntrace = 1) { trace_child = ntrace; }
320 DWORD trace () const { return trace_child; }
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;}
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; }
332 void quit_server (BOOL quit) { server_quit_p = quit ? TRUE : FALSE; }
333 BOOL quit_server () const { return server_quit_p; }
335 void handle_exception (DEBUG_EVENT &ev);
338 BOOL resume_program (BOOL step);
339 void load_dll_event (DEBUG_EVENT &ev);
340 BOOL create_child ();
343 void fromtarget_break ();
344 void fromtarget_exit ();
345 void fromtarget_terminate ();
348 /* win32-strace.cc */
349 extern int win32_output_debug_string (child_process *, DEBUG_EVENT &);
351 /* win32-target.cc */
352 extern "C" struct gdbserv_target *win32_attach (struct gdbserv *, void *);