* elf.c (rewrite_elf_program_header): Don't wrap p_paddr to
[deliverable/binutils-gdb.git] / bfd / elfxx-mips.c
index b71d08fc0a77c07cfa191458d6c95e5a5d0545ae..827915caa9e1eca40e8d7be612cff547f5d8fb4f 100644 (file)
@@ -1172,7 +1172,7 @@ mips_elf_check_mips16_stubs (struct mips_elf_link_hash_entry *h,
     }
 
   if (h->call_stub != NULL
-      && h->root.other == STO_MIPS16)
+      && ELF_ST_IS_MIPS16 (h->root.other))
     {
       /* We don't need the call_stub; this is a 16 bit function, so
          calls from other 16 bit functions are OK.  Clobber the size
@@ -1184,7 +1184,7 @@ mips_elf_check_mips16_stubs (struct mips_elf_link_hash_entry *h,
     }
 
   if (h->call_fp_stub != NULL
-      && h->root.other == STO_MIPS16)
+      && ELF_ST_IS_MIPS16 (h->root.other))
     {
       /* We don't need the call_stub; this is a 16 bit function, so
          calls from other 16 bit functions are OK.  Clobber the size
@@ -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.  */
@@ -4182,7 +4182,7 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
        }
 
       /* MIPS16 text labels should be treated as odd.  */
-      if (sym->st_other == STO_MIPS16)
+      if (ELF_ST_IS_MIPS16 (sym->st_other))
        ++symbol;
 
       /* Record the name of this symbol, for our caller.  */
@@ -4192,7 +4192,7 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
       if (*namep == '\0')
        *namep = bfd_section_name (input_bfd, sec);
 
-      target_is_16_bit_code_p = (sym->st_other == STO_MIPS16);
+      target_is_16_bit_code_p = ELF_ST_IS_MIPS16 (sym->st_other);
     }
   else
     {
@@ -4288,7 +4288,7 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
          symbol = 0;
        }
 
-      target_is_16_bit_code_p = (h->root.other == STO_MIPS16);
+      target_is_16_bit_code_p = ELF_ST_IS_MIPS16 (h->root.other);
     }
 
   /* If this is a 32- or 64-bit call to a 16-bit function with a stub, we
@@ -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
@@ -5702,7 +5693,7 @@ _bfd_mips_elf_section_from_shdr (bfd *abfd,
       break;
     case SHT_MIPS_DWARF:
       if (! CONST_STRNEQ (name, ".debug_")
-          && ! CONST_STRNEQ (name, ".zdebug_")
+          && ! CONST_STRNEQ (name, ".zdebug_"))
        return FALSE;
       break;
     case SHT_MIPS_SYMBOL_LIB:
@@ -6121,7 +6112,7 @@ _bfd_mips_elf_add_symbol_hook (bfd *abfd, struct bfd_link_info *info,
   /* If this is a mips16 text symbol, add 1 to the value to make it
      odd.  This will cause something like .word SYM to come up with
      the right value when it is loaded into the PC.  */
-  if (sym->st_other == STO_MIPS16)
+  if (ELF_ST_IS_MIPS16 (sym->st_other))
     ++*valp;
 
   return TRUE;
@@ -6144,7 +6135,7 @@ _bfd_mips_elf_link_output_symbol_hook
       && strcmp (input_sec->name, ".scommon") == 0)
     sym->st_shndx = SHN_MIPS_SCOMMON;
 
-  if (sym->st_other == STO_MIPS16)
+  if (ELF_ST_IS_MIPS16 (sym->st_other))
     sym->st_value &= ~1;
 
   return TRUE;
@@ -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.  */
@@ -8721,7 +8769,7 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd *output_bfd,
     }
 
   /* If this is a mips16 symbol, force the value to be even.  */
-  if (sym->st_other == STO_MIPS16)
+  if (ELF_ST_IS_MIPS16 (sym->st_other))
     sym->st_value &= ~1;
 
   return TRUE;
@@ -8893,7 +8941,7 @@ _bfd_mips_vxworks_finish_dynamic_symbol (bfd *output_bfd,
     }
 
   /* If this is a mips16 symbol, force the value to be even.  */
-  if (sym->st_other == STO_MIPS16)
+  if (ELF_ST_IS_MIPS16 (sym->st_other))
     sym->st_value &= ~1;
 
   return TRUE;
This page took 0.028967 seconds and 4 git commands to generate.