Rename bfd_elf_get_arch_size to bfd_get_arch_size
[deliverable/binutils-gdb.git] / bfd / elf.c
index d957476d79baa0c7b9613eaccaeb2d7525643cc8..d22e57b6f8477d48324891394dca5fc8b9d4e646 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -1,5 +1,5 @@
 /* ELF executable support for BFD.
-   Copyright 1993, 94, 95, 96, 97, 98, 1999 Free Software Foundation, Inc.
+   Copyright 1993, 94, 95, 96, 97, 98, 99, 2000 Free Software Foundation, Inc.
 
 This file is part of BFD, the Binary File Descriptor library.
 
@@ -31,6 +31,10 @@ SECTION
        haven't bothered yet.
  */
 
+#ifdef __sparcv9
+#define _SYSCALL32     /* For Sparc64-cross-32 */
+#endif
+
 #include "bfd.h"
 #include "sysdep.h"
 #include "bfdlink.h"
@@ -761,6 +765,7 @@ bfd_elf_print_symbol (abfd, filep, symbol, how)
        CONST char *section_name;
        CONST char *name = NULL;
        struct elf_backend_data *bed;
+       unsigned char st_other;
        
        section_name = symbol->section ? symbol->section->name : "(*none*)";
 
@@ -836,10 +841,19 @@ bfd_elf_print_symbol (abfd, filep, symbol, how)
          }
 
        /* If the st_other field is not zero, print it.  */
-       if (((elf_symbol_type *) symbol)->internal_elf_sym.st_other != 0)
-         fprintf (file, " 0x%02x",
-                  ((unsigned int)
-                   ((elf_symbol_type *) symbol)->internal_elf_sym.st_other));
+       st_other = ((elf_symbol_type *) symbol)->internal_elf_sym.st_other;
+       
+       switch (st_other)
+         {
+         case 0: break;
+         case STV_INTERNAL:  fprintf (file, " .internal");  break;
+         case STV_HIDDEN:    fprintf (file, " .hidden");    break;
+         case STV_PROTECTED: fprintf (file, " .protected"); break;
+         default:
+           /* Some other non-defined flags are also present, so print
+              everything hex.  */
+           fprintf (file, " 0x%02x", (unsigned int) st_other);
+         }
 
        fprintf (file, " %s", name);
       }
@@ -896,6 +910,59 @@ _bfd_elf_link_hash_newfunc (entry, table, string)
   return (struct bfd_hash_entry *) ret;
 }
 
+/* Copy data from an indirect symbol to its direct symbol, hiding the
+   old indirect symbol.  */
+
+void
+_bfd_elf_link_hash_copy_indirect (dir, ind)
+     struct elf_link_hash_entry *dir, *ind;
+{
+  /* Copy down any references that we may have already seen to the
+     symbol which just became indirect.  */
+
+  dir->elf_link_hash_flags |=
+    (ind->elf_link_hash_flags
+     & (ELF_LINK_HASH_REF_DYNAMIC
+       | ELF_LINK_HASH_REF_REGULAR
+       | ELF_LINK_HASH_REF_REGULAR_NONWEAK
+       | ELF_LINK_NON_GOT_REF));
+
+  /* Copy over the global and procedure linkage table offset entries.
+     These may have been already set up by a check_relocs routine.  */
+  if (dir->got.offset == (bfd_vma) -1)
+    {
+      dir->got.offset = ind->got.offset;
+      ind->got.offset = (bfd_vma) -1;
+    }
+  BFD_ASSERT (ind->got.offset == (bfd_vma) -1);
+
+  if (dir->plt.offset == (bfd_vma) -1)
+    {
+      dir->plt.offset = ind->plt.offset;
+      ind->plt.offset = (bfd_vma) -1;
+    }
+  BFD_ASSERT (ind->plt.offset == (bfd_vma) -1);
+
+  if (dir->dynindx == -1)
+    {
+      dir->dynindx = ind->dynindx;
+      dir->dynstr_index = ind->dynstr_index;
+      ind->dynindx = -1;
+      ind->dynstr_index = 0;
+    }
+  BFD_ASSERT (ind->dynindx == -1);
+}
+
+void
+_bfd_elf_link_hash_hide_symbol(info, h)
+     struct bfd_link_info *info ATTRIBUTE_UNUSED;
+     struct elf_link_hash_entry *h;
+{
+  h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;
+  h->dynindx = -1;
+  h->plt.offset = (bfd_vma) -1;
+}
+
 /* Initialize an ELF linker hash table.  */
 
 boolean
