* config/pa/tm-hppa.h: Define lots register offsets needed by
[deliverable/binutils-gdb.git] / gdb / core.c
index 119f7162f2f45edeabe06f978a59bdd893ff9d77..974e55c1859de6cdf1f8ae1ef42a01e868b2be1e 100644 (file)
-/* Work with core dump and executable files, for GDB.
-   Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+/* Core dump and executable file functions above target vector, for GDB.
+   Copyright 1986, 1987, 1989, 1991, 1992, 1993, 1994
+   Free Software Foundation, Inc.
 
 This file is part of GDB.
 
-GDB is free software; you can redistribute it and/or modify
+This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 1, or (at your option)
-any later version.
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
 
-GDB is distributed in the hope that it will be useful,
+This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with GDB; see the file COPYING.  If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
-#include <stdio.h>
+#include "defs.h"
+#include <string.h>
 #include <errno.h>
 #include <signal.h>
-#include "defs.h"
-#include "param.h"
+#include <fcntl.h>
 #include "frame.h"  /* required by inferior.h */
 #include "inferior.h"
 #include "symtab.h"
 #include "command.h"
+#include "gdbcmd.h"
 #include "bfd.h"
 #include "target.h"
 #include "gdbcore.h"
-
-extern int xfer_memory ();
-extern void child_attach (), child_create_inferior ();
-
-extern int sys_nerr;
-extern char *sys_errlist[];
-extern char *sys_siglist[];
+#include "dis-asm.h"
+#include "language.h"
 
 extern char registers[];
 
 /* Hook for `exec_file_command' command to call.  */
 
-void (*exec_file_display_hook) () = NULL;
-
-struct section_table *core_sections, *core_sections_end;
+void (*exec_file_display_hook) PARAMS ((char *)) = NULL;
 
 /* Binary file diddling handle for the core file.  */
 
 bfd *core_bfd = NULL;
 
-/* Forward decl */
-extern struct target_ops core_ops;
-
 \f
-/* Discard all vestiges of any previous core file
-   and mark data and stack spaces as empty.  */
-
-void
-core_close (quitting)
-     int quitting;
-{
-  if (core_bfd) {
-    free (bfd_get_filename (core_bfd));
-    bfd_close (core_bfd);
-    core_bfd = NULL;
-  }
-}
-
-/* This routine opens and sets up the core file bfd */
-
-void
-core_open (filename, from_tty)
-     char *filename;
-     int from_tty;
-{
-  char *p;
-  int siggy;
-  struct cleanup *old_chain;
-  char *temp;
-  bfd *temp_bfd;
-  int ontop;
-
-  if (!filename)
-    {
-      error (core_bfd? 
-       "No core file specified.  (Use `detach' to stop debugging a core file.)"
-     : "No core file specified.");
-    }
-
-  filename = tilde_expand (filename);
-  if (filename[0] != '/') {
-    temp = concat (current_directory, "/", filename);
-    free (filename);
-    filename = temp;
-  }
-
-  old_chain = make_cleanup (free, filename);
-  temp_bfd = bfd_openr (filename, NULL);
-  if (temp_bfd == NULL)
-    {
-      perror_with_name (filename);
-    }
-
-  if (!bfd_check_format (temp_bfd, bfd_core))
-    {
-      bfd_close (temp_bfd);
-      error ("\"%s\" does not appear to be a core dump", filename);
-    }
-
-  /* Looks semi-reasonable.  Toss the old core file and work on the new.  */
-
-  discard_cleanups (old_chain);                /* Don't free filename any more */
-  unpush_target (&core_ops);
-  core_bfd = temp_bfd;
-  old_chain = make_cleanup (core_close, core_bfd);
-
-  validate_files ();
-
-  /* Find the data section */
-  if (build_section_table (core_bfd, &core_sections, &core_sections_end))
-    error ("Can't find sections in `%s': %s", bfd_get_filename(core_bfd),
-          bfd_errmsg (bfd_error));
-
-  ontop = !push_target (&core_ops);
-
-  p = bfd_core_file_failing_command (core_bfd);
-  if (p)
-    printf ("Core file invoked as `%s'.\n", p);
-
-  siggy = bfd_core_file_failing_signal (core_bfd);
-  if (siggy > 0)
-    printf ("Program terminated with signal %d, %s.\n", siggy,
-           siggy < NSIG ? sys_siglist[siggy] : "(undocumented)");
-
-  if (ontop) {
-    /* Fetch all registers from core file */
-    target_fetch_registers (-1);
-    set_current_frame ( create_new_frame (read_register (FP_REGNUM),
-                                         read_pc ()));
-    select_frame (get_current_frame (), 0);
-    /* FIXME, handle shared library reading here.  */
-    print_sel_frame (0);       /* Print the top frame and source line */
-  } else {
-    printf (
-"Warning: you won't be able to access this core file until you terminate\n\
-your %s; do ``info files''\n", current_target->to_longname);
-  }
-
-  discard_cleanups (old_chain);
-}
-
-void
-core_detach (args, from_tty)
-     char *args;
-     int from_tty;
-{
-  if (args)
-    error ("Too many arguments");
-  unpush_target (&core_ops);
-  if (from_tty)
-    printf ("No core file now.\n");
-}
-
 /* Backward compatability with old way of specifying core files.  */
 
 void
