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