For bfd, add vr5400 and vr5000 mips machine variants to list of machines.
[deliverable/binutils-gdb.git] / bfd / elf.c
index dd5527f1e9f2a2103e8413b2a8a265cf37278411..88bdaf9ed9660b0e0220f81c1646518610856541 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -1,5 +1,5 @@
 /* ELF executable support for BFD.
-   Copyright 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
+   Copyright 1993, 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
 
 This file is part of BFD, the Binary File Descriptor library.
 
@@ -47,6 +47,156 @@ static boolean assign_file_positions_except_relocs PARAMS ((bfd *));
 static boolean prep_headers PARAMS ((bfd *));
 static boolean swap_out_syms PARAMS ((bfd *, struct bfd_strtab_hash **));
 static boolean copy_private_bfd_data PARAMS ((bfd *, bfd *));
+static char *elf_read PARAMS ((bfd *, long, unsigned int));
+static void elf_fake_sections PARAMS ((bfd *, asection *, PTR));
+static boolean assign_section_numbers PARAMS ((bfd *));
+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 *));
+
+/* Swap version information in and out.  The version information is
+   currently size independent.  If that ever changes, this code will
+   need to move into elfcode.h.  */
+
+/* Swap in a Verdef structure.  */
+
+void
+_bfd_elf_swap_verdef_in (abfd, src, dst)
+     bfd *abfd;
+     const Elf_External_Verdef *src;
+     Elf_Internal_Verdef *dst;
+{
+  dst->vd_version = bfd_h_get_16 (abfd, src->vd_version);
+  dst->vd_flags   = bfd_h_get_16 (abfd, src->vd_flags);
+  dst->vd_ndx     = bfd_h_get_16 (abfd, src->vd_ndx);
+  dst->vd_cnt     = bfd_h_get_16 (abfd, src->vd_cnt);
+  dst->vd_hash    = bfd_h_get_32 (abfd, src->vd_hash);
+  dst->vd_aux     = bfd_h_get_32 (abfd, src->vd_aux);
+  dst->vd_next    = bfd_h_get_32 (abfd, src->vd_next);
+}
+
+/* Swap out a Verdef structure.  */
+
+void
+_bfd_elf_swap_verdef_out (abfd, src, dst)
+     bfd *abfd;
+     const Elf_Internal_Verdef *src;
+     Elf_External_Verdef *dst;
+{
+  bfd_h_put_16 (abfd, src->vd_version, dst->vd_version);
+  bfd_h_put_16 (abfd, src->vd_flags, dst->vd_flags);
+  bfd_h_put_16 (abfd, src->vd_ndx, dst->vd_ndx);
+  bfd_h_put_16 (abfd, src->vd_cnt, dst->vd_cnt);
+  bfd_h_put_32 (abfd, src->vd_hash, dst->vd_hash);
+  bfd_h_put_32 (abfd, src->vd_aux, dst->vd_aux);
+  bfd_h_put_32 (abfd, src->vd_next, dst->vd_next);
+}
+
+/* Swap in a Verdaux structure.  */
+
+void
+_bfd_elf_swap_verdaux_in (abfd, src, dst)
+     bfd *abfd;
+     const Elf_External_Verdaux *src;
+     Elf_Internal_Verdaux *dst;
+{
+  dst->vda_name = bfd_h_get_32 (abfd, src->vda_name);
+  dst->vda_next = bfd_h_get_32 (abfd, src->vda_next);
+}
+
+/* Swap out a Verdaux structure.  */
+
+void
+_bfd_elf_swap_verdaux_out (abfd, src, dst)
+     bfd *abfd;
+     const Elf_Internal_Verdaux *src;
+     Elf_External_Verdaux *dst;
+{
+  bfd_h_put_32 (abfd, src->vda_name, dst->vda_name);
+  bfd_h_put_32 (abfd, src->vda_next, dst->vda_next);
+}
+
+/* Swap in a Verneed structure.  */
+
+void
+_bfd_elf_swap_verneed_in (abfd, src, dst)
+     bfd *abfd;
+     const Elf_External_Verneed *src;
+     Elf_Internal_Verneed *dst;
+{
+  dst->vn_version = bfd_h_get_16 (abfd, src->vn_version);
+  dst->vn_cnt     = bfd_h_get_16 (abfd, src->vn_cnt);
+  dst->vn_file    = bfd_h_get_32 (abfd, src->vn_file);
+  dst->vn_aux     = bfd_h_get_32 (abfd, src->vn_aux);
+  dst->vn_next    = bfd_h_get_32 (abfd, src->vn_next);
+}
+
+/* Swap out a Verneed structure.  */
+
+void
+_bfd_elf_swap_verneed_out (abfd, src, dst)
+     bfd *abfd;
+     const Elf_Internal_Verneed *src;
+     Elf_External_Verneed *dst;
+{
+  bfd_h_put_16 (abfd, src->vn_version, dst->vn_version);
+  bfd_h_put_16 (abfd, src->vn_cnt, dst->vn_cnt);
+  bfd_h_put_32 (abfd, src->vn_file, dst->vn_file);
+  bfd_h_put_32 (abfd, src->vn_aux, dst->vn_aux);
+  bfd_h_put_32 (abfd, src->vn_next, dst->vn_next);
+}
+
+/* Swap in a Vernaux structure.  */
+
+void
+_bfd_elf_swap_vernaux_in (abfd, src, dst)
+     bfd *abfd;
+     const Elf_External_Vernaux *src;
+     Elf_Internal_Vernaux *dst;
+{
+  dst->vna_hash  = bfd_h_get_32 (abfd, src->vna_hash);
+  dst->vna_flags = bfd_h_get_16 (abfd, src->vna_flags);
+  dst->vna_other = bfd_h_get_16 (abfd, src->vna_other);
+  dst->vna_name  = bfd_h_get_32 (abfd, src->vna_name);
+  dst->vna_next  = bfd_h_get_32 (abfd, src->vna_next);
+}
+
+/* Swap out a Vernaux structure.  */
+
+void
+_bfd_elf_swap_vernaux_out (abfd, src, dst)
+     bfd *abfd;
+     const Elf_Internal_Vernaux *src;
+     Elf_External_Vernaux *dst;
+{
+  bfd_h_put_32 (abfd, src->vna_hash, dst->vna_hash);
+  bfd_h_put_16 (abfd, src->vna_flags, dst->vna_flags);
+  bfd_h_put_16 (abfd, src->vna_other, dst->vna_other);
+  bfd_h_put_32 (abfd, src->vna_name, dst->vna_name);
+  bfd_h_put_32 (abfd, src->vna_next, dst->vna_next);
+}
+
+/* Swap in a Versym structure.  */
+
+void
+_bfd_elf_swap_versym_in (abfd, src, dst)
+     bfd *abfd;
+     const Elf_External_Versym *src;
+     Elf_Internal_Versym *dst;
+{
+  dst->vs_vers = bfd_h_get_16 (abfd, src->vs_vers);
+}
+
+/* Swap out a Versym structure.  */
+
+void
+_bfd_elf_swap_versym_out (abfd, src, dst)
+     bfd *abfd;
+     const Elf_Internal_Versym *src;
+     Elf_External_Versym *dst;
+{
+  bfd_h_put_16 (abfd, src->vs_vers, dst->vs_vers);
+}
 
 /* Standard ELF hash function.  Do not change this function; you will
    cause invalid hash tables to be generated.  (Well, you would if this
@@ -97,7 +247,7 @@ elf_read (abfd, offset, size)
 }
 
 boolean
-elf_mkobject (abfd)
+bfd_elf_mkobject (abfd)
      bfd * abfd;
 {
   /* this just does initialization */
