xref: /openbsd-src/gnu/usr.bin/binutils/gdb/gdbserver/server.c (revision b725ae7711052a2233e31a66fefb8a752c388d7a)
1e93f7393Sniklas /* Main code for remote server for GDB.
2*b725ae77Skettenis    Copyright 1989, 1993, 1994, 1995, 1997, 1998, 1999, 2000, 2002, 2003, 2004
3*b725ae77Skettenis    Free Software Foundation, Inc.
4e93f7393Sniklas 
5e93f7393Sniklas    This file is part of GDB.
6e93f7393Sniklas 
7e93f7393Sniklas    This program is free software; you can redistribute it and/or modify
8e93f7393Sniklas    it under the terms of the GNU General Public License as published by
9e93f7393Sniklas    the Free Software Foundation; either version 2 of the License, or
10e93f7393Sniklas    (at your option) any later version.
11e93f7393Sniklas 
12e93f7393Sniklas    This program is distributed in the hope that it will be useful,
13e93f7393Sniklas    but WITHOUT ANY WARRANTY; without even the implied warranty of
14e93f7393Sniklas    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15e93f7393Sniklas    GNU General Public License for more details.
16e93f7393Sniklas 
17e93f7393Sniklas    You should have received a copy of the GNU General Public License
18e93f7393Sniklas    along with this program; if not, write to the Free Software
19*b725ae77Skettenis    Foundation, Inc., 59 Temple Place - Suite 330,
20*b725ae77Skettenis    Boston, MA 02111-1307, USA.  */
21e93f7393Sniklas 
22e93f7393Sniklas #include "server.h"
23e93f7393Sniklas 
24*b725ae77Skettenis #include <unistd.h>
25*b725ae77Skettenis #include <signal.h>
26*b725ae77Skettenis #include <sys/wait.h>
27*b725ae77Skettenis 
28e93f7393Sniklas int cont_thread;
29e93f7393Sniklas int general_thread;
30*b725ae77Skettenis int step_thread;
31e93f7393Sniklas int thread_from_wait;
32e93f7393Sniklas int old_thread_from_wait;
33e93f7393Sniklas int extended_protocol;
34*b725ae77Skettenis int server_waiting;
35*b725ae77Skettenis 
36*b725ae77Skettenis jmp_buf toplevel;
37*b725ae77Skettenis 
38*b725ae77Skettenis /* The PID of the originally created or attached inferior.  Used to
39*b725ae77Skettenis    send signals to the process when GDB sends us an asynchronous interrupt
40*b725ae77Skettenis    (user hitting Control-C in the client), and to wait for the child to exit
41*b725ae77Skettenis    when no longer debugging it.  */
42*b725ae77Skettenis 
43*b725ae77Skettenis int signal_pid;
44*b725ae77Skettenis 
45*b725ae77Skettenis static unsigned char
start_inferior(char * argv[],char * statusptr)46*b725ae77Skettenis start_inferior (char *argv[], char *statusptr)
47*b725ae77Skettenis {
48*b725ae77Skettenis   signal (SIGTTOU, SIG_DFL);
49*b725ae77Skettenis   signal (SIGTTIN, SIG_DFL);
50*b725ae77Skettenis 
51*b725ae77Skettenis   signal_pid = create_inferior (argv[0], argv);
52*b725ae77Skettenis 
53*b725ae77Skettenis   fprintf (stderr, "Process %s created; pid = %d\n", argv[0],
54*b725ae77Skettenis 	   signal_pid);
55*b725ae77Skettenis 
56*b725ae77Skettenis   signal (SIGTTOU, SIG_IGN);
57*b725ae77Skettenis   signal (SIGTTIN, SIG_IGN);
58*b725ae77Skettenis   tcsetpgrp (fileno (stderr), signal_pid);
59*b725ae77Skettenis 
60*b725ae77Skettenis   /* Wait till we are at 1st instruction in program, return signal number.  */
61*b725ae77Skettenis   return mywait (statusptr, 0);
62*b725ae77Skettenis }
63*b725ae77Skettenis 
64*b725ae77Skettenis static int
attach_inferior(int pid,char * statusptr,unsigned char * sigptr)65*b725ae77Skettenis attach_inferior (int pid, char *statusptr, unsigned char *sigptr)
66*b725ae77Skettenis {
67*b725ae77Skettenis   /* myattach should return -1 if attaching is unsupported,
68*b725ae77Skettenis      0 if it succeeded, and call error() otherwise.  */
69*b725ae77Skettenis 
70*b725ae77Skettenis   if (myattach (pid) != 0)
71*b725ae77Skettenis     return -1;
72*b725ae77Skettenis 
73*b725ae77Skettenis   fprintf (stderr, "Attached; pid = %d\n", pid);
74*b725ae77Skettenis 
75*b725ae77Skettenis   /* FIXME - It may be that we should get the SIGNAL_PID from the
76*b725ae77Skettenis      attach function, so that it can be the main thread instead of
77*b725ae77Skettenis      whichever we were told to attach to.  */
78*b725ae77Skettenis   signal_pid = pid;
79*b725ae77Skettenis 
80*b725ae77Skettenis   *sigptr = mywait (statusptr, 0);
81*b725ae77Skettenis 
82*b725ae77Skettenis   return 0;
83*b725ae77Skettenis }
84*b725ae77Skettenis 
85*b725ae77Skettenis extern int remote_debug;
86*b725ae77Skettenis 
87*b725ae77Skettenis /* Handle all of the extended 'q' packets.  */
88*b725ae77Skettenis void
handle_query(char * own_buf)89*b725ae77Skettenis handle_query (char *own_buf)
90*b725ae77Skettenis {
91*b725ae77Skettenis   static struct inferior_list_entry *thread_ptr;
92*b725ae77Skettenis 
93*b725ae77Skettenis   if (strcmp ("qSymbol::", own_buf) == 0)
94*b725ae77Skettenis     {
95*b725ae77Skettenis       if (the_target->look_up_symbols != NULL)
96*b725ae77Skettenis 	(*the_target->look_up_symbols) ();
97*b725ae77Skettenis 
98*b725ae77Skettenis       strcpy (own_buf, "OK");
99*b725ae77Skettenis       return;
100*b725ae77Skettenis     }
101*b725ae77Skettenis 
102*b725ae77Skettenis   if (strcmp ("qfThreadInfo", own_buf) == 0)
103*b725ae77Skettenis     {
104*b725ae77Skettenis       thread_ptr = all_threads.head;
105*b725ae77Skettenis       sprintf (own_buf, "m%x", thread_ptr->id);
106*b725ae77Skettenis       thread_ptr = thread_ptr->next;
107*b725ae77Skettenis       return;
108*b725ae77Skettenis     }
109*b725ae77Skettenis 
110*b725ae77Skettenis   if (strcmp ("qsThreadInfo", own_buf) == 0)
111*b725ae77Skettenis     {
112*b725ae77Skettenis       if (thread_ptr != NULL)
113*b725ae77Skettenis 	{
114*b725ae77Skettenis 	  sprintf (own_buf, "m%x", thread_ptr->id);
115*b725ae77Skettenis 	  thread_ptr = thread_ptr->next;
116*b725ae77Skettenis 	  return;
117*b725ae77Skettenis 	}
118*b725ae77Skettenis       else
119*b725ae77Skettenis 	{
120*b725ae77Skettenis 	  sprintf (own_buf, "l");
121*b725ae77Skettenis 	  return;
122*b725ae77Skettenis 	}
123*b725ae77Skettenis     }
124*b725ae77Skettenis 
125*b725ae77Skettenis   if (the_target->read_auxv != NULL
126*b725ae77Skettenis       && strncmp ("qPart:auxv:read::", own_buf, 17) == 0)
127*b725ae77Skettenis     {
128*b725ae77Skettenis       char data[(PBUFSIZ - 1) / 2];
129*b725ae77Skettenis       CORE_ADDR ofs;
130*b725ae77Skettenis       unsigned int len;
131*b725ae77Skettenis       int n;
132*b725ae77Skettenis       decode_m_packet (&own_buf[17], &ofs, &len); /* "OFS,LEN" */
133*b725ae77Skettenis       if (len > sizeof data)
134*b725ae77Skettenis 	len = sizeof data;
135*b725ae77Skettenis       n = (*the_target->read_auxv) (ofs, data, len);
136*b725ae77Skettenis       if (n == 0)
137*b725ae77Skettenis 	write_ok (own_buf);
138*b725ae77Skettenis       else if (n < 0)
139*b725ae77Skettenis 	write_enn (own_buf);
140*b725ae77Skettenis       else
141*b725ae77Skettenis 	convert_int_to_ascii (data, own_buf, n);
142*b725ae77Skettenis       return;
143*b725ae77Skettenis     }
144*b725ae77Skettenis 
145*b725ae77Skettenis   /* Otherwise we didn't know what packet it was.  Say we didn't
146*b725ae77Skettenis      understand it.  */
147*b725ae77Skettenis   own_buf[0] = 0;
148*b725ae77Skettenis }
149*b725ae77Skettenis 
150*b725ae77Skettenis /* Parse vCont packets.  */
151*b725ae77Skettenis void
handle_v_cont(char * own_buf,char * status,unsigned char * signal)152*b725ae77Skettenis handle_v_cont (char *own_buf, char *status, unsigned char *signal)
153*b725ae77Skettenis {
154*b725ae77Skettenis   char *p, *q;
155*b725ae77Skettenis   int n = 0, i = 0;
156*b725ae77Skettenis   struct thread_resume *resume_info, default_action;
157*b725ae77Skettenis 
158*b725ae77Skettenis   /* Count the number of semicolons in the packet.  There should be one
159*b725ae77Skettenis      for every action.  */
160*b725ae77Skettenis   p = &own_buf[5];
161*b725ae77Skettenis   while (p)
162*b725ae77Skettenis     {
163*b725ae77Skettenis       n++;
164*b725ae77Skettenis       p++;
165*b725ae77Skettenis       p = strchr (p, ';');
166*b725ae77Skettenis     }
167*b725ae77Skettenis   /* Allocate room for one extra action, for the default remain-stopped
168*b725ae77Skettenis      behavior; if no default action is in the list, we'll need the extra
169*b725ae77Skettenis      slot.  */
170*b725ae77Skettenis   resume_info = malloc ((n + 1) * sizeof (resume_info[0]));
171*b725ae77Skettenis 
172*b725ae77Skettenis   default_action.thread = -1;
173*b725ae77Skettenis   default_action.leave_stopped = 1;
174*b725ae77Skettenis   default_action.step = 0;
175*b725ae77Skettenis   default_action.sig = 0;
176*b725ae77Skettenis 
177*b725ae77Skettenis   p = &own_buf[5];
178*b725ae77Skettenis   i = 0;
179*b725ae77Skettenis   while (*p)
180*b725ae77Skettenis     {
181*b725ae77Skettenis       p++;
182*b725ae77Skettenis 
183*b725ae77Skettenis       resume_info[i].leave_stopped = 0;
184*b725ae77Skettenis 
185*b725ae77Skettenis       if (p[0] == 's' || p[0] == 'S')
186*b725ae77Skettenis 	resume_info[i].step = 1;
187*b725ae77Skettenis       else if (p[0] == 'c' || p[0] == 'C')
188*b725ae77Skettenis 	resume_info[i].step = 0;
189*b725ae77Skettenis       else
190*b725ae77Skettenis 	goto err;
191*b725ae77Skettenis 
192*b725ae77Skettenis       if (p[0] == 'S' || p[0] == 'C')
193*b725ae77Skettenis 	{
194*b725ae77Skettenis 	  int sig;
195*b725ae77Skettenis 	  sig = strtol (p + 1, &q, 16);
196*b725ae77Skettenis 	  if (p == q)
197*b725ae77Skettenis 	    goto err;
198*b725ae77Skettenis 	  p = q;
199*b725ae77Skettenis 
200*b725ae77Skettenis 	  if (!target_signal_to_host_p (sig))
201*b725ae77Skettenis 	    goto err;
202*b725ae77Skettenis 	  resume_info[i].sig = target_signal_to_host (sig);
203*b725ae77Skettenis 	}
204*b725ae77Skettenis       else
205*b725ae77Skettenis 	{
206*b725ae77Skettenis 	  resume_info[i].sig = 0;
207*b725ae77Skettenis 	  p = p + 1;
208*b725ae77Skettenis 	}
209*b725ae77Skettenis 
210*b725ae77Skettenis       if (p[0] == 0)
211*b725ae77Skettenis 	{
212*b725ae77Skettenis 	  resume_info[i].thread = -1;
213*b725ae77Skettenis 	  default_action = resume_info[i];
214*b725ae77Skettenis 
215*b725ae77Skettenis 	  /* Note: we don't increment i here, we'll overwrite this entry
216*b725ae77Skettenis 	     the next time through.  */
217*b725ae77Skettenis 	}
218*b725ae77Skettenis       else if (p[0] == ':')
219*b725ae77Skettenis 	{
220*b725ae77Skettenis 	  resume_info[i].thread = strtol (p + 1, &q, 16);
221*b725ae77Skettenis 	  if (p == q)
222*b725ae77Skettenis 	    goto err;
223*b725ae77Skettenis 	  p = q;
224*b725ae77Skettenis 	  if (p[0] != ';' && p[0] != 0)
225*b725ae77Skettenis 	    goto err;
226*b725ae77Skettenis 
227*b725ae77Skettenis 	  i++;
228*b725ae77Skettenis 	}
229*b725ae77Skettenis     }
230*b725ae77Skettenis 
231*b725ae77Skettenis   resume_info[i] = default_action;
232*b725ae77Skettenis 
233*b725ae77Skettenis   /* Still used in occasional places in the backend.  */
234*b725ae77Skettenis   if (n == 1 && resume_info[0].thread != -1)
235*b725ae77Skettenis     cont_thread = resume_info[0].thread;
236*b725ae77Skettenis   else
237*b725ae77Skettenis     cont_thread = -1;
238*b725ae77Skettenis   set_desired_inferior (0);
239*b725ae77Skettenis 
240*b725ae77Skettenis   (*the_target->resume) (resume_info);
241*b725ae77Skettenis 
242*b725ae77Skettenis   free (resume_info);
243*b725ae77Skettenis 
244*b725ae77Skettenis   *signal = mywait (status, 1);
245*b725ae77Skettenis   prepare_resume_reply (own_buf, *status, *signal);
246*b725ae77Skettenis   return;
247*b725ae77Skettenis 
248*b725ae77Skettenis err:
249*b725ae77Skettenis   /* No other way to report an error... */
250*b725ae77Skettenis   strcpy (own_buf, "");
251*b725ae77Skettenis   free (resume_info);
252*b725ae77Skettenis   return;
253*b725ae77Skettenis }
254*b725ae77Skettenis 
255*b725ae77Skettenis /* Handle all of the extended 'v' packets.  */
256*b725ae77Skettenis void
handle_v_requests(char * own_buf,char * status,unsigned char * signal)257*b725ae77Skettenis handle_v_requests (char *own_buf, char *status, unsigned char *signal)
258*b725ae77Skettenis {
259*b725ae77Skettenis   if (strncmp (own_buf, "vCont;", 6) == 0)
260*b725ae77Skettenis     {
261*b725ae77Skettenis       handle_v_cont (own_buf, status, signal);
262*b725ae77Skettenis       return;
263*b725ae77Skettenis     }
264*b725ae77Skettenis 
265*b725ae77Skettenis   if (strncmp (own_buf, "vCont?", 6) == 0)
266*b725ae77Skettenis     {
267*b725ae77Skettenis       strcpy (own_buf, "vCont;c;C;s;S");
268*b725ae77Skettenis       return;
269*b725ae77Skettenis     }
270*b725ae77Skettenis 
271*b725ae77Skettenis   /* Otherwise we didn't know what packet it was.  Say we didn't
272*b725ae77Skettenis      understand it.  */
273*b725ae77Skettenis   own_buf[0] = 0;
274*b725ae77Skettenis   return;
275*b725ae77Skettenis }
276*b725ae77Skettenis 
277*b725ae77Skettenis void
myresume(int step,int sig)278*b725ae77Skettenis myresume (int step, int sig)
279*b725ae77Skettenis {
280*b725ae77Skettenis   struct thread_resume resume_info[2];
281*b725ae77Skettenis   int n = 0;
282*b725ae77Skettenis 
283*b725ae77Skettenis   if (step || sig || cont_thread > 0)
284*b725ae77Skettenis     {
285*b725ae77Skettenis       resume_info[0].thread
286*b725ae77Skettenis 	= ((struct inferior_list_entry *) current_inferior)->id;
287*b725ae77Skettenis       resume_info[0].step = step;
288*b725ae77Skettenis       resume_info[0].sig = sig;
289*b725ae77Skettenis       resume_info[0].leave_stopped = 0;
290*b725ae77Skettenis       n++;
291*b725ae77Skettenis     }
292*b725ae77Skettenis   resume_info[n].thread = -1;
293*b725ae77Skettenis   resume_info[n].step = 0;
294*b725ae77Skettenis   resume_info[n].sig = 0;
295*b725ae77Skettenis   resume_info[n].leave_stopped = (cont_thread > 0);
296*b725ae77Skettenis 
297*b725ae77Skettenis   (*the_target->resume) (resume_info);
298*b725ae77Skettenis }
299*b725ae77Skettenis 
300*b725ae77Skettenis static int attached;
301*b725ae77Skettenis 
302*b725ae77Skettenis static void
gdbserver_usage(void)303*b725ae77Skettenis gdbserver_usage (void)
304*b725ae77Skettenis {
305*b725ae77Skettenis   error ("Usage:\tgdbserver COMM PROG [ARGS ...]\n"
306*b725ae77Skettenis 	 "\tgdbserver COMM --attach PID\n"
307*b725ae77Skettenis 	 "\n"
308*b725ae77Skettenis 	 "COMM may either be a tty device (for serial debugging), or \n"
309*b725ae77Skettenis 	 "HOST:PORT to listen for a TCP connection.\n");
310*b725ae77Skettenis }
311e93f7393Sniklas 
312e93f7393Sniklas int
main(int argc,char * argv[])313*b725ae77Skettenis main (int argc, char *argv[])
314e93f7393Sniklas {
315*b725ae77Skettenis   char ch, status, *own_buf, mem_buf[2000];
316e93f7393Sniklas   int i = 0;
317e93f7393Sniklas   unsigned char signal;
318*b725ae77Skettenis   unsigned int len;
319*b725ae77Skettenis   CORE_ADDR mem_addr;
320*b725ae77Skettenis   int bad_attach;
321*b725ae77Skettenis   int pid;
322*b725ae77Skettenis   char *arg_end;
323e93f7393Sniklas 
324e93f7393Sniklas   if (setjmp (toplevel))
325e93f7393Sniklas     {
326e93f7393Sniklas       fprintf (stderr, "Exiting\n");
327e93f7393Sniklas       exit (1);
328e93f7393Sniklas     }
329e93f7393Sniklas 
330*b725ae77Skettenis   bad_attach = 0;
331*b725ae77Skettenis   pid = 0;
332*b725ae77Skettenis   attached = 0;
333*b725ae77Skettenis   if (argc >= 3 && strcmp (argv[2], "--attach") == 0)
334*b725ae77Skettenis     {
335*b725ae77Skettenis       if (argc == 4
336*b725ae77Skettenis 	  && argv[3] != '\0'
337*b725ae77Skettenis 	  && (pid = strtoul (argv[3], &arg_end, 10)) != 0
338*b725ae77Skettenis 	  && *arg_end == '\0')
339*b725ae77Skettenis 	{
340*b725ae77Skettenis 	  ;
341*b725ae77Skettenis 	}
342*b725ae77Skettenis       else
343*b725ae77Skettenis 	bad_attach = 1;
344*b725ae77Skettenis     }
345e93f7393Sniklas 
346*b725ae77Skettenis   if (argc < 3 || bad_attach)
347*b725ae77Skettenis     gdbserver_usage();
348e93f7393Sniklas 
349*b725ae77Skettenis   initialize_low ();
350*b725ae77Skettenis 
351*b725ae77Skettenis   own_buf = malloc (PBUFSIZ);
352*b725ae77Skettenis 
353*b725ae77Skettenis   if (pid == 0)
354*b725ae77Skettenis     {
355*b725ae77Skettenis       /* Wait till we are at first instruction in program.  */
356*b725ae77Skettenis       signal = start_inferior (&argv[2], &status);
357e93f7393Sniklas 
358e93f7393Sniklas       /* We are now stopped at the first instruction of the target process */
359*b725ae77Skettenis     }
360*b725ae77Skettenis   else
361*b725ae77Skettenis     {
362*b725ae77Skettenis       switch (attach_inferior (pid, &status, &signal))
363*b725ae77Skettenis 	{
364*b725ae77Skettenis 	case -1:
365*b725ae77Skettenis 	  error ("Attaching not supported on this target");
366*b725ae77Skettenis 	  break;
367*b725ae77Skettenis 	default:
368*b725ae77Skettenis 	  attached = 1;
369*b725ae77Skettenis 	  break;
370*b725ae77Skettenis 	}
371*b725ae77Skettenis     }
372e93f7393Sniklas 
373e93f7393Sniklas   while (1)
374e93f7393Sniklas     {
375e93f7393Sniklas       remote_open (argv[1]);
376e93f7393Sniklas 
377e93f7393Sniklas     restart:
378e93f7393Sniklas       setjmp (toplevel);
379e93f7393Sniklas       while (getpkt (own_buf) > 0)
380e93f7393Sniklas 	{
381e93f7393Sniklas 	  unsigned char sig;
382e93f7393Sniklas 	  i = 0;
383e93f7393Sniklas 	  ch = own_buf[i++];
384e93f7393Sniklas 	  switch (ch)
385e93f7393Sniklas 	    {
386*b725ae77Skettenis 	    case 'q':
387*b725ae77Skettenis 	      handle_query (own_buf);
388*b725ae77Skettenis 	      break;
389*b725ae77Skettenis 	    case 'd':
390*b725ae77Skettenis 	      remote_debug = !remote_debug;
391*b725ae77Skettenis 	      break;
392*b725ae77Skettenis 	    case 'D':
393*b725ae77Skettenis 	      fprintf (stderr, "Detaching from inferior\n");
394*b725ae77Skettenis 	      detach_inferior ();
395*b725ae77Skettenis 	      write_ok (own_buf);
396*b725ae77Skettenis 	      putpkt (own_buf);
397*b725ae77Skettenis 	      remote_close ();
398*b725ae77Skettenis 
399*b725ae77Skettenis 	      /* If we are attached, then we can exit.  Otherwise, we need to
400*b725ae77Skettenis 		 hang around doing nothing, until the child is gone.  */
401*b725ae77Skettenis 	      if (!attached)
402*b725ae77Skettenis 		{
403*b725ae77Skettenis 		  int status, ret;
404*b725ae77Skettenis 
405*b725ae77Skettenis 		  do {
406*b725ae77Skettenis 		    ret = waitpid (signal_pid, &status, 0);
407*b725ae77Skettenis 		    if (WIFEXITED (status) || WIFSIGNALED (status))
408*b725ae77Skettenis 		      break;
409*b725ae77Skettenis 		  } while (ret != -1 || errno != ECHILD);
410*b725ae77Skettenis 		}
411*b725ae77Skettenis 
412*b725ae77Skettenis 	      exit (0);
413*b725ae77Skettenis 
414e93f7393Sniklas 	    case '!':
415*b725ae77Skettenis 	      if (attached == 0)
416*b725ae77Skettenis 		{
417e93f7393Sniklas 		  extended_protocol = 1;
418e93f7393Sniklas 		  prepare_resume_reply (own_buf, status, signal);
419*b725ae77Skettenis 		}
420*b725ae77Skettenis 	      else
421*b725ae77Skettenis 		{
422*b725ae77Skettenis 		  /* We can not use the extended protocol if we are
423*b725ae77Skettenis 		     attached, because we can not restart the running
424*b725ae77Skettenis 		     program.  So return unrecognized.  */
425*b725ae77Skettenis 		  own_buf[0] = '\0';
426*b725ae77Skettenis 		}
427e93f7393Sniklas 	      break;
428e93f7393Sniklas 	    case '?':
429e93f7393Sniklas 	      prepare_resume_reply (own_buf, status, signal);
430e93f7393Sniklas 	      break;
431e93f7393Sniklas 	    case 'H':
432e93f7393Sniklas 	      switch (own_buf[1])
433e93f7393Sniklas 		{
434e93f7393Sniklas 		case 'g':
435e93f7393Sniklas 		  general_thread = strtol (&own_buf[2], NULL, 16);
436e93f7393Sniklas 		  write_ok (own_buf);
437*b725ae77Skettenis 		  set_desired_inferior (1);
438e93f7393Sniklas 		  break;
439e93f7393Sniklas 		case 'c':
440e93f7393Sniklas 		  cont_thread = strtol (&own_buf[2], NULL, 16);
441e93f7393Sniklas 		  write_ok (own_buf);
442e93f7393Sniklas 		  break;
443*b725ae77Skettenis 		case 's':
444*b725ae77Skettenis 		  step_thread = strtol (&own_buf[2], NULL, 16);
445*b725ae77Skettenis 		  write_ok (own_buf);
446*b725ae77Skettenis 		  break;
447e93f7393Sniklas 		default:
448e93f7393Sniklas 		  /* Silently ignore it so that gdb can extend the protocol
449e93f7393Sniklas 		     without compatibility headaches.  */
450e93f7393Sniklas 		  own_buf[0] = '\0';
451e93f7393Sniklas 		  break;
452e93f7393Sniklas 		}
453e93f7393Sniklas 	      break;
454e93f7393Sniklas 	    case 'g':
455*b725ae77Skettenis 	      set_desired_inferior (1);
456*b725ae77Skettenis 	      registers_to_string (own_buf);
457e93f7393Sniklas 	      break;
458e93f7393Sniklas 	    case 'G':
459*b725ae77Skettenis 	      set_desired_inferior (1);
460*b725ae77Skettenis 	      registers_from_string (&own_buf[1]);
461e93f7393Sniklas 	      write_ok (own_buf);
462e93f7393Sniklas 	      break;
463e93f7393Sniklas 	    case 'm':
464e93f7393Sniklas 	      decode_m_packet (&own_buf[1], &mem_addr, &len);
465*b725ae77Skettenis 	      if (read_inferior_memory (mem_addr, mem_buf, len) == 0)
466e93f7393Sniklas 		convert_int_to_ascii (mem_buf, own_buf, len);
467*b725ae77Skettenis 	      else
468*b725ae77Skettenis 		write_enn (own_buf);
469e93f7393Sniklas 	      break;
470e93f7393Sniklas 	    case 'M':
471e93f7393Sniklas 	      decode_M_packet (&own_buf[1], &mem_addr, &len, mem_buf);
472e93f7393Sniklas 	      if (write_inferior_memory (mem_addr, mem_buf, len) == 0)
473e93f7393Sniklas 		write_ok (own_buf);
474e93f7393Sniklas 	      else
475e93f7393Sniklas 		write_enn (own_buf);
476e93f7393Sniklas 	      break;
477e93f7393Sniklas 	    case 'C':
478e93f7393Sniklas 	      convert_ascii_to_int (own_buf + 1, &sig, 1);
479*b725ae77Skettenis 	      if (target_signal_to_host_p (sig))
480*b725ae77Skettenis 		signal = target_signal_to_host (sig);
481*b725ae77Skettenis 	      else
482*b725ae77Skettenis 		signal = 0;
483*b725ae77Skettenis 	      set_desired_inferior (0);
484*b725ae77Skettenis 	      myresume (0, signal);
485*b725ae77Skettenis 	      signal = mywait (&status, 1);
486e93f7393Sniklas 	      prepare_resume_reply (own_buf, status, signal);
487e93f7393Sniklas 	      break;
488e93f7393Sniklas 	    case 'S':
489e93f7393Sniklas 	      convert_ascii_to_int (own_buf + 1, &sig, 1);
490*b725ae77Skettenis 	      if (target_signal_to_host_p (sig))
491*b725ae77Skettenis 		signal = target_signal_to_host (sig);
492*b725ae77Skettenis 	      else
493*b725ae77Skettenis 		signal = 0;
494*b725ae77Skettenis 	      set_desired_inferior (0);
495*b725ae77Skettenis 	      myresume (1, signal);
496*b725ae77Skettenis 	      signal = mywait (&status, 1);
497e93f7393Sniklas 	      prepare_resume_reply (own_buf, status, signal);
498e93f7393Sniklas 	      break;
499e93f7393Sniklas 	    case 'c':
500*b725ae77Skettenis 	      set_desired_inferior (0);
501e93f7393Sniklas 	      myresume (0, 0);
502*b725ae77Skettenis 	      signal = mywait (&status, 1);
503e93f7393Sniklas 	      prepare_resume_reply (own_buf, status, signal);
504e93f7393Sniklas 	      break;
505e93f7393Sniklas 	    case 's':
506*b725ae77Skettenis 	      set_desired_inferior (0);
507e93f7393Sniklas 	      myresume (1, 0);
508*b725ae77Skettenis 	      signal = mywait (&status, 1);
509e93f7393Sniklas 	      prepare_resume_reply (own_buf, status, signal);
510e93f7393Sniklas 	      break;
511e93f7393Sniklas 	    case 'k':
512e93f7393Sniklas 	      fprintf (stderr, "Killing inferior\n");
513e93f7393Sniklas 	      kill_inferior ();
514e93f7393Sniklas 	      /* When using the extended protocol, we start up a new
515e93f7393Sniklas 	         debugging session.   The traditional protocol will
516e93f7393Sniklas 	         exit instead.  */
517e93f7393Sniklas 	      if (extended_protocol)
518e93f7393Sniklas 		{
519e93f7393Sniklas 		  write_ok (own_buf);
520e93f7393Sniklas 		  fprintf (stderr, "GDBserver restarting\n");
521e93f7393Sniklas 
522e93f7393Sniklas 		  /* Wait till we are at 1st instruction in prog.  */
523*b725ae77Skettenis 		  signal = start_inferior (&argv[2], &status);
524e93f7393Sniklas 		  goto restart;
525e93f7393Sniklas 		  break;
526e93f7393Sniklas 		}
527e93f7393Sniklas 	      else
528e93f7393Sniklas 		{
529e93f7393Sniklas 		  exit (0);
530e93f7393Sniklas 		  break;
531e93f7393Sniklas 		}
532e93f7393Sniklas 	    case 'T':
533e93f7393Sniklas 	      if (mythread_alive (strtol (&own_buf[1], NULL, 16)))
534e93f7393Sniklas 		write_ok (own_buf);
535e93f7393Sniklas 	      else
536e93f7393Sniklas 		write_enn (own_buf);
537e93f7393Sniklas 	      break;
538e93f7393Sniklas 	    case 'R':
539e93f7393Sniklas 	      /* Restarting the inferior is only supported in the
540e93f7393Sniklas 	         extended protocol.  */
541e93f7393Sniklas 	      if (extended_protocol)
542e93f7393Sniklas 		{
543e93f7393Sniklas 		  kill_inferior ();
544e93f7393Sniklas 		  write_ok (own_buf);
545e93f7393Sniklas 		  fprintf (stderr, "GDBserver restarting\n");
546e93f7393Sniklas 
547e93f7393Sniklas 		  /* Wait till we are at 1st instruction in prog.  */
548*b725ae77Skettenis 		  signal = start_inferior (&argv[2], &status);
549e93f7393Sniklas 		  goto restart;
550e93f7393Sniklas 		  break;
551e93f7393Sniklas 		}
552e93f7393Sniklas 	      else
553e93f7393Sniklas 		{
554e93f7393Sniklas 		  /* It is a request we don't understand.  Respond with an
555e93f7393Sniklas 		     empty packet so that gdb knows that we don't support this
556e93f7393Sniklas 		     request.  */
557e93f7393Sniklas 		  own_buf[0] = '\0';
558e93f7393Sniklas 		  break;
559e93f7393Sniklas 		}
560*b725ae77Skettenis 	    case 'v':
561*b725ae77Skettenis 	      /* Extended (long) request.  */
562*b725ae77Skettenis 	      handle_v_requests (own_buf, &status, &signal);
563*b725ae77Skettenis 	      break;
564e93f7393Sniklas 	    default:
565e93f7393Sniklas 	      /* It is a request we don't understand.  Respond with an
566e93f7393Sniklas 	         empty packet so that gdb knows that we don't support this
567e93f7393Sniklas 	         request.  */
568e93f7393Sniklas 	      own_buf[0] = '\0';
569e93f7393Sniklas 	      break;
570e93f7393Sniklas 	    }
571e93f7393Sniklas 
572e93f7393Sniklas 	  putpkt (own_buf);
573e93f7393Sniklas 
574e93f7393Sniklas 	  if (status == 'W')
575e93f7393Sniklas 	    fprintf (stderr,
576*b725ae77Skettenis 		     "\nChild exited with status %d\n", signal);
577e93f7393Sniklas 	  if (status == 'X')
578*b725ae77Skettenis 	    fprintf (stderr, "\nChild terminated with signal = 0x%x\n",
579*b725ae77Skettenis 		     signal);
580e93f7393Sniklas 	  if (status == 'W' || status == 'X')
581e93f7393Sniklas 	    {
582e93f7393Sniklas 	      if (extended_protocol)
583e93f7393Sniklas 		{
584e93f7393Sniklas 		  fprintf (stderr, "Killing inferior\n");
585e93f7393Sniklas 		  kill_inferior ();
586e93f7393Sniklas 		  write_ok (own_buf);
587e93f7393Sniklas 		  fprintf (stderr, "GDBserver restarting\n");
588e93f7393Sniklas 
589e93f7393Sniklas 		  /* Wait till we are at 1st instruction in prog.  */
590*b725ae77Skettenis 		  signal = start_inferior (&argv[2], &status);
591e93f7393Sniklas 		  goto restart;
592e93f7393Sniklas 		  break;
593e93f7393Sniklas 		}
594e93f7393Sniklas 	      else
595e93f7393Sniklas 		{
596e93f7393Sniklas 		  fprintf (stderr, "GDBserver exiting\n");
597e93f7393Sniklas 		  exit (0);
598e93f7393Sniklas 		}
599e93f7393Sniklas 	    }
600e93f7393Sniklas 	}
601e93f7393Sniklas 
602e93f7393Sniklas       /* We come here when getpkt fails.
603e93f7393Sniklas 
604e93f7393Sniklas          For the extended remote protocol we exit (and this is the only
605e93f7393Sniklas          way we gracefully exit!).
606e93f7393Sniklas 
607e93f7393Sniklas          For the traditional remote protocol close the connection,
608e93f7393Sniklas          and re-open it at the top of the loop.  */
609e93f7393Sniklas       if (extended_protocol)
610e93f7393Sniklas 	{
611e93f7393Sniklas 	  remote_close ();
612e93f7393Sniklas 	  exit (0);
613e93f7393Sniklas 	}
614e93f7393Sniklas       else
615e93f7393Sniklas 	{
616*b725ae77Skettenis 	  fprintf (stderr, "Remote side has terminated connection.  "
617*b725ae77Skettenis 			   "GDBserver will reopen the connection.\n");
618e93f7393Sniklas 	  remote_close ();
619e93f7393Sniklas 	}
620e93f7393Sniklas     }
621e93f7393Sniklas }
622