@@ -169,11 +52,18 @@ core_file_command (filename, from_tty)
      char *filename;
      int from_tty;
 {
+  struct target_ops *t;
+
   dont_repeat ();                      /* Either way, seems bogus. */
-  if (!filename)
-    core_detach (filename, from_tty);
+
+  t = find_core_target ();
+  if (t != NULL)
+    if (!filename)
+      (t->to_detach) (filename, from_tty);
+    else
+      (t->to_open) (filename, from_tty);
   else
-    core_open (filename, from_tty);
+    error ("GDB can't read core files on this machine.");
 }
 
 \f
@@ -182,7 +72,7 @@ core_file_command (filename, from_tty)
 
 void
 specify_exec_file_hook (hook)
-     void (*hook) ();
+     void (*hook) PARAMS ((char *));
 {
   exec_file_display_hook = hook;
 }
@@ -210,19 +100,17 @@ reopen_exec_file ()
 }
 \f
 /* If we have both a core file and an exec file,
-   print a warning if they don't go together.
-   This should really check that the core file came
-   from that exec file, but I don't know how to do it.  */
+   print a warning if they don't go together.  */
 
 void
 validate_files ()
 {
   if (exec_bfd && core_bfd)
     {
-      if (core_file_matches_executable_p (core_bfd, exec_bfd))
-       printf ("Warning: core file does not match specified executable file.\n");
+      if (!core_file_matches_executable_p (core_bfd, exec_bfd))
+       warning ("core file may not match specified executable file.");
       else if (bfd_get_mtime(exec_bfd) > bfd_get_mtime(core_bfd))
-       printf ("Warning: exec file is newer than core file.\n");
+       warning ("exec file is newer than core file.");
     }
 }
 
@@ -242,39 +130,32 @@ Use the \"file\" or \"exec-file\" command.");
   return NULL;
 }
 
-static void
-core_files_info ()
-{
-  struct section_table *p;
-
-  printf ("\tCore file `%s'.\n", bfd_get_filename(core_bfd));
-
-  for (p = core_sections; p < core_sections_end; p++)
-    printf("\tcore file  from 0x%08x to 0x%08x is %s\n",
-       p->addr, p->endaddr,
-       bfd_section_name (core_bfd, p->sec_ptr));
-}
 \f
+/* Report a memory error with error().  */
+
 void
 memory_error (status, memaddr)
      int status;
      CORE_ADDR memaddr;
 {
-
   if (status == EIO)
     {
       /* Actually, address between memaddr and memaddr + len
         was out of bounds. */
-      error ("Cannot access memory: address 0x%x out of bounds.", memaddr);
+      error_begin ();
+      printf_filtered ("Cannot access memory at address ");
+      print_address_numeric (memaddr, 1, gdb_stdout);
+      printf_filtered (".\n");
+      return_to_top_level (RETURN_ERROR);
     }
   else
     {
-      if (status >= sys_nerr || status < 0)
-       error ("Error accessing memory address 0x%x: unknown error (%d).",
-              memaddr, status);
-      else
-       error ("Error accessing memory address 0x%x: %s.",
-              memaddr, sys_errlist[status]);
+      error_begin ();
+      printf_filtered ("Error accessing memory address ");
+      print_address_numeric (memaddr, 1, gdb_stdout);
+      printf_filtered (": %s.\n",
+                        safe_strerror (status));
+      return_to_top_level (RETURN_ERROR);
     }
 }
 
@@ -291,6 +172,37 @@ read_memory (memaddr, myaddr, len)
     memory_error (status, memaddr);
 }
 
