* elf.c (rewrite_elf_program_header): Don't wrap p_paddr to
[deliverable/binutils-gdb.git] / bfd / elfxx-mips.c
index fabae69cdf34e4c20e2349a2451ebbcb32cc8060..827915caa9e1eca40e8d7be612cff547f5d8fb4f 100644 (file)
@@ -4099,12 +4099,12 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
   bfd_vma symbol = 0;
   /* The final GP value to be used for the relocatable, executable, or
      shared object file being produced.  */
-  bfd_vma gp = MINUS_ONE;
+  bfd_vma gp;
   /* The place (section offset or address) of the storage unit being
      relocated.  */
   bfd_vma p;
   /* The value of GP used to create the relocatable object.  */
-  bfd_vma gp0 = MINUS_ONE;
+  bfd_vma gp0;
   /* The offset into the global offset table at which the address of
      the relocation entry symbol, adjusted by the addend, resides
      during execution.  */
@@ -4367,8 +4367,17 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
   local_p = mips_elf_local_relocation_p (input_bfd, relocation,
                                         local_sections, TRUE);
 
-  /* If we haven't already determined the GOT offset, or the GP value,
-     and we're going to need it, get it now.  */
+  gp0 = _bfd_get_gp_value (input_bfd);
+  gp = _bfd_get_gp_value (abfd);
+  if (dynobj)
+    gp += mips_elf_adjust_gp (abfd, mips_elf_got_info (dynobj, NULL),
+                             input_bfd);
+
+  if (gnu_local_gp_p)
+    symbol = gp;
+
+  /* If we haven't already determined the GOT offset, oand we're going
+     to need it, get it now.  */
   switch (r_type)
     {
     case R_MIPS_GOT_PAGE:
@@ -4449,29 +4458,8 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
       /* Convert GOT indices to actual offsets.  */
       g = mips_elf_got_offset_from_index (dynobj, abfd, input_bfd, g);
       break;
-
-    case R_MIPS_HI16:
-    case R_MIPS_LO16:
-    case R_MIPS_GPREL16:
-    case R_MIPS_GPREL32:
-    case R_MIPS_LITERAL:
-    case R_MIPS16_HI16:
-    case R_MIPS16_LO16:
-    case R_MIPS16_GPREL:
-      gp0 = _bfd_get_gp_value (input_bfd);
-      gp = _bfd_get_gp_value (abfd);
-      if (dynobj)
-       gp += mips_elf_adjust_gp (abfd, mips_elf_got_info (dynobj, NULL),
-                                 input_bfd);
-      break;
-
-    default:
-      break;
     }
 
-  if (gnu_local_gp_p)
-    symbol = gp;
-
   /* Relocations against the VxWorks __GOTT_BASE__ and __GOTT_INDEX__
      symbols are resolved by the loader.  Add them to .rela.dyn.  */
   if (h != NULL && is_gott_symbol (info, &h->root))
@@ -4521,6 +4509,9 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
               && h->root.def_dynamic
               && !h->root.def_regular))
          && r_symndx != 0
