/* Remote debugging interface for AMD 29000 EBMON on IBM PC, for GDB.
- Copyright 1990-1991 Free Software Foundation, Inc.
+ Copyright 1990, 1991, 1992 Free Software Foundation, Inc.
Contributed by Cygnus Support. Written by Jim Kingdon for Cygnus.
This file is part of GDB.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 1, or (at your option)
-any later version.
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with this program; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* This is like remote.c but is for an esoteric situation--
- having a 29k board in a PC hooked up to a unix machine with
+ having a a29k board in a PC hooked up to a unix machine with
a serial line, and running ctty com1 on the PC, through which
the unix machine can run ebmon. Not to mention that the PC
has PC/NFS, so it can access the same executables that gdb can,
over the net in real time. */
-#include <stdio.h>
-#include <string.h>
#include "defs.h"
-#include "tm-29k.h"
-#include "param-no-tm.h"
+#include "gdb_string.h"
+
#include "inferior.h"
+#include "bfd.h"
+#include "symfile.h"
#include "wait.h"
#include "value.h"
#include <ctype.h>
#include <errno.h>
#include "terminal.h"
#include "target.h"
-
-extern void add_syms_addr_command ();
-extern struct value *call_function_by_hand();
+#include "gdbcore.h"
extern struct target_ops eb_ops; /* Forward declaration */
+static void eb_close();
+
#define LOG_FILE "eb.log"
#if defined (LOG_FILE)
FILE *log_file;
#endif
-static int timeout = 5;
+static int timeout = 24;
/* Descriptor for I/O to remote machine. Initialize it to -1 so that
eb_open knows that we don't have a file open when the program
val = 0;
for (j = 0; j < 8; j++)
val = (val << 4) + get_hex_digit (j == 0);
- supply_register (regno++, &val);
+ supply_register (regno++, (char *) &val);
}
}
/* This is called not only when we first attach, but also when the
user types "run" after having attached. */
-void
-eb_start (inferior_args)
-char *inferior_args;
+static void
+eb_create_inferior (execfile, args, env)
+ char *execfile;
+ char *args;
+ char **env;
{
- /* OK, now read in the file. Y=read, C=COFF, D=no symbols
- 0=start address, %s=filename. */
+ int entry_pt;
- fprintf (eb_stream, "YC D,0:%s", prog_name);
+ if (args && *args)
+ error ("Can't pass arguments to remote EBMON process");
- if (inferior_args != NULL)
- fprintf(eb_stream, " %s", inferior_args);
+ if (execfile == 0 || exec_bfd == 0)
+ error ("No executable file specified");
- fprintf (eb_stream, "\n");
- fflush (eb_stream);
+ entry_pt = (int) bfd_get_start_address (exec_bfd);
- expect_prompt ();
+ {
+ /* OK, now read in the file. Y=read, C=COFF, D=no symbols
+ 0=start address, %s=filename. */
+
+ fprintf (eb_stream, "YC D,0:%s", prog_name);
+
+ if (args != NULL)
+ fprintf(eb_stream, " %s", args);
+
+ fprintf (eb_stream, "\n");
+ fflush (eb_stream);
+
+ expect_prompt ();
+
+ need_gi = 1;
+ }
- need_gi = 1;
+/* The "process" (board) is already stopped awaiting our commands, and
+ the program is already downloaded. We just set its PC and go. */
+
+ clear_proceed_status ();
+
+ /* Tell wait_for_inferior that we've started a new process. */
+ init_wait_for_inferior ();
+
+ /* Set up the "saved terminal modes" of the inferior
+ based on what modes we are starting it with. */
+ target_terminal_init ();
+
+ /* Install inferior's terminal modes. */
+ target_terminal_inferior ();
+
+ /* insert_step_breakpoint (); FIXME, do we need this? */
+ proceed ((CORE_ADDR)entry_pt, TARGET_SIGNAL_DEFAULT, 0); /* Let 'er rip... */
}
/* Translate baud rates from integers to damn B_codes. Unix should
char *p;
+ target_preopen (from_tty);
+
/* Find the first whitespace character, it separates dev_name from
prog_name. */
if (name == 0)
/* Close out all files and local state before this target loses control. */
-void
+static void
eb_close (quitting)
int quitting;
{
eb_desc = -1;
#if defined (LOG_FILE)
- if (ferror (log_file))
- printf ("Error writing log file.\n");
- if (fclose (log_file) != 0)
- printf ("Error closing log file.\n");
+ if (log_file) {
+ if (ferror (log_file))
+ printf ("Error writing log file.\n");
+ if (fclose (log_file) != 0)
+ printf ("Error closing log file.\n");
+ }
#endif
}
/* Tell the remote machine to resume. */
void
-eb_resume (step, sig)
- int step, sig;
+eb_resume (pid, step, sig)
+ int pid, step;
+ enum target_signal sig;
{
if (step)
{
int
eb_wait (status)
- WAITTYPE *status;
+ struct target_waitstatus *status;
{
/* Strings to look for. '?' means match any single character.
Note that with the algorithm we use, the initial character
int old_timeout = timeout;
- WSETEXIT ((*status), 0);
+ status->kind = TARGET_WAITKIND_EXITED;
+ status->value.integer = 0;
if (need_artificial_trap != 0)
{
- WSETSTOP ((*status), SIGTRAP);
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_TRAP;
need_artificial_trap--;
return 0;
}
}
expect_prompt ();
if (*bp== '\0')
- WSETSTOP ((*status), SIGTRAP);
+ {
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_TRAP;
+ }
else
- WSETEXIT ((*status), 0);
+ {
+ status->kind = TARGET_WAITKIND_EXITED;
+ status->value.integer = 0;
+ }
timeout = old_timeout;
return 0;
/* There doesn't seem to be any way to get these. */
{
int val = -1;
- supply_register (FPE_REGNUM, &val);
- supply_register (INT_REGNUM, &val);
- supply_register (FPS_REGNUM, &val);
- supply_register (EXO_REGNUM, &val);
+ supply_register (FPE_REGNUM, (char *) &val);
+ supply_register (INTE_REGNUM, (char *) &val);
+ supply_register (FPS_REGNUM, (char *) &val);
+ supply_register (EXO_REGNUM, (char *) &val);
}
write (eb_desc, "dw gr1,gr1\n", 11);
/* Fetch register REGNO, or all registers if REGNO is -1.
Returns errno value. */
-int
+void
eb_fetch_register (regno)
int regno;
{
get_hex_regs (1, regno);
expect_prompt ();
}
- return 0;
+ return;
}
/* Store the remote registers from the contents of the block REGS. */
/* Store register REGNO, or all if REGNO == 0.
Return errno value. */
-int
+void
eb_store_register (regno)
int regno;
{
registers_changed ();
expect_prompt ();
}
- return 0;
}
/* Get ready to modify the registers array. On machines which store
/* Do nothing, since we can store individual regs */
}
-/* FIXME! Merge these two. */
+
+/* FIXME-someday! Merge these two. */
int
-eb_xfer_inferior_memory (memaddr, myaddr, len, write)
+eb_xfer_inferior_memory (memaddr, myaddr, len, write, target)
CORE_ADDR memaddr;
char *myaddr;
int len;
int write;
+ struct target_ops *target; /* ignored */
{
if (write)
return eb_write_inferior_memory (memaddr, myaddr, len);
else
- return eb_write_inferior_memory (memaddr, myaddr, len);
+ return eb_read_inferior_memory (memaddr, myaddr, len);
}
void
}
/* Copy LEN bytes of data from debugger memory at MYADDR
- to inferior's memory at MEMADDR. Returns errno value. */
+ to inferior's memory at MEMADDR. Returns length moved. */
int
eb_write_inferior_memory (memaddr, myaddr, len)
CORE_ADDR memaddr;
else
fprintf (eb_stream, "%x,", ((unsigned char *)myaddr)[i]);
}
- return 0;
+ return len;
}
/* Read LEN bytes from inferior memory at MEMADDR. Put the result
- at debugger address MYADDR. Returns errno value. */
+ at debugger address MYADDR. Returns length moved. */
int
eb_read_inferior_memory(memaddr, myaddr, len)
CORE_ADDR memaddr;
eb_read_bytes (CORE_ADDR_MAX - 3, foo, 4)
doesn't need to work. Detect it and give up if there's an attempt
to do that. */
- if (((memaddr - 1) + len) < memaddr)
- return EIO;
+ if (((memaddr - 1) + len) < memaddr) {
+ errno = EIO;
+ return 0;
+ }
startaddr = memaddr;
count = 0;
startaddr += len_this_pass;
}
- return 0;
+ return len;
}
+static void
+eb_kill (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ return; /* Ignore attempts to kill target system */
+}
+
+/* Clean up when a program exits.
+
+ The program actually lives on in the remote processor's RAM, and may be
+ run again without a download. Don't leave it full of breakpoint
+ instructions. */
+
+void
+eb_mourn_inferior ()
+{
+ remove_breakpoints ();
+ unpush_target (&eb_ops);
+ generic_mourn_inferior (); /* Do all the proper things now */
+}
/* Define the target subroutine names */
-struct target_ops eb_ops = {
- "amd-eb", "Remote serial AMD EBMON target",
- eb_open, eb_close,
- 0, eb_detach, eb_resume, eb_wait,
- eb_fetch_register, eb_store_register,
- eb_prepare_to_store, 0, 0, /* conv_to, conv_from */
- eb_xfer_inferior_memory, eb_files_info,
- 0, 0, /* Breakpoints */
- 0, 0, 0, 0, 0, /* Terminal handling */
- 0, /* FIXME, kill */
- 0, add_syms_addr_command, /* load */
- call_function_by_hand,
- 0, /* lookup_symbol */
- 0, /* create_inferior FIXME, eb_start here or something? */
- 0, /* mourn_inferior FIXME */
- process_stratum, 0, /* next */
- 1, 1, 1, 1, 1, /* all mem, mem, stack, regs, exec */
- OPS_MAGIC, /* Always the last thing */
+struct target_ops eb_ops ;
+
+static void
+init_eb_ops(void)
+{
+ eb_ops.to_shortname = "amd-eb";
+ eb_ops.to_longname = "Remote serial AMD EBMON target";
+ eb_ops.to_doc = "Use a remote computer running EBMON connected by a serial line.\n\
+Arguments are the name of the device for the serial line,\n\
+the speed to connect at in bits per second, and the filename of the\n\
+executable as it exists on the remote computer. For example,\n\
+target amd-eb /dev/ttya 9600 demo",
+ eb_ops.to_open = eb_open;
+ eb_ops.to_close = eb_close;
+ eb_ops.to_attach = 0;
+ eb_ops.to_post_attach = NULL;
+ eb_ops.to_require_attach = NULL;
+ eb_ops.to_detach = eb_detach;
+ eb_ops.to_require_detach = NULL;
+ eb_ops.to_resume = eb_resume;
+ eb_ops.to_wait = eb_wait;
+ eb_ops.to_post_wait = NULL;
+ eb_ops.to_fetch_registers = eb_fetch_register;
+ eb_ops.to_store_registers = eb_store_register;
+ eb_ops.to_prepare_to_store = eb_prepare_to_store;
+ eb_ops.to_xfer_memory = eb_xfer_inferior_memory;
+ eb_ops.to_files_info = eb_files_info;
+ eb_ops.to_insert_breakpoint = 0;
+ eb_ops.to_remove_breakpoint = 0; /* Breakpoints */
+ eb_ops.to_terminal_init = 0;
+ eb_ops.to_terminal_inferior = 0;
+ eb_ops.to_terminal_ours_for_output = 0;
+ eb_ops.to_terminal_ours = 0;
+ eb_ops.to_terminal_info = 0; /* Terminal handling */
+ eb_ops.to_kill = eb_kill;
+ eb_ops.to_load = generic_load; /* load */
+ eb_ops.to_lookup_symbol = 0; /* lookup_symbol */
+ eb_ops.to_create_inferior = eb_create_inferior;
+ eb_ops.to_post_startup_inferior = NULL;
+ eb_ops.to_acknowledge_created_inferior = NULL;
+ eb_ops.to_clone_and_follow_inferior = NULL;
+ eb_ops.to_post_follow_inferior_by_clone = NULL;
+ eb_ops.to_insert_fork_catchpoint = NULL;
+ eb_ops.to_remove_fork_catchpoint = NULL;
+ eb_ops.to_insert_vfork_catchpoint = NULL;
+ eb_ops.to_remove_vfork_catchpoint = NULL;
+ eb_ops.to_has_forked = NULL;
+ eb_ops.to_has_vforked = NULL;
+ eb_ops.to_can_follow_vfork_prior_to_exec = NULL;
+ eb_ops.to_post_follow_vfork = NULL;
+ eb_ops.to_insert_exec_catchpoint = NULL;
+ eb_ops.to_remove_exec_catchpoint = NULL;
+ eb_ops.to_has_execd = NULL;
+ eb_ops.to_reported_exec_events_per_exec_call = NULL;
+ eb_ops.to_has_exited = NULL;
+ eb_ops.to_mourn_inferior = eb_mourn_inferior;
+ eb_ops.to_can_run = 0; /* can_run */
+ eb_ops.to_notice_signals = 0; /* notice_signals */
+ eb_ops.to_thread_alive = 0; /* thread-alive */
+ eb_ops.to_stop = 0; /* to_stop */
+ eb_ops.to_pid_to_exec_file = NULL;
+ eb_ops.to_core_file_to_sym_file = NULL;
+ eb_ops.to_stratum = process_stratum;
+ eb_ops.DONT_USE = 0; /* next */
+ eb_ops.to_has_all_memory = 1;
+ eb_ops.to_has_memory = 1;
+ eb_ops.to_has_stack = 1;
+ eb_ops.to_has_registers = 1;
+ eb_ops.to_has_execution = 1; /* all mem, mem, stack, regs, exec */
+ eb_ops.to_sections = 0; /* sections */
+ eb_ops.to_sections_end = 0; /* sections end */
+ eb_ops.to_magic = OPS_MAGIC; /* Always the last thing */
};
void
_initialize_remote_eb ()
{
+ init_eb_ops() ;
add_target (&eb_ops);
}