@@ -915,6 +982,7 @@ _bfd_elf_link_hash_table_init (table, abfd, newfunc)
   table->needed = NULL;
   table->hgot = NULL;
   table->stab_info = NULL;
+  table->dynlocal = NULL;
   return _bfd_link_hash_table_init (&table->root, abfd, newfunc);
 }
 
@@ -1265,8 +1333,10 @@ bfd_section_from_shdr (abfd, shindex)
        /* If this reloc section does not use the main symbol table we
           don't treat it as a reloc section.  BFD can't adequately
           represent such a section, so at least for now, we don't
-          try.  We just present it as a normal section.  */
-       if (hdr->sh_link != elf_onesymtab (abfd))
+          try.  We just present it as a normal section.  We also 
+          can't use it as a reloc section if it points to the null
+          section. */
+       if (hdr->sh_link != elf_onesymtab (abfd) || hdr->sh_info == SHN_UNDEF)
          return _bfd_elf_make_section_from_shdr (abfd, hdr, name);
 
        if (! bfd_section_from_shdr (abfd, hdr->sh_info))
@@ -1292,8 +1362,9 @@ bfd_section_from_shdr (abfd, shindex)
        target_sect->rel_filepos = hdr->sh_offset;
        /* In the section to which the relocations apply, mark whether
           its relocations are of the REL or RELA variety.  */
-       elf_section_data (target_sect)->use_rela_p 
-         = (hdr->sh_type == SHT_RELA);
+       if (hdr->sh_size != 0)
+         elf_section_data (target_sect)->use_rela_p
+           = (hdr->sh_type == SHT_RELA);
        abfd->flags |= HAS_RELOC;
        return true;
       }
@@ -1702,7 +1773,6 @@ assign_section_numbers (abfd)
   asection *sec;
   unsigned int section_number;
   Elf_Internal_Shdr **i_shdrp;
-  struct elf_backend_data *bed = get_elf_backend_data (abfd);
 
   section_number = 1;
 
@@ -1837,7 +1907,7 @@ assign_section_numbers (abfd)
 
                  /* This is a .stab section.  */
                  elf_section_data (s)->this_hdr.sh_entsize =
-                   4 + 2 * (bed->s->arch_size / 8);
+                   4 + 2 * bfd_get_arch_size (abfd) / 8;
                }
            }
          break;
