* objdump.c (usage): Mention --stabs.
[deliverable/binutils-gdb.git] / gdb / remote-mon.c
CommitLineData
c033ec17
JK
1/* Remote debugging interface for MONITOR boot monitor, for GDB.
2 Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
3 Contributed by Cygnus Support. Written by Rob Savoye for Cygnus.
4
5This file is part of GDB.
6
7This program is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2 of the License, or
10(at your option) any later version.
11
12This program is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with this program; if not, write to the Free Software
19Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
20
21/* This file was derived from remote-eb.c, which did a similar job, but for
22 an AMD-29K running EBMON. That file was in turn derived from remote.c
23 as mentioned in the following comment (left in for comic relief):
24
25 "This is like remote.c but is for an esoteric situation--
26 having an a29k board in a PC hooked up to a unix machine with
27 a serial line, and running ctty com1 on the PC, through which
28 the unix machine can run ebmon. Not to mention that the PC
29 has PC/NFS, so it can access the same executables that gdb can,
30 over the net in real time."
31
32 In reality, this module talks to a debug monitor called 'MONITOR', which
33 We communicate with MONITOR via either a direct serial line, or a TCP
34 (or possibly TELNET) stream to a terminal multiplexor,
35 which in turn talks to the target board.
36
37 This is based on remote-st2000.c. I left in the above note here for histerical
38 reasons.
39*/
40
41#include "defs.h"
42#include "gdbcore.h"
43#include "target.h"
44#include "wait.h"
45#include <varargs.h>
46#include <signal.h>
47#include <string.h>
48#include <sys/types.h>
49#include "command.h"
50#include "serial.h"
51#include "monitor.h"
a94abe5b 52#include "remote-utils.h"
c033ec17
JK
53
54#ifdef HAVE_TERMIO
55# define TERMINAL struct termios
56#else
57# define TERMINAL struct sgttyb
58#endif
59
60struct monitor_ops *current_monitor;
61extern struct target_ops rom68k_ops; /* Forward declaration */
62extern struct target_ops mon68_ops; /* Forward declaration */
63extern struct target_ops monitor_bug_ops; /* Forward declaration */
64extern struct monitor_ops rom68k_cmds; /* Forward declaration */
65extern struct monitor_ops mon68_cmds; /* Forward declaration */
66extern struct monitor_ops bug_cmds; /* Forward declaration */
67extern struct cmd_list_element *setlist;
68extern struct cmd_list_element *unsetlist;
69struct cmd_list_element *showlist;
70
71static void monitor_close();
72static void monitor_fetch_register();
73static void monitor_store_register();
74static int kiodebug; /* flag set by "set remotedebug" */
75static int hashmark; /* flag set by "set hash" */
76
77#define LOG_FILE "monitor.log"
78#if defined (LOG_FILE)
79FILE *log_file;
80#endif
81
82static int timeout = 24;
83
84/* Descriptor for I/O to remote machine. Initialize it to NULL so that
85 monitor_open knows that we don't have a file open when the program starts.
86 */
87static serial_t monitor_desc = NULL;
88
89/* Send data to monitor. Works just like printf. */
90
91static void
92printf_monitor(va_alist)
93 va_dcl
94{
95 va_list args;
96 char *pattern;
97 char buf[200];
98 int i;
99
100 va_start(args);
101
102 pattern = va_arg(args, char *);
103
104 vsprintf(buf, pattern, args);
105
106 if (SERIAL_WRITE(monitor_desc, buf, strlen(buf)))
107 fprintf(stderr, "SERIAL_WRITE failed: %s\n", safe_strerror(errno));
108}
109
110/* Read a character from the remote system, doing all the fancy
111 timeout stuff. */
112static int
113readchar(timeout)
114 int timeout;
115{
116 int c;
117
118 c = SERIAL_READCHAR(monitor_desc, timeout);
119
120 if (kiodebug)
121 putchar(c & 0x7f);
122
123#ifdef LOG_FILE
124 if (isascii (c))
125 putc(c & 0x7f, log_file);
126#endif
127
128 if (c >= 0)
129 return c & 0x7f;
130
131 if (c == SERIAL_TIMEOUT)
132 {
133 if (timeout == 0)
134 return c; /* Polls shouldn't generate timeout errors */
135
136 error("Timeout reading from remote system.");
137 }
138
139 perror_with_name("remote-monitor");
140}
141
142/* Scan input from the remote system, until STRING is found. If DISCARD is
143 non-zero, then discard non-matching input, else print it out.
144 Let the user break out immediately. */
145static void
146expect(string, discard)
147 char *string;
148 int discard;
149{
150 char *p = string;
151 int c;
152
153 if (kiodebug)
154 printf ("Expecting \"%s\"\n", string);
155
156 immediate_quit = 1;
157 while (1)
158 {
159 c = readchar(timeout);
160 if (!isascii (c))
161 continue;
162 if (c == *p++)
163 {
164 if (*p == '\0')
165 {
166 immediate_quit = 0;
167 if (kiodebug)
168 printf ("\nMatched\n");
169 return;
170 }
171 }
172 else
173 {
174 if (!discard)
175 {
176 fwrite(string, 1, (p - 1) - string, stdout);
177 putchar((char)c);
178 fflush(stdout);
179 }
180 p = string;
181 }
182 }
183}
184
185/* Keep discarding input until we see the MONITOR prompt.
186
187 The convention for dealing with the prompt is that you
188 o give your command
189 o *then* wait for the prompt.
190
191 Thus the last thing that a procedure does with the serial line
192 will be an expect_prompt(). Exception: monitor_resume does not
193 wait for the prompt, because the terminal is being handed over
194 to the inferior. However, the next thing which happens after that
195 is a monitor_wait which does wait for the prompt.
196 Note that this includes abnormal exit, e.g. error(). This is
197 necessary to prevent getting into states from which we can't
198 recover. */
199static void
200expect_prompt(discard)
201 int discard;
202{
203#if defined (LOG_FILE)
204 /* This is a convenient place to do this. The idea is to do it often
205 enough that we never lose much data if we terminate abnormally. */
206 fflush(log_file);
207#endif
208 expect (PROMPT, discard);
209}
210
211/* Get a hex digit from the remote system & return its value.
212 If ignore_space is nonzero, ignore spaces (not newline, tab, etc). */
213static int
214get_hex_digit(ignore_space)
215 int ignore_space;
216{
217 int ch;
218 while (1)
219 {
220 ch = readchar(timeout);
221 if (ch >= '0' && ch <= '9')
222 return ch - '0';
223 else if (ch >= 'A' && ch <= 'F')
224 return ch - 'A' + 10;
225 else if (ch >= 'a' && ch <= 'f')
226 return ch - 'a' + 10;
227 else if (ch == ' ' && ignore_space)
228 ;
229 else
230 {
231 expect_prompt(1);
232 error("Invalid hex digit from remote system.");
233 }
234 }
235}
236
237/* Get a byte from monitor and put it in *BYT. Accept any number
238 leading spaces. */
239static void
240get_hex_byte (byt)
241 char *byt;
242{
243 int val;
244
245 val = get_hex_digit (1) << 4;
246 val |= get_hex_digit (0);
247 *byt = val;
248}
249
250/* Get N 32-bit words from remote, each preceded by a space,
251 and put them in registers starting at REGNO. */
252static void
253get_hex_regs (n, regno)
254 int n;
255 int regno;
256{
257 long val;
258 int i;
259
260 for (i = 0; i < n; i++)
261 {
262 int j;
263
264 val = 0;
265 for (j = 0; j < 8; j++)
266 val = (val << 4) + get_hex_digit (j == 0);
267 supply_register (regno++, (char *) &val);
268 }
269}
270
271/* This is called not only when we first attach, but also when the
272 user types "run" after having attached. */
273static void
274monitor_create_inferior (execfile, args, env)
275 char *execfile;
276 char *args;
277 char **env;
278{
279 int entry_pt;
280
281 if (args && *args)
282 error("Can't pass arguments to remote MONITOR process");
283
284 if (execfile == 0 || exec_bfd == 0)
285 error("No exec file specified");
286
287 entry_pt = (int) bfd_get_start_address (exec_bfd);
288
289#ifdef CREATE_INFERIOR_HOOK
290 CREATE_INFERIOR_HOOK (0); /* No process-ID */
291#endif
292#ifdef LOG_FILE
293 fputs ("\nIn Create_inferior()", log_file);
294#endif
295
296/* The "process" (board) is already stopped awaiting our commands, and
297 the program is already downloaded. We just set its PC and go. */
298
299 clear_proceed_status ();
300
301 /* Tell wait_for_inferior that we've started a new process. */
302 init_wait_for_inferior ();
303
304 /* Set up the "saved terminal modes" of the inferior
305 based on what modes we are starting it with. */
306 target_terminal_init ();
307
308 /* Install inferior's terminal modes. */
309 target_terminal_inferior ();
310
311 /* insert_step_breakpoint (); FIXME, do we need this? */
312 proceed ((CORE_ADDR)entry_pt, -1, 0); /* Let 'er rip... */
313}
314
315/* Open a connection to a remote debugger.
316 NAME is the filename used for communication. */
317
318static int baudrate = 9600;
319static char dev_name[100];
320
321static void
322general_open(args, name, from_tty)
323 char *args;
324 char *name;
325 int from_tty;
326{
327 if (args == NULL)
328 error ("Use `target %s DEVICE-NAME' to use a serial port, or \n\
329`target %s HOST-NAME:PORT-NUMBER' to use a network connection.", name, name);
330
331 target_preopen(from_tty);
332
333 monitor_close(0);
334
335 monitor_desc = SERIAL_OPEN(dev_name);
336
337 if (monitor_desc == NULL)
338 perror_with_name(dev_name);
339
340 /* The baud rate was specified when GDB was started. */
a94abe5b 341 if (SERIAL_SETBAUDRATE (monitor_desc, sr_get_baud_rate()))
c033ec17 342 {
a94abe5b
RP
343 SERIAL_CLOSE (monitor_desc);
344 perror_with_name (name);
c033ec17
JK
345 }
346
347 SERIAL_RAW(monitor_desc);
348
349#if defined (LOG_FILE)
350 log_file = fopen (LOG_FILE, "w");
351 if (log_file == NULL)
352 perror_with_name (LOG_FILE);
353#endif
354
355 /* Hello? Are you there? */
356 printf_monitor("\r"); /* CR wakes up monitor */
357
358 expect_prompt(1);
359
360 if (from_tty)
361 printf("Remote %s connected to %s\n", target_shortname,
362 dev_name);
363}
364
365static void
366rom68k_open(args, from_tty)
367 char *args;
368 int from_tty;
369{
370 push_target(&rom68k_ops);
371 push_monitor (&rom68k_cmds);
372
373 general_open (args, "rom68k", from_tty);
374}
375
376static void
377mon68_open(args, from_tty)
378 char *args;
379 int from_tty;
380{
381 push_target(&mon68_ops);
382 push_monitor (&mon68_cmds);
383
384 general_open (args, "mon68", from_tty);
385}
386
387static void
388bug_open(args, from_tty)
389 char *args;
390 int from_tty;
391{
392 push_target(&monitor_bug_ops);
393 push_monitor (&bug_cmds);
394
395 general_open (args, "bug", from_tty);
396}
397
398/*
399 * _close -- Close out all files and local state before this target loses control.
400 */
401
402static void
403monitor_close (quitting)
404 int quitting;
405{
406 SERIAL_CLOSE(monitor_desc);
407 monitor_desc = NULL;
408
409#if defined (LOG_FILE)
410 if (log_file) {
411 if (ferror(log_file))
412 fprintf(stderr, "Error writing log file.\n");
413 if (fclose(log_file) != 0)
414 fprintf(stderr, "Error closing log file.\n");
415 }
416#endif
417}
418
419/* Terminate the open connection to the remote debugger.
420 Use this when you want to detach and do something else
421 with your gdb. */
422static void
423monitor_detach (from_tty)
424 int from_tty;
425{
426 pop_target(); /* calls monitor_close to do the real work */
427 if (from_tty)
428 printf ("Ending remote %s debugging\n", target_shortname);
429}
430
431/*
432 * _resume -- Tell the remote machine to resume.
433 */
434static void
435monitor_resume (pid, step, sig)
436 int pid, step, sig;
437{
438#ifdef LOG_FILE
439 fprintf (log_file, "\nIn Resume (step=%d, sig=%d)\n", step, sig);
440#endif
441
442 if (step)
443 {
444 printf_monitor (STEP_CMD);
445 /* wait for the echo. */
446 expect (STEP_CMD, 1);
447 }
448 else
449 {
450 printf_monitor (GO_CMD);
451 /* swallow the echo. */
452 expect (GO_CMD, 1);
453 }
454}
455
456/*
457 * _wait -- Wait until the remote machine stops, then return,
458 * storing status in status just as `wait' would.
459 */
460
461static int
462monitor_wait (status)
463 WAITTYPE *status;
464{
465 int old_timeout = timeout;
466#ifdef LOG_FILE
467 fputs ("\nIn wait ()", log_file);
468#endif
469
470 WSETEXIT ((*status), 0);
471
472 timeout = 0; /* Don't time out -- user program is running. */
473
474 expect_prompt(0); /* Wait for prompt, outputting extraneous text */
475
476 WSETSTOP ((*status), SIGTRAP);
477
478 timeout = old_timeout;
479
480 return 0;
481}
482
483/* Return the name of register number regno in the form input and output by
484 monitor. Currently, register_names just happens to contain exactly what
485 monitor wants. Lets take advantage of that just as long as possible! */
486
487static char *
488get_reg_name (regno)
489 int regno;
490{
491 static char buf[50];
492 const char *p;
493 char *b;
494
495 b = buf;
496
497 if (regno < 0)
498 return ("");
499 for (p = reg_names[regno]; *p; p++)
500 *b++ = toupper(*p);
501 *b = '\000';
502
503 return buf;
504}
505
506/* read the remote registers into the block regs. */
507
508static void
509monitor_fetch_registers ()
510{
511 int regno;
512
513 /* yeah yeah, i know this is horribly inefficient. but it isn't done
514 very often... i'll clean it up later. */
515
516 for (regno = 0; regno <= PC_REGNUM; regno++)
517 monitor_fetch_register(regno);
518}
519
520/* Fetch register REGNO, or all registers if REGNO is -1.
521 Returns errno value. */
522static void
523monitor_fetch_register (regno)
524 int regno;
525{
526 int val, j;
527
528#ifdef LOG_FILE
529 fprintf (log_file, "\nIn Fetch Register (reg=%s)\n", get_reg_name (regno));
530 fflush (log_file);
531#endif
532
533 if (regno < 0)
534 {
535 monitor_fetch_registers ();
536 }
537 else
538 {
539 char *name = get_reg_name (regno);
540 printf_monitor (GET_REG, name);
541 expect (name, 1);
542 expect (REG_DELIM, 1);
543 if (strcasecmp (name, "SR") == 0)
544 {
545 val = 0;
546 for (j = 0; j < 4; j++)
547 val = (val << 4) + get_hex_digit (j == 0);
548 supply_register (regno, (char *) &val);
549 }
550 else
551 {
552 get_hex_regs (1, regno);
553 }
554 if (CMD_END)
555 {
556 expect (CMD_DELIM);
557 printf_monitor (CMD_END);
558 }
559 expect_prompt (1);
560 }
561 return;
562}
563
564/* Store the remote registers from the contents of the block REGS. */
565
566static void
567monitor_store_registers ()
568{
569 int regno;
570
571 for (regno = 0; regno <= PC_REGNUM; regno++)
572 monitor_store_register(regno);
573
574 registers_changed ();
575}
576
577/* Store register REGNO, or all if REGNO == 0.
578 return errno value. */
579static void
580monitor_store_register (regno)
581 int regno;
582{
583#ifdef LOG_FILE
584 fprintf (log_file, "\nIn Store_register (regno=%d)\n", regno);
585#endif
586 if (regno == -1)
587 monitor_store_registers ();
588 else
589 {
590 if (kiodebug)
591 printf ("Setting register %s to 0x%x\n", get_reg_name (regno), read_register (regno));
592
593 printf_monitor (SET_REG, get_reg_name (regno),
594 read_register (regno));
595
596 expect_prompt (1);
597 }
598}
599
600/* Get ready to modify the registers array. On machines which store
601 individual registers, this doesn't need to do anything. On machines
602 which store all the registers in one fell swoop, this makes sure
603 that registers contains all the registers from the program being
604 debugged. */
605
606static void
607monitor_prepare_to_store ()
608{
609 /* Do nothing, since we can store individual regs */
610}
611
612static void
613monitor_files_info ()
614{
615 printf ("\tAttached to %s at %d baud.\n",
616 dev_name, baudrate);
617}
618
619/* Copy LEN bytes of data from debugger memory at MYADDR
620 to inferior's memory at MEMADDR. Returns length moved. */
621static int
622monitor_write_inferior_memory (memaddr, myaddr, len)
623 CORE_ADDR memaddr;
624 unsigned char *myaddr;
625 int len;
626{
627 int i;
628 char buf[10];
629
630#ifdef LOG_FILE
631 fprintf (log_file, "\nIn Write_inferior_memory (memaddr=%x, len=%d)\n", memaddr, len);
632#endif
633 for (i = 0; i < len; i++)
634 {
635 printf_monitor (MEM_SET_CMD, memaddr + i);
636 expect (sprintf (buf, MEM_PROMPT, memaddr + i), 1);
637 expect (CMD_DELIM);
638 printf_monitor ("%x", myaddr[i]);
639 if (kiodebug)
640 printf ("\nSet 0x%x to 0x%x\n", memaddr + i, myaddr[i]);
641 if (CMD_END)
642 {
643/*** expect (sprintf (buf, MEM_PROMPT, memaddr + i +1), 1);
644 expect (CMD_DELIM); ***/
645 printf_monitor (CMD_END);
646 }
647 expect_prompt (1);
648 }
649 return len;
650}
651
652/* Read LEN bytes from inferior memory at MEMADDR. Put the result
653 at debugger address MYADDR. Returns length moved. */
654static int
655monitor_read_inferior_memory(memaddr, myaddr, len)
656 CORE_ADDR memaddr;
657 char *myaddr;
658 int len;
659{
660 int i, j;
661 char buf[20];
662
663 /* Number of bytes read so far. */
664 int count;
665
666 /* Starting address of this pass. */
667 unsigned long startaddr;
668
669 /* Number of bytes to read in this pass. */
670 int len_this_pass;
671
672#ifdef LOG_FILE
673 fprintf (log_file, "\nIn Read_inferior_memory (memaddr=%x, len=%d)\n", memaddr, len);
674#endif
675
676 /* Note that this code works correctly if startaddr is just less
677 than UINT_MAX (well, really CORE_ADDR_MAX if there was such a
678 thing). That is, something like
679 monitor_read_bytes (CORE_ADDR_MAX - 4, foo, 4)
680 works--it never adds len To memaddr and gets 0. */
681 /* However, something like
682 monitor_read_bytes (CORE_ADDR_MAX - 3, foo, 4)
683 doesn't need to work. Detect it and give up if there's an attempt
684 to do that. */
685 if (((memaddr - 1) + len) < memaddr) {
686 errno = EIO;
687 return 0;
688 }
689
690 startaddr = memaddr;
691 count = 0;
692 while (count < len)
693 {
694 len_this_pass = 16;
695 if ((startaddr % 16) != 0)
696 len_this_pass -= startaddr % 16;
697 if (len_this_pass > (len - count))
698 len_this_pass = (len - count);
699 if (kiodebug)
700 printf ("\nDisplay %d bytes at %x\n", len_this_pass, startaddr);
701
702 for (i = 0; i < len_this_pass; i++)
703 {
704 printf_monitor (MEM_DIS_CMD, startaddr);
705 expect (sprintf(buf, MEM_PROMPT, startaddr), 1);
706 get_hex_byte (&myaddr[count++]);
707 if (kiodebug)
708 printf ("\nRead a 0x%x from 0x%x\n", myaddr[count-1], startaddr);
709 if (CMD_END)
710 {
711 expect (CMD_DELIM);
712 printf_monitor (CMD_END);
713 }
714 expect_prompt (1);
715 startaddr += 1;
716 }
717 }
718 return len;
719}
720
721/* FIXME-someday! merge these two. */
722static int
723monitor_xfer_inferior_memory (memaddr, myaddr, len, write, target)
724 CORE_ADDR memaddr;
725 char *myaddr;
726 int len;
727 int write;
728 struct target_ops *target; /* ignored */
729{
730 if (write)
731 return monitor_write_inferior_memory (memaddr, myaddr, len);
732 else
733 return monitor_read_inferior_memory (memaddr, myaddr, len);
734}
735
736static void
737monitor_kill (args, from_tty)
738 char *args;
739 int from_tty;
740{
741 return; /* ignore attempts to kill target system */
742}
743
744/* Clean up when a program exits.
745 The program actually lives on in the remote processor's RAM, and may be
746 run again without a download. Don't leave it full of breakpoint
747 instructions. */
748
749static void
750monitor_mourn_inferior ()
751{
752 remove_breakpoints ();
753 generic_mourn_inferior (); /* Do all the proper things now */
754}
755
756#define MAX_MONITOR_BREAKPOINTS 16
757
758extern int memory_breakpoint_size;
759static CORE_ADDR breakaddr[MAX_MONITOR_BREAKPOINTS] = {0};
760
761static int
762monitor_insert_breakpoint (addr, shadow)
763 CORE_ADDR addr;
764 char *shadow;
765{
766 int i;
767
768#ifdef LOG_FILE
769 fprintf (log_file, "\nIn Insert_breakpoint (addr=%x)\n", addr);
770#endif
771 for (i = 0; i <= MAX_MONITOR_BREAKPOINTS; i++)
772 if (breakaddr[i] == 0)
773 {
774 breakaddr[i] = addr;
775 if (kiodebug)
776 printf ("Breakpoint at %x\n", addr);
777 monitor_read_inferior_memory(addr, shadow, memory_breakpoint_size);
778 printf_monitor(SET_BREAK_CMD, addr);
779 expect_prompt(1);
780 return 0;
781 }
782
783 fprintf(stderr, "Too many breakpoints (> 16) for monitor\n");
784 return 1;
785}
786
787/*
788 * _remove_breakpoint -- Tell the monitor to remove a breakpoint
789 */
790static int
791monitor_remove_breakpoint (addr, shadow)
792 CORE_ADDR addr;
793 char *shadow;
794{
795 int i;
796
797#ifdef LOG_FILE
798 fprintf (log_file, "\nIn Remove_breakpoint (addr=%x)\n", addr);
799#endif
800 for (i = 0; i < MAX_MONITOR_BREAKPOINTS; i++)
801 if (breakaddr[i] == addr)
802 {
803 breakaddr[i] = 0;
804 /* some monitors remove breakpoints based on the address */
805 if (strcasecmp (target_shortname, "bug") == 0)
806 printf_monitor(CLR_BREAK_CMD, addr);
807 else
808 printf_monitor(CLR_BREAK_CMD, i);
809 expect_prompt(1);
810 return 0;
811 }
812
813 fprintf(stderr, "Can't find breakpoint associated with 0x%x\n", addr);
814 return 1;
815}
816
817/* Load a file. This is usually an srecord, which is ascii. No
818 protocol, just sent line by line. */
819
820#define DOWNLOAD_LINE_SIZE 100
821static void
822monitor_load (arg)
823 char *arg;
824{
825 FILE *download;
826 char buf[DOWNLOAD_LINE_SIZE];
827 int i, bytes_read;
828
829 if (kiodebug)
830 printf ("Loading %s to monitor\n", arg);
831
832 download = fopen (arg, "r");
833 if (download == NULL)
834 {
835 error (sprintf (buf, "%s Does not exist", arg));
836 return;
837 }
838
839 printf_monitor (LOAD_CMD);
840/* expect ("Waiting for S-records from host... ", 1); */
841
842 while (!feof (download))
843 {
844 bytes_read = fread (buf, sizeof (char), DOWNLOAD_LINE_SIZE, download);
845 if (hashmark)
846 {
847 putchar ('.');
848 fflush (stdout);
849 }
850
851 if (SERIAL_WRITE(monitor_desc, buf, bytes_read)) {
852 fprintf(stderr, "SERIAL_WRITE failed: (while downloading) %s\n", safe_strerror(errno));
853 break;
854 }
855 i = 0;
856 while (i++ <=200000) {} ; /* Ugly HACK, probably needs flow control */
857 if (bytes_read < DOWNLOAD_LINE_SIZE)
858 {
859 if (!feof (download))
860 error ("Only read %d bytes\n", bytes_read);
861 break;
862 }
863 }
864
865 if (hashmark)
866 {
867 putchar ('\n');
868 }
869 if (!feof (download))
870 error ("Never got EOF while downloading");
871 fclose (download);
872}
873
874/* Put a command string, in args, out to MONITOR. Output from MONITOR is placed
875 on the users terminal until the prompt is seen. */
876
877static void
878monitor_command (args, fromtty)
879 char *args;
880 int fromtty;
881{
882#ifdef LOG_FILE
883 fprintf (log_file, "\nIn command (args=%s)\n", args);
884#endif
885 if (monitor_desc == NULL)
886 error("monitor target not open.");
887
888 if (!args)
889 error("Missing command.");
890
891 printf_monitor("%s\r", args);
892 expect_prompt(0);
893}
894
895#if 0
896
897/* Connect the user directly to MONITOR. This command acts just like the
898 'cu' or 'tip' command. Use <CR>~. or <CR>~^D to break out. */
899
900static struct ttystate ttystate;
901
902static void
903cleanup_tty()
904{ printf("\r\n[Exiting connect mode]\r\n");
905 /*SERIAL_RESTORE(0, &ttystate);*/
906}
907
908static void
909connect_command (args, fromtty)
910 char *args;
911 int fromtty;
912{
913 fd_set readfds;
914 int numfds;
915 int c;
916 char cur_esc = 0;
917
918 dont_repeat();
919
920 if (monitor_desc == NULL)
921 error("monitor target not open.");
922
923 if (args)
924 fprintf("This command takes no args. They have been ignored.\n");
925
926 printf("[Entering connect mode. Use ~. or ~^D to escape]\n");
927
928 serial_raw(0, &ttystate);
929
930 make_cleanup(cleanup_tty, 0);
931
932 FD_ZERO(&readfds);
933
934 while (1)
935 {
936 do
937 {
938 FD_SET(0, &readfds);
939 FD_SET(monitor_desc, &readfds);
940 numfds = select(sizeof(readfds)*8, &readfds, 0, 0, 0);
941 }
942 while (numfds == 0);
943
944 if (numfds < 0)
945 perror_with_name("select");
946
947 if (FD_ISSET(0, &readfds))
948 { /* tty input, send to monitor */
949 c = getchar();
950 if (c < 0)
951 perror_with_name("connect");
952
953 printf_monitor("%c", c);
954 switch (cur_esc)
955 {
956 case 0:
957 if (c == '\r')
958 cur_esc = c;
959 break;
960 case '\r':
961 if (c == '~')
962 cur_esc = c;
963 else
964 cur_esc = 0;
965 break;
966 case '~':
967 if (c == '.' || c == '\004')
968 return;
969 else
970 cur_esc = 0;
971 }
972 }
973
974 if (FD_ISSET(monitor_desc, &readfds))
975 {
976 while (1)
977 {
978 c = readchar(0);
979 if (c < 0)
980 break;
981 putchar(c);
982 }
983 fflush(stdout);
984 }
985 }
986}
987#endif
988
989/*
990 * Define the monitor command strings. Since these are passed directly
991 * through to a printf style function, we need can include formatting
992 * strings. We also need a CR or LF on the end.
993 */
994struct monitor_ops rom68k_cmds = {
995 "go \r", /* execute or usually GO command */
996 "go \r", /* continue command */
997 "st \r", /* single step */
998 "db %x\r", /* set a breakpoint */
999 "cb %x\r", /* clear a breakpoint */
1000 "pm %x\r", /* set memory to a value */
1001 "pm %x\r", /* display memory */
1002 "-%08X ", /* prompt memory commands use */
1003 "pr %s %x\r", /* set a register */
1004 ": ", /* delimiter between registers */
1005 "pr %s\r", /* read a register */
1006 "dc \r", /* download command */
1007 "ROM68K :->", /* monitor command prompt */
1008 "=", /* end-of-command delimitor */
1009 ".\r" /* optional command terminator */
1010};
1011
1012struct monitor_ops bug_cmds = {
1013 "go \r", /* execute or usually GO command */
1014 "go \r", /* continue command */
1015 "gn \r", /* single step */
1016 "br %x\r", /* set a breakpoint */
1017 "nobr %x\r", /* clear a breakpoint */
1018 "mm %x\r", /* set memory to a value */
1019 "mm %x\r", /* display memory */
1020 "%08X", /* prompt memory commands use */
1021 "rs %s %x\r", /* set a register */
1022 "=", /* delimiter between registers */
1023 "rm %s\r", /* read a register */
1024 "lo 0\r", /* download command */
1025 "Bug>", /* monitor command prompt */
1026 "? ", /* end-of-command delimitor */
1027 ".\r" /* optional command terminator */
1028};
1029
1030/* Define the target subroutine names */
1031struct monitor_ops mon68_cmds = {
1032 "", /* execute or usually GO command */
1033 "", /* continue command */
1034 "", /* single step */
1035 "", /* set a breakpoint */
1036 "", /* clear a breakpoint */
1037 "", /* set memory to a value */
1038 "", /* display memory */
1039 "", /* set a register */
1040 "", /* delimiter between registers */
1041 "", /* read a register */
1042 "", /* download command */
1043 ">", /* monitor command prompt */
1044 "", /* end-of-command delimitor */
1045 "" /* optional command terminator */
1046};
1047
1048struct target_ops rom68k_ops = {
1049 "rom68k",
1050 "Integrated System's ROM68K remote debug monitor",
1051 "Use a remote computer running the ROM68K debug monitor.\n\
1052Specify the serial device it is connected to (e.g. /dev/ttya).",
1053 rom68k_open,
1054 monitor_close,
1055 0,
1056 monitor_detach,
1057 monitor_resume,
1058 monitor_wait,
1059 monitor_fetch_register,
1060 monitor_store_register,
1061 monitor_prepare_to_store,
1062 monitor_xfer_inferior_memory,
1063 monitor_files_info,
1064 monitor_insert_breakpoint,
1065 monitor_remove_breakpoint, /* Breakpoints */
1066 0,
1067 0,
1068 0,
1069 0,
1070 0, /* Terminal handling */
1071 monitor_kill,
1072 monitor_load, /* load */
1073 0, /* lookup_symbol */
1074 monitor_create_inferior,
1075 monitor_mourn_inferior,
1076 0, /* can_run */
1077 0, /* notice_signals */
1078 process_stratum,
1079 0, /* next */
1080 1,
1081 1,
1082 1,
1083 1,
1084 1, /* all mem, mem, stack, regs, exec */
1085 0,
1086 0, /* Section pointers */
1087 OPS_MAGIC, /* Always the last thing */
1088};
1089
1090struct target_ops monitor_bug_ops = {
1091 "bug",
1092 "Motorola's BUG remote serial debug monitor",
1093 "Use a remote computer running Motorola's BUG debug monitor.\n\
1094Specify the serial device it is connected to (e.g. /dev/ttya).",
1095 bug_open,
1096 monitor_close,
1097 0,
1098 monitor_detach,
1099 monitor_resume,
1100 monitor_wait,
1101 monitor_fetch_register,
1102 monitor_store_register,
1103 monitor_prepare_to_store,
1104 monitor_xfer_inferior_memory,
1105 monitor_files_info,
1106 monitor_insert_breakpoint,
1107 monitor_remove_breakpoint, /* Breakpoints */
1108 0,
1109 0,
1110 0,
1111 0,
1112 0, /* Terminal handling */
1113 monitor_kill,
1114 monitor_load, /* load */
1115 0, /* lookup_symbol */
1116 monitor_create_inferior,
1117 monitor_mourn_inferior,
1118 0, /* can_run */
1119 0, /* notice_signals */
1120 process_stratum,
1121 0, /* next */
1122 1,
1123 1,
1124 1,
1125 1,
1126 1, /* all mem, mem, stack, regs, exec */
1127 0,
1128 0, /* Section pointers */
1129 OPS_MAGIC, /* Always the last thing */
1130};
1131
1132struct target_ops mon68_ops = {
1133 "mon68",
1134 "Intermetric's MON68 remote serial debug monitor",
1135 "Use a remote computer running the MON68 debug monitor.\n\
1136Specify the serial device it is connected to (e.g. /dev/ttya).",
1137 mon68_open,
1138 monitor_close,
1139 0,
1140 monitor_detach,
1141 monitor_resume,
1142 monitor_wait,
1143 monitor_fetch_register,
1144 monitor_store_register,
1145 monitor_prepare_to_store,
1146 monitor_xfer_inferior_memory,
1147 monitor_files_info,
1148 monitor_insert_breakpoint,
1149 monitor_remove_breakpoint, /* Breakpoints */
1150 0,
1151 0,
1152 0,
1153 0,
1154 0, /* Terminal handling */
1155 monitor_kill,
1156 monitor_load, /* load */
1157 0, /* lookup_symbol */
1158 monitor_create_inferior,
1159 monitor_mourn_inferior,
1160 0, /* can_run */
1161 0, /* notice_signals */
1162 process_stratum,
1163 0, /* next */
1164 1,
1165 1,
1166 1,
1167 1,
1168 1, /* all mem, mem, stack, regs, exec */
1169 0,
1170 0, /* Section pointers */
1171 OPS_MAGIC, /* Always the last thing */
1172};
1173
1174void
1175_initialize_remote_monitors ()
1176{
1177 add_show_from_set (
1178 add_set_cmd ("remotedebug", no_class, var_boolean,
1179 (char *)&kiodebug,
1180 "Set debugging of I/O to a serial based Monitor.\n\
1181When enabled, debugging info is displayed.",
1182 &setlist),
1183 &showlist);
1184 add_show_from_set (
1185 add_set_cmd ("hash", no_class, var_boolean,
1186 (char *)&hashmark,
1187 "Set display of activity while downloading a file.\n\
1188When enabled, a period \'.\' is displayed.",
1189 &setlist),
1190 &showlist);
1191
1192 /* generic monitor command */
1193 add_com ("monitor <command>", class_obscure, monitor_command,
1194 "Send a command to the debug monitor.");
1195#if 0
1196 add_com ("connect", class_obscure, connect_command,
1197 "Connect the terminal directly up to a serial based command monitor.\n\
1198Use <CR>~. or <CR>~^D to break out.");
1199#endif
1200
1201 add_target (&rom68k_ops);
1202/* add_target (&mon68_ops); */
1203 add_target (&monitor_bug_ops);
1204}
This page took 0.07147 seconds and 4 git commands to generate.