X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fremote-mips.c;h=01f780f2200c0dde96b3518802d385bfd98f8bbf;hb=e71bd25763bc51ee86c6ad66736e4d7dde6d13b4;hp=60f4546063b54870994cd18ddbf563d4426b4702;hpb=d05559016da4d9698f5ccb6995f5ac8e4c048ee0;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/remote-mips.c b/gdb/remote-mips.c index 60f4546063..01f780f220 100644 --- a/gdb/remote-mips.c +++ b/gdb/remote-mips.c @@ -1,7 +1,6 @@ /* Remote debugging interface for MIPS remote debugging protocol. - Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, - 2002, 2003, 2004 Free Software Foundation, Inc. + Copyright (C) 1993-2004, 2006-2012 Free Software Foundation, Inc. Contributed by Cygnus Support. Written by Ian Lance Taylor . @@ -10,7 +9,7 @@ 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 2 of the License, or + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, @@ -19,9 +18,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ + along with this program. If not, see . */ #include "defs.h" #include "inferior.h" @@ -32,12 +29,13 @@ #include "serial.h" #include "target.h" #include "exceptions.h" -#include "remote-utils.h" #include "gdb_string.h" #include "gdb_stat.h" +#include "gdb_usleep.h" #include "regcache.h" #include #include "mips-tdep.h" +#include "gdbthread.h" /* Breakpoint types. Values 0, 1, and 2 must agree with the watch @@ -87,35 +85,27 @@ static void lsi_open (char *name, int from_tty); static void mips_close (int quitting); -static void mips_detach (char *args, int from_tty); +static void mips_detach (struct target_ops *ops, char *args, int from_tty); -static void mips_resume (ptid_t ptid, int step, - enum target_signal siggnal); +static int mips_map_regno (struct gdbarch *, int); -static ptid_t mips_wait (ptid_t ptid, - struct target_waitstatus *status); +static void mips_set_register (int regno, ULONGEST value); -static int mips_map_regno (int regno); +static void mips_prepare_to_store (struct regcache *regcache); -static void mips_fetch_registers (int regno); - -static void mips_prepare_to_store (void); - -static void mips_store_registers (int regno); - -static unsigned int mips_fetch_word (CORE_ADDR addr); +static int mips_fetch_word (CORE_ADDR addr, unsigned int *valp); static int mips_store_word (CORE_ADDR addr, unsigned int value, - char *old_contents); + int *old_contents); -static int mips_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, +static int mips_xfer_memory (CORE_ADDR memaddr, gdb_byte *myaddr, int len, int write, struct mem_attrib *attrib, struct target_ops *target); static void mips_files_info (struct target_ops *ignore); -static void mips_mourn_inferior (void); +static void mips_mourn_inferior (struct target_ops *ops); static int pmon_makeb64 (unsigned long v, char *p, int n, int *chksum); @@ -143,17 +133,19 @@ static void mips_load (char *file, int from_tty); static int mips_make_srec (char *buffer, int type, CORE_ADDR memaddr, unsigned char *myaddr, int len); -static int set_breakpoint (CORE_ADDR addr, int len, enum break_type type); +static int mips_set_breakpoint (CORE_ADDR addr, int len, enum break_type type); -static int clear_breakpoint (CORE_ADDR addr, int len, enum break_type type); +static int mips_clear_breakpoint (CORE_ADDR addr, int len, + enum break_type type); -static int common_breakpoint (int set, CORE_ADDR addr, int len, - enum break_type type); +static int mips_common_breakpoint (int set, CORE_ADDR addr, int len, + enum break_type type); /* Forward declarations. */ extern struct target_ops mips_ops; extern struct target_ops pmon_ops; extern struct target_ops ddb_ops; +extern struct target_ops rockhopper_ops; /* *INDENT-OFF* */ /* The MIPS remote debugging interface is built on top of a simple packet protocol. Each packet is organized as follows: @@ -299,17 +291,22 @@ extern struct target_ops ddb_ops; These are initialized with code in _initialize_remote_mips instead of static initializers, to make it easier to extend the target_ops vector later. */ -struct target_ops mips_ops, pmon_ops, ddb_ops, lsi_ops; +struct target_ops mips_ops, pmon_ops, ddb_ops, rockhopper_ops, lsi_ops; enum mips_monitor_type { /* IDT/SIM monitor being used: */ MON_IDT, /* PMON monitor being used: */ - MON_PMON, /* 3.0.83 [COGENT,EB,FP,NET] Algorithmics Ltd. Nov 9 1995 17:19:50 */ - MON_DDB, /* 2.7.473 [DDBVR4300,EL,FP,NET] Risq Modular Systems, Thu Jun 6 09:28:40 PDT 1996 */ - MON_LSI, /* 4.3.12 [EB,FP], LSI LOGIC Corp. Tue Feb 25 13:22:14 1997 */ - /* Last and unused value, for sizing vectors, etc. */ + MON_PMON, /* 3.0.83 [COGENT,EB,FP,NET] + Algorithmics Ltd. Nov 9 1995 17:19:50 */ + MON_DDB, /* 2.7.473 [DDBVR4300,EL,FP,NET] + Risq Modular Systems, + Thu Jun 6 09:28:40 PDT 1996 */ + MON_LSI, /* 4.3.12 [EB,FP], + LSI LOGIC Corp. Tue Feb 25 13:22:14 1997 */ + MON_ROCKHOPPER, + /* Last and unused value, for sizing vectors, etc. */ MON_LAST }; static enum mips_monitor_type mips_monitor = MON_LAST; @@ -331,7 +328,7 @@ static char *mips_monitor_prompt; /* Set to 1 if the target is open. */ static int mips_is_open; -/* Currently active target description (if mips_is_open == 1) */ +/* Currently active target description (if mips_is_open == 1). */ static struct target_ops *current_ops; /* Set to 1 while the connection is being initialized. */ @@ -381,25 +378,25 @@ static FILE *tftp_file; via ^C. */ static int interrupt_count; -/* If non-zero, means that the target is running. */ +/* If non-zero, means that the target is running. */ static int mips_wait_flag = 0; -/* If non-zero, monitor supports breakpoint commands. */ +/* If non-zero, monitor supports breakpoint commands. */ static int monitor_supports_breakpoints = 0; /* Data cache header. */ -#if 0 /* not used (yet?) */ +#if 0 /* not used (yet?) */ static DCACHE *mips_dcache; #endif -/* Non-zero means that we've just hit a read or write watchpoint */ +/* Non-zero means that we've just hit a read or write watchpoint. */ static int hit_watchpoint; /* Table of breakpoints/watchpoints (used only on LSI PMON target). The table is indexed by a breakpoint number, which is an integer - from 0 to 255 returned by the LSI PMON when a breakpoint is set. - */ + from 0 to 255 returned by the LSI PMON when a breakpoint is set. */ + #define MAX_LSI_BREAKPOINTS 256 struct lsi_breakpoint_info { @@ -412,15 +409,21 @@ lsi_breakpoints[MAX_LSI_BREAKPOINTS]; /* Error/warning codes returned by LSI PMON for breakpoint commands. Warning values may be ORed together; error values may not. */ -#define W_WARN 0x100 /* This bit is set if the error code is a warning */ -#define W_MSK 0x101 /* warning: Range feature is supported via mask */ -#define W_VAL 0x102 /* warning: Value check is not supported in hardware */ -#define W_QAL 0x104 /* warning: Requested qualifiers are not supported in hardware */ - -#define E_ERR 0x200 /* This bit is set if the error code is an error */ +#define W_WARN 0x100 /* This bit is set if the error code + is a warning */ +#define W_MSK 0x101 /* warning: Range feature is supported + via mask */ +#define W_VAL 0x102 /* warning: Value check is not + supported in hardware */ +#define W_QAL 0x104 /* warning: Requested qualifiers are + not supported in hardware */ + +#define E_ERR 0x200 /* This bit is set if the error code + is an error */ #define E_BPT 0x200 /* error: No such breakpoint number */ #define E_RGE 0x201 /* error: Range is not supported */ -#define E_QAL 0x202 /* error: The requested qualifiers can not be used */ +#define E_QAL 0x202 /* error: The requested qualifiers can + not be used */ #define E_OUT 0x203 /* error: Out of hardware resources */ #define E_NON 0x204 /* error: Hardware breakpoint not supported */ @@ -452,6 +455,14 @@ struct lsi_error lsi_error_table[] = of warnings returned by PMON when hardware breakpoints are used. */ static int monitor_warnings; +/* This is the ptid we use while we're connected to the remote. Its + value is arbitrary, as the remote-mips target doesn't have a notion of + processes or threads, but we need something non-null to place in + inferior_ptid. */ +static ptid_t remote_mips_ptid; + +/* Close any ports which might be open. Reset certain globals indicating + the state of those ports. */ static void close_ports (void) @@ -472,7 +483,7 @@ close_ports (void) all hell to break loose--the rest of GDB will tend to get left in an inconsistent state. */ -static NORETURN void +static void ATTRIBUTE_NORETURN mips_error (char *string,...) { va_list args; @@ -480,7 +491,7 @@ mips_error (char *string,...) va_start (args, string); target_terminal_ours (); - wrap_here (""); /* Force out any buffered output */ + wrap_here (""); /* Force out any buffered output. */ gdb_flush (gdb_stdout); if (error_pre_print) fputs_filtered (error_pre_print, gdb_stderr); @@ -495,9 +506,10 @@ mips_error (char *string,...) close_ports (); printf_unfiltered ("Ending remote MIPS debugging.\n"); - target_mourn_inferior (); + if (!ptid_equal (inferior_ptid, null_ptid)) + target_mourn_inferior (); - throw_reason (RETURN_ERROR); + deprecated_throw_reason (RETURN_ERROR); } /* putc_readable - print a character, displaying non-printable chars in @@ -532,9 +544,35 @@ fputs_readable (const char *string, struct ui_file *file) } +/* Read P as a hex value. Return true if every character made sense, + storing the result in *RESULT. Leave *RESULT unchanged otherwise. */ + +static int +read_hex_value (const char *p, ULONGEST *result) +{ + ULONGEST retval; + + retval = 0; + while (*p != 0) + { + retval <<= 4; + if (*p >= '0' && *p <= '9') + retval |= *p - '0'; + else if (*p >= 'A' && *p <= 'F') + retval |= *p - 'A' + 10; + else if (*p >= 'a' && *p <= 'f') + retval |= *p - 'a' + 10; + else + return 0; + p++; + } + *result = retval; + return 1; +} + + /* Wait until STRING shows up in mips_desc. Returns 1 if successful, else 0 if - timed out. TIMEOUT specifies timeout value in seconds. - */ + timed out. TIMEOUT specifies timeout value in seconds. */ static int mips_expect_timeout (const char *string, int timeout) @@ -554,7 +592,7 @@ mips_expect_timeout (const char *string, int timeout) int c; /* Must use serial_readchar() here cuz mips_readchar would get - confused if we were waiting for the mips_monitor_prompt... */ + confused if we were waiting for the mips_monitor_prompt... */ c = serial_readchar (mips_desc, timeout); @@ -589,8 +627,7 @@ mips_expect_timeout (const char *string, int timeout) /* Wait until STRING shows up in mips_desc. Returns 1 if successful, else 0 if timed out. The timeout value is hard-coded to 2 seconds. Use - mips_expect_timeout if a different timeout value is needed. - */ + mips_expect_timeout if a different timeout value is needed. */ static int mips_expect (const char *string) @@ -619,7 +656,7 @@ mips_readchar (int timeout) static int state = 0; int mips_monitor_prompt_len = strlen (mips_monitor_prompt); - { + { /* FIXME this whole block is dead code! */ int i; i = timeout; @@ -631,16 +668,16 @@ mips_readchar (int timeout) timeout = 1; ch = serial_readchar (mips_desc, timeout); - if (ch == SERIAL_TIMEOUT && timeout == -1) /* Watchdog went off */ + if (ch == SERIAL_TIMEOUT && timeout == -1) /* Watchdog went off. */ { target_mourn_inferior (); - error ("Watchdog has expired. Target detached.\n"); + error (_("Watchdog has expired. Target detached.")); } if (ch == SERIAL_EOF) - mips_error ("End of file from remote"); + mips_error (_("End of file from remote")); if (ch == SERIAL_ERROR) - mips_error ("Error reading from remote: %s", safe_strerror (errno)); + mips_error (_("Error reading from remote: %s"), safe_strerror (errno)); if (remote_debug > 1) { /* Don't use _filtered; we can't deal with a QUIT out of @@ -664,7 +701,8 @@ mips_readchar (int timeout) if (remote_debug > 0) /* Don't use _filtered; we can't deal with a QUIT out of target_wait, and I think this might be called from there. */ - fprintf_unfiltered (gdb_stdlog, "Reinitializing MIPS debugging mode\n"); + fprintf_unfiltered (gdb_stdlog, + "Reinitializing MIPS debugging mode\n"); mips_need_reply = 0; mips_initialize (); @@ -672,9 +710,9 @@ mips_readchar (int timeout) state = 0; /* At this point, about the only thing we can do is abort the command - in progress and get back to command level as quickly as possible. */ + in progress and get back to command level as quickly as possible. */ - error ("Remote board reset, debug protocol re-initialized."); + error (_("Remote board reset, debug protocol re-initialized.")); } if (ch == mips_monitor_prompt[state]) @@ -712,7 +750,7 @@ mips_receive_header (unsigned char *hdr, int *pgarbage, int ch, int timeout) what the program is outputting, if the debugging is being done on the console port. Don't use _filtered: we can't deal with a QUIT out of target_wait and - buffered target output confuses the user. */ + buffered target output confuses the user. */ if (!mips_initializing || remote_debug > 0) { if (isprint (ch) || isspace (ch)) @@ -726,13 +764,14 @@ mips_receive_header (unsigned char *hdr, int *pgarbage, int ch, int timeout) gdb_flush (gdb_stdtarg); } - /* Only count unprintable characters. */ + /* Only count unprintable characters. */ if (! (isprint (ch) || isspace (ch))) (*pgarbage) += 1; if (mips_syn_garbage > 0 && *pgarbage > mips_syn_garbage) - mips_error ("Debug protocol failure: more than %d characters before a sync.", + mips_error (_("Debug protocol failure: more " + "than %d characters before a sync."), mips_syn_garbage); } } @@ -763,7 +802,8 @@ mips_receive_header (unsigned char *hdr, int *pgarbage, int ch, int timeout) for success, -1 for timeout, -2 for error. */ static int -mips_receive_trailer (unsigned char *trlr, int *pgarbage, int *pch, int timeout) +mips_receive_trailer (unsigned char *trlr, int *pgarbage, + int *pch, int timeout) { int i; int ch; @@ -819,7 +859,7 @@ mips_send_packet (const char *s, int get_ack) len = strlen (s); if (len > DATA_MAXLEN) - mips_error ("MIPS protocol data packet too long: %s", s); + mips_error (_("MIPS protocol data packet too long: %s"), s); packet = (unsigned char *) alloca (HDR_LENGTH + len + TRLR_LENGTH + 1); @@ -857,7 +897,7 @@ mips_send_packet (const char *s, int get_ack) if (serial_write (mips_desc, packet, HDR_LENGTH + len + TRLR_LENGTH) != 0) - mips_error ("write to target failed: %s", safe_strerror (errno)); + mips_error (_("write to target failed: %s"), safe_strerror (errno)); if (!get_ack) return; @@ -888,7 +928,7 @@ mips_send_packet (const char *s, int get_ack) int i; /* Ignore any errors raised whilst attempting to ignore - packet. */ + packet. */ len = HDR_GET_LEN (hdr); @@ -904,7 +944,7 @@ mips_send_packet (const char *s, int get_ack) } if (rch == SERIAL_TIMEOUT) break; - /* ignore the character */ + /* Ignore the character. */ } if (i == len) @@ -912,7 +952,7 @@ mips_send_packet (const char *s, int get_ack) remote_timeout); /* We don't bother checking the checksum, or providing an - ACK to the packet. */ + ACK to the packet. */ continue; } @@ -965,7 +1005,7 @@ mips_send_packet (const char *s, int get_ack) } } - mips_error ("Remote did not acknowledge packet"); + mips_error (_("Remote did not acknowledge packet")); } /* Receive and acknowledge a packet, returning the data in BUFF (which @@ -996,7 +1036,7 @@ mips_receive_packet (char *buff, int throw_error, int timeout) if (mips_receive_header (hdr, &garbage, ch, timeout) != 0) { if (throw_error) - mips_error ("Timed out waiting for remote packet"); + mips_error (_("Timed out waiting for remote packet")); else return -1; } @@ -1012,7 +1052,7 @@ mips_receive_packet (char *buff, int throw_error, int timeout) if (len == 0) { /* Ignore the error condition, since we are going to - ignore the packet anyway. */ + ignore the packet anyway. */ (void) mips_receive_trailer (trlr, &garbage, &ch, timeout); } /* Don't use _filtered; we can't deal with a QUIT out of @@ -1036,7 +1076,7 @@ mips_receive_packet (char *buff, int throw_error, int timeout) if (rch == SERIAL_TIMEOUT) { if (throw_error) - mips_error ("Timed out waiting for remote packet"); + mips_error (_("Timed out waiting for remote packet")); else return -1; } @@ -1058,7 +1098,7 @@ mips_receive_packet (char *buff, int throw_error, int timeout) if (err == -1) { if (throw_error) - mips_error ("Timed out waiting for packet"); + mips_error (_("Timed out waiting for packet")); else return -1; } @@ -1118,7 +1158,8 @@ mips_receive_packet (char *buff, int throw_error, int timeout) if (serial_write (mips_desc, ack, HDR_LENGTH + TRLR_LENGTH) != 0) { if (throw_error) - mips_error ("write to target failed: %s", safe_strerror (errno)); + mips_error (_("write to target failed: %s"), + safe_strerror (errno)); else return -1; } @@ -1158,7 +1199,7 @@ mips_receive_packet (char *buff, int throw_error, int timeout) if (serial_write (mips_desc, ack, HDR_LENGTH + TRLR_LENGTH) != 0) { if (throw_error) - mips_error ("write to target failed: %s", safe_strerror (errno)); + mips_error (_("write to target failed: %s"), safe_strerror (errno)); else return -1; } @@ -1199,12 +1240,14 @@ mips_request (int cmd, int timeout, char *buff) { + int addr_size = gdbarch_addr_bit (target_gdbarch) / 8; char myBuff[DATA_MAXLEN + 1]; + char response_string[17]; int len; int rpid; char rcmd; int rerrflg; - unsigned long rresponse; + ULONGEST rresponse; if (buff == (char *) NULL) buff = myBuff; @@ -1213,8 +1256,17 @@ mips_request (int cmd, { if (mips_need_reply) internal_error (__FILE__, __LINE__, - "mips_request: Trying to send command before reply"); - sprintf (buff, "0x0 %c 0x%s 0x%s", cmd, paddr_nz (addr), paddr_nz (data)); + _("mips_request: Trying to send " + "command before reply")); + /* 'T' sets a register to a 64-bit value, so make sure we use + the right conversion function. */ + if (cmd == 'T') + sprintf (buff, "0x0 %c 0x%s 0x%s", cmd, + phex_nz (addr, addr_size), phex_nz (data, 8)); + else + sprintf (buff, "0x0 %c 0x%s 0x%s", cmd, + phex_nz (addr, addr_size), phex_nz (data, addr_size)); + mips_send_packet (buff, 1); mips_need_reply = 1; } @@ -1224,17 +1276,18 @@ mips_request (int cmd, if (!mips_need_reply) internal_error (__FILE__, __LINE__, - "mips_request: Trying to get reply before command"); + _("mips_request: Trying to get reply before command")); mips_need_reply = 0; len = mips_receive_packet (buff, 1, timeout); buff[len] = '\0'; - if (sscanf (buff, "0x%x %c 0x%x 0x%lx", - &rpid, &rcmd, &rerrflg, &rresponse) != 4 + if (sscanf (buff, "0x%x %c 0x%x 0x%16s", + &rpid, &rcmd, &rerrflg, response_string) != 4 + || !read_hex_value (response_string, &rresponse) || (cmd != '\0' && rcmd != cmd)) - mips_error ("Bad response from remote board"); + mips_error (_("Bad response from remote board")); if (rerrflg != 0) { @@ -1253,18 +1306,25 @@ mips_request (int cmd, return rresponse; } +/* Cleanup associated with mips_initialize(). */ + static void mips_initialize_cleanups (void *arg) { mips_initializing = 0; } +/* Cleanup associated with mips_exit_debug(). */ + static void mips_exit_cleanups (void *arg) { mips_exiting = 0; } +/* Send a command and wait for that command to be echoed back. Wait, + too, for the following prompt. */ + static void mips_send_command (const char *cmd, int prompt) { @@ -1276,6 +1336,7 @@ mips_send_command (const char *cmd, int prompt) } /* Enter remote (dbx) debug mode: */ + static void mips_enter_debug (void) { @@ -1285,27 +1346,29 @@ mips_enter_debug (void) if (mips_monitor != MON_IDT) mips_send_command ("debug\r", 0); - else /* assume IDT monitor by default */ + else /* Assume IDT monitor by default. */ mips_send_command ("db tty0\r", 0); - sleep (1); + gdb_usleep (1000000); serial_write (mips_desc, "\r", sizeof "\r" - 1); /* We don't need to absorb any spurious characters here, since the mips_receive_header will eat up a reasonable number of characters whilst looking for the SYN, however this avoids the "garbage" - being displayed to the user. */ + being displayed to the user. */ if (mips_monitor != MON_IDT) mips_expect ("\r"); { char buff[DATA_MAXLEN + 1]; + if (mips_receive_packet (buff, 1, 3) < 0) - mips_error ("Failed to initialize (didn't receive packet)."); + mips_error (_("Failed to initialize (didn't receive packet).")); } } /* Exit remote (dbx) debug mode, returning to the monitor prompt: */ + static int mips_exit_debug (void) { @@ -1314,7 +1377,7 @@ mips_exit_debug (void) mips_exiting = 1; - if (mips_monitor != MON_IDT) + if (mips_monitor != MON_IDT && mips_monitor != MON_ROCKHOPPER) { /* The DDB (NEC) and MiniRISC (LSI) versions of PMON exit immediately, so we do not get a reply to this command: */ @@ -1350,7 +1413,7 @@ mips_initialize (void) if (mips_initializing) { - warning ("internal error: mips_initialize called twice"); + warning (_("internal error: mips_initialize called twice")); return; } @@ -1363,24 +1426,25 @@ mips_initialize (void) /* Force the system into the monitor. After this we *should* be at the mips_monitor_prompt. */ if (mips_monitor != MON_IDT) - j = 0; /* start by checking if we are already at the prompt */ + j = 0; /* Start by checking if we are already + at the prompt. */ else - j = 1; /* start by sending a break */ + j = 1; /* Start by sending a break. */ for (; j <= 4; j++) { switch (j) { - case 0: /* First, try sending a CR */ + case 0: /* First, try sending a CR. */ serial_flush_input (mips_desc); serial_write (mips_desc, "\r", 1); break; - case 1: /* First, try sending a break */ + case 1: /* First, try sending a break. */ serial_send_break (mips_desc); break; - case 2: /* Then, try a ^C */ + case 2: /* Then, try a ^C. */ serial_write (mips_desc, "\003", 1); break; - case 3: /* Then, try escaping from download */ + case 3: /* Then, try escaping from download. */ { if (mips_monitor != MON_IDT) { @@ -1389,9 +1453,9 @@ mips_initialize (void) /* We shouldn't need to send multiple termination sequences, since the target performs line (or block) reads, and then processes those - packets. In-case we were downloading a large packet + packets. In-case we were downloading a large packet we flush the output buffer before inserting a - termination sequence. */ + termination sequence. */ serial_flush_output (mips_desc); sprintf (tbuff, "\r/E/E\r"); serial_write (mips_desc, tbuff, 6); @@ -1407,8 +1471,7 @@ mips_initialize (void) out is to send enough termination packets (8 bytes) to fill up and then overflow the largest size S-record (255 bytes in this case). This amounts to - 256/8 + 1 packets. - */ + 256/8 + 1 packets. */ mips_make_srec (srec, '7', 0, NULL, 0); @@ -1418,13 +1481,13 @@ mips_initialize (void) if (serial_readchar (mips_desc, 0) >= 0) break; /* Break immediatly if we get something from - the board. */ + the board. */ } } } break; case 4: - mips_error ("Failed to initialize."); + mips_error (_("Failed to initialize.")); } if (mips_expect (mips_monitor_prompt)) @@ -1446,14 +1509,14 @@ mips_initialize (void) /* Delete all the current breakpoints: */ mips_send_command ("db *\r", -1); /* NOTE: PMON does not have breakpoint support through the - "debug" mode, only at the monitor command-line. */ + "debug" mode, only at the monitor command-line. */ } mips_enter_debug (); /* Clear all breakpoints: */ if ((mips_monitor == MON_IDT - && clear_breakpoint (-1, 0, BREAK_UNUSED) == 0) + && mips_clear_breakpoint (-1, 0, BREAK_UNUSED) == 0) || mips_monitor == MON_LSI) monitor_supports_breakpoints = 1; else @@ -1468,6 +1531,7 @@ mips_initialize (void) } /* Open a connection to the remote board. */ + static void common_open (struct target_ops *ops, char *name, int from_tty, enum mips_monitor_type new_monitor, @@ -1480,27 +1544,26 @@ common_open (struct target_ops *ops, char *name, int from_tty, char **argv; if (name == 0) - error ( - "To open a MIPS remote debugging connection, you need to specify what serial\n\ -device is attached to the target board (e.g., /dev/ttya).\n" - "If you want to use TFTP to download to the board, specify the name of a\n" - "temporary file to be used by GDB for downloads as the second argument.\n" - "This filename must be in the form host:filename, where host is the name\n" - "of the host running the TFTP server, and the file must be readable by the\n" - "world. If the local name of the temporary file differs from the name as\n" - "seen from the board via TFTP, specify that name as the third parameter.\n"); + error (_("\ +To open a MIPS remote debugging connection, you need to specify what\n\ +serial device is attached to the target board (e.g., /dev/ttya).\n\ +If you want to use TFTP to download to the board, specify the name of a\n\ +temporary file to be used by GDB for downloads as the second argument.\n\ +This filename must be in the form host:filename, where host is the name\n\ +of the host running the TFTP server, and the file must be readable by the\n\ +world. If the local name of the temporary file differs from the name as\n\ +seen from the board via TFTP, specify that name as the third parameter.\n")); /* Parse the serial port name, the optional TFTP name, and the optional local TFTP name. */ - if ((argv = buildargv (name)) == NULL) - nomem (0); + argv = gdb_buildargv (name); make_cleanup_freeargv (argv); serial_port_name = xstrdup (argv[0]); - if (argv[1]) /* remote TFTP name specified? */ + if (argv[1]) /* Remote TFTP name specified? */ { remote_name = argv[1]; - if (argv[2]) /* local TFTP filename specified? */ + if (argv[2]) /* Local TFTP filename specified? */ local_name = argv[2]; } @@ -1535,7 +1598,7 @@ device is attached to the target board (e.g., /dev/ttya).\n" { udp_desc = serial_open (remote_name); if (!udp_desc) - perror_with_name ("Unable to open UDP port"); + perror_with_name (_("Unable to open UDP port")); udp_in_use = 1; } else @@ -1549,9 +1612,9 @@ device is attached to the target board (e.g., /dev/ttya).\n" xfree (tftp_localname); if (local_name == NULL) if ((local_name = strchr (remote_name, ':')) != NULL) - local_name++; /* skip over the colon */ + local_name++; /* Skip over the colon. */ if (local_name == NULL) - local_name = remote_name; /* local name same as remote name */ + local_name = remote_name; /* Local name same as remote name. */ tftp_name = xstrdup (remote_name); tftp_localname = xstrdup (local_name); tftp_in_use = 1; @@ -1574,7 +1637,9 @@ device is attached to the target board (e.g., /dev/ttya).\n" /* Switch to using remote target now. */ push_target (ops); - /* FIXME: Should we call start_remote here? */ + inferior_ptid = remote_mips_ptid; + inferior_appeared (current_inferior (), ptid_get_pid (inferior_ptid)); + add_thread_silent (inferior_ptid); /* Try to figure out the processor model if possible. */ deprecated_mips_set_processor_regs_hack (); @@ -1584,21 +1649,23 @@ device is attached to the target board (e.g., /dev/ttya).\n" of some sort. That doesn't happen here (in fact, it may not be possible to get the monitor to send the appropriate packet). */ - flush_cached_frames (); + reinit_frame_cache (); registers_changed (); - stop_pc = read_pc (); + stop_pc = regcache_read_pc (get_current_regcache ()); print_stack_frame (get_selected_frame (NULL), 0, SRC_AND_LOC); xfree (serial_port_name); } +/* Open a connection to an IDT board. */ + static void mips_open (char *name, int from_tty) { const char *monitor_prompt = NULL; - if (TARGET_ARCHITECTURE != NULL - && TARGET_ARCHITECTURE->arch == bfd_arch_mips) + if (gdbarch_bfd_arch_info (target_gdbarch) != NULL + && gdbarch_bfd_arch_info (target_gdbarch)->arch == bfd_arch_mips) { - switch (TARGET_ARCHITECTURE->mach) + switch (gdbarch_bfd_arch_info (target_gdbarch)->mach) { case bfd_mach_mips4100: case bfd_mach_mips4300: @@ -1614,18 +1681,32 @@ mips_open (char *name, int from_tty) common_open (&mips_ops, name, from_tty, MON_IDT, monitor_prompt); } +/* Open a connection to a PMON board. */ + static void pmon_open (char *name, int from_tty) { common_open (&pmon_ops, name, from_tty, MON_PMON, "PMON> "); } +/* Open a connection to a DDB board. */ + static void ddb_open (char *name, int from_tty) { common_open (&ddb_ops, name, from_tty, MON_DDB, "NEC010>"); } +/* Open a connection to a rockhopper board. */ + +static void +rockhopper_open (char *name, int from_tty) +{ + common_open (&rockhopper_ops, name, from_tty, MON_ROCKHOPPER, "NEC01>"); +} + +/* Open a connection to an LSI board. */ + static void lsi_open (char *name, int from_tty) { @@ -1650,15 +1731,17 @@ mips_close (int quitting) close_ports (); } + + generic_mourn_inferior (); } /* Detach from the remote board. */ static void -mips_detach (char *args, int from_tty) +mips_detach (struct target_ops *ops, char *args, int from_tty) { if (args) - error ("Argument given to \"detach\" when remotely debugging."); + error (_("Argument given to \"detach\" when remotely debugging.")); pop_target (); @@ -1673,7 +1756,8 @@ mips_detach (char *args, int from_tty) where PMON does return a reply. */ static void -mips_resume (ptid_t ptid, int step, enum target_signal siggnal) +mips_resume (struct target_ops *ops, + ptid_t ptid, int step, enum target_signal siggnal) { int err; @@ -1686,6 +1770,7 @@ mips_resume (ptid_t ptid, int step, enum target_signal siggnal) /* Return the signal corresponding to SIG, where SIG is the number which the MIPS protocol uses for the signal. */ + static enum target_signal mips_signal_from_protocol (int sig) { @@ -1703,16 +1788,45 @@ mips_signal_from_protocol (int sig) return (enum target_signal) sig; } +/* Set the register designated by REGNO to the value designated by VALUE. */ + +static void +mips_set_register (int regno, ULONGEST value) +{ + char buf[MAX_REGISTER_SIZE]; + struct regcache *regcache = get_current_regcache (); + struct gdbarch *gdbarch = get_regcache_arch (regcache); + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + + /* We got the number the register holds, but gdb expects to see a + value in the target byte ordering. */ + + if (mips_monitor != MON_ROCKHOPPER + && (regno == mips_regnum (gdbarch)->pc || regno < 32)) + /* Some 64-bit boards have monitors that only send the bottom 32 bits. + In such cases we can only really debug 32-bit code properly so, + when reading a GPR or the PC, assume that the full 64-bit + value is the sign extension of the lower 32 bits. */ + store_signed_integer (buf, register_size (gdbarch, regno), byte_order, + value); + else + store_unsigned_integer (buf, register_size (gdbarch, regno), byte_order, + value); + + regcache_raw_supply (regcache, regno, buf); +} + /* Wait until the remote stops, and return a wait status. */ static ptid_t -mips_wait (ptid_t ptid, struct target_waitstatus *status) +mips_wait (struct target_ops *ops, + ptid_t ptid, struct target_waitstatus *status, int options) { int rstatus; int err; char buff[DATA_MAXLEN]; - int rpc, rfp, rsp; - char flags[20]; + ULONGEST rpc, rfp, rsp; + char pc_string[17], fp_string[17], sp_string[17], flags[20]; int nfields; int i; @@ -1734,41 +1848,39 @@ mips_wait (ptid_t ptid, struct target_waitstatus *status) rstatus = mips_request ('\000', 0, 0, &err, -1, buff); mips_wait_flag = 0; if (err) - mips_error ("Remote failure: %s", safe_strerror (errno)); + mips_error (_("Remote failure: %s"), safe_strerror (errno)); /* On returning from a continue, the PMON monitor seems to start echoing back the messages we send prior to sending back the - ACK. The code can cope with this, but to try and avoid the + ACK. The code can cope with this, but to try and avoid the unnecessary serial traffic, and "spurious" characters displayed - to the user, we cheat and reset the debug protocol. The problems + to the user, we cheat and reset the debug protocol. The problems seems to be caused by a check on the number of arguments, and the command length, within the monitor causing it to echo the command - as a bad packet. */ + as a bad packet. */ if (mips_monitor == MON_PMON) { mips_exit_debug (); mips_enter_debug (); } - /* See if we got back extended status. If so, pick out the pc, fp, sp, etc... */ + /* See if we got back extended status. If so, pick out the pc, fp, + sp, etc... */ - nfields = sscanf (buff, "0x%*x %*c 0x%*x 0x%*x 0x%x 0x%x 0x%x 0x%*x %s", - &rpc, &rfp, &rsp, flags); - if (nfields >= 3) + nfields = sscanf (buff, + "0x%*x %*c 0x%*x 0x%*x 0x%16s 0x%16s 0x%16s 0x%*x %s", + pc_string, fp_string, sp_string, flags); + if (nfields >= 3 + && read_hex_value (pc_string, &rpc) + && read_hex_value (fp_string, &rfp) + && read_hex_value (sp_string, &rsp)) { - char buf[MAX_REGISTER_SIZE]; - - store_unsigned_integer (buf, register_size (current_gdbarch, PC_REGNUM), rpc); - regcache_raw_supply (current_regcache, PC_REGNUM, buf); + struct regcache *regcache = get_current_regcache (); + struct gdbarch *gdbarch = get_regcache_arch (regcache); - store_unsigned_integer (buf, register_size (current_gdbarch, PC_REGNUM), rfp); - regcache_raw_supply (current_regcache, 30, buf); /* This register they are avoiding and so it is unnamed */ - - store_unsigned_integer (buf, register_size (current_gdbarch, SP_REGNUM), rsp); - regcache_raw_supply (current_regcache, SP_REGNUM, buf); - - store_unsigned_integer (buf, register_size (current_gdbarch, DEPRECATED_FP_REGNUM), 0); - regcache_raw_supply (current_regcache, DEPRECATED_FP_REGNUM, buf); + mips_set_register (gdbarch_pc_regnum (gdbarch), rpc); + mips_set_register (30, rfp); + mips_set_register (gdbarch_sp_regnum (gdbarch), rsp); if (nfields == 9) { @@ -1785,14 +1897,15 @@ mips_wait (ptid_t ptid, struct target_waitstatus *status) if (strcmp (target_shortname, "lsi") == 0) { #if 0 - /* If this is an LSI PMON target, see if we just hit a hardrdware watchpoint. - Right now, PMON doesn't give us enough information to determine which - breakpoint we hit. So we have to look up the PC in our own table - of breakpoints, and if found, assume it's just a normal instruction - fetch breakpoint, not a data watchpoint. FIXME when PMON - provides some way to tell us what type of breakpoint it is. */ + /* If this is an LSI PMON target, see if we just hit a + hardrdware watchpoint. Right now, PMON doesn't give us + enough information to determine which breakpoint we hit. So + we have to look up the PC in our own table of breakpoints, + and if found, assume it's just a normal instruction fetch + breakpoint, not a data watchpoint. FIXME when PMON provides + some way to tell us what type of breakpoint it is. */ int i; - CORE_ADDR pc = read_pc (); + CORE_ADDR pc = regcache_read_pc (get_current_regcache ()); hit_watchpoint = 1; for (i = 0; i < MAX_LSI_BREAKPOINTS; i++) @@ -1843,7 +1956,7 @@ mips_wait (ptid_t ptid, struct target_waitstatus *status) { char *func_name; CORE_ADDR func_start; - CORE_ADDR pc = read_pc (); + CORE_ADDR pc = regcache_read_pc (get_current_regcache ()); find_pc_partial_function (pc, &func_name, &func_start, NULL); if (func_name != NULL && strcmp (func_name, "_exit") == 0 @@ -1866,24 +1979,24 @@ mips_wait (ptid_t ptid, struct target_waitstatus *status) #define REGNO_OFFSET 96 static int -mips_map_regno (int regno) +mips_map_regno (struct gdbarch *gdbarch, int regno) { if (regno < 32) return regno; - if (regno >= mips_regnum (current_gdbarch)->fp0 - && regno < mips_regnum (current_gdbarch)->fp0 + 32) - return regno - mips_regnum (current_gdbarch)->fp0 + 32; - else if (regno == mips_regnum (current_gdbarch)->pc) + if (regno >= mips_regnum (gdbarch)->fp0 + && regno < mips_regnum (gdbarch)->fp0 + 32) + return regno - mips_regnum (gdbarch)->fp0 + 32; + else if (regno == mips_regnum (gdbarch)->pc) return REGNO_OFFSET + 0; - else if (regno == mips_regnum (current_gdbarch)->cause) + else if (regno == mips_regnum (gdbarch)->cause) return REGNO_OFFSET + 1; - else if (regno == mips_regnum (current_gdbarch)->hi) + else if (regno == mips_regnum (gdbarch)->hi) return REGNO_OFFSET + 2; - else if (regno == mips_regnum (current_gdbarch)->lo) + else if (regno == mips_regnum (gdbarch)->lo) return REGNO_OFFSET + 3; - else if (regno == mips_regnum (current_gdbarch)->fp_control_status) + else if (regno == mips_regnum (gdbarch)->fp_control_status) return REGNO_OFFSET + 4; - else if (regno == mips_regnum (current_gdbarch)->fp_implementation_revision) + else if (regno == mips_regnum (gdbarch)->fp_implementation_revision) return REGNO_OFFSET + 5; else /* FIXME: Is there a way to get the status register? */ @@ -1893,113 +2006,115 @@ mips_map_regno (int regno) /* Fetch the remote registers. */ static void -mips_fetch_registers (int regno) +mips_fetch_registers (struct target_ops *ops, + struct regcache *regcache, int regno) { - unsigned LONGEST val; + struct gdbarch *gdbarch = get_regcache_arch (regcache); + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + ULONGEST val; int err; if (regno == -1) { - for (regno = 0; regno < NUM_REGS; regno++) - mips_fetch_registers (regno); + for (regno = 0; regno < gdbarch_num_regs (gdbarch); regno++) + mips_fetch_registers (ops, regcache, regno); return; } - if (regno == DEPRECATED_FP_REGNUM || regno == MIPS_ZERO_REGNUM) - /* DEPRECATED_FP_REGNUM on the mips is a hack which is just + if (regno == gdbarch_deprecated_fp_regnum (gdbarch) + || regno == MIPS_ZERO_REGNUM) + /* gdbarch_deprecated_fp_regnum on the mips is a hack which is just supposed to read zero (see also mips-nat.c). */ val = 0; else { /* If PMON doesn't support this register, don't waste serial bandwidth trying to read it. */ - int pmon_reg = mips_map_regno (regno); + int pmon_reg = mips_map_regno (gdbarch, regno); + if (regno != 0 && pmon_reg == 0) val = 0; else { /* Unfortunately the PMON version in the Vr4300 board has been - compiled without the 64bit register access commands. This - means we cannot get hold of the full register width. */ - if (mips_monitor == MON_DDB) - val = (unsigned) mips_request ('t', pmon_reg, 0, - &err, mips_receive_wait, NULL); + compiled without the 64bit register access commands. This + means we cannot get hold of the full register width. */ + if (mips_monitor == MON_DDB || mips_monitor == MON_ROCKHOPPER) + val = mips_request ('t', pmon_reg, 0, + &err, mips_receive_wait, NULL); else val = mips_request ('r', pmon_reg, 0, &err, mips_receive_wait, NULL); if (err) - mips_error ("Can't read register %d: %s", regno, + mips_error (_("Can't read register %d: %s"), regno, safe_strerror (errno)); } } - { - char buf[MAX_REGISTER_SIZE]; - - /* We got the number the register holds, but gdb expects to see a - value in the target byte ordering. */ - store_unsigned_integer (buf, register_size (current_gdbarch, regno), val); - regcache_raw_supply (current_regcache, regno, buf); - } + mips_set_register (regno, val); } /* Prepare to store registers. The MIPS protocol can store individual registers, so this function doesn't have to do anything. */ static void -mips_prepare_to_store (void) +mips_prepare_to_store (struct regcache *regcache) { } /* Store remote register(s). */ static void -mips_store_registers (int regno) +mips_store_registers (struct target_ops *ops, + struct regcache *regcache, int regno) { + struct gdbarch *gdbarch = get_regcache_arch (regcache); + ULONGEST val; int err; if (regno == -1) { - for (regno = 0; regno < NUM_REGS; regno++) - mips_store_registers (regno); + for (regno = 0; regno < gdbarch_num_regs (gdbarch); regno++) + mips_store_registers (ops, regcache, regno); return; } - mips_request ('R', mips_map_regno (regno), - read_register (regno), + regcache_cooked_read_unsigned (regcache, regno, &val); + mips_request (mips_monitor == MON_ROCKHOPPER ? 'T' : 'R', + mips_map_regno (gdbarch, regno), + val, &err, mips_receive_wait, NULL); if (err) - mips_error ("Can't write register %d: %s", regno, safe_strerror (errno)); + mips_error (_("Can't write register %d: %s"), regno, + safe_strerror (errno)); } -/* Fetch a word from the target board. */ +/* Fetch a word from the target board. Return word fetched in location + addressed by VALP. Return 0 when successful; return positive error + code when not. */ -static unsigned int -mips_fetch_word (CORE_ADDR addr) +static int +mips_fetch_word (CORE_ADDR addr, unsigned int *valp) { - unsigned int val; int err; - val = mips_request ('d', addr, 0, &err, mips_receive_wait, NULL); + *valp = mips_request ('d', addr, 0, &err, mips_receive_wait, NULL); if (err) { /* Data space failed; try instruction space. */ - val = mips_request ('i', addr, 0, &err, - mips_receive_wait, NULL); - if (err) - mips_error ("Can't read address 0x%s: %s", - paddr_nz (addr), safe_strerror (errno)); + *valp = mips_request ('i', addr, 0, &err, + mips_receive_wait, NULL); } - return val; + return err; } /* Store a word to the target board. Returns errno code or zero for success. If OLD_CONTENTS is non-NULL, put the old contents of that memory location there. */ -/* FIXME! make sure only 32-bit quantities get stored! */ +/* FIXME! make sure only 32-bit quantities get stored! */ static int -mips_store_word (CORE_ADDR addr, unsigned int val, char *old_contents) +mips_store_word (CORE_ADDR addr, unsigned int val, int *old_contents) { int err; unsigned int oldcontents; @@ -2015,7 +2130,7 @@ mips_store_word (CORE_ADDR addr, unsigned int val, char *old_contents) return errno; } if (old_contents != NULL) - store_unsigned_integer (old_contents, 4, oldcontents); + *old_contents = oldcontents; return 0; } @@ -2029,9 +2144,10 @@ mips_store_word (CORE_ADDR addr, unsigned int val, char *old_contents) static int mask_address_p = 1; static int -mips_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write, +mips_xfer_memory (CORE_ADDR memaddr, gdb_byte *myaddr, int len, int write, struct mem_attrib *attrib, struct target_ops *target) { + enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch); int i; CORE_ADDR addr; int count; @@ -2039,7 +2155,7 @@ mips_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write, int status; /* PMON targets do not cope well with 64 bit addresses. Mask the - value down to 32 bits. */ + value down to 32 bits. */ if (mask_address_p) memaddr &= (CORE_ADDR) 0xffffffff; @@ -2055,19 +2171,29 @@ mips_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write, /* Fill start and end extra bytes of buffer with existing data. */ if (addr != memaddr || len < 4) { + unsigned int val; + + if (mips_fetch_word (addr, &val)) + return 0; + /* Need part of initial word -- fetch it. */ - store_unsigned_integer (&buffer[0], 4, mips_fetch_word (addr)); + store_unsigned_integer (&buffer[0], 4, byte_order, val); } if (count > 1) { + unsigned int val; + /* Need part of last word -- fetch it. FIXME: we do this even if we don't need it. */ - store_unsigned_integer (&buffer[(count - 1) * 4], 4, - mips_fetch_word (addr + (count - 1) * 4)); + if (mips_fetch_word (addr + (count - 1) * 4, &val)) + return 0; + + store_unsigned_integer (&buffer[(count - 1) * 4], + 4, byte_order, val); } - /* Copy data to be written over corresponding part of buffer */ + /* Copy data to be written over corresponding part of buffer. */ memcpy ((char *) buffer + (memaddr & 3), myaddr, len); @@ -2075,10 +2201,11 @@ mips_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write, for (i = 0; i < count; i++, addr += 4) { - status = mips_store_word (addr, - extract_unsigned_integer (&buffer[i * 4], 4), - NULL); - /* Report each kilobyte (we download 32-bit words at a time) */ + int word; + + word = extract_unsigned_integer (&buffer[i * 4], 4, byte_order); + status = mips_store_word (addr, word, NULL); + /* Report each kilobyte (we download 32-bit words at a time). */ if (i % 256 == 255) { printf_unfiltered ("*"); @@ -2096,10 +2223,15 @@ mips_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write, } else { - /* Read all the longwords */ + /* Read all the longwords. */ for (i = 0; i < count; i++, addr += 4) { - store_unsigned_integer (&buffer[i * 4], 4, mips_fetch_word (addr)); + unsigned int val; + + if (mips_fetch_word (addr, &val)) + return 0; + + store_unsigned_integer (&buffer[i * 4], 4, byte_order, val); QUIT; } @@ -2123,10 +2255,13 @@ mips_files_info (struct target_ops *ignore) right port, we could interrupt the process with a break signal. */ static void -mips_kill (void) +mips_kill (struct target_ops *ops) { if (!mips_wait_flag) - return; + { + target_mourn_inferior (); + return; + } interrupt_count++; @@ -2136,19 +2271,19 @@ mips_kill (void) target_terminal_ours (); - if (query ("Interrupted while waiting for the program.\n\ -Give up (and stop debugging it)? ")) + if (query (_("Interrupted while waiting for the program.\n\ +Give up (and stop debugging it)? "))) { - /* Clean up in such a way that mips_close won't try to talk to the - board (it almost surely won't work since we weren't able to talk to - it). */ + /* Clean up in such a way that mips_close won't try to talk + to the board (it almost surely won't work since we + weren't able to talk to it). */ mips_wait_flag = 0; close_ports (); printf_unfiltered ("Ending remote MIPS debugging.\n"); target_mourn_inferior (); - throw_reason (RETURN_QUIT); + deprecated_throw_reason (RETURN_QUIT); } target_terminal_inferior (); @@ -2159,6 +2294,8 @@ Give up (and stop debugging it)? ")) serial_send_break (mips_desc); + target_mourn_inferior (); + #if 0 if (mips_is_open) { @@ -2176,38 +2313,37 @@ Give up (and stop debugging it)? ")) /* Start running on the target board. */ static void -mips_create_inferior (char *execfile, char *args, char **env, int from_tty) +mips_create_inferior (struct target_ops *ops, char *execfile, + char *args, char **env, int from_tty) { CORE_ADDR entry_pt; if (args && *args) { - warning ("\ -Can't pass arguments to remote MIPS board; arguments ignored."); + warning (_("\ +Can't pass arguments to remote MIPS board; arguments ignored.")); /* And don't try to use them on the next "run" command. */ execute_command ("set args", 0); } if (execfile == 0 || exec_bfd == 0) - error ("No executable file specified"); + error (_("No executable file specified")); entry_pt = (CORE_ADDR) bfd_get_start_address (exec_bfd); init_wait_for_inferior (); - /* FIXME: Should we set inferior_ptid here? */ - - proceed (entry_pt, TARGET_SIGNAL_DEFAULT, 0); + regcache_write_pc (get_current_regcache (), entry_pt); } -/* Clean up after a process. Actually nothing to do. */ +/* Clean up after a process. The bulk of the work is done in mips_close(), + which is called when unpushing the target. */ static void -mips_mourn_inferior (void) +mips_mourn_inferior (struct target_ops *ops) { if (current_ops != NULL) unpush_target (current_ops); - generic_mourn_inferior (); } /* We can write a breakpoint and read the shadow contents in one @@ -2216,32 +2352,37 @@ mips_mourn_inferior (void) /* Insert a breakpoint. On targets that don't have built-in breakpoint support, we read the contents of the target location and stash it, then overwrite it with a breakpoint instruction. ADDR is - the target location in the target machine. CONTENTS_CACHE is a - pointer to memory allocated for saving the target contents. It is - guaranteed by the caller to be long enough to save the breakpoint - length returned by BREAKPOINT_FROM_PC. */ + the target location in the target machine. BPT is the breakpoint + being inserted or removed, which contains memory for saving the + target contents. */ static int -mips_insert_breakpoint (CORE_ADDR addr, char *contents_cache) +mips_insert_breakpoint (struct gdbarch *gdbarch, + struct bp_target_info *bp_tgt) { if (monitor_supports_breakpoints) - return set_breakpoint (addr, MIPS_INSN32_SIZE, BREAK_FETCH); + return mips_set_breakpoint (bp_tgt->placed_address, MIPS_INSN32_SIZE, + BREAK_FETCH); else - return memory_insert_breakpoint (addr, contents_cache); + return memory_insert_breakpoint (gdbarch, bp_tgt); } +/* Remove a breakpoint. */ + static int -mips_remove_breakpoint (CORE_ADDR addr, char *contents_cache) +mips_remove_breakpoint (struct gdbarch *gdbarch, + struct bp_target_info *bp_tgt) { if (monitor_supports_breakpoints) - return clear_breakpoint (addr, MIPS_INSN32_SIZE, BREAK_FETCH); + return mips_clear_breakpoint (bp_tgt->placed_address, MIPS_INSN32_SIZE, + BREAK_FETCH); else - return memory_remove_breakpoint (addr, contents_cache); + return memory_remove_breakpoint (gdbarch, bp_tgt); } /* Tell whether this target can support a hardware breakpoint. CNT is the number of hardware breakpoints already installed. This - implements the TARGET_CAN_USE_HARDWARE_WATCHPOINT macro. */ + implements the target_can_use_hardware_watchpoint macro. */ int mips_can_use_watchpoint (int type, int cnt, int othertype) @@ -2275,26 +2416,33 @@ calculate_mask (CORE_ADDR addr, int len) /* Set a data watchpoint. ADDR and LEN should be obvious. TYPE is 0 for a write watchpoint, 1 for a read watchpoint, or 2 for a read/write - watchpoint. */ + watchpoint. */ int -mips_insert_watchpoint (CORE_ADDR addr, int len, int type) +mips_insert_watchpoint (CORE_ADDR addr, int len, int type, + struct expression *cond) { - if (set_breakpoint (addr, len, type)) + if (mips_set_breakpoint (addr, len, type)) return -1; return 0; } +/* Remove a watchpoint. */ + int -mips_remove_watchpoint (CORE_ADDR addr, int len, int type) +mips_remove_watchpoint (CORE_ADDR addr, int len, int type, + struct expression *cond) { - if (clear_breakpoint (addr, len, type)) + if (mips_clear_breakpoint (addr, len, type)) return -1; return 0; } +/* Test to see if a watchpoint has been hit. Return 1 if so; return 0, + if not. */ + int mips_stopped_by_watchpoint (void) { @@ -2305,18 +2453,18 @@ mips_stopped_by_watchpoint (void) /* Insert a breakpoint. */ static int -set_breakpoint (CORE_ADDR addr, int len, enum break_type type) +mips_set_breakpoint (CORE_ADDR addr, int len, enum break_type type) { - return common_breakpoint (1, addr, len, type); + return mips_common_breakpoint (1, addr, len, type); } /* Clear a breakpoint. */ static int -clear_breakpoint (CORE_ADDR addr, int len, enum break_type type) +mips_clear_breakpoint (CORE_ADDR addr, int len, enum break_type type) { - return common_breakpoint (0, addr, len, type); + return mips_common_breakpoint (0, addr, len, type); } @@ -2324,14 +2472,14 @@ clear_breakpoint (CORE_ADDR addr, int len, enum break_type type) command. If there's no error, just return 0. If it's a warning, print the warning text and return 0. If it's an error, print the error text and return 1. is the address of the breakpoint - that was being set. is the error code returned by PMON. - This is a helper function for common_breakpoint. */ + that was being set. is the error code returned by PMON. + This is a helper function for mips_common_breakpoint. */ static int -check_lsi_error (CORE_ADDR addr, int rerrflg) +mips_check_lsi_error (CORE_ADDR addr, int rerrflg) { struct lsi_error *err; - char *saddr = paddr_nz (addr); /* printable address string */ + const char *saddr = paddress (target_gdbarch, addr); if (rerrflg == 0) /* no error */ return 0; @@ -2342,20 +2490,21 @@ check_lsi_error (CORE_ADDR addr, int rerrflg) if (monitor_warnings) { int found = 0; + for (err = lsi_warning_table; err->code != 0; err++) { if ((err->code & rerrflg) == err->code) { found = 1; - fprintf_unfiltered (gdb_stderr, - "common_breakpoint (0x%s): Warning: %s\n", + fprintf_unfiltered (gdb_stderr, "\ +mips_common_breakpoint (%s): Warning: %s\n", saddr, err->string); } } if (!found) - fprintf_unfiltered (gdb_stderr, - "common_breakpoint (0x%s): Unknown warning: 0x%x\n", + fprintf_unfiltered (gdb_stderr, "\ +mips_common_breakpoint (%s): Unknown warning: 0x%x\n", saddr, rerrflg); } @@ -2367,15 +2516,15 @@ check_lsi_error (CORE_ADDR addr, int rerrflg) { if ((err->code & rerrflg) == err->code) { - fprintf_unfiltered (gdb_stderr, - "common_breakpoint (0x%s): Error: %s\n", + fprintf_unfiltered (gdb_stderr, "\ +mips_common_breakpoint (%s): Error: %s\n", saddr, err->string); return 1; } } - fprintf_unfiltered (gdb_stderr, - "common_breakpoint (0x%s): Unknown error: 0x%x\n", + fprintf_unfiltered (gdb_stderr, "\ +mips_common_breakpoint (%s): Unknown error: 0x%x\n", saddr, rerrflg); return 1; @@ -2396,14 +2545,15 @@ check_lsi_error (CORE_ADDR addr, int rerrflg) Return 0 if successful; otherwise 1. */ static int -common_breakpoint (int set, CORE_ADDR addr, int len, enum break_type type) +mips_common_breakpoint (int set, CORE_ADDR addr, int len, enum break_type type) { + int addr_size = gdbarch_addr_bit (target_gdbarch) / 8; char buf[DATA_MAXLEN + 1]; char cmd, rcmd; int rpid, rerrflg, rresponse, rlen; int nfields; - addr = ADDR_BITS_REMOVE (addr); + addr = gdbarch_addr_bits_remove (target_gdbarch, addr); if (mips_monitor == MON_LSI) { @@ -2429,8 +2579,9 @@ common_breakpoint (int set, CORE_ADDR addr, int len, enum break_type type) /* Clear the table entry and tell PMON to clear the breakpoint. */ if (i == MAX_LSI_BREAKPOINTS) { - warning ("common_breakpoint: Attempt to clear bogus breakpoint at %s\n", - paddr_nz (addr)); + warning (_("\ +mips_common_breakpoint: Attempt to clear bogus breakpoint at %s"), + paddress (target_gdbarch, addr)); return 1; } @@ -2443,9 +2594,11 @@ common_breakpoint (int set, CORE_ADDR addr, int len, enum break_type type) nfields = sscanf (buf, "0x%x b 0x0 0x%x", &rpid, &rerrflg); if (nfields != 2) - mips_error ("common_breakpoint: Bad response from remote board: %s", buf); + mips_error (_("mips_common_breakpoint: " + "Bad response from remote board: %s"), + buf); - return (check_lsi_error (addr, rerrflg)); + return (mips_check_lsi_error (addr, rerrflg)); } else /* set a breakpoint */ @@ -2470,22 +2623,21 @@ common_breakpoint (int set, CORE_ADDR addr, int len, enum break_type type) succesful completion, other values indicate various errors and warnings. - Possible return codes: OK, W_QAL, E_QAL, E_OUT, E_NON. - - */ + Possible return codes: OK, W_QAL, E_QAL, E_OUT, E_NON. */ if (type == BREAK_FETCH) /* instruction breakpoint */ { cmd = 'B'; - sprintf (buf, "0x0 B 0x%s 0x0", paddr_nz (addr)); + sprintf (buf, "0x0 B 0x%s 0x0", phex_nz (addr, addr_size)); } else /* watchpoint */ { cmd = 'A'; - sprintf (buf, "0x0 A 0x%s 0x%x 0x%s", paddr_nz (addr), - type == BREAK_READ ? 1 : (type == BREAK_WRITE ? 2 : 3), - paddr_nz (addr + len - 1)); + sprintf (buf, "0x0 A 0x%s 0x%x 0x%s", + phex_nz (addr, addr_size), + type == BREAK_READ ? 1 : (type == BREAK_WRITE ? 2 : 3), + phex_nz (addr + len - 1, addr_size)); } mips_send_packet (buf, 1); @@ -2495,10 +2647,12 @@ common_breakpoint (int set, CORE_ADDR addr, int len, enum break_type type) nfields = sscanf (buf, "0x%x %c 0x%x 0x%x", &rpid, &rcmd, &rresponse, &rerrflg); if (nfields != 4 || rcmd != cmd || rresponse > 255) - mips_error ("common_breakpoint: Bad response from remote board: %s", buf); + mips_error (_("mips_common_breakpoint: " + "Bad response from remote board: %s"), + buf); if (rerrflg != 0) - if (check_lsi_error (addr, rerrflg)) + if (mips_check_lsi_error (addr, rerrflg)) return 1; /* rresponse contains PMON's breakpoint number. Record the @@ -2515,8 +2669,9 @@ common_breakpoint (int set, CORE_ADDR addr, int len, enum break_type type) /* On non-LSI targets, the breakpoint command has this form: 0x0 is a don't care mask for addresses. - is any combination of `r', `w', or `f' for read/write/fetch. - */ + is any combination of `r', `w', or `f' for + read/write/fetch. */ + unsigned long mask; mask = calculate_mask (addr, len); @@ -2525,6 +2680,7 @@ common_breakpoint (int set, CORE_ADDR addr, int len, enum break_type type) if (set) /* set a breakpoint */ { char *flags; + switch (type) { case BREAK_WRITE: /* write */ @@ -2540,17 +2696,18 @@ common_breakpoint (int set, CORE_ADDR addr, int len, enum break_type type) flags = "f"; break; default: - internal_error (__FILE__, __LINE__, "failed internal consistency check"); + internal_error (__FILE__, __LINE__, + _("failed internal consistency check")); } cmd = 'B'; - sprintf (buf, "0x0 B 0x%s 0x%s %s", paddr_nz (addr), - paddr_nz (mask), flags); + sprintf (buf, "0x0 B 0x%s 0x%s %s", phex_nz (addr, addr_size), + phex_nz (mask, addr_size), flags); } else { cmd = 'b'; - sprintf (buf, "0x0 b 0x%s", paddr_nz (addr)); + sprintf (buf, "0x0 b 0x%s", phex_nz (addr, addr_size)); } mips_send_packet (buf, 1); @@ -2562,7 +2719,8 @@ common_breakpoint (int set, CORE_ADDR addr, int len, enum break_type type) &rpid, &rcmd, &rerrflg, &rresponse); if (nfields != 4 || rcmd != cmd) - mips_error ("common_breakpoint: Bad response from remote board: %s", + mips_error (_("mips_common_breakpoint: " + "Bad response from remote board: %s"), buf); if (rerrflg != 0) @@ -2572,15 +2730,20 @@ common_breakpoint (int set, CORE_ADDR addr, int len, enum break_type type) if (mips_monitor == MON_DDB) rresponse = rerrflg; if (rresponse != 22) /* invalid argument */ - fprintf_unfiltered (gdb_stderr, - "common_breakpoint (0x%s): Got error: 0x%x\n", - paddr_nz (addr), rresponse); + fprintf_unfiltered (gdb_stderr, "\ +mips_common_breakpoint (%s): Got error: 0x%x\n", + paddress (target_gdbarch, addr), rresponse); return 1; } } return 0; } +/* Send one S record as specified by SREC of length LEN, starting + at ADDR. Note, however, that ADDR is not used except to provide + a useful message to the user in the event that a NACK is received + from the board. */ + static void send_srec (char *srec, int len, CORE_ADDR addr) { @@ -2595,20 +2758,23 @@ send_srec (char *srec, int len, CORE_ADDR addr) switch (ch) { case SERIAL_TIMEOUT: - error ("Timeout during download."); + error (_("Timeout during download.")); break; case 0x6: /* ACK */ return; case 0x15: /* NACK */ - fprintf_unfiltered (gdb_stderr, "Download got a NACK at byte %s! Retrying.\n", paddr_u (addr)); + fprintf_unfiltered (gdb_stderr, + "Download got a NACK at byte %s! Retrying.\n", + paddress (target_gdbarch, addr)); continue; default: - error ("Download got unexpected ack char: 0x%x, retrying.\n", ch); + error (_("Download got unexpected ack char: 0x%x, retrying."), + ch); } } } -/* Download a binary file by converting it to S records. */ +/* Download a binary file by converting it to S records. */ static void mips_load_srec (char *args) @@ -2645,7 +2811,7 @@ mips_load_srec (char *args) { unsigned int numbytes; - /* FIXME! vma too small????? */ + /* FIXME! vma too small????? */ printf_filtered ("%s\t: 0x%4lx .. 0x%4lx ", s->name, (long) s->vma, (long) (s->vma + bfd_get_section_size (s))); @@ -2689,7 +2855,7 @@ mips_load_srec (char *args) } /* - * mips_make_srec -- make an srecord. This writes each line, one at a + * mips_make_srec -- make an srecord. This writes each line, one at a * time, each with it's own header and trailer line. * An srecord looks like this: * @@ -2706,7 +2872,7 @@ mips_load_srec (char *args) * * Where * - length - * is the number of bytes following upto the checksum. Note that + * is the number of bytes following upto the checksum. Note that * this is not the number of chars following, since it takes two * chars to represent a byte. * - type @@ -2739,16 +2905,16 @@ mips_make_srec (char *buf, int type, CORE_ADDR memaddr, unsigned char *myaddr, unsigned char checksum; int i; - /* Create the header for the srec. addr_size is the number of bytes in the address, - and 1 is the number of bytes in the count. */ + /* Create the header for the srec. addr_size is the number of bytes + in the address, and 1 is the number of bytes in the count. */ - /* FIXME!! bigger buf required for 64-bit! */ + /* FIXME!! bigger buf required for 64-bit! */ buf[0] = 'S'; buf[1] = type; buf[2] = len + 4 + 1; /* len + 4 byte address + 1 byte checksum */ - /* This assumes S3 style downloads (4byte addresses). There should + /* This assumes S3 style downloads (4byte addresses). There should probably be a check, or the code changed to make it more - explicit. */ + explicit. */ buf[3] = memaddr >> 24; buf[4] = memaddr >> 16; buf[5] = memaddr >> 8; @@ -2759,7 +2925,7 @@ mips_make_srec (char *buf, int type, CORE_ADDR memaddr, unsigned char *myaddr, hexified data. It includes the length, address and the data portions of the packet. */ checksum = 0; - buf += 2; /* Point at length byte */ + buf += 2; /* Point at length byte. */ for (i = 0; i < len + 4 + 1; i++) checksum += *buf++; @@ -2769,8 +2935,8 @@ mips_make_srec (char *buf, int type, CORE_ADDR memaddr, unsigned char *myaddr, } /* The following manifest controls whether we enable the simple flow - control support provided by the monitor. If enabled the code will - wait for an affirmative ACK between transmitting packets. */ + control support provided by the monitor. If enabled the code will + wait for an affirmative ACK between transmitting packets. */ #define DOETXACK (1) /* The PMON fast-download uses an encoded packet format constructed of @@ -2779,7 +2945,8 @@ mips_make_srec (char *buf, int type, CORE_ADDR memaddr, unsigned char *myaddr, 'K' clear checksum 'C' compare checksum (12bit value, not included in checksum calculation) - 'S' define symbol name (for addr) terminated with "," and padded to 4char boundary + 'S' define symbol name (for addr) terminated with "," + and padded to 4char boundary 'Z' zero fill multiple of 3bytes 'B' byte (12bit encoded value, of 8bit data) 'A' address (36bit encoded value) @@ -2794,12 +2961,14 @@ mips_make_srec (char *buf, int type, CORE_ADDR memaddr, unsigned char *myaddr, The encoding of numbers is done in 6bit fields. The 6bit value is used to index into this string to get the specific character encoding for the value: */ -static char encoding[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789,."; +static char encoding[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789,."; /* Convert the number of bits required into an encoded number, 6bits at a time (range 0..63). Keep a checksum if required (passed - pointer non-NULL). The function returns the number of encoded - characters written into the buffer. */ + pointer non-NULL). The function returns the number of encoded + characters written into the buffer. */ + static int pmon_makeb64 (unsigned long v, char *p, int n, int *chksum) { @@ -2808,13 +2977,16 @@ pmon_makeb64 (unsigned long v, char *p, int n, int *chksum) if ((n % 12) != 0) { fprintf_unfiltered (gdb_stderr, - "Fast encoding bitcount must be a multiple of 12bits: %dbit%s\n", n, (n == 1) ? "" : "s"); + "Fast encoding bitcount must be a " + "multiple of 12bits: %dbit%s\n", + n, (n == 1) ? "" : "s"); return (0); } if (n > 36) { fprintf_unfiltered (gdb_stderr, - "Fast encoding cannot process more than 36bits at the moment: %dbits\n", n); + "Fast encoding cannot process more " + "than 36bits at the moment: %dbits\n", n); return (0); } @@ -2843,7 +3015,8 @@ pmon_makeb64 (unsigned long v, char *p, int n, int *chksum) } /* Shorthand function (that could be in-lined) to output the zero-fill - escape sequence into the data stream. */ + escape sequence into the data stream. */ + static int pmon_zeroset (int recsize, char **buff, int *amount, unsigned int *chksum) { @@ -2856,6 +3029,20 @@ pmon_zeroset (int recsize, char **buff, int *amount, unsigned int *chksum) return (recsize + count + 2); } +/* Add the checksum specified by *VALUE to end of the record under + construction. *BUF specifies the location at which to begin + writing characters comprising the checksum information. RECSIZE + specifies the size of the record constructed thus far. (A trailing + NUL character may be present in the buffer holding the record, but + the record size does not include this character.) + + Return the total size of the record after adding the checksum escape, + the checksum itself, and the trailing newline. + + The checksum specified by *VALUE is zeroed out prior to returning. + Additionally, *BUF is updated to refer to the location just beyond + the record elements added by this call. */ + static int pmon_checkset (int recsize, char **buff, int *value) { @@ -2866,7 +3053,7 @@ pmon_checkset (int recsize, char **buff, int *value) count = pmon_makeb64 (*value, (*buff + 2), 12, NULL); *buff += (count + 2); sprintf (*buff, "\n"); - *buff += 2; /* include zero terminator */ + *buff += 2; /* Include zero terminator. */ /* Forcing a checksum validation clears the sum: */ *value = 0; return (recsize + count + 3); @@ -2875,7 +3062,7 @@ pmon_checkset (int recsize, char **buff, int *value) /* Amount of padding we leave after at the end of the output buffer, for the checksum and line termination characters: */ #define CHECKSIZE (4 + 4 + 4 + 2) -/* zero-fill, checksum, transfer end and line termination space. */ +/* zero-fill, checksum, transfer end and line termination space. */ /* The amount of binary data loaded from the object file in a single operation: */ @@ -2883,8 +3070,34 @@ pmon_checkset (int recsize, char **buff, int *value) /* Maximum line of data accepted by the monitor: */ #define MAXRECSIZE (550) -/* NOTE: This constant depends on the monitor being used. This value - is for PMON 5.x on the Cogent Vr4300 board. */ +/* NOTE: This constant depends on the monitor being used. This value + is for PMON 5.x on the Cogent Vr4300 board. */ + +/* Create a FastLoad format record. + + *OUTBUF is the buffer into which a FastLoad formatted record is + written. On return, the pointer position represented by *OUTBUF + is updated to point at the end of the data, i.e. the next position + in the buffer that may be written. No attempt is made to NUL- + terminate this portion of the record written to the buffer. + + INBUF contains the binary input data from which the FastLoad + formatted record will be built. *INPTR is an index into this + buffer. *INPTR is updated as the input is consumed. Thus, on + return, the caller has access to the position of the next input + byte yet to be processed. INAMOUNT is the size, in bytes, of the + input data. + + *RECSIZE will be written with the size of the record written to the + output buffer prior to returning. This size does not include a + NUL-termination byte as none is written to the output buffer. + + *CSUM is the output buffer checksum. It is updated as data is + written to the output buffer. + + *ZEROFILL is the current number of 3-byte zero sequences that have + been encountered. It is both an input and an output to this + function. */ static void pmon_make_fastrec (char **outbuf, unsigned char *inbuf, int *inptr, @@ -2895,9 +3108,9 @@ pmon_make_fastrec (char **outbuf, unsigned char *inbuf, int *inptr, char *p = *outbuf; /* This is a simple check to ensure that our data will fit within - the maximum allowable record size. Each record output is 4bytes - in length. We must allow space for a pending zero fill command, - the record, and a checksum record. */ + the maximum allowable record size. Each record output is 4bytes + in length. We must allow space for a pending zero fill command, + the record, and a checksum record. */ while ((*recsize < (MAXRECSIZE - CHECKSIZE)) && ((inamount - *inptr) > 0)) { /* Process the binary data: */ @@ -2913,14 +3126,17 @@ pmon_make_fastrec (char **outbuf, unsigned char *inbuf, int *inptr, } else { - unsigned int value = ((inbuf[*inptr + 0] << 16) | (inbuf[*inptr + 1] << 8) | inbuf[*inptr + 2]); - /* Simple check for zero data. TODO: A better check would be + unsigned int value = ((inbuf[*inptr + 0] << 16) + | (inbuf[*inptr + 1] << 8) + | (inbuf[*inptr + 2])); + + /* Simple check for zero data. TODO: A better check would be to check the last, and then the middle byte for being zero - (if the first byte is not). We could then check for + (if the first byte is not). We could then check for following runs of zeros, and if above a certain size it is worth the 4 or 8 character hit of the byte insertions used - to pad to the start of the zeroes. NOTE: This also depends - on the alignment at the end of the zero run. */ + to pad to the start of the zeroes. NOTE: This also depends + on the alignment at the end of the zero run. */ if (value == 0x00000000) { (*zerofill)++; @@ -2943,6 +3159,10 @@ pmon_make_fastrec (char **outbuf, unsigned char *inbuf, int *inptr, return; } +/* Attempt to read an ACK. If an ACK is not read in a timely manner, + output the message specified by MESG. Return -1 for failure, 0 + for success. */ + static int pmon_check_ack (char *mesg) { @@ -2957,7 +3177,7 @@ pmon_check_ack (char *mesg) { fprintf_unfiltered (gdb_stderr, "Failed to receive valid ACK for %s\n", mesg); - return (-1); /* terminate the download */ + return (-1); /* Terminate the download. */ } } #endif /* DOETXACK */ @@ -2985,6 +3205,12 @@ pmon_start_download (void) } } +/* Look for the string specified by STRING sent from the target board + during a download operation. If the string in question is not + seen, output an error message, remove the temporary file, if + appropriate, and return 0. Otherwise, return 1 to indicate + success. */ + static int mips_expect_download (char *string) { @@ -2992,37 +3218,59 @@ mips_expect_download (char *string) { fprintf_unfiltered (gdb_stderr, "Load did not complete successfully.\n"); if (tftp_in_use) - remove (tftp_localname); /* Remove temporary file */ + remove (tftp_localname); /* Remove temporary file. */ return 0; } else return 1; } +/* Look for messages from the target board associated with the entry + address. + + NOTE: This function doesn't indicate success or failure, so we + have no way to determine whether or not the output from the board + was correctly seen. However, given that other items are checked + after this, it seems unlikely that those checks will pass if this + check doesn't first (silently) pass. */ + static void pmon_check_entry_address (char *entry_address, int final) { - char hexnumber[9]; /* includes '\0' space */ + char hexnumber[9]; /* Includes '\0' space. */ + mips_expect_timeout (entry_address, tftp_in_use ? 15 : remote_timeout); sprintf (hexnumber, "%x", final); mips_expect (hexnumber); mips_expect ("\r\n"); } +/* Look for messages from the target board showing the total number of + bytes downloaded to the board. Output 1 for success if the tail + end of the message was read correctly, 0 otherwise. */ + static int pmon_check_total (int bintotal) { - char hexnumber[9]; /* includes '\0' space */ + char hexnumber[9]; /* Includes '\0' space. */ + mips_expect ("\r\ntotal = 0x"); sprintf (hexnumber, "%x", bintotal); mips_expect (hexnumber); return mips_expect_download (" bytes\r\n"); } +/* Look for the termination messages associated with the end of + a download to the board. + + Also, when `tftp_in_use' is set, issue the load command to the + board causing the file to be transferred. (This is done prior + to looking for the above mentioned termination messages.) */ + static void pmon_end_download (int final, int bintotal) { - char hexnumber[9]; /* includes '\0' space */ + char hexnumber[9]; /* Includes '\0' space. */ if (tftp_in_use) { @@ -3039,7 +3287,8 @@ pmon_end_download (int final, int bintotal) chmod (tftp_localname, stbuf.st_mode | S_IROTH); /* Must reinitialize the board to prevent PMON from crashing. */ - mips_send_command ("initEther\r", -1); + if (mips_monitor != MON_ROCKHOPPER) + mips_send_command ("initEther\r", -1); /* Send the load command. */ cmd = xmalloc (strlen (load_cmd_prefix) + strlen (tftp_name) + 2); @@ -3058,7 +3307,7 @@ pmon_end_download (int final, int bintotal) /* Wait for the stuff that PMON prints after the load has completed. The timeout value for use in the tftp case (15 seconds) was picked - arbitrarily but might be too small for really large downloads. FIXME. */ + arbitrarily but might be too small for really large downloads. FIXME. */ switch (mips_monitor) { case MON_LSI: @@ -3067,6 +3316,11 @@ pmon_end_download (int final, int bintotal) if (!pmon_check_total (bintotal)) return; break; + case MON_ROCKHOPPER: + if (!pmon_check_total (bintotal)) + return; + pmon_check_entry_address ("Entry Address = ", final); + break; default: pmon_check_entry_address ("Entry Address = ", final); pmon_check_ack ("termination"); @@ -3076,18 +3330,31 @@ pmon_end_download (int final, int bintotal) } if (tftp_in_use) - remove (tftp_localname); /* Remove temporary file */ + remove (tftp_localname); /* Remove temporary file. */ } +/* Write the buffer specified by BUFFER of length LENGTH to either + the board or the temporary file that'll eventually be transferred + to the board. */ + static void pmon_download (char *buffer, int length) { if (tftp_in_use) - fwrite (buffer, 1, length, tftp_file); + { + size_t written; + + written = fwrite (buffer, 1, length, tftp_file); + if (written < length) + perror_with_name (tftp_localname); + } else serial_write (udp_in_use ? udp_desc : mips_desc, buffer, length); } +/* Open object or executable file, FILE, and send it to the board + using the FastLoad format. */ + static void pmon_load_fast (char *file) { @@ -3122,33 +3389,34 @@ pmon_load_fast (char *file) mips_send_command ("set dlproto etxack\r", -1); mips_send_command ("set dlecho off\r", -1); /* NOTE: We get a "cannot set variable" message if the variable is - already defined to have the argument we give. The code doesn't - care, since it just scans to the next prompt anyway. */ + already defined to have the argument we give. The code doesn't + care, since it just scans to the next prompt anyway. */ /* Start the download: */ pmon_start_download (); - /* Zero the checksum */ + /* Zero the checksum. */ sprintf (buffer, "/Kxx\n"); reclen = strlen (buffer); pmon_download (buffer, reclen); finished = pmon_check_ack ("/Kxx"); for (s = abfd->sections; s && !finished; s = s->next) - if (s->flags & SEC_LOAD) /* only deal with loadable sections */ + if (s->flags & SEC_LOAD) /* Only deal with loadable sections. */ { bintotal += bfd_get_section_size (s); final = (s->vma + bfd_get_section_size (s)); - printf_filtered ("%s\t: 0x%4x .. 0x%4x ", s->name, (unsigned int) s->vma, + printf_filtered ("%s\t: 0x%4x .. 0x%4x ", s->name, + (unsigned int) s->vma, (unsigned int) (s->vma + bfd_get_section_size (s))); gdb_flush (gdb_stdout); - /* Output the starting address */ + /* Output the starting address. */ sprintf (buffer, "/A"); reclen = pmon_makeb64 (s->vma, &buffer[2], 36, &csum); buffer[2 + reclen] = '\n'; buffer[3 + reclen] = '\0'; - reclen += 3; /* for the initial escape code and carriage return */ + reclen += 3; /* For the initial escape code and carriage return. */ pmon_download (buffer, reclen); finished = pmon_check_ack ("/A"); @@ -3184,7 +3452,8 @@ pmon_load_fast (char *file) finished = pmon_check_ack ("data record"); if (finished) { - zerofill = 0; /* do not transmit pending zerofills */ + zerofill = 0; /* Do not transmit pending + zerofills. */ break; } @@ -3221,9 +3490,9 @@ pmon_load_fast (char *file) putchar_unfiltered ('\n'); } - /* Terminate the transfer. We know that we have an empty output - buffer at this point. */ - sprintf (buffer, "/E/E\n"); /* include dummy padding characters */ + /* Terminate the transfer. We know that we have an empty output + buffer at this point. */ + sprintf (buffer, "/E/E\n"); /* Include dummy padding characters. */ reclen = strlen (buffer); pmon_download (buffer, reclen); @@ -3239,14 +3508,16 @@ pmon_load_fast (char *file) return; } -/* mips_load -- download a file. */ +/* mips_load -- download a file. */ static void mips_load (char *file, int from_tty) { + struct regcache *regcache; + /* Get the board out of remote debugging mode. */ if (mips_exit_debug ()) - error ("mips_load: Couldn't get into monitor mode."); + error (_("mips_load: Couldn't get into monitor mode.")); if (mips_monitor != MON_IDT) pmon_load_fast (file); @@ -3255,28 +3526,48 @@ mips_load (char *file, int from_tty) mips_initialize (); - /* Finally, make the PC point at the start address */ + /* Finally, make the PC point at the start address. */ + regcache = get_current_regcache (); if (mips_monitor != MON_IDT) { /* Work around problem where PMON monitor updates the PC after a load - to a different value than GDB thinks it has. The following ensures - that the write_pc() WILL update the PC value: */ - deprecated_register_valid[PC_REGNUM] = 0; + to a different value than GDB thinks it has. The following ensures + that the regcache_write_pc() WILL update the PC value: */ + regcache_invalidate (regcache, + mips_regnum (get_regcache_arch (regcache))->pc); } if (exec_bfd) - write_pc (bfd_get_start_address (exec_bfd)); - - inferior_ptid = null_ptid; /* No process now */ + regcache_write_pc (regcache, bfd_get_start_address (exec_bfd)); +} -/* This is necessary because many things were based on the PC at the time that - we attached to the monitor, which is no longer valid now that we have loaded - new code (and just changed the PC). Another way to do this might be to call - normal_stop, except that the stack may not be valid, and things would get - horribly confused... */ +/* Check to see if a thread is still alive. */ + +static int +mips_thread_alive (struct target_ops *ops, ptid_t ptid) +{ + if (ptid_equal (ptid, remote_mips_ptid)) + /* The monitor's task is always alive. */ + return 1; - clear_symtab_users (); + return 0; } +/* Convert a thread ID to a string. Returns the string in a static + buffer. */ + +static char * +mips_pid_to_str (struct target_ops *ops, ptid_t ptid) +{ + static char buf[64]; + + if (ptid_equal (ptid, remote_mips_ptid)) + { + xsnprintf (buf, sizeof buf, "Thread
"); + return buf; + } + + return normal_pid_to_str (ptid); +} /* Pass the command argument as a packet to PMON verbatim. */ @@ -3295,7 +3586,12 @@ pmon_command (char *args, int from_tty) printf_filtered ("Received packet: %s\n", buf); } -extern initialize_file_ftype _initialize_remote_mips; /* -Wmissing-prototypes */ +/* -Wmissing-prototypes */ +extern initialize_file_ftype _initialize_remote_mips; + +/* Initialize mips_ops, lsi_ops, ddb_ops, pmon_ops, and rockhopper_ops. + Create target specific commands and perform other initializations + specific to this file. */ void _initialize_remote_mips (void) @@ -3320,16 +3616,19 @@ _initialize_remote_mips (void) mips_ops.to_load = mips_load; mips_ops.to_create_inferior = mips_create_inferior; mips_ops.to_mourn_inferior = mips_mourn_inferior; + mips_ops.to_thread_alive = mips_thread_alive; + mips_ops.to_pid_to_str = mips_pid_to_str; + mips_ops.to_log_command = serial_log_command; mips_ops.to_stratum = process_stratum; - mips_ops.to_has_all_memory = 1; - mips_ops.to_has_memory = 1; - mips_ops.to_has_stack = 1; - mips_ops.to_has_registers = 1; - mips_ops.to_has_execution = 1; + mips_ops.to_has_all_memory = default_child_has_all_memory; + mips_ops.to_has_memory = default_child_has_memory; + mips_ops.to_has_stack = default_child_has_stack; + mips_ops.to_has_registers = default_child_has_registers; + mips_ops.to_has_execution = default_child_has_execution; mips_ops.to_magic = OPS_MAGIC; /* Copy the common fields to all four target vectors. */ - pmon_ops = ddb_ops = lsi_ops = mips_ops; + rockhopper_ops = pmon_ops = ddb_ops = lsi_ops = mips_ops; /* Initialize target-specific fields in the target vectors. */ mips_ops.to_shortname = "mips"; @@ -3359,6 +3658,11 @@ of the TFTP temporary file, if it differs from the filename seen by the board."; ddb_ops.to_open = ddb_open; ddb_ops.to_wait = mips_wait; + rockhopper_ops.to_shortname = "rockhopper"; + rockhopper_ops.to_doc = ddb_ops.to_doc; + rockhopper_ops.to_open = rockhopper_open; + rockhopper_ops.to_wait = mips_wait; + lsi_ops.to_shortname = "lsi"; lsi_ops.to_doc = pmon_ops.to_doc; lsi_ops.to_open = lsi_open; @@ -3369,57 +3673,63 @@ of the TFTP temporary file, if it differs from the filename seen by the board."; add_target (&pmon_ops); add_target (&ddb_ops); add_target (&lsi_ops); - - deprecated_add_show_from_set - (add_set_cmd ("timeout", no_class, var_zinteger, - (char *) &mips_receive_wait, - "Set timeout in seconds for remote MIPS serial I/O.", - &setlist), - &showlist); - - deprecated_add_show_from_set - (add_set_cmd ("retransmit-timeout", no_class, var_zinteger, - (char *) &mips_retransmit_wait, "\ -Set retransmit timeout in seconds for remote MIPS serial I/O.\n\ + add_target (&rockhopper_ops); + + add_setshow_zinteger_cmd ("timeout", no_class, &mips_receive_wait, _("\ +Set timeout in seconds for remote MIPS serial I/O."), _("\ +Show timeout in seconds for remote MIPS serial I/O."), NULL, + NULL, + NULL, /* FIXME: i18n: */ + &setlist, &showlist); + + add_setshow_zinteger_cmd ("retransmit-timeout", no_class, + &mips_retransmit_wait, _("\ +Set retransmit timeout in seconds for remote MIPS serial I/O."), _("\ +Show retransmit timeout in seconds for remote MIPS serial I/O."), _("\ This is the number of seconds to wait for an acknowledgement to a packet\n\ -before resending the packet.", &setlist), - &showlist); - - deprecated_add_show_from_set - (add_set_cmd ("syn-garbage-limit", no_class, var_zinteger, - (char *) &mips_syn_garbage, "\ -Set the maximum number of characters to ignore when scanning for a SYN.\n\ +before resending the packet."), + NULL, + NULL, /* FIXME: i18n: */ + &setlist, &showlist); + + add_setshow_zinteger_cmd ("syn-garbage-limit", no_class, + &mips_syn_garbage, _("\ +Set the maximum number of characters to ignore when scanning for a SYN."), _("\ +Show the maximum number of characters to ignore when scanning for a SYN."), _("\ This is the maximum number of characters GDB will ignore when trying to\n\ synchronize with the remote system. A value of -1 means that there is no\n\ limit. (Note that these characters are printed out even though they are\n\ -ignored.)", - &setlist), - &showlist); - - deprecated_add_show_from_set - (add_set_cmd ("monitor-prompt", class_obscure, var_string, - (char *) &mips_monitor_prompt, - "Set the prompt that GDB expects from the monitor.", - &setlist), - &showlist); - - deprecated_add_show_from_set - (add_set_cmd ("monitor-warnings", class_obscure, var_zinteger, - (char *) &monitor_warnings, - "Set printing of monitor warnings.\n" - "When enabled, monitor warnings about hardware breakpoints " - "will be displayed.", - &setlist), - &showlist); - - add_com ("pmon ", class_obscure, pmon_command, - "Send a packet to PMON (must be in debug mode)."); - - deprecated_add_show_from_set - (add_set_cmd ("mask-address", no_class, - var_boolean, &mask_address_p, "\ -Set zeroing of upper 32 bits of 64-bit addresses when talking to PMON targets.\n\ -Use \"on\" to enable the masking and \"off\" to disable it.\n", - &setlist), - &showlist); +ignored.)"), + NULL, + NULL, /* FIXME: i18n: */ + &setlist, &showlist); + + add_setshow_string_cmd ("monitor-prompt", class_obscure, + &mips_monitor_prompt, _("\ +Set the prompt that GDB expects from the monitor."), _("\ +Show the prompt that GDB expects from the monitor."), NULL, + NULL, + NULL, /* FIXME: i18n: */ + &setlist, &showlist); + + add_setshow_zinteger_cmd ("monitor-warnings", class_obscure, + &monitor_warnings, _("\ +Set printing of monitor warnings."), _("\ +Show printing of monitor warnings."), _("\ +When enabled, monitor warnings about hardware breakpoints will be displayed."), + NULL, + NULL, /* FIXME: i18n: */ + &setlist, &showlist); + + add_com ("pmon", class_obscure, pmon_command, + _("Send a packet to PMON (must be in debug mode).")); + + add_setshow_boolean_cmd ("mask-address", no_class, &mask_address_p, _("\ +Set zeroing of upper 32 bits of 64-bit addresses when talking to PMON targets."), _("\ +Show zeroing of upper 32 bits of 64-bit addresses when talking to PMON targets."), _("\ +Use \"on\" to enable the masking and \"off\" to disable it."), + NULL, + NULL, /* FIXME: i18n: */ + &setlist, &showlist); + remote_mips_ptid = ptid_build (42000, 0, 42000); }