* elf32-frv.c (FRV_SYM_LOCAL): Weak undefined doesn't imply local.
authorAlexandre Oliva <aoliva@redhat.com>
Tue, 24 Feb 2004 16:39:01 +0000 (16:39 +0000)
committerAlexandre Oliva <aoliva@redhat.com>
Tue, 24 Feb 2004 16:39:01 +0000 (16:39 +0000)
(_frv_emit_got_relocs_plt_entries): Decay relocation to protected
function's descriptor to symbol+offset, and map local undefweak
symbol to NULL function descriptor.
(elf32_frv_relocate_section): Likewise.

bfd/ChangeLog
bfd/elf32-frv.c

index bde4f4fbf12f4c4887454a4345194da15e67b940..0ccab082a5c9cf0efb2b8928c11c518b72e5a35d 100644 (file)
@@ -1,3 +1,11 @@
+2004-02-24  Alexandre Oliva  <aoliva@redhat.com>
+
+       * elf32-frv.c (FRV_SYM_LOCAL): Weak undefined doesn't imply local.
+       (_frv_emit_got_relocs_plt_entries): Decay relocation to protected
+       function's descriptor to symbol+offset, and map local undefweak
+       symbol to NULL function descriptor.
+       (elf32_frv_relocate_section): Likewise.
+
 2004-02-23  Mark Kettenis  <kettenis@gnu.org>
 
        * libaout.h (enum machine_type): Add M_SPARC64_NETBSD and
