1 /*  kid.c -- ARMulator RDP/RDI interface:  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 3 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, see <http://www.gnu.org/licenses/>. */
16 
17 /*****************************************************************/
18 /* The child process continues here...                           */
19 /* It waits on a pipe from the parent and translates the RDP     */
20 /* messages into RDI calls to the ARMulator passing RDP replies  */
21 /* back up a pipe to the parent.                                 */
22 /*****************************************************************/
23 
24 #include <sys/types.h>
25 #include <signal.h>
26 
27 #include "armdefs.h"
28 #include "dbg_conf.h"
29 #include "dbg_hif.h"
30 #include "dbg_rdi.h"
31 #include "gdbhost.h"
32 #include "communicate.h"
33 
34 /* The pipes between the two processes */
35 extern int mumkid[2];
36 extern int kidmum[2];
37 
38 /* The maximum number of file descriptors */
39 extern int nfds;
40 
41 /* The machine name */
42 #define MAXHOSTNAMELENGTH 64
43 extern char localhost[MAXHOSTNAMELENGTH + 1];
44 
45 /* The socket number */
46 extern unsigned int socketnumber;
47 
48 /* RDI interface */
49 extern const struct RDIProcVec armul_rdi;
50 
51 static int MYrdp_level = 0;
52 
53 static int rdi_state = 0;
54 
55 /**************************************************************/
56 /* Signal handler that terminates excecution in the ARMulator */
57 /**************************************************************/
58 void
kid_handlesignal(int sig)59 kid_handlesignal (int sig)
60 {
61 #ifdef DEBUG
62   fprintf (stderr, "Terminate ARMulator excecution\n");
63 #endif
64   if (sig != SIGUSR1)
65     {
66       fprintf (stderr, "Unsupported signal.\n");
67       return;
68     }
69   armul_rdi.info (RDISignal_Stop, (unsigned long *) 0, (unsigned long *) 0);
70 }
71 
72 /********************************************************************/
73 /* Waits on a pipe from the socket demon for RDP and                */
74 /* acts as an RDP to RDI interpreter on the front of the ARMulator. */
75 /********************************************************************/
76 void
kid()77 kid ()
78 {
79   char *p, *q;
80   int i, j, k;
81   long outofthebag;
82   unsigned char c, d, message;
83   ARMword x, y, z;
84   struct sigaction action;
85   PointHandle point;
86   Dbg_ConfigBlock config;
87   Dbg_HostosInterface hostif;
88   struct Dbg_MCState *MCState;
89   char command_line[256];
90   struct fd_set readfds;
91 
92   /* Setup a signal handler for SIGUSR1 */
93   action.sa_handler = kid_handlesignal;
94   action.sa_mask = 0;
95   action.sa_flags = 0;
96 
97   sigaction (SIGUSR1, &action, (struct sigaction *) 0);
98 
99   while (1)
100     {
101       /* Wait for ever */
102       FD_ZERO (&readfds);
103       FD_SET (mumkid[0], &readfds);
104 
105       i = select (nfds, &readfds,
106 		  (fd_set *) 0, (fd_set *) 0, (struct timeval *) 0);
107 
108       if (i < 0)
109 	{
110 	  perror ("select");
111 	}
112 
113       if (read (mumkid[0], &message, 1) < 1)
114 	{
115 	  perror ("read");
116 	}
117 
118       switch (message)
119 	{
120 	case RDP_Start:
121 	  /* Open and/or Initialise */
122 	  BAG_newbag ();
123 
124 	  MYread_char (mumkid[0], &c);	/* type */
125 	  MYread_word (mumkid[0], &x);	/* memorysize */
126 	  if (c & 0x2)
127 	    MYread_char (mumkid[0], &d);	/* speed */
128 	  config.processor = 0;
129 	  config.memorysize = x;
130 	  config.bytesex = (c & 0x4) ? RDISex_Big : RDISex_Little;
131 	  if (c & 0x8)
132 	    config.bytesex = RDISex_DontCare;
133 
134 	  hostif.dbgprint = myprint;
135 	  hostif.dbgpause = mypause;
136 	  hostif.dbgarg = stdout;
137 	  hostif.writec = mywritec;
138 	  hostif.readc = myreadc;
139 	  hostif.write = mywrite;
140 	  hostif.gets = mygets;
141 	  hostif.reset = mypause;	/* do nothing */
142 	  hostif.resetarg = "Do I love resetting or what!\n";
143 
144 	  if (rdi_state)
145 	    {
146 	      /* we have restarted, so kill off the existing run.  */
147 	      /* armul_rdi.close(); */
148 	    }
149 	  i = armul_rdi.open (c & 0x3, &config, &hostif, MCState);
150 	  rdi_state = 1;
151 
152 	  MYwrite_char (kidmum[1], RDP_Return);
153 	  MYwrite_char (kidmum[1], (unsigned char) i);
154 
155 	  x = ~0x4;
156 	  armul_rdi.info (RDIVector_Catch, &x, 0);
157 
158 	  break;
159 
160 	case RDP_End:
161 	  /* Close and Finalise */
162 	  i = armul_rdi.close ();
163 	  rdi_state = 0;
164 	  MYwrite_char (kidmum[1], RDP_Return);
165 	  MYwrite_char (kidmum[1], (unsigned char) i);
166 	  break;
167 
168 	case RDP_Read:
169 	  /* Read Memory Address */
170 	  MYread_word (mumkid[0], &x);	/* address */
171 	  MYread_word (mumkid[0], &y);	/* nbytes */
172 	  p = (char *) malloc (y);
173 	  i = armul_rdi.read (x, p, (unsigned *) &y);
174 	  MYwrite_char (kidmum[1], RDP_Return);
175 	  for (k = 0; k < y; k++)
176 	    MYwrite_char (kidmum[1], p[k]);
177 	  free (p);
178 	  MYwrite_char (kidmum[1], (unsigned char) i);
179 	  if (i)
180 	    MYwrite_word (kidmum[1], y);	/* number of bytes sent without error */
181 	  break;
182 
183 	case RDP_Write:
184 	  /* Write Memory Address */
185 	  MYread_word (mumkid[0], &x);	/* address */
186 	  MYread_word (mumkid[0], &y);	/* nbytes */
187 	  p = (char *) malloc (y);
188 	  for (k = 0; k < y; k++)
189 	    MYread_char (mumkid[0], &p[k]);
190 	  i = armul_rdi.write (p, x, (unsigned *) &y);
191 	  free (p);
192 	  MYwrite_char (kidmum[1], RDP_Return);
193 	  MYwrite_char (kidmum[1], (unsigned char) i);
194 	  if (i)
195 	    MYwrite_word (kidmum[1], y);	/* number of bytes sent without error */
196 	  break;
197 
198 	case RDP_CPUread:
199 	  /* Read CPU State */
200 	  MYread_char (mumkid[0], &c);	/* mode */
201 	  MYread_word (mumkid[0], &x);	/* mask */
202 	  p = (char *) malloc (4 * RDINumCPURegs);
203 	  i = armul_rdi.CPUread (c, x, (ARMword *) p);
204 	  MYwrite_char (kidmum[1], RDP_Return);
205 	  for (k = 1, j = 0; k != 0x80000000; k *= 2)
206 	    if (k & x)
207 	      MYwrite_word (kidmum[1], ((ARMword *) p)[j++]);
208 	  free (p);
209 	  if (i)
210 	    MYwrite_char (kidmum[1], (unsigned char) j);
211 	  MYwrite_char (kidmum[1], (unsigned char) i);
212 	  break;
213 
214 	case RDP_CPUwrite:
215 	  /* Write CPU State */
216 	  MYread_char (mumkid[0], &c);	/* mode */
217 	  MYread_word (mumkid[0], &x);	/* mask */
218 
219 	  p = (char *) malloc (4 * RDINumCPURegs);
220 	  for (k = 1, j = 0; k != 0x80000000; k *= 2)
221 	    if (k & x)
222 	      MYread_word (mumkid[0], &(((ARMword *) p)[j++]));
223 	  i = armul_rdi.CPUwrite (c, x, (ARMword *) p);
224 	  MYwrite_char (kidmum[1], RDP_Return);
225 	  MYwrite_char (kidmum[1], (unsigned char) i);
226 	  free (p);
227 	  break;
228 
229 	case RDP_CPread:
230 	  /* Read Co-Processor State */
231 	  MYread_char (mumkid[0], &c);	/* CPnum */
232 	  MYread_word (mumkid[0], &x);	/* mask */
233 	  p = q = (char *) malloc (16 * RDINumCPRegs);
234 	  i = armul_rdi.CPread (c, x, (ARMword *) p);
235 	  MYwrite_char (kidmum[1], RDP_Return);
236 	  for (k = 1, j = 0; k != 0x80000000; k *= 2, j++)
237 	    if (k & x)
238 	      {
239 		if ((c == 1 || c == 2) && k <= 128)
240 		  {
241 		    MYwrite_FPword (kidmum[1], q);
242 		    q += 16;
243 		  }
244 		else
245 		  {
246 		    MYwrite_word (kidmum[1], *q);
247 		    q += 4;
248 		  }
249 	      }
250 	  free (p);
251 	  if (i)
252 	    MYwrite_char (kidmum[1], (unsigned char) j);
253 	  MYwrite_char (kidmum[1], (unsigned char) i);
254 	  break;
255 
256 	case RDP_CPwrite:
257 	  /* Write Co-Processor State */
258 	  MYread_char (mumkid[0], &c);	/* CPnum */
259 	  MYread_word (mumkid[0], &x);	/* mask */
260 	  p = q = (char *) malloc (16 * RDINumCPURegs);
261 	  for (k = 1, j = 0; k != 0x80000000; k *= 2, j++)
262 	    if (k & x)
263 	      {
264 		if ((c == 1 || c == 2) && k <= 128)
265 		  {
266 		    MYread_FPword (kidmum[1], q);
267 		    q += 16;
268 		  }
269 		else
270 		  {
271 		    MYread_word (mumkid[0], (ARMword *) q);
272 		    q += 4;
273 		  }
274 	      }
275 	  i = armul_rdi.CPwrite (c, x, (ARMword *) p);
276 	  MYwrite_char (kidmum[1], RDP_Return);
277 	  MYwrite_char (kidmum[1], (unsigned char) i);
278 	  free (p);
279 	  break;
280 
281 	case RDP_SetBreak:
282 	  /* Set Breakpoint */
283 	  MYread_word (mumkid[0], &x);	/* address */
284 	  MYread_char (mumkid[0], &c);	/* type */
285 	  if ((c & 0xf) >= 5)
286 	    MYread_word (mumkid[0], &y);	/* bound */
287 	  i = armul_rdi.setbreak (x, c, y, &point);
288 	  if (!MYrdp_level)
289 	    BAG_putpair ((long) x, (long) point);
290 	  MYwrite_char (kidmum[1], RDP_Return);
291 	  if (MYrdp_level)
292 	    MYwrite_word (kidmum[1], point);
293 	  MYwrite_char (kidmum[1], (unsigned char) i);
294 	  break;
295 
296 	case RDP_ClearBreak:
297 	  /* Clear Breakpoint */
298 	  MYread_word (mumkid[0], &point);	/* PointHandle */
299 	  if (!MYrdp_level)
300 	    {
301 	      BAG_getsecond ((long) point, &outofthebag);	/* swap pointhandle for address */
302 	      BAG_killpair_byfirst (outofthebag);
303 	      point = outofthebag;
304 	    }
305 	  i = armul_rdi.clearbreak (point);
306 	  MYwrite_char (kidmum[1], RDP_Return);
307 	  MYwrite_char (kidmum[1], (unsigned char) i);
308 	  break;
309 
310 	case RDP_SetWatch:
311 	  /* Set Watchpoint */
312 	  MYread_word (mumkid[0], &x);	/* address */
313 	  MYread_char (mumkid[0], &c);	/* type */
314 	  MYread_char (mumkid[0], &d);	/* datatype */
315 	  if ((c & 0xf) >= 5)
316 	    MYread_word (mumkid[0], &y);	/* bound */
317 	  i = armul_rdi.setwatch (x, c, d, y, &point);
318 	  MYwrite_char (kidmum[1], RDP_Return);
319 	  MYwrite_word (kidmum[1], point);
320 	  MYwrite_char (kidmum[1], (unsigned char) i);
321 	  break;
322 
323 	case RDP_ClearWatch:
324 	  /* Clear Watchpoint */
325 	  MYread_word (mumkid[0], &point);	/* PointHandle */
326 	  i = armul_rdi.clearwatch (point);
327 	  MYwrite_char (kidmum[1], RDP_Return);
328 	  MYwrite_char (kidmum[1], (unsigned char) i);
329 	  break;
330 
331 	case RDP_Execute:
332 	  /* Excecute */
333 
334 	  MYread_char (mumkid[0], &c);	/* return */
335 
336 #ifdef DEBUG
337 	  fprintf (stderr, "Starting execution\n");
338 #endif
339 	  i = armul_rdi.execute (&point);
340 #ifdef DEBUG
341 	  fprintf (stderr, "Completed execution\n");
342 #endif
343 	  MYwrite_char (kidmum[1], RDP_Return);
344 	  if (c & 0x80)
345 	    MYwrite_word (kidmum[1], point);
346 	  MYwrite_char (kidmum[1], (unsigned char) i);
347 	  break;
348 
349 	case RDP_Step:
350 	  /* Step */
351 	  MYread_char (mumkid[0], &c);	/* return */
352 	  MYread_word (mumkid[0], &x);	/* ninstr */
353 	  point = 0x87654321;
354 	  i = armul_rdi.step (x, &point);
355 	  MYwrite_char (kidmum[1], RDP_Return);
356 	  if (c & 0x80)
357 	    MYwrite_word (kidmum[1], point);
358 	  MYwrite_char (kidmum[1], (unsigned char) i);
359 	  break;
360 
361 	case RDP_Info:
362 	  /* Info */
363 	  MYread_word (mumkid[0], &x);
364 	  switch (x)
365 	    {
366 	    case RDIInfo_Target:
367 	      i = armul_rdi.info (RDIInfo_Target, &y, &z);
368 	      MYwrite_char (kidmum[1], RDP_Return);
369 	      MYwrite_word (kidmum[1], y);	/* Loads of info... */
370 	      MYwrite_word (kidmum[1], z);	/* Model */
371 	      MYwrite_char (kidmum[1], (unsigned char) i);
372 	      break;
373 
374 	    case RDISet_RDILevel:
375 	      MYread_word (mumkid[0], &x);	/* arg1, debug level */
376 	      i = armul_rdi.info (RDISet_RDILevel, &x, 0);
377 	      if (i == RDIError_NoError)
378 		MYrdp_level = x;
379 	      MYwrite_char (kidmum[1], RDP_Return);
380 	      MYwrite_char (kidmum[1], (unsigned char) i);
381 	      break;
382 
383 	    case RDISet_Cmdline:
384 	      for (p = command_line; MYread_char (mumkid[0], p), *p; p++)
385 		;		/* String */
386 	      i = armul_rdi.info (RDISet_Cmdline,
387 				  (unsigned long *) command_line, 0);
388 	      MYwrite_char (kidmum[1], RDP_Return);
389 	      MYwrite_char (kidmum[1], (unsigned char) i);
390 	      break;
391 
392 	    case RDIInfo_Step:
393 	      i = armul_rdi.info (RDIInfo_Step, &x, 0);
394 	      MYwrite_char (kidmum[1], RDP_Return);
395 	      MYwrite_word (kidmum[1], x);
396 	      MYwrite_char (kidmum[1], (unsigned char) i);
397 	      break;
398 
399 	    case RDIVector_Catch:
400 	      MYread_word (mumkid[0], &x);
401 	      i = armul_rdi.info (RDIVector_Catch, &x, 0);
402 	      MYwrite_char (kidmum[1], RDP_Return);
403 	      MYwrite_char (kidmum[1], i);
404 	      break;
405 
406 	    case RDIInfo_Points:
407 	      i = armul_rdi.info (RDIInfo_Points, &x, 0);
408 	      MYwrite_char (kidmum[1], RDP_Return);
409 	      MYwrite_word (kidmum[1], x);
410 	      MYwrite_char (kidmum[1], (unsigned char) i);
411 	      break;
412 
413 	    default:
414 	      fprintf (stderr, "Unsupported info code %d\n", x);
415 	      break;
416 	    }
417 	  break;
418 
419 	case RDP_OSOpReply:
420 	  /* OS Operation Reply */
421 	  MYwrite_char (kidmum[1], RDP_Fatal);
422 	  break;
423 
424 	case RDP_Reset:
425 	  /* Reset */
426 	  for (i = 0; i < 50; i++)
427 	    MYwrite_char (kidmum[1], RDP_Reset);
428 	  p = (char *) malloc (MAXHOSTNAMELENGTH + 5 + 20);
429 	  sprintf (p, "Running on %s:%d\n", localhost, socketnumber);
430 	  MYwrite_string (kidmum[1], p);
431 	  free (p);
432 
433 	  break;
434 	default:
435 	  fprintf (stderr, "Oh dear: Something is seriously wrong :-(\n");
436 	  /* Hmm.. bad RDP operation */
437 	  break;
438 	}
439     }
440 }
441 
442 
443 /* Handles memory read operations until an OS Operation Reply Message is */
444 /* encounterd. It then returns the byte info value (0, 1, or 2) and fills  */
445 /* in 'putinr0' with the data if appropriate. */
446 int
wait_for_osreply(ARMword * reply)447 wait_for_osreply (ARMword * reply)
448 {
449   char *p, *q;
450   int i, j, k;
451   unsigned char c, d, message;
452   ARMword x, y, z;
453   struct sigaction action;
454   PointHandle point;
455   Dbg_ConfigBlock config;
456   Dbg_HostosInterface hostif;
457   struct Dbg_MCState *MCState;
458   char command_line[256];
459   struct fd_set readfds;
460 
461 #ifdef DEBUG
462   fprintf (stderr, "wait_for_osreply ().\n");
463 #endif
464 
465   /* Setup a signal handler for SIGUSR1 */
466   action.sa_handler = kid_handlesignal;
467   action.sa_mask = 0;
468   action.sa_flags = 0;
469 
470   sigaction (SIGUSR1, &action, (struct sigaction *) 0);
471 
472   while (1)
473     {
474       /* Wait for ever */
475       FD_ZERO (&readfds);
476       FD_SET (mumkid[0], &readfds);
477 
478       i = select (nfds, &readfds,
479 		  (fd_set *) 0, (fd_set *) 0, (struct timeval *) 0);
480 
481       if (i < 0)
482 	{
483 	  perror ("select");
484 	}
485 
486       if (read (mumkid[0], &message, 1) < 1)
487 	{
488 	  perror ("read");
489 	}
490 
491       switch (message)
492 	{
493 	case RDP_Read:
494 	  /* Read Memory Address */
495 	  MYread_word (mumkid[0], &x);	/* address */
496 	  MYread_word (mumkid[0], &y);	/* nbytes */
497 	  p = (char *) malloc (y);
498 	  i = armul_rdi.read (x, p, (unsigned *) &y);
499 	  MYwrite_char (kidmum[1], RDP_Return);
500 	  for (k = 0; k < y; k++)
501 	    MYwrite_char (kidmum[1], p[k]);
502 	  free (p);
503 	  MYwrite_char (kidmum[1], (unsigned char) i);
504 	  if (i)
505 	    MYwrite_word (kidmum[1], y);	/* number of bytes sent without error */
506 	  break;
507 
508 	case RDP_Write:
509 	  /* Write Memory Address */
510 	  MYread_word (mumkid[0], &x);	/* address */
511 	  MYread_word (mumkid[0], &y);	/* nbytes */
512 	  p = (char *) malloc (y);
513 	  for (k = 0; k < y; k++)
514 	    MYread_char (mumkid[0], &p[k]);
515 	  i = armul_rdi.write (p, x, (unsigned *) &y);
516 	  free (p);
517 	  MYwrite_char (kidmum[1], RDP_Return);
518 	  MYwrite_char (kidmum[1], (unsigned char) i);
519 	  if (i)
520 	    MYwrite_word (kidmum[1], y);	/* number of bytes sent without error */
521 	  break;
522 
523 	case RDP_OSOpReply:
524 	  /* OS Operation Reply */
525 	  MYread_char (mumkid[0], &c);
526 	  if (c == 1)
527 	    MYread_char (mumkid[0], (char *) reply);
528 	  if (c == 2)
529 	    MYread_word (mumkid[0], reply);
530 	  return c;
531 	  break;
532 
533 	default:
534 	  fprintf (stderr,
535 		   "HELP! Unaccounted-for message during OS request. \n");
536 	  MYwrite_char (kidmum[1], RDP_Fatal);
537 	}
538     }
539 }
540