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