@@ -155,6 +305,18 @@ bfd_elf_string_from_elf_section (abfd, shindex, strindex)
       && bfd_elf_get_str_section (abfd, shindex) == NULL)
     return NULL;
 
+  if (strindex >= hdr->sh_size)
+    {
+      (*_bfd_error_handler)
+       ("%s: invalid string offset %u >= %lu for section `%s'",
+        bfd_get_filename (abfd), strindex, (unsigned long) hdr->sh_size,
+        ((shindex == elf_elfheader(abfd)->e_shstrndx
+          && strindex == hdr->sh_name)
+         ? ".shstrtab"
+         : elf_string_from_elf_strtab (abfd, hdr->sh_name)));
+      return "";
+    }
+
   return ((char *) hdr->contents) + strindex;
 }
 
@@ -467,6 +629,13 @@ _bfd_elf_print_private_bfd_data (abfd, farg)
            case DT_DEBUG: name = "DEBUG"; break;
            case DT_TEXTREL: name = "TEXTREL"; break;
            case DT_JMPREL: name = "JMPREL"; break;
+           case DT_AUXILIARY: name = "AUXILIARY"; stringp = true; break;
+           case DT_FILTER: name = "FILTER"; stringp = true; break;
+           case DT_VERSYM: name = "VERSYM"; break;
+           case DT_VERDEF: name = "VERDEF"; break;
+           case DT_VERDEFNUM: name = "VERDEFNUM"; break;
+           case DT_VERNEED: name = "VERNEED"; break;
+           case DT_VERNEEDNUM: name = "VERNEEDNUM"; break;
            }
 
          fprintf (f, "  %-11s ", name);
