/* ELF linking support for BFD.
Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
- 2005, 2006, 2007, 2008, 2009, 2010, 2011
+ 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
/* Silently discard TLS symbols from --just-syms. There's no way to
combine a static TLS block with a new TLS block for this executable. */
if (ELF_ST_TYPE (sym->st_info) == STT_TLS
- && sec->sec_info_type == ELF_INFO_TYPE_JUST_SYMS)
+ && sec->sec_info_type == SEC_INFO_TYPE_JUST_SYMS)
{
*skip = TRUE;
return TRUE;
over to the real definition. */
if (h->u.weakdef != NULL)
{
- struct elf_link_hash_entry *weakdef;
-
- weakdef = h->u.weakdef;
- while (h->root.type == bfd_link_hash_indirect)
- h = (struct elf_link_hash_entry *) h->root.u.i.link;
-
- BFD_ASSERT (h->root.type == bfd_link_hash_defined
- || h->root.type == bfd_link_hash_defweak);
- BFD_ASSERT (weakdef->def_dynamic);
-
/* If the real definition is defined by a regular object file,
don't do anything special. See the longer description in
_bfd_elf_adjust_dynamic_symbol, below. */
- if (weakdef->def_regular)
+ if (h->u.weakdef->def_regular)
h->u.weakdef = NULL;
else
{
+ struct elf_link_hash_entry *weakdef = h->u.weakdef;
+
+ while (h->root.type == bfd_link_hash_indirect)
+ h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
+ BFD_ASSERT (h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak);
+ BFD_ASSERT (weakdef->def_dynamic);
BFD_ASSERT (weakdef->root.type == bfd_link_hash_defined
|| weakdef->root.type == bfd_link_hash_defweak);
(*bed->elf_backend_copy_indirect_symbol) (eif->info, weakdef, h);
if ((h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak)
&& ((sec = h->root.u.def.section)->flags & SEC_MERGE)
- && sec->sec_info_type == ELF_INFO_TYPE_MERGE)
+ && sec->sec_info_type == SEC_INFO_TYPE_MERGE)
{
bfd *output_bfd = (bfd *) data;
/* ld --just-symbols and dynamic objects don't mix very well.
ld shouldn't allow it. */
if ((s = abfd->sections) != NULL
- && s->sec_info_type == ELF_INFO_TYPE_JUST_SYMS)
+ && s->sec_info_type == SEC_INFO_TYPE_JUST_SYMS)
abort ();
/* If this dynamic lib was specified on the command line with
sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
if (sec == NULL)
sec = bfd_abs_section_ptr;
- else if (elf_discarded_section (sec))
+ else if (discarded_section (sec))
{
/* Symbols from discarded section are undefined. We keep
its visibility. */
&string_offset))
goto error_return;
if (secdata->sec_info)
- stab->sec_info_type = ELF_INFO_TYPE_STABS;
+ stab->sec_info_type = SEC_INFO_TYPE_STABS;
}
}
}
return TRUE;
}
\f
-/* Indicate that we are only retrieving symbol values from this
- section. */
-
-void
-_bfd_elf_link_just_syms (asection *sec, struct bfd_link_info *info)
-{
- if (is_elf_hash_table (info->hash))
- sec->sec_info_type = ELF_INFO_TYPE_JUST_SYMS;
- _bfd_generic_link_just_syms (sec, info);
-}
-
/* Make sure sec_info_type is cleared if sec_info is cleared too. */
static void
merge_sections_remove_hook (bfd *abfd ATTRIBUTE_UNUSED,
asection *sec)
{
- BFD_ASSERT (sec->sec_info_type == ELF_INFO_TYPE_MERGE);
- sec->sec_info_type = ELF_INFO_TYPE_NONE;
+ BFD_ASSERT (sec->sec_info_type == SEC_INFO_TYPE_MERGE);
+ sec->sec_info_type = SEC_INFO_TYPE_NONE;
}
/* Finish SHF_MERGE section merging. */
sec, &secdata->sec_info))
return FALSE;
else if (secdata->sec_info)
- sec->sec_info_type = ELF_INFO_TYPE_MERGE;
+ sec->sec_info_type = SEC_INFO_TYPE_MERGE;
}
if (elf_hash_table (info)->merge_info != NULL)
else if ((h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak)
&& ((finfo->info->strip_discarded
- && elf_discarded_section (h->root.u.def.section))
+ && discarded_section (h->root.u.def.section))
|| (h->root.u.def.section->owner != NULL
&& (h->root.u.def.section->owner->flags & BFD_PLUGIN) != 0)))
strip = TRUE;
/* If this symbol should be put in the .dynsym section, then put it
there now. We already know the symbol index. We also fill in
the entry in the .hash section. */
- if (h->dynindx != -1
+ if (finfo->dynsym_sec != NULL
+ && h->dynindx != -1
&& elf_hash_table (finfo->info)->dynamic_sections_created)
{
bfd_byte *esym;
switch (sec->sec_info_type)
{
- case ELF_INFO_TYPE_STABS:
- case ELF_INFO_TYPE_EH_FRAME:
+ case SEC_INFO_TYPE_STABS:
+ case SEC_INFO_TYPE_EH_FRAME:
return TRUE;
default:
break;
*ppsection = NULL;
continue;
}
- else if (isec->sec_info_type == ELF_INFO_TYPE_MERGE
+ else if (isec->sec_info_type == SEC_INFO_TYPE_MERGE
&& ELF_ST_TYPE (isym->st_info) != STT_SECTION)
isym->st_value =
_bfd_merged_section_offset (output_bfd, &isec,
{
/* Complain if the definition comes from a
discarded section. */
- if ((sec = *ps) != NULL && elf_discarded_section (sec))
+ if ((sec = *ps) != NULL && discarded_section (sec))
{
BFD_ASSERT (r_symndx != STN_UNDEF);
if (action_discarded & COMPLAIN)
r_symndx = osec->target_index;
if (r_symndx == STN_UNDEF)
{
- struct elf_link_hash_table *htab;
- asection *oi;
-
- htab = elf_hash_table (finfo->info);
- oi = htab->text_index_section;
- if ((osec->flags & SEC_READONLY) == 0
- && htab->data_index_section != NULL)
- oi = htab->data_index_section;
-
- if (oi != NULL)
- {
- irela->r_addend += osec->vma - oi->vma;
- r_symndx = oi->target_index;
- }
+ irela->r_addend += osec->vma;
+ osec = _bfd_nearby_section (output_bfd, osec,
+ osec->vma);
+ irela->r_addend -= osec->vma;
+ r_symndx = osec->target_index;
}
-
- BFD_ASSERT (r_symndx != STN_UNDEF);
}
}
}
else switch (o->sec_info_type)
{
- case ELF_INFO_TYPE_STABS:
+ case SEC_INFO_TYPE_STABS:
if (! (_bfd_write_section_stabs
(output_bfd,
&elf_hash_table (finfo->info)->stab_info,
o, &elf_section_data (o)->sec_info, contents)))
return FALSE;
break;
- case ELF_INFO_TYPE_MERGE:
+ case SEC_INFO_TYPE_MERGE:
if (! _bfd_write_merged_section (output_bfd, o,
elf_section_data (o)->sec_info))
return FALSE;
break;
- case ELF_INFO_TYPE_EH_FRAME:
+ case SEC_INFO_TYPE_EH_FRAME:
{
if (! _bfd_elf_write_section_eh_frame (output_bfd, finfo->info,
o, contents))
{
finfo.dynsym_sec = bfd_get_section_by_name (dynobj, ".dynsym");
finfo.hash_sec = bfd_get_section_by_name (dynobj, ".hash");
- BFD_ASSERT (finfo.dynsym_sec != NULL);
+ /* Note that dynsym_sec can be NULL (on VMS). */
finfo.symver_sec = bfd_get_section_by_name (dynobj, ".gnu.version");
/* Note that it is OK if symver_sec is NULL. */
}
if (sec->flags & SEC_MERGE)
merged = TRUE;
- if (info->relocatable || info->emitrelocations)
+ if (esdo->this_hdr.sh_type == SHT_REL
+ || esdo->this_hdr.sh_type == SHT_RELA)
+ /* Some backends use reloc_count in relocation sections
+ to count particular types of relocs. Of course,
+ reloc sections themselves can't have relocations. */
+ reloc_count = 0;
+ else if (info->relocatable || info->emitrelocations)
reloc_count = sec->reloc_count;
else if (bed->elf_backend_count_relocs)
reloc_count = (*bed->elf_backend_count_relocs) (info, sec);
symtab_hdr->sh_info = bfd_get_symcount (abfd);
if (dynamic
+ && finfo.dynsym_sec != NULL
&& finfo.dynsym_sec->output_section != bfd_abs_section_ptr)
{
Elf_Internal_Sym sym;
goto error_return;
/* Check for DT_TEXTREL (late, in case the backend removes it). */
- if ((info->warn_shared_textrel && info->shared)
- || info->error_textrel)
+ if (((info->warn_shared_textrel && info->shared)
+ || info->error_textrel)
+ && (o = bfd_get_section_by_name (dynobj, ".dynamic")) != NULL)
{
bfd_byte *dyncon, *dynconend;
- /* Fix up .dynamic entries. */
- o = bfd_get_section_by_name (dynobj, ".dynamic");
- BFD_ASSERT (o != NULL);
-
dyncon = o->contents;
dynconend = o->contents + o->size;
for (; dyncon < dynconend; dyncon += bed->s->sizeof_dyn)
|| h->root.type == bfd_link_hash_warning)
h = (struct elf_link_hash_entry *) h->root.u.i.link;
h->mark = 1;
+ /* If this symbol is weak and there is a non-weak definition, we
+ keep the non-weak definition because many backends put
+ dynamic reloc info on the non-weak definition for code
+ handling copy relocs. */
+ if (h->u.weakdef != NULL)
+ h->u.weakdef->mark = 1;
return (*gc_mark_hook) (sec, info, cookie->rel, h, NULL);
}
rsec = _bfd_elf_gc_mark_rsec (info, sec, gc_mark_hook, cookie);
if (rsec && !rsec->gc_mark)
{
- if (bfd_get_flavour (rsec->owner) != bfd_target_elf_flavour)
+ if (bfd_get_flavour (rsec->owner) != bfd_target_elf_flavour
+ || (rsec->owner->flags & DYNAMIC) != 0)
rsec->gc_mark = 1;
else if (!_bfd_elf_gc_mark (info, rsec, gc_mark_hook))
return FALSE;
if (!h->mark
&& (((h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak)
- && !h->root.u.def.section->gc_mark)
+ && !(h->def_regular
+ && h->root.u.def.section->gc_mark))
|| h->root.type == bfd_link_hash_undefined
|| h->root.type == bfd_link_hash_undefweak))
{
if ((h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak)
- && elf_discarded_section (h->root.u.def.section))
+ && discarded_section (h->root.u.def.section))
return TRUE;
else
return FALSE;
/* Need to: get the symbol; get the section. */
isym = &rcookie->locsyms[r_symndx];
isec = bfd_section_from_elf_index (rcookie->abfd, isym->st_shndx);
- if (isec != NULL && elf_discarded_section (isec))
+ if (isec != NULL && discarded_section (isec))
return TRUE;
}
return FALSE;
if (stab != NULL
&& (stab->size == 0
|| bfd_is_abs_section (stab->output_section)
- || stab->sec_info_type != ELF_INFO_TYPE_STABS))
+ || stab->sec_info_type != SEC_INFO_TYPE_STABS))
stab = NULL;
if (stab == NULL