+/* Like target_read_memory, but slightly different parameters.  */
+
+int
+dis_asm_read_memory (memaddr, myaddr, len, info)
+     bfd_vma memaddr;
+     bfd_byte *myaddr;
+     int len;
+     disassemble_info *info;
+{
+  return target_read_memory (memaddr, (char *) myaddr, len);
+}
+
+/* Like memory_error with slightly different parameters.  */
+void
+dis_asm_memory_error (status, memaddr, info)
+     int status;
+     bfd_vma memaddr;
+     disassemble_info *info;
+{
+  memory_error (status, memaddr);
+}
+
+/* Like print_address with slightly different parameters.  */
+void
+dis_asm_print_address (addr, info)
+     bfd_vma addr;
+     struct disassemble_info *info;
+{
+  print_address (addr, info->stream);
+}
+
 /* Same as target_write_memory, but report an error if can't write.  */
 void
 write_memory (memaddr, myaddr, len)
@@ -307,141 +219,121 @@ write_memory (memaddr, myaddr, len)
 
 /* Read an integer from debugged memory, given address and number of bytes.  */
 
-long
+LONGEST
 read_memory_integer (memaddr, len)
      CORE_ADDR memaddr;
      int len;
 {
-  char cbuf;
-  short sbuf;
-  int ibuf;
-  long lbuf;
+  char buf[sizeof (LONGEST)];
 
-  if (len == sizeof (char))
-    {
-      read_memory (memaddr, &cbuf, len);
-      return cbuf;
-    }
-  if (len == sizeof (short))
-    {
-      read_memory (memaddr, (char *)&sbuf, len);
-      SWAP_TARGET_AND_HOST (&sbuf, sizeof (short));
-      return sbuf;
-    }
-  if (len == sizeof (int))
-    {
-      read_memory (memaddr, (char *)&ibuf, len);
-      SWAP_TARGET_AND_HOST (&ibuf, sizeof (int));
-      return ibuf;
-    }
-  if (len == sizeof (lbuf))
-    {
-      read_memory (memaddr, (char *)&lbuf, len);
-      SWAP_TARGET_AND_HOST (&lbuf, sizeof (lbuf));
-      return lbuf;
-    }
-  error ("Cannot handle integers of %d bytes.", len);
-  return -1;   /* for lint */
+  read_memory (memaddr, buf, len);
+  return extract_signed_integer (buf, len);
 }
-\f
-/* Read or write the core file.
-
-   Args are address within core file, address within gdb address-space,
-   length, and a flag indicating whether to read or write.
-
-   Result is a length:
-
-       0:    We cannot handle this address and length.
-       > 0:  We have handled N bytes starting at this address.
-             (If N == length, we did it all.)  We might be able
-             to handle more bytes beyond this length, but no
-             promises.
-       < 0:  We cannot handle this address, but if somebody
-             else handles (-N) bytes, we can start from there.
 
-   The actual work is done by xfer_memory in exec.c, which we share
-   in common with exec_xfer_memory().  */
-
-static int
-core_xfer_memory (memaddr, myaddr, len, write)
+unsigned LONGEST
+read_memory_unsigned_integer (memaddr, len)
      CORE_ADDR memaddr;
-     char *myaddr;
      int len;
-     int write;
 {
-  return xfer_memory (memaddr, myaddr, len, write,
-                     core_bfd, core_sections, core_sections_end);
+  char buf[sizeof (unsigned LONGEST)];
+
+  read_memory (memaddr, buf, len);
+  return extract_unsigned_integer (buf, len);
 }
 \f
-/* Get the registers out of a core file.  This is the machine-
-   independent part.  Fetch_core_registers is the machine-dependent
-   part, typically implemented in the xm-file for each architecture.  */
+#if 0
+/* Enable after 4.12.  It is not tested.  */
 