index 488438e59bc9da6521cbe72e8fd87e51c1424537..b8c325f1b0bbc9268ae7ccbb74c0b255fc4dfd25 100644 (file)
@@ -659,7 +659,6 @@ frv_elf_link_hash_table_create (bfd *abfd)
 #define FRV_SYM_LOCAL(INFO, H) \
   (_bfd_elf_symbol_refs_local_p ((H), (INFO), 1) \
    || ! elf_hash_table (INFO)->dynamic_sections_created \
-   || (H)->root.type == bfd_link_hash_undefweak \
    || (/* The condition below is an ugly hack to get .scommon data to
          be regarded as local.  For some reason the
          ELF_LINK_HASH_DEF_REGULAR bit is not set on such common
@@ -1029,46 +1028,60 @@ _frv_emit_got_relocs_plt_entries (struct frv_pic_relocs_info *entry,
   if (entry->fdgot_entry)
     {
       int reloc, idx;
-      bfd_vma ad;
+      bfd_vma ad = 0;
       
-      /* If the symbol is dynamic and there may be dynamic symbol
-        resolution because we are or are linked with a shared
-        library, emit a FUNCDESC relocation such that the dynamic
-        linker will allocate the function descriptor.  */
-      if (entry->symndx == -1 && ! FRV_FUNCDESC_LOCAL (info, entry->d.h))
+      if (! (entry->symndx == -1
+            && entry->d.h->root.type == bfd_link_hash_undefweak
+            && FRV_SYM_LOCAL (info, entry->d.h)))
        {
-         reloc = R_FRV_FUNCDESC;
-         idx = dynindx;
-         ad = addend;
-         if (ad)
-           return FALSE;
-       }
-      else
-       {
-         /* Otherwise, we know we have a private function descriptor,
-            so reference it directly.  */
-         if (elf_hash_table (info)->dynamic_sections_created)
-           BFD_ASSERT (entry->privfd);
-         reloc = R_FRV_32;
-         idx = elf_section_data (frv_got_section (info)->output_section)
-           ->dynindx;
-         ad = frv_got_section (info)->output_offset +
-           frv_got_initial_offset (info) + entry->fd_entry;
-       }
-
-      /* If there is room for dynamic symbol resolution, emit the
-        dynamic relocation.  However, if we're linking an executable
-        at a fixed location, we won't have emitted a dynamic symbol
-        entry for the got section, so idx will be zero, which means
-        we can and should compute the address of the private
-        descriptor ourselves.  */
-      if (info->executable && !info->pie
-         && (entry->symndx != -1 || FRV_FUNCDESC_LOCAL (info, entry->d.h)))
-       {
-         if (entry->symndx == -1
-             && entry->d.h->root.type == bfd_link_hash_undefweak)
-           ad = 0;
+         /* If the symbol is dynamic and there may be dynamic symbol
+            resolution because we are, or are linked with, a shared
+            library, emit a FUNCDESC relocation such that the dynamic
+            linker will allocate the function descriptor.  If the
+            symbol needs a non-local function descriptor but binds
+            locally (e.g., its visibility is protected, emit a
+            dynamic relocation decayed to section+offset.  */
+         if (entry->symndx == -1 && ! FRV_FUNCDESC_LOCAL (info, entry->d.h)
+             && FRV_SYM_LOCAL (info, entry->d.h)
+             && !(info->executable && !info->pie))
+           {
+             reloc = R_FRV_FUNCDESC;
+             idx = elf_section_data (entry->d.h->root.u.def.section
+                                     ->output_section)->dynindx;
+             ad = entry->d.h->root.u.def.section->output_offset
+               + entry->d.h->root.u.def.value;
+           }
+         else if (entry->symndx == -1
+                  && ! FRV_FUNCDESC_LOCAL (info, entry->d.h))
+           {
+             reloc = R_FRV_FUNCDESC;
+             idx = dynindx;
+             ad = addend;
+             if (ad)
+               return FALSE;
+           }
          else
+           {
+             /* Otherwise, we know we have a private function descriptor,
+                so reference it directly.  */
+             if (elf_hash_table (info)->dynamic_sections_created)
+               BFD_ASSERT (entry->privfd);
+             reloc = R_FRV_32;
+             idx = elf_section_data (frv_got_section (info)
+                                     ->output_section)->dynindx;
+             ad = frv_got_section (info)->output_offset
+               + frv_got_initial_offset (info) + entry->fd_entry;
+           }
+
+         /* If there is room for dynamic symbol resolution, emit the
+            dynamic relocation.  However, if we're linking an
+            executable at a fixed location, we won't have emitted a
+            dynamic symbol entry for the got section, so idx will be
+            zero, which means we can and should compute the address
+            of the private descriptor ourselves.  */
+         if (info->executable && !info->pie
+             && (entry->symndx != -1
+                 || FRV_FUNCDESC_LOCAL (info, entry->d.h)))
            {
              ad += frv_got_section (info)->output_section->vma;
              _frv_add_rofixup (output_bfd, frv_gotfixup_section (info),
@@ -1077,17 +1090,17 @@ _frv_emit_got_relocs_plt_entries (struct frv_pic_relocs_info *entry,
                                + frv_got_initial_offset (info)
                                + entry->fdgot_entry);
            }
+         else
+           _frv_add_dyn_reloc (output_bfd, frv_gotrel_section (info),
+                               _bfd_elf_section_offset
+                               (output_bfd, info,
+                                frv_got_section (info),
+                                frv_got_initial_offset (info)
+                                + entry->fdgot_entry)
+                               + frv_got_section (info)->output_section->vma
+                               + frv_got_section (info)->output_offset,
+                               reloc, idx, ad);
        }
-      else
-       _frv_add_dyn_reloc (output_bfd, frv_gotrel_section (info),
-                           _bfd_elf_section_offset
-                           (output_bfd, info,
-                            frv_got_section (info),
-                            frv_got_initial_offset (info)
-                            + entry->fdgot_entry)
-                           + frv_got_section (info)->output_section->vma
-                           + frv_got_section (info)->output_offset,
-                           reloc, idx, ad);
 
       bfd_put_32 (output_bfd, ad,
                  frv_got_section (info)->contents
@@ -2005,88 +2018,103 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section,
            int dynindx;
            bfd_vma addend = rel->r_addend;
 
-           /* If the symbol is dynamic and there may be dynamic
-              symbol resolution because we are or are linked with a
-              shared library, emit a FUNCDESC relocation such that
-              the dynamic linker will allocate the function
-              descriptor.  */
-           if (h && ! FRV_FUNCDESC_LOCAL (info, h))
+           if (! (h && h->root.type == bfd_link_hash_undefweak
+                  && FRV_SYM_LOCAL (info, h)))
              {
-               if (addend)
+               /* If the symbol is dynamic and there may be dynamic
+                  symbol resolution because we are or are linked with a
+                  shared library, emit a FUNCDESC relocation such that
+                  the dynamic linker will allocate the function
+                  descriptor.  If the symbol needs a non-local function
+                  descriptor but binds locally (e.g., its visibility is
+                  protected, emit a dynamic relocation decayed to
+                  section+offset.  */
+               if (h && ! FRV_FUNCDESC_LOCAL (info, h)
+                   && FRV_SYM_LOCAL (info, h)
+                   && !(info->executable && !info->pie))
                  {
-                   info->callbacks->warning
-                     (info, _("R_FRV_FUNCDESC references dynamic symbol with nonzero addend"),
-                      name, input_bfd, input_section, rel->r_offset);
-                   return FALSE;
+                   dynindx = elf_section_data (h->root.u.def.section
+                                               ->output_section)->dynindx;
+                   addend += h->root.u.def.section->output_offset
+                     + h->root.u.def.value;
+                 }
+               else if (h && ! FRV_FUNCDESC_LOCAL (info, h))
+                 {
+                   if (addend)
+                     {
+                       info->callbacks->warning
+                         (info, _("R_FRV_FUNCDESC references dynamic symbol with nonzero addend"),
+                          name, input_bfd, input_section, rel->r_offset);
+                       return FALSE;
+                     }
+                   dynindx = h->dynindx;
+                 }
+               else
+                 {
+                   /* Otherwise, we know we have a private function
+                      descriptor, so reference it directly.  */
+                   BFD_ASSERT (picrel->privfd);
+                   r_type = R_FRV_32;
+                   dynindx = elf_section_data (frv_got_section (info)
+                                               ->output_section)->dynindx;
+                   addend = frv_got_section (info)->output_offset
+                     + frv_got_initial_offset (info)
+                     + picrel->fd_entry;
                  }
-               dynindx = h->dynindx;
-             }
-           else
-             {
-               /* Otherwise, we know we have a private function
-                  descriptor, so reference it directly.  */
-               BFD_ASSERT (picrel->privfd);
-               r_type = R_FRV_32;
-               dynindx = elf_section_data (frv_got_section
-                                           (info)->output_section)->dynindx;
-               addend = frv_got_section (info)->output_offset
-                 + frv_got_initial_offset (info)
-                 + picrel->fd_entry;
-             }
 
-           /* If there is room for dynamic symbol resolution, emit
-              the dynamic relocation.  However, if we're linking an
-              executable at a fixed location, we won't have emitted a
-              dynamic symbol entry for the got section, so idx will
-              be zero, which means we can and should compute the
-              address of the private descriptor ourselves.  */
-           if (info->executable && !info->pie
-               && (!h || FRV_FUNCDESC_LOCAL (info, h)))
-             {
-               addend += frv_got_section (info)->output_section->vma;
-               if ((bfd_get_section_flags (output_bfd,
-                                          input_section->output_section)
-                    & (SEC_ALLOC | SEC_LOAD)) == (SEC_ALLOC | SEC_LOAD))
+               /* If there is room for dynamic symbol resolution, emit
+                  the dynamic relocation.  However, if we're linking an
+                  executable at a fixed location, we won't have emitted a
+                  dynamic symbol entry for the got section, so idx will
+                  be zero, which means we can and should compute the
+                  address of the private descriptor ourselves.  */
+               if (info->executable && !info->pie
+                   && (!h || FRV_FUNCDESC_LOCAL (info, h)))
+                 {
+                   addend += frv_got_section (info)->output_section->vma;
+                   if ((bfd_get_section_flags (output_bfd,
+                                               input_section->output_section)
+                        & (SEC_ALLOC | SEC_LOAD)) == (SEC_ALLOC | SEC_LOAD))
+                     {
+                       if (_frv_osec_readonly_p (output_bfd,
+                                                 input_section->output_section))
+                         {
+                           info->callbacks->warning
+                             (info,
+                              _("cannot emit fixups in read-only section"),
+                              name, input_bfd, input_section, rel->r_offset);
+                           return FALSE;
+                         }
+                       _frv_add_rofixup (output_bfd,
+                                         frv_gotfixup_section (info),
+                                         _bfd_elf_section_offset
+                                         (output_bfd, info,
+                                          input_section, rel->r_offset)
+                                         + input_section->output_section->vma
+                                         + input_section->output_offset);
+                     }
+                 }
+               else if ((bfd_get_section_flags (output_bfd,
+                                                input_section->output_section)
+                         & (SEC_ALLOC | SEC_LOAD)) == (SEC_ALLOC | SEC_LOAD))
                  {
                    if (_frv_osec_readonly_p (output_bfd,
                                              input_section->output_section))
                      {
                        info->callbacks->warning
                          (info,
-                          _("cannot emit fixups in read-only section"),
+                          _("cannot emit dynamic relocations in read-only section"),
                           name, input_bfd, input_section, rel->r_offset);
                        return FALSE;
                      }
-                   if (! h || h->root.type != bfd_link_hash_undefweak)
-                     _frv_add_rofixup (output_bfd,
-                                       frv_gotfixup_section (info),
+                   _frv_add_dyn_reloc (output_bfd, frv_gotrel_section (info),
                                        _bfd_elf_section_offset
                                        (output_bfd, info,
                                         input_section, rel->r_offset)
                                        + input_section->output_section->vma
-                                       + input_section->output_offset);
-                 }
-             }
-           else if ((bfd_get_section_flags (output_bfd,
-                                            input_section->output_section)
-                     & (SEC_ALLOC | SEC_LOAD)) == (SEC_ALLOC | SEC_LOAD))
-             {
-               if (_frv_osec_readonly_p (output_bfd,
-                                         input_section->output_section))
-                 {
-                   info->callbacks->warning
-                     (info,
-                      _("cannot emit dynamic relocations in read-only section"),
-                      name, input_bfd, input_section, rel->r_offset);
-                   return FALSE;
+                                       + input_section->output_offset,
+                                       r_type, dynindx, addend);
                  }
-               _frv_add_dyn_reloc (output_bfd, frv_gotrel_section (info),
-                                   _bfd_elf_section_offset
-                                   (output_bfd, info,
-                                    input_section, rel->r_offset)
-                                   + input_section->output_section->vma
-                                   + input_section->output_offset,
-                                   r_type, dynindx, addend);
              }
 
            /* We want the addend in-place because dynamic