@@ -489,6 +658,52 @@ _bfd_elf_print_private_bfd_data (abfd, farg)
       dynbuf = NULL;
     }
 
+  if ((elf_dynverdef (abfd) != 0 && elf_tdata (abfd)->verdef == NULL)
+      || (elf_dynverref (abfd) != 0 && elf_tdata (abfd)->verref == NULL))
+    {
+      if (! _bfd_elf_slurp_version_tables (abfd))
+       return false;
+    }
+
+  if (elf_dynverdef (abfd) != 0)
+    {
+      Elf_Internal_Verdef *t;
+
+      fprintf (f, "\nVersion definitions:\n");
+      for (t = elf_tdata (abfd)->verdef; t != NULL; t = t->vd_nextdef)
+       {
+         fprintf (f, "%d 0x%2.2x 0x%8.8lx %s\n", t->vd_ndx,
+                  t->vd_flags, t->vd_hash, t->vd_nodename);
+         if (t->vd_auxptr->vda_nextptr != NULL)
+           {
+             Elf_Internal_Verdaux *a;
+
+             fprintf (f, "\t");
+             for (a = t->vd_auxptr->vda_nextptr;
+                  a != NULL;
+                  a = a->vda_nextptr)
+               fprintf (f, "%s ", a->vda_nodename);
+             fprintf (f, "\n");
+           }
+       }
+    }
+
+  if (elf_dynverref (abfd) != 0)
+    {
+      Elf_Internal_Verneed *t;
+
+      fprintf (f, "\nVersion References:\n");
+      for (t = elf_tdata (abfd)->verref; t != NULL; t = t->vn_nextref)
+       {
+         Elf_Internal_Vernaux *a;
+
+         fprintf (f, "  required from %s:\n", t->vn_filename);
+         for (a = t->vn_auxptr; a != NULL; a = a->vna_nextptr)
+           fprintf (f, "    0x%8.8lx 0x%2.2x %2.2d %s\n", a->vna_hash,
+                    a->vna_flags, a->vna_other, a->vna_nodename);
+       }
+    }
+
   return true;
 
  error_return:
@@ -498,9 +713,10 @@ _bfd_elf_print_private_bfd_data (abfd, farg)
 }
 
 /* Display ELF-specific fields of a symbol.  */
+
 void
-bfd_elf_print_symbol (ignore_abfd, filep, symbol, how)
-     bfd *ignore_abfd;
+bfd_elf_print_symbol (abfd, filep, symbol, how)
+     bfd *abfd;
      PTR filep;
      asymbol *symbol;
      bfd_print_symbol_type how;
@@ -530,6 +746,64 @@ bfd_elf_print_symbol (ignore_abfd, filep, symbol, how)
                     (bfd_is_com_section (symbol->section)
                      ? ((elf_symbol_type *) symbol)->internal_elf_sym.st_value
                      : ((elf_symbol_type *) symbol)->internal_elf_sym.st_size));
