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