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. */
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:
/* 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))
&& 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
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
{
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))
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
&& 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
}
}
+ /* 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. */