* libxcoff.h (struct xcoff_backend_data_rec): Constify src param
[binutils-gdb.git] / bfd / elf.c
index 191627c4aed00b9a1dfe53331922cd2016c51f0d..b06417c5e1dfe46733c800644b1bb5e2923ee20d 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -57,10 +57,16 @@ static INLINE int sym_is_global PARAMS ((bfd *, asymbol *));
 static boolean elf_map_symbols PARAMS ((bfd *));
 static bfd_size_type get_program_header_size PARAMS ((bfd *));
 static boolean elfcore_read_notes PARAMS ((bfd *, bfd_vma, bfd_vma));
-static boolean elf_find_function PARAMS ((bfd *, asection *,
-                                         asymbol **,
-                                         bfd_vma, const char **,
-                                         const char **));
+static boolean elf_find_function PARAMS ((bfd *, asection *, asymbol **,
+                                         bfd_vma, const char **,
+                                         const char **));
+static int elfcore_make_pid PARAMS ((bfd *));
+static boolean elfcore_maybe_make_sect PARAMS ((bfd *, char *, asection *));
+static boolean elfcore_make_note_pseudosection PARAMS ((bfd *, char *,
+                                                       Elf_Internal_Note *));
+static boolean elfcore_grok_prfpreg PARAMS ((bfd *, Elf_Internal_Note *));
+static boolean elfcore_grok_prxfpreg PARAMS ((bfd *, Elf_Internal_Note *));
+static boolean elfcore_grok_note PARAMS ((bfd *, Elf_Internal_Note *));
 
 /* Swap version information in and out.  The version information is
    currently size independent.  If that ever changes, this code will
@@ -2677,18 +2683,22 @@ elf_sort_sections (arg1, arg2)
   if (TOEND (sec1))
     {
       if (TOEND (sec2))
-       return sec1->target_index - sec2->target_index;
+       {
+         /* If the indicies are the same, do not return 0
+            here, but continue to try the next comparison.  */
+         if (sec1->target_index - sec2->target_index != 0)
+           return sec1->target_index - sec2->target_index;
+       }
       else
        return 1;
     }
-
-  if (TOEND (sec2))
+  else if (TOEND (sec2))
     return -1;
 
 #undef TOEND
 
-  /* Sort by size, to put zero sized sections before others at the
-     same address.  */
+  /* Sort by size, to put zero sized sections
+     before others at the same address.  */
 
   if (sec1->_raw_size < sec2->_raw_size)
     return -1;
@@ -5376,6 +5386,43 @@ elfcore_maybe_make_sect (abfd, name, sect)
   return true;
 }
 
+/* Create a pseudosection containing SIZE bytes at FILEPOS.  This
+   actually creates up to two pseudosections:
+   - For the single-threaded case, a section named NAME, unless
+     such a section already exists.
+   - For the multi-threaded case, a section named "NAME/PID", where
+     PID is elfcore_make_pid (abfd).
+   Both pseudosections have identical contents. */
+boolean
+_bfd_elfcore_make_pseudosection (abfd, name, size, filepos)
+     bfd *abfd;
+     char *name;
+     int size;
+     int filepos;
+{
+  char buf[100];
+  char *threaded_name;
+  asection *sect;
+
+  /* Build the section name.  */
+
+  sprintf (buf, "%s/%d", name, elfcore_make_pid (abfd));
+  threaded_name = bfd_alloc (abfd, strlen (buf) + 1);
+  if (threaded_name == NULL)
+    return false;
+  strcpy (threaded_name, buf);
+
+  sect = bfd_make_section (abfd, threaded_name);
+  if (sect == NULL)
+    return false;
+  sect->_raw_size = size;
+  sect->filepos = filepos;
+  sect->flags = SEC_HAS_CONTENTS;
+  sect->alignment_power = 2;
+
+  return elfcore_maybe_make_sect (abfd, name, sect);
+}
+
 /* prstatus_t exists on:
      solaris 2.5+
      linux 2.[01] + glibc
@@ -5383,14 +5430,13 @@ elfcore_maybe_make_sect (abfd, name, sect)
 */
 
 #if defined (HAVE_PRSTATUS_T)
+static boolean elfcore_grok_prstatus PARAMS ((bfd *, Elf_Internal_Note *));
+
 static boolean
 elfcore_grok_prstatus (abfd, note)
      bfd *abfd;
      Elf_Internal_Note *note;
 {
-  char buf[100];
-  char *name;
-  asection *sect;
   int raw_size;
   int offset;
 
@@ -5446,69 +5492,21 @@ elfcore_grok_prstatus (abfd, note)
       return true;
     }
 
