/* Xtensa-specific support for 32-bit ELF.
- Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+ Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
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[] =
{
/* 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)
/* 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;
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;
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)
{
+ 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)
{
error_message = NULL;
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;
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;
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;
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);
}
}
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;
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;
#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);
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)
{
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
{
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;
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);
}
/* 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);
{ 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_NAME "elf32-xtensa-le"