/* Xtensa-specific support for 32-bit ELF.
- Copyright (C) 2003-2017 Free Software Foundation, Inc.
+ Copyright (C) 2003-2019 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
int elf32xtensa_no_literal_movement = 1;
+/* Place property records for a section into individual property section
+ with xt.prop. prefix. */
+
+bfd_boolean elf32xtensa_separate_props = FALSE;
+
/* Rename one of the generic section flags to better document how it
is used here. */
/* Whether relocations have been processed. */
/* GNU extension to record C++ vtable hierarchy. */
HOWTO (R_XTENSA_GNU_VTINHERIT, 0, 2, 0, FALSE, 0, complain_overflow_dont,
- NULL, "R_XTENSA_GNU_VTINHERIT",
+ NULL, "R_XTENSA_GNU_VTINHERIT",
FALSE, 0, 0, FALSE),
/* GNU extension to record C++ vtable member usage. */
HOWTO (R_XTENSA_GNU_VTENTRY, 0, 2, 0, FALSE, 0, complain_overflow_dont,
- _bfd_elf_rel_vtable_reloc_fn, "R_XTENSA_GNU_VTENTRY",
+ _bfd_elf_rel_vtable_reloc_fn, "R_XTENSA_GNU_VTENTRY",
FALSE, 0, 0, FALSE),
/* Relocations for supporting difference of symbols. */
break;
}
+ /* xgettext:c-format */
+ _bfd_error_handler (_("%pB: unsupported relocation type %#x"), abfd, (int) code);
+ bfd_set_error (bfd_error_bad_value);
TRACE ("Unknown");
return NULL;
}
/* Given an ELF "rela" relocation, find the corresponding howto and record
it in the BFD internal arelent representation of the relocation. */
-static void
-elf_xtensa_info_to_howto_rela (bfd *abfd ATTRIBUTE_UNUSED,
+static bfd_boolean
+elf_xtensa_info_to_howto_rela (bfd *abfd,
arelent *cache_ptr,
Elf_Internal_Rela *dst)
{
if (r_type >= (unsigned int) R_XTENSA_max)
{
/* xgettext:c-format */
- _bfd_error_handler (_("%B: invalid XTENSA reloc number: %d"), abfd, r_type);
- r_type = 0;
+ _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
+ abfd, r_type);
+ bfd_set_error (bfd_error_bad_value);
+ return FALSE;
}
cache_ptr->howto = &elf_howto_table[r_type];
+ return TRUE;
}
\f
section. Sets TABLE_P and returns the number of entries. On
error, returns a negative value. */
-static int
+int
xtensa_read_table_entries (bfd *abfd,
asection *section,
property_table_entry **table_p,
property_table_compare);
/* Check that the table contents are valid. Problems may occur,
- for example, if an unrelocated object file is stripped. */
+ for example, if an unrelocated object file is stripped. */
for (blk = 1; blk < block_count; blk++)
{
/* The only circumstance where two entries may legitimately
blocks[blk - 1].size != 0)
{
/* xgettext:c-format */
- _bfd_error_handler (_("%B(%A): invalid property table"),
+ _bfd_error_handler (_("%pB(%pA): invalid property table"),
abfd, section);
bfd_set_error (bfd_error_bad_value);
free (blocks);
if (r_symndx >= NUM_SHDR_ENTRIES (symtab_hdr))
{
/* xgettext:c-format */
- _bfd_error_handler (_("%B: bad symbol index: %d"),
+ _bfd_error_handler (_("%pB: bad symbol index: %d"),
abfd, r_symndx);
return FALSE;
}
while (h->root.type == bfd_link_hash_indirect
|| h->root.type == bfd_link_hash_warning)
h = (struct elf_link_hash_entry *) h->root.u.i.link;
-
- /* PR15323, ref flags aren't set for references in the same
- object. */
- h->root.non_ir_ref_regular = 1;
}
eh = elf_xtensa_hash_entry (h);
{
_bfd_error_handler
/* xgettext:c-format */
- (_("%B: `%s' accessed both as normal and thread local symbol"),
+ (_("%pB: `%s' accessed both as normal and thread local symbol"),
abfd,
h ? h->root.root.string : "<local>");
return FALSE;
static void
elf_xtensa_make_sym_local (struct bfd_link_info *info,
- struct elf_link_hash_entry *h)
+ struct elf_link_hash_entry *h)
{
if (bfd_link_pic (info))
{
if (h->plt.refcount > 0)
- {
+ {
/* For shared objects, there's no need for PLT entries for local
symbols (use RELATIVE relocs instead of JMP_SLOT relocs). */
- if (h->got.refcount < 0)
- h->got.refcount = 0;
- h->got.refcount += h->plt.refcount;
- h->plt.refcount = 0;
- }
+ if (h->got.refcount < 0)
+ h->got.refcount = 0;
+ h->got.refcount += h->plt.refcount;
+ h->plt.refcount = 0;
+ }
}
else
{
static void
elf_xtensa_hide_symbol (struct bfd_link_info *info,
- struct elf_link_hash_entry *h,
- bfd_boolean force_local)
+ struct elf_link_hash_entry *h,
+ bfd_boolean force_local)
{
/* For a shared link, move the plt refcount to the got refcount to leave
space for RELATIVE relocs. */
}
-/* Update the GOT & PLT entry reference counts
- for the section being removed. */
-
-static bfd_boolean
-elf_xtensa_gc_sweep_hook (bfd *abfd,
- struct bfd_link_info *info,
- asection *sec,
- const Elf_Internal_Rela *relocs)
-{
- Elf_Internal_Shdr *symtab_hdr;
- struct elf_link_hash_entry **sym_hashes;
- const Elf_Internal_Rela *rel, *relend;
- struct elf_xtensa_link_hash_table *htab;
-
- htab = elf_xtensa_hash_table (info);
- if (htab == NULL)
- return FALSE;
-
- if (bfd_link_relocatable (info))
- return TRUE;
-
- if ((sec->flags & SEC_ALLOC) == 0)
- return TRUE;
-
- symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
- sym_hashes = elf_sym_hashes (abfd);
-
- relend = relocs + sec->reloc_count;
- for (rel = relocs; rel < relend; rel++)
- {
- unsigned long r_symndx;
- unsigned int r_type;
- struct elf_link_hash_entry *h = NULL;
- struct elf_xtensa_link_hash_entry *eh;
- bfd_boolean is_got = FALSE;
- bfd_boolean is_plt = FALSE;
- bfd_boolean is_tlsfunc = FALSE;
-
- r_symndx = ELF32_R_SYM (rel->r_info);
- if (r_symndx >= symtab_hdr->sh_info)
- {
- h = sym_hashes[r_symndx - symtab_hdr->sh_info];
- while (h->root.type == bfd_link_hash_indirect
- || h->root.type == bfd_link_hash_warning)
- h = (struct elf_link_hash_entry *) h->root.u.i.link;
- }
- eh = elf_xtensa_hash_entry (h);
-
- r_type = ELF32_R_TYPE (rel->r_info);
- switch (r_type)
- {
- case R_XTENSA_TLSDESC_FN:
- if (bfd_link_pic (info))
- {
- is_got = TRUE;
- is_tlsfunc = TRUE;
- }
- break;
-
- case R_XTENSA_TLSDESC_ARG:
- if (bfd_link_pic (info))
- is_got = TRUE;
- else
- {
- if (h && elf_xtensa_hash_entry (h) != htab->tlsbase)
- is_got = TRUE;
- }
- break;
-
- case R_XTENSA_TLS_TPOFF:
- if (bfd_link_pic (info) || h)
- is_got = TRUE;
- break;
-
- case R_XTENSA_32:
- is_got = TRUE;
- break;
-
- case R_XTENSA_PLT:
- is_plt = TRUE;
- break;
-
- default:
- continue;
- }
-
- if (h)
- {
- if (is_plt)
- {
- /* If the symbol has been localized its plt.refcount got moved
- to got.refcount. Handle it as GOT. */
- if (h->plt.refcount > 0)
- h->plt.refcount--;
- else
- is_got = TRUE;
- }
- if (is_got)
- {
- if (h->got.refcount > 0)
- h->got.refcount--;
- }
- if (is_tlsfunc)
- {
- if (eh->tlsfunc_refcount > 0)
- eh->tlsfunc_refcount--;
- }
- }
- else
- {
- if (is_got || is_plt)
- {
- bfd_signed_vma *got_refcount
- = &elf_local_got_refcounts (abfd) [r_symndx];
- if (*got_refcount > 0)
- *got_refcount -= 1;
- }
- if (is_tlsfunc)
- {
- bfd_signed_vma *tlsfunc_refcount
- = &elf_xtensa_local_tlsfunc_refcounts (abfd) [r_symndx];
- if (*tlsfunc_refcount > 0)
- *tlsfunc_refcount -= 1;
- }
- }
- }
-
- return TRUE;
-}
-
-
/* Create all the dynamic sections. */
static bfd_boolean
/* If this is a weak symbol, and there is a real definition, the
processor independent code will have arranged for us to see the
real definition first, and we can just use the same value. */
- if (h->u.weakdef)
+ if (h->is_weakalias)
{
- BFD_ASSERT (h->u.weakdef->root.type == bfd_link_hash_defined
- || h->u.weakdef->root.type == bfd_link_hash_defweak);
- h->root.u.def.section = h->u.weakdef->root.u.def.section;
- h->root.u.def.value = h->u.weakdef->root.u.def.value;
+ struct elf_link_hash_entry *def = weakdef (h);
+ BFD_ASSERT (def->root.type == bfd_link_hash_defined);
+ h->root.u.def.section = def->root.u.def.section;
+ h->root.u.def.value = def->root.u.def.value;
return TRUE;
}
if (! elf_xtensa_dynamic_symbol_p (h, info))
elf_xtensa_make_sym_local (info, h);
+ if (! elf_xtensa_dynamic_symbol_p (h, info)
+ && h->root.type == bfd_link_hash_undefweak)
+ return TRUE;
+
if (h->plt.refcount > 0)
htab->elf.srelplt->size += (h->plt.refcount * sizeof (Elf32_External_Rela));
case R_XTENSA_ASM_SIMPLIFY:
{
- /* Convert the L32R/CALLX to CALL. */
+ /* Convert the L32R/CALLX to CALL. */
bfd_reloc_status_type retval =
elf_xtensa_do_asm_simplify (contents, address, input_size,
error_message);
}
else if (opcode == get_const16_opcode ())
{
- /* ALT used for high 16 bits. */
- newval = relocation >> 16;
+ /* ALT used for high 16 bits.
+ Ignore 32-bit overflow. */
+ newval = (relocation >> 16) & 0xffff;
opnd = 1;
}
else
xtensa_format_set_slot (isa, fmt, 0, ibuff, sbuff);
xtensa_insnbuf_to_chars (isa, ibuff, contents + rel->r_offset,
- input_size - rel->r_offset);
+ input_size - rel->r_offset);
return TRUE;
}
if (!xtensa_default_isa)
xtensa_default_isa = xtensa_isa_init (0, 0);
- BFD_ASSERT (is_xtensa_elf (input_bfd));
+ if (!is_xtensa_elf (input_bfd))
+ {
+ bfd_set_error (bfd_error_wrong_format);
+ return FALSE;
+ }
htab = elf_xtensa_hash_table (info);
if (htab == NULL)
{
_bfd_error_handler
/* xgettext:c-format */
- (_("%B(%A+%#Lx): relocation offset out of range (size=%#Lx)"),
- input_bfd, input_section, rel->r_offset, input_size);
+ (_("%pB(%pA+%#" PRIx64 "): "
+ "relocation offset out of range (size=%#" PRIx64 ")"),
+ input_bfd, input_section, (uint64_t) rel->r_offset,
+ (uint64_t) input_size);
bfd_set_error (bfd_error_bad_value);
return FALSE;
}
_bfd_error_handler
((sym_type == STT_TLS
/* xgettext:c-format */
- ? _("%B(%A+%#Lx): %s used with TLS symbol %s")
+ ? _("%pB(%pA+%#" PRIx64 "): %s used with TLS symbol %s")
/* xgettext:c-format */
- : _("%B(%A+%#Lx): %s used with non-TLS symbol %s")),
+ : _("%pB(%pA+%#" PRIx64 "): %s used with non-TLS symbol %s")),
input_bfd,
input_section,
- rel->r_offset,
+ (uint64_t) rel->r_offset,
howto->name,
name);
}
}
unresolved_reloc = FALSE;
}
- else
+ else if (!is_weak_undef)
{
/* Generate a RELATIVE relocation. */
outrel.r_info = ELF32_R_INFO (0, R_XTENSA_RELATIVE);
outrel.r_addend = 0;
}
+ else
+ {
+ continue;
+ }
}
loc = (srel->contents
{
_bfd_error_handler
/* xgettext:c-format */
- (_("%B(%A+%#Lx): unresolvable %s relocation against symbol `%s'"),
+ (_("%pB(%pA+%#" PRIx64 "): "
+ "unresolvable %s relocation against symbol `%s'"),
input_bfd,
input_section,
- rel->r_offset,
+ (uint64_t) rel->r_offset,
howto->name,
name);
return FALSE;
{
struct elf_xtensa_link_hash_table *htab;
bfd *dynobj;
- asection *sdyn, *srelplt, *sgot, *sxtlit, *sgotloc;
+ asection *sdyn, *srelplt, *srelgot, *sgot, *sxtlit, *sgotloc;
Elf32_External_Dyn *dyncon, *dynconend;
int num_xtlit_entries = 0;
}
srelplt = htab->elf.srelplt;
+ srelgot = htab->elf.srelgot;
if (srelplt && srelplt->size != 0)
{
- asection *sgotplt, *srelgot, *spltlittbl;
+ asection *sgotplt, *spltlittbl;
int chunk, plt_chunks, plt_entries;
Elf_Internal_Rela irela;
bfd_byte *loc;
unsigned rtld_reloc;
- srelgot = htab->elf.srelgot;
spltlittbl = htab->spltlittbl;
BFD_ASSERT (srelgot != NULL && spltlittbl != NULL);
spltlittbl->contents + (chunk * 8) + 4);
}
- /* All the dynamic relocations have been emitted at this point.
- Make sure the relocation sections are the correct size. */
- if (srelgot->size != (sizeof (Elf32_External_Rela)
- * srelgot->reloc_count)
- || srelplt->size != (sizeof (Elf32_External_Rela)
- * srelplt->reloc_count))
- abort ();
-
/* The .xt.lit.plt section has just been modified. This must
happen before the code below which combines adjacent literal
table entries, and the .xt.lit.plt contents have to be forced to
spltlittbl->flags &= ~SEC_HAS_CONTENTS;
}
+ /* All the dynamic relocations have been emitted at this point.
+ Make sure the relocation sections are the correct size. */
+ if ((srelgot && srelgot->size != (sizeof (Elf32_External_Rela)
+ * srelgot->reloc_count))
+ || (srelplt && srelplt->size != (sizeof (Elf32_External_Rela)
+ * srelplt->reloc_count)))
+ abort ();
+
/* Combine adjacent literal table entries. */
BFD_ASSERT (! bfd_link_relocatable (info));
sxtlit = bfd_get_section_by_name (output_bfd, ".xt.lit");
{
_bfd_error_handler
/* xgettext:c-format */
- (_("%B: incompatible machine type. Output is 0x%x. Input is 0x%x"),
+ (_("%pB: incompatible machine type; output is 0x%x; input is 0x%x"),
ibfd, out_mach, in_mach);
bfd_set_error (bfd_error_wrong_format);
return FALSE;
if (content_length < address)
{
- *error_message = _("Attempt to convert L32R/CALLX to CALL failed");
+ *error_message = _("attempt to convert L32R/CALLX to CALL failed");
return bfd_reloc_other;
}
direct_call_opcode = swap_callx_for_call_opcode (opcode);
if (direct_call_opcode == XTENSA_UNDEFINED)
{
- *error_message = _("Attempt to convert L32R/CALLX to CALL failed");
+ *error_message = _("attempt to convert L32R/CALLX to CALL failed");
return bfd_reloc_other;
}
/* The following text actions are generated:
- "ta_remove_insn" remove an instruction or instructions
- "ta_remove_longcall" convert longcall to call
+ "ta_remove_insn" remove an instruction or instructions
+ "ta_remove_longcall" convert longcall to call
"ta_convert_longcall" convert longcall to nop/call
- "ta_narrow_insn" narrow a wide instruction
- "ta_widen" widen a narrow instruction
- "ta_fill" add fill or remove fill
+ "ta_narrow_insn" narrow a wide instruction
+ "ta_widen" widen a narrow instruction
+ "ta_fill" add fill or remove fill
removed < 0 is a fill; branches to the fill address will be
changed to address + fill size (e.g., address - removed)
removed >= 0 branches to the fill address will stay unchanged
- "ta_remove_literal" remove a literal; this action is
+ "ta_remove_literal" remove a literal; this action is
indicated when a literal is removed
- or replaced.
- "ta_add_literal" insert a new literal; this action is
- indicated when a literal has been moved.
- It may use a virtual_offset because
+ or replaced.
+ "ta_add_literal" insert a new literal; this action is
+ indicated when a literal has been moved.
+ It may use a virtual_offset because
multiple literals can be placed at the
- same location.
+ same location.
For each of these text actions, we also record the number of bytes
removed by performing the text action. In the case of a "ta_widen"
enum text_action_enum_t
{
ta_none,
- ta_remove_insn, /* removed = -size */
- ta_remove_longcall, /* removed = -size */
- ta_convert_longcall, /* removed = 0 */
- ta_narrow_insn, /* removed = -1 */
- ta_widen_insn, /* removed = +1 */
- ta_fill, /* removed = +size */
+ ta_remove_insn, /* removed = -size */
+ ta_remove_longcall, /* removed = -size */
+ ta_convert_longcall, /* removed = 0 */
+ ta_narrow_insn, /* removed = -1 */
+ ta_widen_insn, /* removed = +1 */
+ ta_fill, /* removed = +size */
ta_remove_literal,
ta_add_literal
};
{
_bfd_error_handler
/* xgettext:c-format */
- (_("%B(%A+%#Lx): could not decode instruction; "
+ (_("%pB(%pA+%#" PRIx64 "): could not decode instruction; "
"possible configuration mismatch"),
- ebb->sec->owner, ebb->sec, ebb->end_offset + insn_block_len);
+ ebb->sec->owner, ebb->sec,
+ (uint64_t) (ebb->end_offset + insn_block_len));
return FALSE;
}
ebb->end_offset += insn_block_len;
{
_bfd_error_handler
/* xgettext:c-format */
- (_("%B(%A+%#Lx): could not decode instruction; "
+ (_("%pB(%pA+%#" PRIx64 "): could not decode instruction; "
"possible configuration mismatch"),
- ebb->sec->owner, ebb->sec, ebb->end_offset + insn_block_len);
+ ebb->sec->owner, ebb->sec,
+ (uint64_t) (ebb->end_offset + insn_block_len));
return FALSE;
}
ebb->start_offset -= insn_block_len;
static bfd_boolean check_section_ebb_reduces (const ebb_constraint *);
static void text_action_add_proposed
(text_action_list *, const ebb_constraint *, asection *);
-static int compute_fill_extra_space (property_table_entry *);
/* First pass: */
static bfd_boolean compute_removed_literals
continue;
/* Count PC-relative operand relocations against the target section.
- Note: The conditions tested here must match the conditions under
+ Note: The conditions tested here must match the conditions under
which init_source_reloc is called in collect_source_relocs(). */
is_l32r_reloc = FALSE;
if (is_operand_relocation (ELF32_R_TYPE (irel->r_info)))
bfd_boolean *is_reachable_p)
{
asection *target_sec;
+ asection *s;
+ bfd_vma first_vma;
+ bfd_vma last_vma;
+ unsigned int first_align;
+ unsigned int adjust;
bfd_vma target_offset;
r_reloc r_rel;
xtensa_opcode opcode, direct_call_opcode;
+ target_sec->output_offset + target_offset);
}
+ /* Adjust addresses with alignments for the worst case to see if call insn
+ can fit. Don't relax l32r + callx to call if the target can be out of
+ range due to alignment.
+ Caller and target addresses are highest and lowest address.
+ Search all sections between caller and target, looking for max alignment.
+ The adjustment is max alignment bytes. If the alignment at the lowest
+ address is less than the adjustment, apply the adjustment to highest
+ address. */
+
+ /* Start from lowest address.
+ Lowest address aligmnet is from input section.
+ Initial alignment (adjust) is from input section. */
+ if (dest_address > self_address)
+ {
+ s = sec->output_section;
+ last_vma = dest_address;
+ first_align = sec->alignment_power;
+ adjust = target_sec->alignment_power;
+ }
+ else
+ {
+ s = target_sec->output_section;
+ last_vma = self_address;
+ first_align = target_sec->alignment_power;
+ adjust = sec->alignment_power;
+ }
+
+ first_vma = s->vma;
+
+ /* Find the largest alignment in output section list. */
+ for (; s && s->vma >= first_vma && s->vma <= last_vma ; s = s->next)
+ {
+ if (s->alignment_power > adjust)
+ adjust = s->alignment_power;
+ }
+
+ if (adjust > first_align)
+ {
+ /* Alignment may enlarge the range, adjust highest address. */
+ adjust = 1 << adjust;
+ if (dest_address > self_address)
+ {
+ dest_address += adjust;
+ }
+ else
+ {
+ self_address += adjust;
+ }
+ }
+
*is_reachable_p = pcrel_reloc_fits (direct_call_opcode, 0,
self_address, dest_address);
reloc[i].irel = irel;
/* Every relocation won't possibly be checked in the optimized version of
- check_section_ebb_pcrels_fit, so this needs to be done here. */
+ check_section_ebb_pcrels_fit, so this needs to be done here. */
if (is_alt_relocation (ELF32_R_TYPE (irel->r_info)))
{
/* None of the current alternate relocs are PC-relative,
{
_bfd_error_handler
/* xgettext:c-format */
- (_("%B(%A+%#Lx): could not decode instruction for "
+ (_("%pB(%pA+%#" PRIx64 "): could not decode instruction for "
"XTENSA_ASM_SIMPLIFY relocation; "
"possible configuration mismatch"),
- sec->owner, sec, r_offset);
+ sec->owner, sec, (uint64_t) r_offset);
continue;
}
decode_error:
_bfd_error_handler
/* xgettext:c-format */
- (_("%B(%A+%#Lx): could not decode instruction; "
+ (_("%pB(%pA+%#" PRIx64 "): could not decode instruction; "
"possible configuration mismatch"),
- ebb->sec->owner, ebb->sec, offset);
+ ebb->sec->owner, ebb->sec, (uint64_t) offset);
return FALSE;
}
BFD_ASSERT (action->action == ta_fill);
BFD_ASSERT (ebb->ends_unreachable->flags & XTENSA_PROP_UNREACHABLE);
- extra_space = compute_fill_extra_space (ebb->ends_unreachable);
+ extra_space = xtensa_compute_fill_extra_space (ebb->ends_unreachable);
br = action->removed_bytes + removed_bytes + extra_space;
br = br & ((1 << ebb->sec->alignment_power ) - 1);
struct xlate_map_entry
{
- unsigned orig_address;
- unsigned new_address;
+ bfd_vma orig_address;
+ bfd_vma new_address;
unsigned size;
};
{
void *r;
xlate_map_entry_t *e;
+ struct xlate_map_entry se;
if (map == NULL)
return offset_with_removed_text (action_list, offset);
if (map->entry_count == 0)
return offset;
- r = bsearch (&offset, map->entry, map->entry_count,
+ se.orig_address = offset;
+ r = bsearch (&se, map->entry, map->entry_count,
sizeof (xlate_map_entry_t), &xlate_compare);
e = (xlate_map_entry_t *) r;
+ /* There could be a jump past the end of the section,
+ allow it using the last xlate map entry to translate its address. */
+ if (e == NULL)
+ {
+ e = map->entry + map->entry_count - 1;
+ if (xlate_compare (&se, e) <= 0)
+ e = NULL;
+ }
BFD_ASSERT (e != NULL);
if (e == NULL)
return offset;
int
-compute_fill_extra_space (property_table_entry *entry)
+xtensa_compute_fill_extra_space (property_table_entry *entry)
{
int fill_extra_space;
do not add fill. */
the_add_entry = elf_xtensa_find_property_entry (prop_table, ptblsize,
entry_sec_offset);
- fill_extra_space = compute_fill_extra_space (the_add_entry);
+ fill_extra_space = xtensa_compute_fill_extra_space (the_add_entry);
fa = find_fill_action (&relax_info->action_list, sec, entry_sec_offset);
removed_diff = compute_removed_action_diff (fa, sec, entry_sec_offset,
continue;
/* The original and new output section for these must be the same
- in order to coalesce. */
+ in order to coalesce. */
if (r_reloc_get_section (&reloc[i].r_rel)->output_section
!= sec->output_section)
return FALSE;
/* Update the action so that the code that moves
the contents will do the right thing. */
/* ta_remove_longcall and ta_remove_insn actions are
- grouped together in the tree as well as
+ grouped together in the tree as well as
ta_convert_longcall and ta_none, so that changes below
can be done w/o removing and reinserting action into
the tree. */
if ((r_type == R_XTENSA_32 || r_type == R_XTENSA_PLT)
&& (input_section->flags & SEC_ALLOC) != 0
- && (dynamic_symbol || bfd_link_pic (info)))
+ && (dynamic_symbol || bfd_link_pic (info))
+ && (!h || h->root.type != bfd_link_hash_undefweak
+ || (dynamic_symbol && bfd_link_dll (info))))
{
asection *srel;
bfd_boolean is_plt = FALSE;
predef_flags = xtensa_get_property_predef_flags (sec);
/* Walk over memory and relocations at the same time.
- This REQUIRES that the internal_relocs be sorted by offset. */
+ This REQUIRES that the internal_relocs be sorted by offset. */
qsort (internal_relocs, sec->reloc_count, sizeof (Elf_Internal_Rela),
internal_reloc_compare);
{
_bfd_error_handler
/* xgettext:c-format */
- (_("%B(%A+%#Lx): unexpected fix for %s relocation"),
- input_bfd, input_section, rel->r_offset,
+ (_("%pB(%pA+%#" PRIx64 "): unexpected fix for %s relocation"),
+ input_bfd, input_section, (uint64_t) rel->r_offset,
elf_howto_table[r_type].name);
return FALSE;
}
elf_xtensa_get_plt_section (struct bfd_link_info *info, int chunk)
{
bfd *dynobj;
- char plt_name[10];
+ char plt_name[17];
if (chunk == 0)
return elf_hash_table (info)->splt;
elf_xtensa_get_gotplt_section (struct bfd_link_info *info, int chunk)
{
bfd *dynobj;
- char got_name[14];
+ char got_name[21];
if (chunk == 0)
return elf_hash_table (info)->sgotplt;
struct elf_link_hash_entry *h = elf_sym_hashes (abfd)[indx];
while (h->root.type == bfd_link_hash_indirect
- || h->root.type == bfd_link_hash_warning)
- h = (struct elf_link_hash_entry *) h->root.u.i.link;
+ || h->root.type == bfd_link_hash_warning)
+ h = (struct elf_link_hash_entry *) h->root.u.i.link;
switch (h->root.type)
{
elf_sym_hashes (abfd)[indx];
while (h->root.type == bfd_link_hash_indirect
- || h->root.type == bfd_link_hash_warning)
+ || h->root.type == bfd_link_hash_warning)
h = (struct elf_link_hash_entry *) h->root.u.i.link;
if (h->root.type == bfd_link_hash_defined
- || h->root.type == bfd_link_hash_defweak)
+ || h->root.type == bfd_link_hash_defweak)
offset = h->root.u.def.value;
}
return offset;
}
+static char *
+xtensa_add_names (const char *base, const char *suffix)
+{
+ if (suffix)
+ {
+ size_t base_len = strlen (base);
+ size_t suffix_len = strlen (suffix);
+ char *str = bfd_malloc (base_len + suffix_len + 1);
+
+ memcpy (str, base, base_len);
+ memcpy (str + base_len, suffix, suffix_len + 1);
+ return str;
+ }
+ else
+ {
+ return strdup (base);
+ }
+}
+
static int linkonce_len = sizeof (".gnu.linkonce.") - 1;
static char *
-xtensa_property_section_name (asection *sec, const char *base_name)
+xtensa_property_section_name (asection *sec, const char *base_name,
+ bfd_boolean separate_sections)
{
const char *suffix, *group_name;
char *prop_sec_name;
suffix = strrchr (sec->name, '.');
if (suffix == sec->name)
suffix = 0;
- prop_sec_name = (char *) bfd_malloc (strlen (base_name) + 1
- + (suffix ? strlen (suffix) : 0));
- strcpy (prop_sec_name, base_name);
- if (suffix)
- strcat (prop_sec_name, suffix);
+ prop_sec_name = xtensa_add_names (base_name, suffix);
}
else if (strncmp (sec->name, ".gnu.linkonce.", linkonce_len) == 0)
{
suffix = sec->name + linkonce_len;
/* For backward compatibility, replace "t." instead of inserting
- the new linkonce_kind (but not for "prop" sections). */
+ the new linkonce_kind (but not for "prop" sections). */
if (CONST_STRNEQ (suffix, "t.") && linkonce_kind[1] == '.')
- suffix += 2;
+ suffix += 2;
strcat (prop_sec_name + linkonce_len, suffix);
}
else
- prop_sec_name = strdup (base_name);
+ {
+ prop_sec_name = xtensa_add_names (base_name,
+ separate_sections ? sec->name : NULL);
+ }
return prop_sec_name;
}
static asection *
-xtensa_get_property_section (asection *sec, const char *base_name)
+xtensa_get_separate_property_section (asection *sec, const char *base_name,
+ bfd_boolean separate_section)
{
char *prop_sec_name;
asection *prop_sec;
- prop_sec_name = xtensa_property_section_name (sec, base_name);
+ prop_sec_name = xtensa_property_section_name (sec, base_name,
+ separate_section);
prop_sec = bfd_get_section_by_name_if (sec->owner, prop_sec_name,
match_section_group,
(void *) elf_group_name (sec));
return prop_sec;
}
+static asection *
+xtensa_get_property_section (asection *sec, const char *base_name)
+{
+ asection *prop_sec;
+
+ /* Try individual property section first. */
+ prop_sec = xtensa_get_separate_property_section (sec, base_name, TRUE);
+
+ /* Refer to a common property section if individual is not present. */
+ if (!prop_sec)
+ prop_sec = xtensa_get_separate_property_section (sec, base_name, FALSE);
+
+ return prop_sec;
+}
+
asection *
xtensa_make_property_section (asection *sec, const char *base_name)
asection *prop_sec;
/* Check if the section already exists. */
- prop_sec_name = xtensa_property_section_name (sec, base_name);
+ prop_sec_name = xtensa_property_section_name (sec, base_name,
+ elf32xtensa_separate_props);
prop_sec = bfd_get_section_by_name_if (sec->owner, prop_sec_name,
match_section_group,
(void *) elf_group_name (sec));
{
{ STRING_COMMA_LEN (".fini.literal"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR },
{ STRING_COMMA_LEN (".init.literal"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR },
- { STRING_COMMA_LEN (".literal"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR },
- { STRING_COMMA_LEN (".xtensa.info"), 0, SHT_NOTE, 0 },
- { NULL, 0, 0, 0, 0 }
+ { STRING_COMMA_LEN (".literal"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR },
+ { STRING_COMMA_LEN (".xtensa.info"), 0, SHT_NOTE, 0 },
+ { NULL, 0, 0, 0, 0 }
};
\f
#define ELF_TARGET_ID XTENSA_ELF_DATA
#define elf_backend_finish_dynamic_sections elf_xtensa_finish_dynamic_sections
#define elf_backend_finish_dynamic_symbol elf_xtensa_finish_dynamic_symbol
#define elf_backend_gc_mark_hook elf_xtensa_gc_mark_hook
-#define elf_backend_gc_sweep_hook elf_xtensa_gc_sweep_hook
#define elf_backend_grok_prstatus elf_xtensa_grok_prstatus
#define elf_backend_grok_psinfo elf_xtensa_grok_psinfo
#define elf_backend_hide_symbol elf_xtensa_hide_symbol
#define elf_backend_relocate_section elf_xtensa_relocate_section
#define elf_backend_size_dynamic_sections elf_xtensa_size_dynamic_sections
#define elf_backend_always_size_sections elf_xtensa_always_size_sections
-#define elf_backend_omit_section_dynsym \
- ((bfd_boolean (*) (bfd *, struct bfd_link_info *, asection *)) bfd_true)
+#define elf_backend_omit_section_dynsym _bfd_elf_omit_section_dynsym_all
#define elf_backend_special_sections elf_xtensa_special_sections
#define elf_backend_action_discarded elf_xtensa_action_discarded
#define elf_backend_copy_indirect_symbol elf_xtensa_copy_indirect_symbol