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")); |