-static int
-get_core_registers (regno)
-     int regno;
+/* Search code.  Targets can just make this their search function, or
+   if the protocol has a less general search function, they can call this
+   in the cases it can't handle.  */
+void
+generic_search (len, data, mask, startaddr, increment, lorange, hirange
+               addr_found, data_found)
+     int len;
+     char *data;
+     char *mask;
+     CORE_ADDR startaddr;
+     int increment;
+     CORE_ADDR lorange;
+     CORE_ADDR hirange;
+     CORE_ADDR *addr_found;
+     char *data_found;
 {
-  sec_ptr reg_sec;
-  unsigned size;
-  char *the_regs;
-
-  reg_sec = bfd_get_section_by_name (core_bfd, ".reg");
-  size = bfd_section_size (core_bfd, reg_sec);
-  the_regs = alloca (size);
-  if (bfd_get_section_contents (core_bfd, reg_sec, the_regs,
-                               (unsigned)0, size))
+  int i;
+  CORE_ADDR curaddr = startaddr;
+
+  while (curaddr >= lorange && curaddr < hirange)
     {
-      fetch_core_registers (the_regs, size, 0);
+      read_memory (curaddr, data_found, len);
+      for (i = 0; i < len; ++i)
+       if ((data_found[i] & mask[i]) != data[i])
+         goto try_again;
+      /* It matches.  */
+      *addr_found = curaddr;
+      return;
+
+    try_again:
+      curaddr += increment;
     }
+  *addr_found = (CORE_ADDR)0;
+  return;
+}
+#endif /* 0 */
+\f
+/* The current default bfd target.  Points to storage allocated for
+   gnutarget_string.  */
+char *gnutarget;
+
+/* Same thing, except it is "auto" not NULL for the default case.  */
+static char *gnutarget_string;
+
+static void set_gnutarget_command
+  PARAMS ((char *, int, struct cmd_list_element *));
+
+static void
+set_gnutarget_command (ignore, from_tty, c)
+     char *ignore;
+     int from_tty;
+     struct cmd_list_element *c;
+{
+  if (STREQ (gnutarget_string, "auto"))
+    gnutarget = NULL;
   else
-    {
-      fprintf (stderr, "Couldn't fetch registers from core file: %s\n",
-              bfd_errmsg (bfd_error));
-    }
+    gnutarget = gnutarget_string;
+}
 
-  /* Now do it again for the float registers, if they exist.  */
-  reg_sec = bfd_get_section_by_name (core_bfd, ".reg2");
-  if (reg_sec) {
-    size = bfd_section_size (core_bfd, reg_sec);
-    the_regs = alloca (size);
-    if (bfd_get_section_contents (core_bfd, reg_sec, the_regs,
-                                 (unsigned)0, size))
-      {
-       fetch_core_registers (the_regs, size, 2);
-      }
-    else
-      {
-       fprintf (stderr, "Couldn't fetch register set 2 from core file: %s\n",
-                bfd_errmsg (bfd_error));
-      }
-  }
-  registers_fetched();
-  return 0;  /* FIXME, what result goes here?  */
+/* Set the gnutarget.  */
+void
+set_gnutarget (newtarget)
+     char *newtarget;
+{
+  if (gnutarget_string != NULL)
+    free (gnutarget_string);
+  gnutarget_string = savestring (newtarget, strlen (newtarget));
+  set_gnutarget_command (NULL, 0, NULL);
 }
-\f
-struct target_ops core_ops = {
-       "core", "Local core dump file",
-       core_open, core_close,
-       child_attach, core_detach, 0, 0, /* resume, wait */
-       get_core_registers, 
-       0, 0, 0, 0, /* store_regs, prepare_to_store, conv_to, conv_from */
-       core_xfer_memory, core_files_info,
-       0, 0, /* core_insert_breakpoint, core_remove_breakpoint, */
-       0, 0, 0, 0, 0, /* terminal stuff */
-       0, 0, 0, 0, 0, /* kill, load, add_syms, call fn, lookup sym */
-       child_create_inferior, 0, /* mourn_inferior */
-       core_stratum, 0, /* next */
-       0, 1, 1, 1, 0,  /* all mem, mem, stack, regs, exec */
-       OPS_MAGIC,              /* Always the last thing */
-};
 
 void
 _initialize_core()
 {
-
-  add_com ("core-file", class_files, core_file_command,
-          "Use FILE as core dump for examining memory and registers.\n\
+  struct cmd_list_element *c;
+  c = add_cmd ("core-file", class_files, core_file_command,
+              "Use FILE as core dump for examining memory and registers.\n\
 No arg means have no core file.  This command has been superseded by the\n\
-`target core' and `detach' commands.");
-  add_target (&core_ops);
+`target core' and `detach' commands.", &cmdlist);
+  c->completer = filename_completer;
+
+  c = add_set_cmd ("gnutarget", class_files, var_string_noescape,
+                 (char *) &gnutarget_string,
+                 "Set the current BFD target.\n\
+Use `set gnutarget auto' to specify automatic detection.",
+                 &setlist);
+  c->function.sfunc = set_gnutarget_command;
+  add_show_from_set (c, &showlist);
+
+  if (getenv ("GNUTARGET"))
+    set_gnutarget (getenv ("GNUTARGET"));
+  else
+    set_gnutarget ("auto");
 }
This page took 0.029331 seconds and 4 git commands to generate.