/* Xtensa-specific support for 32-bit ELF.
- Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
- Free Software Foundation, Inc.
+ Copyright (C) 2003-2015 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
\f
static reloc_howto_type elf_howto_table[] =
{
- HOWTO (R_XTENSA_NONE, 0, 0, 0, FALSE, 0, complain_overflow_dont,
+ HOWTO (R_XTENSA_NONE, 0, 3, 0, FALSE, 0, complain_overflow_dont,
bfd_elf_xtensa_reloc, "R_XTENSA_NONE",
FALSE, 0, 0, FALSE),
HOWTO (R_XTENSA_32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
FALSE, 0, 0, FALSE),
/* Relocations for supporting difference of symbols. */
- HOWTO (R_XTENSA_DIFF8, 0, 0, 8, FALSE, 0, complain_overflow_bitfield,
+ HOWTO (R_XTENSA_DIFF8, 0, 0, 8, FALSE, 0, complain_overflow_signed,
bfd_elf_xtensa_reloc, "R_XTENSA_DIFF8", FALSE, 0, 0xff, FALSE),
- HOWTO (R_XTENSA_DIFF16, 0, 1, 16, FALSE, 0, complain_overflow_bitfield,
+ HOWTO (R_XTENSA_DIFF16, 0, 1, 16, FALSE, 0, complain_overflow_signed,
bfd_elf_xtensa_reloc, "R_XTENSA_DIFF16", FALSE, 0, 0xffff, FALSE),
- HOWTO (R_XTENSA_DIFF32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
+ HOWTO (R_XTENSA_DIFF32, 0, 2, 32, FALSE, 0, complain_overflow_signed,
bfd_elf_xtensa_reloc, "R_XTENSA_DIFF32", FALSE, 0, 0xffffffff, FALSE),
/* General immediate operand relocations. */
{
unsigned int r_type = ELF32_R_TYPE (dst->r_info);
- BFD_ASSERT (r_type < (unsigned int) R_XTENSA_max);
+ if (r_type >= (unsigned int) R_XTENSA_max)
+ {
+ _bfd_error_handler (_("%A: invalid XTENSA reloc number: %d"), abfd, r_type);
+ r_type = 0;
+ }
cache_ptr->howto = &elf_howto_table[r_type];
}
struct elf_xtensa_link_hash_table *ret;
bfd_size_type amt = sizeof (struct elf_xtensa_link_hash_table);
- ret = bfd_malloc (amt);
+ ret = bfd_zmalloc (amt);
if (ret == NULL)
return NULL;
return NULL;
}
- ret->sgot = NULL;
- ret->sgotplt = NULL;
- ret->srelgot = NULL;
- ret->splt = NULL;
- ret->srelplt = NULL;
- ret->sgotloc = NULL;
- ret->spltlittbl = NULL;
-
- ret->plt_reloc_count = 0;
-
/* Create a hash entry for "_TLS_MODULE_BASE_" to speed up checking
for it later. */
tlsbase = elf_link_hash_lookup (&ret->elf, "_TLS_MODULE_BASE_",
!= GET_XTENSA_PROP_ALIGNMENT (b->flags)))
return (GET_XTENSA_PROP_ALIGNMENT (a->flags)
- GET_XTENSA_PROP_ALIGNMENT (b->flags));
-
+
if ((a->flags & XTENSA_PROP_UNREACHABLE)
!= (b->flags & XTENSA_PROP_UNREACHABLE))
return ((b->flags & XTENSA_PROP_UNREACHABLE)
if (table_section)
table_size = table_section->size;
- if (table_size == 0)
+ if (table_size == 0)
{
*table_p = NULL;
return 0;
section_limit = bfd_get_section_limit (abfd, section);
rel_end = internal_relocs + table_section->reloc_count;
- for (off = 0; off < table_size; off += table_entry_size)
+ for (off = 0; off < table_size; off += table_entry_size)
{
bfd_vma address = bfd_get_32 (abfd, table_data + off);
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 = 1;
}
eh = elf_xtensa_hash_entry (h);
/* First do all the standard stuff. */
if (! _bfd_elf_create_dynamic_sections (dynobj, info))
return FALSE;
- htab->splt = bfd_get_section_by_name (dynobj, ".plt");
- htab->srelplt = bfd_get_section_by_name (dynobj, ".rela.plt");
- htab->sgot = bfd_get_section_by_name (dynobj, ".got");
- htab->sgotplt = bfd_get_section_by_name (dynobj, ".got.plt");
- htab->srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
+ htab->splt = bfd_get_linker_section (dynobj, ".plt");
+ htab->srelplt = bfd_get_linker_section (dynobj, ".rela.plt");
+ htab->sgot = bfd_get_linker_section (dynobj, ".got");
+ htab->sgotplt = bfd_get_linker_section (dynobj, ".got.plt");
+ htab->srelgot = bfd_get_linker_section (dynobj, ".rela.got");
/* Create any extra PLT sections in case check_relocs has already
been called on all the non-dynamic input files. */
return FALSE;
/* Create ".got.loc" (literal tables for use by dynamic linker). */
- htab->sgotloc = bfd_make_section_with_flags (dynobj, ".got.loc", flags);
+ htab->sgotloc = bfd_make_section_anyway_with_flags (dynobj, ".got.loc",
+ flags);
if (htab->sgotloc == NULL
|| ! bfd_set_section_alignment (dynobj, htab->sgotloc, 2))
return FALSE;
/* Create ".xt.lit.plt" (literal table for ".got.plt*"). */
- htab->spltlittbl = bfd_make_section_with_flags (dynobj, ".xt.lit.plt",
- noalloc_flags);
+ htab->spltlittbl = bfd_make_section_anyway_with_flags (dynobj, ".xt.lit.plt",
+ noalloc_flags);
if (htab->spltlittbl == NULL
|| ! bfd_set_section_alignment (dynobj, htab->spltlittbl, 2))
return FALSE;
sname = (char *) bfd_malloc (10);
sprintf (sname, ".plt.%u", chunk);
- s = bfd_make_section_with_flags (dynobj, sname, flags | SEC_CODE);
+ s = bfd_make_section_anyway_with_flags (dynobj, sname, flags | SEC_CODE);
if (s == NULL
|| ! bfd_set_section_alignment (dynobj, s, 2))
return FALSE;
sname = (char *) bfd_malloc (14);
sprintf (sname, ".got.plt.%u", chunk);
- s = bfd_make_section_with_flags (dynobj, sname, flags);
+ s = bfd_make_section_anyway_with_flags (dynobj, sname, flags);
if (s == NULL
|| ! bfd_set_section_alignment (dynobj, s, 2))
return FALSE;
if (h->root.type == bfd_link_hash_indirect)
return TRUE;
- if (h->root.type == bfd_link_hash_warning)
- h = (struct elf_link_hash_entry *) h->root.u.i.link;
-
info = (struct bfd_link_info *) arg;
htab = elf_xtensa_hash_table (info);
if (htab == NULL)
if (htab == NULL)
return;
- for (i = info->input_bfds; i; i = i->link_next)
+ for (i = info->input_bfds; i; i = i->link.next)
{
bfd_signed_vma *local_got_refcounts;
bfd_size_type j, cnt;
/* Set the contents of the .interp section to the interpreter. */
if (info->executable)
{
- s = bfd_get_section_by_name (dynobj, ".interp");
+ s = bfd_get_linker_section (dynobj, ".interp");
if (s == NULL)
abort ();
s->size = sizeof ELF_DYNAMIC_INTERPRETER;
literal tables. */
sgotloc = htab->sgotloc;
sgotloc->size = spltlittbl->size;
- for (abfd = info->input_bfds; abfd != NULL; abfd = abfd->link_next)
+ for (abfd = info->input_bfds; abfd != NULL; abfd = abfd->link.next)
{
if (abfd->flags & DYNAMIC)
continue;
for (s = abfd->sections; s != NULL; s = s->next)
{
- if (! elf_discarded_section (s)
+ if (! discarded_section (s)
&& xtensa_is_littable_section (s)
&& s != spltlittbl)
sgotloc->size += s->size;
if (is_windowed_call_opcode (opcode))
{
if ((self_address >> CALL_SEGMENT_BITS)
- != (relocation >> CALL_SEGMENT_BITS))
+ != (relocation >> CALL_SEGMENT_BITS))
{
*error_message = "windowed longcall crosses 1GB boundary; "
"return may fail";
&& is_windowed_call_opcode (opcode))
{
if ((self_address >> CALL_SEGMENT_BITS)
- != (relocation >> CALL_SEGMENT_BITS))
+ != (relocation >> CALL_SEGMENT_BITS))
{
*error_message =
"windowed call crosses 1GB boundary; return may fail";
static char *message = NULL;
bfd_size_type orig_len, len = 0;
bfd_boolean is_append;
+ va_list ap;
+
+ va_start (ap, arglen);
- VA_OPEN (ap, arglen);
- VA_FIXEDARG (ap, const char *, origmsg);
-
- is_append = (origmsg == message);
+ is_append = (origmsg == message);
orig_len = strlen (origmsg);
len = orig_len + strlen (fmt) + arglen + 20;
memcpy (message, origmsg, orig_len);
vsprintf (message + orig_len, fmt, ap);
}
- VA_CLOSE (ap);
+ va_end (ap);
return message;
}
}
else
{
+ bfd_boolean ignored;
+
RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
r_symndx, symtab_hdr, sym_hashes,
h, sec, relocation,
- unresolved_reloc, warned);
+ unresolved_reloc, warned, ignored);
if (relocation == 0
&& !unresolved_reloc
sym_type = h->type;
}
- if (sec != NULL && elf_discarded_section (sec))
- {
- /* For relocs against symbols from removed linkonce sections,
- or sections discarded by a linker script, we just want the
- section contents zeroed. Avoid any special processing. */
- _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset);
- rel->r_info = 0;
- rel->r_addend = 0;
- continue;
- }
+ if (sec != NULL && discarded_section (sec))
+ RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
+ rel, 1, relend, howto, 0, contents);
if (info->relocatable)
{
name = bfd_section_name (input_bfd, sec);
}
- if (r_symndx != 0
+ if (r_symndx != STN_UNDEF
&& r_type != R_XTENSA_NONE
&& (h == NULL
|| h->root.type == bfd_link_hash_defined
not process them. */
if (unresolved_reloc
&& !((input_section->flags & SEC_DEBUGGING) != 0
- && h->def_dynamic))
+ && h->def_dynamic)
+ && _bfd_elf_section_offset (output_bfd, info, input_section,
+ rel->r_offset) != (bfd_vma) -1)
{
(*_bfd_error_handler)
(_("%B(%A+0x%lx): unresolvable %s relocation against symbol `%s'"),
}
/* Mark _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute. */
- if (strcmp (h->root.root.string, "_DYNAMIC") == 0
+ if (h == elf_hash_table (info)->hdynamic
|| h == elf_hash_table (info)->hgot)
sym->st_shndx = SHN_ABS;
return FALSE;
dynobj = elf_hash_table (info)->dynobj;
- sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
+ sdyn = bfd_get_linker_section (dynobj, ".dynamic");
BFD_ASSERT (sdyn != NULL);
/* Set the first entry in the global offset table to the address of
unsigned out_mach, in_mach;
flagword out_flag, in_flag;
- /* Check if we have the same endianess. */
+ /* Check if we have the same endianness. */
if (!_bfd_generic_verify_endian_match (ibfd, obfd))
return FALSE;
return TRUE;
}
- if ((out_flag & EF_XTENSA_XT_INSN) != (in_flag & EF_XTENSA_XT_INSN))
+ if ((out_flag & EF_XTENSA_XT_INSN) != (in_flag & EF_XTENSA_XT_INSN))
elf_elfheader (obfd)->e_flags &= (~ EF_XTENSA_XT_INSN);
- if ((out_flag & EF_XTENSA_XT_LIT) != (in_flag & EF_XTENSA_XT_LIT))
+ if ((out_flag & EF_XTENSA_XT_LIT) != (in_flag & EF_XTENSA_XT_LIT))
elf_elfheader (obfd)->e_flags &= (~ EF_XTENSA_XT_LIT);
return TRUE;
static enum elf_reloc_type_class
-elf_xtensa_reloc_type_class (const Elf_Internal_Rela *rela)
+elf_xtensa_reloc_type_class (const struct bfd_link_info *info ATTRIBUTE_UNUSED,
+ const asection *rel_sec ATTRIBUTE_UNUSED,
+ const Elf_Internal_Rela *rela)
{
switch ((int) ELF32_R_TYPE (rela->r_info))
{
based on the size. Just assume this is GNU/Linux. */
/* pr_cursig */
- elf_tdata (abfd)->core_signal = bfd_get_16 (abfd, note->descdata + 12);
+ elf_tdata (abfd)->core->signal = bfd_get_16 (abfd, note->descdata + 12);
/* pr_pid */
- elf_tdata (abfd)->core_pid = bfd_get_32 (abfd, note->descdata + 24);
+ elf_tdata (abfd)->core->lwpid = bfd_get_32 (abfd, note->descdata + 24);
/* pr_reg */
offset = 72;
return FALSE;
case 128: /* GNU/Linux elf_prpsinfo */
- elf_tdata (abfd)->core_program
+ elf_tdata (abfd)->core->program
= _bfd_elfcore_strndup (abfd, note->descdata + 32, 16);
- elf_tdata (abfd)->core_command
+ elf_tdata (abfd)->core->command
= _bfd_elfcore_strndup (abfd, note->descdata + 48, 80);
}
implementations, so strip it off if it exists. */
{
- char *command = elf_tdata (abfd)->core_command;
+ char *command = elf_tdata (abfd)->core->command;
int n = strlen (command);
if (0 < n && command[n - 1] == ' ')
return 0;
size += insnlen;
-
+
insnlen = insn_decode_len (contents, content_len, offset + size);
if (insnlen == 0)
return 0;
return FALSE;
}
-
+
#define MIN_INSN_LENGTH 2
/* Return 0 if it fails to decode. */
BFD_ASSERT (FALSE);
return FALSE;
}
-
+
loop_len = insn_decode_len (contents, content_length, offset);
insn_len = insn_decode_len (contents, content_length, offset + loop_len);
if (loop_len == 0 || insn_len == 0)
return 0;
}
-
+
/* Attempt to widen an instruction. If the widening is valid, perform
the action in-place directly into the contents and return TRUE. Otherwise,
the return value is FALSE and the contents are not modified. */
*error_message = _("Attempt to convert L32R/CALLX to CALL failed");
return bfd_reloc_other;
}
-
+
/* Assemble a NOP ("or a1, a1, a1") into the 0 byte offset. */
core_format = xtensa_format_lookup (isa, "x24");
opcode = xtensa_opcode_lookup (isa, "or");
xtensa_opcode_encode (isa, core_format, 0, slotbuf, opcode);
- for (opn = 0; opn < 3; opn++)
+ for (opn = 0; opn < 3; opn++)
{
uint32 regno = 1;
xtensa_operand_encode (isa, opcode, opn, ®no);
#define CONST16_TARGET_REG_OPERAND 0
#define CALLN_SOURCE_OPERAND 0
-static xtensa_opcode
+static xtensa_opcode
get_expanded_call_opcode (bfd_byte *buf, int bufsize, bfd_boolean *p_uses_l32r)
{
static xtensa_insnbuf insnbuf = NULL;
|| xtensa_format_get_slot (isa, fmt, 0, insnbuf, slotbuf))
return XTENSA_UNDEFINED;
opcode = xtensa_opcode_decode (isa, fmt, 0, slotbuf);
- if (opcode == XTENSA_UNDEFINED
+ if (opcode == XTENSA_UNDEFINED
|| !is_indirect_call_opcode (opcode))
return XTENSA_UNDEFINED;
For efficiency, an r_reloc also contains a "target_offset" field to
cache the target-section-relative offset value that is represented by
the relocation.
-
+
The r_reloc also contains a virtual offset that allows multiple
inserted literals to be placed at the same "address" with
different offsets. */
fprintf (fp, " + ");
fprintf_vma (fp, r_rel->virtual_offset);
}
-
+
fprintf (fp, ")");
}
struct literal_value_struct
{
- r_reloc r_rel;
+ r_reloc r_rel;
unsigned long value;
bfd_boolean is_abs_literal;
};
{
struct elf_link_hash_entry *h1, *h2;
- if (r_reloc_is_const (&src1->r_rel) != r_reloc_is_const (&src2->r_rel))
+ if (r_reloc_is_const (&src1->r_rel) != r_reloc_is_const (&src2->r_rel))
return FALSE;
if (r_reloc_is_const (&src1->r_rel))
if (src1->r_rel.target_offset != src2->r_rel.target_offset)
return FALSE;
-
+
if (src1->r_rel.virtual_offset != src2->r_rel.virtual_offset)
return FALSE;
if (src1->value != src2->value)
return FALSE;
-
+
/* 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);
values->count = 0;
values->buckets = (value_map **)
bfd_zmalloc (sizeof (value_map *) * values->bucket_count);
- if (values->buckets == NULL)
+ if (values->buckets == NULL)
{
free (values);
return NULL;
hash_val += hash_bfd_vma (src->is_abs_literal * 1000);
hash_val += hash_bfd_vma (src->r_rel.target_offset);
hash_val += hash_bfd_vma (src->r_rel.virtual_offset);
-
+
/* Now check for the same section and the same elf_hash. */
if (r_reloc_is_defined (&src->r_rel))
sec_or_hash = r_reloc_get_section (&src->r_rel);
*bucket_p = val_e;
map->count++;
/* FIXME: Consider resizing the hash table if we get too many entries. */
-
+
return val_e;
}
"unreachable_space" bytes can be freely contracted. Note that a
negative removed value is a fill. */
-static void
+static void
text_action_add (text_action_list *l,
text_action_t action,
asection *sec,
for (m_p = &l->head; *m_p && (*m_p)->offset <= offset; m_p = &(*m_p)->next)
{
text_action *t = *m_p;
-
- if (action == ta_fill)
+
+ if (action == ta_fill)
{
/* When the action is another fill at the same address,
just increase the size. */
}
-static bfd_vma
+static bfd_vma
offset_with_removed_text (text_action_list *action_list, bfd_vma offset)
{
text_action *r = action_list->head;
fprintf (fp, "%s: %s[0x%lx] \"%s\" %d\n",
r->sec->owner->filename,
- r->sec->name, r->offset, t, r->removed_bytes);
+ r->sec->name, (unsigned long) r->offset, t, r->removed_bytes);
}
}
else
new_r->to.abfd = NULL;
new_r->next = NULL;
-
+
r = removed_list->head;
- if (r == NULL)
+ if (r == NULL)
{
removed_list->head = new_r;
removed_list->tail = new_r;
}
else
{
- while (r->from.target_offset < from->target_offset && r->next)
+ while (r->from.target_offset < from->target_offset && r->next)
{
r = r->next;
}
reallocated, the newly allocated relocations will be referenced
here along with the actual size allocated. The relocation
count will always be found in the section structure. */
- Elf_Internal_Rela *allocated_relocs;
+ Elf_Internal_Rela *allocated_relocs;
unsigned relocs_count;
unsigned allocated_relocs_count;
};
relax_info->fix_array = NULL;
relax_info->fix_array_count = 0;
- relax_info->allocated_relocs = NULL;
+ relax_info->allocated_relocs = NULL;
relax_info->relocs_count = 0;
relax_info->allocated_relocs_count = 0;
}
asection *src_sec;
bfd_vma src_offset;
unsigned src_type; /* Relocation type. */
-
+
asection *target_sec;
bfd_vma target_offset;
bfd_boolean translated;
-
+
reloc_bfd_fix *next;
};
static void
-clear_section_cache (section_cache_t *sec_cache)
+free_section_cache (section_cache_t *sec_cache)
{
if (sec_cache->sec)
{
release_internal_relocs (sec_cache->sec, sec_cache->relocs);
if (sec_cache->ptbl)
free (sec_cache->ptbl);
- memset (sec_cache, 0, sizeof (sec_cache));
}
}
goto err;
/* Fill in the new section cache. */
- clear_section_cache (sec_cache);
- memset (sec_cache, 0, sizeof (sec_cache));
+ free_section_cache (sec_cache);
+ init_section_cache (sec_cache);
sec_cache->sec = sec;
sec_cache->contents = contents;
sec_size = bfd_get_section_limit (abfd, sec);
contents = elf_section_data (sec)->this_hdr.contents;
-
+
if (contents == NULL && sec_size != 0)
{
if (!bfd_malloc_and_get_section (abfd, sec, &contents))
free (contents);
return NULL;
}
- if (keep_memory)
+ if (keep_memory)
elf_section_data (sec)->this_hdr.contents = contents;
}
return contents;
(bfd *, asection *, struct bfd_link_info *, value_map_hash_table *);
static Elf_Internal_Rela *get_irel_at_offset
(asection *, Elf_Internal_Rela *, bfd_vma);
-static bfd_boolean is_removable_literal
+static bfd_boolean is_removable_literal
(const source_reloc *, int, const source_reloc *, int, asection *,
property_table_entry *, int);
static bfd_boolean remove_dead_literal
(bfd *, asection *, struct bfd_link_info *, Elf_Internal_Rela *,
- Elf_Internal_Rela *, source_reloc *, property_table_entry *, int);
+ Elf_Internal_Rela *, source_reloc *, property_table_entry *, int);
static bfd_boolean identify_literal_placement
(bfd *, asection *, bfd_byte *, struct bfd_link_info *,
value_map_hash_table *, bfd_boolean *, Elf_Internal_Rela *, int,
static bfd_boolean relax_section_symbols (bfd *, asection *);
-static bfd_boolean
+static bfd_boolean
elf_xtensa_relax_section (bfd *abfd,
asection *sec,
struct bfd_link_info *link_info,
bfd_boolean is_relaxable = FALSE;
/* Initialize the per-section relaxation info. */
- for (abfd = link_info->input_bfds; abfd != NULL; abfd = abfd->link_next)
+ for (abfd = link_info->input_bfds; abfd != NULL; abfd = abfd->link.next)
for (sec = abfd->sections; sec != NULL; sec = sec->next)
{
init_xtensa_relax_info (sec);
}
/* Mark relaxable sections (and count relocations against each one). */
- for (abfd = link_info->input_bfds; abfd != NULL; abfd = abfd->link_next)
+ for (abfd = link_info->input_bfds; abfd != NULL; abfd = abfd->link.next)
for (sec = abfd->sections; sec != NULL; sec = sec->next)
{
if (!find_relaxable_sections (abfd, sec, link_info, &is_relaxable))
return TRUE;
/* Allocate space for source_relocs. */
- for (abfd = link_info->input_bfds; abfd != NULL; abfd = abfd->link_next)
+ for (abfd = link_info->input_bfds; abfd != NULL; abfd = abfd->link.next)
for (sec = abfd->sections; sec != NULL; sec = sec->next)
{
xtensa_relax_info *relax_info;
}
/* Collect info on relocations against each relaxable section. */
- for (abfd = link_info->input_bfds; abfd != NULL; abfd = abfd->link_next)
+ for (abfd = link_info->input_bfds; abfd != NULL; abfd = abfd->link.next)
for (sec = abfd->sections; sec != NULL; sec = sec->next)
{
if (!collect_source_relocs (abfd, sec, link_info))
}
/* Compute the text actions. */
- for (abfd = link_info->input_bfds; abfd != NULL; abfd = abfd->link_next)
+ for (abfd = link_info->input_bfds; abfd != NULL; abfd = abfd->link.next)
for (sec = abfd->sections; sec != NULL; sec = sec->next)
{
if (!compute_text_actions (abfd, sec, link_info))
internal_relocs = retrieve_internal_relocs (abfd, sec,
link_info->keep_memory);
- if (internal_relocs == NULL)
+ if (internal_relocs == NULL)
return ok;
contents = retrieve_contents (abfd, sec, link_info->keep_memory);
}
source_relax_info = get_xtensa_relax_info (sec);
- for (i = 0; i < sec->reloc_count; i++)
+ for (i = 0; i < sec->reloc_count; i++)
{
Elf_Internal_Rela *irel = &internal_relocs[i];
r_reloc r_rel;
unsigned i;
bfd_size_type sec_size;
- internal_relocs = retrieve_internal_relocs (abfd, sec,
+ internal_relocs = retrieve_internal_relocs (abfd, sec,
link_info->keep_memory);
- if (internal_relocs == NULL)
+ if (internal_relocs == NULL)
return ok;
sec_size = bfd_get_section_limit (abfd, sec);
}
/* Record relocations against relaxable literal sections. */
- for (i = 0; i < sec->reloc_count; i++)
+ for (i = 0; i < sec->reloc_count; i++)
{
Elf_Internal_Rela *irel = &internal_relocs[i];
r_reloc r_rel;
relocations associated with ASM_EXPANDs because they were just
added in the preceding loop over the relocations. */
- for (i = 0; i < sec->reloc_count; i++)
+ for (i = 0; i < sec->reloc_count; i++)
{
Elf_Internal_Rela *irel = &internal_relocs[i];
bfd_boolean is_reachable;
the l32r_irel. Note: The src_relocs array is not yet
sorted, but it wouldn't matter anyway because we're
searching by source offset instead of target offset. */
- s_reloc = find_source_reloc (target_relax_info->src_relocs,
+ s_reloc = find_source_reloc (target_relax_info->src_relocs,
target_relax_info->src_next,
sec, l32r_irel);
BFD_ASSERT (s_reloc);
if (contents == NULL)
return FALSE;
- if (ELF32_R_TYPE (irel->r_info) != R_XTENSA_ASM_EXPAND)
+ if (ELF32_R_TYPE (irel->r_info) != R_XTENSA_ASM_EXPAND)
return FALSE;
sec_size = bfd_get_section_limit (abfd, sec);
/* Optimization of longcalls that use CONST16 is not yet implemented. */
if (!uses_l32r)
return FALSE;
-
+
direct_call_opcode = swap_callx_for_call_opcode (opcode);
if (direct_call_opcode == XTENSA_UNDEFINED)
return FALSE;
shouldn't crash regardless. */
if (!target_sec->output_section)
return FALSE;
-
+
/* For relocatable sections, we can only simplify when the output
section of the target is the same as the output section of the
source. */
|| is_reloc_sym_weak (abfd, irel)))
return FALSE;
- self_address = (sec->output_section->vma
- + sec->output_offset + irel->r_offset + 3);
- dest_address = (target_sec->output_section->vma
- + target_sec->output_offset + target_offset);
-
+ if (target_sec->output_section != sec->output_section)
+ {
+ /* If the two sections are sufficiently far away that relaxation
+ might take the call out of range, we can't simplify. For
+ example, a positive displacement call into another memory
+ could get moved to a lower address due to literal removal,
+ but the destination won't move, and so the displacment might
+ get larger.
+
+ If the displacement is negative, assume the destination could
+ move as far back as the start of the output section. The
+ self_address will be at least as far into the output section
+ as it is prior to relaxation.
+
+ If the displacement is postive, assume the destination will be in
+ it's pre-relaxed location (because relaxation only makes sections
+ smaller). The self_address could go all the way to the beginning
+ of the output section. */
+
+ dest_address = target_sec->output_section->vma;
+ self_address = sec->output_section->vma;
+
+ if (sec->output_section->vma > target_sec->output_section->vma)
+ self_address += sec->output_offset + irel->r_offset + 3;
+ else
+ dest_address += bfd_get_section_limit (abfd, target_sec->output_section);
+ /* Call targets should be four-byte aligned. */
+ dest_address = (dest_address + 3) & ~3;
+ }
+ else
+ {
+
+ self_address = (sec->output_section->vma
+ + sec->output_offset + irel->r_offset + 3);
+ dest_address = (target_sec->output_section->vma
+ + target_sec->output_offset + target_offset);
+ }
+
*is_reachable_p = pcrel_reloc_fits (direct_call_opcode, 0,
self_address, dest_address);
{
unsigned i;
- for (i = 0; i < sec->reloc_count; i++)
+ for (i = 0; i < sec->reloc_count; i++)
{
Elf_Internal_Rela *irel = &internal_relocs[i];
return FALSE;
prev_opcode = insn_decode_opcode (contents, content_length, offset-3, 0);
return (xtensa_opcode_is_loop (xtensa_default_isa, prev_opcode) == 1);
-}
+}
/* Find all of the possible actions for an extended basic block. */
insn_len = insn_decode_len (ebb->contents, ebb->content_length,
offset);
- if (insn_len == 0)
+ if (insn_len == 0)
goto decode_error;
if (check_branch_target_aligned_address (offset, insn_len))
{
bfd_size_type simplify_size;
- simplify_size = get_asm_simplify_size (ebb->contents,
+ simplify_size = get_asm_simplify_size (ebb->contents,
ebb->content_length,
irel->r_offset);
if (simplify_size == 0)
ebb_propose_action (ebb_table, EBB_NO_ALIGN, 0,
ta_convert_longcall, offset, 0, TRUE);
-
+
offset += simplify_size;
continue;
}
};
-static int
+static int
xlate_compare (const void *a_v, const void *b_v)
{
const xlate_map_entry_t *a = (const xlate_map_entry_t *) a_v;
r = bsearch (&offset, map->entry, map->entry_count,
sizeof (xlate_map_entry_t), &xlate_compare);
e = (xlate_map_entry_t *) r;
-
+
BFD_ASSERT (e != NULL);
if (e == NULL)
return offset;
return NULL;
num_actions = action_list_count (action_list);
- map->entry = (xlate_map_entry_t *)
+ map->entry = (xlate_map_entry_t *)
bfd_malloc (sizeof (xlate_map_entry_t) * (num_actions + 1));
if (map->entry == NULL)
{
return NULL;
}
map->entry_count = 0;
-
+
removed = 0;
current_entry = &map->entry[0];
/* Free an offset translation map. */
-static void
+static void
free_xlate_map (xlate_map_t *map)
{
if (map && map->entry)
add an entry to the per-section list of removed literals. The
actual changes are deferred until the next pass. */
-static bfd_boolean
+static bfd_boolean
compute_removed_literals (bfd *abfd,
asection *sec,
struct bfd_link_info *link_info,
if (!relax_info->is_relaxable_literal_section)
return ok;
- internal_relocs = retrieve_internal_relocs (abfd, sec,
+ internal_relocs = retrieve_internal_relocs (abfd, sec,
link_info->keep_memory);
sec_size = bfd_get_section_limit (abfd, sec);
continue;
prev_i = i;
- if (last_loc_is_prev &&
+ if (last_loc_is_prev &&
last_target_offset + 4 != rel->r_rel.target_offset)
last_loc_is_prev = FALSE;
/* Check if the relocation was from an L32R that is being removed
because a CALLX was converted to a direct CALL, and check if
there are no other relocations to the literal. */
- if (is_removable_literal (rel, i, src_relocs, relax_info->src_count,
+ if (is_removable_literal (rel, i, src_relocs, relax_info->src_count,
sec, prop_table, ptblsize))
{
if (!remove_dead_literal (abfd, sec, link_info, internal_relocs,
}
if (!identify_literal_placement (abfd, sec, contents, link_info,
- values,
- &last_loc_is_prev, irel,
+ values,
+ &last_loc_is_prev, irel,
relax_info->src_count - i, rel,
prop_table, ptblsize,
&target_sec_cache, rel->is_abs_literal))
#endif /* DEBUG */
error_return:
- if (prop_table) free (prop_table);
- clear_section_cache (&target_sec_cache);
+ if (prop_table)
+ free (prop_table);
+ free_section_cache (&target_sec_cache);
release_contents (sec, contents);
release_internal_relocs (sec, internal_relocs);
unsigned r_type;
Elf_Internal_Rela key;
- if (!internal_relocs)
+ if (!internal_relocs)
return NULL;
key.r_offset = offset;
if (!rel->is_null)
return FALSE;
-
- entry = elf_xtensa_find_property_entry (prop_table, ptblsize,
+
+ entry = elf_xtensa_find_property_entry (prop_table, ptblsize,
sec->vma + rel->r_rel.target_offset);
if (entry && (entry->flags & XTENSA_PROP_NO_TRANSFORM))
return FALSE;
}
-bfd_boolean
+bfd_boolean
remove_dead_literal (bfd *abfd,
asection *sec,
struct bfd_link_info *link_info,
ta_remove_literal, sec, rel->r_rel.target_offset, 4);
/* If the section is 4-byte aligned, do not add fill. */
- if (sec->alignment_power > 2)
+ if (sec->alignment_power > 2)
{
int fill_extra_space;
bfd_vma entry_sec_offset;
}
-bfd_boolean
+bfd_boolean
identify_literal_placement (bfd *abfd,
asection *sec,
bfd_byte *contents,
/* For relocatable links, do not try to move literals. To do it
correctly might increase the number of relocations in an input
section making the default relocatable linking fail. */
- if (!link_info->relocatable && !literal_placed
+ if (!link_info->relocatable && !literal_placed
&& values->has_last_loc && !(*last_loc_is_prev_p))
{
asection *target_sec = r_reloc_get_section (&values->last_loc);
/* There is a last loc that was in the same output section. */
if (relocations_reach (rel, remaining_src_rels, &try_loc)
&& move_shared_literal (sec, link_info, rel,
- prop_table, ptblsize,
+ prop_table, ptblsize,
&try_loc, &val, target_sec_cache))
{
values->last_loc.virtual_offset += 4;
/* Move a literal to another literal location because it is
the same as the other literal value. */
-static bfd_boolean
+static bfd_boolean
coalesce_shared_literal (asection *sec,
source_reloc *rel,
property_table_entry *prop_table,
ta_remove_literal, sec, rel->r_rel.target_offset, 4);
/* If the section is 4-byte aligned, do not add fill. */
- if (sec->alignment_power > 2)
+ if (sec->alignment_power > 2)
{
int fill_extra_space;
bfd_vma entry_sec_offset;
total amount of space used because of alignments so we need to do
this carefully. Also, it may make a branch go out of range. */
-static bfd_boolean
+static bfd_boolean
move_shared_literal (asection *sec,
struct bfd_link_info *link_info,
source_reloc *rel,
return FALSE;
target_entry = elf_xtensa_find_property_entry
- (target_sec_cache->ptbl, target_sec_cache->pte_count,
+ (target_sec_cache->ptbl, target_sec_cache->pte_count,
target_sec->vma + target_loc->target_offset);
if (!target_entry)
init_ebb_constraint (&ebb_table);
ebb = &ebb_table.ebb;
- init_ebb (ebb, target_sec_cache->sec, target_sec_cache->contents,
+ init_ebb (ebb, target_sec_cache->sec, target_sec_cache->contents,
target_sec_cache->content_length,
target_sec_cache->ptbl, target_sec_cache->pte_count,
target_sec_cache->relocs, target_sec_cache->reloc_count);
-4 - (1 << target_sec->alignment_power), TRUE);
/* Check all of the PC-relative relocations to make sure they still fit. */
- relocs_fit = check_section_ebb_pcrels_fit (target_sec->owner, target_sec,
+ relocs_fit = check_section_ebb_pcrels_fit (target_sec->owner, target_sec,
target_sec_cache->contents,
target_sec_cache->relocs,
&ebb_table, NULL);
- if (!relocs_fit)
+ if (!relocs_fit)
return FALSE;
text_action_add_literal (&target_relax_info->action_list,
ta_add_literal, target_loc, lit_value, -4);
- if (target_sec->alignment_power > 2 && target_entry != src_entry)
+ if (target_sec->alignment_power > 2 && target_entry != src_entry)
{
/* May need to add or remove some fill to maintain alignment. */
int fill_extra_space;
bfd_vma entry_sec_offset;
- entry_sec_offset =
+ entry_sec_offset =
target_entry->address - target_sec->vma + target_entry->size;
/* If the literal range is at the end of the section,
ta_remove_literal, sec, rel->r_rel.target_offset, 4);
/* If the section is 4-byte aligned, do not add fill. */
- if (sec->alignment_power > 2 && target_entry != src_entry)
+ if (sec->alignment_power > 2 && target_entry != src_entry)
{
int fill_extra_space;
bfd_vma entry_sec_offset;
return relax_property_section (abfd, sec, link_info);
}
- internal_relocs = retrieve_internal_relocs (abfd, sec,
+ internal_relocs = retrieve_internal_relocs (abfd, sec,
link_info->keep_memory);
if (!internal_relocs && !relax_info->action_list.head)
return TRUE;
that here and adjust things accordingly. */
if (! elf_xtensa_ignore_discarded_relocs (sec)
&& elf_xtensa_action_discarded (sec) == PRETEND
- && sec->sec_info_type != ELF_INFO_TYPE_STABS
+ && sec->sec_info_type != SEC_INFO_TYPE_STABS
&& target_sec != NULL
- && elf_discarded_section (target_sec))
+ && discarded_section (target_sec))
{
/* It would be natural to call _bfd_elf_check_kept_section
here, but it's not exported from elflink.c. It's also a
|| r_type == R_XTENSA_DIFF16
|| r_type == R_XTENSA_DIFF32)
{
- bfd_vma diff_value = 0, new_end_offset, diff_mask = 0;
+ bfd_signed_vma diff_value = 0;
+ bfd_vma new_end_offset, diff_mask = 0;
if (bfd_get_section_limit (abfd, sec) < old_source_offset)
{
{
case R_XTENSA_DIFF8:
diff_value =
- bfd_get_8 (abfd, &contents[old_source_offset]);
+ bfd_get_signed_8 (abfd, &contents[old_source_offset]);
break;
case R_XTENSA_DIFF16:
diff_value =
- bfd_get_16 (abfd, &contents[old_source_offset]);
+ bfd_get_signed_16 (abfd, &contents[old_source_offset]);
break;
case R_XTENSA_DIFF32:
diff_value =
- bfd_get_32 (abfd, &contents[old_source_offset]);
+ bfd_get_signed_32 (abfd, &contents[old_source_offset]);
break;
}
switch (r_type)
{
case R_XTENSA_DIFF8:
- diff_mask = 0xff;
- bfd_put_8 (abfd, diff_value,
+ diff_mask = 0x7f;
+ bfd_put_signed_8 (abfd, diff_value,
&contents[old_source_offset]);
break;
case R_XTENSA_DIFF16:
- diff_mask = 0xffff;
- bfd_put_16 (abfd, diff_value,
+ diff_mask = 0x7fff;
+ bfd_put_signed_16 (abfd, diff_value,
&contents[old_source_offset]);
break;
case R_XTENSA_DIFF32:
- diff_mask = 0xffffffff;
- bfd_put_32 (abfd, diff_value,
+ diff_mask = 0x7fffffff;
+ bfd_put_signed_32 (abfd, diff_value,
&contents[old_source_offset]);
break;
}
- /* Check for overflow. */
- if ((diff_value & ~diff_mask) != 0)
+ /* Check for overflow. Sign bits must be all zeroes or all ones */
+ if ((diff_value & ~diff_mask) != 0 &&
+ (diff_value & ~diff_mask) != (-1 & ~diff_mask))
{
(*link_info->callbacks->reloc_dangerous)
(link_info, _("overflow after relaxation"),
dup_dot += copy_size;
}
virtual_action = TRUE;
- }
+ }
else
BFD_ASSERT (action->virtual_offset <= orig_dot_vo);
}
relax_info, &internal_relocs, &action->value))
goto error_return;
- if (virtual_action)
+ if (virtual_action)
orig_dot_vo += copy_size;
orig_dot += orig_insn_size;
}
-static bfd_boolean
+static bfd_boolean
translate_section_fixes (asection *sec)
{
xtensa_relax_info *relax_info;
/* Translate a fix given the mapping in the relax info for the target
section. If it has already been translated, no work is required. */
-static bfd_boolean
+static bfd_boolean
translate_reloc_bfd_fix (reloc_bfd_fix *fix)
{
reloc_bfd_fix new_fix;
target_offset);
}
- if (removed)
+ if (removed)
{
asection *new_sec;
/* This was moved to some other address (possibly another section). */
new_sec = r_reloc_get_section (&removed->to);
- if (new_sec != sec)
+ if (new_sec != sec)
{
sec = new_sec;
relax_info = get_xtensa_relax_info (sec);
- if (!relax_info ||
+ if (!relax_info ||
(!relax_info->is_relaxable_literal_section
&& !relax_info->is_relaxable_asm_section))
{
BFD_ASSERT (relax_info->allocated_relocs == NULL
|| sec->reloc_count == relax_info->relocs_count);
- if (relax_info->allocated_relocs_count == 0)
+ if (relax_info->allocated_relocs_count == 0)
new_relocs_count = (sec->reloc_count + 2) * 2;
else
new_relocs_count = (relax_info->allocated_relocs_count + 2) * 2;
if (insert_at != sec->reloc_count)
memcpy (new_relocs + insert_at + 1,
(*internal_relocs_p) + insert_at,
- (sec->reloc_count - insert_at)
+ (sec->reloc_count - insert_at)
* sizeof (Elf_Internal_Rela));
if (*internal_relocs_p != relax_info->allocated_relocs)
bfd_size_type entry_size;
sec_size = bfd_get_section_limit (abfd, sec);
- internal_relocs = retrieve_internal_relocs (abfd, sec,
+ internal_relocs = retrieve_internal_relocs (abfd, sec,
link_info->keep_memory);
contents = retrieve_contents (abfd, sec, link_info->keep_memory);
if (contents == NULL && sec_size != 0)
actual_offset = offset - removed_bytes;
size = bfd_get_32 (abfd, &contents[actual_offset + 4]);
- if (is_full_prop_section)
+ if (is_full_prop_section)
flags = bfd_get_32 (abfd, &contents[actual_offset + 8]);
else
flags = predef_flags;
bfd_vma new_address =
(offset_rel->r_addend
+ bfd_get_32 (abfd, &contents[actual_offset]));
- if (is_full_prop_section)
+ if (is_full_prop_section)
old_flags = bfd_get_32
(abfd, &contents[last_irel->r_offset + 8]);
else
dynobj = elf_hash_table (info)->dynobj;
sprintf (plt_name, ".plt.%u", chunk);
- return bfd_get_section_by_name (dynobj, plt_name);
+ return bfd_get_linker_section (dynobj, plt_name);
}
dynobj = elf_hash_table (info)->dynobj;
sprintf (got_name, ".got.plt.%u", chunk);
- return bfd_get_section_by_name (dynobj, got_name);
+ return bfd_get_linker_section (dynobj, got_name);
}
}
-static bfd_boolean
+static bfd_boolean
xtensa_is_property_section (asection *sec)
{
if (xtensa_is_insntable_section (sec)
}
-static bfd_boolean
+static bfd_boolean
xtensa_is_insntable_section (asection *sec)
{
if (CONST_STRNEQ (sec->name, XTENSA_INSN_SEC_NAME)
}
-static bfd_boolean
+static bfd_boolean
xtensa_is_littable_section (asection *sec)
{
if (CONST_STRNEQ (sec->name, XTENSA_LIT_SEC_NAME)
}
-static bfd_boolean
+static bfd_boolean
xtensa_is_proptable_section (asection *sec)
{
if (CONST_STRNEQ (sec->name, XTENSA_PROP_SEC_NAME)
{
const char *gname = inf;
const char *group_name = elf_group_name (sec);
-
+
return (group_name == gname
|| (group_name != NULL
&& gname != NULL
{
char *linkonce_kind = 0;
- if (strcmp (base_name, XTENSA_INSN_SEC_NAME) == 0)
+ if (strcmp (base_name, XTENSA_INSN_SEC_NAME) == 0)
linkonce_kind = "x.";
- else if (strcmp (base_name, XTENSA_LIT_SEC_NAME) == 0)
+ else if (strcmp (base_name, XTENSA_LIT_SEC_NAME) == 0)
linkonce_kind = "p.";
else if (strcmp (base_name, XTENSA_PROP_SEC_NAME) == 0)
linkonce_kind = "prop.";
/* Find the corresponding ".got.plt*" section. */
if (sec->name[4] == '\0')
- sgotplt = bfd_get_section_by_name (sec->owner, ".got.plt");
+ sgotplt = bfd_get_linker_section (sec->owner, ".got.plt");
else
{
char got_name[14];
chunk = strtol (&sec->name[5], NULL, 10);
sprintf (got_name, ".got.plt.%u", chunk);
- sgotplt = bfd_get_section_by_name (sec->owner, got_name);
+ sgotplt = bfd_get_linker_section (sec->owner, got_name);
}
BFD_ASSERT (sgotplt);
if (bfd_get_flavour (abfd) != bfd_target_elf_flavour)
return ok;
- internal_relocs = retrieve_internal_relocs (abfd, sec,
+ internal_relocs = retrieve_internal_relocs (abfd, sec,
link_info->keep_memory);
if (internal_relocs == NULL
|| sec->reloc_count == 0)
{ NULL, 0, 0, 0, 0 }
};
\f
+#define ELF_TARGET_ID XTENSA_ELF_DATA
#ifndef ELF_ARCH
-#define TARGET_LITTLE_SYM bfd_elf32_xtensa_le_vec
+#define TARGET_LITTLE_SYM xtensa_elf32_le_vec
#define TARGET_LITTLE_NAME "elf32-xtensa-le"
-#define TARGET_BIG_SYM bfd_elf32_xtensa_be_vec
+#define TARGET_BIG_SYM xtensa_elf32_be_vec
#define TARGET_BIG_NAME "elf32-xtensa-be"
#define ELF_ARCH bfd_arch_xtensa