@@ -2839,18 +2909,21 @@ assign_file_positions_for_segments (abfd)
 
          if (p->p_type == PT_NOTE && bfd_get_format (abfd) == bfd_core)
            {
-             if (i == 0)       /* the actual "note" segment */
-               {               /* this one actually contains everything. */
+             /* The actual "note" segment has i == 0.
+                This is the one that actually contains everything.  */
+             if (i == 0)
+               {
                  sec->filepos = off;
                  p->p_filesz = sec->_raw_size;
                  off += sec->_raw_size;
                  voff = off;
                }
-             else      /* fake sections -- don't need to be written */
+             else
                {
+                 /* Fake sections -- don't need to be written.  */
                  sec->filepos = 0;
                  sec->_raw_size = 0;
-                 flags = sec->flags = 0;       /* no contents */
+                 flags = sec->flags = 0;
                }
              p->p_memsz = 0;
              p->p_align = 1;
@@ -3143,7 +3216,7 @@ prep_headers (abfd)
     bfd_big_endian (abfd) ? ELFDATA2MSB : ELFDATA2LSB;
   i_ehdrp->e_ident[EI_VERSION] = bed->s->ev_current;
 
-  i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_SYSV;
+  i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_NONE;
   i_ehdrp->e_ident[EI_ABIVERSION] = 0;
 
   for (count = EI_PAD; count < EI_NIDENT; count++)
@@ -3164,14 +3237,26 @@ prep_headers (abfd)
       i_ehdrp->e_machine = EM_NONE;
       break;
     case bfd_arch_sparc:
-      if (bed->s->arch_size == 64)
+      if (bfd_get_arch_size (abfd) == 64)
        i_ehdrp->e_machine = EM_SPARCV9;
       else
        i_ehdrp->e_machine = EM_SPARC;
       break;
+    case bfd_arch_i370:
+      i_ehdrp->e_machine = EM_S370;
+      break;
     case bfd_arch_i386:
       i_ehdrp->e_machine = EM_386;
       break;
+    case bfd_arch_ia64:
+      i_ehdrp->e_machine = EM_IA_64;
+      break;
+    case bfd_arch_m68hc11:
+      i_ehdrp->e_machine = EM_68HC11;
+      break;
+    case bfd_arch_m68hc12:
+      i_ehdrp->e_machine = EM_68HC12;
+      break;
     case bfd_arch_m68k:
       i_ehdrp->e_machine = EM_68K;
       break;
@@ -3211,6 +3296,9 @@ prep_headers (abfd)
     case bfd_arch_mcore:
       i_ehdrp->e_machine = EM_MCORE;
       break;
+    case bfd_arch_avr:
+      i_ehdrp->e_machine = EM_AVR;
+      break;
     case bfd_arch_v850:
       switch (bfd_get_mach (abfd))
        {
@@ -3658,7 +3746,7 @@ copy_private_bfd_data (ibfd, obfd)
         more to do.  */
 
       isec = 0;
-      matching_lma = false;
+      matching_lma = 0;
       suggested_lma = 0;
 
       for (j = 0, s = ibfd->sections; s != NULL; s = s->next)
@@ -3724,21 +3812,32 @@ copy_private_bfd_data (ibfd, obfd)
          free (sections);
          continue;
        }
-      else if (matching_lma != 0)
-       {
-         /* At least one section fits inside the current segment.
-            Keep it, but modify its physical address to match the
-            LMA of the first section that fitted.  */
-
-         m->p_paddr = matching_lma;
-       }
       else
        {
-         /* None of the sections fitted inside the current segment.
-            Change the current segment's physical address to match
-            the LMA of the first section.  */
+         if (matching_lma != 0)
+           {
+             /* At least one section fits inside the current segment.
+                Keep it, but modify its physical address to match the
+                LMA of the first section that fitted.  */
+
+             m->p_paddr = matching_lma;
+           }
+         else
+           {
+             /* None of the sections fitted inside the current segment.
+                Change the current segment's physical address to match
+                the LMA of the first section.  */
+
+             m->p_paddr = suggested_lma;
+           }
+
+         /* Offset the segment physical address from the lma to allow
+            for space taken up by elf headers.  */
+         if (m->includes_filehdr)
+           m->p_paddr -= iehdr->e_ehsize;
 
-         m->p_paddr = suggested_lma;
+         if (m->includes_phdrs)
+           m->p_paddr -= iehdr->e_phnum * iehdr->e_phentsize;
        }
 
       /* Step Three: Loop over the sections again, this time assigning
@@ -3771,7 +3870,12 @@ copy_private_bfd_data (ibfd, obfd)
                    {
                      /* If the first section in a segment does not start at
                         the beginning of the segment, then something is wrong.  */
-                     if (os->lma != m->p_paddr)
+                     if (os->lma != (m->p_paddr
+                                     + (m->includes_filehdr
+                                        ? iehdr->e_ehsize : 0)
+                                     + (m->includes_phdrs
+                                        ? iehdr->e_phnum * iehdr->e_phentsize
+                                        : 0)))
                        abort ();
                    }
                  else
@@ -4159,7 +4263,8 @@ swap_out_syms (abfd, sttp, relocatable_p)
          type = STT_NOTYPE;
 
         /* Processor-specific types */
-        if (bed->elf_backend_get_symbol_type)
+        if (type_ptr != NULL
+           && bed->elf_backend_get_symbol_type)
           type = (*bed->elf_backend_get_symbol_type) (&type_ptr->internal_elf_sym, type);
 
        if (flags & BSF_SECTION_SYM)
@@ -4401,18 +4506,13 @@ _bfd_elf_slurp_version_tables (abfd)
       Elf_Internal_Shdr *hdr;
       Elf_External_Verdef *everdef;
       Elf_Internal_Verdef *iverdef;
+      Elf_Internal_Verdef *iverdefarr;
+      Elf_Internal_Verdef iverdefmem;
       unsigned int i;
+      unsigned int maxidx;
 
       hdr = &elf_tdata (abfd)->dynverdef_hdr;
 
-      elf_tdata (abfd)->verdef =
-       ((Elf_Internal_Verdef *)
-        bfd_zalloc (abfd, hdr->sh_info * sizeof (Elf_Internal_Verdef)));
-      if (elf_tdata (abfd)->verdef == NULL)
-       goto error_return;
-
-      elf_tdata (abfd)->cverdefs = hdr->sh_info;
-
       contents = (bfd_byte *) bfd_malloc (hdr->sh_size);
       if (contents == NULL)
        goto error_return;
@@ -4420,15 +4520,42 @@ _bfd_elf_slurp_version_tables (abfd)
          || bfd_read ((PTR) contents, 1, hdr->sh_size, abfd) != hdr->sh_size)
        goto error_return;
 
