#include "objfiles.h"
#include "gdb-stabs.h"
#include "gdbthread.h"
-
+#include "gdbcore.h"
#include "dcache.h"
#ifdef USG
static void sds_mourn PARAMS ((void));
-static void sds_restart PARAMS ((void));
-
static void sds_create_inferior PARAMS ((char *, char *, char **));
+static void sds_load PARAMS ((char *, int));
+
static int getmessage PARAMS ((unsigned char *, int));
static int putmessage PARAMS ((unsigned char *, int));
was static int sds_timeout = 2; */
static int sds_timeout = 2;
-/* This variable chooses whether to send a ^C or a break when the user
- requests program interruption. Although ^C is usually what remote
- systems expect, and that is the default here, sometimes a break is
- preferable instead. */
-
-static int sds_break;
-
/* Descriptor for I/O to remote machine. Initialize it to NULL so
that sds_open knows that we don't have a file open when the program
starts. */
static serial_t sds_desc = NULL;
-/* Having this larger than 400 causes us to be incompatible with m68k-stub.c
- and i386-stub.c. Normally, no one would notice because it only matters
- for writing large chunks of memory (e.g. in downloads). Also, this needs
- to be more than 400 if required to hold the registers (see below, where
- we round it up based on REGISTER_BYTES). */
-#define PBUFSIZ 400
+/* This limit comes from the monitor. */
+
+#define PBUFSIZ 250
/* Maximum number of bytes to read/write at once. The value here
is chosen to fill up a packet (the headers account for the 32). */
#define MAXBUFBYTES ((PBUFSIZ-32)/2)
-/* Round up PBUFSIZ to hold all the registers, at least. */
-/* The blank line after the #if seems to be required to work around a
- bug in HP's PA compiler. */
-#if REGISTER_BYTES > MAXBUFBYTES
-
-#undef PBUFSIZ
-#define PBUFSIZ (REGISTER_BYTES * 2 + 32)
-#endif
-
static int next_msg_id;
static int just_started;
static int message_pending;
-\f
-/* Restart the remote side; this is an extended protocol operation. */
-
-static void
-sds_restart ()
-{
-}
\f
/* Clean up connection to a remote debugger. */
SERIAL_WRITE (sds_desc, "{#}\r\n", 5);
while ((c = readchar (1)) >= 0)
- printf_unfiltered ("%c");
+ printf_unfiltered ("%c", c);
printf_unfiltered ("\n");
next_msg_id = 251;
}
push_target (&sds_ops); /* Switch to using remote target now */
- /* Without this, some commands which require an active target (such
- as kill) won't work. This variable serves (at least) double duty
- as both the pid of the target process (if it has such), and as a
- flag indicating that a target is active. These functions should
- be split out into seperate variables, especially since GDB will
- someday have a notion of debugging several processes. */
-
- inferior_pid = 42000;
-
just_started = 1;
/* Start the remote connection; if error (0), discard this target.
int len;
{
int i, sum;
+ char *p;
if (len % 3 != 0)
error ("bad length");
+ p = outbuf;
for (i = 0; i < len; i += 3)
{
/* Collect the next three bytes into a number. */
sum |= ((long) *inbuf++);
/* Spit out 4 6-bit encodings. */
- *outbuf++ = ((sum >> 18) & 0x3f) + '0';
- *outbuf++ = ((sum >> 12) & 0x3f) + '0';
- *outbuf++ = ((sum >> 6) & 0x3f) + '0';
- *outbuf++ = (sum & 0x3f) + '0';
+ *p++ = ((sum >> 18) & 0x3f) + '0';
+ *p++ = ((sum >> 12) & 0x3f) + '0';
+ *p++ = ((sum >> 6) & 0x3f) + '0';
+ *p++ = (sum & 0x3f) + '0';
}
+ return (p - outbuf);
}
static int
sds_send (buf, 2);
}
\f
-/* Send ^C to target to halt it. Target will respond, and send us a
- packet. */
+/* Send a message to target to halt it. Target will respond, and send
+ us a message pending notice. */
static void
sds_interrupt (signo)
int signo;
{
+ unsigned char buf[PBUFSIZ];
+
/* If this doesn't work, try more severe steps. */
signal (signo, sds_interrupt_twice);
if (remote_debug)
printf_unfiltered ("sds_interrupt called\n");
- /* Send a break or a ^C, depending on user preference. */
- if (sds_break)
- SERIAL_SEND_BREAK (sds_desc);
- else
- SERIAL_WRITE (sds_desc, "\003", 1);
+ buf[0] = 25;
+ sds_send (buf, 1);
}
static void (*ofunc)();
/* The user typed ^C twice. */
+
static void
sds_interrupt_twice (signo)
int signo;
{
buf[0] = 26;
retlen = sds_send (buf, 1);
+ if (remote_debug)
+ {
+ fprintf_unfiltered (gdb_stderr, "Signals: %04x %02x %02x\n",
+ ((int) buf[0]) << 8 + buf[1],
+ buf[2], buf[3]);
+ }
message_pending = 0;
status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_TRAP;
goto got_status;
}
}
return inferior_pid;
}
-/* Number of bytes of registers this stub implements. */
-static int register_bytes_found;
+static unsigned char sprs[16];
/* Read the remote registers into the block REGS. */
/* Currently we just read all the registers, so we don't use regno. */
int regno;
{
unsigned char buf[PBUFSIZ];
- int i, len;
+ int i, retlen;
char *p;
char regs[REGISTER_BYTES];
memset (regs, 0, REGISTER_BYTES);
buf[0] = 18;
- buf[1] = 2;
+ buf[1] = 1;
buf[2] = 0;
- len = sds_send (buf, 3);
-
- /* Reply describes registers byte by byte. Suck them all up, then
- supply them to the register cacheing/storage mechanism. */
+ retlen = sds_send (buf, 3);
- for (i = 0; i < len; i++)
- regs[i] = buf[i];
+ for (i = 0; i < 4 * 6; ++i)
+ regs[i + 4 * 32 + 8 * 32] = buf[i];
+ for (i = 0; i < 4 * 4; ++i)
+ sprs[i] = buf[i + 4 * 7];
buf[0] = 18;
- buf[1] = 1;
+ buf[1] = 2;
buf[2] = 0;
- len = sds_send (buf, 3);
+ retlen = sds_send (buf, 3);
- for (i = 0; i < 4 * 6; i++)
- {
- regs[i + 4 * 32 + 8 * 32] = buf[i];
- }
+ for (i = 0; i < retlen; i++)
+ regs[i] = buf[i];
/* (should warn about reply too short) */
- supply_them:
for (i = 0; i < NUM_REGS; i++)
supply_register (i, ®s[REGISTER_BYTE(i)]);
}
-/* Prepare to store registers. Since we may send them all (using a
- 'G' request), we have to read out the ones we don't want to change
- first. */
+/* Prepare to store registers. Since we may send them all, we have to
+ read out the ones we don't want to change first. */
static void
sds_prepare_to_store ()
sds_store_registers (regno)
int regno;
{
- unsigned char buf[PBUFSIZ];
+ unsigned char *p, buf[PBUFSIZ];
int i;
- char *p;
-
- buf[0] = 19;
- buf[1] = 2;
- buf[2] = 0;
- buf[3] = 0;
-
- p = buf + 4;
+ /* Store all the special-purpose registers. */
+ p = buf;
+ *p++ = 19;
+ *p++ = 1;
+ *p++ = 0;
+ *p++ = 0;
+ for (i = 0; i < 4 * 6; i++)
+ *p++ = registers[i + 4 * 32 + 8 * 32];
+ for (i = 0; i < 4 * 1; i++)
+ *p++ = 0;
+ for (i = 0; i < 4 * 4; i++)
+ *p++ = sprs[i];
+
+ sds_send (buf, p - buf);
+
+ /* Store all the general-purpose registers. */
+ p = buf;
+ *p++ = 19;
+ *p++ = 2;
+ *p++ = 0;
+ *p++ = 0;
for (i = 0; i < 4 * 32; i++)
- p[i] = registers[i];
-
- sds_send (buf, 4 + 4 * 32);
-
- buf[0] = 19;
- buf[1] = 1;
- buf[2] = 0;
- buf[3] = 0;
+ *p++ = registers[i];
- p = buf + 4;
+ sds_send (buf, p - buf);
- for (i = 0; i < 4 * 10; i++)
- p[i] = registers[i];
-
- sds_send (buf, 4 + 4 * 10);
-}
-
-/*
- Use of the data cache *used* to be disabled because it loses for looking at
- and changing hardware I/O ports and the like. Accepting `volatile'
- would perhaps be one way to fix it. Another idea would be to use the
- executable file for the text segment (for all SEC_CODE sections?
- For all SEC_READONLY sections?). This has problems if you want to
- actually see what the memory contains (e.g. self-modifying code,
- clobbered memory, user downloaded the wrong thing).
-
- Because it speeds so much up, it's now enabled, if you're playing
- with registers you turn it of (set remotecache 0)
-*/
-
-/* Read a word from remote address ADDR and return it.
- This goes through the data cache. */
-
-#if 0 /* unused? */
-static int
-sds_fetch_word (addr)
- CORE_ADDR addr;
-{
- return dcache_fetch (sds_dcache, addr);
}
-
-/* Write a word WORD into remote address ADDR.
- This goes through the data cache. */
-
-static void
-sds_store_word (addr, word)
- CORE_ADDR addr;
- int word;
-{
- dcache_poke (sds_dcache, addr, word);
-}
-#endif /* 0 (unused?) */
-
\f
/* Write memory data directly to the remote machine. This does not
inform the data cache; the data cache uses this. MEMADDR is the
sds_files_info (ignore)
struct target_ops *ignore;
{
- puts_filtered ("Debugging a target over a serial line.\n");
+ puts_filtered ("Debugging over a serial connection, using SDS protocol.\n");
}
\f
/* Stuff for dealing with the packets which are part of this protocol.
}
}
+/* An SDS-style checksum is a sum of the bytes modulo 253. (Presumably
+ because 253, 254, and 255 are special flags in the protocol.) */
+
static int
compute_checksum (csum, buf, len)
int csum, len;
unsigned char *buf;
int len;
{
- int i;
+ int i, enclen;
unsigned char csum = 0;
char buf2[PBUFSIZ], buf3[PBUFSIZ];
unsigned char header[3];
/* Copy the packet into buffer BUF2, encapsulating it
and giving it a checksum. */
- if (len > (int) sizeof (buf2) - 5) /* Prosanity check */
+ if (len > 170) /* Prosanity check */
abort();
if (remote_debug)
p = buf2;
*p++ = '$';
- header[1] = next_msg_id;
-
if (len % 3 != 0)
{
buf[len] = '\0';
buf[len+1] = '\0';
}
- len = ((len + 2) / 3) * 3;
+ header[1] = next_msg_id;
header[2] = len;
csum = compute_checksum (csum, buf, len);
- csum = compute_checksum (csum, header+1, 2);
+ csum = compute_checksum (csum, header + 1, 2);
header[0] = csum;
tob64 (header, p, 3);
p += 4;
- tob64 (buf, buf3, len);
+ enclen = tob64 (buf, buf3, ((len + 2) / 3) * 3);
- for (i = 0; i < (len / 3) * 4; i++)
- {
- *p++ = buf3[i];
- }
+ for (i = 0; i < enclen; ++i)
+ *p++ = buf3[i];
*p++ = '\r';
*p++ = '\n';
{
*bp = '\000';
if (remote_debug)
- printf_filtered ("Received encoded: \"%s\"\n", buf);
+ fprintf_unfiltered (gdb_stderr, "Received encoded: \"%s\"\n",
+ buf);
return 1;
}
static void
sds_kill ()
{
- /* For some mysterious reason, wait_for_inferior calls kill instead of
- mourn after it gets TARGET_WAITKIND_SIGNALLED. Work around it. */
- if (kill_kludge)
- {
- kill_kludge = 0;
- target_mourn_inferior ();
- return;
- }
-
-#if 0 /* fix to use 1-arg fn */
- /* Use catch_errors so the user can quit from gdb even when we aren't on
- speaking terms with the remote system. */
- catch_errors (putmessage, "k", "", RETURN_MASK_ERROR);
-#endif
-
- /* Don't wait for it to die. I'm not really sure it matters whether
- we do or not. For the existing stubs, kill is a noop. */
- target_mourn_inferior ();
+ /* Don't try to do anything to the target. */
}
static void
char *args;
char **env;
{
- /* Rip out the breakpoints; we'll reinsert them after restarting
- the remote server. */
- remove_breakpoints ();
-
- /* Now restart the remote server. */
- sds_restart ();
-
- /* Now put the breakpoints back in. This way we're safe if the
- restart function works via a unix fork on the remote side. */
- insert_breakpoints ();
+ inferior_pid = 42000;
/* Clean up from the last time we were running. */
clear_proceed_status ();
/* Let the remote process run. */
- proceed (-1, TARGET_SIGNAL_0, 0);
+ proceed (bfd_get_start_address (exec_bfd), TARGET_SIGNAL_0, 0);
}
+static void
+sds_load (filename, from_tty)
+ char *filename;
+ int from_tty;
+{
+ generic_load (filename, from_tty);
+
+ inferior_pid = 0;
+}
\f
/* The SDS monitor has commands for breakpoint insertion, although it
it doesn't actually manage the breakpoints, it just returns the
CORE_ADDR addr;
char *contents_cache;
{
- int retlen;
- unsigned char buf[PBUFSIZ];
+ int i, retlen;
+ unsigned char *p, buf[PBUFSIZ];
+
+ p = buf;
+ *p++ = 16;
+ *p++ = 0;
+ *p++ = (int) (addr >> 24) & 0xff;
+ *p++ = (int) (addr >> 16) & 0xff;
+ *p++ = (int) (addr >> 8) & 0xff;
+ *p++ = (int) (addr ) & 0xff;
+
+ retlen = sds_send (buf, p - buf);
- buf[0] = 16;
- buf[1] = 0;
+ for (i = 0; i < 4; ++i)
+ contents_cache[i] = buf[i + 2];
- retlen = sds_send (buf, 7);
+ return 0;
}
static int
CORE_ADDR addr;
char *contents_cache;
{
- int retlen;
- unsigned char buf[PBUFSIZ];
-
- buf[0] = 17;
- buf[1] = 0;
-
- retlen = sds_send (buf, 7);
+ int i, retlen;
+ unsigned char *p, buf[PBUFSIZ];
+
+ p = buf;
+ *p++ = 17;
+ *p++ = 0;
+ *p++ = (int) (addr >> 24) & 0xff;
+ *p++ = (int) (addr >> 16) & 0xff;
+ *p++ = (int) (addr >> 8) & 0xff;
+ *p++ = (int) (addr ) & 0xff;
+ for (i = 0; i < 4; ++i)
+ *p++ = contents_cache[i];
+
+ retlen = sds_send (buf, p - buf);
+
+ return 0;
}
\f
/* Define the target operations vector. */
-static struct target_ops sds_ops =
+static struct target_ops sds_ops ;
+
+static void init_sds_ops(void)
{
- "sds", /* to_shortname */
- "Remote serial target with SDS protocol", /* to_longname */
- "Use a remote computer via a serial line, using the SDS protocol.\n\
-Specify the serial device it is connected to (e.g. /dev/ttya).", /* to_doc */
- sds_open, /* to_open */
- sds_close, /* to_close */
- NULL, /* to_attach */
- sds_detach, /* to_detach */
- sds_resume, /* to_resume */
- sds_wait, /* to_wait */
- sds_fetch_registers, /* to_fetch_registers */
- sds_store_registers, /* to_store_registers */
- sds_prepare_to_store, /* to_prepare_to_store */
- sds_xfer_memory, /* to_xfer_memory */
- sds_files_info, /* to_files_info */
- sds_insert_breakpoint, /* to_insert_breakpoint */
- sds_remove_breakpoint, /* to_remove_breakpoint */
- NULL, /* to_terminal_init */
- NULL, /* to_terminal_inferior */
- NULL, /* to_terminal_ours_for_output */
- NULL, /* to_terminal_ours */
- NULL, /* to_terminal_info */
- sds_kill, /* to_kill */
- generic_load, /* to_load */
- NULL, /* to_lookup_symbol */
- sds_create_inferior, /* to_create_inferior */
- sds_mourn, /* to_mourn_inferior */
- 0, /* to_can_run */
- 0, /* to_notice_signals */
- 0, /* to_thread_alive */
- 0, /* to_stop */
- process_stratum, /* to_stratum */
- NULL, /* to_next */
- 1, /* to_has_all_memory */
- 1, /* to_has_memory */
- 1, /* to_has_stack */
- 1, /* to_has_registers */
- 1, /* to_has_execution */
- NULL, /* sections */
- NULL, /* sections_end */
- OPS_MAGIC /* to_magic */
-};
+ sds_ops.to_shortname = "sds";
+ sds_ops.to_longname = "Remote serial target with SDS protocol";
+ sds_ops.to_doc = "Use a remote computer via a serial line; using the SDS protocol.\n\
+Specify the serial device it is connected to (e.g. /dev/ttya).",
+ sds_ops.to_open = sds_open;
+ sds_ops.to_close = sds_close;
+ sds_ops.to_attach = NULL;
+ sds_ops.to_detach = sds_detach;
+ sds_ops.to_resume = sds_resume;
+ sds_ops.to_wait = sds_wait;
+ sds_ops.to_fetch_registers = sds_fetch_registers;
+ sds_ops.to_store_registers = sds_store_registers;
+ sds_ops.to_prepare_to_store = sds_prepare_to_store;
+ sds_ops.to_xfer_memory = sds_xfer_memory;
+ sds_ops.to_files_info = sds_files_info;
+ sds_ops.to_insert_breakpoint = sds_insert_breakpoint;
+ sds_ops.to_remove_breakpoint = sds_remove_breakpoint;
+ sds_ops.to_terminal_init = NULL;
+ sds_ops.to_terminal_inferior = NULL;
+ sds_ops.to_terminal_ours_for_output = NULL;
+ sds_ops.to_terminal_ours = NULL;
+ sds_ops.to_terminal_info = NULL;
+ sds_ops.to_kill = sds_kill;
+ sds_ops.to_load = sds_load;
+ sds_ops.to_lookup_symbol = NULL;
+ sds_ops.to_create_inferior = sds_create_inferior;
+ sds_ops.to_mourn_inferior = sds_mourn;
+ sds_ops.to_can_run = 0;
+ sds_ops.to_notice_signals = 0;
+ sds_ops.to_thread_alive = 0;
+ sds_ops.to_stop = 0;
+ sds_ops.to_stratum = process_stratum;
+ sds_ops.DONT_USE = NULL;
+ sds_ops.to_has_all_memory = 1;
+ sds_ops.to_has_memory = 1;
+ sds_ops.to_has_stack = 1; /* to_has_stack */
+ sds_ops.to_has_registers = 1; sds_ops.to_has_execution = 1;
+ sds_ops.to_sections = NULL;
+ sds_ops.to_sections_end = NULL;
+ sds_ops.to_magic = OPS_MAGIC ;
+}
/* Put a command string, in args, out to the monitor and display the
reply message. */
int from_tty;
{
char *p;
- int i, len, resp_len;
+ int i, len, retlen;
unsigned char buf[1000];
/* Convert hexadecimal chars into a byte buffer. */
p += 2;
}
- len = sds_send (buf, len);
+ retlen = sds_send (buf, len);
printf_filtered ("Reply is ");
- for (i = 0; i < len; ++i)
+ for (i = 0; i < retlen; ++i)
{
printf_filtered ("%02x", buf[i]);
}
void
_initialize_remote_sds ()
{
+ init_sds_ops() ;
add_target (&sds_ops);
add_show_from_set (add_set_cmd ("sdstimeout", no_class,