1 /* THIS FILE HAS NOT HAD ITS COPYRIGHT CHECKED...FSF SHOULD NOT
2 DISTRIBUTE IT UNTIL THIS HAPPENS. */
4 /* Memory-access and commands for inferior process, for GDB.
20 #include <sys/types.h>
28 #define TERMINAL struct termios
31 #define SHORTTIMEOUT 1
34 #define KD_LINEDISCIPLINE 2
36 #define KD_BLOCKTRANSFER 8
42 #define GL_READING 0 /* get line is reading data */
43 #define GL_OK 1 /* Getline saw the "ok" string */
44 #define GL_SUCCESS 2 /* Get line got data */
45 #define GL_TIMEOUT 3 /* Get line timed out */
46 #define GL_OVERRUN 4 /* Get line filled up the buffer */
47 #define GL_EXCEPTION 5 /* Get line saw "Exception" */
48 #define GL_PROMLINE 6 /* Get line saw prom specific info */
49 #define GL_BLANKLINE 7 /* Get line saw a blank line */
51 static int kiodebug /* = KD_RETRY | KD_BLOCKTRANSFER */;
53 static CORE_ADDR remote_pc = 0;
54 static CORE_ADDR remote_next_pc = 0;
55 static CORE_ADDR remove_thisbp_next_pc = 0;
56 static CORE_ADDR remove_thisbp_target = 0;
58 enum showDrainage {DONTSHOW , SHOW} ;
61 /* Descriptor for I/O to remote machine. Initialize it to -1 so that
62 remote_open knows that we don't have a file open when the program
70 unsigned char ignorebuf[PBUFSIZ];
71 #define IGNORE &ignorebuf[0]
73 /* Maximum number of bytes to read/write at once. The value here
74 is chosen to fill up a packet (the headers account for the 32). */
75 #define MAXBUFBYTES ((PBUFSIZ-32)/2)
77 static void remote_send ();
78 static void putpkt ();
82 /* Open a connection to a remote debugger.
83 NAME is the filename used for communication. */
84 CORE_ADDR breakpoint_regs_addr;
88 remote_open (name, from_tty)
92 extern int frame_file_full_name;
93 unsigned char buf[PBUFSIZ];
101 breakpoint_regs_addr = parse_and_eval_address("&breakpoint_regs");
103 dontskipcrs = !frame_file_full_name; /* if we are running inside of
104 emacs, this will be true.
105 then skip carriage returns */
107 remote_desc = open (name, O_RDWR);
109 perror_with_name (name);
114 printf ("Remote debugging using %s\n", name);
115 remote_debugging = 1;
119 static char *boot_cmd = 0;
121 static print_boot_cmd()
123 fprintf(stderr, "boot command set to be \"%s\"\n", boot_cmd);
128 WAITTYPE ignoredWaitType;
133 remote_wait (&ignoredWaitType);
137 remote_wait (&ignoredWaitType);
141 fprintf(stderr, "rgdb and nucleus synchronized, booting....\n");
145 error("The boot command is null. Cannot start the remote kernel/nucleus");
149 /* Close the open connection to the remote debugger.
150 Use this when you want to detach and do something else
153 remote_close (from_tty)
156 if (!remote_debugging)
157 error ("Can't close remote connection: not debugging remotely.");
159 close (remote_desc); /* This should never be called if
160 there isn't something valid in
163 /* Do not try to close remote_desc again, later in the program. */
167 printf ("Ending remote debugging\n");
169 remote_debugging = 0;
172 /* Convert hex digit A to a number. */
178 if (a >= '0' && a <= '9')
180 else if (a >= 'a' && a <= 'f')
183 error ("Reply contains invalid hex digit");
186 /* Convert number NIB to a hex digit. */
198 /* Tell the remote machine to resume. */
200 extern int one_stepped; /* From machine dependent code */
201 static int remote_set_one_stepped;
204 remote_resume (step, signal)
209 remote_single_step();
211 remote_set_one_stepped = step;
215 /* Wait until the remote machine stops, then return,
216 storing status in STATUS just as `wait' would. */
223 int pend, saveTheOh = 0;
227 WSETEXIT ((*status), 0177);
233 int readUser, readProm, state;
235 doselect(&readUser, &readProm);
238 switch (state = getline(buf, PBUFSIZ, SHORTTIMEOUT))
241 if (remote_set_one_stepped)
251 if (kiodebug & KD_LINEDISCIPLINE)
252 fprintf(stderr, "%d<%s>\n", state, buf);
255 fprintf(stderr, "%s", buf);
260 remote_cleanup_after_stop();
261 WSETSTOP ((*status), SIGTRAP);
268 shuffleFromUserToProm();
271 static TERMINAL userterminal;
273 user_terminal_restore()
276 int in_desc = fileno (stdin);
277 ioctl (in_desc, TCSETS, &userterminal);
280 static void set_term_raw();
285 TERMINAL tempterminal;
286 int in_desc = fileno (stdin);
287 ioctl (in_desc, TCGETS, &userterminal);
288 tempterminal = userterminal;
290 tempterminal.c_lflag &= ~(ICANON|ISIG|IEXTEN);
291 tempterminal.c_cc[VMIN] = 1;
292 tempterminal.c_cc[VTIME] = 0;
293 tempterminal.c_iflag &= ~(INPCK|IXON|IXOFF);
294 tempterminal.c_oflag = 0;
296 ioctl (in_desc, TCSETS, &tempterminal);
300 doselect(pReadUser, pReadProm)
301 int *pReadUser, *pReadProm;
303 extern FILE *instream;
304 int in_desc = fileno (stdin);
305 int instreammask = 1 << in_desc;
306 int remotemask = 1 << remote_desc;
307 int rfds = instreammask | remotemask;
309 select (32, &rfds, 0, 0, (struct timeval *) 0); /* 0 = Block indefinitely */
310 *pReadUser = (rfds & instreammask) == instreammask;
311 *pReadProm = (rfds & remotemask) == remotemask;
316 /* Read the remote registers into the block pRegisters.
317 implementation copied largely from fetch_inferior_registers ()
321 remote_fetch_registers(ignored)
324 struct regs inferior_registers;
325 extern char registers[];
326 CORE_ADDR breakpoint_regs_target;
328 if (breakpoint_regs_addr == 0)
330 error("no address for breakpoint_regs\n");
333 remote_read_inferior_memory(breakpoint_regs_addr, &breakpoint_regs_target,
334 sizeof(breakpoint_regs_target));
336 bzero(registers, REGISTER_BYTES);
337 registers[REGISTER_BYTE (0)] = 0;
339 if (breakpoint_regs_target)
341 remote_read_inferior_memory(breakpoint_regs_target, &inferior_registers,
342 sizeof(inferior_registers));
343 registers[REGISTER_BYTE (0)] = 0;
344 bcopy (&inferior_registers.r_g1, ®isters[REGISTER_BYTE (1)], 15 * 4);
345 *(int *)®isters[REGISTER_BYTE (PS_REGNUM)] = inferior_registers.r_ps;
346 *(int *)®isters[REGISTER_BYTE (PC_REGNUM)] = inferior_registers.r_pc;
347 *(int *)®isters[REGISTER_BYTE (NPC_REGNUM)] = inferior_registers.r_npc;
348 *(int *)®isters[REGISTER_BYTE (Y_REGNUM)] = inferior_registers.r_y;
349 remote_pc = inferior_registers.r_pc;
350 remote_next_pc = inferior_registers.r_npc;
351 remote_read_inferior_memory (inferior_registers.r_sp,
352 ®isters[REGISTER_BYTE (16)],
357 error("breakpoint_regs == 0\n");
364 /* Write memory data directly to the remote machine.
365 This does not inform the data cache; the data cache uses this.
366 MEMADDR is the address in the remote memory space.
367 MYADDR is the address of the buffer in our space.
368 LEN is the number of bytes. */
371 remote_write_bytes (memaddr, myaddr, len)
373 unsigned char *myaddr;
379 /* Command describes registers byte by byte,
380 each byte encoded as two hex characters. */
382 for (i = 0; i < len; i++)
384 sprintf(buf, "%x %x c!", myaddr[i], memaddr + i);
385 remote_send (buf, buf);
386 if (strstr(buf, "Exception"))
394 /* Copy LEN bytes of data from debugger memory at MYADDR
395 to inferior's memory at MEMADDR. Returns errno value. */
397 remote_write_inferior_memory (memaddr, myaddr, len)
407 if (len > MAXBUFBYTES)
408 xfersize = MAXBUFBYTES;
412 retval = remote_write_bytes(memaddr, myaddr, xfersize);
414 return retval; /* error */
420 return 0; /* no error */
424 /* read a single character */
432 /* termio does the timeout for us. */
433 read (remote_desc, &buf, 1);
437 /* Send the command in BUF to the remote machine,
438 and read the reply into BUF.
439 Report an error if we get an error reply. */
442 remote_send (buf, buf2)
449 /* Send a single character out over the wire */
460 write(remote_desc, &ch, 1);
461 for (i = 0; i < 100; i++)
465 if (read (remote_desc, &nch, 1) == 0)
468 || (ch == '\n' && nch == '\r')
469 || (ch == '\r' && nch == '\n'))
471 if (kiodebug & KD_MINUTAE)
472 fprintf (stderr, "Sent %c(%d) Received %c(%d)\n", ch, ch, nch, nch);
477 /* Send a packet to the remote machine, with error checking.
478 The data of the packet is in BUF. */
485 int cnt = strlen (buf);
488 if (kiodebug & KD_LINEDISCIPLINE)
489 fprintf(stderr, "putpkt(%s)\n", buf);
491 for (i = 0; i < cnt; i++)
492 putcharacter (buf[i]);
496 jmp_buf getline_jmpbuf;
498 /* Read a line from the remote machine, and store it in BUF. */
503 if (kiodebug & KD_RETRY)
504 fprintf(stderr, "getline timed out\n");
505 longjmp(getline_jmpbuf, 1);
509 getline (buf, size, timeout)
515 int isspace_state = 1;
517 if ((void (*)) signal (SIGALRM, getline_timer) == (void (*)) -1)
518 perror ("remote_open: error in signal");
520 --size; /* back it up one so that we can read */
524 if (setjmp(getline_jmpbuf))
531 char ch = readCharFromProm();
532 isspace_state = isspace_state && isspace(ch);
533 if (ch && (dontskipcrs || ch != '\r'))
538 if (kiodebug & KD_MINUTAE)
539 fprintf (stderr,"letter received :%c\n", buf[cnt - 1]);
540 if (cnt >= 2 && buf[cnt - 2] == 'o' && buf[cnt - 1] == 'k')
542 else if (buf[cnt - 1] == '\n' )
543 state = isspace_state ? GL_BLANKLINE : GL_SUCCESS;
544 else if (cnt == size)
546 else if (strstr(buf, "Type 'go' to resume"))
548 else if (strstr(buf, "Type help for more information"))
550 else if (strstr(buf, "Exception"))
551 state = GL_EXCEPTION;
553 while (state == GL_READING);
557 if (kiodebug & KD_LINEDISCIPLINE)
558 fprintf (stderr,"Line received :%s\n", buf);
563 /* Read a packet from the remote machine, and store it in BUF. */
573 char ch = readCharFromProm();
576 if (kiodebug & KD_MINUTAE)
577 fprintf (stderr,"letter received :%c\n", buf[cnt - 1]);
580 buf[cnt - 2] != 'o' &&
581 buf[cnt - 1] != 'k');
584 if (kiodebug& KD_LINEDISCIPLINE)
585 fprintf (stderr,"Packet received :%s\n", buf);
589 void remote_fetch_word (addr)
592 error ("Internal error: remote_fetch_word is obsolete.\n");
594 void remote_store_word (addr)
597 error ("Internal error: remote_store_word is obsolete.\n");
602 enum showDrainage showit;
604 unsigned char buf[PBUFSIZ];
607 while ((cnt = read(remote_desc, buf, PBUFSIZ)) > 0)
610 if (kiodebug& KD_LINEDISCIPLINE)
611 fprintf (stderr,"Draining :%s\n", buf);
614 fprintf (stderr,"%s", buf);
616 if (kiodebug& KD_LINEDISCIPLINE)
617 fprintf (stderr,"Drained\n");
621 if (kiodebug & KD_RETRY)
622 fprintf (stderr,"rgdb sending break to target...\n");
625 fprintf (stderr,"=");
629 ioctl (remote_desc, TCSBRK, 0);
634 /* shuffle a character from the user to remote debugger */
637 shuffleFromUserToProm()
640 static int escape = 0;
642 extern FILE *instream;
645 if (read(STDIN, &ch , 1) != 1 || ch == 0)
654 read(STDIN, &ch , 1);
658 static char tilde = '~';
664 } else /* not escape */ {
675 /* Tell the Prom put a breakpoint at memaddr */
676 remote_insert_breakpoint(memaddr)
681 /* Command describes registers byte by byte,
682 each byte encoded as two hex characters. */
684 sprintf(buf, "%x +bp", memaddr);
685 remote_send(buf, buf);
686 if (strstr(buf, "Exception"))
696 /* Tell the Prom remove the the breakpoint at memaddr */
697 remote_remove_breakpoint(memaddr)
702 /* Command describes registers byte by byte,
703 each byte encoded as two hex characters. */
705 sprintf(buf, "%x -bp", memaddr);
706 remote_send(buf, buf);
707 if (strstr(buf, "Exception"))
721 /* Read memory data directly from the remote machine.
722 This does not use the data cache; the data cache uses this.
723 MEMADDR is the address in the remote memory space.
724 MYADDR is the address of the buffer in our space.
725 LEN is the number of words. */
728 remote_read(memaddr, myaddr, len, increment, promcommand)
730 unsigned char *myaddr;
739 /* Command describes registers byte by byte,
740 each byte encoded as two hex characters. */
742 for (i = 0; i < len; i += increment)
744 sprintf(buf, promcommand, memaddr + i) ;
745 remote_send(buf, buf2);
746 remote_send(".", buf);
747 if (strstr(buf2, "Exception"))
749 bzero(&myaddr[i], len - i);
755 for (pBuf = &buf[0]; *pBuf == '\r' || *pBuf == '\n'; pBuf++)
757 sscanf(pBuf, "%x\n", &num);
760 case 1: myaddr[i] = num;
762 fprintf(stderr, "number out of bounds %x truncating to %x\n",
765 case 4: {unsigned long *p;
766 p = (unsigned long *) &myaddr[i];
770 default: fprintf(stderr, "unknown increment\n"); break;
779 /* Read LEN bytes from inferior memory at MEMADDR. Put the result
780 at debugger address MYADDR. Returns errno value. */
782 remote_read_inferior_memory(memaddr, myaddr, len)
792 if (len > MAXBUFBYTES)
793 xfersize = MAXBUFBYTES;
798 if (mod == 0 && xfersize >= 4)
799 if (mod == 0 && xfersize >= 16)
801 xfersize = remote_read_many(memaddr, myaddr, (len & ~3));
805 xfersize = remote_read(memaddr, myaddr, 4, 4, "%x @");
807 xfersize = remote_read(memaddr, myaddr, max(mod, 1), 1, "%x c@");
809 return EFAULT; /* error */
814 return 0; /* no error */
816 static int baud_rate=B38400;
818 static void set_term_raw(pTermio)
821 pTermio->c_cflag &= (CREAD|HUPCL|CLOCAL);
822 pTermio->c_cflag |= baud_rate | CS8;
823 pTermio->c_iflag = ISTRIP /* | IXON | IXOFF */;
824 pTermio->c_oflag = 0;
825 pTermio->c_lflag = 0;
826 pTermio->c_cc[VMIN] = 0;
827 pTermio->c_cc[VTIME] = 1;
830 /* setup the remote termio stream */
835 ioctl(remote_desc, TCGETS, &temptempio);
836 set_term_raw(&temptempio);
837 ioctl(remote_desc, TCSETS, &temptempio);
840 /* step one machine instruction */
841 remote_single_step ()
843 CORE_ADDR next_pc, npc4, target, pc;
846 Error, not_branch, bicc, bicca, ba, baa, ticc, ta
848 branch_type br, isannulled();
850 npc4 = remote_next_pc + 4; /* branch not taken */
852 /* Always set breakpoint for NPC. */
854 remote_insert_breakpoint(remote_next_pc);
855 remove_thisbp_next_pc = remote_next_pc;
857 /* printf ("set break at %x\n",remote_next_pc); */
859 br = isannulled (remote_pc, &target);
863 /* Conditional annulled branch will either end up at
864 npc (if taken) or at npc+4 (if not taken).
866 remote_insert_breakpoint(npc4);
867 remove_thisbp_target = npc4;
869 else if (br == baa && target != remote_next_pc)
871 /* Unconditional annulled branch will always end up at
873 remote_insert_breakpoint(target);
874 remove_thisbp_target = target;
881 /* read many words of memory */
883 remote_read_many(memaddr, myaddr, len)
885 unsigned char *myaddr;
888 #define BLOCKSIZE 1024
889 static int max_number_of_blocks = 24;
895 /* Command describes registers byte by byte,
896 each byte encoded as two hex characters. */
898 len = min(len, max_number_of_blocks * BLOCKSIZE);
900 sprintf(buf, "%x %x do i @ . cr 4 +loop", memaddr + len, memaddr);
902 getline(buf2, PBUFSIZ, LONGTIMEOUT); /* I don't care */
904 p = (unsigned long *) myaddr;
905 for (i = 0; i < len; i += 4, p++)
907 extern int InspectIt;
909 if (!InspectIt && ((i % BLOCKSIZE) == 0))
910 fprintf(stderr, "+"); /* let 'em know that we are working */
911 switch (getline(buf2, PBUFSIZ, LONGTIMEOUT))
920 /* resync and retry */
921 max_number_of_blocks = max(1, i / BLOCKSIZE);
922 fprintf(stderr, "-"); /* let 'em know that we are working */
924 if (kiodebug & KD_BLOCKTRANSFER)
925 fprintf(stderr, "failed read_many %d %d/%d (%s)\n",
926 max_number_of_blocks, i, len, buf2);
928 return remote_read_many(memaddr, myaddr, len);
932 sscanf(buf2, "%x\n", p);
936 if (kiodebug & KD_BLOCKTRANSFER)
937 fprintf(stderr, "success read_many %d %d/%d (%s)\n", max_number_of_blocks,
942 * allow the user to type directly to the prom !
946 int readUser, readProm;
949 fprintf(stderr, "entering prom mode...\n");
952 doselect(&readUser, &readProm);
954 if (shuffleFromUserToProm())
956 fprintf(stderr, "exiting prom mode\n");
957 user_terminal_restore();
961 fprintf(stderr, "%c", readCharFromProm ());
964 static char *boot_set_msg = "boot needs a string in quotes of the form \"boot vmunix\" ";
965 static char *baud_set_msg = "baud rate should be of the form \"set baud=9600\"";
968 set_boot (arg, from_tty)
977 error_no_arg (boot_set_msg);
980 arg = tilde_expand (arg);
981 make_cleanup (free, arg);
983 i = strlen (arg) - 1;
988 while (*arg && h < i && (arg[h] == ' ' || arg[h] == '\t'))
993 while (i > 0 && (arg[i] == ' ' || arg[i] == '\t'))
996 if (h >= i || !*arg || arg[h] != '"' || arg[i] != '"')
997 error (boot_set_msg);
1000 boot_cmd = savestring (++arg, i);
1001 boot_cmd[i - 1] = '\0';
1007 static int bauds[] = {
1008 0, 50, 75, 110, 134, 150, 200, 300, 600,
1009 1200, 1800, 2400, 4800, 9600, 19200, 38400, -1
1013 static int convert_to_baud_B(n)
1018 for (p = bauds; *p != -1; p++)
1019 if (*p != 0 && *p == n)
1024 static void print_acceptable_bauds()
1028 for (p = bauds; *p != -1; p++)
1030 fprintf(stderr, "%d\n", *p);
1033 static void print_baud()
1035 fprintf(stderr, "the baud rate is now %d\n", bauds[baud_rate]);
1039 set_baud (arg, from_tty)
1048 print_acceptable_bauds();
1049 error_no_arg (baud_set_msg);
1053 while (*arg && !isdigit(*arg))
1056 if (*arg && (temp_baud_rate = convert_to_baud_B(atoi(arg))) != NULL)
1058 baud_rate = temp_baud_rate;
1059 if (remote_debugging)
1064 fprintf(stderr, "bad baud rate %s, acceptable values are\n", arg);
1065 print_acceptable_bauds();
1075 _initialize_remote()
1077 /* Chain containing all defined set subcommands */
1079 extern struct cmd_list_element *setlist;
1082 add_com ("prom", class_obscure, prom_command,
1083 "Conduct a dialogue directly with the prom. \
1084 only useful after an attach\n\
1085 Terminate by typing ~.");
1087 add_cmd ("boot_cmd", class_support, set_boot, boot_set_msg, &setlist);
1089 add_cmd ("baud", class_support, set_baud, baud_set_msg, &setlist);
1091 set_boot ("\"boot nucleus -d\"", 0);
1095 /* Store the remote registers from the contents of the block REGS. */
1098 remote_store_registers (registers)
1102 struct regs inferior_registers;
1104 core = parse_and_eval_address("breakpoint_regs");
1106 bcopy (®isters[REGISTER_BYTE (1)],
1107 &inferior_registers.r_g1, 15 * 4);
1109 inferior_registers.r_ps =
1110 *(int *)®isters[REGISTER_BYTE (PS_REGNUM)];
1111 inferior_registers.r_pc =
1112 *(int *)®isters[REGISTER_BYTE (PC_REGNUM)];
1113 inferior_registers.r_npc =
1114 *(int *)®isters[REGISTER_BYTE (NPC_REGNUM)];
1115 inferior_registers.r_y =
1116 *(int *)®isters[REGISTER_BYTE (Y_REGNUM)];
1118 remote_write_inferior_memory (*(int *)®isters[REGISTER_BYTE (SP_REGNUM)],
1119 ®isters[REGISTER_BYTE (16)],
1121 remote_write_inferior_memory (core,
1122 &inferior_registers,
1123 sizeof(inferior_registers));
1128 /* we have stopped. do some cleanup */
1129 remote_cleanup_after_stop()
1131 if (remove_thisbp_next_pc)
1133 remote_remove_breakpoint (remove_thisbp_next_pc);
1134 remove_thisbp_next_pc = 0;
1136 if (remove_thisbp_target)
1138 remote_remove_breakpoint (remove_thisbp_target);
1139 remove_thisbp_target = 0;
1141 user_terminal_restore();
1143 one_stepped = remote_set_one_stepped;