+
+       /* If we have version information, print it.  */
+       if (elf_tdata (abfd)->dynversym_section != 0
+           && (elf_tdata (abfd)->dynverdef_section != 0
+               || elf_tdata (abfd)->dynverref_section != 0))
+         {
+           unsigned int vernum;
+           const char *version_string;
+
+           vernum = ((elf_symbol_type *) symbol)->version & VERSYM_VERSION;
+
+           if (vernum == 0)
+             version_string = "";
+           else if (vernum == 1)
+             version_string = "Base";
+           else if (vernum <= elf_tdata (abfd)->cverdefs)
+             version_string =
+               elf_tdata (abfd)->verdef[vernum - 1].vd_nodename;
+           else
+             {
+               Elf_Internal_Verneed *t;
+
+               version_string = "";
+               for (t = elf_tdata (abfd)->verref;
+                    t != NULL;
+                    t = t->vn_nextref)
+                 {
+                   Elf_Internal_Vernaux *a;
+
+                   for (a = t->vn_auxptr; a != NULL; a = a->vna_nextptr)
+                     {
+                       if (a->vna_other == vernum)
+                         {
+                           version_string = a->vna_nodename;
+                           break;
+                         }
+                     }
+                 }
+             }
+
+           if ((((elf_symbol_type *) symbol)->version & VERSYM_HIDDEN) == 0)
+             fprintf (file, "  %-11s", version_string);
+           else
+             {
+               int i;
+
+               fprintf (file, " (%s)", version_string);
+               for (i = 10 - strlen (version_string); i > 0; --i)
+                 putc (' ', file);
+             }
+         }
+
+       /* 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));
+
        fprintf (file, " %s", symbol->name);
       }
       break;
@@ -569,7 +843,9 @@ _bfd_elf_link_hash_newfunc (entry, table, string)
       ret->got_offset = (bfd_vma) -1;
       ret->plt_offset = (bfd_vma) -1;
       ret->linker_section_pointer = (elf_linker_section_pointers_t *)0;
+      ret->verinfo.verdef = NULL;
       ret->type = STT_NOTYPE;
+      ret->other = 0;
       /* Assume that we have been called by a non-ELF symbol reader.
          This flag is then reset by the code which reads an ELF input
          file.  This ensures that a symbol created by a non-ELF symbol
@@ -885,6 +1161,24 @@ bfd_section_from_shdr (abfd, shindex)
       }
       break;
 
+    case SHT_GNU_verdef:
+      elf_dynverdef (abfd) = shindex;
+      elf_tdata (abfd)->dynverdef_hdr = *hdr;
+      return _bfd_elf_make_section_from_shdr (abfd, hdr, name);
+      break;
+
+    case SHT_GNU_versym:
+      elf_dynversym (abfd) = shindex;
+      elf_tdata (abfd)->dynversym_hdr = *hdr;
+      return _bfd_elf_make_section_from_shdr (abfd, hdr, name);
+      break;
+
+    case SHT_GNU_verneed:
+      elf_dynverref (abfd) = shindex;
+      elf_tdata (abfd)->dynverref_hdr = *hdr;
+      return _bfd_elf_make_section_from_shdr (abfd, hdr, name);
+      break;
+
     case SHT_SHLIB:
       return true;
 
@@ -1099,11 +1393,42 @@ elf_fake_sections (abfd, asect, failedptrarg)
       this_hdr->sh_type = SHT_REL;
       this_hdr->sh_entsize = bed->s->sizeof_rel;
     }
-  else if (strcmp (asect->name, ".note") == 0)
+  else if (strncmp (asect->name, ".note", 5) == 0)
     this_hdr->sh_type = SHT_NOTE;
   else if (strncmp (asect->name, ".stab", 5) == 0
           && strcmp (asect->name + strlen (asect->name) - 3, "str") == 0)
     this_hdr->sh_type = SHT_STRTAB;
+  else if (strcmp (asect->name, ".gnu.version") == 0)
+    {
+      this_hdr->sh_type = SHT_GNU_versym;
+      this_hdr->sh_entsize = sizeof (Elf_External_Versym);
+    }
+  else if (strcmp (asect->name, ".gnu.version_d") == 0)
+    {
+      this_hdr->sh_type = SHT_GNU_verdef;
+      this_hdr->sh_entsize = 0;
+      /* objcopy or strip will copy over sh_info, but may not set
+         cverdefs.  The linker will set cverdefs, but sh_info will be
+         zero.  */
+      if (this_hdr->sh_info == 0)
+       this_hdr->sh_info = elf_tdata (abfd)->cverdefs;
+      else
+       BFD_ASSERT (elf_tdata (abfd)->cverdefs == 0
+                   || this_hdr->sh_info == elf_tdata (abfd)->cverdefs);
+    }
+  else if (strcmp (asect->name, ".gnu.version_r") == 0)
+    {
+      this_hdr->sh_type = SHT_GNU_verneed;
+      this_hdr->sh_entsize = 0;
+      /* objcopy or strip will copy over sh_info, but may not set
+         cverrefs.  The linker will set cverrefs, but sh_info will be
+         zero.  */
+      if (this_hdr->sh_info == 0)
+       this_hdr->sh_info = elf_tdata (abfd)->cverrefs;
+      else
+       BFD_ASSERT (elf_tdata (abfd)->cverrefs == 0
+                   || this_hdr->sh_info == elf_tdata (abfd)->cverrefs);
+    }
   else if ((asect->flags & SEC_ALLOC) != 0
           && (asect->flags & SEC_LOAD) != 0)
     this_hdr->sh_type = SHT_PROGBITS;
@@ -1309,16 +1634,20 @@ assign_section_numbers (abfd)
 
        case SHT_DYNAMIC:
        case SHT_DYNSYM:
