diff --git a/gdb/ChangeLog b/gdb/ChangeLog index b5ddf0dbd8..5773c7e72f 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,20 @@ +Fri Apr 4 08:21:21 1997 Stu Grossman (grossman@critters.cygnus.com) + + * remote.c: Fix doc for `C' and `S' commands to indicate full + address. + * (remote_ops extended_remote_ops remote_desc remote_write_size): + Make static. + * (remote_fetch_registers remote_write_bytes remote_read_bytes): + Record size of response to fetch registers command, use this to + limit size of memory read and write commands. + * (push_remote_target): New function to make it possible to have + another target switch to the remote target. + * target.h: Add prototype for push_remote_target. + * sh-tdep.c (sh_frame_find_saved_regs): Fix sign extension bugs + for hosts which default to unsigned chars (such as SGI's). + * (_initialize_sh_tdep): Don't set remote_write_size. It's now + handled automatically in remote.c. + Thu Apr 3 15:10:30 1997 Michael Snyder * blockframe.c: blockvector_for_pc_sect(), block_for_pc_sect(), diff --git a/gdb/remote.c b/gdb/remote.c index 65caedb629..1e23db1a18 100644 --- a/gdb/remote.c +++ b/gdb/remote.c @@ -1,5 +1,5 @@ /* Remote target communications for serial-line targets in custom GDB protocol - Copyright 1988, 1991, 1992, 1993, 1994, 1995, 1996 Free Software Foundation, Inc. + Copyright 1988, 1991, 1992, 1993, 1994, 1995, 1996, 1997 Free Software Foundation, Inc. This file is part of GDB. @@ -97,10 +97,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ If AA..AA is omitted, resume at same address. - continue with Csig;AA Continue with signal sig (hex signal - signal number). + continue with Csig;AA..AA Continue with signal sig (hex signal + signal number). If ;AA..AA is omitted, resume + at same address. - step with Ssig;AA Like 'C' but step not continue. + step with Ssig;AA..AA Like 'C' but step not continue. signal last signal ? Reply the current reason for stopping. @@ -278,8 +279,8 @@ static int remote_insert_breakpoint PARAMS ((CORE_ADDR, char *)); static int remote_remove_breakpoint PARAMS ((CORE_ADDR, char *)); -extern struct target_ops remote_ops; /* Forward decl */ -extern struct target_ops extended_remote_ops; /* Forward decl */ +static struct target_ops remote_ops; /* Forward decl */ +static struct target_ops extended_remote_ops; /* Forward decl */ /* This was 5 seconds, which is a long time to sit and wait. Unless this is going though some terminal server or multiplexer or @@ -300,7 +301,7 @@ static int remote_break; /* Descriptor for I/O to remote machine. Initialize it to NULL so that remote_open knows that we don't have a file open when the program starts. */ -serial_t remote_desc = NULL; +static serial_t remote_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 @@ -329,10 +330,22 @@ serial_t remote_desc = NULL; static int remote_write_size = PBUFSIZ; +/* This is the size (in chars) of the first response to the `g' command. This + is used to limit the size of the memory read and write commands to prevent + stub buffers from overflowing. */ + +static int remote_register_buf_size = 0; + /* Should we try the 'P' request? If this is set to one when the stub doesn't support 'P', the only consequence is some unnecessary traffic. */ static int stub_supports_P = 1; +/* These are pointers to hook functions that may be set in order to + modify resume/wait behavior for a particular architecture. */ + +void (*target_resume_hook) PARAMS ((void)); +void (*target_wait_loop_hook) PARAMS ((void)); + /* These are the threads which we last sent to the remote system. -1 for all or -2 for not sent yet. */ @@ -663,6 +676,11 @@ remote_resume (pid, step, siggnal) last_sent_signal = siggnal; last_sent_step = step; + /* A hook for when we need to do something at the last moment before + resumption. */ + if (target_resume_hook) + (*target_resume_hook) (); + if (siggnal != TARGET_SIGNAL_0) { buf[0] = step ? 'S' : 'C'; @@ -754,6 +772,11 @@ remote_wait (pid, status) getpkt ((char *) buf, 1); signal (SIGINT, ofunc); + /* This is a hook for when we need to do something (perhaps the + collection of trace data) every time the target stops. */ + if (target_wait_loop_hook) + (*target_wait_loop_hook) (); + switch (buf[0]) { case 'E': /* Error of some sort */ @@ -915,6 +938,9 @@ remote_fetch_registers (regno) sprintf (buf, "g"); remote_send (buf); + if (remote_register_buf_size == 0) + remote_register_buf_size = strlen (buf); + /* Unimplemented registers read as all bits zero. */ memset (regs, 0, REGISTER_BYTES); @@ -1068,6 +1094,21 @@ remote_store_word (addr, word) #endif /* 0 (unused?) */ + +/* Return the number of hex digits in num. */ + +static int +hexnumlen (num) + ULONGEST num; +{ + int i; + + for (i = 0; num != 0; i++) + num >>= 4; + + return min (i, 1); +} + /* Write memory data directly to the remote machine. This does not inform the data cache; the data cache uses this. MEMADDR is the address in the remote memory space. @@ -1082,24 +1123,32 @@ remote_write_bytes (memaddr, myaddr, len) char *myaddr; int len; { - char buf[PBUFSIZ]; - int i; - char *p; - int done; + int max_buf_size; /* Max size of packet output buffer */ + int origlen; + /* Chop the transfer down if necessary */ - done = 0; - while (done < len) - { - int todo = len - done; - int cando = min(remote_write_size, PBUFSIZ) / 2 - 32; /* num bytes that will fit */ + max_buf_size = min (remote_write_size, PBUFSIZ); + max_buf_size = min (max_buf_size, remote_register_buf_size); - if (todo > cando) - todo = cando; +#define PACKET_OVERHEAD (1 + 1 + 1 + 2) /* $x#xx - Overhead for all types of packets */ + + /* packet overhead + ,: */ + max_buf_size -= PACKET_OVERHEAD + hexnumlen (memaddr + len - 1) + 1 + hexnumlen (len) + 1; + + origlen = len; + while (len > 0) + { + char buf[PBUFSIZ]; + char *p; + int todo; + int i; + + todo = min (len, max_buf_size / 2); /* num bytes that will fit */ /* FIXME-32x64: Need a version of print_address_numeric which puts the result in a buffer like sprintf. */ - sprintf (buf, "M%lx,%x:", (unsigned long) memaddr + done, todo); + sprintf (buf, "M%lx,%x:", (unsigned long) memaddr, todo); /* We send target system values byte by byte, in increasing byte addresses, each byte encoded as two hex characters. */ @@ -1107,8 +1156,8 @@ remote_write_bytes (memaddr, myaddr, len) p = buf + strlen (buf); for (i = 0; i < todo; i++) { - *p++ = tohex ((myaddr[i + done] >> 4) & 0xf); - *p++ = tohex (myaddr[i + done] & 0xf); + *p++ = tohex ((myaddr[i] >> 4) & 0xf); + *p++ = tohex (myaddr[i] & 0xf); } *p = '\0'; @@ -1124,9 +1173,11 @@ remote_write_bytes (memaddr, myaddr, len) errno = EIO; return 0; } - done += todo; + myaddr += todo; + memaddr += todo; + len -= todo; } - return len; + return origlen; } /* Read memory data directly from the remote machine. @@ -1143,28 +1194,30 @@ remote_read_bytes (memaddr, myaddr, len) char *myaddr; int len; { - char buf[PBUFSIZ]; - int i; - char *p; - int done; - /* Chop transfer down if neccessary */ + int max_buf_size; /* Max size of packet output buffer */ + int origlen; -#if 0 - /* FIXME: This is wrong for larger packets */ - if (len > PBUFSIZ / 2 - 1) - abort (); -#endif - done = 0; - while (done < len) + /* Chop the transfer down if necessary */ + + max_buf_size = min (remote_write_size, PBUFSIZ); + max_buf_size = min (max_buf_size, remote_register_buf_size); + + /* packet overhead */ + max_buf_size -= PACKET_OVERHEAD; + + origlen = len; + while (len > 0) { - int todo = len - done; - int cando = PBUFSIZ / 2 - 32; /* number of bytes that will fit. */ - if (todo > cando) - todo = cando; + char buf[PBUFSIZ]; + char *p; + int todo; + int i; + + todo = min (len, max_buf_size / 2); /* num bytes that will fit */ /* FIXME-32x64: Need a version of print_address_numeric which puts the result in a buffer like sprintf. */ - sprintf (buf, "m%lx,%x", (unsigned long) memaddr + done, todo); + sprintf (buf, "m%lx,%x", (unsigned long) memaddr, todo); putpkt (buf); getpkt (buf, 0); @@ -1187,13 +1240,15 @@ remote_read_bytes (memaddr, myaddr, len) if (p[0] == 0 || p[1] == 0) /* Reply is short. This means that we were able to read only part of what we wanted to. */ - return i + done; - myaddr[i + done] = fromhex (p[0]) * 16 + fromhex (p[1]); + return i + (origlen - len); + myaddr[i] = fromhex (p[0]) * 16 + fromhex (p[1]); p += 2; } - done += todo; + myaddr += todo; + memaddr += todo; + len -= todo; } - return len; + return origlen; } /* Read or write LEN bytes from inferior memory at MEMADDR, transferring @@ -1782,7 +1837,8 @@ remote_remove_breakpoint (addr, contents_cache) /* Define the target subroutine names */ -struct target_ops remote_ops = { +static struct target_ops remote_ops = +{ "remote", /* to_shortname */ "Remote serial target in gdb-specific protocol", /* to_longname */ "Use a remote computer via a serial line, using a gdb-specific protocol.\n\ @@ -1826,7 +1882,8 @@ Specify the serial device it is connected to (e.g. /dev/ttya).", /* to_doc */ OPS_MAGIC /* to_magic */ }; -struct target_ops extended_remote_ops = { +static struct target_ops extended_remote_ops = +{ "extended-remote", /* to_shortname */ "Extended remote serial target in gdb-specific protocol",/* to_longname */ "Use a remote computer via a serial line, using a gdb-specific protocol.\n\ @@ -1872,6 +1929,26 @@ Specify the serial device it is connected to (e.g. /dev/ttya).", /* to_doc */ OPS_MAGIC /* to_magic */ }; +/* Some targets are only capable of doing downloads, and afterwards they switch + to the remote serial protocol. This function provides a clean way to get + from the download target to the remote target. It's basically just a + wrapper so that we don't have to expose any of the internal workings of + remote.c. + + Prior to calling this routine, you should shutdown the current target code, + else you will get the "A program is being debugged already..." message. + Usually a call to pop_target() suffices. +*/ + +void +push_remote_target (name, from_tty) + char *name; + int from_tty; +{ + printf_filtered ("Switching to remote protocol\n"); + remote_open (name, from_tty); +} + void _initialize_remote () { diff --git a/gdb/sh-tdep.c b/gdb/sh-tdep.c index 4a3eb2e0d4..dcec846298 100644 --- a/gdb/sh-tdep.c +++ b/gdb/sh-tdep.c @@ -262,7 +262,7 @@ sh_frame_find_saved_regs (fi, fsr) } else if (IS_MOV_R3 (insn)) { - r3_val = (char) (insn & 0xff); + r3_val = ((insn & 0xff) ^ 0x80) - 0x80; pc += 2; insn = read_memory_integer (pc, 2); } @@ -281,7 +281,7 @@ sh_frame_find_saved_regs (fi, fsr) else if (IS_ADD_SP (insn)) { pc += 2; - depth += -((char) (insn & 0xff)); + depth -= ((insn & 0xff) ^ 0x80) - 0x80; insn = read_memory_integer (pc, 2); } else @@ -706,9 +706,4 @@ Set this to be able to access processor-type-specific registers.\n\ sh_set_processor_type_command (strsave (DEFAULT_SH_TYPE), 0); add_com ("regs", class_vars, sh_show_regs, "Print all registers"); - - /* Reduce the remote write size because some CMONs can't take - more than 400 bytes in a packet. 300 seems like a safe bet. */ - remote_write_size = 300; } -