This is the mail archive of the
gdb@sources.redhat.com
mailing list for the GDB project.
[RFC] Core files and the architecture vector
- From: Mark Kettenis <kettenis at chello dot nl>
- To: gdb at sources dot redhat dot com
- Date: Sun, 12 Oct 2003 00:07:32 +0200 (CEST)
- Subject: [RFC] Core files and the architecture vector
Folks,
With the new regset_from_core_section architecture method, most of the
infrastructure for non-native generic core file support is present.
Now I face the problem of how to acrually use it. My initial
approach, which I used to test the stuff that I've already checked in,
was to create yet another `struct core_fns', and register it using
add_core_fns(). This works, but has its problems:
* We have to do this seperately for every BFD "flavour" (i.e. a.out,
COFF, ELF).
* It's diffucult to handle the case where the "architecture" of the
core file is different from the "architecture" of the executable.
Let me elaborate on the second point. When a 32-bit executable
running on FreeBSD/amd64 or GNU/Linux x86-64 dumps, it produces an
64-bit ELF core file. To be able to make any sense out of this core
file, we'll need the 64-bit register set definitions that are provided
by the regset_from_core_section method from the 64-bit architecture
vector. It is easier to accomplish this from a lower level, directly
in the functions in corelow.c. This maybe a better way anyway, since
I'll propose to deprecate the old way of adding core file support
(using `struct core_fns') in the near future.
The problem I'm having, is that we have no clean seperation between
initalizing and activating an architecture vector; it's all done from
gdbarch.c:gdbarch_update_p(). Looking at the function, it seems as if
it's not quite so easy to seperate the two because of the
per-architecture swapped data. I've hacked around this by
unconditionally setting the architecture from CORE_BFD, fetching the
core architecture vector from CURRENT_GDBARCH, and reset the
architecture from EXEC_BFD if we have one; refer to the attached code
to see what I mean.
Is this kosher? Do folks agree with this approach?
Mark
Index: corelow.c
===================================================================
RCS file: /cvs/src/src/gdb/corelow.c,v
retrieving revision 1.30
diff -u -p -r1.30 corelow.c
--- corelow.c 21 Sep 2003 01:26:44 -0000 1.30
+++ corelow.c 11 Oct 2003 21:25:14 -0000
@@ -37,9 +37,12 @@
#include "gdbcore.h"
#include "gdbthread.h"
#include "regcache.h"
+#include "regset.h"
#include "symfile.h"
#include <readline/readline.h>
+#include "gdb_assert.h"
+
#ifndef O_BINARY
#define O_BINARY 0
#endif
@@ -55,6 +58,8 @@ static struct core_fns *core_file_fns =
static struct core_fns *core_vec = NULL;
+struct gdbarch *core_gdbarch = NULL;
+
static void core_files_info (struct target_ops *);
#ifdef SOLIB_ADD
@@ -124,6 +129,9 @@ sniff_core_bfd (bfd *abfd)
struct core_fns *yummy = NULL;
int matches = 0;;
+ if (gdbarch_regset_from_core_section_p (core_gdbarch))
+ return NULL;
+
for (cf = core_file_fns; cf != NULL; cf = cf->next)
{
if (cf->core_sniffer (cf, abfd))
@@ -208,6 +216,7 @@ core_close (int quitting)
}
}
core_vec = NULL;
+ core_gdbarch = NULL;
}
static void
@@ -310,6 +319,9 @@ core_open (char *filename, int from_tty)
core_bfd = temp_bfd;
old_chain = make_cleanup (core_close_cleanup, 0 /*ignore*/);
+ set_gdbarch_from_file (core_bfd);
+ core_gdbarch = current_gdbarch;
+
/* Find a suitable core file handler to munch on core_bfd */
core_vec = sniff_core_bfd (core_bfd);
@@ -321,12 +333,11 @@ core_open (char *filename, int from_tty)
error ("\"%s\": Can't find sections: %s",
bfd_get_filename (core_bfd), bfd_errmsg (bfd_get_error ()));
- /* If we have no exec file, try to set the architecture from the
- core file. We don't do this unconditionally since an exec file
+ /* If we have an exec file, reset the architecture. An exec file
typically contains more information that helps us determine the
architecture than a core file. */
- if (!exec_bfd)
- set_gdbarch_from_file (core_bfd);
+ if (exec_bfd)
+ set_gdbarch_from_file (exec_bfd);
ontop = !push_target (&core_ops);
discard_cleanups (old_chain);
@@ -436,6 +447,24 @@ get_core_register_section (char *name,
return;
}
+ if (gdbarch_regset_from_core_section_p (core_gdbarch))
+ {
+ const struct regset *regset;
+
+ regset = gdbarch_regset_from_core_section (core_gdbarch, name, size);
+ if (regset == NULL)
+ {
+ if (required)
+ warning ("Couldn't recognize %s registers in core file.\n",
+ human_name);
+ return;
+ }
+
+ regset->supply_regset (regset, current_regcache, -1, contents, size);
+ return;
+ }
+
+ gdb_assert (core_vec);
core_vec->core_read_registers (contents, size, which,
((CORE_ADDR)
bfd_section_vma (core_bfd, section)));
@@ -453,8 +482,8 @@ get_core_registers (int regno)
{
int status;
- if (core_vec == NULL
- || core_vec->core_read_registers == NULL)
+ if (!gdbarch_regset_from_core_section_p (core_gdbarch)
+ && (core_vec == NULL || core_vec->core_read_registers == NULL))
{
fprintf_filtered (gdb_stderr,
"Can't fetch registers from this type of core file\n");