+       case SHT_GNU_verneed:
+       case SHT_GNU_verdef:
          /* sh_link is the section header index of the string table
-            used for the dynamic entries or symbol table.  */
+            used for the dynamic entries, or the symbol table, or the
+            version strings.  */
          s = bfd_get_section_by_name (abfd, ".dynstr");
          if (s != NULL)
            d->this_hdr.sh_link = elf_section_data (s)->this_idx;
          break;
 
        case SHT_HASH:
+       case SHT_GNU_versym:
          /* sh_link is the section header index of the symbol table
-            this hash table is for.  */
+            this hash table or version table is for.  */
          s = bfd_get_section_by_name (abfd, ".dynsym");
          if (s != NULL)
            d->this_hdr.sh_link = elf_section_data (s)->this_idx;
@@ -1789,7 +2118,7 @@ map_sections_to_segments (abfd)
          new_segment = true;
        }
       else if (BFD_ALIGN (last_hdr->lma + last_hdr->_raw_size, maxpagesize)
-              < hdr->lma)
+              < BFD_ALIGN (hdr->lma, maxpagesize))
        {
          /* If putting this section in this segment would force us to
              skip a page in the segment, then we need a new segment.  */
@@ -1884,6 +2213,30 @@ map_sections_to_segments (abfd)
       pm = &m->next;
     }
 
+  /* For each loadable .note section, add a PT_NOTE segment.  We don't
+     use bfd_get_section_by_name, because if we link together
+     nonloadable .note sections and loadable .note sections, we will
+     generate two .note sections in the output file.  FIXME: Using
+     names for section types is bogus anyhow.  */
+  for (s = abfd->sections; s != NULL; s = s->next)
+    {
+      if ((s->flags & SEC_LOAD) != 0
+         && strncmp (s->name, ".note", 5) == 0)
+       {
+         m = ((struct elf_segment_map *)
+              bfd_zalloc (abfd, sizeof (struct elf_segment_map)));
+         if (m == NULL)
+           goto error_return;
+         m->next = NULL;
+         m->p_type = PT_NOTE;
+         m->count = 1;
+         m->sections[0] = s;
+
+         *pm = m;
+         pm = &m->next;
+       }
+    }
+
   free (sections);
   sections = NULL;
 
@@ -2035,7 +2388,7 @@ assign_file_positions_for_segments (abfd)
 
       if (p->p_type == PT_LOAD
          && m->count > 0
-         && (m->sections[0]->flags & SEC_LOAD) != 0)
+         && (m->sections[0]->flags & SEC_ALLOC) != 0)
        {
          if ((abfd->flags & D_PAGED) != 0)
            off += (m->sections[0]->vma - off) % bed->maxpagesize;
@@ -2298,6 +2651,16 @@ get_program_header_size (abfd)
       ++segs;
     }
 
+  for (s = abfd->sections; s != NULL; s = s->next)
+    {
+      if ((s->flags & SEC_LOAD) != 0
+         && strncmp (s->name, ".note", 5) == 0)
+       {
+         /* We need a PT_NOTE segment.  */
+         ++segs;
+       }
+    }
+
   /* Let the backend count up any program headers it might need.  */
   if (bed->elf_backend_additional_program_headers)
     {
@@ -2499,26 +2862,35 @@ prep_headers (abfd)
     case bfd_arch_sh:
       i_ehdrp->e_machine = EM_SH;
       break;
-/* start-sanitize-d10v */
     case bfd_arch_d10v:
       i_ehdrp->e_machine = EM_CYGNUS_D10V;
       break;
-/* end-sanitize-d10v */
+/* start-sanitize-d30v */
+    case bfd_arch_d30v:
+      i_ehdrp->e_machine = EM_CYGNUS_D30V;
+      break;
+/* end-sanitize-d30v */
 /* start-sanitize-v850 */
     case bfd_arch_v850:
-      i_ehdrp->e_machine = EM_CYGNUS_V850;
+      switch (bfd_get_mach (abfd))
+       {
+       default:
+       case 0:               i_ehdrp->e_machine = EM_CYGNUS_V850; break;
+       }
       break;
 /* end-sanitize-v850 */
-/* start-sanitize-arc */
-    case bfd_arch_arc:
+   case bfd_arch_arc:
       i_ehdrp->e_machine = EM_CYGNUS_ARC;
       break;
-/* end-sanitize-arc */
-/* start-sanitize-m32r */
     case bfd_arch_m32r:
       i_ehdrp->e_machine = EM_CYGNUS_M32R;
       break;
-/* end-sanitize-m32r */
+    case bfd_arch_mn10200:
+      i_ehdrp->e_machine = EM_CYGNUS_MN10200;
+      break;
+    case bfd_arch_mn10300:
+      i_ehdrp->e_machine = EM_CYGNUS_MN10300;
+      break;
       /* also note that EM_M32, AT&T WE32100 is unknown to bfd */
     default:
       i_ehdrp->e_machine = EM_NONE;
@@ -2804,7 +3176,7 @@ copy_private_bfd_data (ibfd, obfd)
       m = ((struct elf_segment_map *)
           bfd_alloc (obfd,
                      (sizeof (struct elf_segment_map)
-                      + (csecs - 1) * sizeof (asection *))));
+                      + ((size_t) csecs - 1) * sizeof (asection *))));
       if (m == NULL)
        return false;
 
