]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/remote-os9k.c
import gdb-1999-07-07 post reformat
[thirdparty/binutils-gdb.git] / gdb / remote-os9k.c
CommitLineData
c906108c 1/* Remote debugging interface for boot monitors, for GDB.
9846de1b 2 Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
c906108c 3
c5aa993b 4 This file is part of GDB.
c906108c 5
c5aa993b
JM
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
c906108c 10
c5aa993b
JM
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
c906108c 15
c5aa993b
JM
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
c906108c
SS
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
c5aa993b 25 "This is like remote.c but is for a different situation--
c906108c
SS
26 having a PC running os9000 hook up with a unix machine with
27 a serial line, and running ctty com2 on the PC. os9000 has a debug
28 monitor called ROMBUG running. 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 'ROMBUG', which
33 We communicate with ROMBUG via a direct serial line, the network version
34 of ROMBUG is not available yet.
c5aa993b 35 */
c906108c
SS
36
37/* FIXME This file needs to be rewritten if it's to work again, either
38 to self-contained or to use the new monitor interface. */
39
40#include "defs.h"
41#include "gdbcore.h"
42#include "target.h"
43#include "wait.h"
44#ifdef ANSI_PROTOTYPES
45#include <stdarg.h>
46#else
47#include <varargs.h>
48#endif
49#include <signal.h>
43ff13b4 50#include "gdb_string.h"
9846de1b 51#include <sys/types.h>
c906108c
SS
52#include "command.h"
53#include "serial.h"
54#include "monitor.h"
55#include "remote-utils.h"
56#include "symtab.h"
57#include "symfile.h"
58#include "objfiles.h"
59#include "gdb-stabs.h"
60
61struct cmd_list_element *showlist;
c5aa993b
JM
62extern struct target_ops rombug_ops; /* Forward declaration */
63extern struct monitor_ops rombug_cmds; /* Forward declaration */
c906108c
SS
64extern struct cmd_list_element *setlist;
65extern struct cmd_list_element *unsetlist;
66extern int attach_flag;
67
c5aa993b
JM
68static void rombug_close ();
69static void rombug_fetch_register ();
70static void rombug_fetch_registers ();
71static void rombug_store_register ();
c906108c 72#if 0
c5aa993b 73static int sr_get_debug (); /* flag set by "set remotedebug" */
c906108c 74#endif
c5aa993b 75static int hashmark; /* flag set by "set hash" */
c906108c
SS
76static int rombug_is_open = 0;
77
78/* FIXME: Replace with sr_get_debug (). */
79#define LOG_FILE "monitor.log"
80FILE *log_file;
81static int monitor_log = 0;
82static int tty_xon = 0;
83static int tty_xoff = 0;
84
85static int timeout = 10;
86static int is_trace_mode = 0;
c5aa993b 87/* Descriptor for I/O to remote machine. Initialize it to NULL */
c906108c
SS
88static serial_t monitor_desc = NULL;
89
90static CORE_ADDR bufaddr = 0;
91static int buflen = 0;
92static char readbuf[16];
93
94/* Send data to monitor. Works just like printf. */
95static void
96#ifdef ANSI_PROTOTYPES
c5aa993b 97printf_monitor (char *pattern,...)
c906108c 98#else
c5aa993b 99printf_monitor (va_alist)
c906108c
SS
100 va_dcl
101#endif
102{
103 va_list args;
104 char buf[200];
105 int i;
106
107#ifdef ANSI_PROTOTYPES
108 va_start (args, pattern);
109#else
110 char *pattern;
c5aa993b
JM
111 va_start (args);
112 pattern = va_arg (args, char *);
c906108c
SS
113#endif
114
c5aa993b
JM
115 vsprintf (buf, pattern, args);
116 va_end (args);
c906108c 117
c5aa993b
JM
118 if (SERIAL_WRITE (monitor_desc, buf, strlen (buf)))
119 fprintf (stderr, "SERIAL_WRITE failed: %s\n", safe_strerror (errno));
c906108c
SS
120}
121
c5aa993b 122/* Read a character from the remote system, doing all the fancy timeout stuff */
c906108c 123static int
c5aa993b 124readchar (timeout)
c906108c
SS
125 int timeout;
126{
127 int c;
128
c5aa993b 129 c = SERIAL_READCHAR (monitor_desc, timeout);
c906108c 130
c5aa993b
JM
131 if (sr_get_debug ())
132 putchar (c & 0x7f);
c906108c 133
c5aa993b
JM
134 if (monitor_log && isascii (c))
135 putc (c & 0x7f, log_file);
c906108c
SS
136
137 if (c >= 0)
138 return c & 0x7f;
139
140 if (c == SERIAL_TIMEOUT)
141 {
142 if (timeout == 0)
143 return c; /* Polls shouldn't generate timeout errors */
144
c5aa993b 145 error ("Timeout reading from remote system.");
c906108c
SS
146 }
147
c5aa993b 148 perror_with_name ("remote-monitor");
c906108c
SS
149}
150
151/* Scan input from the remote system, until STRING is found. If DISCARD is
152 non-zero, then discard non-matching input, else print it out.
153 Let the user break out immediately. */
154static void
c5aa993b 155expect (string, discard)
c906108c
SS
156 char *string;
157 int discard;
158{
159 char *p = string;
160 int c;
161
c5aa993b 162 if (sr_get_debug ())
c906108c
SS
163 printf ("Expecting \"%s\"\n", string);
164
165 immediate_quit = 1;
166 while (1)
167 {
c5aa993b 168 c = readchar (timeout);
c906108c
SS
169 if (!isascii (c))
170 continue;
171 if (c == *p++)
172 {
173 if (*p == '\0')
174 {
175 immediate_quit = 0;
c5aa993b 176 if (sr_get_debug ())
c906108c
SS
177 printf ("\nMatched\n");
178 return;
179 }
180 }
181 else
182 {
183 if (!discard)
184 {
c5aa993b
JM
185 fwrite (string, 1, (p - 1) - string, stdout);
186 putchar ((char) c);
187 fflush (stdout);
c906108c
SS
188 }
189 p = string;
190 }
191 }
192}
193
194/* Keep discarding input until we see the ROMBUG prompt.
195
196 The convention for dealing with the prompt is that you
197 o give your command
198 o *then* wait for the prompt.
199
200 Thus the last thing that a procedure does with the serial line
201 will be an expect_prompt(). Exception: rombug_resume does not
202 wait for the prompt, because the terminal is being handed over
203 to the inferior. However, the next thing which happens after that
204 is a rombug_wait which does wait for the prompt.
205 Note that this includes abnormal exit, e.g. error(). This is
206 necessary to prevent getting into states from which we can't
207 recover. */
208static void
c5aa993b 209expect_prompt (discard)
c906108c
SS
210 int discard;
211{
212 if (monitor_log)
c5aa993b
JM
213 /* This is a convenient place to do this. The idea is to do it often
214 enough that we never lose much data if we terminate abnormally. */
215 fflush (log_file);
216
217 if (is_trace_mode)
218 {
219 expect ("trace", discard);
220 }
221 else
222 {
223 expect (PROMPT, discard);
224 }
c906108c
SS
225}
226
227/* Get a hex digit from the remote system & return its value.
228 If ignore_space is nonzero, ignore spaces (not newline, tab, etc). */
229static int
c5aa993b 230get_hex_digit (ignore_space)
c906108c
SS
231 int ignore_space;
232{
233 int ch;
234 while (1)
235 {
c5aa993b 236 ch = readchar (timeout);
c906108c
SS
237 if (ch >= '0' && ch <= '9')
238 return ch - '0';
239 else if (ch >= 'A' && ch <= 'F')
240 return ch - 'A' + 10;
241 else if (ch >= 'a' && ch <= 'f')
242 return ch - 'a' + 10;
243 else if (ch == ' ' && ignore_space)
244 ;
245 else
246 {
c5aa993b
JM
247 expect_prompt (1);
248 error ("Invalid hex digit from remote system.");
c906108c
SS
249 }
250 }
251}
252
253/* Get a byte from monitor and put it in *BYT. Accept any number
254 leading spaces. */
255static void
256get_hex_byte (byt)
257 char *byt;
258{
259 int val;
260
261 val = get_hex_digit (1) << 4;
262 val |= get_hex_digit (0);
263 *byt = val;
264}
265
266/* Get N 32-bit words from remote, each preceded by a space,
267 and put them in registers starting at REGNO. */
268static void
269get_hex_regs (n, regno)
270 int n;
271 int regno;
272{
273 long val;
274 int i;
275 unsigned char b;
276
277 for (i = 0; i < n; i++)
278 {
279 int j;
c5aa993b 280
c906108c
SS
281 val = 0;
282 for (j = 0; j < 4; j++)
283 {
284 get_hex_byte (&b);
285 if (TARGET_BYTE_ORDER == BIG_ENDIAN)
286 val = (val << 8) + b;
287 else
c5aa993b 288 val = val + (b << (j * 8));
c906108c
SS
289 }
290 supply_register (regno++, (char *) &val);
291 }
292}
293
294/* This is called not only when we first attach, but also when the
295 user types "run" after having attached. */
296static void
297rombug_create_inferior (execfile, args, env)
298 char *execfile;
299 char *args;
300 char **env;
301{
302 int entry_pt;
303
304 if (args && *args)
c5aa993b 305 error ("Can't pass arguments to remote ROMBUG process");
c906108c
SS
306
307 if (execfile == 0 || exec_bfd == 0)
c5aa993b 308 error ("No executable file specified");
c906108c
SS
309
310 entry_pt = (int) bfd_get_start_address (exec_bfd);
311
312 if (monitor_log)
313 fputs ("\nIn Create_inferior()", log_file);
314
315
316/* The "process" (board) is already stopped awaiting our commands, and
317 the program is already downloaded. We just set its PC and go. */
318
319 init_wait_for_inferior ();
c5aa993b 320 proceed ((CORE_ADDR) entry_pt, TARGET_SIGNAL_DEFAULT, 0);
c906108c
SS
321}
322
323/* Open a connection to a remote debugger.
324 NAME is the filename used for communication. */
325
326static char dev_name[100];
327
328static void
c5aa993b 329rombug_open (args, from_tty)
c906108c
SS
330 char *args;
331 int from_tty;
332{
333 if (args == NULL)
334 error ("Use `target RomBug DEVICE-NAME' to use a serial port, or \n\
335`target RomBug HOST-NAME:PORT-NUMBER' to use a network connection.");
336
c5aa993b 337 target_preopen (from_tty);
c906108c
SS
338
339 if (rombug_is_open)
c5aa993b 340 unpush_target (&rombug_ops);
c906108c 341
c5aa993b
JM
342 strcpy (dev_name, args);
343 monitor_desc = SERIAL_OPEN (dev_name);
c906108c 344 if (monitor_desc == NULL)
c5aa993b 345 perror_with_name (dev_name);
c906108c
SS
346
347 /* if baud rate is set by 'set remotebaud' */
c5aa993b 348 if (SERIAL_SETBAUDRATE (monitor_desc, sr_get_baud_rate ()))
c906108c
SS
349 {
350 SERIAL_CLOSE (monitor_desc);
351 perror_with_name ("RomBug");
352 }
c5aa993b 353 SERIAL_RAW (monitor_desc);
c906108c
SS
354 if (tty_xon || tty_xoff)
355 {
c5aa993b
JM
356 struct hardware_ttystate
357 {
358 struct termios t;
359 }
360 *tty_s;
361
362 tty_s = (struct hardware_ttystate *) SERIAL_GET_TTY_STATE (monitor_desc);
363 if (tty_xon)
364 tty_s->t.c_iflag |= IXON;
365 if (tty_xoff)
366 tty_s->t.c_iflag |= IXOFF;
367 SERIAL_SET_TTY_STATE (monitor_desc, (serial_ttystate) tty_s);
c906108c
SS
368 }
369
370 rombug_is_open = 1;
371
372 log_file = fopen (LOG_FILE, "w");
373 if (log_file == NULL)
374 perror_with_name (LOG_FILE);
375
376 push_monitor (&rombug_cmds);
c5aa993b
JM
377 printf_monitor ("\r"); /* CR wakes up monitor */
378 expect_prompt (1);
c906108c
SS
379 push_target (&rombug_ops);
380 attach_flag = 1;
381
382 if (from_tty)
c5aa993b
JM
383 printf ("Remote %s connected to %s\n", target_shortname,
384 dev_name);
c906108c 385
c5aa993b 386 rombug_fetch_registers ();
c906108c
SS
387
388 printf_monitor ("ov e \r");
c5aa993b 389 expect_prompt (1);
c906108c
SS
390 bufaddr = 0;
391 buflen = 0;
392}
393
394/*
395 * Close out all files and local state before this target loses control.
396 */
397
398static void
399rombug_close (quitting)
400 int quitting;
401{
c5aa993b
JM
402 if (rombug_is_open)
403 {
404 SERIAL_CLOSE (monitor_desc);
405 monitor_desc = NULL;
406 rombug_is_open = 0;
407 }
408
409 if (log_file)
410 {
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 log_file = 0;
416 }
c906108c
SS
417}
418
419int
c5aa993b 420rombug_link (mod_name, text_reloc)
c906108c
SS
421 char *mod_name;
422 CORE_ADDR *text_reloc;
423{
424 int i, j;
425 unsigned long val;
426 unsigned char b;
427
c5aa993b
JM
428 printf_monitor ("l %s \r", mod_name);
429 expect_prompt (1);
430 printf_monitor (".r \r");
431 expect (REG_DELIM, 1);
432 for (i = 0; i <= 7; i++)
c906108c
SS
433 {
434 val = 0;
435 for (j = 0; j < 4; j++)
c5aa993b
JM
436 {
437 get_hex_byte (&b);
438 val = (val << 8) + b;
c906108c
SS
439 }
440 }
c5aa993b 441 expect_prompt (1);
c906108c
SS
442 *text_reloc = val;
443 return 1;
444}
445
446/* Terminate the open connection to the remote debugger.
447 Use this when you want to detach and do something else
448 with your gdb. */
449static void
450rombug_detach (from_tty)
451 int from_tty;
452{
c5aa993b
JM
453 if (attach_flag)
454 {
455 printf_monitor (GO_CMD);
456 attach_flag = 0;
457 }
458 pop_target (); /* calls rombug_close to do the real work */
c906108c
SS
459 if (from_tty)
460 printf ("Ending remote %s debugging\n", target_shortname);
461}
c5aa993b 462
c906108c
SS
463/*
464 * Tell the remote machine to resume.
465 */
466static void
467rombug_resume (pid, step, sig)
468 int pid, step;
469 enum target_signal sig;
470{
471 if (monitor_log)
472 fprintf (log_file, "\nIn Resume (step=%d, sig=%d)\n", step, sig);
473
474 if (step)
475 {
476 is_trace_mode = 1;
477 printf_monitor (STEP_CMD);
478 /* wait for the echo. **
c5aa993b
JM
479 expect (STEP_CMD, 1);
480 */
c906108c
SS
481 }
482 else
483 {
484 printf_monitor (GO_CMD);
485 /* swallow the echo. **
c5aa993b
JM
486 expect (GO_CMD, 1);
487 */
c906108c
SS
488 }
489 bufaddr = 0;
c5aa993b 490 buflen = 0;
c906108c
SS
491}
492
493/*
494 * Wait until the remote machine stops, then return,
495 * storing status in status just as `wait' would.
496 */
497
498static int
499rombug_wait (pid, status)
500 int pid;
501 struct target_waitstatus *status;
502{
503 int old_timeout = timeout;
504 struct section_offsets *offs;
505 CORE_ADDR addr, pc;
506 struct obj_section *obj_sec;
507
508 if (monitor_log)
509 fputs ("\nIn wait ()", log_file);
510
511 status->kind = TARGET_WAITKIND_EXITED;
512 status->value.integer = 0;
513
c5aa993b
JM
514 timeout = -1; /* Don't time out -- user program is running. */
515 expect ("eax:", 0); /* output any message before register display */
516 expect_prompt (1); /* Wait for prompt, outputting extraneous text */
c906108c
SS
517
518 status->kind = TARGET_WAITKIND_STOPPED;
519 status->value.sig = TARGET_SIGNAL_TRAP;
520 timeout = old_timeout;
c5aa993b 521 rombug_fetch_registers ();
c906108c
SS
522 bufaddr = 0;
523 buflen = 0;
c5aa993b
JM
524 pc = read_register (PC_REGNUM);
525 addr = read_register (DATABASE_REG);
c906108c
SS
526 obj_sec = find_pc_section (pc);
527 if (obj_sec != NULL)
528 {
529 if (obj_sec->objfile != symfile_objfile)
c5aa993b 530 new_symfile_objfile (obj_sec->objfile, 1, 0);
c906108c 531 offs = ((struct section_offsets *)
c5aa993b
JM
532 alloca (sizeof (struct section_offsets)
533 + (symfile_objfile->num_sections * sizeof (offs->offsets))));
c906108c 534 memcpy (offs, symfile_objfile->section_offsets,
c5aa993b
JM
535 (sizeof (struct section_offsets) +
536 (symfile_objfile->num_sections * sizeof (offs->offsets))));
c906108c
SS
537 ANOFFSET (offs, SECT_OFF_DATA) = addr;
538 ANOFFSET (offs, SECT_OFF_BSS) = addr;
539
c5aa993b 540 objfile_relocate (symfile_objfile, offs);
c906108c
SS
541 }
542
543 return 0;
544}
545
546/* Return the name of register number regno in the form input and output by
547 monitor. Currently, register_names just happens to contain exactly what
548 monitor wants. Lets take advantage of that just as long as possible! */
549
550static char *
551get_reg_name (regno)
552 int regno;
553{
554 static char buf[50];
555 char *p;
556 char *b;
557
558 b = buf;
559
560 if (regno < 0)
561 return ("");
562/*
c5aa993b
JM
563 for (p = REGISTER_NAME (regno); *p; p++)
564 *b++ = toupper(*p);
565 *b = '\000';
566 */
567 p = (char *) REGISTER_NAME (regno);
c906108c
SS
568 return p;
569/*
c5aa993b
JM
570 return buf;
571 */
c906108c
SS
572}
573
574/* read the remote registers into the block regs. */
575
576static void
577rombug_fetch_registers ()
578{
579 int regno, j, i;
580 long val;
581 unsigned char b;
582
583 printf_monitor (GET_REG);
c5aa993b
JM
584 expect ("eax:", 1);
585 expect ("\n", 1);
586 get_hex_regs (1, 0);
587 get_hex_regs (1, 3);
588 get_hex_regs (1, 1);
589 get_hex_regs (1, 2);
590 get_hex_regs (1, 6);
591 get_hex_regs (1, 7);
592 get_hex_regs (1, 5);
593 get_hex_regs (1, 4);
c906108c
SS
594 for (regno = 8; regno <= 15; regno++)
595 {
c5aa993b 596 expect (REG_DELIM, 1);
c906108c
SS
597 if (regno >= 8 && regno <= 13)
598 {
599 val = 0;
600 for (j = 0; j < 2; j++)
c5aa993b
JM
601 {
602 get_hex_byte (&b);
c906108c
SS
603 if (TARGET_BYTE_ORDER == BIG_ENDIAN)
604 val = (val << 8) + b;
605 else
c5aa993b
JM
606 val = val + (b << (j * 8));
607 }
c906108c 608
c5aa993b
JM
609 if (regno == 8)
610 i = 10;
611 if (regno >= 9 && regno <= 12)
612 i = regno + 3;
613 if (regno == 13)
614 i = 11;
c906108c
SS
615 supply_register (i, (char *) &val);
616 }
617 else if (regno == 14)
618 {
c5aa993b 619 get_hex_regs (1, PC_REGNUM);
c906108c
SS
620 }
621 else if (regno == 15)
622 {
c5aa993b 623 get_hex_regs (1, 9);
c906108c
SS
624 }
625 else
626 {
627 val = 0;
c5aa993b 628 supply_register (regno, (char *) &val);
c906108c
SS
629 }
630 }
631 is_trace_mode = 0;
632 expect_prompt (1);
633}
634
635/* Fetch register REGNO, or all registers if REGNO is -1.
636 Returns errno value. */
637static void
638rombug_fetch_register (regno)
639 int regno;
640{
641 int val, j;
642 unsigned char b;
643
c5aa993b
JM
644 if (monitor_log)
645 {
646 fprintf (log_file, "\nIn Fetch Register (reg=%s)\n", get_reg_name (regno));
647 fflush (log_file);
648 }
c906108c
SS
649
650 if (regno < 0)
651 {
652 rombug_fetch_registers ();
653 }
654 else
655 {
656 char *name = get_reg_name (regno);
657 printf_monitor (GET_REG);
658 if (regno >= 10 && regno <= 15)
659 {
660 expect ("\n", 1);
661 expect ("\n", 1);
c5aa993b
JM
662 expect (name, 1);
663 expect (REG_DELIM, 1);
c906108c
SS
664 val = 0;
665 for (j = 0; j < 2; j++)
c5aa993b
JM
666 {
667 get_hex_byte (&b);
c906108c
SS
668 if (TARGET_BYTE_ORDER == BIG_ENDIAN)
669 val = (val << 8) + b;
670 else
c5aa993b
JM
671 val = val + (b << (j * 8));
672 }
c906108c
SS
673 supply_register (regno, (char *) &val);
674 }
675 else if (regno == 8 || regno == 9)
676 {
677 expect ("\n", 1);
678 expect ("\n", 1);
679 expect ("\n", 1);
c5aa993b
JM
680 expect (name, 1);
681 expect (REG_DELIM, 1);
c906108c
SS
682 get_hex_regs (1, regno);
683 }
684 else
685 {
c5aa993b
JM
686 expect (name, 1);
687 expect (REG_DELIM, 1);
688 expect ("\n", 1);
689 get_hex_regs (1, 0);
690 get_hex_regs (1, 3);
691 get_hex_regs (1, 1);
692 get_hex_regs (1, 2);
693 get_hex_regs (1, 6);
694 get_hex_regs (1, 7);
695 get_hex_regs (1, 5);
696 get_hex_regs (1, 4);
c906108c
SS
697 }
698 expect_prompt (1);
699 }
700 return;
701}
702
703/* Store the remote registers from the contents of the block REGS. */
704
705static void
706rombug_store_registers ()
707{
708 int regno;
709
710 for (regno = 0; regno <= PC_REGNUM; regno++)
c5aa993b 711 rombug_store_register (regno);
c906108c
SS
712
713 registers_changed ();
714}
715
716/* Store register REGNO, or all if REGNO == 0.
717 return errno value. */
718static void
719rombug_store_register (regno)
720 int regno;
721{
c5aa993b 722 char *name;
c906108c
SS
723
724 if (monitor_log)
725 fprintf (log_file, "\nIn Store_register (regno=%d)\n", regno);
726
727 if (regno == -1)
728 rombug_store_registers ();
729 else
730 {
c5aa993b 731 if (sr_get_debug ())
c906108c
SS
732 printf ("Setting register %s to 0x%x\n", get_reg_name (regno), read_register (regno));
733
c5aa993b
JM
734 name = get_reg_name (regno);
735 if (name == 0)
736 return;
c906108c
SS
737 printf_monitor (SET_REG, name, read_register (regno));
738
739 is_trace_mode = 0;
740 expect_prompt (1);
741 }
742}
743
744/* Get ready to modify the registers array. On machines which store
745 individual registers, this doesn't need to do anything. On machines
746 which store all the registers in one fell swoop, this makes sure
747 that registers contains all the registers from the program being
748 debugged. */
749
750static void
751rombug_prepare_to_store ()
752{
753 /* Do nothing, since we can store individual regs */
754}
755
756static void
757rombug_files_info ()
758{
759 printf ("\tAttached to %s at %d baud.\n",
c5aa993b 760 dev_name, sr_get_baud_rate ());
c906108c
SS
761}
762
763/* Copy LEN bytes of data from debugger memory at MYADDR
764 to inferior's memory at MEMADDR. Returns length moved. */
765static int
766rombug_write_inferior_memory (memaddr, myaddr, len)
767 CORE_ADDR memaddr;
768 unsigned char *myaddr;
769 int len;
770{
771 int i;
772 char buf[10];
773
774 if (monitor_log)
775 fprintf (log_file, "\nIn Write_inferior_memory (memaddr=%x, len=%d)\n", memaddr, len);
776
777 printf_monitor (MEM_SET_CMD, memaddr);
778 for (i = 0; i < len; i++)
779 {
780 expect (CMD_DELIM, 1);
781 printf_monitor ("%x \r", myaddr[i]);
c5aa993b 782 if (sr_get_debug ())
c906108c
SS
783 printf ("\nSet 0x%x to 0x%x\n", memaddr + i, myaddr[i]);
784 }
785 expect (CMD_DELIM, 1);
786 if (CMD_END)
787 printf_monitor (CMD_END);
788 is_trace_mode = 0;
789 expect_prompt (1);
790
791 bufaddr = 0;
792 buflen = 0;
793 return len;
794}
795
796/* Read LEN bytes from inferior memory at MEMADDR. Put the result
797 at debugger address MYADDR. Returns length moved. */
798static int
c5aa993b 799rombug_read_inferior_memory (memaddr, myaddr, len)
c906108c
SS
800 CORE_ADDR memaddr;
801 char *myaddr;
802 int len;
803{
804 int i, j;
805
806 /* Number of bytes read so far. */
807 int count;
808
809 /* Starting address of this pass. */
810 unsigned long startaddr;
811
812 /* Number of bytes to read in this pass. */
813 int len_this_pass;
814
815 if (monitor_log)
816 fprintf (log_file, "\nIn Read_inferior_memory (memaddr=%x, len=%d)\n", memaddr, len);
817
818 /* Note that this code works correctly if startaddr is just less
819 than UINT_MAX (well, really CORE_ADDR_MAX if there was such a
820 thing). That is, something like
821 rombug_read_bytes (CORE_ADDR_MAX - 4, foo, 4)
822 works--it never adds len To memaddr and gets 0. */
823 /* However, something like
824 rombug_read_bytes (CORE_ADDR_MAX - 3, foo, 4)
825 doesn't need to work. Detect it and give up if there's an attempt
826 to do that. */
c5aa993b
JM
827 if (((memaddr - 1) + len) < memaddr)
828 {
829 errno = EIO;
830 return 0;
831 }
832 if (bufaddr <= memaddr && (memaddr + len) <= (bufaddr + buflen))
c906108c 833 {
c5aa993b 834 memcpy (myaddr, &readbuf[memaddr - bufaddr], len);
c906108c
SS
835 return len;
836 }
c5aa993b 837
c906108c
SS
838 startaddr = memaddr;
839 count = 0;
840 while (count < len)
841 {
842 len_this_pass = 16;
843 if ((startaddr % 16) != 0)
844 len_this_pass -= startaddr % 16;
845 if (len_this_pass > (len - count))
846 len_this_pass = (len - count);
c5aa993b 847 if (sr_get_debug ())
c906108c
SS
848 printf ("\nDisplay %d bytes at %x\n", len_this_pass, startaddr);
849
850 printf_monitor (MEM_DIS_CMD, startaddr, 8);
851 expect ("- ", 1);
852 for (i = 0; i < 16; i++)
853 {
854 get_hex_byte (&readbuf[i]);
855 }
856 bufaddr = startaddr;
857 buflen = 16;
c5aa993b 858 memcpy (&myaddr[count], readbuf, len_this_pass);
c906108c
SS
859 count += len_this_pass;
860 startaddr += len_this_pass;
c5aa993b 861 expect (CMD_DELIM, 1);
c906108c 862 }
c5aa993b
JM
863 if (CMD_END)
864 printf_monitor (CMD_END);
c906108c
SS
865 is_trace_mode = 0;
866 expect_prompt (1);
867
868 return len;
869}
870
871/* FIXME-someday! merge these two. */
872static int
873rombug_xfer_inferior_memory (memaddr, myaddr, len, write, target)
874 CORE_ADDR memaddr;
875 char *myaddr;
876 int len;
877 int write;
c5aa993b 878 struct target_ops *target; /* ignored */
c906108c
SS
879{
880 if (write)
881 return rombug_write_inferior_memory (memaddr, myaddr, len);
882 else
883 return rombug_read_inferior_memory (memaddr, myaddr, len);
884}
885
886static void
887rombug_kill (args, from_tty)
888 char *args;
889 int from_tty;
890{
c5aa993b 891 return; /* ignore attempts to kill target system */
c906108c
SS
892}
893
894/* Clean up when a program exits.
895 The program actually lives on in the remote processor's RAM, and may be
896 run again without a download. Don't leave it full of breakpoint
897 instructions. */
898
899static void
900rombug_mourn_inferior ()
901{
902 remove_breakpoints ();
903 generic_mourn_inferior (); /* Do all the proper things now */
904}
905
906#define MAX_MONITOR_BREAKPOINTS 16
907
c5aa993b
JM
908static CORE_ADDR breakaddr[MAX_MONITOR_BREAKPOINTS] =
909{0};
c906108c
SS
910
911static int
912rombug_insert_breakpoint (addr, shadow)
913 CORE_ADDR addr;
914 char *shadow;
915{
916 int i;
917 CORE_ADDR bp_addr = addr;
918 int bp_size = 0;
919
920 if (monitor_log)
921 fprintf (log_file, "\nIn Insert_breakpoint (addr=%x)\n", addr);
922 BREAKPOINT_FROM_PC (&bp_addr, &bp_size);
923
924 for (i = 0; i <= MAX_MONITOR_BREAKPOINTS; i++)
925 if (breakaddr[i] == 0)
926 {
927 breakaddr[i] = addr;
c5aa993b 928 if (sr_get_debug ())
c906108c
SS
929 printf ("Breakpoint at %x\n", addr);
930 rombug_read_inferior_memory (bp_addr, shadow, bp_size);
c5aa993b 931 printf_monitor (SET_BREAK_CMD, addr);
c906108c 932 is_trace_mode = 0;
c5aa993b 933 expect_prompt (1);
c906108c
SS
934 return 0;
935 }
936
c5aa993b 937 fprintf (stderr, "Too many breakpoints (> 16) for monitor\n");
c906108c
SS
938 return 1;
939}
940
941/*
942 * _remove_breakpoint -- Tell the monitor to remove a breakpoint
943 */
944static int
945rombug_remove_breakpoint (addr, shadow)
946 CORE_ADDR addr;
947 char *shadow;
948{
949 int i;
950
951 if (monitor_log)
952 fprintf (log_file, "\nIn Remove_breakpoint (addr=%x)\n", addr);
953
954 for (i = 0; i < MAX_MONITOR_BREAKPOINTS; i++)
955 if (breakaddr[i] == addr)
956 {
957 breakaddr[i] = 0;
c5aa993b 958 printf_monitor (CLR_BREAK_CMD, addr);
c906108c 959 is_trace_mode = 0;
c5aa993b 960 expect_prompt (1);
c906108c
SS
961 return 0;
962 }
963
c5aa993b 964 fprintf (stderr, "Can't find breakpoint associated with 0x%x\n", addr);
c906108c
SS
965 return 1;
966}
967
968/* Load a file. This is usually an srecord, which is ascii. No
969 protocol, just sent line by line. */
970
971#define DOWNLOAD_LINE_SIZE 100
972static void
973rombug_load (arg)
c5aa993b 974 char *arg;
c906108c
SS
975{
976/* this part comment out for os9* */
977#if 0
978 FILE *download;
979 char buf[DOWNLOAD_LINE_SIZE];
980 int i, bytes_read;
981
c5aa993b 982 if (sr_get_debug ())
c906108c
SS
983 printf ("Loading %s to monitor\n", arg);
984
985 download = fopen (arg, "r");
986 if (download == NULL)
987 {
c5aa993b
JM
988 error (sprintf (buf, "%s Does not exist", arg));
989 return;
990 }
c906108c
SS
991
992 printf_monitor (LOAD_CMD);
993/* expect ("Waiting for S-records from host... ", 1); */
994
995 while (!feof (download))
996 {
997 bytes_read = fread (buf, sizeof (char), DOWNLOAD_LINE_SIZE, download);
998 if (hashmark)
999 {
1000 putchar ('.');
1001 fflush (stdout);
1002 }
1003
c5aa993b
JM
1004 if (SERIAL_WRITE (monitor_desc, buf, bytes_read))
1005 {
1006 fprintf (stderr, "SERIAL_WRITE failed: (while downloading) %s\n", safe_strerror (errno));
1007 break;
1008 }
c906108c 1009 i = 0;
c5aa993b
JM
1010 while (i++ <= 200000)
1011 {
1012 }; /* Ugly HACK, probably needs flow control */
c906108c
SS
1013 if (bytes_read < DOWNLOAD_LINE_SIZE)
1014 {
1015 if (!feof (download))
1016 error ("Only read %d bytes\n", bytes_read);
1017 break;
1018 }
1019 }
1020
1021 if (hashmark)
1022 {
1023 putchar ('\n');
1024 }
1025 if (!feof (download))
1026 error ("Never got EOF while downloading");
1027 fclose (download);
c5aa993b 1028#endif /* 0 */
c906108c
SS
1029}
1030
1031/* Put a command string, in args, out to MONITOR.
1032 Output from MONITOR is placed on the users terminal until the prompt
1033 is seen. */
1034
1035static void
1036rombug_command (args, fromtty)
c5aa993b
JM
1037 char *args;
1038 int fromtty;
c906108c
SS
1039{
1040 if (monitor_desc == NULL)
c5aa993b
JM
1041 error ("monitor target not open.");
1042
c906108c
SS
1043 if (monitor_log)
1044 fprintf (log_file, "\nIn command (args=%s)\n", args);
1045
1046 if (!args)
c5aa993b
JM
1047 error ("Missing command.");
1048
1049 printf_monitor ("%s\r", args);
1050 expect_prompt (0);
c906108c
SS
1051}
1052
1053#if 0
1054/* Connect the user directly to MONITOR. This command acts just like the
1055 'cu' or 'tip' command. Use <CR>~. or <CR>~^D to break out. */
1056
1057static struct ttystate ttystate;
1058
1059static void
c5aa993b
JM
1060cleanup_tty ()
1061{
1062 printf ("\r\n[Exiting connect mode]\r\n");
1063 /*SERIAL_RESTORE(0, &ttystate); */
c906108c
SS
1064}
1065
1066static void
1067connect_command (args, fromtty)
c5aa993b
JM
1068 char *args;
1069 int fromtty;
c906108c
SS
1070{
1071 fd_set readfds;
1072 int numfds;
1073 int c;
1074 char cur_esc = 0;
1075
c5aa993b 1076 dont_repeat ();
c906108c
SS
1077
1078 if (monitor_desc == NULL)
c5aa993b
JM
1079 error ("monitor target not open.");
1080
c906108c 1081 if (args)
c5aa993b
JM
1082 fprintf ("This command takes no args. They have been ignored.\n");
1083
1084 printf ("[Entering connect mode. Use ~. or ~^D to escape]\n");
c906108c 1085
c5aa993b 1086 serial_raw (0, &ttystate);
c906108c 1087
c5aa993b 1088 make_cleanup (cleanup_tty, 0);
c906108c 1089
c5aa993b 1090 FD_ZERO (&readfds);
c906108c
SS
1091
1092 while (1)
1093 {
1094 do
1095 {
c5aa993b
JM
1096 FD_SET (0, &readfds);
1097 FD_SET (monitor_desc, &readfds);
1098 numfds = select (sizeof (readfds) * 8, &readfds, 0, 0, 0);
c906108c
SS
1099 }
1100 while (numfds == 0);
1101
1102 if (numfds < 0)
c5aa993b 1103 perror_with_name ("select");
c906108c 1104
c5aa993b 1105 if (FD_ISSET (0, &readfds))
c906108c 1106 { /* tty input, send to monitor */
c5aa993b 1107 c = getchar ();
c906108c 1108 if (c < 0)
c5aa993b 1109 perror_with_name ("connect");
c906108c 1110
c5aa993b 1111 printf_monitor ("%c", c);
c906108c
SS
1112 switch (cur_esc)
1113 {
1114 case 0:
1115 if (c == '\r')
1116 cur_esc = c;
1117 break;
1118 case '\r':
1119 if (c == '~')
1120 cur_esc = c;
1121 else
1122 cur_esc = 0;
1123 break;
1124 case '~':
1125 if (c == '.' || c == '\004')
1126 return;
1127 else
1128 cur_esc = 0;
1129 }
1130 }
1131
c5aa993b 1132 if (FD_ISSET (monitor_desc, &readfds))
c906108c
SS
1133 {
1134 while (1)
1135 {
c5aa993b 1136 c = readchar (0);
c906108c
SS
1137 if (c < 0)
1138 break;
c5aa993b 1139 putchar (c);
c906108c 1140 }
c5aa993b 1141 fflush (stdout);
c906108c
SS
1142 }
1143 }
1144}
1145#endif
1146
1147/*
1148 * Define the monitor command strings. Since these are passed directly
1149 * through to a printf style function, we need can include formatting
1150 * strings. We also need a CR or LF on the end.
1151 */
1152#warning FIXME: monitor interface pattern strings, stale struct decl
c5aa993b
JM
1153struct monitor_ops rombug_cmds =
1154{
1155 "g \r", /* execute or usually GO command */
1156 "g \r", /* continue command */
1157 "t \r", /* single step */
1158 "b %x\r", /* set a breakpoint */
1159 "k %x\r", /* clear a breakpoint */
1160 "c %x\r", /* set memory to a value */
1161 "d %x %d\r", /* display memory */
1162 "$%08X", /* prompt memory commands use */
1163 ".%s %x\r", /* set a register */
1164 ":", /* delimiter between registers */
1165 ". \r", /* read a register */
1166 "mf \r", /* download command */
1167 "RomBug: ", /* monitor command prompt */
1168 ": ", /* end-of-command delimitor */
1169 ".\r" /* optional command terminator */
c906108c
SS
1170};
1171
c5aa993b 1172struct target_ops rombug_ops;
c906108c 1173
c5aa993b
JM
1174static void
1175init_rombug_ops (void)
c906108c 1176{
c5aa993b
JM
1177 rombug_ops.to_shortname = "rombug";
1178 rombug_ops.to_longname = "Microware's ROMBUG debug monitor";
1179 rombug_ops.to_doc = "Use a remote computer running the ROMBUG debug monitor.\n\
c906108c 1180Specify the serial device it is connected to (e.g. /dev/ttya).",
c5aa993b
JM
1181 rombug_ops.to_open = rombug_open;
1182 rombug_ops.to_close = rombug_close;
1183 rombug_ops.to_attach = 0;
c906108c
SS
1184 rombug_ops.to_post_attach = NULL;
1185 rombug_ops.to_require_attach = NULL;
c5aa993b 1186 rombug_ops.to_detach = rombug_detach;
c906108c 1187 rombug_ops.to_require_detach = NULL;
c5aa993b
JM
1188 rombug_ops.to_resume = rombug_resume;
1189 rombug_ops.to_wait = rombug_wait;
c906108c 1190 rombug_ops.to_post_wait = NULL;
c5aa993b
JM
1191 rombug_ops.to_fetch_registers = rombug_fetch_register;
1192 rombug_ops.to_store_registers = rombug_store_register;
1193 rombug_ops.to_prepare_to_store = rombug_prepare_to_store;
1194 rombug_ops.to_xfer_memory = rombug_xfer_inferior_memory;
1195 rombug_ops.to_files_info = rombug_files_info;
1196 rombug_ops.to_insert_breakpoint = rombug_insert_breakpoint;
1197 rombug_ops.to_remove_breakpoint = rombug_remove_breakpoint; /* Breakpoints */
1198 rombug_ops.to_terminal_init = 0;
1199 rombug_ops.to_terminal_inferior = 0;
1200 rombug_ops.to_terminal_ours_for_output = 0;
1201 rombug_ops.to_terminal_ours = 0;
1202 rombug_ops.to_terminal_info = 0; /* Terminal handling */
1203 rombug_ops.to_kill = rombug_kill;
1204 rombug_ops.to_load = rombug_load; /* load */
1205 rombug_ops.to_lookup_symbol = rombug_link; /* lookup_symbol */
1206 rombug_ops.to_create_inferior = rombug_create_inferior;
c906108c
SS
1207 rombug_ops.to_post_startup_inferior = NULL;
1208 rombug_ops.to_acknowledge_created_inferior = NULL;
1209 rombug_ops.to_clone_and_follow_inferior = NULL;
1210 rombug_ops.to_post_follow_inferior_by_clone = NULL;
1211 rombug_ops.to_insert_fork_catchpoint = NULL;
1212 rombug_ops.to_remove_fork_catchpoint = NULL;
1213 rombug_ops.to_insert_vfork_catchpoint = NULL;
1214 rombug_ops.to_remove_vfork_catchpoint = NULL;
1215 rombug_ops.to_has_forked = NULL;
1216 rombug_ops.to_has_vforked = NULL;
1217 rombug_ops.to_can_follow_vfork_prior_to_exec = NULL;
1218 rombug_ops.to_post_follow_vfork = NULL;
1219 rombug_ops.to_insert_exec_catchpoint = NULL;
1220 rombug_ops.to_remove_exec_catchpoint = NULL;
1221 rombug_ops.to_has_execd = NULL;
1222 rombug_ops.to_reported_exec_events_per_exec_call = NULL;
1223 rombug_ops.to_has_exited = NULL;
c5aa993b
JM
1224 rombug_ops.to_mourn_inferior = rombug_mourn_inferior;
1225 rombug_ops.to_can_run = 0; /* can_run */
1226 rombug_ops.to_notice_signals = 0; /* notice_signals */
1227 rombug_ops.to_thread_alive = 0;
1228 rombug_ops.to_stop = 0; /* to_stop */
c906108c
SS
1229 rombug_ops.to_pid_to_exec_file = NULL;
1230 rombug_ops.to_core_file_to_sym_file = NULL;
c5aa993b
JM
1231 rombug_ops.to_stratum = process_stratum;
1232 rombug_ops.DONT_USE = 0; /* next */
1233 rombug_ops.to_has_all_memory = 1;
1234 rombug_ops.to_has_memory = 1;
1235 rombug_ops.to_has_stack = 1;
1236 rombug_ops.to_has_registers = 1;
1237 rombug_ops.to_has_execution = 1; /* has execution */
1238 rombug_ops.to_sections = 0;
1239 rombug_ops.to_sections_end = 0; /* Section pointers */
1240 rombug_ops.to_magic = OPS_MAGIC; /* Always the last thing */
1241}
c906108c
SS
1242
1243void
1244_initialize_remote_os9k ()
1245{
c5aa993b 1246 init_rombug_ops ();
c906108c
SS
1247 add_target (&rombug_ops);
1248
1249 add_show_from_set (
c5aa993b
JM
1250 add_set_cmd ("hash", no_class, var_boolean, (char *) &hashmark,
1251 "Set display of activity while downloading a file.\nWhen enabled, a period \'.\' is displayed.",
1252 &setlist),
1253 &showlist);
c906108c
SS
1254
1255 add_show_from_set (
c5aa993b
JM
1256 add_set_cmd ("timeout", no_class, var_zinteger,
1257 (char *) &timeout,
1258 "Set timeout in seconds for remote MIPS serial I/O.",
1259 &setlist),
1260 &showlist);
c906108c
SS
1261
1262 add_show_from_set (
c5aa993b
JM
1263 add_set_cmd ("remotelog", no_class, var_zinteger,
1264 (char *) &monitor_log,
1265 "Set monitor activity log on(=1) or off(=0).",
1266 &setlist),
1267 &showlist);
c906108c
SS
1268
1269 add_show_from_set (
c5aa993b
JM
1270 add_set_cmd ("remotexon", no_class, var_zinteger,
1271 (char *) &tty_xon,
1272 "Set remote tty line XON control",
1273 &setlist),
1274 &showlist);
c906108c
SS
1275
1276 add_show_from_set (
c5aa993b
JM
1277 add_set_cmd ("remotexoff", no_class, var_zinteger,
1278 (char *) &tty_xoff,
1279 "Set remote tty line XOFF control",
1280 &setlist),
1281 &showlist);
c906108c
SS
1282
1283 add_com ("rombug <command>", class_obscure, rombug_command,
c5aa993b 1284 "Send a command to the debug monitor.");
c906108c
SS
1285#if 0
1286 add_com ("connect", class_obscure, connect_command,
c5aa993b 1287 "Connect the terminal directly up to a serial based command monitor.\nUse <CR>~. or <CR>~^D to break out.");
c906108c
SS
1288#endif
1289}