119370Spst/* Core dump and executable file functions below target vector, for GDB.
219370Spst
3130803Smarcel   Copyright 1986, 1987, 1989, 1991, 1992, 1993, 1994, 1995, 1996,
4130803Smarcel   1997, 1998, 1999, 2000, 2001, 2003, 2004 Free Software Foundation,
5130803Smarcel   Inc.
6130803Smarcel
798944Sobrien   This file is part of GDB.
819370Spst
998944Sobrien   This program is free software; you can redistribute it and/or modify
1098944Sobrien   it under the terms of the GNU General Public License as published by
1198944Sobrien   the Free Software Foundation; either version 2 of the License, or
1298944Sobrien   (at your option) any later version.
1319370Spst
1498944Sobrien   This program is distributed in the hope that it will be useful,
1598944Sobrien   but WITHOUT ANY WARRANTY; without even the implied warranty of
1698944Sobrien   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1798944Sobrien   GNU General Public License for more details.
1819370Spst
1998944Sobrien   You should have received a copy of the GNU General Public License
2098944Sobrien   along with this program; if not, write to the Free Software
2198944Sobrien   Foundation, Inc., 59 Temple Place - Suite 330,
2298944Sobrien   Boston, MA 02111-1307, USA.  */
2319370Spst
2419370Spst#include "defs.h"
25130803Smarcel#include "arch-utils.h"
2619370Spst#include "gdb_string.h"
2719370Spst#include <errno.h>
2819370Spst#include <signal.h>
2919370Spst#include <fcntl.h>
3098944Sobrien#ifdef HAVE_SYS_FILE_H
3198944Sobrien#include <sys/file.h>		/* needed for F_OK and friends */
3298944Sobrien#endif
3398944Sobrien#include "frame.h"		/* required by inferior.h */
3419370Spst#include "inferior.h"
3519370Spst#include "symtab.h"
3619370Spst#include "command.h"
3719370Spst#include "bfd.h"
3819370Spst#include "target.h"
3919370Spst#include "gdbcore.h"
4046283Sdfr#include "gdbthread.h"
4198944Sobrien#include "regcache.h"
42130803Smarcel#include "regset.h"
4398944Sobrien#include "symfile.h"
44130803Smarcel#include "exec.h"
45130803Smarcel#include "readline/readline.h"
4619370Spst
47130803Smarcel#include "gdb_assert.h"
48130803Smarcel
4998944Sobrien#ifndef O_BINARY
5098944Sobrien#define O_BINARY 0
5198944Sobrien#endif
5298944Sobrien
5319370Spst/* List of all available core_fns.  On gdb startup, each core file register
5419370Spst   reader calls add_core_fns() to register information on each core format it
5519370Spst   is prepared to read. */
5619370Spst
5719370Spststatic struct core_fns *core_file_fns = NULL;
5819370Spst
5998944Sobrien/* The core_fns for a core file handler that is prepared to read the core
6098944Sobrien   file currently open on core_bfd. */
6119370Spst
6298944Sobrienstatic struct core_fns *core_vec = NULL;
6398944Sobrien
64130803Smarcel/* FIXME: kettenis/20031023: Eventually this variable should
65130803Smarcel   disappear.  */
66130803Smarcel
67130803Smarcelstruct gdbarch *core_gdbarch = NULL;
68130803Smarcel
6998944Sobrienstatic void core_files_info (struct target_ops *);
7098944Sobrien
7119370Spst#ifdef SOLIB_ADD
72130803Smarcelstatic int solib_add_stub (void *);
7319370Spst#endif
7419370Spst
7598944Sobrienstatic struct core_fns *sniff_core_bfd (bfd *);
7619370Spst
77130803Smarcelstatic int gdb_check_format (bfd *);
7819370Spst
7998944Sobrienstatic void core_open (char *, int);
8019370Spst
8198944Sobrienstatic void core_detach (char *, int);
8219370Spst
8398944Sobrienstatic void core_close (int);
8446283Sdfr
8598944Sobrienstatic void core_close_cleanup (void *ignore);
8646283Sdfr
8798944Sobrienstatic void get_core_registers (int);
8846283Sdfr
89130803Smarcelstatic void add_to_thread_list (bfd *, asection *, void *);
9046283Sdfr
9198944Sobrienstatic int ignore (CORE_ADDR, char *);
9246283Sdfr
9398944Sobrienstatic int core_file_thread_alive (ptid_t tid);
9446283Sdfr
9598944Sobrienstatic void init_core_ops (void);
9698944Sobrien
9798944Sobrienvoid _initialize_corelow (void);
9898944Sobrien
9946283Sdfrstruct target_ops core_ops;
10046283Sdfr
10119370Spst/* Link a new core_fns into the global core_file_fns list.  Called on gdb
10219370Spst   startup by the _initialize routine in each core file register reader, to
10319370Spst   register information about each format the the reader is prepared to
10419370Spst   handle. */
10519370Spst
10619370Spstvoid
10798944Sobrienadd_core_fns (struct core_fns *cf)
10819370Spst{
10998944Sobrien  cf->next = core_file_fns;
11019370Spst  core_file_fns = cf;
11119370Spst}
11219370Spst
11398944Sobrien/* The default function that core file handlers can use to examine a
11498944Sobrien   core file BFD and decide whether or not to accept the job of
11598944Sobrien   reading the core file. */
11619370Spst
11798944Sobrienint
11898944Sobriendefault_core_sniffer (struct core_fns *our_fns, bfd *abfd)
11998944Sobrien{
12098944Sobrien  int result;
12198944Sobrien
12298944Sobrien  result = (bfd_get_flavour (abfd) == our_fns -> core_flavour);
12398944Sobrien  return (result);
12498944Sobrien}
12598944Sobrien
12698944Sobrien/* Walk through the list of core functions to find a set that can
12798944Sobrien   handle the core file open on ABFD.  Default to the first one in the
12898944Sobrien   list if nothing matches.  Returns pointer to set that is
12998944Sobrien   selected. */
13098944Sobrien
13198944Sobrienstatic struct core_fns *
13298944Sobriensniff_core_bfd (bfd *abfd)
13398944Sobrien{
13498944Sobrien  struct core_fns *cf;
13598944Sobrien  struct core_fns *yummy = NULL;
13698944Sobrien  int matches = 0;;
13798944Sobrien
138130803Smarcel  /* Don't sniff if we have support for register sets in CORE_GDBARCH.  */
139130803Smarcel  if (core_gdbarch && gdbarch_regset_from_core_section_p (core_gdbarch))
140130803Smarcel    return NULL;
141130803Smarcel
14298944Sobrien  for (cf = core_file_fns; cf != NULL; cf = cf->next)
14398944Sobrien    {
14498944Sobrien      if (cf->core_sniffer (cf, abfd))
14598944Sobrien	{
14698944Sobrien	  yummy = cf;
14798944Sobrien	  matches++;
14898944Sobrien	}
14998944Sobrien    }
15098944Sobrien  if (matches > 1)
15198944Sobrien    {
15298944Sobrien      warning ("\"%s\": ambiguous core format, %d handlers match",
15398944Sobrien	       bfd_get_filename (abfd), matches);
15498944Sobrien    }
15598944Sobrien  else if (matches == 0)
15698944Sobrien    {
15798944Sobrien      warning ("\"%s\": no core file handler recognizes format, using default",
15898944Sobrien	       bfd_get_filename (abfd));
15998944Sobrien    }
16098944Sobrien  if (yummy == NULL)
16198944Sobrien    {
16298944Sobrien      yummy = core_file_fns;
16398944Sobrien    }
16498944Sobrien  return (yummy);
16598944Sobrien}
16698944Sobrien
16798944Sobrien/* The default is to reject every core file format we see.  Either
16898944Sobrien   BFD has to recognize it, or we have to provide a function in the
16998944Sobrien   core file handler that recognizes it. */
17098944Sobrien
17198944Sobrienint
17298944Sobriendefault_check_format (bfd *abfd)
17398944Sobrien{
17498944Sobrien  return (0);
17598944Sobrien}
17698944Sobrien
17798944Sobrien/* Attempt to recognize core file formats that BFD rejects. */
17898944Sobrien
179130803Smarcelstatic int
18098944Sobriengdb_check_format (bfd *abfd)
18198944Sobrien{
18298944Sobrien  struct core_fns *cf;
18398944Sobrien
18498944Sobrien  for (cf = core_file_fns; cf != NULL; cf = cf->next)
18598944Sobrien    {
18698944Sobrien      if (cf->check_format (abfd))
18798944Sobrien	{
18898944Sobrien	  return (1);
18998944Sobrien	}
19098944Sobrien    }
19198944Sobrien  return (0);
19298944Sobrien}
19398944Sobrien
19419370Spst/* Discard all vestiges of any previous core file and mark data and stack
19519370Spst   spaces as empty.  */
19619370Spst
19719370Spststatic void
19898944Sobriencore_close (int quitting)
19919370Spst{
20019370Spst  char *name;
20119370Spst
20219370Spst  if (core_bfd)
20319370Spst    {
20498944Sobrien      inferior_ptid = null_ptid;	/* Avoid confusion from thread stuff */
20546283Sdfr
20698944Sobrien      /* Clear out solib state while the bfd is still open. See
20798944Sobrien         comments in clear_solib in solib.c. */
20898944Sobrien#ifdef CLEAR_SOLIB
20998944Sobrien      CLEAR_SOLIB ();
21098944Sobrien#endif
21198944Sobrien
21219370Spst      name = bfd_get_filename (core_bfd);
21319370Spst      if (!bfd_close (core_bfd))
21419370Spst	warning ("cannot close \"%s\": %s",
21519370Spst		 name, bfd_errmsg (bfd_get_error ()));
21698944Sobrien      xfree (name);
21719370Spst      core_bfd = NULL;
21819370Spst      if (core_ops.to_sections)
21919370Spst	{
22098944Sobrien	  xfree (core_ops.to_sections);
22119370Spst	  core_ops.to_sections = NULL;
22219370Spst	  core_ops.to_sections_end = NULL;
22319370Spst	}
22419370Spst    }
22598944Sobrien  core_vec = NULL;
226130803Smarcel  core_gdbarch = NULL;
22719370Spst}
22819370Spst
22998944Sobrienstatic void
23098944Sobriencore_close_cleanup (void *ignore)
23198944Sobrien{
23298944Sobrien  core_close (0/*ignored*/);
23398944Sobrien}
23498944Sobrien
23519370Spst#ifdef SOLIB_ADD
23619370Spst/* Stub function for catch_errors around shared library hacking.  FROM_TTYP
23719370Spst   is really an int * which points to from_tty.  */
23819370Spst
23998944Sobrienstatic int
240130803Smarcelsolib_add_stub (void *from_ttyp)
24119370Spst{
24298944Sobrien  SOLIB_ADD (NULL, *(int *) from_ttyp, &current_target, auto_solib_add);
24319370Spst  re_enable_breakpoints_in_shlibs ();
24419370Spst  return 0;
24519370Spst}
24619370Spst#endif /* SOLIB_ADD */
24719370Spst
24819370Spst/* Look for sections whose names start with `.reg/' so that we can extract the
24919370Spst   list of threads in a core file.  */
25019370Spst
25119370Spststatic void
252130803Smarceladd_to_thread_list (bfd *abfd, asection *asect, void *reg_sect_arg)
25319370Spst{
25419370Spst  int thread_id;
25519370Spst  asection *reg_sect = (asection *) reg_sect_arg;
25619370Spst
25719370Spst  if (strncmp (bfd_section_name (abfd, asect), ".reg/", 5) != 0)
25819370Spst    return;
25919370Spst
26019370Spst  thread_id = atoi (bfd_section_name (abfd, asect) + 5);
26119370Spst
26298944Sobrien  add_thread (pid_to_ptid (thread_id));
26319370Spst
26419370Spst/* Warning, Will Robinson, looking at BFD private data! */
26519370Spst
26646283Sdfr  if (reg_sect != NULL
26798944Sobrien      && asect->filepos == reg_sect->filepos)	/* Did we find .reg? */
26898944Sobrien    inferior_ptid = pid_to_ptid (thread_id);	/* Yes, make it current */
26919370Spst}
27019370Spst
27119370Spst/* This routine opens and sets up the core file bfd.  */
27219370Spst
27319370Spststatic void
27498944Sobriencore_open (char *filename, int from_tty)
27519370Spst{
27619370Spst  const char *p;
27719370Spst  int siggy;
27819370Spst  struct cleanup *old_chain;
27919370Spst  char *temp;
28019370Spst  bfd *temp_bfd;
28119370Spst  int ontop;
28219370Spst  int scratch_chan;
28319370Spst
28419370Spst  target_preopen (from_tty);
28519370Spst  if (!filename)
28619370Spst    {
28798944Sobrien      error (core_bfd ?
28898944Sobrien	     "No core file specified.  (Use `detach' to stop debugging a core file.)"
28998944Sobrien	     : "No core file specified.");
29019370Spst    }
29119370Spst
29219370Spst  filename = tilde_expand (filename);
29319370Spst  if (filename[0] != '/')
29419370Spst    {
29519370Spst      temp = concat (current_directory, "/", filename, NULL);
29698944Sobrien      xfree (filename);
29719370Spst      filename = temp;
29819370Spst    }
29919370Spst
30098944Sobrien  old_chain = make_cleanup (xfree, filename);
30119370Spst
30298944Sobrien  scratch_chan = open (filename, O_BINARY | ( write_files ? O_RDWR : O_RDONLY ), 0);
30319370Spst  if (scratch_chan < 0)
30419370Spst    perror_with_name (filename);
30519370Spst
30619370Spst  temp_bfd = bfd_fdopenr (filename, gnutarget, scratch_chan);
30719370Spst  if (temp_bfd == NULL)
30819370Spst    perror_with_name (filename);
30919370Spst
31098944Sobrien  if (!bfd_check_format (temp_bfd, bfd_core) &&
31198944Sobrien      !gdb_check_format (temp_bfd))
31219370Spst    {
31319370Spst      /* Do it after the err msg */
31419370Spst      /* FIXME: should be checking for errors from bfd_close (for one thing,
31598944Sobrien         on error it does not free all the storage associated with the
31698944Sobrien         bfd).  */
31798944Sobrien      make_cleanup_bfd_close (temp_bfd);
31819370Spst      error ("\"%s\" is not a core dump: %s",
31919370Spst	     filename, bfd_errmsg (bfd_get_error ()));
32019370Spst    }
32119370Spst
32219370Spst  /* Looks semi-reasonable.  Toss the old core file and work on the new.  */
32319370Spst
32498944Sobrien  discard_cleanups (old_chain);	/* Don't free filename any more */
32519370Spst  unpush_target (&core_ops);
32619370Spst  core_bfd = temp_bfd;
32798944Sobrien  old_chain = make_cleanup (core_close_cleanup, 0 /*ignore*/);
32819370Spst
329130803Smarcel  /* FIXME: kettenis/20031023: This is very dangerous.  The
330130803Smarcel     CORE_GDBARCH that results from this call may very well be
331130803Smarcel     different from CURRENT_GDBARCH.  However, its methods may only
332130803Smarcel     work if it is selected as the current architecture, because they
333130803Smarcel     rely on swapped data (see gdbarch.c).  We should get rid of that
334130803Smarcel     swapped data.  */
335130803Smarcel  core_gdbarch = gdbarch_from_bfd (core_bfd);
336130803Smarcel
33798944Sobrien  /* Find a suitable core file handler to munch on core_bfd */
33898944Sobrien  core_vec = sniff_core_bfd (core_bfd);
33998944Sobrien
34019370Spst  validate_files ();
34119370Spst
34219370Spst  /* Find the data section */
34319370Spst  if (build_section_table (core_bfd, &core_ops.to_sections,
34419370Spst			   &core_ops.to_sections_end))
34519370Spst    error ("\"%s\": Can't find sections: %s",
34619370Spst	   bfd_get_filename (core_bfd), bfd_errmsg (bfd_get_error ()));
34719370Spst
348130803Smarcel  /* If we have no exec file, try to set the architecture from the
349130803Smarcel     core file.  We don't do this unconditionally since an exec file
350130803Smarcel     typically contains more information that helps us determine the
351130803Smarcel     architecture than a core file.  */
352130803Smarcel  if (!exec_bfd)
353130803Smarcel    set_gdbarch_from_file (core_bfd);
35498944Sobrien
35519370Spst  ontop = !push_target (&core_ops);
35619370Spst  discard_cleanups (old_chain);
35719370Spst
35819370Spst  p = bfd_core_file_failing_command (core_bfd);
35919370Spst  if (p)
36019370Spst    printf_filtered ("Core was generated by `%s'.\n", p);
36119370Spst
36219370Spst  siggy = bfd_core_file_failing_signal (core_bfd);
36319370Spst  if (siggy > 0)
36498944Sobrien    /* NOTE: target_signal_from_host() converts a target signal value
36598944Sobrien       into gdb's internal signal value.  Unfortunately gdb's internal
36698944Sobrien       value is called ``target_signal'' and this function got the
36798944Sobrien       name ..._from_host(). */
36819370Spst    printf_filtered ("Program terminated with signal %d, %s.\n", siggy,
36998944Sobrien		     target_signal_to_string (target_signal_from_host (siggy)));
37019370Spst
37119370Spst  /* Build up thread list from BFD sections. */
37219370Spst
37319370Spst  init_thread_list ();
37419370Spst  bfd_map_over_sections (core_bfd, add_to_thread_list,
37519370Spst			 bfd_get_section_by_name (core_bfd, ".reg"));
37619370Spst
37719370Spst  if (ontop)
37819370Spst    {
37919370Spst      /* Fetch all registers from core file.  */
38019370Spst      target_fetch_registers (-1);
38119370Spst
38219370Spst      /* Add symbols and section mappings for any shared libraries.  */
38319370Spst#ifdef SOLIB_ADD
38498944Sobrien      catch_errors (solib_add_stub, &from_tty, (char *) 0,
38519370Spst		    RETURN_MASK_ALL);
38619370Spst#endif
38719370Spst
38819370Spst      /* Now, set up the frame cache, and print the top of stack.  */
38919370Spst      flush_cached_frames ();
390130803Smarcel      select_frame (get_current_frame ());
391130803Smarcel      print_stack_frame (deprecated_selected_frame,
392130803Smarcel			 frame_relative_level (deprecated_selected_frame), 1);
39319370Spst    }
39419370Spst  else
39519370Spst    {
39619370Spst      warning (
39798944Sobrien		"you won't be able to access this core file until you terminate\n\
39819370Spstyour %s; do ``info files''", target_longname);
39919370Spst    }
40019370Spst}
40119370Spst
40219370Spststatic void
40398944Sobriencore_detach (char *args, int from_tty)
40419370Spst{
40519370Spst  if (args)
40619370Spst    error ("Too many arguments");
40719370Spst  unpush_target (&core_ops);
40819370Spst  reinit_frame_cache ();
40919370Spst  if (from_tty)
41019370Spst    printf_filtered ("No core file now.\n");
41119370Spst}
41219370Spst
41319370Spst
41498944Sobrien/* Try to retrieve registers from a section in core_bfd, and supply
41598944Sobrien   them to core_vec->core_read_registers, as the register set numbered
41698944Sobrien   WHICH.
41719370Spst
41898944Sobrien   If inferior_ptid is zero, do the single-threaded thing: look for a
41998944Sobrien   section named NAME.  If inferior_ptid is non-zero, do the
42098944Sobrien   multi-threaded thing: look for a section named "NAME/PID", where
42198944Sobrien   PID is the shortest ASCII decimal representation of inferior_ptid.
42219370Spst
42398944Sobrien   HUMAN_NAME is a human-readable name for the kind of registers the
42498944Sobrien   NAME section contains, for use in error messages.
42519370Spst
42698944Sobrien   If REQUIRED is non-zero, print an error if the core file doesn't
42798944Sobrien   have a section by the appropriate name.  Otherwise, just do nothing.  */
42819370Spst
42998944Sobrienstatic void
43098944Sobrienget_core_register_section (char *name,
43198944Sobrien			   int which,
43298944Sobrien			   char *human_name,
43398944Sobrien			   int required)
43498944Sobrien{
435277816Spfg  static char *section_name = NULL;
436130803Smarcel  struct bfd_section *section;
43798944Sobrien  bfd_size_type size;
43898944Sobrien  char *contents;
43919370Spst
440277816Spfg  xfree (section_name);
44198944Sobrien  if (PIDGET (inferior_ptid))
442277816Spfg    section_name = xstrprintf ("%s/%d", name, PIDGET (inferior_ptid));
44319370Spst  else
444277816Spfg    section_name = xstrdup (name);
44519370Spst
44698944Sobrien  section = bfd_get_section_by_name (core_bfd, section_name);
44798944Sobrien  if (! section)
44819370Spst    {
44998944Sobrien      if (required)
45098944Sobrien	warning ("Couldn't find %s registers in core file.\n", human_name);
45198944Sobrien      return;
45219370Spst    }
45398944Sobrien
45498944Sobrien  size = bfd_section_size (core_bfd, section);
45598944Sobrien  contents = alloca (size);
45698944Sobrien  if (! bfd_get_section_contents (core_bfd, section, contents,
45798944Sobrien				  (file_ptr) 0, size))
45819370Spst    {
45998944Sobrien      warning ("Couldn't read %s registers from `%s' section in core file.\n",
46098944Sobrien	       human_name, name);
46198944Sobrien      return;
46219370Spst    }
46319370Spst
464130803Smarcel  if (core_gdbarch && gdbarch_regset_from_core_section_p (core_gdbarch))
465130803Smarcel    {
466130803Smarcel      const struct regset *regset;
467130803Smarcel
468130803Smarcel      regset = gdbarch_regset_from_core_section (core_gdbarch, name, size);
469130803Smarcel      if (regset == NULL)
470130803Smarcel	{
471130803Smarcel	  if (required)
472130803Smarcel	    warning ("Couldn't recognize %s registers in core file.\n",
473130803Smarcel		     human_name);
474130803Smarcel	  return;
475130803Smarcel	}
476130803Smarcel
477130803Smarcel      regset->supply_regset (regset, current_regcache, -1, contents, size);
478130803Smarcel      return;
479130803Smarcel    }
480130803Smarcel
481130803Smarcel  gdb_assert (core_vec);
482130803Smarcel  core_vec->core_read_registers (contents, size, which,
48398944Sobrien				 ((CORE_ADDR)
48498944Sobrien				  bfd_section_vma (core_bfd, section)));
48519370Spst}
48619370Spst
48746283Sdfr
48898944Sobrien/* Get the registers out of a core file.  This is the machine-
48998944Sobrien   independent part.  Fetch_core_registers is the machine-dependent
49098944Sobrien   part, typically implemented in the xm-file for each architecture.  */
49146283Sdfr
49298944Sobrien/* We just get all the registers, so we don't use regno.  */
49346283Sdfr
49498944Sobrienstatic void
49598944Sobrienget_core_registers (int regno)
49698944Sobrien{
49798944Sobrien  int status;
49846283Sdfr
499130803Smarcel  if (!(core_gdbarch && gdbarch_regset_from_core_section_p (core_gdbarch))
500130803Smarcel      && (core_vec == NULL || core_vec->core_read_registers == NULL))
50146283Sdfr    {
50298944Sobrien      fprintf_filtered (gdb_stderr,
50398944Sobrien		     "Can't fetch registers from this type of core file\n");
50498944Sobrien      return;
50546283Sdfr    }
50646283Sdfr
50798944Sobrien  get_core_register_section (".reg", 0, "general-purpose", 1);
50898944Sobrien  get_core_register_section (".reg2", 2, "floating-point", 0);
50998944Sobrien  get_core_register_section (".reg-xfp", 3, "extended floating-point", 0);
51046283Sdfr
511130803Smarcel  deprecated_registers_fetched ();
51246283Sdfr}
51346283Sdfr
51419370Spststatic void
51598944Sobriencore_files_info (struct target_ops *t)
51619370Spst{
51719370Spst  print_section_info (t, core_bfd);
51819370Spst}
51919370Spst
520130803Smarcelstatic LONGEST
521130803Smarcelcore_xfer_partial (struct target_ops *ops, enum target_object object,
522130803Smarcel		   const char *annex, void *readbuf,
523130803Smarcel		   const void *writebuf, ULONGEST offset, LONGEST len)
524130803Smarcel{
525130803Smarcel  switch (object)
526130803Smarcel    {
527130803Smarcel    case TARGET_OBJECT_MEMORY:
528130803Smarcel      if (readbuf)
529132685Smarcel	return (*ops->to_xfer_memory) (offset, readbuf, len, 0/*read*/,
530130803Smarcel				       NULL, ops);
531130803Smarcel      if (writebuf)
532132685Smarcel	return (*ops->to_xfer_memory) (offset, writebuf, len, 1/*write*/,
533130803Smarcel				       NULL, ops);
534130803Smarcel      return -1;
535130803Smarcel
536130803Smarcel    case TARGET_OBJECT_AUXV:
537130803Smarcel      if (readbuf)
538130803Smarcel	{
539130803Smarcel	  /* When the aux vector is stored in core file, BFD
540130803Smarcel	     represents this with a fake section called ".auxv".  */
541130803Smarcel
542130803Smarcel	  struct bfd_section *section;
543130803Smarcel	  bfd_size_type size;
544130803Smarcel	  char *contents;
545130803Smarcel
546130803Smarcel	  section = bfd_get_section_by_name (core_bfd, ".auxv");
547130803Smarcel	  if (section == NULL)
548130803Smarcel	    return -1;
549130803Smarcel
550130803Smarcel	  size = bfd_section_size (core_bfd, section);
551130803Smarcel	  if (offset >= size)
552130803Smarcel	    return 0;
553130803Smarcel	  size -= offset;
554130803Smarcel	  if (size > len)
555130803Smarcel	    size = len;
556130803Smarcel	  if (size > 0 &&
557130803Smarcel	      ! bfd_get_section_contents (core_bfd, section, readbuf,
558130803Smarcel					  (file_ptr) offset, size))
559130803Smarcel	    {
560130803Smarcel	      warning ("Couldn't read NT_AUXV note in core file.");
561130803Smarcel	      return -1;
562130803Smarcel	    }
563130803Smarcel
564130803Smarcel	  return size;
565130803Smarcel	}
566130803Smarcel      return -1;
567130803Smarcel
568132685Smarcel    case TARGET_OBJECT_DIRTY:
569132685Smarcel      {
570132685Smarcel	ULONGEST addr;
571132685Smarcel	addr = *(ULONGEST*)annex + offset;
572132685Smarcel	if (readbuf)
573132685Smarcel	  return (*ops->to_xfer_memory) (addr, readbuf, len, 0/*read*/,
574132685Smarcel					 NULL, ops);
575132685Smarcel	if (writebuf)
576132685Smarcel	  return (*ops->to_xfer_memory) (addr, writebuf, len, 1/*write*/,
577132685Smarcel					 NULL, ops);
578132685Smarcel	return -1;
579132685Smarcel      }
580132685Smarcel
581130803Smarcel    default:
582130803Smarcel      if (ops->beneath != NULL)
583130803Smarcel	return ops->beneath->to_xfer_partial (ops->beneath, object, annex,
584130803Smarcel					      readbuf, writebuf, offset, len);
585130803Smarcel      return -1;
586130803Smarcel    }
587130803Smarcel}
588130803Smarcel
589130803Smarcel
59019370Spst/* If mourn is being called in all the right places, this could be say
59119370Spst   `gdb internal error' (since generic_mourn calls breakpoint_init_inferior).  */
59219370Spst
59319370Spststatic int
59498944Sobrienignore (CORE_ADDR addr, char *contents)
59519370Spst{
59619370Spst  return 0;
59719370Spst}
59819370Spst
59919370Spst
60046283Sdfr/* Okay, let's be honest: threads gleaned from a core file aren't
60146283Sdfr   exactly lively, are they?  On the other hand, if we don't claim
60246283Sdfr   that each & every one is alive, then we don't get any of them
60346283Sdfr   to appear in an "info thread" command, which is quite a useful
60446283Sdfr   behaviour.
60598944Sobrien */
60646283Sdfrstatic int
60798944Sobriencore_file_thread_alive (ptid_t tid)
60846283Sdfr{
60946283Sdfr  return 1;
61046283Sdfr}
61146283Sdfr
61246283Sdfr/* Fill in core_ops with its defined operations and properties.  */
61346283Sdfr
61446283Sdfrstatic void
61598944Sobrieninit_core_ops (void)
61646283Sdfr{
61746283Sdfr  core_ops.to_shortname = "core";
61846283Sdfr  core_ops.to_longname = "Local core dump file";
61946283Sdfr  core_ops.to_doc =
62046283Sdfr    "Use a core file as a target.  Specify the filename of the core file.";
62146283Sdfr  core_ops.to_open = core_open;
62246283Sdfr  core_ops.to_close = core_close;
62346283Sdfr  core_ops.to_attach = find_default_attach;
62446283Sdfr  core_ops.to_detach = core_detach;
62546283Sdfr  core_ops.to_fetch_registers = get_core_registers;
626130803Smarcel  core_ops.to_xfer_partial = core_xfer_partial;
62746283Sdfr  core_ops.to_xfer_memory = xfer_memory;
62846283Sdfr  core_ops.to_files_info = core_files_info;
62946283Sdfr  core_ops.to_insert_breakpoint = ignore;
63046283Sdfr  core_ops.to_remove_breakpoint = ignore;
63146283Sdfr  core_ops.to_create_inferior = find_default_create_inferior;
63246283Sdfr  core_ops.to_thread_alive = core_file_thread_alive;
63346283Sdfr  core_ops.to_stratum = core_stratum;
63446283Sdfr  core_ops.to_has_memory = 1;
63546283Sdfr  core_ops.to_has_stack = 1;
63646283Sdfr  core_ops.to_has_registers = 1;
63798944Sobrien  core_ops.to_magic = OPS_MAGIC;
63846283Sdfr}
63946283Sdfr
64046283Sdfr/* non-zero if we should not do the add_target call in
64146283Sdfr   _initialize_corelow; not initialized (i.e., bss) so that
64246283Sdfr   the target can initialize it (i.e., data) if appropriate.
64346283Sdfr   This needs to be set at compile time because we don't know
64446283Sdfr   for sure whether the target's initialize routine is called
64546283Sdfr   before us or after us. */
64646283Sdfrint coreops_suppress_target;
64746283Sdfr
64819370Spstvoid
64998944Sobrien_initialize_corelow (void)
65019370Spst{
65146283Sdfr  init_core_ops ();
65246283Sdfr
65346283Sdfr  if (!coreops_suppress_target)
65446283Sdfr    add_target (&core_ops);
65519370Spst}
656