+      /* We know the number of entries in the section but not the maximum
+        index.  Therefore we have to run through all entries and find
+        the maximum.  */
       everdef = (Elf_External_Verdef *) contents;
-      iverdef = elf_tdata (abfd)->verdef;
-      for (i = 0; i < hdr->sh_info; i++, iverdef++)
+      maxidx = 0;
+      for (i = 0; i < hdr->sh_info; ++i)
+       {
+         _bfd_elf_swap_verdef_in (abfd, everdef, &iverdefmem);
+
+         if ((iverdefmem.vd_ndx & VERSYM_VERSION) > maxidx)
+           maxidx = iverdefmem.vd_ndx & VERSYM_VERSION;
+
+         everdef = ((Elf_External_Verdef *)
+                    ((bfd_byte *) everdef + iverdefmem.vd_next));
+       }
+
+      elf_tdata (abfd)->verdef =
+       ((Elf_Internal_Verdef *)
+        bfd_zalloc (abfd, maxidx * sizeof (Elf_Internal_Verdef)));
+      if (elf_tdata (abfd)->verdef == NULL)
+       goto error_return;
+
+      elf_tdata (abfd)->cverdefs = maxidx;
+
+      everdef = (Elf_External_Verdef *) contents;
+      iverdefarr = elf_tdata (abfd)->verdef;
+      for (i = 0; i < hdr->sh_info; i++)
        {
          Elf_External_Verdaux *everdaux;
          Elf_Internal_Verdaux *iverdaux;
          unsigned int j;
 
-         _bfd_elf_swap_verdef_in (abfd, everdef, iverdef);
+         _bfd_elf_swap_verdef_in (abfd, everdef, &iverdefmem);
+
+         iverdef = &iverdefarr[(iverdefmem.vd_ndx & VERSYM_VERSION) - 1];
+         memcpy (iverdef, &iverdefmem, sizeof (Elf_Internal_Verdef));
 
          iverdef->vd_bfd = abfd;
 
@@ -4979,7 +5106,7 @@ elfcore_maybe_make_sect (abfd, name, sect)
 
 
 /* prstatus_t exists on:
-     solaris 2.[567]
+     solaris 2.5+
      linux 2.[01] + glibc
      unixware 4.2
 */
@@ -4990,28 +5117,60 @@ elfcore_grok_prstatus (abfd, note)
      bfd* abfd;
      Elf_Internal_Note* note;
 {
-  prstatus_t prstat;
   char buf[100];
   char* name;
   asection* sect;
+  int raw_size;
 
-  if (note->descsz != sizeof (prstat))
-    return true;
+  if (note->descsz == sizeof (prstatus_t))
+    {
+      prstatus_t prstat;
+
+      raw_size = sizeof (prstat.pr_reg);
+      memcpy (&prstat, note->descdata, sizeof (prstat));
+
+      elf_tdata (abfd)->core_signal = prstat.pr_cursig;
+      elf_tdata (abfd)->core_pid = prstat.pr_pid;
 
-  memcpy (&prstat, note->descdata, sizeof (prstat));
+      /* pr_who exists on:
+        solaris 2.5+
+        unixware 4.2
+        pr_who doesn't exist on:
+        linux 2.[01]
+        */
+#if defined (HAVE_PRSTATUS_T_PR_WHO)
+      elf_tdata (abfd)->core_lwpid = prstat.pr_who;
+#endif
+    }
+#if defined (__sparcv9)
+  else if (note->descsz == sizeof (prstatus32_t))
+    {
+      /* 64-bit host, 32-bit corefile */
+      prstatus32_t prstat;
+
+      raw_size = sizeof (prstat.pr_reg);
+      memcpy (&prstat, note->descdata, sizeof (prstat));
 
-  elf_tdata (abfd)->core_signal = prstat.pr_cursig;
-  elf_tdata (abfd)->core_pid = prstat.pr_pid;
+      elf_tdata (abfd)->core_signal = prstat.pr_cursig;
+      elf_tdata (abfd)->core_pid = prstat.pr_pid;
 
-  /* pr_who exists on:
-       solaris 2.[567]
-       unixware 4.2
-     pr_who doesn't exist on:
-       linux 2.[01]
-  */
+      /* pr_who exists on:
+        solaris 2.5+
+        unixware 4.2
+        pr_who doesn't exist on:
+        linux 2.[01]
+        */
 #if defined (HAVE_PRSTATUS_T_PR_WHO)
-  elf_tdata (abfd)->core_lwpid = prstat.pr_who;
+      elf_tdata (abfd)->core_lwpid = prstat.pr_who;
 #endif
+    }
+#endif /* __sparcv9 */
+  else
+    {
+      /* Fail - we don't know how to handle any other
+        note size (ie. data object type).  */
+      return true;
+    }
 
   /* Make a ".reg/999" section. */
 
@@ -5024,8 +5183,20 @@ elfcore_grok_prstatus (abfd, note)
   sect = bfd_make_section (abfd, name);
   if (sect == NULL)
     return false;
-  sect->_raw_size = sizeof (prstat.pr_reg);
-  sect->filepos = note->descpos + offsetof (prstatus_t, pr_reg);
+
+  if (note->descsz == sizeof (prstatus_t))
+    {
+      sect->_raw_size = raw_size;
+      sect->filepos = note->descpos + offsetof (prstatus_t, pr_reg);
+    }
+#if defined (__sparcv9)
+  else if (note->descsz == sizeof (prstatus32_t))
+    {
+      sect->_raw_size = raw_size;
+      sect->filepos = note->descpos + offsetof (prstatus32_t, pr_reg);
+    }
+#endif
+
   sect->flags = SEC_HAS_CONTENTS;
   sect->alignment_power = 2;
 
@@ -5037,28 +5208,33 @@ elfcore_grok_prstatus (abfd, note)
 #endif /* defined (HAVE_PRSTATUS_T) */
 
 
-/* There isn't a consistent prfpregset_t across platforms,
-   but it doesn't matter, because we don't have to pick this
-   data structure apart. */
+/* 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.  */
 
 static boolean
-elfcore_grok_prfpreg (abfd, note)
+elfcore_make_note_pseudosection (abfd, name, note)
      bfd* abfd;
+     char *name;
      Elf_Internal_Note* note;
 {
   char buf[100];
-  charname;
+  char *threaded_name;
   asection* sect;
 
-  /* Make a ".reg2/999" section. */
+  /* Build the section name.  */
 
-  sprintf (buf, ".reg2/%d", elfcore_make_pid (abfd));
-  name = bfd_alloc (abfd, strlen (buf) + 1);
-  if (name == NULL)
+  sprintf (buf, "%s/%d", name, elfcore_make_pid (abfd));
+  threaded_name = bfd_alloc (abfd, strlen (buf) + 1);
+  if (threaded_name == NULL)
     return false;
-  strcpy (name, buf);
+  strcpy (threaded_name, buf);
 
-  sect = bfd_make_section (abfd, name);
+  sect = bfd_make_section (abfd, threaded_name);
   if (sect == NULL)
     return false;
   sect->_raw_size = note->descsz;
@@ -5066,18 +5242,49 @@ elfcore_grok_prfpreg (abfd, note)
   sect->flags = SEC_HAS_CONTENTS;
   sect->alignment_power = 2;
 
-  if (! elfcore_maybe_make_sect (abfd, ".reg2", sect))
+  if (! elfcore_maybe_make_sect (abfd, name, sect))
     return false;
 
   return true;
 }
 
+
+/* There isn't a consistent prfpregset_t across platforms,
+   but it doesn't matter, because we don't have to pick this
+   data structure apart. */
+static boolean
+elfcore_grok_prfpreg (abfd, note)
+     bfd* abfd;
+     Elf_Internal_Note* note;
+{
+  return elfcore_make_note_pseudosection (abfd, ".reg2", note);
+}
+
+
+/* Linux dumps the Intel SSE regs in a note named "LINUX" with a note
+   type of 5 (NT_PRXFPREG).  Just include the whole note's contents
+   literally.  */
+static boolean
+elfcore_grok_prxfpreg (abfd, note)
+     bfd* abfd;
+     Elf_Internal_Note* note;
+{
+  return elfcore_make_note_pseudosection (abfd, ".reg-xfp", note);
+}
+
+
 #if defined (HAVE_PRPSINFO_T)
-# define elfcore_psinfo_t prpsinfo_t
+typedef prpsinfo_t   elfcore_psinfo_t;
+#if defined (__sparcv9)        /* Sparc64 cross Sparc32 */
+typedef prpsinfo32_t elfcore_psinfo32_t;
+#endif
 #endif
 
 #if defined (HAVE_PSINFO_T)
-# define elfcore_psinfo_t psinfo_t
+typedef psinfo_t   elfcore_psinfo_t;
+#if defined (__sparcv9)        /* Sparc64 cross Sparc32 */
+typedef psinfo32_t elfcore_psinfo32_t;
+#endif
 #endif
 
 
@@ -5117,18 +5324,40 @@ elfcore_grok_psinfo (abfd, note)
      bfd* abfd;
      Elf_Internal_Note* note;
 {
-  elfcore_psinfo_t psinfo;
+  if (note->descsz == sizeof (elfcore_psinfo_t))
+    {
+      elfcore_psinfo_t psinfo;
 
-  if (note->descsz != sizeof (elfcore_psinfo_t))
-    return true;
+      memcpy (&psinfo, note->descdata, note->descsz);
+
+      elf_tdata (abfd)->core_program
+       = 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));
+    }
+#if defined (__sparcv9)
+  else if (note->descsz == sizeof (elfcore_psinfo32_t))
+    {
+      /* 64-bit host, 32-bit corefile */
+      elfcore_psinfo32_t psinfo;
+
+      memcpy (&psinfo, note->descdata, note->descsz);
 
-  memcpy (&psinfo, note->descdata, note->descsz);
+      elf_tdata (abfd)->core_program
+       = elfcore_strndup (abfd, psinfo.pr_fname, sizeof (psinfo.pr_fname));
 
-  elf_tdata (abfd)->core_program
-    = 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));
+    }
+#endif
 