-  /* Make a ".reg/999" section.  */
-
-  sprintf (buf, ".reg/%d", elfcore_make_pid (abfd));
-  name = bfd_alloc (abfd, strlen (buf) + 1);
-  if (name == NULL)
-    return false;
-  strcpy (name, buf);
-
-  sect = bfd_make_section (abfd, name);
-  if (sect == NULL)
-    return false;
-
-  sect->_raw_size = raw_size;
-  sect->filepos = note->descpos + offset;
-
-  sect->flags = SEC_HAS_CONTENTS;
-  sect->alignment_power = 2;
-
-  if (! elfcore_maybe_make_sect (abfd, ".reg", sect))
-    return false;
-
-  return true;
+  /* Make a ".reg/999" section and a ".reg" section.  */
+  return _bfd_elfcore_make_pseudosection (abfd, ".reg",
+                                         raw_size, note->descpos + offset);
 }
 #endif /* defined (HAVE_PRSTATUS_T) */
 
-/* Create a pseudosection containing the exact contents of NOTE.  This
-   actually creates up to two pseudosections:
-   - For the single-threaded case, a section named NAME, unless
-     such a section already exists.
-   - For the multi-threaded case, a section named "NAME/PID", where
-     PID is elfcore_make_pid (abfd).
-   Both pseudosections have identical contents: the contents of NOTE.  */
-
+/* Create a pseudosection containing the exact contents of NOTE.  */
 static boolean
 elfcore_make_note_pseudosection (abfd, name, note)
      bfd *abfd;
      char *name;
      Elf_Internal_Note *note;
 {
-  char buf[100];
-  char *threaded_name;
-  asection *sect;
-
-  /* Build the section name.  */
-
-  sprintf (buf, "%s/%d", name, elfcore_make_pid (abfd));
-  threaded_name = bfd_alloc (abfd, strlen (buf) + 1);
-  if (threaded_name == NULL)
-    return false;
-  strcpy (threaded_name, buf);
-
-  sect = bfd_make_section (abfd, threaded_name);
-  if (sect == NULL)
-    return false;
-  sect->_raw_size = note->descsz;
-  sect->filepos = note->descpos;
-  sect->flags = SEC_HAS_CONTENTS;
-  sect->alignment_power = 2;
-
-  if (! elfcore_maybe_make_sect (abfd, name, sect))
-    return false;
-
-  return true;
+  return _bfd_elfcore_make_pseudosection (abfd, name,
+                                         note->descsz, note->descpos);
 }
 
 /* There isn't a consistent prfpregset_t across platforms,
@@ -5549,14 +5547,12 @@ typedef psinfo32_t elfcore_psinfo32_t;
 #endif
 #endif
 
-#if defined (HAVE_PRPSINFO_T) || defined (HAVE_PSINFO_T)
-
 /* return a malloc'ed copy of a string at START which is at
    most MAX bytes long, possibly without a terminating '\0'.
    the copy will always have a terminating '\0'.  */
 
-static char*
-elfcore_strndup (abfd, start, max)
+char *
+_bfd_elfcore_strndup (abfd, start, max)
      bfd *abfd;
      char *start;
      int max;
@@ -5580,6 +5576,9 @@ elfcore_strndup (abfd, start, max)
   return dup;
 }
 
+#if defined (HAVE_PRPSINFO_T) || defined (HAVE_PSINFO_T)
+static boolean elfcore_grok_psinfo PARAMS ((bfd *, Elf_Internal_Note *));
+
 static boolean
 elfcore_grok_psinfo (abfd, note)
      bfd *abfd;
@@ -5592,10 +5591,12 @@ elfcore_grok_psinfo (abfd, note)
       memcpy (&psinfo, note->descdata, sizeof (psinfo));
 
       elf_tdata (abfd)->core_program
-       = elfcore_strndup (abfd, psinfo.pr_fname, sizeof (psinfo.pr_fname));
+       = _bfd_elfcore_strndup (abfd, psinfo.pr_fname,
+                               sizeof (psinfo.pr_fname));
 
       elf_tdata (abfd)->core_command
-       = elfcore_strndup (abfd, psinfo.pr_psargs, sizeof (psinfo.pr_psargs));
+       = _bfd_elfcore_strndup (abfd, psinfo.pr_psargs,
+                               sizeof (psinfo.pr_psargs));
     }
 #if defined (HAVE_PRPSINFO32_T) || defined (HAVE_PSINFO32_T)
   else if (note->descsz == sizeof (elfcore_psinfo32_t))
@@ -5606,10 +5607,12 @@ elfcore_grok_psinfo (abfd, note)
       memcpy (&psinfo, note->descdata, sizeof (psinfo));
 
       elf_tdata (abfd)->core_program
-       = elfcore_strndup (abfd, psinfo.pr_fname, sizeof (psinfo.pr_fname));
+       = _bfd_elfcore_strndup (abfd, psinfo.pr_fname,
+                               sizeof (psinfo.pr_fname));
 
       elf_tdata (abfd)->core_command
-       = elfcore_strndup (abfd, psinfo.pr_psargs, sizeof (psinfo.pr_psargs));
+       = _bfd_elfcore_strndup (abfd, psinfo.pr_psargs,
+                               sizeof (psinfo.pr_psargs));
     }
 #endif
 
