1 /*  parent.c -- ARMulator RDP comms code:  ARM6 Instruction Emulator.
2     Copyright (C) 1994 Advanced RISC Machines Ltd.
3 
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8 
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13 
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
17 
18 /*****************************************************************/
19 /* The Parent process continues here...                          */
20 /* It waits on the socket and passes on RDP messages down a pipe */
21 /* to the ARMulator RDP to RDI interpreter.                      */
22 /*****************************************************************/
23 
24 #include <stdio.h>
25 #include <sys/types.h>
26 #include <signal.h>
27 #include "time.h"
28 #include "armdefs.h"
29 #include "dbg_rdi.h"
30 #include "communicate.h"
31 
32 /* The socket to the debugger */
33 extern int debugsock;
34 
35 /* The pipes between the two processes */
36 extern int mumkid[2];
37 extern int kidmum[2];
38 
39 /* A pipe for handling SWI return values that goes straight from the */
40 /* parent to the ARMulator host interface, bypassing the child's RDP */
41 /* to RDI interpreter */
42 extern int DebuggerARMul[2];
43 
44 /* The maximum number of file descriptors */
45 extern int nfds;
46 
47 /* The child process id. */
48 extern pid_t child;
49 
50 void
parent()51 parent ()
52 {
53   int i, j, k;
54   unsigned char message, CPnum, exreturn;
55   ARMword mask, nbytes, messagetype;
56   unsigned char c, d;
57   ARMword x, y;
58   int virgin = 1;
59   struct fd_set readfds;
60 
61 #ifdef DEBUG
62   fprintf (stderr, "parent ()...\n");
63 #endif
64 
65 panic_error:
66 
67   if (!virgin)
68     {
69 #ifdef DEBUG
70       fprintf (stderr, "Arghh! What is going on?\n");
71 #endif
72       kill (child, SIGHUP);
73       MYwrite_char (debugsock, RDP_Reset);
74     }
75 
76   virgin = 0;
77 
78   while (1)
79     {
80 
81       /* Wait either for the ARMulator or the debugger */
82 
83       FD_ZERO (&readfds);
84       FD_SET (kidmum[0], &readfds);	/* Wait for messages from ARMulator */
85       FD_SET (debugsock, &readfds);	/* Wait for messages from debugger */
86 
87 #ifdef DEBUG
88       fprintf (stderr, "Waiting for ARMulator or debugger... ");
89 #endif
90 
91       while ((i = select (nfds, &readfds, (fd_set *) 0, (fd_set *) 0, 0)) < 0)
92 	{
93 	  perror ("select");
94 	}
95 
96 #ifdef DEBUG
97       fprintf (stderr, "(%d/2)", i);
98 #endif
99 
100       if (FD_ISSET (debugsock, &readfds))
101 	{
102 #ifdef DEBUG
103 	  fprintf (stderr, "->debugger\n");
104 #endif
105 
106 	  /* Inside this rather large if statement with simply pass on a complete
107 	     message to the ARMulator.  The reason we need to pass messages on one
108 	     at a time is that we have to know whether the message is an OSOpReply
109 	     or an info(stop), so that we can take different action in those
110 	     cases. */
111 
112 	  if (MYread_char (debugsock, &message))
113 	    goto panic_error;
114 
115 	  switch (message)
116 	    {
117 	    case RDP_Start:
118 	      /* Open and/or Initialise */
119 #ifdef DEBUG
120 	      fprintf (stderr, "RDP Open\n");
121 #endif
122 	      if (MYread_char (debugsock, &c))	/* type */
123 		goto panic_error;
124 
125 	      if (MYread_word (debugsock, &x))	/* memory size */
126 		goto panic_error;
127 
128 	      MYwrite_char (mumkid[1], message);
129 	      MYwrite_char (mumkid[1], c);
130 	      MYwrite_word (mumkid[1], x);
131 	      if (c & 0x2)
132 		{
133 		  passon (debugsock, mumkid[1], 1);	/* speed */
134 		}
135 	      break;
136 
137 	    case RDP_End:
138 	      /* Close and Finalise */
139 #ifdef DEBUG
140 	      fprintf (stderr, "RDP Close\n");
141 #endif
142 	      MYwrite_char (mumkid[1], message);
143 	      break;
144 
145 	    case RDP_Read:
146 	      /* Read Memory Address */
147 #ifdef DEBUG
148 	      fprintf (stderr, "RDP Read Memory\n");
149 #endif
150 	      MYwrite_char (mumkid[1], message);
151 	      if (passon (debugsock, mumkid[1], 4))
152 		goto panic_error;	/* address */
153 	      if (MYread_word (debugsock, &nbytes))
154 		goto panic_error;	/* nbytes */
155 	      MYwrite_word (mumkid[1], nbytes);
156 	      break;
157 
158 	    case RDP_Write:
159 	      /* Write Memory Address */
160 #ifdef DEBUG
161 	      fprintf (stderr, "RDP Write Memory\n");
162 #endif
163 	      if (MYread_word (debugsock, &x))
164 		goto panic_error;	/* address */
165 
166 	      if (MYread_word (debugsock, &y))
167 		goto panic_error;	/* nbytes */
168 
169 	      MYwrite_char (mumkid[1], message);
170 	      MYwrite_word (mumkid[1], x);
171 	      MYwrite_word (mumkid[1], y);
172 	      passon (debugsock, mumkid[1], y);	/* actual data */
173 	      break;
174 
175 	    case RDP_CPUread:
176 	      /* Read CPU State */
177 #ifdef DEBUG
178 	      fprintf (stderr, "RDP Read CPU\n");
179 #endif
180 	      if (MYread_char (debugsock, &c))
181 		goto panic_error;	/* mode */
182 
183 	      if (MYread_word (debugsock, &mask))
184 		goto panic_error;	/* mask */
185 
186 	      MYwrite_char (mumkid[1], message);
187 	      MYwrite_char (mumkid[1], c);
188 	      MYwrite_word (mumkid[1], mask);
189 	      break;
190 
191 	    case RDP_CPUwrite:
192 	      /* Write CPU State */
193 #ifdef DEBUG
194 	      fprintf (stderr, "RDP Write CPU\n");
195 #endif
196 	      if (MYread_char (debugsock, &c))
197 		goto panic_error;	/* mode */
198 
199 	      if (MYread_word (debugsock, &x))
200 		goto panic_error;	/* mask */
201 
202 	      MYwrite_char (mumkid[1], message);
203 	      MYwrite_char (mumkid[1], c);
204 	      MYwrite_word (mumkid[1], x);
205 	      for (k = 1, j = 0; k != 0x80000000; k *= 2, j++)
206 		if ((k & x) && passon (debugsock, mumkid[1], 4))
207 		  goto panic_error;
208 	      break;
209 
210 	    case RDP_CPread:
211 	      /* Read Co-Processor State */
212 #ifdef DEBUG
213 	      fprintf (stderr, "RDP Read CP state\n");
214 #endif
215 	      if (MYread_char (debugsock, &CPnum))
216 		goto panic_error;
217 
218 	      if (MYread_word (debugsock, &mask))
219 		goto panic_error;
220 
221 	      MYwrite_char (mumkid[1], message);
222 	      MYwrite_char (mumkid[1], CPnum);
223 	      MYwrite_word (mumkid[1], mask);
224 	      break;
225 
226 	    case RDP_CPwrite:
227 	      /* Write Co-Processor State */
228 #ifdef DEBUG
229 	      fprintf (stderr, "RDP Write CP state\n");
230 #endif
231 	      if (MYread_char (debugsock, &CPnum))
232 		goto panic_error;
233 
234 	      if (MYread_word (debugsock, &mask))
235 		goto panic_error;
236 
237 	      MYwrite_char (mumkid[1], message);
238 	      MYwrite_char (mumkid[1], c);
239 	      MYwrite_char (mumkid[1], x);
240 	      for (k = 1, j = 0; k != 0x80000000; k *= 2, j++)
241 		if (k & x)
242 		  {
243 		    if ((c == 1 || c == 2) && k <= 128)
244 		      {
245 			/* FP register = 12 bytes + 4 bytes format */
246 			if (passon (debugsock, mumkid[1], 16))
247 			  goto panic_error;
248 		      }
249 		    else
250 		      {
251 			/* Normal register = 4 bytes */
252 			if (passon (debugsock, mumkid[1], 4))
253 			  goto panic_error;
254 		      }
255 		  }
256 	      break;
257 
258 	    case RDP_SetBreak:
259 	      /* Set Breakpoint */
260 #ifdef DEBUG
261 	      fprintf (stderr, "RDP Set Breakpoint\n");
262 #endif
263 	      if (MYread_word (debugsock, &x))
264 		goto panic_error;	/* address */
265 
266 	      if (MYread_char (debugsock, &c))
267 		goto panic_error;	/* type */
268 
269 	      MYwrite_char (mumkid[1], message);
270 	      MYwrite_word (mumkid[1], x);
271 	      MYwrite_char (mumkid[1], c);
272 	      if (((c & 0xf) >= 5) && passon (debugsock, mumkid[1], 4))
273 		goto panic_error;	/* bound */
274 	      break;
275 
276 	    case RDP_ClearBreak:
277 	      /* Clear Breakpoint */
278 #ifdef DEBUG
279 	      fprintf (stderr, "RDP Clear Breakpoint\n");
280 #endif
281 	      MYwrite_char (mumkid[1], message);
282 	      if (passon (debugsock, mumkid[1], 4))
283 		goto panic_error;	/* point */
284 	      break;
285 
286 	    case RDP_SetWatch:
287 	      /* Set Watchpoint */
288 #ifdef DEBUG
289 	      fprintf (stderr, "RDP Set Watchpoint\n");
290 #endif
291 	      if (MYread_word (debugsock, &x))
292 		goto panic_error;	/* address */
293 
294 	      if (MYread_char (debugsock, &c))
295 		goto panic_error;	/* type */
296 
297 	      if (MYread_char (debugsock, &d))
298 		goto panic_error;	/* datatype */
299 
300 	      MYwrite_char (mumkid[1], message);
301 	      MYwrite_word (mumkid[1], x);
302 	      MYwrite_char (mumkid[1], c);
303 	      MYwrite_char (mumkid[1], d);
304 	      if (((c & 0xf) >= 5) && passon (debugsock, mumkid[1], 4))
305 		goto panic_error;	/* bound */
306 	      break;
307 
308 	    case RDP_ClearWatch:
309 	      /* Clear Watchpoint */
310 #ifdef DEBUG
311 	      fprintf (stderr, "RDP Clear Watchpoint\n");
312 #endif
313 	      MYwrite_char (mumkid[1], message);
314 	      if (passon (debugsock, mumkid[1], 4))
315 		goto panic_error;	/* point */
316 	      break;
317 
318 	    case RDP_Execute:
319 	      /* Excecute */
320 #ifdef DEBUG
321 	      fprintf (stderr, "RDP Execute\n");
322 #endif
323 
324 	      /* LEAVE THIS ONE 'TIL LATER... */
325 	      /* NEED TO WORK THINGS OUT */
326 
327 	      /* NO ASCYNCHROUS RUNNING */
328 
329 	      if (MYread_char (debugsock, &c))
330 		goto panic_error;	/* return */
331 
332 	      /* Remember incase bit 7 is set and we have to send back a word */
333 	      exreturn = c;
334 
335 	      MYwrite_char (mumkid[1], message);
336 	      MYwrite_char (mumkid[1], c);
337 	      break;
338 
339 	    case RDP_Step:
340 	      /* Step */
341 #ifdef DEBUG
342 	      fprintf (stderr, "RDP Step\n");
343 #endif
344 
345 	      if (MYread_char (debugsock, &c))
346 		goto panic_error;	/* return */
347 
348 	      if (MYread_word (debugsock, &x))
349 		goto panic_error;	/* ninstr */
350 
351 	      MYwrite_char (mumkid[1], message);
352 	      MYwrite_char (mumkid[1], c);
353 	      MYwrite_word (mumkid[1], x);
354 	      break;
355 
356 	    case RDP_Info:
357 	      /* Info */
358 #ifdef DEBUG
359 	      fprintf (stderr, "RDP Info\n");
360 #endif
361 	      /* INFO TARGET, SET RDI LEVEL */
362 	      if (MYread_word (debugsock, &messagetype))
363 		goto panic_error;	/* info */
364 
365 	      switch (messagetype)
366 		{
367 		case RDIInfo_Target:
368 		  MYwrite_char (mumkid[1], message);
369 		  MYwrite_word (mumkid[1], messagetype);
370 		  break;
371 
372 		case RDISet_RDILevel:
373 		  MYwrite_char (mumkid[1], message);
374 		  MYwrite_word (mumkid[1], messagetype);
375 		  if (passon (debugsock, mumkid[1], 1))
376 		    goto panic_error;	/* argument */
377 		  break;
378 
379 		case RDISet_Cmdline:
380 		  /* Got to pass on a string argument */
381 		  MYwrite_char (mumkid[1], message);
382 		  MYwrite_word (mumkid[1], messagetype);
383 		  do
384 		    {
385 		      if (MYread_char (debugsock, &c))
386 			goto panic_error;
387 
388 		      MYwrite_char (mumkid[1], c);
389 		    }
390 		  while (c);
391 		  break;
392 
393 		case RDISignal_Stop:
394 		  kill (child, SIGUSR1);
395 		  MYwrite_char (debugsock, RDP_Return);
396 		  MYwrite_char (debugsock, RDIError_UserInterrupt);
397 		  break;
398 
399 		case RDIVector_Catch:
400 		  MYread_word (debugsock, &x);
401 		  MYwrite_char (mumkid[1], message);
402 		  MYwrite_word (mumkid[1], messagetype);
403 		  MYwrite_word (mumkid[1], x);
404 		  break;
405 
406 		case RDIInfo_Step:
407 		  MYwrite_char (mumkid[1], message);
408 		  MYwrite_word (mumkid[1], messagetype);
409 		  break;
410 
411 		case RDIInfo_Points:
412 		  MYwrite_char (mumkid[1], message);
413 		  MYwrite_word (mumkid[1], messagetype);
414 		  break;
415 
416 		default:
417 		  fprintf (stderr, "Unrecognized RDIInfo request %d\n",
418 			   messagetype);
419 		  goto panic_error;
420 		}
421 	      break;
422 
423 	    case RDP_OSOpReply:
424 	      /* OS Operation Reply */
425 #ifdef DEBUG
426 	      fprintf (stderr, "RDP OS Reply\n");
427 #endif
428 	      MYwrite_char (mumkid[1], message);
429 	      if (MYread_char (debugsock, &message))
430 		goto panic_error;
431 	      MYwrite_char (mumkid[1], message);
432 	      switch (message)
433 		{
434 		case 0:	/* return value i.e. nothing else. */
435 		  break;
436 
437 		case 1:	/* returns a byte... */
438 		  if (MYread_char (debugsock, &c))
439 		    goto panic_error;
440 
441 		  MYwrite_char (mumkid[1], c);
442 		  break;
443 
444 		case 2:	/* returns a word... */
445 		  if (MYread_word (debugsock, &x))
446 		    goto panic_error;
447 
448 		  MYwrite_word (mumkid[1], x);
449 		  break;
450 		}
451 	      break;
452 
453 	    case RDP_Reset:
454 	      /* Reset */
455 #ifdef DEBUG
456 	      fprintf (stderr, "RDP Reset\n");
457 #endif
458 	      MYwrite_char (mumkid[1], message);
459 	      break;
460 
461 	    default:
462 	      /* Hmm.. bad RDP operation */
463 	      fprintf (stderr, "RDP Bad RDP request (%d)\n", message);
464 	      MYwrite_char (debugsock, RDP_Return);
465 	      MYwrite_char (debugsock, RDIError_UnimplementedMessage);
466 	      break;
467 	    }
468 	}
469 
470       if (FD_ISSET (kidmum[0], &readfds))
471 	{
472 #ifdef DEBUG
473 	  fprintf (stderr, "->ARMulator\n");
474 #endif
475 	  /* Anything we get from the ARMulator has to go to the debugger... */
476 	  /* It is that simple! */
477 
478 	  passon (kidmum[0], debugsock, 1);
479 	}
480     }
481 }
482