+         && (h == NULL
+             || h->root.root.type != bfd_link_hash_undefweak
+             || ELF_ST_VISIBILITY (h->root.other) == STV_DEFAULT)
          && (input_section->flags & SEC_ALLOC) != 0)
        {
          /* If we're creating a shared library, or this relocation is
@@ -7020,7 +7011,7 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
                  if (sreloc == NULL)
                    return FALSE;
                }
-             if (info->shared)
+             if (info->shared && h == NULL)
                {
                  /* When creating a shared object, we must copy these
                     reloc types into the output file as R_MIPS_REL32
@@ -7035,8 +7026,17 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
                {
                  struct mips_elf_link_hash_entry *hmips;
 
-                 /* We only need to copy this reloc if the symbol is
-                     defined in a dynamic object.  */
+                 /* For a shared object, we must copy this relocation
+                    unless the symbol turns out to be undefined and
+                    weak with non-default visibility, in which case
+                    it will be left as zero.
+
+                    We could elide R_MIPS_REL32 for locally binding symbols
+                    in shared libraries, but do not yet do so.
+
+                    For an executable, we only need to copy this
+                    reloc if the symbol is defined in a dynamic
+                    object.  */
                  hmips = (struct mips_elf_link_hash_entry *) h;
                  ++hmips->possibly_dynamic_relocs;
                  if (MIPS_ELF_READONLY_SECTION (sec))
@@ -7301,6 +7301,66 @@ _bfd_mips_relax_section (bfd *abfd, asection *sec,
   return FALSE;
 }
 \f
+/* Allocate space for global sym dynamic relocs.  */
+
+static bfd_boolean
+allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
+{
+  struct bfd_link_info *info = inf;
+  bfd *dynobj;
+  struct mips_elf_link_hash_entry *hmips;
+  struct mips_elf_link_hash_table *htab;
+
+  htab = mips_elf_hash_table (info);
+  dynobj = elf_hash_table (info)->dynobj;
+  hmips = (struct mips_elf_link_hash_entry *) h;
+
+  /* VxWorks executables are handled elsewhere; we only need to
+     allocate relocations in shared objects.  */
+  if (htab->is_vxworks && !info->shared)
+    return TRUE;
+
+  /* If this symbol is defined in a dynamic object, or we are creating
+     a shared library, we will need to copy any R_MIPS_32 or
+     R_MIPS_REL32 relocs against it into the output file.  */
+  if (! info->relocatable
+      && hmips->possibly_dynamic_relocs != 0
+      && (h->root.type == bfd_link_hash_defweak
+         || !h->def_regular
+         || info->shared))
+    {
+      bfd_boolean do_copy = TRUE;
+
+      if (h->root.type == bfd_link_hash_undefweak)
+       {
+         /* Do not copy relocations for undefined weak symbols with
+            non-default visibility.  */
+         if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
+           do_copy = FALSE;
+
+         /* Make sure undefined weak symbols are output as a dynamic
+            symbol in PIEs.  */
+         else if (h->dynindx == -1 && !h->forced_local)
+           {
+             if (! bfd_elf_link_record_dynamic_symbol (info, h))
+               return FALSE;
+           }
+       }
+
+      if (do_copy)
+       {
+         mips_elf_allocate_dynamic_relocations
+           (dynobj, info, hmips->possibly_dynamic_relocs);
+         if (hmips->readonly_reloc)
+           /* We tell the dynamic linker that there are relocations
+              against the text segment.  */
+           info->flags |= DF_TEXTREL;
+       }
+    }
+
+  return TRUE;
+}
+
 /* Adjust a symbol defined by a dynamic object and referenced by a
    regular object.  The current definition is in some section of the
    dynamic object, but we're not including those sections.  We have to
@@ -7327,22 +7387,7 @@ _bfd_mips_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
                      && h->ref_regular
                      && !h->def_regular)));
 
-  /* If this symbol is defined in a dynamic object, we need to copy
-     any R_MIPS_32 or R_MIPS_REL32 relocs against it into the output
-     file.  */
   hmips = (struct mips_elf_link_hash_entry *) h;
-  if (! info->relocatable
-      && hmips->possibly_dynamic_relocs != 0
-      && (h->root.type == bfd_link_hash_defweak
-         || !h->def_regular))
-    {
-      mips_elf_allocate_dynamic_relocations
-       (dynobj, info, hmips->possibly_dynamic_relocs);
-      if (hmips->readonly_reloc)
-       /* We tell the dynamic linker that there are relocations
-          against the text segment.  */
-       info->flags |= DF_TEXTREL;
-    }
 
   /* For a function, create a stub, if allowed.  */
   if (! hmips->no_fn_stub
@@ -7736,6 +7781,9 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_bfd,
        }
     }
 
+  /* Allocate space for global sym dynamic relocs.  */
+  elf_link_hash_traverse (&htab->root, allocate_dynrelocs, (PTR) info);
+
   /* The check_relocs and adjust_dynamic_symbol entry points have
      determined the sizes of the various dynamic sections.  Allocate
      memory for them.  */
This page took 0.026614 seconds and 4 git commands to generate.