2000-03-21 J.T. Conklin <jtc@redback.com>
[platform/upstream/binutils.git] / gdb / remote-st.c
1 /* Remote debugging interface for Tandem ST2000 phone switch, for GDB.
2    Copyright 1990, 1991, 1992 Free Software Foundation, Inc.
3    Contributed by Cygnus Support.  Written by Jim Kingdon for Cygnus.
4
5    This file is part of GDB.
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 59 Temple Place - Suite 330,
20    Boston, MA 02111-1307, USA.  */
21
22 /* This file was derived from remote-eb.c, which did a similar job, but for
23    an AMD-29K running EBMON.  That file was in turn derived from remote.c
24    as mentioned in the following comment (left in for comic relief):
25
26    "This is like remote.c but is for an esoteric situation--
27    having an a29k board in a PC hooked up to a unix machine with
28    a serial line, and running ctty com1 on the PC, through which
29    the unix machine can run ebmon.  Not to mention that the PC
30    has PC/NFS, so it can access the same executables that gdb can,
31    over the net in real time."
32
33    In reality, this module talks to a debug monitor called 'STDEBUG', which
34    runs in a phone switch.  We communicate with STDEBUG via either a direct
35    serial line, or a TCP (or possibly TELNET) stream to a terminal multiplexor,
36    which in turn talks to the phone switch. */
37
38 #include "defs.h"
39 #include "gdbcore.h"
40 #include "target.h"
41 #include "gdb_wait.h"
42 #include <signal.h>
43 #include "gdb_string.h"
44 #include <sys/types.h>
45 #include "serial.h"
46
47 extern struct target_ops st2000_ops;    /* Forward declaration */
48
49 static void st2000_close ();
50 static void st2000_fetch_register ();
51 static void st2000_store_register ();
52
53 #define LOG_FILE "st2000.log"
54 #if defined (LOG_FILE)
55 FILE *log_file;
56 #endif
57
58 static int timeout = 24;
59
60 /* Descriptor for I/O to remote machine.  Initialize it to -1 so that
61    st2000_open knows that we don't have a file open when the program
62    starts.  */
63
64 static serial_t st2000_desc;
65
66 /* Send data to stdebug.  Works just like printf. */
67
68 static void
69 printf_stdebug (char *pattern,...)
70 {
71   va_list args;
72   char buf[200];
73
74   va_start (args, pattern);
75
76   vsprintf (buf, pattern, args);
77   va_end (args);
78
79   if (SERIAL_WRITE (st2000_desc, buf, strlen (buf)))
80     fprintf (stderr, "SERIAL_WRITE failed: %s\n", safe_strerror (errno));
81 }
82
83 /* Read a character from the remote system, doing all the fancy timeout
84    stuff.  */
85
86 static int
87 readchar (timeout)
88      int timeout;
89 {
90   int c;
91
92   c = SERIAL_READCHAR (st2000_desc, timeout);
93
94 #ifdef LOG_FILE
95   putc (c & 0x7f, log_file);
96 #endif
97
98   if (c >= 0)
99     return c & 0x7f;
100
101   if (c == SERIAL_TIMEOUT)
102     {
103       if (timeout == 0)
104         return c;               /* Polls shouldn't generate timeout errors */
105
106       error ("Timeout reading from remote system.");
107     }
108
109   perror_with_name ("remote-st2000");
110 }
111
112 /* Scan input from the remote system, until STRING is found.  If DISCARD is
113    non-zero, then discard non-matching input, else print it out.
114    Let the user break out immediately.  */
115 static void
116 expect (string, discard)
117      char *string;
118      int discard;
119 {
120   char *p = string;
121   int c;
122
123   immediate_quit = 1;
124   while (1)
125     {
126       c = readchar (timeout);
127       if (c == *p++)
128         {
129           if (*p == '\0')
130             {
131               immediate_quit = 0;
132               return;
133             }
134         }
135       else
136         {
137           if (!discard)
138             {
139               fwrite (string, 1, (p - 1) - string, stdout);
140               putchar ((char) c);
141               fflush (stdout);
142             }
143           p = string;
144         }
145     }
146 }
147
148 /* Keep discarding input until we see the STDEBUG prompt.
149
150    The convention for dealing with the prompt is that you
151    o give your command
152    o *then* wait for the prompt.
153
154    Thus the last thing that a procedure does with the serial line
155    will be an expect_prompt().  Exception:  st2000_resume does not
156    wait for the prompt, because the terminal is being handed over
157    to the inferior.  However, the next thing which happens after that
158    is a st2000_wait which does wait for the prompt.
159    Note that this includes abnormal exit, e.g. error().  This is
160    necessary to prevent getting into states from which we can't
161    recover.  */
162 static void
163 expect_prompt (discard)
164      int discard;
165 {
166 #if defined (LOG_FILE)
167   /* This is a convenient place to do this.  The idea is to do it often
168      enough that we never lose much data if we terminate abnormally.  */
169   fflush (log_file);
170 #endif
171   expect ("dbug> ", discard);
172 }
173
174 /* Get a hex digit from the remote system & return its value.
175    If ignore_space is nonzero, ignore spaces (not newline, tab, etc).  */
176 static int
177 get_hex_digit (ignore_space)
178      int ignore_space;
179 {
180   int ch;
181   while (1)
182     {
183       ch = readchar (timeout);
184       if (ch >= '0' && ch <= '9')
185         return ch - '0';
186       else if (ch >= 'A' && ch <= 'F')
187         return ch - 'A' + 10;
188       else if (ch >= 'a' && ch <= 'f')
189         return ch - 'a' + 10;
190       else if (ch == ' ' && ignore_space)
191         ;
192       else
193         {
194           expect_prompt (1);
195           error ("Invalid hex digit from remote system.");
196         }
197     }
198 }
199
200 /* Get a byte from stdebug and put it in *BYT.  Accept any number
201    leading spaces.  */
202 static void
203 get_hex_byte (byt)
204      char *byt;
205 {
206   int val;
207
208   val = get_hex_digit (1) << 4;
209   val |= get_hex_digit (0);
210   *byt = val;
211 }
212
213 /* Get N 32-bit words from remote, each preceded by a space,
214    and put them in registers starting at REGNO.  */
215 static void
216 get_hex_regs (n, regno)
217      int n;
218      int regno;
219 {
220   long val;
221   int i;
222
223   for (i = 0; i < n; i++)
224     {
225       int j;
226
227       val = 0;
228       for (j = 0; j < 8; j++)
229         val = (val << 4) + get_hex_digit (j == 0);
230       supply_register (regno++, (char *) &val);
231     }
232 }
233
234 /* This is called not only when we first attach, but also when the
235    user types "run" after having attached.  */
236 static void
237 st2000_create_inferior (execfile, args, env)
238      char *execfile;
239      char *args;
240      char **env;
241 {
242   int entry_pt;
243
244   if (args && *args)
245     error ("Can't pass arguments to remote STDEBUG process");
246
247   if (execfile == 0 || exec_bfd == 0)
248     error ("No executable file specified");
249
250   entry_pt = (int) bfd_get_start_address (exec_bfd);
251
252 /* The "process" (board) is already stopped awaiting our commands, and
253    the program is already downloaded.  We just set its PC and go.  */
254
255   clear_proceed_status ();
256
257   /* Tell wait_for_inferior that we've started a new process.  */
258   init_wait_for_inferior ();
259
260   /* Set up the "saved terminal modes" of the inferior
261      based on what modes we are starting it with.  */
262   target_terminal_init ();
263
264   /* Install inferior's terminal modes.  */
265   target_terminal_inferior ();
266
267   /* insert_step_breakpoint ();  FIXME, do we need this?  */
268   /* Let 'er rip... */
269   proceed ((CORE_ADDR) entry_pt, TARGET_SIGNAL_DEFAULT, 0);
270 }
271
272 /* Open a connection to a remote debugger.
273    NAME is the filename used for communication.  */
274
275 static int baudrate = 9600;
276 static char dev_name[100];
277
278 static void
279 st2000_open (args, from_tty)
280      char *args;
281      int from_tty;
282 {
283   int n;
284   char junk[100];
285
286   target_preopen (from_tty);
287
288   n = sscanf (args, " %s %d %s", dev_name, &baudrate, junk);
289
290   if (n != 2)
291     error ("Bad arguments.  Usage: target st2000 <device> <speed>\n\
292 or target st2000 <host> <port>\n");
293
294   st2000_close (0);
295
296   st2000_desc = SERIAL_OPEN (dev_name);
297
298   if (!st2000_desc)
299     perror_with_name (dev_name);
300
301   SERIAL_SETBAUDRATE (st2000_desc, baudrate);
302
303   SERIAL_RAW (st2000_desc);
304
305   push_target (&st2000_ops);
306
307 #if defined (LOG_FILE)
308   log_file = fopen (LOG_FILE, "w");
309   if (log_file == NULL)
310     perror_with_name (LOG_FILE);
311 #endif
312
313   /* Hello?  Are you there?  */
314   printf_stdebug ("\003");      /* ^C wakes up dbug */
315
316   expect_prompt (1);
317
318   if (from_tty)
319     printf ("Remote %s connected to %s\n", target_shortname,
320             dev_name);
321 }
322
323 /* Close out all files and local state before this target loses control. */
324
325 static void
326 st2000_close (quitting)
327      int quitting;
328 {
329   SERIAL_CLOSE (st2000_desc);
330
331 #if defined (LOG_FILE)
332   if (log_file)
333     {
334       if (ferror (log_file))
335         fprintf (stderr, "Error writing log file.\n");
336       if (fclose (log_file) != 0)
337         fprintf (stderr, "Error closing log file.\n");
338     }
339 #endif
340 }
341
342 /* Terminate the open connection to the remote debugger.
343    Use this when you want to detach and do something else
344    with your gdb.  */
345 static void
346 st2000_detach (from_tty)
347      int from_tty;
348 {
349   pop_target ();                /* calls st2000_close to do the real work */
350   if (from_tty)
351     printf ("Ending remote %s debugging\n", target_shortname);
352 }
353
354 /* Tell the remote machine to resume.  */
355
356 static void
357 st2000_resume (pid, step, sig)
358      int pid, step;
359      enum target_signal sig;
360 {
361   if (step)
362     {
363       printf_stdebug ("ST\r");
364       /* Wait for the echo.  */
365       expect ("ST\r", 1);
366     }
367   else
368     {
369       printf_stdebug ("GO\r");
370       /* Swallow the echo.  */
371       expect ("GO\r", 1);
372     }
373 }
374
375 /* Wait until the remote machine stops, then return,
376    storing status in STATUS just as `wait' would.  */
377
378 static int
379 st2000_wait (status)
380      struct target_waitstatus *status;
381 {
382   int old_timeout = timeout;
383
384   status->kind = TARGET_WAITKIND_EXITED;
385   status->value.integer = 0;
386
387   timeout = 0;                  /* Don't time out -- user program is running. */
388
389   expect_prompt (0);            /* Wait for prompt, outputting extraneous text */
390
391   status->kind = TARGET_WAITKIND_STOPPED;
392   status->value.sig = TARGET_SIGNAL_TRAP;
393
394   timeout = old_timeout;
395
396   return 0;
397 }
398
399 /* Return the name of register number REGNO in the form input and output by
400    STDEBUG.  Currently, REGISTER_NAMES just happens to contain exactly what
401    STDEBUG wants.  Lets take advantage of that just as long as possible! */
402
403 static char *
404 get_reg_name (regno)
405      int regno;
406 {
407   static char buf[50];
408   const char *p;
409   char *b;
410
411   b = buf;
412
413   for (p = REGISTER_NAME (regno); *p; p++)
414     *b++ = toupper (*p);
415   *b = '\000';
416
417   return buf;
418 }
419
420 /* Read the remote registers into the block REGS.  */
421
422 static void
423 st2000_fetch_registers ()
424 {
425   int regno;
426
427   /* Yeah yeah, I know this is horribly inefficient.  But it isn't done
428      very often...  I'll clean it up later.  */
429
430   for (regno = 0; regno <= PC_REGNUM; regno++)
431     st2000_fetch_register (regno);
432 }
433
434 /* Fetch register REGNO, or all registers if REGNO is -1.
435    Returns errno value.  */
436 static void
437 st2000_fetch_register (regno)
438      int regno;
439 {
440   if (regno == -1)
441     st2000_fetch_registers ();
442   else
443     {
444       char *name = get_reg_name (regno);
445       printf_stdebug ("DR %s\r", name);
446       expect (name, 1);
447       expect (" : ", 1);
448       get_hex_regs (1, regno);
449       expect_prompt (1);
450     }
451   return;
452 }
453
454 /* Store the remote registers from the contents of the block REGS.  */
455
456 static void
457 st2000_store_registers ()
458 {
459   int regno;
460
461   for (regno = 0; regno <= PC_REGNUM; regno++)
462     st2000_store_register (regno);
463
464   registers_changed ();
465 }
466
467 /* Store register REGNO, or all if REGNO == 0.
468    Return errno value.  */
469 static void
470 st2000_store_register (regno)
471      int regno;
472 {
473   if (regno == -1)
474     st2000_store_registers ();
475   else
476     {
477       printf_stdebug ("PR %s %x\r", get_reg_name (regno),
478                       read_register (regno));
479
480       expect_prompt (1);
481     }
482 }
483
484 /* Get ready to modify the registers array.  On machines which store
485    individual registers, this doesn't need to do anything.  On machines
486    which store all the registers in one fell swoop, this makes sure
487    that registers contains all the registers from the program being
488    debugged.  */
489
490 static void
491 st2000_prepare_to_store ()
492 {
493   /* Do nothing, since we can store individual regs */
494 }
495
496 static void
497 st2000_files_info ()
498 {
499   printf ("\tAttached to %s at %d baud.\n",
500           dev_name, baudrate);
501 }
502
503 /* Copy LEN bytes of data from debugger memory at MYADDR
504    to inferior's memory at MEMADDR.  Returns length moved.  */
505 static int
506 st2000_write_inferior_memory (memaddr, myaddr, len)
507      CORE_ADDR memaddr;
508      unsigned char *myaddr;
509      int len;
510 {
511   int i;
512
513   for (i = 0; i < len; i++)
514     {
515       printf_stdebug ("PM.B %x %x\r", memaddr + i, myaddr[i]);
516       expect_prompt (1);
517     }
518   return len;
519 }
520
521 /* Read LEN bytes from inferior memory at MEMADDR.  Put the result
522    at debugger address MYADDR.  Returns length moved.  */
523 static int
524 st2000_read_inferior_memory (memaddr, myaddr, len)
525      CORE_ADDR memaddr;
526      char *myaddr;
527      int len;
528 {
529   int i;
530
531   /* Number of bytes read so far.  */
532   int count;
533
534   /* Starting address of this pass.  */
535   unsigned long startaddr;
536
537   /* Number of bytes to read in this pass.  */
538   int len_this_pass;
539
540   /* Note that this code works correctly if startaddr is just less
541      than UINT_MAX (well, really CORE_ADDR_MAX if there was such a
542      thing).  That is, something like
543      st2000_read_bytes (CORE_ADDR_MAX - 4, foo, 4)
544      works--it never adds len to memaddr and gets 0.  */
545   /* However, something like
546      st2000_read_bytes (CORE_ADDR_MAX - 3, foo, 4)
547      doesn't need to work.  Detect it and give up if there's an attempt
548      to do that.  */
549   if (((memaddr - 1) + len) < memaddr)
550     {
551       errno = EIO;
552       return 0;
553     }
554
555   startaddr = memaddr;
556   count = 0;
557   while (count < len)
558     {
559       len_this_pass = 16;
560       if ((startaddr % 16) != 0)
561         len_this_pass -= startaddr % 16;
562       if (len_this_pass > (len - count))
563         len_this_pass = (len - count);
564
565       printf_stdebug ("DI.L %x %x\r", startaddr, len_this_pass);
566       expect (":  ", 1);
567
568       for (i = 0; i < len_this_pass; i++)
569         get_hex_byte (&myaddr[count++]);
570
571       expect_prompt (1);
572
573       startaddr += len_this_pass;
574     }
575   return len;
576 }
577
578 /* FIXME-someday!  Merge these two.  */
579 static int
580 st2000_xfer_inferior_memory (memaddr, myaddr, len, write, target)
581      CORE_ADDR memaddr;
582      char *myaddr;
583      int len;
584      int write;
585      struct target_ops *target; /* ignored */
586 {
587   if (write)
588     return st2000_write_inferior_memory (memaddr, myaddr, len);
589   else
590     return st2000_read_inferior_memory (memaddr, myaddr, len);
591 }
592
593 static void
594 st2000_kill (args, from_tty)
595      char *args;
596      int from_tty;
597 {
598   return;                       /* Ignore attempts to kill target system */
599 }
600
601 /* Clean up when a program exits.
602
603    The program actually lives on in the remote processor's RAM, and may be
604    run again without a download.  Don't leave it full of breakpoint
605    instructions.  */
606
607 static void
608 st2000_mourn_inferior ()
609 {
610   remove_breakpoints ();
611   unpush_target (&st2000_ops);
612   generic_mourn_inferior ();    /* Do all the proper things now */
613 }
614
615 #define MAX_STDEBUG_BREAKPOINTS 16
616
617 static CORE_ADDR breakaddr[MAX_STDEBUG_BREAKPOINTS] =
618 {0};
619
620 static int
621 st2000_insert_breakpoint (addr, shadow)
622      CORE_ADDR addr;
623      char *shadow;
624 {
625   int i;
626   CORE_ADDR bp_addr = addr;
627   int bp_size = 0;
628
629   BREAKPOINT_FROM_PC (&bp_addr, &bp_size);
630
631   for (i = 0; i <= MAX_STDEBUG_BREAKPOINTS; i++)
632     if (breakaddr[i] == 0)
633       {
634         breakaddr[i] = addr;
635
636         st2000_read_inferior_memory (bp_addr, shadow, bp_size);
637         printf_stdebug ("BR %x H\r", addr);
638         expect_prompt (1);
639         return 0;
640       }
641
642   fprintf (stderr, "Too many breakpoints (> 16) for STDBUG\n");
643   return 1;
644 }
645
646 static int
647 st2000_remove_breakpoint (addr, shadow)
648      CORE_ADDR addr;
649      char *shadow;
650 {
651   int i;
652
653   for (i = 0; i < MAX_STDEBUG_BREAKPOINTS; i++)
654     if (breakaddr[i] == addr)
655       {
656         breakaddr[i] = 0;
657
658         printf_stdebug ("CB %d\r", i);
659         expect_prompt (1);
660         return 0;
661       }
662
663   fprintf (stderr, "Can't find breakpoint associated with 0x%x\n", addr);
664   return 1;
665 }
666
667
668 /* Put a command string, in args, out to STDBUG.  Output from STDBUG is placed
669    on the users terminal until the prompt is seen. */
670
671 static void
672 st2000_command (args, fromtty)
673      char *args;
674      int fromtty;
675 {
676   if (!st2000_desc)
677     error ("st2000 target not open.");
678
679   if (!args)
680     error ("Missing command.");
681
682   printf_stdebug ("%s\r", args);
683   expect_prompt (0);
684 }
685
686 /* Connect the user directly to STDBUG.  This command acts just like the
687    'cu' or 'tip' command.  Use <CR>~. or <CR>~^D to break out.  */
688
689 /*static struct ttystate ttystate; */
690
691 static void
692 cleanup_tty ()
693 {
694   printf ("\r\n[Exiting connect mode]\r\n");
695 /*  SERIAL_RESTORE(0, &ttystate); */
696 }
697
698 #if 0
699 /* This all should now be in serial.c */
700
701 static void
702 connect_command (args, fromtty)
703      char *args;
704      int fromtty;
705 {
706   fd_set readfds;
707   int numfds;
708   int c;
709   char cur_esc = 0;
710
711   dont_repeat ();
712
713   if (st2000_desc < 0)
714     error ("st2000 target not open.");
715
716   if (args)
717     fprintf ("This command takes no args.  They have been ignored.\n");
718
719   printf ("[Entering connect mode.  Use ~. or ~^D to escape]\n");
720
721   serial_raw (0, &ttystate);
722
723   make_cleanup (cleanup_tty, 0);
724
725   FD_ZERO (&readfds);
726
727   while (1)
728     {
729       do
730         {
731           FD_SET (0, &readfds);
732           FD_SET (DEPRECATED_SERIAL_FD (st2000_desc), &readfds);
733           numfds = select (sizeof (readfds) * 8, &readfds, 0, 0, 0);
734         }
735       while (numfds == 0);
736
737       if (numfds < 0)
738         perror_with_name ("select");
739
740       if (FD_ISSET (0, &readfds))
741         {                       /* tty input, send to stdebug */
742           c = getchar ();
743           if (c < 0)
744             perror_with_name ("connect");
745
746           printf_stdebug ("%c", c);
747           switch (cur_esc)
748             {
749             case 0:
750               if (c == '\r')
751                 cur_esc = c;
752               break;
753             case '\r':
754               if (c == '~')
755                 cur_esc = c;
756               else
757                 cur_esc = 0;
758               break;
759             case '~':
760               if (c == '.' || c == '\004')
761                 return;
762               else
763                 cur_esc = 0;
764             }
765         }
766
767       if (FD_ISSET (DEPRECATED_SERIAL_FD (st2000_desc), &readfds))
768         {
769           while (1)
770             {
771               c = readchar (0);
772               if (c < 0)
773                 break;
774               putchar (c);
775             }
776           fflush (stdout);
777         }
778     }
779 }
780 #endif /* 0 */
781
782 /* Define the target subroutine names */
783
784 struct target_ops st2000_ops;
785
786 static void
787 init_st2000_ops (void)
788 {
789   st2000_ops.to_shortname = "st2000";
790   st2000_ops.to_longname = "Remote serial Tandem ST2000 target";
791   st2000_ops.to_doc = "Use a remote computer running STDEBUG connected by a serial line;\n\
792 or a network connection.\n\
793 Arguments are the name of the device for the serial line,\n\
794 the speed to connect at in bits per second.";
795   st2000_ops.to_open = st2000_open;
796   st2000_ops.to_close = st2000_close;
797   st2000_ops.to_attach = 0;
798   st2000_run_ops.to_post_attach = NULL;
799   st2000_ops.to_require_attach = NULL;
800   st2000_ops.to_detach = st2000_detach;
801   st2000_ops.to_require_detach = NULL;
802   st2000_ops.to_resume = st2000_resume;
803   st2000_ops.to_wait = st2000_wait;
804   st2000_ops.to_post_wait = NULL;
805   st2000_ops.to_fetch_registers = st2000_fetch_register;
806   st2000_ops.to_store_registers = st2000_store_register;
807   st2000_ops.to_prepare_to_store = st2000_prepare_to_store;
808   st2000_ops.to_xfer_memory = st2000_xfer_inferior_memory;
809   st2000_ops.to_files_info = st2000_files_info;
810   st2000_ops.to_insert_breakpoint = st2000_insert_breakpoint;
811   st2000_ops.to_remove_breakpoint = st2000_remove_breakpoint;   /* Breakpoints */
812   st2000_ops.to_terminal_init = 0;
813   st2000_ops.to_terminal_inferior = 0;
814   st2000_ops.to_terminal_ours_for_output = 0;
815   st2000_ops.to_terminal_ours = 0;
816   st2000_ops.to_terminal_info = 0;      /* Terminal handling */
817   st2000_ops.to_kill = st2000_kill;
818   st2000_ops.to_load = 0;       /* load */
819   st2000_ops.to_lookup_symbol = 0;      /* lookup_symbol */
820   st2000_ops.to_create_inferior = st2000_create_inferior;
821   st2000_ops.to_post_startup_inferior = NULL;
822   st2000_ops.to_acknowledge_created_inferior = NULL;
823   st2000_ops.to_clone_and_follow_inferior = NULL;
824   st2000_ops.to_post_follow_inferior_by_clone = NULL;
825   st2000_run_ops.to_insert_fork_catchpoint = NULL;
826   st2000_run_ops.to_remove_fork_catchpoint = NULL;
827   st2000_run_ops.to_insert_vfork_catchpoint = NULL;
828   st2000_run_ops.to_remove_vfork_catchpoint = NULL;
829   st2000_ops.to_has_forked = NULL;
830   st2000_ops.to_has_vforked = NULL;
831   st2000_run_ops.to_can_follow_vfork_prior_to_exec = NULL;
832   st2000_ops.to_post_follow_vfork = NULL;
833   st2000_run_ops.to_insert_exec_catchpoint = NULL;
834   st2000_run_ops.to_remove_exec_catchpoint = NULL;
835   st2000_run_ops.to_has_execd = NULL;
836   st2000_run_ops.to_reported_exec_events_per_exec_call = NULL;
837   st2000_run_ops.to_has_exited = NULL;
838   st2000_ops.to_mourn_inferior = st2000_mourn_inferior;
839   st2000_ops.to_can_run = 0;    /* can_run */
840   st2000_ops.to_notice_signals = 0;     /* notice_signals */
841   st2000_ops.to_thread_alive = 0;       /* thread alive */
842   st2000_ops.to_stop = 0;       /* to_stop */
843   st2000_ops.to_pid_to_exec_file = NULL;
844   st2000_run_ops.to_core_file_to_sym_file = NULL;
845   st2000_ops.to_stratum = process_stratum;
846   st2000_ops.DONT_USE = 0;      /* next */
847   st2000_ops.to_has_all_memory = 1;
848   st2000_ops.to_has_memory = 1;
849   st2000_ops.to_has_stack = 1;
850   st2000_ops.to_has_registers = 1;
851   st2000_ops.to_has_execution = 1;      /* all mem, mem, stack, regs, exec */
852   st2000_ops.to_sections = 0;
853   st2000_ops.to_sections_end = 0;       /* Section pointers */
854   st2000_ops.to_magic = OPS_MAGIC;      /* Always the last thing */
855 };
856
857 void
858 _initialize_remote_st2000 ()
859 {
860   init_st2000_ops ();
861   add_target (&st2000_ops);
862   add_com ("st2000 <command>", class_obscure, st2000_command,
863            "Send a command to the STDBUG monitor.");
864   add_com ("connect", class_obscure, connect_command,
865            "Connect the terminal directly up to the STDBUG command monitor.\n\
866 Use <CR>~. or <CR>~^D to break out.");
867 }