/* Xtensa-specific support for 32-bit ELF.
- Copyright 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+ Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+ Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
int elf32xtensa_no_literal_movement = 1;
+/* Rename one of the generic section flags to better document how it
+ is used here. */
+/* Whether relocations have been processed. */
+#define reloc_done sec_flg0
\f
static reloc_howto_type elf_howto_table[] =
{
#define is_xtensa_elf(bfd) \
(bfd_get_flavour (bfd) == bfd_target_elf_flavour \
&& elf_tdata (bfd) != NULL \
- && elf_object_id (bfd) == XTENSA_ELF_TDATA)
+ && elf_object_id (bfd) == XTENSA_ELF_DATA)
static bfd_boolean
elf_xtensa_mkobject (bfd *abfd)
{
return bfd_elf_allocate_object (abfd, sizeof (struct elf_xtensa_obj_tdata),
- XTENSA_ELF_TDATA);
+ XTENSA_ELF_DATA);
}
/* Xtensa ELF linker hash table. */
/* Get the Xtensa ELF linker hash table from a link_info structure. */
#define elf_xtensa_hash_table(p) \
- ((struct elf_xtensa_link_hash_table *) ((p)->hash))
+ (elf_hash_table_id ((struct elf_link_hash_table *) ((p)->hash)) \
+ == XTENSA_ELF_DATA ? ((struct elf_xtensa_link_hash_table *) ((p)->hash)) : NULL)
/* Create an entry in an Xtensa ELF linker hash table. */
if (!_bfd_elf_link_hash_table_init (&ret->elf, abfd,
elf_xtensa_link_hash_newfunc,
- sizeof (struct elf_xtensa_link_hash_entry)))
+ sizeof (struct elf_xtensa_link_hash_entry),
+ XTENSA_ELF_DATA))
{
free (ret);
return NULL;
BFD_ASSERT (is_xtensa_elf (abfd));
htab = elf_xtensa_hash_table (info);
+ if (htab == NULL)
+ return FALSE;
+
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
sym_hashes = elf_sym_hashes (abfd);
{
if (is_plt)
{
- h->plt.refcount += 1;
- h->needs_plt = 1;
+ if (h->plt.refcount <= 0)
+ {
+ h->needs_plt = 1;
+ h->plt.refcount = 1;
+ }
+ else
+ h->plt.refcount += 1;
/* Keep track of the total PLT relocation count even if we
don't yet know whether the dynamic sections will be
}
}
else if (is_got)
- h->got.refcount += 1;
+ {
+ if (h->got.refcount <= 0)
+ h->got.refcount = 1;
+ else
+ h->got.refcount += 1;
+ }
if (is_tlsfunc)
eh->tlsfunc_refcount += 1;
struct elf_xtensa_link_hash_table *htab;
htab = elf_xtensa_hash_table (info);
+ if (htab == NULL)
+ return FALSE;
if (info->relocatable)
return TRUE;
flagword flags, noalloc_flags;
htab = elf_xtensa_hash_table (info);
+ if (htab == NULL)
+ return FALSE;
/* First do all the standard stuff. */
if (! _bfd_elf_create_dynamic_sections (dynobj, info))
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");
/* Create any extra PLT sections in case check_relocs has already
been called on all the non-dynamic input files. */
|| ! bfd_set_section_flags (dynobj, htab->sgotplt, flags))
return FALSE;
- /* Create ".rela.got". */
- htab->srelgot = bfd_make_section_with_flags (dynobj, ".rela.got", flags);
- if (htab->srelgot == NULL
- || ! bfd_set_section_alignment (dynobj, htab->srelgot, 2))
- return FALSE;
-
/* Create ".got.loc" (literal tables for use by dynamic linker). */
htab->sgotloc = bfd_make_section_with_flags (dynobj, ".got.loc", flags);
if (htab->sgotloc == NULL
info = (struct bfd_link_info *) arg;
htab = elf_xtensa_hash_table (info);
+ if (htab == NULL)
+ return FALSE;
/* If we saw any use of an IE model for this symbol, we can then optimize
away GOT entries for any TLSDESC_FN relocs. */
bfd *i;
htab = elf_xtensa_hash_table (info);
+ if (htab == NULL)
+ return;
for (i = info->input_bfds; i; i = i->link_next)
{
plt_chunks = 0;
htab = elf_xtensa_hash_table (info);
+ if (htab == NULL)
+ return FALSE;
+
dynobj = elf_hash_table (info)->dynobj;
if (dynobj == NULL)
abort ();
asection *tls_sec;
htab = elf_xtensa_hash_table (info);
+ if (htab == NULL)
+ return FALSE;
+
tls_sec = htab->elf.tls_sec;
if (tls_sec && (htab->tlsbase->tls_type & GOT_TLS_ANY) != 0)
if (!is_weak_undef)
{
/* Check for windowed CALL across a 1GB boundary. */
- xtensa_opcode opcode =
- get_expanded_call_opcode (contents + address,
- input_size - address, 0);
+ opcode = get_expanded_call_opcode (contents + address,
+ input_size - address, 0);
if (is_windowed_call_opcode (opcode))
{
if ((self_address >> CALL_SEGMENT_BITS)
BFD_ASSERT (is_xtensa_elf (input_bfd));
htab = elf_xtensa_hash_table (info);
+ if (htab == NULL)
+ return FALSE;
+
symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
sym_hashes = elf_sym_hashes (input_bfd);
local_got_tls_types = elf_xtensa_local_got_tls_type (input_bfd);
if (info->relocatable)
{
+ bfd_vma dest_addr;
+ asection * sym_sec = get_elf_r_symndx_section (input_bfd, r_symndx);
+
/* This is a relocatable link.
1) If the reloc is against a section symbol, adjust
according to the output section.
return FALSE;
}
+ dest_addr = sym_sec->output_section->vma + sym_sec->output_offset
+ + get_elf_r_symndx_offset (input_bfd, r_symndx) + rel->r_addend;
+
if (r_type == R_XTENSA_ASM_SIMPLIFY)
{
- char *error_message = NULL;
+ error_message = NULL;
/* Convert ASM_SIMPLIFY into the simpler relocation
so that they never escape a relaxing link. */
r = contract_asm_expansion (contents, input_size, rel,
to work around problems with DWARF in relocatable links
with some previous version of BFD. Now we can't easily get
rid of the hack without breaking backward compatibility.... */
- if (rel->r_addend)
+ r = bfd_reloc_ok;
+ howto = &elf_howto_table[r_type];
+ if (howto->partial_inplace && rel->r_addend)
{
- howto = &elf_howto_table[r_type];
- if (howto->partial_inplace)
+ r = elf_xtensa_do_reloc (howto, input_bfd, input_section,
+ rel->r_addend, contents,
+ rel->r_offset, FALSE,
+ &error_message);
+ rel->r_addend = 0;
+ }
+ else
+ {
+ /* Put the correct bits in the target instruction, even
+ though the relocation will still be present in the output
+ file. This makes disassembly clearer, as well as
+ allowing loadable kernel modules to work without needing
+ relocations on anything other than calls and l32r's. */
+
+ /* If it is not in the same section, there is nothing we can do. */
+ if (r_type >= R_XTENSA_SLOT0_OP && r_type <= R_XTENSA_SLOT14_OP &&
+ sym_sec->output_section == input_section->output_section)
{
r = elf_xtensa_do_reloc (howto, input_bfd, input_section,
- rel->r_addend, contents,
+ dest_addr, contents,
rel->r_offset, FALSE,
&error_message);
- if (r != bfd_reloc_ok)
- {
- if (!((*info->callbacks->reloc_dangerous)
- (info, error_message, input_bfd, input_section,
- rel->r_offset)))
- return FALSE;
- }
- rel->r_addend = 0;
}
}
+ if (r != bfd_reloc_ok)
+ {
+ if (!((*info->callbacks->reloc_dangerous)
+ (info, error_message, input_bfd, input_section,
+ rel->r_offset)))
+ return FALSE;
+ }
/* Done with work for relocatable link; continue with next reloc. */
continue;
for (n = 0; n < num; n++)
{
- bfd_boolean remove = FALSE;
+ bfd_boolean remove_entry = FALSE;
if (table[n].size == 0)
- remove = TRUE;
- else if (n > 0 &&
- (table[n-1].address + table[n-1].size == table[n].address))
+ remove_entry = TRUE;
+ else if (n > 0
+ && (table[n-1].address + table[n-1].size == table[n].address))
{
table[n-1].size += table[n].size;
- remove = TRUE;
+ remove_entry = TRUE;
}
- if (remove)
+ if (remove_entry)
{
for (m = n; m < num - 1; m++)
{
return TRUE;
htab = elf_xtensa_hash_table (info);
+ if (htab == NULL)
+ return FALSE;
+
dynobj = elf_hash_table (info)->dynobj;
sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
BFD_ASSERT (sdyn != NULL);
for (m_p = &l->head; *m_p && (*m_p)->offset <= offset; m_p = &(*m_p)->next)
{
text_action *t = *m_p;
- /* When the action is another fill at the same address,
- just increase the size. */
- if (t->offset == offset && t->action == ta_fill && action == ta_fill)
+
+ if (action == ta_fill)
{
- t->removed_bytes += removed;
- return;
+ /* When the action is another fill at the same address,
+ just increase the size. */
+ if (t->offset == offset && t->action == ta_fill)
+ {
+ t->removed_bytes += removed;
+ return;
+ }
+ /* Fills need to happen before widens so that we don't
+ insert fill bytes into the instruction stream. */
+ if (t->offset == offset && t->action == ta_widen_insn)
+ break;
}
}
text_action_list *action_list,
bfd_vma offset)
{
- xlate_map_entry_t tmp;
void *r;
xlate_map_entry_t *e;
if (map->entry_count == 0)
return offset;
- tmp.orig_address = offset;
- tmp.new_address = offset;
- tmp.size = 1;
-
r = bsearch (&offset, map->entry, map->entry_count,
sizeof (xlate_map_entry_t), &xlate_compare);
e = (xlate_map_entry_t *) r;
internal_relocs = retrieve_internal_relocs (abfd, sec,
link_info->keep_memory);
+ if (!internal_relocs && !relax_info->action_list.head)
+ return TRUE;
+
contents = retrieve_contents (abfd, sec, link_info->keep_memory);
if (contents == NULL && sec_size != 0)
{
bfd_boolean dynamic_symbol;
htab = elf_xtensa_hash_table (info);
+ if (htab == NULL)
+ return;
+
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
sym_hashes = elf_sym_hashes (abfd);
{
int r_type;
unsigned i;
- asection *target_sec;
reloc_bfd_fix *fix;
unsigned insert_at;
r_type = ELF32_R_TYPE (r_rel->rela.r_info);
- target_sec = r_reloc_get_section (r_rel);
/* This is the difficult case. We have to create a fix up. */
this_rela.r_offset = offset;
if (remove_this_rel)
{
offset_rel->r_info = ELF32_R_INFO (0, R_XTENSA_NONE);
- /* In case this is the last entry, move the relocation offset
- to the previous entry, if there is one. */
- if (offset_rel->r_offset >= bytes_to_remove)
- offset_rel->r_offset -= bytes_to_remove;
- else
- offset_rel->r_offset = 0;
+ offset_rel->r_offset = 0;
}
if (bytes_to_remove != 0)
if (chunk == 0)
{
htab = elf_xtensa_hash_table (info);
+ if (htab == NULL)
+ return NULL;
+
return htab->splt;
}
if (chunk == 0)
{
htab = elf_xtensa_hash_table (info);
+ if (htab == NULL)
+ return NULL;
return htab->sgotplt;
}