| Index: gdb/corefile.c
|
| diff --git a/gdb/corefile.c b/gdb/corefile.c
|
| index ac8eff55a6e2559878c001601ed29ca5a41f883f..d821fdd8cb1bc6b83b387c03845aad6f9c443535 100644
|
| --- a/gdb/corefile.c
|
| +++ b/gdb/corefile.c
|
| @@ -1,7 +1,6 @@
|
| /* Core dump and executable file functions above target vector, for GDB.
|
|
|
| - Copyright (C) 1986-1987, 1989, 1991-1994, 1996-2001, 2003, 2006-2012
|
| - Free Software Foundation, Inc.
|
| + Copyright (C) 1986-2013 Free Software Foundation, Inc.
|
|
|
| This file is part of GDB.
|
|
|
| @@ -19,7 +18,7 @@
|
| along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
|
|
| #include "defs.h"
|
| -#include "gdb_string.h"
|
| +#include <string.h>
|
| #include <errno.h>
|
| #include <signal.h>
|
| #include <fcntl.h>
|
| @@ -31,10 +30,11 @@
|
| #include "target.h"
|
| #include "gdbcore.h"
|
| #include "dis-asm.h"
|
| -#include "gdb_stat.h"
|
| +#include <sys/stat.h>
|
| #include "completer.h"
|
| #include "exceptions.h"
|
| #include "observer.h"
|
| +#include "cli/cli-utils.h"
|
|
|
| /* Local function declarations. */
|
|
|
| @@ -182,8 +182,8 @@ validate_files (void)
|
| char *
|
| get_exec_file (int err)
|
| {
|
| - if (exec_bfd)
|
| - return bfd_get_filename (exec_bfd);
|
| + if (exec_filename)
|
| + return exec_filename;
|
| if (!err)
|
| return NULL;
|
|
|
| @@ -193,22 +193,52 @@ Use the \"file\" or \"exec-file\" command."));
|
| }
|
|
|
|
|
| -/* Report a memory error by throwing a MEMORY_ERROR error. */
|
| +char *
|
| +memory_error_message (enum target_xfer_error err,
|
| + struct gdbarch *gdbarch, CORE_ADDR memaddr)
|
| +{
|
| + switch (err)
|
| + {
|
| + case TARGET_XFER_E_IO:
|
| + /* Actually, address between memaddr and memaddr + len was out of
|
| + bounds. */
|
| + return xstrprintf (_("Cannot access memory at address %s"),
|
| + paddress (gdbarch, memaddr));
|
| + case TARGET_XFER_E_UNAVAILABLE:
|
| + return xstrprintf (_("Memory at address %s unavailable."),
|
| + paddress (gdbarch, memaddr));
|
| + default:
|
| + internal_error (__FILE__, __LINE__,
|
| + "unhandled target_xfer_error: %s (%s)",
|
| + target_xfer_error_to_string (err),
|
| + plongest (err));
|
| + }
|
| +}
|
| +
|
| +/* Report a memory error by throwing a suitable exception. */
|
|
|
| void
|
| -memory_error (int status, CORE_ADDR memaddr)
|
| +memory_error (enum target_xfer_error err, CORE_ADDR memaddr)
|
| {
|
| - if (status == EIO)
|
| - /* Actually, address between memaddr and memaddr + len was out of
|
| - bounds. */
|
| - throw_error (MEMORY_ERROR,
|
| - _("Cannot access memory at address %s"),
|
| - paddress (target_gdbarch, memaddr));
|
| - else
|
| - throw_error (MEMORY_ERROR,
|
| - _("Error accessing memory address %s: %s."),
|
| - paddress (target_gdbarch, memaddr),
|
| - safe_strerror (status));
|
| + char *str;
|
| +
|
| + /* Build error string. */
|
| + str = memory_error_message (err, target_gdbarch (), memaddr);
|
| + make_cleanup (xfree, str);
|
| +
|
| + /* Choose the right error to throw. */
|
| + switch (err)
|
| + {
|
| + case TARGET_XFER_E_IO:
|
| + err = MEMORY_ERROR;
|
| + break;
|
| + case TARGET_XFER_E_UNAVAILABLE:
|
| + err = NOT_AVAILABLE_ERROR;
|
| + break;
|
| + }
|
| +
|
| + /* Throw it. */
|
| + throw_error (err, ("%s"), str);
|
| }
|
|
|
| /* Same as target_read_memory, but report an error if can't read. */
|
| @@ -216,11 +246,22 @@ memory_error (int status, CORE_ADDR memaddr)
|
| void
|
| read_memory (CORE_ADDR memaddr, gdb_byte *myaddr, ssize_t len)
|
| {
|
| - int status;
|
| + LONGEST xfered = 0;
|
|
|
| - status = target_read_memory (memaddr, myaddr, len);
|
| - if (status != 0)
|
| - memory_error (status, memaddr);
|
| + while (xfered < len)
|
| + {
|
| + LONGEST xfer = target_xfer_partial (current_target.beneath,
|
| + TARGET_OBJECT_MEMORY, NULL,
|
| + myaddr + xfered, NULL,
|
| + memaddr + xfered, len - xfered);
|
| +
|
| + if (xfer == 0)
|
| + memory_error (TARGET_XFER_E_IO, memaddr + xfered);
|
| + if (xfer < 0)
|
| + memory_error (xfer, memaddr + xfered);
|
| + xfered += xfer;
|
| + QUIT;
|
| + }
|
| }
|
|
|
| /* Same as target_read_stack, but report an error if can't read. */
|
| @@ -235,6 +276,18 @@ read_stack (CORE_ADDR memaddr, gdb_byte *myaddr, ssize_t len)
|
| memory_error (status, memaddr);
|
| }
|
|
|
| +/* Same as target_read_code, but report an error if can't read. */
|
| +
|
| +void
|
| +read_code (CORE_ADDR memaddr, gdb_byte *myaddr, ssize_t len)
|
| +{
|
| + int status;
|
| +
|
| + status = target_read_code (memaddr, myaddr, len);
|
| + if (status != 0)
|
| + memory_error (status, memaddr);
|
| +}
|
| +
|
| /* Argument / return result struct for use with
|
| do_captured_read_memory_integer(). MEMADDR and LEN are filled in
|
| by gdb_read_memory_integer(). RESULT is the contents that were
|
| @@ -313,6 +366,26 @@ read_memory_unsigned_integer (CORE_ADDR memaddr, int len,
|
| return extract_unsigned_integer (buf, len, byte_order);
|
| }
|
|
|
| +LONGEST
|
| +read_code_integer (CORE_ADDR memaddr, int len,
|
| + enum bfd_endian byte_order)
|
| +{
|
| + gdb_byte buf[sizeof (LONGEST)];
|
| +
|
| + read_code (memaddr, buf, len);
|
| + return extract_signed_integer (buf, len, byte_order);
|
| +}
|
| +
|
| +ULONGEST
|
| +read_code_unsigned_integer (CORE_ADDR memaddr, int len,
|
| + enum bfd_endian byte_order)
|
| +{
|
| + gdb_byte buf[sizeof (ULONGEST)];
|
| +
|
| + read_code (memaddr, buf, len);
|
| + return extract_unsigned_integer (buf, len, byte_order);
|
| +}
|
| +
|
| void
|
| read_memory_string (CORE_ADDR memaddr, char *buffer, int max_len)
|
| {
|
| @@ -331,7 +404,7 @@ read_memory_string (CORE_ADDR memaddr, char *buffer, int max_len)
|
| cnt = max_len - (cp - buffer);
|
| if (cnt > 8)
|
| cnt = 8;
|
| - read_memory (memaddr + (int) (cp - buffer), cp, cnt);
|
| + read_memory (memaddr + (int) (cp - buffer), (gdb_byte *) cp, cnt);
|
| for (i = 0; i < cnt && *cp; i++, cp++)
|
| ; /* null body */
|
|
|
| @@ -369,7 +442,7 @@ write_memory_with_notification (CORE_ADDR memaddr, const bfd_byte *myaddr,
|
| ssize_t len)
|
| {
|
| write_memory (memaddr, myaddr, len);
|
| - observer_notify_memory_changed (memaddr, len, myaddr);
|
| + observer_notify_memory_changed (current_inferior (), memaddr, len, myaddr);
|
| }
|
|
|
| /* Store VALUE at ADDR in the inferior as a LEN-byte unsigned
|
| @@ -420,12 +493,41 @@ static void
|
| set_gnutarget_command (char *ignore, int from_tty,
|
| struct cmd_list_element *c)
|
| {
|
| + char *gend = gnutarget_string + strlen (gnutarget_string);
|
| +
|
| + gend = remove_trailing_whitespace (gnutarget_string, gend);
|
| + *gend = '\0';
|
| +
|
| if (strcmp (gnutarget_string, "auto") == 0)
|
| gnutarget = NULL;
|
| else
|
| gnutarget = gnutarget_string;
|
| }
|
|
|
| +/* A completion function for "set gnutarget". */
|
| +
|
| +static VEC (char_ptr) *
|
| +complete_set_gnutarget (struct cmd_list_element *cmd,
|
| + const char *text, const char *word)
|
| +{
|
| + static const char **bfd_targets;
|
| +
|
| + if (bfd_targets == NULL)
|
| + {
|
| + int last;
|
| +
|
| + bfd_targets = bfd_target_list ();
|
| + for (last = 0; bfd_targets[last] != NULL; ++last)
|
| + ;
|
| +
|
| + bfd_targets = xrealloc (bfd_targets, (last + 2) * sizeof (const char **));
|
| + bfd_targets[last] = "auto";
|
| + bfd_targets[last + 1] = NULL;
|
| + }
|
| +
|
| + return complete_on_enum (bfd_targets, text, word);
|
| +}
|
| +
|
| /* Set the gnutarget. */
|
| void
|
| set_gnutarget (char *newtarget)
|
| @@ -448,14 +550,17 @@ No arg means have no core file. This command has been superseded by the\n\
|
| set_cmd_completer (c, filename_completer);
|
|
|
|
|
| - add_setshow_string_noescape_cmd ("gnutarget", class_files,
|
| - &gnutarget_string, _("\
|
| + c = add_setshow_string_noescape_cmd ("gnutarget", class_files,
|
| + &gnutarget_string, _("\
|
| Set the current BFD target."), _("\
|
| Show the current BFD target."), _("\
|
| Use `set gnutarget auto' to specify automatic detection."),
|
| - set_gnutarget_command,
|
| - show_gnutarget_string,
|
| - &setlist, &showlist);
|
| + set_gnutarget_command,
|
| + show_gnutarget_string,
|
| + &setlist, &showlist);
|
| + set_cmd_completer (c, complete_set_gnutarget);
|
| +
|
| + add_alias_cmd ("g", "gnutarget", class_files, 1, &setlist);
|
|
|
| if (getenv ("GNUTARGET"))
|
| set_gnutarget (getenv ("GNUTARGET"));
|
|
|