@@ -5751,10 +5754,7 @@ elfcore_grok_lwpstatus (abfd, note)
   sect->flags = SEC_HAS_CONTENTS;
   sect->alignment_power = 2;
 
-  if (!elfcore_maybe_make_sect (abfd, ".reg2", sect))
-    return false;
-
-  return true;
+  return elfcore_maybe_make_sect (abfd, ".reg2", sect);
 }
 #endif /* defined (HAVE_LWPSTATUS_T) */
 
@@ -5841,14 +5841,21 @@ elfcore_grok_note (abfd, note)
      bfd *abfd;
      Elf_Internal_Note *note;
 {
+  struct elf_backend_data *bed = get_elf_backend_data (abfd);
+
   switch (note->type)
     {
     default:
       return true;
 
-#if defined (HAVE_PRSTATUS_T)
     case NT_PRSTATUS:
+      if (bed->elf_backend_grok_prstatus)
+       if ((*bed->elf_backend_grok_prstatus) (abfd, note))
+         return true;
+#if defined (HAVE_PRSTATUS_T)
       return elfcore_grok_prstatus (abfd, note);
+#else
+      return true;
 #endif
 
 #if defined (HAVE_PSTATUS_T)
@@ -5876,10 +5883,15 @@ elfcore_grok_note (abfd, note)
       else
        return true;
 
-#if defined (HAVE_PRPSINFO_T) || defined (HAVE_PSINFO_T)
     case NT_PRPSINFO:
     case NT_PSINFO:
+      if (bed->elf_backend_grok_psinfo)
+       if ((*bed->elf_backend_grok_psinfo) (abfd, note))
+         return true;
+#if defined (HAVE_PRPSINFO_T) || defined (HAVE_PSINFO_T)
       return elfcore_grok_psinfo (abfd, note);
+#else
+      return true;
 #endif
     }
 }
@@ -5935,21 +5947,6 @@ elfcore_read_notes (abfd, offset, size)
   free (buf);
   return true;
 }
-
-/* FIXME: This function is now unnecessary.  Callers can just call
-   bfd_section_from_phdr directly.  */
-
-boolean
-_bfd_elfcore_section_from_phdr (abfd, phdr, sec_num)
-     bfd *abfd;
-     Elf_Internal_Phdr* phdr;
-     int sec_num;
-{
-  if (! bfd_section_from_phdr (abfd, phdr, sec_num))
-    return false;
-
-  return true;
-}
 \f
 /* Providing external access to the ELF program header table.  */
 
@@ -5967,8 +5964,7 @@ bfd_get_elf_phdr_upper_bound (abfd)
       return -1;
     }
 
-  return (elf_elfheader (abfd)->e_phnum
-         * sizeof (Elf_Internal_Phdr));
+  return elf_elfheader (abfd)->e_phnum * sizeof (Elf_Internal_Phdr);
 }
 
 /* Copy ABFD's program header table entries to *PHDRS.  The entries
@@ -5998,3 +5994,62 @@ bfd_get_elf_phdrs (abfd, phdrs)
 
   return num_phdrs;
 }
+
+void
+bfd_elf_sprintf_vma (abfd, buf, value)
+     bfd *abfd;
+     char *buf;
+     bfd_vma value;
+{
+#ifdef BFD64
+  Elf_Internal_Ehdr *i_ehdrp;  /* Elf file header, internal form */
+
+  i_ehdrp = elf_elfheader (abfd);
+  if (i_ehdrp == NULL)
+    sprintf_vma (buf, value);
+  else
+    {
+      if (i_ehdrp->e_ident[EI_CLASS] == ELFCLASS64)
+#if BFD_HOST_64BIT_LONG
+       sprintf (buf, "%016lx", value);
+#else
+       sprintf (buf, "%08lx%08lx", _bfd_int64_high (value),
+                _bfd_int64_low (value));
+#endif
+      else
+       sprintf (buf, "%08lx", (unsigned long) (value & 0xffffffff));
+    }
+#else
+  sprintf_vma (buf, value);
+#endif
+}
+
+void
+bfd_elf_fprintf_vma (abfd, stream, value)
+     bfd *abfd;
+     PTR stream;
+     bfd_vma value;
+{
+#ifdef BFD64
+  Elf_Internal_Ehdr *i_ehdrp;  /* Elf file header, internal form */
+
+  i_ehdrp = elf_elfheader (abfd);
+  if (i_ehdrp == NULL)
+    fprintf_vma ((FILE *) stream, value);
+  else
+    {
+      if (i_ehdrp->e_ident[EI_CLASS] == ELFCLASS64)
+#if BFD_HOST_64BIT_LONG
+       fprintf ((FILE *) stream, "%016lx", value);
+#else
+       fprintf ((FILE *) stream, "%08lx%08lx",
+                _bfd_int64_high (value), _bfd_int64_low (value));
+#endif
+      else
+       fprintf ((FILE *) stream, "%08lx",
+                (unsigned long) (value & 0xffffffff));
+    }
+#else
+  fprintf_vma ((FILE *) stream, value);
+#endif
+}