@@ -2898,7 +3270,9 @@ _bfd_elf_copy_private_section_data (ibfd, isec, obfd, osec)
   ohdr->sh_entsize = ihdr->sh_entsize;
 
   if (ihdr->sh_type == SHT_SYMTAB
-      || ihdr->sh_type == SHT_DYNSYM)
+      || ihdr->sh_type == SHT_DYNSYM
+      || ihdr->sh_type == SHT_GNU_verneed
+      || ihdr->sh_type == SHT_GNU_verdef)
     ohdr->sh_info = ihdr->sh_info;
 
   return true;
@@ -2924,6 +3298,10 @@ _bfd_elf_copy_private_symbol_data (ibfd, isymarg, obfd, osymarg)
 {
   elf_symbol_type *isym, *osym;
 
+  if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
+      || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
+    return true;
+
   isym = elf_symbol_from (ibfd, isymarg);
   osym = elf_symbol_from (obfd, osymarg);
 
@@ -3136,7 +3514,11 @@ swap_out_syms (abfd, sttp)
            sym.st_info = ELF_ST_INFO (bind, type);
          }
 
-       sym.st_other = 0;
+       if (type_ptr != NULL)
+         sym.st_other = type_ptr->internal_elf_sym.st_other;
+       else
+         sym.st_other = 0;
+
        bed->s->swap_symbol_out (abfd, &sym, (PTR) outbound_syms);
        outbound_syms += bed->s->sizeof_sym;
       }
@@ -3216,7 +3598,10 @@ _bfd_elf_canonicalize_reloc (abfd, section, relptr, symbols)
   arelent *tblptr;
   unsigned int i;
 
-  if (! get_elf_backend_data (abfd)->s->slurp_reloc_table (abfd, section, symbols))
+  if (! get_elf_backend_data (abfd)->s->slurp_reloc_table (abfd,
+                                                          section,
+                                                          symbols,
+                                                          false))
     return -1;
 
   tblptr = section->relocation;
@@ -3248,6 +3633,264 @@ _bfd_elf_canonicalize_dynamic_symtab (abfd, alocation)
   return get_elf_backend_data (abfd)->s->slurp_symbol_table (abfd, alocation, true);
 }
 
