struct elf_link_hash_entry **sym_hashes;
const Elf_Internal_Rela *rel;
const Elf_Internal_Rela *rel_end;
- property_table_entry *lit_table;
- int ltblsize;
if (info->relocatable)
return TRUE;
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
sym_hashes = elf_sym_hashes (abfd);
- ltblsize = xtensa_read_table_entries (abfd, sec, &lit_table,
- XTENSA_LIT_SEC_NAME);
- if (ltblsize < 0)
- return FALSE;
-
rel_end = relocs + sec->reloc_count;
for (rel = relocs; rel < rel_end; rel++)
{
if ((sec->flags & SEC_ALLOC) != 0)
{
- if ((sec->flags & SEC_READONLY) != 0
- && !elf_xtensa_in_literal_pool (lit_table, ltblsize,
- sec->vma + rel->r_offset))
- h->elf_link_hash_flags |= ELF_LINK_NON_GOT_REF;
-
if (h->got.refcount <= 0)
h->got.refcount = 1;
else
if ((sec->flags & SEC_ALLOC) != 0)
{
- if ((sec->flags & SEC_READONLY) != 0
- && !elf_xtensa_in_literal_pool (lit_table, ltblsize,
- sec->vma + rel->r_offset))
- h->elf_link_hash_flags |= ELF_LINK_NON_GOT_REF;
-
if (h->plt.refcount <= 0)
{
h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
elf_local_got_refcounts (abfd) = local_got_refcounts;
}
local_got_refcounts[r_symndx] += 1;
-
- /* If the relocation is not inside the GOT, the DF_TEXTREL
- flag needs to be set. */
- if (info->shared
- && (sec->flags & SEC_READONLY) != 0
- && !elf_xtensa_in_literal_pool (lit_table, ltblsize,
- sec->vma + rel->r_offset))
- info->flags |= DF_TEXTREL;
}
break;
case R_XTENSA_GNU_VTINHERIT:
/* This relocation describes the C++ object vtable hierarchy.
Reconstruct it for later use during GC. */
- if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
+ if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
return FALSE;
break;
case R_XTENSA_GNU_VTENTRY:
/* This relocation describes which C++ vtable entries are actually
used. Record for later use during GC. */
- if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend))
+ if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
return FALSE;
break;
}
}
- free (lit_table);
return TRUE;
}
else
{
/* Don't need any dynamic relocations at all. */
- h->elf_link_hash_flags &= ~ELF_LINK_NON_GOT_REF;
h->plt.refcount = 0;
h->got.refcount = 0;
}
if (! xtensa_elf_dynamic_symbol_p (h, info))
elf_xtensa_make_sym_local (info, h);
- /* If the symbol has a relocation outside the GOT, set the
- DF_TEXTREL flag. */
- if ((h->elf_link_hash_flags & ELF_LINK_NON_GOT_REF) != 0)
- info->flags |= DF_TEXTREL;
-
return TRUE;
}
the .dynamic section. The DT_DEBUG entry is filled in by the
dynamic linker and used by the debugger. */
#define add_dynamic_entry(TAG, VAL) \
- bfd_elf32_add_dynamic_entry (info, (bfd_vma) (TAG), (bfd_vma) (VAL))
+ _bfd_elf_add_dynamic_entry (info, TAG, VAL)
if (! info->shared)
{
return FALSE;
}
- if ((info->flags & DF_TEXTREL) != 0)
- {
- if (!add_dynamic_entry (DT_TEXTREL, 0))
- return FALSE;
- }
-
if (!add_dynamic_entry (DT_XTENSA_GOT_LOC_OFF, 0)
|| !add_dynamic_entry (DT_XTENSA_GOT_LOC_SZ, 0))
return FALSE;
struct elf_link_hash_entry **sym_hashes;
asection *srelgot, *srelplt;
bfd *dynobj;
+ property_table_entry *lit_table = 0;
+ int ltblsize = 0;
char *error_message = NULL;
if (xtensa_default_isa == NULL)
srelplt = bfd_get_section_by_name (dynobj, ".rela.plt");
}
+ if (elf_hash_table (info)->dynamic_sections_created)
+ {
+ ltblsize = xtensa_read_table_entries (input_bfd, input_section,
+ &lit_table, XTENSA_LIT_SEC_NAME);
+ if (ltblsize < 0)
+ return FALSE;
+ }
+
rel = relocs;
relend = relocs + input_section->reloc_count;
for (; rel < relend; rel++)
outrel.r_offset += (input_section->output_section->vma
+ input_section->output_offset);
+ /* Complain if the relocation is in a read-only section
+ and not in a literal pool. */
+ if ((input_section->flags & SEC_READONLY) != 0
+ && !elf_xtensa_in_literal_pool (lit_table, ltblsize,
+ input_section->vma
+ + rel->r_offset))
+ {
+ error_message =
+ _("dynamic relocation in read-only section");
+ if (!((*info->callbacks->reloc_dangerous)
+ (info, error_message, input_bfd, input_section,
+ rel->r_offset)))
+ return FALSE;
+ }
+
if (dynamic_symbol)
{
outrel.r_addend = rel->r_addend;
}
}
+ if (lit_table)
+ free (lit_table);
+
return TRUE;
}
while (cookie->rel < cookie->relend
&& cookie->rel->r_offset == offset)
{
- if (_bfd_elf32_reloc_symbol_deleted_p (offset, cookie))
+ if (bfd_elf_reloc_symbol_deleted_p (offset, cookie))
{
/* Remove the table entry. (If the reloc type is NONE, then
the entry has already been merged with another and deleted
static bfd_boolean is_same_value
- PARAMS ((const literal_value *, const literal_value *));
+ PARAMS ((const literal_value *, const literal_value *, bfd_boolean));
static value_map_hash_table *value_map_hash_table_init
PARAMS ((void));
static unsigned hash_literal_value
static unsigned hash_bfd_vma
PARAMS ((bfd_vma));
static value_map *get_cached_value
- PARAMS ((value_map_hash_table *, const literal_value *));
+ PARAMS ((value_map_hash_table *, const literal_value *, bfd_boolean));
static value_map *add_value_map
- PARAMS ((value_map_hash_table *, const literal_value *, const r_reloc *));
+ PARAMS ((value_map_hash_table *, const literal_value *, const r_reloc *,
+ bfd_boolean));
static bfd_boolean
-is_same_value (src1, src2)
+is_same_value (src1, src2, final_static_link)
const literal_value *src1;
const literal_value *src2;
+ bfd_boolean final_static_link;
{
+ struct elf_link_hash_entry *h1, *h2;
+
if (r_reloc_is_const (&src1->r_rel) != r_reloc_is_const (&src2->r_rel))
return FALSE;
if (src1->value != src2->value)
return FALSE;
- /* Now check for the same section and the same elf_hash. */
- if (r_reloc_is_defined (&src1->r_rel))
+ /* Now check for the same section (if defined) or the same elf_hash
+ (if undefined or weak). */
+ h1 = r_reloc_get_hash_entry (&src1->r_rel);
+ h2 = r_reloc_get_hash_entry (&src2->r_rel);
+ if (r_reloc_is_defined (&src1->r_rel)
+ && (final_static_link
+ || ((!h1 || h1->root.type != bfd_link_hash_defweak)
+ && (!h2 || h2->root.type != bfd_link_hash_defweak))))
{
if (r_reloc_get_section (&src1->r_rel)
!= r_reloc_get_section (&src2->r_rel))
}
else
{
- if (r_reloc_get_hash_entry (&src1->r_rel)
- != r_reloc_get_hash_entry (&src2->r_rel))
- return FALSE;
-
- if (r_reloc_get_hash_entry (&src1->r_rel) == 0)
+ /* Require that the hash entries (i.e., symbols) be identical. */
+ if (h1 != h2 || h1 == 0)
return FALSE;
}
/* Check if the specified literal_value has been seen before. */
static value_map *
-get_cached_value (map, val)
+get_cached_value (map, val, final_static_link)
value_map_hash_table *map;
const literal_value *val;
+ bfd_boolean final_static_link;
{
value_map *map_e;
value_map *bucket;
bucket = map->buckets[idx];
for (map_e = bucket; map_e; map_e = map_e->next)
{
- if (is_same_value (&map_e->val, val))
+ if (is_same_value (&map_e->val, val, final_static_link))
return map_e;
}
return NULL;
already has an entry here. */
static value_map *
-add_value_map (map, val, loc)
+add_value_map (map, val, loc, final_static_link)
value_map_hash_table *map;
const literal_value *val;
const r_reloc *loc;
+ bfd_boolean final_static_link;
{
value_map **bucket_p;
unsigned idx;
value_map *val_e = (value_map *) bfd_zmalloc (sizeof (value_map));
- BFD_ASSERT (get_cached_value (map, val) == NULL);
+ BFD_ASSERT (get_cached_value (map, val, final_static_link) == NULL);
val_e->val = *val;
val_e->loc = *loc;
bfd_byte *contents;
Elf_Internal_Rela *internal_relocs;
source_reloc *src_relocs;
+ bfd_boolean final_static_link;
bfd_boolean ok = TRUE;
int i;
goto error_return;
}
+ final_static_link =
+ (!link_info->relocatable
+ && !elf_hash_table (link_info)->dynamic_sections_created);
+
/* Sort the source_relocs by target offset. */
src_relocs = relax_info->src_relocs;
qsort (src_relocs, relax_info->src_count,
val.value = bfd_get_32 (abfd, contents + rel->r_rel.target_offset);
/* Check if we've seen another literal with the same value. */
- val_map = get_cached_value (values, &val);
+ val_map = get_cached_value (values, &val, final_static_link);
if (val_map != NULL)
{
/* First check that THIS and all the other relocs to this
{
/* This is the first time we've seen this literal value. */
BFD_ASSERT (sec == r_reloc_get_section (&rel->r_rel));
- add_value_map (values, &val, &rel->r_rel);
+ add_value_map (values, &val, &rel->r_rel, final_static_link);
}
}
#define elf_info_to_howto elf_xtensa_info_to_howto_rela
-#define bfd_elf32_bfd_final_link bfd_elf32_bfd_final_link
#define bfd_elf32_bfd_merge_private_bfd_data elf_xtensa_merge_private_bfd_data
#define bfd_elf32_new_section_hook elf_xtensa_new_section_hook
#define bfd_elf32_bfd_print_private_bfd_data elf_xtensa_print_private_bfd_data