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.
21 #include <sys/types.h>
29 #define TERMINAL struct termios
32 #define SHORTTIMEOUT 1
35 #define KD_LINEDISCIPLINE 2
37 #define KD_BLOCKTRANSFER 8
43 #define GL_READING 0 /* get line is reading data */
44 #define GL_OK 1 /* Getline saw the "ok" string */
45 #define GL_SUCCESS 2 /* Get line got data */
46 #define GL_TIMEOUT 3 /* Get line timed out */
47 #define GL_OVERRUN 4 /* Get line filled up the buffer */
48 #define GL_EXCEPTION 5 /* Get line saw "Exception" */
49 #define GL_PROMLINE 6 /* Get line saw prom specific info */
50 #define GL_BLANKLINE 7 /* Get line saw a blank line */
52 static int kiodebug /* = KD_RETRY | KD_BLOCKTRANSFER */;
54 static CORE_ADDR remote_pc = 0;
55 static CORE_ADDR remote_next_pc = 0;
56 static CORE_ADDR remove_thisbp_next_pc = 0;
57 static CORE_ADDR remove_thisbp_target = 0;
59 enum showDrainage {DONTSHOW , SHOW} ;
62 /* Descriptor for I/O to remote machine. Initialize it to -1 so that
63 remote_open knows that we don't have a file open when the program
71 unsigned char ignorebuf[PBUFSIZ];
72 #define IGNORE &ignorebuf[0]
74 /* Maximum number of bytes to read/write at once. The value here
75 is chosen to fill up a packet (the headers account for the 32). */
76 #define MAXBUFBYTES ((PBUFSIZ-32)/2)
78 static void remote_send ();
79 static void putpkt ();
83 /* Open a connection to a remote debugger.
84 NAME is the filename used for communication. */
85 CORE_ADDR breakpoint_regs_addr;
89 remote_open (name, from_tty)
93 extern int frame_file_full_name;
94 unsigned char buf[PBUFSIZ];
102 breakpoint_regs_addr = parse_and_eval_address("&breakpoint_regs");
104 dontskipcrs = !frame_file_full_name; /* if we are running inside of
105 emacs, this will be true.
106 then skip carriage returns */
108 remote_desc = open (name, O_RDWR);
110 perror_with_name (name);
115 printf ("Remote debugging using %s\n", name);
116 remote_debugging = 1;
120 static char *boot_cmd = 0;
122 static print_boot_cmd()
124 fprintf(stderr, "boot command set to be \"%s\"\n", boot_cmd);
129 WAITTYPE ignoredWaitType;
134 remote_wait (&ignoredWaitType);
138 remote_wait (&ignoredWaitType);
142 fprintf(stderr, "rgdb and nucleus synchronized, booting....\n");
146 error("The boot command is null. Cannot start the remote kernel/nucleus");
150 /* Close the open connection to the remote debugger.
151 Use this when you want to detach and do something else
154 remote_close (from_tty)
157 if (!remote_debugging)
158 error ("Can't close remote connection: not debugging remotely.");
160 close (remote_desc); /* This should never be called if
161 there isn't something valid in
164 /* Do not try to close remote_desc again, later in the program. */
168 printf ("Ending remote debugging\n");
170 remote_debugging = 0;
173 /* Convert hex digit A to a number. */
179 if (a >= '0' && a <= '9')
181 else if (a >= 'a' && a <= 'f')
184 error ("Reply contains invalid hex digit");
187 /* Convert number NIB to a hex digit. */
199 /* Tell the remote machine to resume. */
201 extern int one_stepped; /* From machine dependent code */
202 static int remote_set_one_stepped;
205 remote_resume (step, signal)
210 remote_single_step();
212 remote_set_one_stepped = step;
216 /* Wait until the remote machine stops, then return,
217 storing status in STATUS just as `wait' would. */
224 int pend, saveTheOh = 0;
228 WSETEXIT ((*status), 0177);
234 int readUser, readProm, state;
236 doselect(&readUser, &readProm);
239 switch (state = getline(buf, PBUFSIZ, SHORTTIMEOUT))
242 if (remote_set_one_stepped)
252 if (kiodebug & KD_LINEDISCIPLINE)
253 fprintf(stderr, "%d<%s>\n", state, buf);
256 fprintf(stderr, "%s", buf);
261 remote_cleanup_after_stop();
262 WSETSTOP ((*status), SIGTRAP);
269 shuffleFromUserToProm();
272 static TERMINAL userterminal;
274 user_terminal_restore()
277 int in_desc = fileno (stdin);
278 ioctl (in_desc, TCSETS, &userterminal);
281 static void set_term_raw();
286 TERMINAL tempterminal;
287 int in_desc = fileno (stdin);
288 ioctl (in_desc, TCGETS, &userterminal);
289 tempterminal = userterminal;
291 tempterminal.c_lflag &= ~(ICANON|ISIG|IEXTEN);
292 tempterminal.c_cc[VMIN] = 1;
293 tempterminal.c_cc[VTIME] = 0;
294 tempterminal.c_iflag &= ~(INPCK|IXON|IXOFF);
295 tempterminal.c_oflag = 0;
297 ioctl (in_desc, TCSETS, &tempterminal);
301 doselect(pReadUser, pReadProm)
302 int *pReadUser, *pReadProm;
304 extern FILE *instream;
305 int in_desc = fileno (stdin);
306 int instreammask = 1 << in_desc;
307 int remotemask = 1 << remote_desc;
308 int rfds = instreammask | remotemask;
310 select (32, &rfds, 0, 0, (struct timeval *) 0); /* 0 = Block indefinitely */
311 *pReadUser = (rfds & instreammask) == instreammask;
312 *pReadProm = (rfds & remotemask) == remotemask;
317 /* Read the remote registers into the block pRegisters.
318 implementation copied largely from fetch_inferior_registers ()
322 remote_fetch_registers(ignored)
325 struct regs inferior_registers;
326 extern char registers[];
327 CORE_ADDR breakpoint_regs_target;
329 if (breakpoint_regs_addr == 0)
331 error("no address for breakpoint_regs\n");
334 remote_read_inferior_memory(breakpoint_regs_addr, &breakpoint_regs_target,
335 sizeof(breakpoint_regs_target));
337 bzero(registers, REGISTER_BYTES);
338 registers[REGISTER_BYTE (0)] = 0;
340 if (breakpoint_regs_target)
342 remote_read_inferior_memory(breakpoint_regs_target, &inferior_registers,
343 sizeof(inferior_registers));
344 registers[REGISTER_BYTE (0)] = 0;
345 bcopy (&inferior_registers.r_g1, ®isters[REGISTER_BYTE (1)], 15 * 4);
346 *(int *)®isters[REGISTER_BYTE (PS_REGNUM)] = inferior_registers.r_ps;
347 *(int *)®isters[REGISTER_BYTE (PC_REGNUM)] = inferior_registers.r_pc;
348 *(int *)®isters[REGISTER_BYTE (NPC_REGNUM)] = inferior_registers.r_npc;
349 *(int *)®isters[REGISTER_BYTE (Y_REGNUM)] = inferior_registers.r_y;
350 remote_pc = inferior_registers.r_pc;
351 remote_next_pc = inferior_registers.r_npc;
352 remote_read_inferior_memory (inferior_registers.r_sp,
353 ®isters[REGISTER_BYTE (16)],
358 error("breakpoint_regs == 0\n");
365 /* Write memory data directly to the remote machine.
366 This does not inform the data cache; the data cache uses this.
367 MEMADDR is the address in the remote memory space.
368 MYADDR is the address of the buffer in our space.
369 LEN is the number of bytes. */
372 remote_write_bytes (memaddr, myaddr, len)
374 unsigned char *myaddr;
380 /* Command describes registers byte by byte,
381 each byte encoded as two hex characters. */
383 for (i = 0; i < len; i++)
385 sprintf(buf, "%x %x c!", myaddr[i], memaddr + i);
386 remote_send (buf, buf);
387 if (strstr(buf, "Exception"))
395 /* Copy LEN bytes of data from debugger memory at MYADDR
396 to inferior's memory at MEMADDR. Returns errno value. */
398 remote_write_inferior_memory (memaddr, myaddr, len)
408 if (len > MAXBUFBYTES)
409 xfersize = MAXBUFBYTES;
413 retval = remote_write_bytes(memaddr, myaddr, xfersize);
415 return retval; /* error */
421 return 0; /* no error */
425 /* read a single character */
433 /* termio does the timeout for us. */
434 read (remote_desc, &buf, 1);
438 /* Send the command in BUF to the remote machine,
439 and read the reply into BUF.
440 Report an error if we get an error reply. */
443 remote_send (buf, buf2)
450 /* Send a single character out over the wire */
461 write(remote_desc, &ch, 1);
462 for (i = 0; i < 100; i++)
466 if (read (remote_desc, &nch, 1) == 0)
469 || (ch == '\n' && nch == '\r')
470 || (ch == '\r' && nch == '\n'))
472 if (kiodebug & KD_MINUTAE)
473 fprintf (stderr, "Sent %c(%d) Received %c(%d)\n", ch, ch, nch, nch);
478 /* Send a packet to the remote machine, with error checking.
479 The data of the packet is in BUF. */
486 int cnt = strlen (buf);
489 if (kiodebug & KD_LINEDISCIPLINE)
490 fprintf(stderr, "putpkt(%s)\n", buf);
492 for (i = 0; i < cnt; i++)
493 putcharacter (buf[i]);
497 jmp_buf getline_jmpbuf;
499 /* Read a line from the remote machine, and store it in BUF. */
504 if (kiodebug & KD_RETRY)
505 fprintf(stderr, "getline timed out\n");
506 longjmp(getline_jmpbuf, 1);
510 getline (buf, size, timeout)
516 int isspace_state = 1;
518 if ((void (*)) signal (SIGALRM, getline_timer) == (void (*)) -1)
519 perror ("remote_open: error in signal");
521 --size; /* back it up one so that we can read */
525 if (setjmp(getline_jmpbuf))
532 char ch = readCharFromProm();
533 isspace_state = isspace_state && isspace(ch);
534 if (ch && (dontskipcrs || ch != '\r'))
539 if (kiodebug & KD_MINUTAE)
540 fprintf (stderr,"letter received :%c\n", buf[cnt - 1]);
541 if (cnt >= 2 && buf[cnt - 2] == 'o' && buf[cnt - 1] == 'k')
543 else if (buf[cnt - 1] == '\n' )
544 state = isspace_state ? GL_BLANKLINE : GL_SUCCESS;
545 else if (cnt == size)
547 else if (strstr(buf, "Type 'go' to resume"))
549 else if (strstr(buf, "Type help for more information"))
551 else if (strstr(buf, "Exception"))
552 state = GL_EXCEPTION;
554 while (state == GL_READING);
558 if (kiodebug & KD_LINEDISCIPLINE)
559 fprintf (stderr,"Line received :%s\n", buf);
564 /* Read a packet from the remote machine, and store it in BUF. */
574 char ch = readCharFromProm();
577 if (kiodebug & KD_MINUTAE)
578 fprintf (stderr,"letter received :%c\n", buf[cnt - 1]);
581 buf[cnt - 2] != 'o' &&
582 buf[cnt - 1] != 'k');
585 if (kiodebug& KD_LINEDISCIPLINE)
586 fprintf (stderr,"Packet received :%s\n", buf);
590 void remote_fetch_word (addr)
593 error ("Internal error: remote_fetch_word is obsolete.\n");
595 void remote_store_word (addr)
598 error ("Internal error: remote_store_word is obsolete.\n");
603 enum showDrainage showit;
605 unsigned char buf[PBUFSIZ];
608 while ((cnt = read(remote_desc, buf, PBUFSIZ)) > 0)
611 if (kiodebug& KD_LINEDISCIPLINE)
612 fprintf (stderr,"Draining :%s\n", buf);
615 fprintf (stderr,"%s", buf);
617 if (kiodebug& KD_LINEDISCIPLINE)
618 fprintf (stderr,"Drained\n");
622 if (kiodebug & KD_RETRY)
623 fprintf (stderr,"rgdb sending break to target...\n");
626 fprintf (stderr,"=");
630 ioctl (remote_desc, TCSBRK, 0);
635 /* shuffle a character from the user to remote debugger */
638 shuffleFromUserToProm()
641 static int escape = 0;
643 extern FILE *instream;
646 if (read(STDIN, &ch , 1) != 1 || ch == 0)
655 read(STDIN, &ch , 1);
659 static char tilde = '~';
665 } else /* not escape */ {
676 /* Tell the Prom put a breakpoint at memaddr */
677 remote_insert_breakpoint(memaddr)
682 /* Command describes registers byte by byte,
683 each byte encoded as two hex characters. */
685 sprintf(buf, "%x +bp", memaddr);
686 remote_send(buf, buf);
687 if (strstr(buf, "Exception"))
697 /* Tell the Prom remove the the breakpoint at memaddr */
698 remote_remove_breakpoint(memaddr)
703 /* Command describes registers byte by byte,
704 each byte encoded as two hex characters. */
706 sprintf(buf, "%x -bp", memaddr);
707 remote_send(buf, buf);
708 if (strstr(buf, "Exception"))
722 /* Read memory data directly from the remote machine.
723 This does not use the data cache; the data cache uses this.
724 MEMADDR is the address in the remote memory space.
725 MYADDR is the address of the buffer in our space.
726 LEN is the number of words. */
729 remote_read(memaddr, myaddr, len, increment, promcommand)
731 unsigned char *myaddr;
740 /* Command describes registers byte by byte,
741 each byte encoded as two hex characters. */
743 for (i = 0; i < len; i += increment)
745 sprintf(buf, promcommand, memaddr + i) ;
746 remote_send(buf, buf2);
747 remote_send(".", buf);
748 if (strstr(buf2, "Exception"))
750 bzero(&myaddr[i], len - i);
756 for (pBuf = &buf[0]; *pBuf == '\r' || *pBuf == '\n'; pBuf++)
758 sscanf(pBuf, "%x\n", &num);
761 case 1: myaddr[i] = num;
763 fprintf(stderr, "number out of bounds %x truncating to %x\n",
766 case 4: {unsigned long *p;
767 p = (unsigned long *) &myaddr[i];
771 default: fprintf(stderr, "unknown increment\n"); break;
780 /* Read LEN bytes from inferior memory at MEMADDR. Put the result
781 at debugger address MYADDR. Returns errno value. */
783 remote_read_inferior_memory(memaddr, myaddr, len)
793 if (len > MAXBUFBYTES)
794 xfersize = MAXBUFBYTES;
799 if (mod == 0 && xfersize >= 4)
800 if (mod == 0 && xfersize >= 16)
802 xfersize = remote_read_many(memaddr, myaddr, (len & ~3));
806 xfersize = remote_read(memaddr, myaddr, 4, 4, "%x @");
808 xfersize = remote_read(memaddr, myaddr, max(mod, 1), 1, "%x c@");
810 return EFAULT; /* error */
815 return 0; /* no error */
817 static int baud_rate=B38400;
819 static void set_term_raw(pTermio)
822 pTermio->c_cflag &= (CREAD|HUPCL|CLOCAL);
823 pTermio->c_cflag |= baud_rate | CS8;
824 pTermio->c_iflag = ISTRIP /* | IXON | IXOFF */;
825 pTermio->c_oflag = 0;
826 pTermio->c_lflag = 0;
827 pTermio->c_cc[VMIN] = 0;
828 pTermio->c_cc[VTIME] = 1;
831 /* setup the remote termio stream */
836 ioctl(remote_desc, TCGETS, &temptempio);
837 set_term_raw(&temptempio);
838 ioctl(remote_desc, TCSETS, &temptempio);
841 /* step one machine instruction */
842 remote_single_step ()
844 CORE_ADDR next_pc, npc4, target, pc;
847 Error, not_branch, bicc, bicca, ba, baa, ticc, ta,
849 branch_type br, isannulled();
851 npc4 = remote_next_pc + 4; /* branch not taken */
853 /* Always set breakpoint for NPC. */
855 remote_insert_breakpoint(remote_next_pc);
856 remove_thisbp_next_pc = remote_next_pc;
858 /* printf ("set break at %x\n",remote_next_pc); */
860 br = isannulled (remote_pc, &target);
864 /* Conditional annulled branch will either end up at
865 npc (if taken) or at npc+4 (if not taken).
867 remote_insert_breakpoint(npc4);
868 remove_thisbp_target = npc4;
870 else if (br == baa && target != remote_next_pc)
872 /* Unconditional annulled branch will always end up at
874 remote_insert_breakpoint(target);
875 remove_thisbp_target = target;
882 /* read many words of memory */
884 remote_read_many(memaddr, myaddr, len)
886 unsigned char *myaddr;
889 #define BLOCKSIZE 1024
890 static int max_number_of_blocks = 24;
896 /* Command describes registers byte by byte,
897 each byte encoded as two hex characters. */
899 len = min(len, max_number_of_blocks * BLOCKSIZE);
901 sprintf(buf, "%x %x do i @ . cr 4 +loop", memaddr + len, memaddr);
903 getline(buf2, PBUFSIZ, LONGTIMEOUT); /* I don't care */
905 p = (unsigned long *) myaddr;
906 for (i = 0; i < len; i += 4, p++)
908 extern int InspectIt;
910 if (!InspectIt && ((i % BLOCKSIZE) == 0))
911 fprintf(stderr, "+"); /* let 'em know that we are working */
912 switch (getline(buf2, PBUFSIZ, LONGTIMEOUT))
921 /* resync and retry */
922 max_number_of_blocks = max(1, i / BLOCKSIZE);
923 fprintf(stderr, "-"); /* let 'em know that we are working */
925 if (kiodebug & KD_BLOCKTRANSFER)
926 fprintf(stderr, "failed read_many %d %d/%d (%s)\n",
927 max_number_of_blocks, i, len, buf2);
929 return remote_read_many(memaddr, myaddr, len);
933 sscanf(buf2, "%x\n", p);
937 if (kiodebug & KD_BLOCKTRANSFER)
938 fprintf(stderr, "success read_many %d %d/%d (%s)\n", max_number_of_blocks,
943 * allow the user to type directly to the prom !
947 int readUser, readProm;
950 fprintf(stderr, "entering prom mode...\n");
953 doselect(&readUser, &readProm);
955 if (shuffleFromUserToProm())
957 fprintf(stderr, "exiting prom mode\n");
958 user_terminal_restore();
962 fprintf(stderr, "%c", readCharFromProm ());
965 static char *boot_set_msg = "boot needs a string in quotes of the form \"boot vmunix\" ";
966 static char *baud_set_msg = "baud rate should be of the form \"set baud=9600\"";
969 set_boot (arg, from_tty)
978 error_no_arg (boot_set_msg);
981 arg = tilde_expand (arg);
982 make_cleanup (free, arg);
984 i = strlen (arg) - 1;
989 while (*arg && h < i && (arg[h] == ' ' || arg[h] == '\t'))
994 while (i > 0 && (arg[i] == ' ' || arg[i] == '\t'))
997 if (h >= i || !*arg || arg[h] != '"' || arg[i] != '"')
998 error (boot_set_msg);
1001 boot_cmd = savestring (++arg, i);
1002 boot_cmd[i - 1] = '\0';
1008 static int bauds[] = {
1009 0, 50, 75, 110, 134, 150, 200, 300, 600,
1010 1200, 1800, 2400, 4800, 9600, 19200, 38400, -1
1014 static int convert_to_baud_B(n)
1019 for (p = bauds; *p != -1; p++)
1020 if (*p != 0 && *p == n)
1025 static void print_acceptable_bauds()
1029 for (p = bauds; *p != -1; p++)
1031 fprintf(stderr, "%d\n", *p);
1034 static void print_baud()
1036 fprintf(stderr, "the baud rate is now %d\n", bauds[baud_rate]);
1040 set_baud (arg, from_tty)
1049 print_acceptable_bauds();
1050 error_no_arg (baud_set_msg);
1054 while (*arg && !isdigit(*arg))
1057 if (*arg && (temp_baud_rate = convert_to_baud_B(atoi(arg))) != NULL)
1059 baud_rate = temp_baud_rate;
1060 if (remote_debugging)
1065 fprintf(stderr, "bad baud rate %s, acceptable values are\n", arg);
1066 print_acceptable_bauds();
1076 _initialize_remote()
1078 /* Chain containing all defined set subcommands */
1080 extern struct cmd_list_element *setlist;
1083 add_com ("prom", class_obscure, prom_command,
1084 "Conduct a dialogue directly with the prom. \
1085 only useful after an attach\n\
1086 Terminate by typing ~.");
1088 add_cmd ("boot_cmd", class_support, set_boot, boot_set_msg, &setlist);
1090 add_cmd ("baud", class_support, set_baud, baud_set_msg, &setlist);
1092 set_boot ("\"boot nucleus -d\"", 0);
1096 /* Store the remote registers from the contents of the block REGS. */
1099 remote_store_registers (registers)
1103 struct regs inferior_registers;
1105 core = parse_and_eval_address("breakpoint_regs");
1107 bcopy (®isters[REGISTER_BYTE (1)],
1108 &inferior_registers.r_g1, 15 * 4);
1110 inferior_registers.r_ps =
1111 *(int *)®isters[REGISTER_BYTE (PS_REGNUM)];
1112 inferior_registers.r_pc =
1113 *(int *)®isters[REGISTER_BYTE (PC_REGNUM)];
1114 inferior_registers.r_npc =
1115 *(int *)®isters[REGISTER_BYTE (NPC_REGNUM)];
1116 inferior_registers.r_y =
1117 *(int *)®isters[REGISTER_BYTE (Y_REGNUM)];
1119 remote_write_inferior_memory (*(int *)®isters[REGISTER_BYTE (SP_REGNUM)],
1120 ®isters[REGISTER_BYTE (16)],
1122 remote_write_inferior_memory (core,
1123 &inferior_registers,
1124 sizeof(inferior_registers));
1129 /* we have stopped. do some cleanup */
1130 remote_cleanup_after_stop()
1132 if (remove_thisbp_next_pc)
1134 remote_remove_breakpoint (remove_thisbp_next_pc);
1135 remove_thisbp_next_pc = 0;
1137 if (remove_thisbp_target)
1139 remote_remove_breakpoint (remove_thisbp_target);
1140 remove_thisbp_target = 0;
1142 user_terminal_restore();
1144 one_stepped = remote_set_one_stepped;