+/* Return the size required for the dynamic reloc entries.  Any
+   section that was actually installed in the BFD, and has type
+   SHT_REL or SHT_RELA, and uses the dynamic symbol table, is
+   considered to be a dynamic reloc section.  */
+
+long
+_bfd_elf_get_dynamic_reloc_upper_bound (abfd)
+     bfd *abfd;
+{
+  long ret;
+  asection *s;
+
+  if (elf_dynsymtab (abfd) == 0)
+    {
+      bfd_set_error (bfd_error_invalid_operation);
+      return -1;
+    }
+
+  ret = sizeof (arelent *);
+  for (s = abfd->sections; s != NULL; s = s->next)
+    if (elf_section_data (s)->this_hdr.sh_link == elf_dynsymtab (abfd)
+       && (elf_section_data (s)->this_hdr.sh_type == SHT_REL
+           || elf_section_data (s)->this_hdr.sh_type == SHT_RELA))
+      ret += ((s->_raw_size / elf_section_data (s)->this_hdr.sh_entsize)
+             * sizeof (arelent *));
+
+  return ret;
+}
+
+/* Canonicalize the dynamic relocation entries.  Note that we return
+   the dynamic relocations as a single block, although they are
+   actually associated with particular sections; the interface, which
+   was designed for SunOS style shared libraries, expects that there
+   is only one set of dynamic relocs.  Any section that was actually
+   installed in the BFD, and has type SHT_REL or SHT_RELA, and uses
+   the dynamic symbol table, is considered to be a dynamic reloc
+   section.  */
+
+long
+_bfd_elf_canonicalize_dynamic_reloc (abfd, storage, syms)
+     bfd *abfd;
+     arelent **storage;
+     asymbol **syms;
+{
+  boolean (*slurp_relocs) PARAMS ((bfd *, asection *, asymbol **, boolean));
+  asection *s;
+  long ret;
+
+  if (elf_dynsymtab (abfd) == 0)
+    {
+      bfd_set_error (bfd_error_invalid_operation);
+      return -1;
+    }
+
+  slurp_relocs = get_elf_backend_data (abfd)->s->slurp_reloc_table;
+  ret = 0;
+  for (s = abfd->sections; s != NULL; s = s->next)
+    {
+      if (elf_section_data (s)->this_hdr.sh_link == elf_dynsymtab (abfd)
+         && (elf_section_data (s)->this_hdr.sh_type == SHT_REL
+             || elf_section_data (s)->this_hdr.sh_type == SHT_RELA))
+       {
+         arelent *p;
+         long count, i;
+
+         if (! (*slurp_relocs) (abfd, s, syms, true))
+           return -1;
+         count = s->_raw_size / elf_section_data (s)->this_hdr.sh_entsize;
+         p = s->relocation;
+         for (i = 0; i < count; i++)
+           *storage++ = p++;
+         ret += count;
+       }
+    }
+
+  *storage = NULL;
+
+  return ret;
+}
+\f
+/* Read in the version information.  */
+
+boolean
+_bfd_elf_slurp_version_tables (abfd)
+     bfd *abfd;
+{
+  bfd_byte *contents = NULL;
+
+  if (elf_dynverdef (abfd) != 0)
+    {
+      Elf_Internal_Shdr *hdr;
+      Elf_External_Verdef *everdef;
+      Elf_Internal_Verdef *iverdef;
+      unsigned int i;
+
+      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;
+      if (bfd_seek (abfd, hdr->sh_offset, SEEK_SET) != 0
+         || bfd_read ((PTR) contents, 1, hdr->sh_size, abfd) != hdr->sh_size)
+       goto error_return;
+
+      everdef = (Elf_External_Verdef *) contents;
+      iverdef = elf_tdata (abfd)->verdef;
+      for (i = 0; i < hdr->sh_info; i++, iverdef++)
+       {
+         Elf_External_Verdaux *everdaux;
+         Elf_Internal_Verdaux *iverdaux;
+         unsigned int j;
+
+         _bfd_elf_swap_verdef_in (abfd, everdef, iverdef);
+
+         iverdef->vd_bfd = abfd;
+
+         iverdef->vd_auxptr = ((Elf_Internal_Verdaux *)
+                               bfd_alloc (abfd,
+                                          (iverdef->vd_cnt
+                                           * sizeof (Elf_Internal_Verdaux))));
+         if (iverdef->vd_auxptr == NULL)
+           goto error_return;
+
+         everdaux = ((Elf_External_Verdaux *)
+                     ((bfd_byte *) everdef + iverdef->vd_aux));
+         iverdaux = iverdef->vd_auxptr;
+         for (j = 0; j < iverdef->vd_cnt; j++, iverdaux++)
+           {
+             _bfd_elf_swap_verdaux_in (abfd, everdaux, iverdaux);
+
+             iverdaux->vda_nodename =
+               bfd_elf_string_from_elf_section (abfd, hdr->sh_link,
+                                                iverdaux->vda_name);
+             if (iverdaux->vda_nodename == NULL)
+               goto error_return;
+
+             if (j + 1 < iverdef->vd_cnt)
+               iverdaux->vda_nextptr = iverdaux + 1;
+             else
+               iverdaux->vda_nextptr = NULL;
+
+             everdaux = ((Elf_External_Verdaux *)
+                         ((bfd_byte *) everdaux + iverdaux->vda_next));
+           }
+
+         iverdef->vd_nodename = iverdef->vd_auxptr->vda_nodename;
+
+         if (i + 1 < hdr->sh_info)
+           iverdef->vd_nextdef = iverdef + 1;
+         else
+           iverdef->vd_nextdef = NULL;
+
+         everdef = ((Elf_External_Verdef *)
+                    ((bfd_byte *) everdef + iverdef->vd_next));
+       }
+
+      free (contents);
+      contents = NULL;
+    }
+
+  if (elf_dynverref (abfd) != 0)
+    {
+      Elf_Internal_Shdr *hdr;
+      Elf_External_Verneed *everneed;
+      Elf_Internal_Verneed *iverneed;
+      unsigned int i;
+
+      hdr = &elf_tdata (abfd)->dynverref_hdr;
+
+      elf_tdata (abfd)->verref =
+       ((Elf_Internal_Verneed *)
+        bfd_zalloc (abfd, hdr->sh_info * sizeof (Elf_Internal_Verneed)));
+      if (elf_tdata (abfd)->verref == NULL)
+       goto error_return;
+
+      elf_tdata (abfd)->cverrefs = hdr->sh_info;
+
+      contents = (bfd_byte *) bfd_malloc (hdr->sh_size);
+      if (contents == NULL)
+       goto error_return;
+      if (bfd_seek (abfd, hdr->sh_offset, SEEK_SET) != 0
+         || bfd_read ((PTR) contents, 1, hdr->sh_size, abfd) != hdr->sh_size)
+       goto error_return;
+
+      everneed = (Elf_External_Verneed *) contents;
+      iverneed = elf_tdata (abfd)->verref;
+      for (i = 0; i < hdr->sh_info; i++, iverneed++)
+       {
+         Elf_External_Vernaux *evernaux;
+         Elf_Internal_Vernaux *ivernaux;
+         unsigned int j;
+
+         _bfd_elf_swap_verneed_in (abfd, everneed, iverneed);
+
+         iverneed->vn_bfd = abfd;
+
+         iverneed->vn_filename =
+           bfd_elf_string_from_elf_section (abfd, hdr->sh_link,
+                                            iverneed->vn_file);
+         if (iverneed->vn_filename == NULL)
+           goto error_return;
+
+         iverneed->vn_auxptr =
+           ((Elf_Internal_Vernaux *)
+            bfd_alloc (abfd,
+                       iverneed->vn_cnt * sizeof (Elf_Internal_Vernaux)));
+
+         evernaux = ((Elf_External_Vernaux *)
+                     ((bfd_byte *) everneed + iverneed->vn_aux));
+         ivernaux = iverneed->vn_auxptr;
+         for (j = 0; j < iverneed->vn_cnt; j++, ivernaux++)
+           {
+             _bfd_elf_swap_vernaux_in (abfd, evernaux, ivernaux);
+
+             ivernaux->vna_nodename =
+               bfd_elf_string_from_elf_section (abfd, hdr->sh_link,
+                                                ivernaux->vna_name);
+             if (ivernaux->vna_nodename == NULL)
+               goto error_return;
+
+             if (j + 1 < iverneed->vn_cnt)
+               ivernaux->vna_nextptr = ivernaux + 1;
+             else
+               ivernaux->vna_nextptr = NULL;
+
+             evernaux = ((Elf_External_Vernaux *)
+                         ((bfd_byte *) evernaux + ivernaux->vna_next));
+           }
+
+         if (i + 1 < hdr->sh_info)
+           iverneed->vn_nextref = iverneed + 1;
+         else
+           iverneed->vn_nextref = NULL;
+
+         everneed = ((Elf_External_Verneed *)
+                     ((bfd_byte *) everneed + iverneed->vn_next));
+       }
+
+      free (contents);
+      contents = NULL;
+    }
+
+  return true;
+
+ error_return:
+  if (contents == NULL)
+    free (contents);
+  return false;
+}
+\f
 asymbol *
 _bfd_elf_make_empty_symbol (abfd)
      bfd *abfd;
