static bfd *reldyn_sorting_bfd;
/* Nonzero if ABFD is using the N32 ABI. */
-
#define ABI_N32_P(abfd) \
((elf_elfheader (abfd)->e_flags & EF_MIPS_ABI2) != 0)
return FALSE;
}
+ /* Make sure we have a GOT to put this entry into. */
+ BFD_ASSERT (g != NULL);
+
entry.abfd = abfd;
entry.symndx = -1;
entry.d.h = (struct mips_elf_link_hash_entry *) h;
return e1->bfd == e2->bfd;
}
-/* In a multi-got link, determine the GOT to be used for IBDF. G must
+/* In a multi-got link, determine the GOT to be used for IBFD. G must
be the master GOT data. */
static struct mips_got_info *
BFD_ASSERT (bfd_get_section_by_name (abfd, ".dynamic") == NULL);
symbol = 0;
}
+ else if (ELF_MIPS_IS_OPTIONAL (h->root.other))
+ {
+ /* This is an optional symbol - an Irix specific extension to the
+ ELF spec. Ignore it for now.
+ XXX - FIXME - there is more to the spec for OPTIONAL symbols
+ than simply ignoring them, but we do not handle this for now.
+ For information see the "64-bit ELF Object File Specification"
+ which is available from here:
+ http://techpubs.sgi.com/library/manuals/4000/007-4658-001/pdf/007-4658-001.pdf */
+ symbol = 0;
+ }
else
{
if (! ((*info->callbacks->undefined_symbol)
if (h->tls_type == GOT_NORMAL
&& (! elf_hash_table(info)->dynamic_sections_created
|| (info->shared
- && (info->symbolic || h->root.dynindx == -1)
+ && (info->symbolic || h->root.forced_local)
&& h->root.def_regular)))
{
/* This is a static link or a -Bsymbolic link. The
if (gnu_local_gp_p)
symbol = gp;
-
+
/* Figure out what kind of relocation is being performed. */
switch (r_type)
{
value &= howto->dst_mask;
break;
- case R_MIPS_GNU_REL16_S2:
- value = symbol + _bfd_mips_elf_sign_extend (addend, 18) - p;
- overflowed_p = mips_elf_overflow_p (value, 18);
- value = (value >> 2) & howto->dst_mask;
- break;
-
case R_MIPS16_26:
/* The calculation for R_MIPS16_26 is just the same as for an
R_MIPS_26. It's only the storage of the relocated field into
break;
case R_MIPS_PC16:
- value = _bfd_mips_elf_sign_extend (addend, 16) + symbol - p;
- overflowed_p = mips_elf_overflow_p (value, 16);
+ case R_MIPS_GNU_REL16_S2:
+ value = symbol + _bfd_mips_elf_sign_extend (addend, 18) - p;
+ overflowed_p = mips_elf_overflow_p (value, 18);
+ value = (value >> 2) & howto->dst_mask;
break;
case R_MIPS_GOT_HI16:
/* We must now calculate the dynamic symbol table index to use
in the relocation. */
if (h != NULL
- && (! info->symbolic || !h->root.def_regular)
- /* h->root.dynindx may be -1 if this symbol was marked to
- become local. */
- && h->root.dynindx != -1)
+ && (!h->root.def_regular
+ || (info->shared && !info->symbolic && !h->root.forced_local)))
{
indx = h->root.dynindx;
if (SGI_COMPAT (output_bfd))
bfd_mips_elf_swap_options_in (abfd, (Elf_External_Options *) l,
&intopt);
+ if (intopt.size < sizeof (Elf_External_Options))
+ {
+ (*_bfd_error_handler)
+ (_("%B: Warning: bad `%s' option size %u smaller than its header"),
+ abfd, MIPS_ELF_OPTIONS_SECTION_NAME (abfd), intopt.size);
+ break;
+ }
if (ABI_64_P (abfd) && intopt.kind == ODK_REGINFO)
{
bfd_byte buf[8];
bfd_mips_elf_swap_options_in (abfd, (Elf_External_Options *) l,
&intopt);
+ if (intopt.size < sizeof (Elf_External_Options))
+ {
+ (*_bfd_error_handler)
+ (_("%B: Warning: bad `%s' option size %u smaller than its header"),
+ abfd, MIPS_ELF_OPTIONS_SECTION_NAME (abfd), intopt.size);
+ break;
+ }
if (ABI_64_P (abfd) && intopt.kind == ODK_REGINFO)
{
Elf64_Internal_RegInfo intreg;
_bfd_mips_elf_fake_sections (bfd *abfd, Elf_Internal_Shdr *hdr, asection *sec)
{
register const char *name;
+ unsigned int sh_type;
name = bfd_get_section_name (abfd, sec);
+ sh_type = hdr->sh_type;
if (strcmp (name, ".liblist") == 0)
{
hdr->sh_entsize = 8;
}
+ /* In the unlikely event a special section is empty it has to lose its
+ special meaning. This may happen e.g. when using `strip' with the
+ "--only-keep-debug" option. */
+ if (sec->size > 0 && !(sec->flags & SEC_HAS_CONTENTS))
+ hdr->sh_type = sh_type;
+
/* The generic elf_fake_sections will set up REL_HDR using the default
kind of relocations. We used to set up a second header for the
non-default kind of relocations here, but only NewABI would use
return TRUE;
}
+ /* Shared objects may have a dynamic symbol '_gp_disp' defined as
+ a SECTION *ABS*. This causes ld to think it can resolve _gp_disp
+ by setting a DT_NEEDED for the shared object. Since _gp_disp is
+ a magic symbol resolved by the linker, we ignore this bogus definition
+ of _gp_disp. New ABI objects do not suffer from this problem so this
+ is not done for them. */
+ if (!NEWABI_P(abfd)
+ && (sym->st_shndx == SHN_ABS)
+ && (strcmp (*namep, "_gp_disp") == 0))
+ {
+ *namep = NULL;
+ return TRUE;
+ }
+
switch (sym->st_shndx)
{
case SHN_COMMON:
h = ((struct mips_elf_link_hash_entry *)
sym_hashes[r_symndx - extsymoff]);
+ while (h->root.root.type == bfd_link_hash_indirect
+ || h->root.root.type == bfd_link_hash_warning)
+ h = (struct mips_elf_link_hash_entry *) h->root.root.u.i.link;
+
/* H is the symbol this stub is for. */
h->fn_stub = sec;
case R_MIPS_GOT_PAGE:
case R_MIPS_GOT_OFST:
case R_MIPS_GOT_DISP:
+ case R_MIPS_TLS_GOTTPREL:
case R_MIPS_TLS_GD:
case R_MIPS_TLS_LDM:
if (dynobj == NULL)
for (s = dynobj->sections; s != NULL; s = s->next)
{
const char *name;
- bfd_boolean strip;
/* It's OK to base decisions on the section name, because none
of the dynobj section names depend upon the input files. */
if ((s->flags & SEC_LINKER_CREATED) == 0)
continue;
- strip = FALSE;
-
if (strncmp (name, ".rel", 4) == 0)
{
- if (s->size == 0)
- {
- /* We only strip the section if the output section name
- has the same name. Otherwise, there might be several
- input sections for this output section. FIXME: This
- code is probably not needed these days anyhow, since
- the linker now does not create empty output sections. */
- if (s->output_section != NULL
- && strcmp (name,
- bfd_get_section_name (s->output_section->owner,
- s->output_section)) == 0)
- strip = TRUE;
- }
- else
+ if (s->size != 0)
{
const char *outname;
asection *target;
continue;
}
- if (strip)
+ if (s->size == 0)
{
s->flags |= SEC_EXCLUDE;
continue;
}
+ if ((s->flags & SEC_HAS_CONTENTS) == 0)
+ continue;
+
/* Allocate memory for the section contents. */
s->contents = bfd_zalloc (dynobj, s->size);
- if (s->contents == NULL && s->size != 0)
+ if (s->contents == NULL)
{
bfd_set_error (bfd_error_no_memory);
return FALSE;
for (rel = relocs; rel < relend; ++rel)
{
const char *name;
- bfd_vma value;
+ bfd_vma value = 0;
reloc_howto_type *howto;
bfd_boolean require_jalx;
/* TRUE if the relocation is a RELA relocation, rather than a
MIPS_ELF_STUB_SECTION_NAME (dynobj));
BFD_ASSERT (s != NULL);
- /* FIXME: Can h->dynindex be more than 64K? */
+ /* FIXME: Can h->dynindx be more than 64K? */
if (h->dynindx & 0xffff0000)
return FALSE;
break;
case DT_MIPS_TIME_STAMP:
- time ((time_t *) &dyn.d_un.d_val);
+ {
+ time_t t;
+ time (&t);
+ dyn.d_un.d_val = t;
+ }
break;
case DT_MIPS_ICHECKSUM:
dyn.d_un.d_ptr = s->vma;
break;
- case DT_RELSZ:
- /* Reduce DT_RELSZ to account for any relocations we
- decided not to make. This is for the n64 irix rld,
- which doesn't seem to apply any relocations if there
- are trailing null entries. */
- s = mips_elf_rel_dyn_section (dynobj, FALSE);
- dyn.d_un.d_val = (s->reloc_count
- * (ABI_64_P (output_bfd)
- ? sizeof (Elf64_Mips_External_Rel)
- : sizeof (Elf32_External_Rel)));
- break;
-
default:
swap_out_p = FALSE;
break;
}
}
+ /* The generation of dynamic relocations for the non-primary gots
+ adds more dynamic relocations. We cannot count them until
+ here. */
+
+ if (elf_hash_table (info)->dynamic_sections_created)
+ {
+ bfd_byte *b;
+ bfd_boolean swap_out_p;
+
+ BFD_ASSERT (sdyn != NULL);
+
+ for (b = sdyn->contents;
+ b < sdyn->contents + sdyn->size;
+ b += MIPS_ELF_DYN_SIZE (dynobj))
+ {
+ Elf_Internal_Dyn dyn;
+ asection *s;
+
+ /* Read in the current dynamic entry. */
+ (*get_elf_backend_data (dynobj)->s->swap_dyn_in) (dynobj, b, &dyn);
+
+ /* Assume that we're going to modify it and write it out. */
+ swap_out_p = TRUE;
+
+ switch (dyn.d_tag)
+ {
+ case DT_RELSZ:
+ /* Reduce DT_RELSZ to account for any relocations we
+ decided not to make. This is for the n64 irix rld,
+ which doesn't seem to apply any relocations if there
+ are trailing null entries. */
+ s = mips_elf_rel_dyn_section (dynobj, FALSE);
+ dyn.d_un.d_val = (s->reloc_count
+ * (ABI_64_P (output_bfd)
+ ? sizeof (Elf64_Mips_External_Rel)
+ : sizeof (Elf32_External_Rel)));
+ break;
+
+ default:
+ swap_out_p = FALSE;
+ break;
+ }
+
+ if (swap_out_p)
+ (*get_elf_backend_data (dynobj)->s->swap_dyn_out)
+ (dynobj, &dyn, b);
+ }
+ }
+
{
asection *s;
Elf32_compact_rel cpt;
_bfd_elf_link_hash_copy_indirect copy the flags for us. */
void
-_bfd_mips_elf_copy_indirect_symbol (const struct elf_backend_data *bed,
+_bfd_mips_elf_copy_indirect_symbol (struct bfd_link_info *info,
struct elf_link_hash_entry *dir,
struct elf_link_hash_entry *ind)
{
struct mips_elf_link_hash_entry *dirmips, *indmips;
- _bfd_elf_link_hash_copy_indirect (bed, dir, ind);
+ _bfd_elf_link_hash_copy_indirect (info, dir, ind);
if (ind->root.type != bfd_link_hash_indirect)
return;
if (dirmips->tls_type == 0)
dirmips->tls_type = indmips->tls_type;
- else
- BFD_ASSERT (indmips->tls_type == 0);
}
void
h->forced_local = force_local;
dynobj = elf_hash_table (info)->dynobj;
- if (dynobj != NULL && force_local && h->root.type != STT_TLS)
+ if (dynobj != NULL && force_local && h->root.type != STT_TLS
+ && (got = mips_elf_got_section (dynobj, FALSE)) != NULL
+ && (g = mips_elf_section_data (got)->u.got_info) != NULL)
{
- got = mips_elf_got_section (dynobj, FALSE);
- g = mips_elf_section_data (got)->u.got_info;
-
if (g->next)
{
struct mips_got_entry e;
input_section, relocatable,
data, gp);
else
- r = bfd_perform_relocation (input_bfd, *parent, data,
+ r = bfd_perform_relocation (input_bfd, *parent, data,
input_section,
relocatable ? abfd : NULL,
&error_message);
case bfd_reloc_undefined:
if (!((*link_info->callbacks->undefined_symbol)
(link_info, bfd_asymbol_name (*(*parent)->sym_ptr_ptr),
- input_bfd, input_section, (*parent)->address,
- TRUE)))
+ input_bfd, input_section, (*parent)->address, TRUE)))
goto error_return;
break;
case bfd_reloc_dangerous:
&& !(*bed->elf_backend_omit_section_dynsym) (abfd, info, p))
++ dynsecsymcount;
}
-
+
if (! mips_elf_sort_hash_table (info, dynsecsymcount + 1))
return FALSE;
{
size_t i;
- for (i = 0; extension != base && i < ARRAY_SIZE (mips_mach_extensions); i++)
+ if (extension == base)
+ return TRUE;
+
+ if (base == bfd_mach_mipsisa32
+ && mips_mach_extends_p (bfd_mach_mipsisa64, extension))
+ return TRUE;
+
+ if (base == bfd_mach_mipsisa32r2
+ && mips_mach_extends_p (bfd_mach_mipsisa64r2, extension))
+ return TRUE;
+
+ for (i = 0; i < ARRAY_SIZE (mips_mach_extensions); i++)
if (extension == mips_mach_extensions[i].extension)
- extension = mips_mach_extensions[i].base;
+ {
+ extension = mips_mach_extensions[i].base;
+ if (extension == base)
+ return TRUE;
+ }
- return extension == base;
+ return FALSE;
}
return TRUE;
}
-static struct bfd_elf_special_section const
- mips_special_sections_l[]=
+const struct bfd_elf_special_section _bfd_mips_elf_special_sections[] =
{
{ ".lit4", 5, 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_MIPS_GPREL },
{ ".lit8", 5, 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_MIPS_GPREL },
- { NULL, 0, 0, 0, 0 }
-};
-
-static struct bfd_elf_special_section const
- mips_special_sections_m[]=
-{
{ ".mdebug", 7, 0, SHT_MIPS_DEBUG, 0 },
- { NULL, 0, 0, 0, 0 }
-};
-
-static struct bfd_elf_special_section const
- mips_special_sections_s[]=
-{
- { ".sdata", 6, -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_MIPS_GPREL },
{ ".sbss", 5, -2, SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_MIPS_GPREL },
-};
-
-static struct bfd_elf_special_section const
- mips_special_sections_u[]=
-{
+ { ".sdata", 6, -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_MIPS_GPREL },
{ ".ucode", 6, 0, SHT_MIPS_UCODE, 0 },
{ NULL, 0, 0, 0, 0 }
};
-struct bfd_elf_special_section const *
- _bfd_mips_elf_special_sections[27] =
-{
- NULL, /* 'a' */
- NULL, /* 'b' */
- NULL, /* 'c' */
- NULL, /* 'd' */
- NULL, /* 'e' */
- NULL, /* 'f' */
- NULL, /* 'g' */
- NULL, /* 'h' */
- NULL, /* 'i' */
- NULL, /* 'j' */
- NULL, /* 'k' */
- mips_special_sections_l, /* 'l' */
- mips_special_sections_m, /* 'm' */
- NULL, /* 'n' */
- NULL, /* 'o' */
- NULL, /* 'p' */
- NULL, /* 'q' */
- NULL, /* 'r' */
- mips_special_sections_s, /* 'm' */
- NULL, /* 't' */
- mips_special_sections_u, /* 'u' */
- NULL, /* 'v' */
- NULL, /* 'w' */
- NULL, /* 'x' */
- NULL, /* 'y' */
- NULL, /* 'z' */
- NULL /* other */
-};
+/* Ensure that the STO_OPTIONAL flag is copied into h->other,
+ even if this is not a defintion of the symbol. */
+void
+_bfd_mips_elf_merge_symbol_attribute (struct elf_link_hash_entry *h,
+ const Elf_Internal_Sym *isym,
+ bfd_boolean definition,
+ bfd_boolean dynamic ATTRIBUTE_UNUSED)
+{
+ if (! definition
+ && ELF_MIPS_IS_OPTIONAL (isym->st_other))
+ h->other |= STO_OPTIONAL;
+}
+
+/* Decide whether an undefined symbol is special and can be ignored.
+ This is the case for OPTIONAL symbols on IRIX. */
+bfd_boolean
+_bfd_mips_elf_ignore_undef_symbol (struct elf_link_hash_entry *h)
+{
+ return ELF_MIPS_IS_OPTIONAL (h->other) ? TRUE : FALSE;
+}