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.
22 #include <sys/types.h>
30 #define TERMINAL struct termios
33 #define SHORTTIMEOUT 1
36 #define KD_LINEDISCIPLINE 2
38 #define KD_BLOCKTRANSFER 8
44 #define GL_READING 0 /* get line is reading data */
45 #define GL_OK 1 /* Getline saw the "ok" string */
46 #define GL_SUCCESS 2 /* Get line got data */
47 #define GL_TIMEOUT 3 /* Get line timed out */
48 #define GL_OVERRUN 4 /* Get line filled up the buffer */
49 #define GL_EXCEPTION 5 /* Get line saw "Exception" */
50 #define GL_PROMLINE 6 /* Get line saw prom specific info */
51 #define GL_BLANKLINE 7 /* Get line saw a blank line */
53 static int kiodebug /* = KD_RETRY | KD_BLOCKTRANSFER */;
55 static CORE_ADDR remote_pc = 0;
56 static CORE_ADDR remote_next_pc = 0;
57 static CORE_ADDR remove_thisbp_next_pc = 0;
58 static CORE_ADDR remove_thisbp_target = 0;
60 enum showDrainage {DONTSHOW , SHOW} ;
63 /* Descriptor for I/O to remote machine. Initialize it to -1 so that
64 remote_open knows that we don't have a file open when the program
72 unsigned char ignorebuf[PBUFSIZ];
73 #define IGNORE &ignorebuf[0]
75 /* Maximum number of bytes to read/write at once. The value here
76 is chosen to fill up a packet (the headers account for the 32). */
77 #define MAXBUFBYTES ((PBUFSIZ-32)/2)
79 static void remote_send ();
80 static void putpkt ();
84 /* Open a connection to a remote debugger.
85 NAME is the filename used for communication. */
86 CORE_ADDR breakpoint_regs_addr;
90 remote_open (name, from_tty)
94 extern int frame_file_full_name;
95 unsigned char buf[PBUFSIZ];
100 if (remote_desc >= 0)
103 breakpoint_regs_addr = parse_and_eval_address("&breakpoint_regs");
105 dontskipcrs = !frame_file_full_name; /* if we are running inside of
106 emacs, this will be true.
107 then skip carriage returns */
109 remote_desc = open (name, O_RDWR);
111 perror_with_name (name);
116 printf ("Remote debugging using %s\n", name);
117 remote_debugging = 1;
121 static char *boot_cmd = 0;
123 static print_boot_cmd()
125 fprintf(stderr, "boot command set to be \"%s\"\n", boot_cmd);
130 WAITTYPE ignoredWaitType;
135 remote_wait (&ignoredWaitType);
139 remote_wait (&ignoredWaitType);
143 fprintf(stderr, "rgdb and nucleus synchronized, booting....\n");
147 error("The boot command is null. Cannot start the remote kernel/nucleus");
151 /* Close the open connection to the remote debugger.
152 Use this when you want to detach and do something else
155 remote_close (from_tty)
158 if (!remote_debugging)
159 error ("Can't close remote connection: not debugging remotely.");
161 close (remote_desc); /* This should never be called if
162 there isn't something valid in
165 /* Do not try to close remote_desc again, later in the program. */
169 printf ("Ending remote debugging\n");
171 remote_debugging = 0;
174 /* Convert hex digit A to a number. */
180 if (a >= '0' && a <= '9')
182 else if (a >= 'a' && a <= 'f')
185 error ("Reply contains invalid hex digit");
188 /* Convert number NIB to a hex digit. */
200 /* Tell the remote machine to resume. */
202 extern int one_stepped; /* From machine dependent code */
203 static int remote_set_one_stepped;
206 remote_resume (step, signal)
211 remote_single_step();
213 remote_set_one_stepped = step;
217 /* Wait until the remote machine stops, then return,
218 storing status in STATUS just as `wait' would. */
225 int pend, saveTheOh = 0;
229 WSETEXIT ((*status), 0177);
235 int readUser, readProm, state;
237 doselect(&readUser, &readProm);
240 switch (state = getline(buf, PBUFSIZ, SHORTTIMEOUT))
243 if (remote_set_one_stepped)
253 if (kiodebug & KD_LINEDISCIPLINE)
254 fprintf(stderr, "%d<%s>\n", state, buf);
257 fprintf(stderr, "%s", buf);
262 remote_cleanup_after_stop();
263 WSETSTOP ((*status), SIGTRAP);
270 shuffleFromUserToProm();
273 static TERMINAL userterminal;
275 user_terminal_restore()
278 int in_desc = fileno (stdin);
279 ioctl (in_desc, TCSETS, &userterminal);
282 static void set_term_raw();
287 TERMINAL tempterminal;
288 int in_desc = fileno (stdin);
289 ioctl (in_desc, TCGETS, &userterminal);
290 tempterminal = userterminal;
292 tempterminal.c_lflag &= ~(ICANON|ISIG|IEXTEN);
293 tempterminal.c_cc[VMIN] = 1;
294 tempterminal.c_cc[VTIME] = 0;
295 tempterminal.c_iflag &= ~(INPCK|IXON|IXOFF);
296 tempterminal.c_oflag = 0;
298 ioctl (in_desc, TCSETS, &tempterminal);
302 doselect(pReadUser, pReadProm)
303 int *pReadUser, *pReadProm;
305 extern FILE *instream;
306 int in_desc = fileno (stdin);
307 int instreammask = 1 << in_desc;
308 int remotemask = 1 << remote_desc;
309 int rfds = instreammask | remotemask;
311 select (32, &rfds, 0, 0, (struct timeval *) 0); /* 0 = Block indefinitely */
312 *pReadUser = (rfds & instreammask) == instreammask;
313 *pReadProm = (rfds & remotemask) == remotemask;
318 /* Read the remote registers into the block pRegisters.
319 implementation copied largely from fetch_inferior_registers ()
323 remote_fetch_registers(ignored)
326 struct regs inferior_registers;
327 extern char registers[];
328 CORE_ADDR breakpoint_regs_target;
330 if (breakpoint_regs_addr == 0)
332 error("no address for breakpoint_regs\n");
335 remote_read_inferior_memory(breakpoint_regs_addr, &breakpoint_regs_target,
336 sizeof(breakpoint_regs_target));
338 bzero(registers, REGISTER_BYTES);
339 registers[REGISTER_BYTE (0)] = 0;
341 if (breakpoint_regs_target)
343 remote_read_inferior_memory(breakpoint_regs_target, &inferior_registers,
344 sizeof(inferior_registers));
345 registers[REGISTER_BYTE (0)] = 0;
346 bcopy (&inferior_registers.r_g1, ®isters[REGISTER_BYTE (1)], 15 * 4);
347 *(int *)®isters[REGISTER_BYTE (PS_REGNUM)] = inferior_registers.r_ps;
348 *(int *)®isters[REGISTER_BYTE (PC_REGNUM)] = inferior_registers.r_pc;
349 *(int *)®isters[REGISTER_BYTE (NPC_REGNUM)] = inferior_registers.r_npc;
350 *(int *)®isters[REGISTER_BYTE (Y_REGNUM)] = inferior_registers.r_y;
351 remote_pc = inferior_registers.r_pc;
352 remote_next_pc = inferior_registers.r_npc;
353 remote_read_inferior_memory (inferior_registers.r_sp,
354 ®isters[REGISTER_BYTE (16)],
359 error("breakpoint_regs == 0\n");
366 /* Write memory data directly to the remote machine.
367 This does not inform the data cache; the data cache uses this.
368 MEMADDR is the address in the remote memory space.
369 MYADDR is the address of the buffer in our space.
370 LEN is the number of bytes. */
373 remote_write_bytes (memaddr, myaddr, len)
375 unsigned char *myaddr;
381 /* Command describes registers byte by byte,
382 each byte encoded as two hex characters. */
384 for (i = 0; i < len; i++)
386 sprintf(buf, "%x %x c!", myaddr[i], memaddr + i);
387 remote_send (buf, buf);
388 if (strstr(buf, "Exception"))
396 /* Copy LEN bytes of data from debugger memory at MYADDR
397 to inferior's memory at MEMADDR. Returns errno value. */
399 remote_write_inferior_memory (memaddr, myaddr, len)
409 if (len > MAXBUFBYTES)
410 xfersize = MAXBUFBYTES;
414 retval = remote_write_bytes(memaddr, myaddr, xfersize);
416 return retval; /* error */
422 return 0; /* no error */
426 /* read a single character */
434 /* termio does the timeout for us. */
435 read (remote_desc, &buf, 1);
439 /* Send the command in BUF to the remote machine,
440 and read the reply into BUF.
441 Report an error if we get an error reply. */
444 remote_send (buf, buf2)
451 /* Send a single character out over the wire */
462 write(remote_desc, &ch, 1);
463 for (i = 0; i < 100; i++)
467 if (read (remote_desc, &nch, 1) == 0)
470 || (ch == '\n' && nch == '\r')
471 || (ch == '\r' && nch == '\n'))
473 if (kiodebug & KD_MINUTAE)
474 fprintf (stderr, "Sent %c(%d) Received %c(%d)\n", ch, ch, nch, nch);
479 /* Send a packet to the remote machine, with error checking.
480 The data of the packet is in BUF. */
487 int cnt = strlen (buf);
490 if (kiodebug & KD_LINEDISCIPLINE)
491 fprintf(stderr, "putpkt(%s)\n", buf);
493 for (i = 0; i < cnt; i++)
494 putcharacter (buf[i]);
498 jmp_buf getline_jmpbuf;
500 /* Read a line from the remote machine, and store it in BUF. */
505 if (kiodebug & KD_RETRY)
506 fprintf(stderr, "getline timed out\n");
507 longjmp(getline_jmpbuf, 1);
511 getline (buf, size, timeout)
517 int isspace_state = 1;
519 if ((void (*)) signal (SIGALRM, getline_timer) == (void (*)) -1)
520 perror ("remote_open: error in signal");
522 --size; /* back it up one so that we can read */
526 if (setjmp(getline_jmpbuf))
533 char ch = readCharFromProm();
534 isspace_state = isspace_state && isspace(ch);
535 if (ch && (dontskipcrs || ch != '\r'))
540 if (kiodebug & KD_MINUTAE)
541 fprintf (stderr,"letter received :%c\n", buf[cnt - 1]);
542 if (cnt >= 2 && buf[cnt - 2] == 'o' && buf[cnt - 1] == 'k')
544 else if (buf[cnt - 1] == '\n' )
545 state = isspace_state ? GL_BLANKLINE : GL_SUCCESS;
546 else if (cnt == size)
548 else if (strstr(buf, "Type 'go' to resume"))
550 else if (strstr(buf, "Type help for more information"))
552 else if (strstr(buf, "Exception"))
553 state = GL_EXCEPTION;
555 while (state == GL_READING);
559 if (kiodebug & KD_LINEDISCIPLINE)
560 fprintf (stderr,"Line received :%s\n", buf);
565 /* Read a packet from the remote machine, and store it in BUF. */
575 char ch = readCharFromProm();
578 if (kiodebug & KD_MINUTAE)
579 fprintf (stderr,"letter received :%c\n", buf[cnt - 1]);
582 buf[cnt - 2] != 'o' &&
583 buf[cnt - 1] != 'k');
586 if (kiodebug& KD_LINEDISCIPLINE)
587 fprintf (stderr,"Packet received :%s\n", buf);
591 void remote_fetch_word (addr)
594 error ("Internal error: remote_fetch_word is obsolete.\n");
596 void remote_store_word (addr)
599 error ("Internal error: remote_store_word is obsolete.\n");
604 enum showDrainage showit;
606 unsigned char buf[PBUFSIZ];
609 while ((cnt = read(remote_desc, buf, PBUFSIZ)) > 0)
612 if (kiodebug& KD_LINEDISCIPLINE)
613 fprintf (stderr,"Draining :%s\n", buf);
616 fprintf (stderr,"%s", buf);
618 if (kiodebug& KD_LINEDISCIPLINE)
619 fprintf (stderr,"Drained\n");
623 if (kiodebug & KD_RETRY)
624 fprintf (stderr,"rgdb sending break to target...\n");
627 fprintf (stderr,"=");
631 ioctl (remote_desc, TCSBRK, 0);
636 /* shuffle a character from the user to remote debugger */
639 shuffleFromUserToProm()
642 static int escape = 0;
644 extern FILE *instream;
647 if (read(STDIN, &ch , 1) != 1 || ch == 0)
656 read(STDIN, &ch , 1);
660 static char tilde = '~';
666 } else /* not escape */ {
677 /* Tell the Prom put a breakpoint at memaddr */
678 remote_insert_breakpoint(memaddr)
683 /* Command describes registers byte by byte,
684 each byte encoded as two hex characters. */
686 sprintf(buf, "%x +bp", memaddr);
687 remote_send(buf, buf);
688 if (strstr(buf, "Exception"))
698 /* Tell the Prom remove the the breakpoint at memaddr */
699 remote_remove_breakpoint(memaddr)
704 /* Command describes registers byte by byte,
705 each byte encoded as two hex characters. */
707 sprintf(buf, "%x -bp", memaddr);
708 remote_send(buf, buf);
709 if (strstr(buf, "Exception"))
723 /* Read memory data directly from the remote machine.
724 This does not use the data cache; the data cache uses this.
725 MEMADDR is the address in the remote memory space.
726 MYADDR is the address of the buffer in our space.
727 LEN is the number of words. */
730 remote_read(memaddr, myaddr, len, increment, promcommand)
732 unsigned char *myaddr;
741 /* Command describes registers byte by byte,
742 each byte encoded as two hex characters. */
744 for (i = 0; i < len; i += increment)
746 sprintf(buf, promcommand, memaddr + i) ;
747 remote_send(buf, buf2);
748 remote_send(".", buf);
749 if (strstr(buf2, "Exception"))
751 bzero(&myaddr[i], len - i);
757 for (pBuf = &buf[0]; *pBuf == '\r' || *pBuf == '\n'; pBuf++)
759 sscanf(pBuf, "%x\n", &num);
762 case 1: myaddr[i] = num;
764 fprintf(stderr, "number out of bounds %x truncating to %x\n",
767 case 4: {unsigned long *p;
768 p = (unsigned long *) &myaddr[i];
772 default: fprintf(stderr, "unknown increment\n"); break;
781 /* Read LEN bytes from inferior memory at MEMADDR. Put the result
782 at debugger address MYADDR. Returns errno value. */
784 remote_read_inferior_memory(memaddr, myaddr, len)
794 if (len > MAXBUFBYTES)
795 xfersize = MAXBUFBYTES;
800 if (mod == 0 && xfersize >= 4)
801 if (mod == 0 && xfersize >= 16)
803 xfersize = remote_read_many(memaddr, myaddr, (len & ~3));
807 xfersize = remote_read(memaddr, myaddr, 4, 4, "%x @");
809 xfersize = remote_read(memaddr, myaddr, max(mod, 1), 1, "%x c@");
811 return EFAULT; /* error */
816 return 0; /* no error */
818 static int baud_rate=B38400;
820 static void set_term_raw(pTermio)
823 pTermio->c_cflag &= (CREAD|HUPCL|CLOCAL);
824 pTermio->c_cflag |= baud_rate | CS8;
825 pTermio->c_iflag = ISTRIP /* | IXON | IXOFF */;
826 pTermio->c_oflag = 0;
827 pTermio->c_lflag = 0;
828 pTermio->c_cc[VMIN] = 0;
829 pTermio->c_cc[VTIME] = 1;
832 /* setup the remote termio stream */
837 ioctl(remote_desc, TCGETS, &temptempio);
838 set_term_raw(&temptempio);
839 ioctl(remote_desc, TCSETS, &temptempio);
842 /* step one machine instruction */
843 remote_single_step ()
845 CORE_ADDR next_pc, npc4, target, pc;
848 Error, not_branch, bicc, bicca, ba, baa, ticc, ta,
850 branch_type br, isannulled();
852 npc4 = remote_next_pc + 4; /* branch not taken */
854 /* Always set breakpoint for NPC. */
856 remote_insert_breakpoint(remote_next_pc);
857 remove_thisbp_next_pc = remote_next_pc;
859 /* printf ("set break at %x\n",remote_next_pc); */
861 br = isannulled (remote_pc, &target);
865 /* Conditional annulled branch will either end up at
866 npc (if taken) or at npc+4 (if not taken).
868 remote_insert_breakpoint(npc4);
869 remove_thisbp_target = npc4;
871 else if (br == baa && target != remote_next_pc)
873 /* Unconditional annulled branch will always end up at
875 remote_insert_breakpoint(target);
876 remove_thisbp_target = target;
883 /* read many words of memory */
885 remote_read_many(memaddr, myaddr, len)
887 unsigned char *myaddr;
890 #define BLOCKSIZE 1024
891 static int max_number_of_blocks = 24;
897 /* Command describes registers byte by byte,
898 each byte encoded as two hex characters. */
900 len = min(len, max_number_of_blocks * BLOCKSIZE);
902 sprintf(buf, "%x %x do i @ . cr 4 +loop", memaddr + len, memaddr);
904 getline(buf2, PBUFSIZ, LONGTIMEOUT); /* I don't care */
906 p = (unsigned long *) myaddr;
907 for (i = 0; i < len; i += 4, p++)
909 extern int InspectIt;
911 if (!InspectIt && ((i % BLOCKSIZE) == 0))
912 fprintf(stderr, "+"); /* let 'em know that we are working */
913 switch (getline(buf2, PBUFSIZ, LONGTIMEOUT))
922 /* resync and retry */
923 max_number_of_blocks = max(1, i / BLOCKSIZE);
924 fprintf(stderr, "-"); /* let 'em know that we are working */
926 if (kiodebug & KD_BLOCKTRANSFER)
927 fprintf(stderr, "failed read_many %d %d/%d (%s)\n",
928 max_number_of_blocks, i, len, buf2);
930 return remote_read_many(memaddr, myaddr, len);
934 sscanf(buf2, "%x\n", p);
938 if (kiodebug & KD_BLOCKTRANSFER)
939 fprintf(stderr, "success read_many %d %d/%d (%s)\n", max_number_of_blocks,
944 * allow the user to type directly to the prom !
948 int readUser, readProm;
951 fprintf(stderr, "entering prom mode...\n");
954 doselect(&readUser, &readProm);
956 if (shuffleFromUserToProm())
958 fprintf(stderr, "exiting prom mode\n");
959 user_terminal_restore();
963 fprintf(stderr, "%c", readCharFromProm ());
966 static char *boot_set_msg = "boot needs a string in quotes of the form \"boot vmunix\" ";
967 static char *baud_set_msg = "baud rate should be of the form \"set baud=9600\"";
970 set_boot (arg, from_tty)
979 error_no_arg (boot_set_msg);
982 arg = tilde_expand (arg);
983 make_cleanup (free, arg);
985 i = strlen (arg) - 1;
990 while (*arg && h < i && (arg[h] == ' ' || arg[h] == '\t'))
995 while (i > 0 && (arg[i] == ' ' || arg[i] == '\t'))
998 if (h >= i || !*arg || arg[h] != '"' || arg[i] != '"')
999 error (boot_set_msg);
1002 boot_cmd = savestring (++arg, i);
1003 boot_cmd[i - 1] = '\0';
1009 static int bauds[] = {
1010 0, 50, 75, 110, 134, 150, 200, 300, 600,
1011 1200, 1800, 2400, 4800, 9600, 19200, 38400, -1
1015 static int convert_to_baud_B(n)
1020 for (p = bauds; *p != -1; p++)
1021 if (*p != 0 && *p == n)
1026 static void print_acceptable_bauds()
1030 for (p = bauds; *p != -1; p++)
1032 fprintf(stderr, "%d\n", *p);
1035 static void print_baud()
1037 fprintf(stderr, "the baud rate is now %d\n", bauds[baud_rate]);
1041 set_baud (arg, from_tty)
1050 print_acceptable_bauds();
1051 error_no_arg (baud_set_msg);
1055 while (*arg && !isdigit(*arg))
1058 if (*arg && (temp_baud_rate = convert_to_baud_B(atoi(arg))) != NULL)
1060 baud_rate = temp_baud_rate;
1061 if (remote_debugging)
1066 fprintf(stderr, "bad baud rate %s, acceptable values are\n", arg);
1067 print_acceptable_bauds();
1077 _initialize_remote()
1079 /* Chain containing all defined set subcommands */
1081 extern struct cmd_list_element *setlist;
1084 add_com ("prom", class_obscure, prom_command,
1085 "Conduct a dialogue directly with the prom. \
1086 only useful after an attach\n\
1087 Terminate by typing ~.");
1089 add_cmd ("boot_cmd", class_support, set_boot, boot_set_msg, &setlist);
1091 add_cmd ("baud", class_support, set_baud, baud_set_msg, &setlist);
1093 set_boot ("\"boot nucleus -d\"", 0);
1097 /* Store the remote registers from the contents of the block REGS. */
1100 remote_store_registers (registers)
1104 struct regs inferior_registers;
1106 core = parse_and_eval_address("breakpoint_regs");
1108 bcopy (®isters[REGISTER_BYTE (1)],
1109 &inferior_registers.r_g1, 15 * 4);
1111 inferior_registers.r_ps =
1112 *(int *)®isters[REGISTER_BYTE (PS_REGNUM)];
1113 inferior_registers.r_pc =
1114 *(int *)®isters[REGISTER_BYTE (PC_REGNUM)];
1115 inferior_registers.r_npc =
1116 *(int *)®isters[REGISTER_BYTE (NPC_REGNUM)];
1117 inferior_registers.r_y =
1118 *(int *)®isters[REGISTER_BYTE (Y_REGNUM)];
1120 remote_write_inferior_memory (*(int *)®isters[REGISTER_BYTE (SP_REGNUM)],
1121 ®isters[REGISTER_BYTE (16)],
1123 remote_write_inferior_memory (core,
1124 &inferior_registers,
1125 sizeof(inferior_registers));
1130 /* we have stopped. do some cleanup */
1131 remote_cleanup_after_stop()
1133 if (remove_thisbp_next_pc)
1135 remote_remove_breakpoint (remove_thisbp_next_pc);
1136 remove_thisbp_next_pc = 0;
1138 if (remove_thisbp_target)
1140 remote_remove_breakpoint (remove_thisbp_target);
1141 remove_thisbp_target = 0;
1143 user_terminal_restore();
1145 one_stepped = remote_set_one_stepped;