* elf-eh-frame.c (ENSURE_NO_RELOCS): Disregard R_*_NONE relocs.
[deliverable/binutils-gdb.git] / bfd / elflink.h
index c116ed5d44aa9de8beac05223cdf4760ff83bb3c..c94519478288ee4a3848b0f748da3f61892096c0 100644 (file)
@@ -1938,19 +1938,17 @@ elf_link_add_object_symbols (abfd, info)
             might be needed here.  */
          if (isym->st_other != 0)
            {
+             unsigned char hvis, symvis, other;
+
+             /* Take the balance of OTHER from the definition.  */
+             other = (definition ? isym->st_other : h->other);
+             other &= ~ ELF_ST_VISIBILITY (-1);
+
              /* Combine visibilities, using the most constraining one.  */
-             unsigned char hvis   = ELF_ST_VISIBILITY (h->other);
-             unsigned char symvis = ELF_ST_VISIBILITY (isym->st_other);
-
-             if (symvis && (hvis > symvis || hvis == 0))
-               h->other = isym->st_other;
-
-             /* If neither has visibility, use the st_other of the
-                definition.  This is an arbitrary choice, since the
-                other bits have no general meaning.  */
-             if (!symvis && !hvis
-                 && (definition || h->other == 0))
-               h->other = isym->st_other;
+             hvis   = ELF_ST_VISIBILITY (h->other);
+             symvis = ELF_ST_VISIBILITY (isym->st_other);
+
+             h->other = other | (hvis > symvis ? hvis : symvis);
            }
 
          /* Set a flag in the hash table entry indicating the type of
@@ -2208,10 +2206,9 @@ elf_link_add_object_symbols (abfd, info)
        }
     }
 
-  /* If this is a non-traditional, non-relocateable link, try to
-     optimize the handling of the .stab/.stabstr sections.  */
+  /* If this is a non-traditional link, try to optimize the handling
+     of the .stab/.stabstr sections.  */
   if (! dynamic
-      && ! info->relocateable
       && ! info->traditional_format
       && info->hash->creator->flavour == bfd_target_elf_flavour
       && is_elf_hash_table (info)
@@ -2342,6 +2339,7 @@ elf_link_create_dynamic_sections (abfd, info)
          || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY)
          || ! bfd_set_section_alignment (abfd, s, 2))
        return false;