-  elf_tdata (abfd)->core_command
-    = elfcore_strndup (abfd, psinfo.pr_psargs, sizeof (psinfo.pr_psargs));
+  else
+    {
+      /* Fail - we don't know how to handle any other
+        note size (ie. data object type).  */
+      return true;
+    }
 
   /* Note that for some reason, a spurious space is tacked
      onto the end of the args in some (at least one anyway)
@@ -5153,15 +5382,25 @@ elfcore_grok_pstatus (abfd, note)
      bfd* abfd;
      Elf_Internal_Note* note;
 {
-  pstatus_t pstat;
+  if (note->descsz == sizeof (pstatus_t))
+    {
+      pstatus_t pstat;
 
-  if (note->descsz != sizeof (pstat))
-    return true;
+      memcpy (&pstat, note->descdata, sizeof (pstat));
 
-  memcpy (&pstat, note->descdata, sizeof (pstat));
+      elf_tdata (abfd)->core_pid = pstat.pr_pid;
+    }
+#if defined (__sparcv9)
+  else if (note->descsz == sizeof (pstatus32_t))
+    {
+      /* 64-bit host, 32-bit corefile */
+      pstatus32_t pstat;
 
-  elf_tdata (abfd)->core_pid = pstat.pr_pid;
+      memcpy (&pstat, note->descdata, sizeof (pstat));
 
