/* kid.c -- ARMulator RDP/RDI interface: ARM6 Instruction Emulator. Copyright (C) 1994 Advanced RISC Machines Ltd. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ /*****************************************************************/ /* The child process continues here... */ /* It waits on a pipe from the parent and translates the RDP */ /* messages into RDI calls to the ARMulator passing RDP replies */ /* back up a pipe to the parent. */ /*****************************************************************/ #include <sys/types.h> #include <signal.h> #include "armdefs.h" #include "dbg_conf.h" #include "dbg_hif.h" #include "dbg_rdi.h" #include "gdbhost.h" #include "communicate.h" /* The pipes between the two processes */ extern int mumkid[2]; extern int kidmum[2]; /* The maximum number of file descriptors */ extern int nfds; /* The machine name */ #define MAXHOSTNAMELENGTH 64 extern char localhost[MAXHOSTNAMELENGTH + 1]; /* The socket number */ extern unsigned int socketnumber; /* RDI interface */ extern const struct RDIProcVec armul_rdi; static int MYrdp_level = 0; static int rdi_state = 0; /**************************************************************/ /* Signal handler that terminates excecution in the ARMulator */ /**************************************************************/ void kid_handlesignal (int sig) { #ifdef DEBUG fprintf (stderr, "Terminate ARMulator excecution\n"); #endif if (sig != SIGUSR1) { fprintf (stderr, "Unsupported signal.\n"); return; } armul_rdi.info (RDISignal_Stop, (unsigned long *) 0, (unsigned long *) 0); } /********************************************************************/ /* Waits on a pipe from the socket demon for RDP and */ /* acts as an RDP to RDI interpreter on the front of the ARMulator. */ /********************************************************************/ void kid () { char *p, *q; int i, j, k; long outofthebag; unsigned char c, d, message; ARMword x, y, z; struct sigaction action; PointHandle point; Dbg_ConfigBlock config; Dbg_HostosInterface hostif; struct Dbg_MCState *MCState; char command_line[256]; struct fd_set readfds; /* Setup a signal handler for SIGUSR1 */ action.sa_handler = kid_handlesignal; action.sa_mask = 0; action.sa_flags = 0; sigaction (SIGUSR1, &action, (struct sigaction *) 0); while (1) { /* Wait for ever */ FD_ZERO (&readfds); FD_SET (mumkid[0], &readfds); i = select (nfds, &readfds, (fd_set *) 0, (fd_set *) 0, (struct timeval *) 0); if (i < 0) { perror ("select"); } if (read (mumkid[0], &message, 1) < 1) { perror ("read"); } switch (message) { case RDP_Start: /* Open and/or Initialise */ BAG_newbag (); MYread_char (mumkid[0], &c); /* type */ MYread_word (mumkid[0], &x); /* memorysize */ if (c & 0x2) MYread_char (mumkid[0], &d); /* speed */ config.processor = 0; config.memorysize = x; config.bytesex = (c & 0x4) ? RDISex_Big : RDISex_Little; if (c & 0x8) config.bytesex = RDISex_DontCare; hostif.dbgprint = myprint; hostif.dbgpause = mypause; hostif.dbgarg = stdout; hostif.writec = mywritec; hostif.readc = myreadc; hostif.write = mywrite; hostif.gets = mygets; hostif.reset = mypause; /* do nothing */ hostif.resetarg = "Do I love resetting or what!\n"; if (rdi_state) { /* we have restarted, so kill off the existing run. */ /* armul_rdi.close(); */ } i = armul_rdi.open (c & 0x3, &config, &hostif, MCState); rdi_state = 1; MYwrite_char (kidmum[1], RDP_Return); MYwrite_char (kidmum[1], (unsigned char) i); x = ~0x4; armul_rdi.info (RDIVector_Catch, &x, 0); break; case RDP_End: /* Close and Finalise */ i = armul_rdi.close (); rdi_state = 0; MYwrite_char (kidmum[1], RDP_Return); MYwrite_char (kidmum[1], (unsigned char) i); break; case RDP_Read: /* Read Memory Address */ MYread_word (mumkid[0], &x); /* address */ MYread_word (mumkid[0], &y); /* nbytes */ p = (char *) malloc (y); i = armul_rdi.read (x, p, (unsigned *) &y); MYwrite_char (kidmum[1], RDP_Return); for (k = 0; k < y; k++) MYwrite_char (kidmum[1], p[k]); free (p); MYwrite_char (kidmum[1], (unsigned char) i); if (i) MYwrite_word (kidmum[1], y); /* number of bytes sent without error */ break; case RDP_Write: /* Write Memory Address */ MYread_word (mumkid[0], &x); /* address */ MYread_word (mumkid[0], &y); /* nbytes */ p = (char *) malloc (y); for (k = 0; k < y; k++) MYread_char (mumkid[0], &p[k]); i = armul_rdi.write (p, x, (unsigned *) &y); free (p); MYwrite_char (kidmum[1], RDP_Return); MYwrite_char (kidmum[1], (unsigned char) i); if (i) MYwrite_word (kidmum[1], y); /* number of bytes sent without error */ break; case RDP_CPUread: /* Read CPU State */ MYread_char (mumkid[0], &c); /* mode */ MYread_word (mumkid[0], &x); /* mask */ p = (char *) malloc (4 * RDINumCPURegs); i = armul_rdi.CPUread (c, x, (ARMword *) p); MYwrite_char (kidmum[1], RDP_Return); for (k = 1, j = 0; k != 0x80000000; k *= 2) if (k & x) MYwrite_word (kidmum[1], ((ARMword *) p)[j++]); free (p); if (i) MYwrite_char (kidmum[1], (unsigned char) j); MYwrite_char (kidmum[1], (unsigned char) i); break; case RDP_CPUwrite: /* Write CPU State */ MYread_char (mumkid[0], &c); /* mode */ MYread_word (mumkid[0], &x); /* mask */ p = (char *) malloc (4 * RDINumCPURegs); for (k = 1, j = 0; k != 0x80000000; k *= 2) if (k & x) MYread_word (mumkid[0], &(((ARMword *) p)[j++])); i = armul_rdi.CPUwrite (c, x, (ARMword *) p); MYwrite_char (kidmum[1], RDP_Return); MYwrite_char (kidmum[1], (unsigned char) i); free (p); break; case RDP_CPread: /* Read Co-Processor State */ MYread_char (mumkid[0], &c); /* CPnum */ MYread_word (mumkid[0], &x); /* mask */ p = q = (char *) malloc (16 * RDINumCPRegs); i = armul_rdi.CPread (c, x, (ARMword *) p); MYwrite_char (kidmum[1], RDP_Return); for (k = 1, j = 0; k != 0x80000000; k *= 2, j++) if (k & x) { if ((c == 1 || c == 2) && k <= 128) { MYwrite_FPword (kidmum[1], q); q += 16; } else { MYwrite_word (kidmum[1], *q); q += 4; } } free (p); if (i) MYwrite_char (kidmum[1], (unsigned char) j); MYwrite_char (kidmum[1], (unsigned char) i); break; case RDP_CPwrite: /* Write Co-Processor State */ MYread_char (mumkid[0], &c); /* CPnum */ MYread_word (mumkid[0], &x); /* mask */ p = q = (char *) malloc (16 * RDINumCPURegs); for (k = 1, j = 0; k != 0x80000000; k *= 2, j++) if (k & x) { if ((c == 1 || c == 2) && k <= 128) { MYread_FPword (kidmum[1], q); q += 16; } else { MYread_word (mumkid[0], (ARMword *) q); q += 4; } } i = armul_rdi.CPwrite (c, x, (ARMword *) p); MYwrite_char (kidmum[1], RDP_Return); MYwrite_char (kidmum[1], (unsigned char) i); free (p); break; case RDP_SetBreak: /* Set Breakpoint */ MYread_word (mumkid[0], &x); /* address */ MYread_char (mumkid[0], &c); /* type */ if ((c & 0xf) >= 5) MYread_word (mumkid[0], &y); /* bound */ i = armul_rdi.setbreak (x, c, y, &point); if (!MYrdp_level) BAG_putpair ((long) x, (long) point); MYwrite_char (kidmum[1], RDP_Return); if (MYrdp_level) MYwrite_word (kidmum[1], point); MYwrite_char (kidmum[1], (unsigned char) i); break; case RDP_ClearBreak: /* Clear Breakpoint */ MYread_word (mumkid[0], &point); /* PointHandle */ if (!MYrdp_level) { BAG_getsecond ((long) point, &outofthebag); /* swap pointhandle for address */ BAG_killpair_byfirst (outofthebag); point = outofthebag; } i = armul_rdi.clearbreak (point); MYwrite_char (kidmum[1], RDP_Return); MYwrite_char (kidmum[1], (unsigned char) i); break; case RDP_SetWatch: /* Set Watchpoint */ MYread_word (mumkid[0], &x); /* address */ MYread_char (mumkid[0], &c); /* type */ MYread_char (mumkid[0], &d); /* datatype */ if ((c & 0xf) >= 5) MYread_word (mumkid[0], &y); /* bound */ i = armul_rdi.setwatch (x, c, d, y, &point); MYwrite_char (kidmum[1], RDP_Return); MYwrite_word (kidmum[1], point); MYwrite_char (kidmum[1], (unsigned char) i); break; case RDP_ClearWatch: /* Clear Watchpoint */ MYread_word (mumkid[0], &point); /* PointHandle */ i = armul_rdi.clearwatch (point); MYwrite_char (kidmum[1], RDP_Return); MYwrite_char (kidmum[1], (unsigned char) i); break; case RDP_Execute: /* Excecute */ MYread_char (mumkid[0], &c); /* return */ #ifdef DEBUG fprintf (stderr, "Starting execution\n"); #endif i = armul_rdi.execute (&point); #ifdef DEBUG fprintf (stderr, "Completed execution\n"); #endif MYwrite_char (kidmum[1], RDP_Return); if (c & 0x80) MYwrite_word (kidmum[1], point); MYwrite_char (kidmum[1], (unsigned char) i); break; case RDP_Step: /* Step */ MYread_char (mumkid[0], &c); /* return */ MYread_word (mumkid[0], &x); /* ninstr */ point = 0x87654321; i = armul_rdi.step (x, &point); MYwrite_char (kidmum[1], RDP_Return); if (c & 0x80) MYwrite_word (kidmum[1], point); MYwrite_char (kidmum[1], (unsigned char) i); break; case RDP_Info: /* Info */ MYread_word (mumkid[0], &x); switch (x) { case RDIInfo_Target: i = armul_rdi.info (RDIInfo_Target, &y, &z); MYwrite_char (kidmum[1], RDP_Return); MYwrite_word (kidmum[1], y); /* Loads of info... */ MYwrite_word (kidmum[1], z); /* Model */ MYwrite_char (kidmum[1], (unsigned char) i); break; case RDISet_RDILevel: MYread_word (mumkid[0], &x); /* arg1, debug level */ i = armul_rdi.info (RDISet_RDILevel, &x, 0); if (i == RDIError_NoError) MYrdp_level = x; MYwrite_char (kidmum[1], RDP_Return); MYwrite_char (kidmum[1], (unsigned char) i); break; case RDISet_Cmdline: for (p = command_line; MYread_char (mumkid[0], p), *p; p++) ; /* String */ i = armul_rdi.info (RDISet_Cmdline, (unsigned long *) command_line, 0); MYwrite_char (kidmum[1], RDP_Return); MYwrite_char (kidmum[1], (unsigned char) i); break; case RDIInfo_Step: i = armul_rdi.info (RDIInfo_Step, &x, 0); MYwrite_char (kidmum[1], RDP_Return); MYwrite_word (kidmum[1], x); MYwrite_char (kidmum[1], (unsigned char) i); break; case RDIVector_Catch: MYread_word (mumkid[0], &x); i = armul_rdi.info (RDIVector_Catch, &x, 0); MYwrite_char (kidmum[1], RDP_Return); MYwrite_char (kidmum[1], i); break; case RDIInfo_Points: i = armul_rdi.info (RDIInfo_Points, &x, 0); MYwrite_char (kidmum[1], RDP_Return); MYwrite_word (kidmum[1], x); MYwrite_char (kidmum[1], (unsigned char) i); break; default: fprintf (stderr, "Unsupported info code %d\n", x); break; } break; case RDP_OSOpReply: /* OS Operation Reply */ MYwrite_char (kidmum[1], RDP_Fatal); break; case RDP_Reset: /* Reset */ for (i = 0; i < 50; i++) MYwrite_char (kidmum[1], RDP_Reset); p = (char *) malloc (MAXHOSTNAMELENGTH + 5 + 20); sprintf (p, "Running on %s:%d\n", localhost, socketnumber); MYwrite_string (kidmum[1], p); free (p); break; default: fprintf (stderr, "Oh dear: Something is seriously wrong :-(\n"); /* Hmm.. bad RDP operation */ break; } } } /* Handles memory read operations until an OS Operation Reply Message is */ /* encounterd. It then returns the byte info value (0, 1, or 2) and fills */ /* in 'putinr0' with the data if appropriate. */ int wait_for_osreply (ARMword * reply) { char *p, *q; int i, j, k; unsigned char c, d, message; ARMword x, y, z; struct sigaction action; PointHandle point; Dbg_ConfigBlock config; Dbg_HostosInterface hostif; struct Dbg_MCState *MCState; char command_line[256]; struct fd_set readfds; #ifdef DEBUG fprintf (stderr, "wait_for_osreply ().\n"); #endif /* Setup a signal handler for SIGUSR1 */ action.sa_handler = kid_handlesignal; action.sa_mask = 0; action.sa_flags = 0; sigaction (SIGUSR1, &action, (struct sigaction *) 0); while (1) { /* Wait for ever */ FD_ZERO (&readfds); FD_SET (mumkid[0], &readfds); i = select (nfds, &readfds, (fd_set *) 0, (fd_set *) 0, (struct timeval *) 0); if (i < 0) { perror ("select"); } if (read (mumkid[0], &message, 1) < 1) { perror ("read"); } switch (message) { case RDP_Read: /* Read Memory Address */ MYread_word (mumkid[0], &x); /* address */ MYread_word (mumkid[0], &y); /* nbytes */ p = (char *) malloc (y); i = armul_rdi.read (x, p, (unsigned *) &y); MYwrite_char (kidmum[1], RDP_Return); for (k = 0; k < y; k++) MYwrite_char (kidmum[1], p[k]); free (p); MYwrite_char (kidmum[1], (unsigned char) i); if (i) MYwrite_word (kidmum[1], y); /* number of bytes sent without error */ break; case RDP_Write: /* Write Memory Address */ MYread_word (mumkid[0], &x); /* address */ MYread_word (mumkid[0], &y); /* nbytes */ p = (char *) malloc (y); for (k = 0; k < y; k++) MYread_char (mumkid[0], &p[k]); i = armul_rdi.write (p, x, (unsigned *) &y); free (p); MYwrite_char (kidmum[1], RDP_Return); MYwrite_char (kidmum[1], (unsigned char) i); if (i) MYwrite_word (kidmum[1], y); /* number of bytes sent without error */ break; case RDP_OSOpReply: /* OS Operation Reply */ MYread_char (mumkid[0], &c); if (c == 1) MYread_char (mumkid[0], (char *) reply); if (c == 2) MYread_word (mumkid[0], reply); return c; break; default: fprintf (stderr, "HELP! Unaccounted-for message during OS request. \n"); MYwrite_char (kidmum[1], RDP_Fatal); } } }