aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Snyder <msnyder@vmware.com>2005-11-22 00:11:55 +0000
committerMichael Snyder <msnyder@vmware.com>2005-11-22 00:11:55 +0000
commit1daf3f9b7428e6cddf9b3e926dd47c50bc27be5b (patch)
tree15fb539fffa24661082f3be924006a8c0747ce14
parentb74d4d1a88b5306341a2a324433d94e102decc1c (diff)
downloadgdb-1daf3f9b7428e6cddf9b3e926dd47c50bc27be5b.zip
gdb-1daf3f9b7428e6cddf9b3e926dd47c50bc27be5b.tar.gz
gdb-1daf3f9b7428e6cddf9b3e926dd47c50bc27be5b.tar.bz2
2005-11-21 Michael Snyder <msnyder@redhat.com>
* gcore.c: Add restore-corefile-command. (call_target_sbrk): Abstracted from derive_heap_segment. (derive_heap_segment): Call call_target_sbrk instead of coding it inline. (load_core_sections): Callback for bfd_map_over_sections. (rcore_command): Implements restore-corefile-command ('rcore'). (__initialize_gcore): Add new command rcore/restore-corefile.
-rw-r--r--gdb/ChangeLog11
-rw-r--r--gdb/gcore.c229
2 files changed, 239 insertions, 1 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 1d0b6c7..bd99d31 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,14 @@
+2005-11-21 Michael Snyder <msnyder@redhat.com>
+
+ * gcore.c: Add restore-corefile-command.
+
+ (call_target_sbrk): Abstracted from derive_heap_segment.
+ (derive_heap_segment): Call call_target_sbrk instead of
+ coding it inline.
+ (load_core_sections): Callback for bfd_map_over_sections.
+ (rcore_command): Implements restore-corefile-command ('rcore').
+ (__initialize_gcore): Add new command rcore/restore-corefile.
+
2005-11-20 Mark Kettenis <kettenis@gnu.org>
* inf-ptrace.c (inf_ptrace_xfer_partial): Use PIOD_WRITE_I instead
diff --git a/gdb/gcore.c b/gdb/gcore.c
index efaccdc..bb62717 100644
--- a/gdb/gcore.c
+++ b/gdb/gcore.c
@@ -205,6 +205,48 @@ derive_stack_segment (bfd_vma *bottom, bfd_vma *top)
return 1;
}
+/* Call target sbrk. */
+
+static bfd_vma top_of_heap;
+
+static bfd_vma
+call_target_sbrk (int sbrk_arg)
+{
+ struct value *target_sbrk_arg;
+ struct value *sbrk_fn, *ret;
+ bfd_vma tmp;
+
+ if (lookup_minimal_symbol ("sbrk", NULL, NULL) != NULL)
+ {
+ sbrk_fn = find_function_in_inferior ("sbrk");
+ if (sbrk_fn == NULL)
+ return (bfd_vma) 0;
+ }
+ else if (lookup_minimal_symbol ("_sbrk", NULL, NULL) != NULL)
+ {
+ sbrk_fn = find_function_in_inferior ("_sbrk");
+ if (sbrk_fn == NULL)
+ return (bfd_vma) 0;
+ }
+ else
+ return (bfd_vma) 0;
+
+ target_sbrk_arg = value_from_longest (builtin_type_int, sbrk_arg);
+ if (target_sbrk_arg == NULL)
+ return (bfd_vma) 0;
+
+ ret = call_function_by_hand (sbrk_fn, 1, &target_sbrk_arg);
+ if (ret == NULL)
+ return (bfd_vma) 0;
+
+ tmp = value_as_long (ret);
+ if ((LONGEST) tmp <= 0 || (LONGEST) tmp == 0xffffffff)
+ return (bfd_vma) 0;
+
+ top_of_heap = tmp;
+ return top_of_heap;
+}
+
/* Derive a reasonable heap segment for ABFD by looking at sbrk and
the static data sections. Store its limits in *BOTTOM and *TOP.
Return non-zero if successful. */
@@ -213,7 +255,6 @@ static int
derive_heap_segment (bfd *abfd, bfd_vma *bottom, bfd_vma *top)
{
bfd_vma top_of_data_memory = 0;
- bfd_vma top_of_heap = 0;
bfd_size_type sec_size;
struct value *zero, *sbrk;
bfd_vma sec_vaddr;
@@ -251,6 +292,7 @@ derive_heap_segment (bfd *abfd, bfd_vma *bottom, bfd_vma *top)
}
/* Now get the top-of-heap by calling sbrk in the inferior. */
+#if 0
if (lookup_minimal_symbol ("sbrk", NULL, NULL) != NULL)
{
sbrk = find_function_in_inferior ("sbrk");
@@ -272,6 +314,10 @@ derive_heap_segment (bfd *abfd, bfd_vma *bottom, bfd_vma *top)
if (sbrk == NULL)
return 0;
top_of_heap = value_as_long (sbrk);
+#else
+ if (call_target_sbrk (0) == (bfd_vma) 0)
+ return 0;
+#endif
/* Return results. */
if (top_of_heap > top_of_data_memory)
@@ -488,6 +534,182 @@ gcore_memory_sections (bfd *obfd)
return 1;
}
+/* OK now, I want to add a new command to read a corefile,
+ and restore its state into the inferior process. Obviously
+ dangerous, probably want to make certain that they are
+ actually the same process! But we can put that off till
+ later. Let's see what's required. This should actually
+ be pretty easy. */
+
+static void
+load_core_sections (bfd *abfd, asection *asect, void *arg)
+{
+ unsigned long from_tty = (unsigned long) arg;
+ char *memhunk;
+ int ret;
+
+ if ((bfd_section_size (abfd, asect) > 0) &&
+ (bfd_get_section_flags (abfd, asect) & SEC_LOAD))
+ {
+ if (info_verbose && from_tty)
+ {
+ printf_filtered (_("Load core section %s"),
+ bfd_section_name (abfd, asect));
+ printf_filtered (_(", vma 0x%08lx to 0x%08lx"),
+ (unsigned long) bfd_section_vma (abfd, asect),
+ (unsigned long) bfd_section_vma (abfd, asect) +
+ (int) bfd_section_size (abfd, asect));
+ printf_filtered (_(", size = %d"),
+ (int) bfd_section_size (abfd, asect));
+ printf_filtered (_(".\n"));
+ }
+ /* Fixme cleanup? */
+ memhunk = xmalloc (bfd_section_size (abfd, asect));
+ bfd_get_section_contents (abfd, asect, memhunk, 0,
+ bfd_section_size (abfd, asect));
+ if ((ret = target_write_memory (bfd_section_vma (abfd, asect),
+ memhunk,
+ bfd_section_size (abfd, asect))) != 0)
+ {
+ print_sys_errmsg ("load_core_sections", ret);
+ if ((LONGEST) top_of_heap <
+ (LONGEST) bfd_section_vma (abfd, asect) +
+ (LONGEST) bfd_section_size (abfd, asect))
+ {
+ int increment = bfd_section_vma (abfd, asect) +
+ bfd_section_size (abfd, asect) - top_of_heap;
+
+ if (call_target_sbrk (increment) == 0)
+ error ("sbrk failed, TOH = 0x%08lx", top_of_heap);
+ else
+ printf_filtered ("Increase TOH to 0x%08lx and retry.\n",
+ (unsigned long) top_of_heap);
+ if (target_write_memory (bfd_section_vma (abfd, asect),
+ memhunk,
+ bfd_section_size (abfd, asect)) != 0)
+ {
+ error ("Nope, still failed.");
+ }
+ }
+ }
+ xfree (memhunk);
+ }
+}
+
+#include <fcntl.h>
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+#include "regcache.h"
+#include "regset.h"
+
+static int rcore_warned;
+
+static void
+rcore_command (char *args, int from_tty)
+{
+ /* corelow.c core_open */
+ /* scratch_chan = open (filename)
+ temp_bfd = bfd_fdopenr (filename, gnutarget, scratch_chan)
+ bfd_check_format (temp_bfd, bfd_core)
+ build_section_table (core_bfd, to_sections, to_sections_end)
+ bfd_map_over_sections (core_bfd, myfunc)
+ myfunc will check for loadable, contents, and size,
+ and then write the section contents into memory at vma.
+ */
+ char *corefilename, corefilename_buffer[40], *scratch_path;
+ int scratch_chan;
+ bfd *core_bfd;
+
+ /* Can't restore a corefile without a target process. */
+ if (!target_has_execution)
+ noprocess ();
+
+ /* Experimental warning. Remove upon confidence. */
+ if (!rcore_warned)
+ {
+ warning ("This command is experimental, and may have dire\n\
+and unexpected results! Proceed at your own risk.");
+ if (!query ("Are you sure you want to go there? "))
+ {
+ fputs_filtered ("Cancelled at user request.\n", gdb_stdout);
+ return;
+ }
+ else
+ {
+ fputs_filtered ("Very well. Warning will not be repeated.\n",
+ gdb_stdout);
+ }
+ }
+ rcore_warned = 1;
+
+ if (args && *args)
+ corefilename = args;
+ else
+ {
+ /* Default corefile name is "core.PID". */
+ sprintf (corefilename_buffer, "core.%d", PIDGET (inferior_ptid));
+ corefilename = corefilename_buffer;
+ }
+
+ if (info_verbose)
+ fprintf_filtered (gdb_stdout,
+ _("Opening corefile '%s' for input.\n"), corefilename);
+
+ scratch_chan = openp (getenv ("PATH"), OPF_TRY_CWD_FIRST, corefilename,
+ O_BINARY | O_RDONLY | O_LARGEFILE, 0, &scratch_path);
+ if (scratch_chan < 0)
+ perror_with_name (corefilename);
+
+ core_bfd = bfd_fdopenr (scratch_path, gnutarget, scratch_chan);
+ if (!core_bfd)
+ perror_with_name (scratch_path);
+
+ if (!bfd_check_format (core_bfd, bfd_core))
+ {
+ make_cleanup_bfd_close (core_bfd);
+ error (_("\"%s\" is not a core file: %s"),
+ corefilename, bfd_errmsg (bfd_get_error ()));
+ }
+
+ if (call_target_sbrk (0) == (bfd_vma) 0)
+ error ("Couldn't get sbrk.");
+
+ bfd_map_over_sections (core_bfd, load_core_sections, (void *) from_tty);
+ /* Now need to get/set registers. */
+ {
+ struct bfd_section *regsect = bfd_get_section_by_name (core_bfd, ".reg");
+ char *contents;
+ int size;
+
+ if (!regsect)
+ error (_("Couldn't find .reg section."));
+
+ size = bfd_section_size (core_bfd, regsect);
+ contents = xmalloc (size);
+ bfd_get_section_contents (core_bfd, regsect, contents, 0, size);
+
+ if (gdbarch_regset_from_core_section_p (current_gdbarch))
+ {
+ const struct regset *regset;
+
+ regset = gdbarch_regset_from_core_section (current_gdbarch,
+ ".reg", size);
+ if (!regset)
+ error (_("Failed to allocate regset."));
+
+ registers_changed ();
+ regset->supply_regset (regset, current_regcache,
+ -1, contents, size);
+ reinit_frame_cache ();
+ target_store_registers (-1);
+ }
+ }
+
+ bfd_close (core_bfd);
+}
+
void
_initialize_gcore (void)
{
@@ -497,4 +719,9 @@ Argument is optional filename. Default filename is 'core.<process_id>'."));
add_com_alias ("gcore", "generate-core-file", class_files, 1);
exec_set_find_memory_regions (objfile_find_memory_regions);
+
+ add_com ("restore-core-file", class_experimental, rcore_command, _("\
+Restore the machine state from a core file into the debugged process.\n\
+Argument is optional filename. Default filename is 'core.<process_id>'."));
+ add_com_alias ("rcore", "restore-core-file", class_experimental, 1);
}