@@ -3273,6 +3916,36 @@ _bfd_elf_get_symbol_info (ignore_abfd, symbol, ret)
   bfd_symbol_info (symbol, ret);
 }
 
+/* Return whether a symbol name implies a local symbol.  Most targets
+   use this function for the is_local_label_name entry point, but some
+   override it.  */
+
+boolean
+_bfd_elf_is_local_label_name (abfd, name)
+     bfd *abfd;
+     const char *name;
+{
+  /* Normal local symbols start with ``.L''.  */
+  if (name[0] == '.' && name[1] == 'L')
+    return true;
+
+  /* At least some SVR4 compilers (e.g., UnixWare 2.1 cc) generate
+     DWARF debugging symbols starting with ``..''.  */
+  if (name[0] == '.' && name[1] == '.')
+    return true;
+
+  /* gcc will sometimes generate symbols beginning with ``_.L_'' when
+     emitting DWARF debugging output.  I suspect this is actually a
+     small bug in gcc (it calls ASM_OUTPUT_LABEL when it should call
+     ASM_GENERATE_INTERNAL_LABEL, and this causes the leading
+     underscore to be emitted on some ELF targets).  For ease of use,
+     we treat such symbols as local.  */
+  if (name[0] == '_' && name[1] == '.' && name[2] == 'L' && name[3] == '_')
+    return true;
+
+  return false;
+}
+
 alent *
 _bfd_elf_get_lineno (ignore_abfd, symbol)
      bfd *ignore_abfd;
This page took 0.032706 seconds and 4 git commands to generate.