+      elf_tdata (abfd)->core_pid = pstat.pr_pid;
+    }
+#endif
   /* Could grab some more details from the "representative"
      lwpstatus_t in pstat.pr_lwp, but we'll catch it all in an
      NT_LWPSTATUS note, presumably. */
@@ -5252,7 +5491,83 @@ elfcore_grok_lwpstatus (abfd, note)
 }
 #endif /* defined (HAVE_LWPSTATUS_T) */
 
+#if defined (HAVE_WIN32_PSTATUS_T)
+static boolean
+elfcore_grok_win32pstatus (abfd, note)
+     bfd * abfd;
+     Elf_Internal_Note * note;
+{
+  char buf[30];
+  char * name;
+  asection * sect;
+  win32_pstatus_t pstatus;
+
+  if (note->descsz < sizeof (pstatus))
+    return true;
 
+  memcpy (& pstatus, note->descdata, note->descsz);
+  
+  switch (pstatus.data_type) 
+    {
+    case NOTE_INFO_PROCESS:
+      /* FIXME: need to add ->core_command.  */
+      elf_tdata (abfd)->core_signal = pstatus.data.process_info.signal;
+      elf_tdata (abfd)->core_pid = pstatus.data.process_info.pid;
+      break ;
+
+    case NOTE_INFO_THREAD:
+      /* Make a ".reg/999" section.  */
+      sprintf (buf, ".reg/%d", pstatus.data.thread_info.tid);
+      
+      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 = sizeof (pstatus.data.thread_info.thread_context);
+      sect->filepos = note->descpos + offsetof (struct win32_pstatus,
+                                               data.thread_info.thread_context);
+      sect->flags = SEC_HAS_CONTENTS;
+      sect->alignment_power = 2;
+
+      if (pstatus.data.thread_info.is_active_thread)
+       if (! elfcore_maybe_make_sect (abfd, ".reg", sect))
+         return false;
+      break;
+
+    case NOTE_INFO_MODULE:
+      /* Make a ".module/xxxxxxxx" section.  */
+      sprintf (buf, ".module/%08x" , pstatus.data.module_info.base_address);
+      
+      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 = note->descsz;
+      sect->filepos = note->descpos;
+      sect->flags = SEC_HAS_CONTENTS;
+      sect->alignment_power = 2;
+      break;
+
+    default:
+      return true;
+    }
+
+  return true;
+}
+#endif /* HAVE_WIN32_PSTATUS_T */
 
 static boolean
 elfcore_grok_note (abfd, note)
