* linux-low.c: Delete inclusion of ansidecl.h, elf/common.h,
[deliverable/binutils-gdb.git] / gdb / corelow.c
index 7956bef6b915f61b7fcc347c454c794f0f2a38ac..d0eada65ffb329b205286773cae58cbfea4ab2f9 100644 (file)
@@ -45,6 +45,7 @@
 #include "exceptions.h"
 #include "solib.h"
 #include "filenames.h"
+#include "progspace.h"
 
 
 #ifndef O_LARGEFILE
@@ -75,6 +76,9 @@ struct gdbarch *core_gdbarch = NULL;
    unix child targets.  */
 static struct target_section_table *core_data;
 
+/* True if we needed to fake the pid of the loaded core inferior.  */
+static int core_has_fake_pid = 0;
+
 static void core_files_info (struct target_ops *);
 
 static struct core_fns *sniff_core_bfd (bfd *);
@@ -205,7 +209,7 @@ core_close (int quitting)
     {
       int pid = ptid_get_pid (inferior_ptid);
       inferior_ptid = null_ptid;       /* Avoid confusion from thread stuff */
-      delete_inferior_silent (pid);
+      exit_inferior_silent (pid);
 
       /* Clear out solib state while the bfd is still open. See
          comments in clear_solib in solib.c. */
@@ -214,6 +218,7 @@ core_close (int quitting)
       xfree (core_data->sections);
       xfree (core_data);
       core_data = NULL;
+      core_has_fake_pid = 0;
 
       name = bfd_get_filename (core_bfd);
       if (!bfd_close (core_bfd))
@@ -239,32 +244,44 @@ static void
 add_to_thread_list (bfd *abfd, asection *asect, void *reg_sect_arg)
 {
   ptid_t ptid;
-  int thread_id;
+  int core_tid;
+  int pid, lwpid;
   asection *reg_sect = (asection *) reg_sect_arg;
 
   if (strncmp (bfd_section_name (abfd, asect), ".reg/", 5) != 0)
     return;
 
-  thread_id = atoi (bfd_section_name (abfd, asect) + 5);
+  core_tid = atoi (bfd_section_name (abfd, asect) + 5);
 
   if (core_gdbarch
       && gdbarch_core_reg_section_encodes_pid (core_gdbarch))
     {
-      uint32_t merged_pid = thread_id;
-      ptid = ptid_build (merged_pid & 0xffff,
-                        merged_pid >> 16, 0);
+      uint32_t merged_pid = core_tid;
+      pid = merged_pid & 0xffff;
+      lwpid = merged_pid >> 16;
+
+      /* This can happen on solaris core, for example, if we don't
+        find a NT_PSTATUS note in the core, but do find NT_LWPSTATUS
+        notes.  */
+      if (pid == 0)
+       {
+         core_has_fake_pid = 1;
+         pid = CORELOW_PID;
+       }
     }
   else
-    ptid = ptid_build (ptid_get_pid (inferior_ptid), thread_id, 0);
+    {
+      core_has_fake_pid = 1;
+      pid = CORELOW_PID;
+      lwpid = core_tid;
+    }
 
-  if (ptid_get_lwp (inferior_ptid) == 0)
-    /* The main thread has already been added before getting here, and
-       this is the first time we hear about a thread id.  Assume this
-       is the main thread.  */
-    thread_change_ptid (inferior_ptid, ptid);
-  else
-    /* Nope, really a new thread.  */
-    add_thread (ptid);
+  if (current_inferior ()->pid == 0)
+    inferior_appeared (current_inferior (), pid);
+
+  ptid = ptid_build (pid, lwpid, 0);
+
+  add_thread (ptid);
 
 /* Warning, Will Robinson, looking at BFD private data! */
 
@@ -286,6 +303,7 @@ core_open (char *filename, int from_tty)
   int scratch_chan;
   int flags;
   int corelow_pid = CORELOW_PID;
+  struct inferior *inf;
 
   target_preopen (from_tty);
   if (!filename)
@@ -321,8 +339,8 @@ core_open (char *filename, int from_tty)
   if (temp_bfd == NULL)
     perror_with_name (filename);
 
-  if (!bfd_check_format (temp_bfd, bfd_core) &&
-      !gdb_check_format (temp_bfd))
+  if (!bfd_check_format (temp_bfd, bfd_core)
+      && !gdb_check_format (temp_bfd))
     {
       /* Do it after the err msg */
       /* FIXME: should be checking for errors from bfd_close (for one thing,
@@ -371,21 +389,14 @@ core_open (char *filename, int from_tty)
   push_target (&core_ops);
   discard_cleanups (old_chain);
 
-  add_inferior_silent (corelow_pid);
-
   /* Do this before acknowledging the inferior, so if
      post_create_inferior throws (can happen easilly if you're loading
      a core file with the wrong exec), we aren't left with threads
      from the previous inferior.  */
   init_thread_list ();
 
-  /* Set INFERIOR_PTID early, so an upper layer can rely on it being
-     set while in the target_find_new_threads call below.  */
-  inferior_ptid = pid_to_ptid (corelow_pid);
-
-  /* Assume ST --- Add a main task.  We'll later detect when we go
-     from ST to MT.  */
-  add_thread_silent (inferior_ptid);
+  inferior_ptid = null_ptid;
+  core_has_fake_pid = 0;
 
   /* Need to flush the register cache (and the frame cache) from a
      previous debug session.  If inferior_ptid ends up the same as the
@@ -401,6 +412,25 @@ core_open (char *filename, int from_tty)
   bfd_map_over_sections (core_bfd, add_to_thread_list,
                         bfd_get_section_by_name (core_bfd, ".reg"));
 
+  if (ptid_equal (inferior_ptid, null_ptid))
+    {
+      /* Either we found no .reg/NN section, and hence we have a
+        non-threaded core (single-threaded, from gdb's perspective),
+        or for some reason add_to_thread_list couldn't determine
+        which was the "main" thread.  The latter case shouldn't
+        usually happen, but we're dealing with input here, which can
+        always be broken in different ways.  */
+      struct thread_info *thread = first_thread_of_process (-1);
+      if (thread == NULL)
+       {
+         add_inferior_silent (CORELOW_PID);
+         inferior_ptid = pid_to_ptid (CORELOW_PID);
+         add_thread_silent (inferior_ptid);
+       }
+      else
+       switch_to_thread (thread->ptid);
+    }
+
   post_create_inferior (&core_ops, from_tty);
 
   /* Now go through the target stack looking for threads since there
@@ -496,9 +526,13 @@ get_core_register_section (struct regcache *regcache,
       && gdbarch_core_reg_section_encodes_pid (core_gdbarch))
     {
       uint32_t merged_pid;
+      int pid = ptid_get_pid (inferior_ptid);
+
+      if (core_has_fake_pid)
+       pid = 0;
 
       merged_pid = ptid_get_lwp (inferior_ptid);
-      merged_pid = merged_pid << 16 | ptid_get_pid (inferior_ptid);
+      merged_pid = merged_pid << 16 | pid;
 
       section_name = xstrprintf ("%s/%s", name, plongest (merged_pid));
     }
@@ -592,6 +626,36 @@ core_files_info (struct target_ops *t)
   print_section_info (core_data, core_bfd);
 }
 \f
+struct spuid_list
+{
+  gdb_byte *buf;
+  ULONGEST offset;
+  LONGEST len;
+  ULONGEST pos;
+  ULONGEST written;
+};
+
+static void
+add_to_spuid_list (bfd *abfd, asection *asect, void *list_p)
+{
+  struct spuid_list *list = list_p;
+  enum bfd_endian byte_order
+    = bfd_big_endian (abfd)? BFD_ENDIAN_BIG : BFD_ENDIAN_LITTLE;
+  int fd, pos = 0;
+
+  sscanf (bfd_section_name (abfd, asect), "SPU/%d/regs%n", &fd, &pos);
+  if (pos == 0)
+    return;
+
+  if (list->pos >= list->offset && list->pos + 4 <= list->offset + list->len)
+    {
+      store_unsigned_integer (list->buf + list->pos - list->offset,
+                             4, byte_order, fd);
+      list->written += 4;
+    }
+  list->pos += 4;
+}
+
 static LONGEST
 core_xfer_partial (struct target_ops *ops, enum target_object object,
                   const char *annex, gdb_byte *readbuf,
@@ -682,6 +746,53 @@ core_xfer_partial (struct target_ops *ops, enum target_object object,
        }
       /* FALL THROUGH */
 
+    case TARGET_OBJECT_SPU:
+      if (readbuf && annex)
+       {
+         /* When the SPU contexts are stored in a core file, BFD
+            represents this with a fake section called "SPU/<annex>".  */
+
+         struct bfd_section *section;
+         bfd_size_type size;
+         char *contents;
+
+         char sectionstr[100];
+         xsnprintf (sectionstr, sizeof sectionstr, "SPU/%s", annex);
+
+         section = bfd_get_section_by_name (core_bfd, sectionstr);
+         if (section == NULL)
+           return -1;
+
+         size = bfd_section_size (core_bfd, section);
+         if (offset >= size)
+           return 0;
+         size -= offset;
+         if (size > len)
+           size = len;
+         if (size > 0
+             && !bfd_get_section_contents (core_bfd, section, readbuf,
+                                           (file_ptr) offset, size))
+           {
+             warning (_("Couldn't read SPU section in core file."));
+             return -1;
+           }
+
+         return size;
+       }
+      else if (readbuf)
+       {
+         /* NULL annex requests list of all present spuids.  */
+         struct spuid_list list;
+         list.buf = readbuf;
+         list.offset = offset;
+         list.len = len;
+         list.pos = 0;
+         list.written = 0;
+         bfd_map_over_sections (core_bfd, add_to_spuid_list, &list);
+         return list.written;
+       }
+      return -1;
+
     default:
       if (ops->beneath != NULL)
        return ops->beneath->to_xfer_partial (ops->beneath, object, annex,
@@ -695,7 +806,7 @@ core_xfer_partial (struct target_ops *ops, enum target_object object,
    `gdb internal error' (since generic_mourn calls breakpoint_init_inferior).  */
 
 static int
-ignore (struct bp_target_info *bp_tgt)
+ignore (struct gdbarch *gdbarch, struct bp_target_info *bp_tgt)
 {
   return 0;
 }
@@ -721,8 +832,8 @@ core_thread_alive (struct target_ops *ops, ptid_t ptid)
 static const struct target_desc *
 core_read_description (struct target_ops *target)
 {
-  if (gdbarch_core_read_description_p (current_gdbarch))
-    return gdbarch_core_read_description (current_gdbarch, target, core_bfd);
+  if (core_gdbarch && gdbarch_core_read_description_p (core_gdbarch))
+    return gdbarch_core_read_description (core_gdbarch, target, core_bfd);
 
   return NULL;
 }
@@ -748,6 +859,24 @@ core_pid_to_str (struct target_ops *ops, ptid_t ptid)
   return buf;
 }
 
+static int
+core_has_memory (struct target_ops *ops)
+{
+  return (core_bfd != NULL);
+}
+
+static int
+core_has_stack (struct target_ops *ops)
+{
+  return (core_bfd != NULL);
+}
+
+static int
+core_has_registers (struct target_ops *ops)
+{
+  return (core_bfd != NULL);
+}
+
 /* Fill in core_ops with its defined operations and properties.  */
 
 static void
@@ -771,9 +900,9 @@ init_core_ops (void)
   core_ops.to_read_description = core_read_description;
   core_ops.to_pid_to_str = core_pid_to_str;
   core_ops.to_stratum = core_stratum;
-  core_ops.to_has_memory = 1;
-  core_ops.to_has_stack = 1;
-  core_ops.to_has_registers = 1;
+  core_ops.to_has_memory = core_has_memory;
+  core_ops.to_has_stack = core_has_stack;
+  core_ops.to_has_registers = core_has_registers;
   core_ops.to_magic = OPS_MAGIC;
 }
 
This page took 0.029939 seconds and 4 git commands to generate.