/* Core dump and executable file functions below target vector, for GDB.
- Copyright 1986, 1987, 1989, 1991, 1992, 1993, 1994, 1995
+ Copyright 1986, 1987, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997
Free Software Foundation, Inc.
This file is part of GDB.
#include "bfd.h"
#include "target.h"
#include "gdbcore.h"
-#include "thread.h"
+#include "gdbthread.h"
+
+/* List of all available core_fns. On gdb startup, each core file register
+ reader calls add_core_fns() to register information on each core format it
+ is prepared to read. */
+
+static struct core_fns *core_file_fns = NULL;
static void core_files_info PARAMS ((struct target_ops *));
static void get_core_registers PARAMS ((int));
+static void add_to_thread_list PARAMS ((bfd *, asection *, PTR));
+
+static int ignore PARAMS ((CORE_ADDR, char *));
+
+/* Link a new core_fns into the global core_file_fns list. Called on gdb
+ startup by the _initialize routine in each core file register reader, to
+ register information about each format the the reader is prepared to
+ handle. */
+
+void
+add_core_fns (cf)
+ struct core_fns *cf;
+{
+ cf -> next = core_file_fns;
+ core_file_fns = cf;
+}
+
+
/* Discard all vestiges of any previous core file and mark data and stack
spaces as empty. */
{
char *name;
- inferior_pid = 0; /* Avoid confusion from thread stuff */
-
if (core_bfd)
{
+ inferior_pid = 0; /* Avoid confusion from thread stuff */
+
name = bfd_get_filename (core_bfd);
if (!bfd_close (core_bfd))
warning ("cannot close \"%s\": %s",
char *from_ttyp;
{
SOLIB_ADD (NULL, *(int *)from_ttyp, ¤t_target);
+ re_enable_breakpoints_in_shlibs ();
return 0;
}
#endif /* SOLIB_ADD */
/* Warning, Will Robinson, looking at BFD private data! */
- if (asect->filepos == reg_sect->filepos) /* Did we find .reg? */
+ if (reg_sect != NULL
+ && asect->filepos == reg_sect->filepos) /* Did we find .reg? */
inferior_pid = thread_id; /* Yes, make it current */
}
sec_ptr reg_sec;
unsigned size;
char *the_regs;
- char secname[10];
+ char secname[30];
+ enum bfd_flavour our_flavour = bfd_get_flavour (core_bfd);
+ struct core_fns *cf = NULL;
+
+ if (core_file_fns == NULL)
+ {
+ fprintf_filtered (gdb_stderr,
+ "Can't fetch registers from this type of core file\n");
+ return;
+ }
/* Thread support. If inferior_pid is non-zero, then we have found a core
file with threads (or multiple processes). In that case, we need to
goto cant;
size = bfd_section_size (core_bfd, reg_sec);
the_regs = alloca (size);
- if (bfd_get_section_contents (core_bfd, reg_sec, the_regs, (file_ptr)0, size))
+ /* Look for the core functions that match this flavor. Default to the
+ first one if nothing matches. */
+ for (cf = core_file_fns; cf != NULL; cf = cf -> next)
{
- fetch_core_registers (the_regs, size, 0,
- (unsigned) bfd_section_vma (abfd,reg_sec));
+ if (our_flavour == cf -> core_flavour)
+ {
+ break;
+ }
+ }
+ if (cf == NULL)
+ {
+ cf = core_file_fns;
+ }
+ if (cf != NULL &&
+ bfd_get_section_contents (core_bfd, reg_sec, the_regs, (file_ptr)0, size) &&
+ cf -> core_read_registers != NULL)
+ {
+ (cf -> core_read_registers (the_regs, size, 0,
+ (unsigned) bfd_section_vma (abfd,reg_sec)));
}
else
{
{
size = bfd_section_size (core_bfd, reg_sec);
the_regs = alloca (size);
- if (bfd_get_section_contents (core_bfd, reg_sec, the_regs, (file_ptr)0,
- size))
+ if (cf != NULL &&
+ bfd_get_section_contents (core_bfd, reg_sec, the_regs, (file_ptr)0, size) &&
+ cf -> core_read_registers != NULL)
{
- fetch_core_registers (the_regs, size, 2,
- (unsigned) bfd_section_vma (abfd,reg_sec));
+ (cf -> core_read_registers (the_regs, size, 2,
+ (unsigned) bfd_section_vma (abfd,reg_sec)));
}
else
{
OPS_MAGIC, /* to_magic */
};
+/* non-zero if we should not do the add_target call in
+ _initialize_corelow; not initialized (i.e., bss) so that
+ the target can initialize it (i.e., data) if appropriate.
+ This needs to be set at compile time because we don't know
+ for sure whether the target's initialize routine is called
+ before us or after us. */
+int coreops_suppress_target;
+
void
_initialize_corelow()
{
- add_target (&core_ops);
+ if (!coreops_suppress_target)
+ add_target (&core_ops);
}