@@ -5282,6 +5597,18 @@ elfcore_grok_note (abfd, note)
     case NT_FPREGSET:          /* FIXME: rename to NT_PRFPREG */
       return elfcore_grok_prfpreg (abfd, note);
 
+#if defined (HAVE_WIN32_PSTATUS_T)
+    case NT_WIN32PSTATUS:      
+      return elfcore_grok_win32pstatus (abfd, note);
+#endif
+
+  case NT_PRXFPREG:            /* Linux SSE extension */
+      if (note->namesz == 5
+         && ! strcmp (note->namedata, "LINUX"))
+       return elfcore_grok_prxfpreg (abfd, note);
+      else
+       return true;
+
 #if defined (HAVE_PRPSINFO_T) || defined (HAVE_PSINFO_T)
     case NT_PRPSINFO:
     case NT_PSINFO:
@@ -5359,3 +5686,51 @@ _bfd_elfcore_section_from_phdr (abfd, phdr, sec_num)
   return true;
 }
 
+
+\f
+/* Providing external access to the ELF program header table.  */
+
+/* Return an upper bound on the number of bytes required to store a
+   copy of ABFD's program header table entries.  Return -1 if an error
+   occurs; bfd_get_error will return an appropriate code.  */
+long
+bfd_get_elf_phdr_upper_bound (abfd)
+     bfd *abfd;
+{
+  if (abfd->xvec->flavour != bfd_target_elf_flavour)
+    {
+      bfd_set_error (bfd_error_wrong_format);
+      return -1;
+    }
+
+  return (elf_elfheader (abfd)->e_phnum
+         * sizeof (Elf_Internal_Phdr));
+}
+
+
+/* Copy ABFD's program header table entries to *PHDRS.  The entries
+   will be stored as an array of Elf_Internal_Phdr structures, as
+   defined in include/elf/internal.h.  To find out how large the
+   buffer needs to be, call bfd_get_elf_phdr_upper_bound.
+
+   Return the number of program header table entries read, or -1 if an
+   error occurs; bfd_get_error will return an appropriate code.  */
+int
+bfd_get_elf_phdrs (abfd, phdrs)
+     bfd *abfd;
+     void *phdrs;
+{
+  int num_phdrs;
+
+  if (abfd->xvec->flavour != bfd_target_elf_flavour)
+    {
+      bfd_set_error (bfd_error_wrong_format);
+      return -1;
+    }
+
+  num_phdrs = elf_elfheader (abfd)->e_phnum;
+  memcpy (phdrs, elf_tdata (abfd)->phdr, 
+         num_phdrs * sizeof (Elf_Internal_Phdr));
+
+  return num_phdrs;
+}
This page took 0.033706 seconds and 4 git commands to generate.