+      elf_hash_table (info)->eh_info.hdr_sec = s;
     }
 
   /* Create sections to hold version informations.  These are removed
@@ -5854,17 +5852,10 @@ elf_bfd_final_link (abfd, info)
        goto error_return;
     }
 
-  if (info->eh_frame_hdr && elf_hash_table (info)->dynobj)
+  if (info->eh_frame_hdr)
     {
-      o = bfd_get_section_by_name (elf_hash_table (info)->dynobj,
-                                  ".eh_frame_hdr");
-      if (o
-         && (elf_section_data (o)->sec_info_type
-             == ELF_INFO_TYPE_EH_FRAME_HDR))
-       {
-         if (! _bfd_elf_write_section_eh_frame_hdr (abfd, o))
-           goto error_return;
-       }
+      if (! _bfd_elf_write_section_eh_frame_hdr (abfd, info))
+       goto error_return;
     }
 
   if (finfo.symstrtab != NULL)
@@ -6396,11 +6387,10 @@ elf_link_output_extsym (h, data)
       sym.st_info = ELF_ST_INFO (bindtype, ELF_ST_TYPE (sym.st_info));
     }
 
-  /* If a symbol is not defined locally, we clear the visibility
-     field.  */
+  /* If a symbol is not defined locally, we clear the visibility field.  */
   if (! finfo->info->relocateable
       && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
-    sym.st_other ^= ELF_ST_VISIBILITY (sym.st_other);
+    sym.st_other &= ~ ELF_ST_VISIBILITY (-1);
 
   /* If this symbol should be put in the .dynsym section, then put it
      there now.  We already know the symbol index.  We also fill in
@@ -6839,12 +6829,7 @@ elf_link_input_bfd (finfo, input_bfd)
             from discarded sections and section symbols from
             removed link-once sections.  Complain about relocs
             against discarded sections.  Zero relocs against removed
-            link-once sections.  We should really complain if
-            anything in the final link tries to use it, but
-            DWARF-based exception handling might have an entry in
-            .eh_frame to describe a routine in the linkonce section,
-            and it turns out to be hard to remove the .eh_frame
-            entry too.  FIXME.  */
+            link-once sections.  */
          if (!finfo->info->relocateable
              && !elf_section_ignore_discarded_relocs (o))
            {
@@ -6961,6 +6946,7 @@ elf_link_input_bfd (finfo, input_bfd)
            {
              Elf_Internal_Rela *irela;
              Elf_Internal_Rela *irelaend;
+             bfd_vma last_offset;
              struct elf_link_hash_entry **rel_hash;
              Elf_Internal_Shdr *input_rel_hdr, *input_rel_hdr2;
              unsigned int next_erel;
@@ -6981,6 +6967,9 @@ elf_link_input_bfd (finfo, input_bfd)
              rel_hash = (elf_section_data (o->output_section)->rel_hashes
                          + elf_section_data (o->output_section)->rel_count
                          + elf_section_data (o->output_section)->rel_count2);
+             last_offset = o->output_offset;
+             if (!finfo->info->relocateable)
+               last_offset += o->output_section->vma;
              for (next_erel = 0; irela < irelaend; irela++, next_erel++)
                {
                  unsigned long r_symndx;
@@ -6993,15 +6982,32 @@ elf_link_input_bfd (finfo, input_bfd)
                      next_erel = 0;
                    }
 
+                 irela->r_offset = _bfd_elf_section_offset (output_bfd,
+                                                            finfo->info, o,
+                                                            irela->r_offset);
+                 if (irela->r_offset >= (bfd_vma) -2)
+                   {
+                     /* This is a reloc for a deleted entry or somesuch.
+                        Turn it into an R_*_NONE reloc, at the same
+                        offset as the last reloc.  elf_eh_frame.c and
+                        elf_bfd_discard_info rely on reloc offsets
+                        being ordered.  */ 
+                     irela->r_offset = last_offset;
+                     irela->r_info = 0;
+                     irela->r_addend = 0;
+                     continue;
+                   }
+
                  irela->r_offset += o->output_offset;
 
                  /* Relocs in an executable have to be virtual addresses.  */
                  if (!finfo->info->relocateable)
                    irela->r_offset += o->output_section->vma;
 
-                 r_symndx = ELF_R_SYM (irela->r_info);
+                 last_offset = irela->r_offset;
 
-                 if (r_symndx == 0)
+                 r_symndx = ELF_R_SYM (irela->r_info);
+                 if (r_symndx == STN_UNDEF)
                    continue;
 
                  if (r_symndx >= locsymcount
@@ -7166,19 +7172,14 @@ elf_link_input_bfd (finfo, input_bfd)
            return false;
          break;
        case ELF_INFO_TYPE_MERGE:
-         if (! (_bfd_write_merged_section
-                (output_bfd, o, elf_section_data (o)->sec_info)))
+         if (! _bfd_write_merged_section (output_bfd, o,
+                                          elf_section_data (o)->sec_info))
            return false;
          break;
        case ELF_INFO_TYPE_EH_FRAME:
          {
-           asection *ehdrsec;
-
-           ehdrsec
-             = bfd_get_section_by_name (elf_hash_table (finfo->info)->dynobj,
-                                        ".eh_frame_hdr");
-           if (! (_bfd_elf_write_section_eh_frame (output_bfd, o, ehdrsec,
-                                                   contents)))
+           if (! _bfd_elf_write_section_eh_frame (output_bfd, finfo->info,
+                                                  o, contents))
              return false;
          }
          break;
@@ -8350,7 +8351,7 @@ elf_reloc_symbol_deleted_p (offset, cookie)
 
   for (; rcookie->rel < rcookie->relend; rcookie->rel++)
     {
-      unsigned long r_symndx = ELF_R_SYM (rcookie->rel->r_info);
+      unsigned long r_symndx;
 
       if (! rcookie->bad_symtab)
        if (rcookie->rel->r_offset > offset)
@@ -8358,6 +8359,10 @@ elf_reloc_symbol_deleted_p (offset, cookie)
       if (rcookie->rel->r_offset != offset)
        continue;
 
+      r_symndx = ELF_R_SYM (rcookie->rel->r_info);
+      if (r_symndx == SHN_UNDEF)
+       return true;
+
       if (r_symndx >= rcookie->locsymcount
          || ELF_ST_BIND (rcookie->locsyms[r_symndx].st_info) != STB_LOCAL)
        {
@@ -8409,24 +8414,18 @@ elf_bfd_discard_info (output_bfd, info)
      struct bfd_link_info *info;
 {
   struct elf_reloc_cookie cookie;
-  asection *stab, *eh, *ehdr;
+  asection *stab, *eh;
   Elf_Internal_Shdr *symtab_hdr;
   struct elf_backend_data *bed;
   bfd *abfd;
+  unsigned int count;
   boolean ret = false;
-  boolean strip = info->strip == strip_all || info->strip == strip_debugger;
 
-  if (info->relocateable
-      || info->traditional_format
+  if (info->traditional_format
       || info->hash->creator->flavour != bfd_target_elf_flavour
       || ! is_elf_hash_table (info))
     return false;
 
-  ehdr = NULL;
-  if (elf_hash_table (info)->dynobj != NULL)
-    ehdr = bfd_get_section_by_name (elf_hash_table (info)->dynobj,
-                                   ".eh_frame_hdr");
-
   for (abfd = info->input_bfds; abfd != NULL; abfd = abfd->link_next)
     {
       if (bfd_get_flavour (abfd) != bfd_target_elf_flavour)
@@ -8437,27 +8436,22 @@ elf_bfd_discard_info (output_bfd, info)
       if ((abfd->flags & DYNAMIC) != 0)
        continue;
 
-      eh = NULL;
-      if (ehdr)
-       {
-         eh = bfd_get_section_by_name (abfd, ".eh_frame");
-         if (eh && (eh->_raw_size == 0
-                    || bfd_is_abs_section (eh->output_section)))
-           eh = NULL;
-       }
+      eh = bfd_get_section_by_name (abfd, ".eh_frame");
+      if (eh != NULL
+         && (eh->_raw_size == 0
+             || bfd_is_abs_section (eh->output_section)))
+       eh = NULL;
 
-      stab = NULL;
-      if (!strip)
-       {
-         stab = bfd_get_section_by_name (abfd, ".stab");
-         if (stab && (stab->_raw_size == 0
-                      || bfd_is_abs_section (stab->output_section)))
-           stab = NULL;
-       }
-      if ((! stab
-          || elf_section_data(stab)->sec_info_type != ELF_INFO_TYPE_STABS)
-         && ! eh
-         && (strip || ! bed->elf_backend_discard_info))
+      stab = bfd_get_section_by_name (abfd, ".stab");
+      if (stab != NULL
+         && (stab->_raw_size == 0
+             || bfd_is_abs_section (stab->output_section)
+             || elf_section_data (stab)->sec_info_type != ELF_INFO_TYPE_STABS))
+       stab = NULL;
+
+      if (stab == NULL
+         && eh == NULL
+         && bed->elf_backend_discard_info == NULL)
        continue;
 
       symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
@@ -8466,8 +8460,7 @@ elf_bfd_discard_info (output_bfd, info)
       cookie.bad_symtab = elf_bad_symtab (abfd);
       if (cookie.bad_symtab)
        {
-         cookie.locsymcount =
-           symtab_hdr->sh_size / sizeof (Elf_External_Sym);
+         cookie.locsymcount = symtab_hdr->sh_size / sizeof (Elf_External_Sym);
          cookie.extsymoff = 0;
        }
       else
@@ -8486,16 +8479,19 @@ elf_bfd_discard_info (output_bfd, info)
            return false;
        }
 
-      if (stab)
+      if (stab != NULL)
        {
-         cookie.rels = (NAME(_bfd_elf,link_read_relocs)
-                        (abfd, stab, (PTR) NULL, (Elf_Internal_Rela *) NULL,
-                         info->keep_memory));
-         if (cookie.rels)
+         cookie.rels = NULL;
+         count = stab->reloc_count;
+         if (count != 0)
+           cookie.rels = (NAME(_bfd_elf,link_read_relocs)
+                          (abfd, stab, (PTR) NULL, (Elf_Internal_Rela *) NULL,
+                           info->keep_memory));
+         if (cookie.rels != NULL)
            {
              cookie.rel = cookie.rels;
-             cookie.relend =
-               cookie.rels + stab->reloc_count * bed->s->int_rels_per_ext_rel;
+             cookie.relend = cookie.rels;
+             cookie.relend += count * bed->s->int_rels_per_ext_rel;
              if (_bfd_discard_section_stabs (abfd, stab,
                                              elf_section_data (stab)->sec_info,
                                              elf_reloc_symbol_deleted_p,
@@ -8506,39 +8502,32 @@ elf_bfd_discard_info (output_bfd, info)
            }
        }
 
-      if (eh)
+      if (eh != NULL)
        {
          cookie.rels = NULL;
-         cookie.rel = NULL;
-         cookie.relend = NULL;
-         if (eh->reloc_count)
+         count = eh->reloc_count;
+         if (count != 0)
            cookie.rels = (NAME(_bfd_elf,link_read_relocs)
                           (abfd, eh, (PTR) NULL, (Elf_Internal_Rela *) NULL,
                            info->keep_memory));
-         if (cookie.rels)
-           {
-             cookie.rel = cookie.rels;
-             cookie.relend =
-               cookie.rels + eh->reloc_count * bed->s->int_rels_per_ext_rel;
-           }
-         if (_bfd_elf_discard_section_eh_frame (abfd, info, eh, ehdr,
+         cookie.rel = cookie.rels;
+         cookie.relend = cookie.rels;
+         if (cookie.rels != NULL)
+           cookie.relend += count * bed->s->int_rels_per_ext_rel;
+
+         if (_bfd_elf_discard_section_eh_frame (abfd, info, eh,
                                                 elf_reloc_symbol_deleted_p,
                                                 &cookie))
-           {
-             /* Relocs have been edited.  Ensure edited version is
-                used later in relocate_section.  */
-             elf_section_data (eh)->relocs = cookie.rels;
-             ret = true;
-           }
-         if (cookie.rels && elf_section_data (eh)->relocs != cookie.rels)
+           ret = true;
+
+         if (cookie.rels != NULL
+             && elf_section_data (eh)->relocs != cookie.rels)
            free (cookie.rels);
        }
 
-      if (bed->elf_backend_discard_info)
-       {
-         if (bed->elf_backend_discard_info (abfd, &cookie, info))
-           ret = true;
-       }
+      if (bed->elf_backend_discard_info != NULL
+         && (*bed->elf_backend_discard_info) (abfd, &cookie, info))
+       ret = true;
 
       if (cookie.locsyms != NULL
          && symtab_hdr->contents != (unsigned char *) cookie.locsyms)
@@ -8550,8 +8539,10 @@ elf_bfd_discard_info (output_bfd, info)
        }
     }
 
-  if (ehdr && _bfd_elf_discard_section_eh_frame_hdr (output_bfd, info, ehdr))
+  if (info->eh_frame_hdr
+      && _bfd_elf_discard_section_eh_frame_hdr (output_bfd, info))
     ret = true;
+
   return ret;
 }
 
This page took 0.03043 seconds and 4 git commands to generate.