/* parent.c -- ARMulator RDP comms code: 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 Parent process continues here... */ /* It waits on the socket and passes on RDP messages down a pipe */ /* to the ARMulator RDP to RDI interpreter. */ /*****************************************************************/ #include #include #include #include "time.h" #include "armdefs.h" #include "dbg_rdi.h" #include "communicate.h" /* The socket to the debugger */ extern int debugsock; /* The pipes between the two processes */ extern int mumkid[2]; extern int kidmum[2]; /* A pipe for handling SWI return values that goes straight from the */ /* parent to the ARMulator host interface, bypassing the child's RDP */ /* to RDI interpreter */ extern int DebuggerARMul[2]; /* The maximum number of file descriptors */ extern int nfds; /* The child process id. */ extern pid_t child; void parent () { int i, j, k; unsigned char message, CPnum, exreturn; ARMword mask, nbytes, messagetype; unsigned char c, d; ARMword x, y; int virgin = 1; struct fd_set readfds; #ifdef DEBUG fprintf (stderr, "parent ()...\n"); #endif panic_error: if (!virgin) { #ifdef DEBUG fprintf (stderr, "Arghh! What is going on?\n"); #endif kill (child, SIGHUP); MYwrite_char (debugsock, RDP_Reset); } virgin = 0; while (1) { /* Wait either for the ARMulator or the debugger */ FD_ZERO (&readfds); FD_SET (kidmum[0], &readfds); /* Wait for messages from ARMulator */ FD_SET (debugsock, &readfds); /* Wait for messages from debugger */ #ifdef DEBUG fprintf (stderr, "Waiting for ARMulator or debugger... "); #endif while ((i = select (nfds, &readfds, (fd_set *) 0, (fd_set *) 0, 0)) < 0) { perror ("select"); } #ifdef DEBUG fprintf (stderr, "(%d/2)", i); #endif if (FD_ISSET (debugsock, &readfds)) { #ifdef DEBUG fprintf (stderr, "->debugger\n"); #endif /* Inside this rather large if statement with simply pass on a complete message to the ARMulator. The reason we need to pass messages on one at a time is that we have to know whether the message is an OSOpReply or an info(stop), so that we can take different action in those cases. */ if (MYread_char (debugsock, &message)) goto panic_error; switch (message) { case RDP_Start: /* Open and/or Initialise */ #ifdef DEBUG fprintf (stderr, "RDP Open\n"); #endif if (MYread_char (debugsock, &c)) /* type */ goto panic_error; if (MYread_word (debugsock, &x)) /* memory size */ goto panic_error; MYwrite_char (mumkid[1], message); MYwrite_char (mumkid[1], c); MYwrite_word (mumkid[1], x); if (c & 0x2) { passon (debugsock, mumkid[1], 1); /* speed */ } break; case RDP_End: /* Close and Finalise */ #ifdef DEBUG fprintf (stderr, "RDP Close\n"); #endif MYwrite_char (mumkid[1], message); break; case RDP_Read: /* Read Memory Address */ #ifdef DEBUG fprintf (stderr, "RDP Read Memory\n"); #endif MYwrite_char (mumkid[1], message); if (passon (debugsock, mumkid[1], 4)) goto panic_error; /* address */ if (MYread_word (debugsock, &nbytes)) goto panic_error; /* nbytes */ MYwrite_word (mumkid[1], nbytes); break; case RDP_Write: /* Write Memory Address */ #ifdef DEBUG fprintf (stderr, "RDP Write Memory\n"); #endif if (MYread_word (debugsock, &x)) goto panic_error; /* address */ if (MYread_word (debugsock, &y)) goto panic_error; /* nbytes */ MYwrite_char (mumkid[1], message); MYwrite_word (mumkid[1], x); MYwrite_word (mumkid[1], y); passon (debugsock, mumkid[1], y); /* actual data */ break; case RDP_CPUread: /* Read CPU State */ #ifdef DEBUG fprintf (stderr, "RDP Read CPU\n"); #endif if (MYread_char (debugsock, &c)) goto panic_error; /* mode */ if (MYread_word (debugsock, &mask)) goto panic_error; /* mask */ MYwrite_char (mumkid[1], message); MYwrite_char (mumkid[1], c); MYwrite_word (mumkid[1], mask); break; case RDP_CPUwrite: /* Write CPU State */ #ifdef DEBUG fprintf (stderr, "RDP Write CPU\n"); #endif if (MYread_char (debugsock, &c)) goto panic_error; /* mode */ if (MYread_word (debugsock, &x)) goto panic_error; /* mask */ MYwrite_char (mumkid[1], message); MYwrite_char (mumkid[1], c); MYwrite_word (mumkid[1], x); for (k = 1, j = 0; k != 0x80000000; k *= 2, j++) if ((k & x) && passon (debugsock, mumkid[1], 4)) goto panic_error; break; case RDP_CPread: /* Read Co-Processor State */ #ifdef DEBUG fprintf (stderr, "RDP Read CP state\n"); #endif if (MYread_char (debugsock, &CPnum)) goto panic_error; if (MYread_word (debugsock, &mask)) goto panic_error; MYwrite_char (mumkid[1], message); MYwrite_char (mumkid[1], CPnum); MYwrite_word (mumkid[1], mask); break; case RDP_CPwrite: /* Write Co-Processor State */ #ifdef DEBUG fprintf (stderr, "RDP Write CP state\n"); #endif if (MYread_char (debugsock, &CPnum)) goto panic_error; if (MYread_word (debugsock, &mask)) goto panic_error; MYwrite_char (mumkid[1], message); MYwrite_char (mumkid[1], c); MYwrite_char (mumkid[1], x); for (k = 1, j = 0; k != 0x80000000; k *= 2, j++) if (k & x) { if ((c == 1 || c == 2) && k <= 128) { /* FP register = 12 bytes + 4 bytes format */ if (passon (debugsock, mumkid[1], 16)) goto panic_error; } else { /* Normal register = 4 bytes */ if (passon (debugsock, mumkid[1], 4)) goto panic_error; } } break; case RDP_SetBreak: /* Set Breakpoint */ #ifdef DEBUG fprintf (stderr, "RDP Set Breakpoint\n"); #endif if (MYread_word (debugsock, &x)) goto panic_error; /* address */ if (MYread_char (debugsock, &c)) goto panic_error; /* type */ MYwrite_char (mumkid[1], message); MYwrite_word (mumkid[1], x); MYwrite_char (mumkid[1], c); if (((c & 0xf) >= 5) && passon (debugsock, mumkid[1], 4)) goto panic_error; /* bound */ break; case RDP_ClearBreak: /* Clear Breakpoint */ #ifdef DEBUG fprintf (stderr, "RDP Clear Breakpoint\n"); #endif MYwrite_char (mumkid[1], message); if (passon (debugsock, mumkid[1], 4)) goto panic_error; /* point */ break; case RDP_SetWatch: /* Set Watchpoint */ #ifdef DEBUG fprintf (stderr, "RDP Set Watchpoint\n"); #endif if (MYread_word (debugsock, &x)) goto panic_error; /* address */ if (MYread_char (debugsock, &c)) goto panic_error; /* type */ if (MYread_char (debugsock, &d)) goto panic_error; /* datatype */ MYwrite_char (mumkid[1], message); MYwrite_word (mumkid[1], x); MYwrite_char (mumkid[1], c); MYwrite_char (mumkid[1], d); if (((c & 0xf) >= 5) && passon (debugsock, mumkid[1], 4)) goto panic_error; /* bound */ break; case RDP_ClearWatch: /* Clear Watchpoint */ #ifdef DEBUG fprintf (stderr, "RDP Clear Watchpoint\n"); #endif MYwrite_char (mumkid[1], message); if (passon (debugsock, mumkid[1], 4)) goto panic_error; /* point */ break; case RDP_Execute: /* Excecute */ #ifdef DEBUG fprintf (stderr, "RDP Execute\n"); #endif /* LEAVE THIS ONE 'TIL LATER... */ /* NEED TO WORK THINGS OUT */ /* NO ASCYNCHROUS RUNNING */ if (MYread_char (debugsock, &c)) goto panic_error; /* return */ /* Remember incase bit 7 is set and we have to send back a word */ exreturn = c; MYwrite_char (mumkid[1], message); MYwrite_char (mumkid[1], c); break; case RDP_Step: /* Step */ #ifdef DEBUG fprintf (stderr, "RDP Step\n"); #endif if (MYread_char (debugsock, &c)) goto panic_error; /* return */ if (MYread_word (debugsock, &x)) goto panic_error; /* ninstr */ MYwrite_char (mumkid[1], message); MYwrite_char (mumkid[1], c); MYwrite_word (mumkid[1], x); break; case RDP_Info: /* Info */ #ifdef DEBUG fprintf (stderr, "RDP Info\n"); #endif /* INFO TARGET, SET RDI LEVEL */ if (MYread_word (debugsock, &messagetype)) goto panic_error; /* info */ switch (messagetype) { case RDIInfo_Target: MYwrite_char (mumkid[1], message); MYwrite_word (mumkid[1], messagetype); break; case RDISet_RDILevel: MYwrite_char (mumkid[1], message); MYwrite_word (mumkid[1], messagetype); if (passon (debugsock, mumkid[1], 1)) goto panic_error; /* argument */ break; case RDISet_Cmdline: /* Got to pass on a string argument */ MYwrite_char (mumkid[1], message); MYwrite_word (mumkid[1], messagetype); do { if (MYread_char (debugsock, &c)) goto panic_error; MYwrite_char (mumkid[1], c); } while (c); break; case RDISignal_Stop: kill (child, SIGUSR1); MYwrite_char (debugsock, RDP_Return); MYwrite_char (debugsock, RDIError_UserInterrupt); break; case RDIVector_Catch: MYread_word (debugsock, &x); MYwrite_char (mumkid[1], message); MYwrite_word (mumkid[1], messagetype); MYwrite_word (mumkid[1], x); break; case RDIInfo_Step: MYwrite_char (mumkid[1], message); MYwrite_word (mumkid[1], messagetype); break; case RDIInfo_Points: MYwrite_char (mumkid[1], message); MYwrite_word (mumkid[1], messagetype); break; default: fprintf (stderr, "Unrecognized RDIInfo request %d\n", messagetype); goto panic_error; } break; case RDP_OSOpReply: /* OS Operation Reply */ #ifdef DEBUG fprintf (stderr, "RDP OS Reply\n"); #endif MYwrite_char (mumkid[1], message); if (MYread_char (debugsock, &message)) goto panic_error; MYwrite_char (mumkid[1], message); switch (message) { case 0: /* return value i.e. nothing else. */ break; case 1: /* returns a byte... */ if (MYread_char (debugsock, &c)) goto panic_error; MYwrite_char (mumkid[1], c); break; case 2: /* returns a word... */ if (MYread_word (debugsock, &x)) goto panic_error; MYwrite_word (mumkid[1], x); break; } break; case RDP_Reset: /* Reset */ #ifdef DEBUG fprintf (stderr, "RDP Reset\n"); #endif MYwrite_char (mumkid[1], message); break; default: /* Hmm.. bad RDP operation */ fprintf (stderr, "RDP Bad RDP request (%d)\n", message); MYwrite_char (debugsock, RDP_Return); MYwrite_char (debugsock, RDIError_UnimplementedMessage); break; } } if (FD_ISSET (kidmum[0], &readfds)) { #ifdef DEBUG fprintf (stderr, "->ARMulator\n"); #endif /* Anything we get from the ARMulator has to go to the debugger... */ /* It is that simple! */ passon (kidmum[0], debugsock, 1); } } }