* Makefile.am: New file, based on old Makefile.in.
[deliverable/binutils-gdb.git] / bfd / elf.c
index 94d953f5a9fd9e0bc658159135d0d8eba780762a..6c29ca762e98a1969f0acc50d9cacd7575e55184 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -1,5 +1,5 @@
 /* ELF executable support for BFD.
 /* 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.
 
 
 This file is part of BFD, the Binary File Descriptor library.
 
@@ -54,6 +54,150 @@ 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 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
    were being used yet.)  */
 /* Standard ELF hash function.  Do not change this function; you will
    cause invalid hash tables to be generated.  (Well, you would if this
    were being used yet.)  */
@@ -103,7 +247,7 @@ elf_read (abfd, offset, size)
 }
 
 boolean
 }
 
 boolean
-elf_mkobject (abfd)
+bfd_elf_mkobject (abfd)
      bfd * abfd;
 {
   /* this just does initialization */
      bfd * abfd;
 {
   /* this just does initialization */
@@ -161,6 +305,18 @@ bfd_elf_string_from_elf_section (abfd, shindex, strindex)
       && bfd_elf_get_str_section (abfd, shindex) == NULL)
     return NULL;
 
       && 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;
 }
 
   return ((char *) hdr->contents) + strindex;
 }
 
@@ -473,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_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);
            }
 
          fprintf (f, "  %-11s ", name);
@@ -495,6 +658,52 @@ _bfd_elf_print_private_bfd_data (abfd, farg)
       dynbuf = NULL;
     }
 
       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:
   return true;
 
  error_return:
@@ -504,9 +713,10 @@ _bfd_elf_print_private_bfd_data (abfd, farg)
 }
 
 /* Display ELF-specific fields of a symbol.  */
 }
 
 /* Display ELF-specific fields of a symbol.  */
+
 void
 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;
      PTR filep;
      asymbol *symbol;
      bfd_print_symbol_type how;
@@ -536,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));
                     (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;
        fprintf (file, " %s", symbol->name);
       }
       break;
@@ -575,6 +843,7 @@ _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->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.
       ret->type = STT_NOTYPE;
       ret->other = 0;
       /* Assume that we have been called by a non-ELF symbol reader.
@@ -864,20 +1133,7 @@ bfd_section_from_shdr (abfd, shindex)
           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))
           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))
-         {
-           if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name))
-             return false;
-           if (hdr->bfd_section != NULL
-               && hdr->sh_info > 0
-               && bfd_section_from_shdr (abfd, hdr->sh_info))
-             {
-               target_sect = bfd_section_from_elf_index (abfd, hdr->sh_info);
-               if (target_sect != NULL
-                   && (target_sect->flags & SEC_DEBUGGING) != 0)
-                 hdr->bfd_section->flags |= SEC_DEBUGGING;
-             }
-           return true;
-         }
+         return _bfd_elf_make_section_from_shdr (abfd, hdr, name);
 
        if (! bfd_section_from_shdr (abfd, hdr->sh_info))
          return false;
 
        if (! bfd_section_from_shdr (abfd, hdr->sh_info))
          return false;
@@ -905,6 +1161,24 @@ bfd_section_from_shdr (abfd, shindex)
       }
       break;
 
       }
       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;
 
     case SHT_SHLIB:
       return true;
 
@@ -1119,11 +1393,42 @@ elf_fake_sections (abfd, asect, failedptrarg)
       this_hdr->sh_type = SHT_REL;
       this_hdr->sh_entsize = bed->s->sizeof_rel;
     }
       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;
     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;
   else if ((asect->flags & SEC_ALLOC) != 0
           && (asect->flags & SEC_LOAD) != 0)
     this_hdr->sh_type = SHT_PROGBITS;
@@ -1329,16 +1634,20 @@ assign_section_numbers (abfd)
 
        case SHT_DYNAMIC:
        case SHT_DYNSYM:
 
        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
          /* 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:
          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
          /* 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;
          s = bfd_get_section_by_name (abfd, ".dynsym");
          if (s != NULL)
            d->this_hdr.sh_link = elf_section_data (s)->this_idx;
@@ -1904,6 +2213,30 @@ map_sections_to_segments (abfd)
       pm = &m->next;
     }
 
       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;
 
   free (sections);
   sections = NULL;
 
@@ -2318,6 +2651,16 @@ get_program_header_size (abfd)
       ++segs;
     }
 
       ++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)
     {
   /* Let the backend count up any program headers it might need.  */
   if (bed->elf_backend_additional_program_headers)
     {
@@ -2519,11 +2862,14 @@ prep_headers (abfd)
     case bfd_arch_sh:
       i_ehdrp->e_machine = EM_SH;
       break;
     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;
     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;
 /* start-sanitize-v850 */
     case bfd_arch_v850:
       i_ehdrp->e_machine = EM_CYGNUS_V850;
@@ -2534,11 +2880,9 @@ prep_headers (abfd)
       i_ehdrp->e_machine = EM_CYGNUS_ARC;
       break;
 /* end-sanitize-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;
     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_mn10200:
       i_ehdrp->e_machine = EM_CYGNUS_MN10200;
       break;
@@ -2830,7 +3174,7 @@ copy_private_bfd_data (ibfd, obfd)
       m = ((struct elf_segment_map *)
           bfd_alloc (obfd,
                      (sizeof (struct elf_segment_map)
       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;
 
       if (m == NULL)
        return false;
 
@@ -2924,7 +3268,9 @@ _bfd_elf_copy_private_section_data (ibfd, isec, obfd, osec)
   ohdr->sh_entsize = ihdr->sh_entsize;
 
   if (ihdr->sh_type == SHT_SYMTAB
   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;
     ohdr->sh_info = ihdr->sh_info;
 
   return true;
@@ -3364,7 +3710,185 @@ _bfd_elf_canonicalize_dynamic_reloc (abfd, storage, syms)
 
   return ret;
 }
 
   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;
 asymbol *
 _bfd_elf_make_empty_symbol (abfd)
      bfd *abfd;
@@ -3390,6 +3914,36 @@ _bfd_elf_get_symbol_info (ignore_abfd, symbol, ret)
   bfd_symbol_info (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;
 alent *
 _bfd_elf_get_lineno (ignore_abfd, symbol)
      bfd *ignore_abfd;
This page took 0.031209 seconds and 4 git commands to generate.