might be needed here. */
if (isym->st_other != 0)
{
+ unsigned char hvis, symvis, other;
+
+ /* Take the balance of OTHER from the definition. */
+ other = (definition ? isym->st_other : h->other);
+ other &= ~ ELF_ST_VISIBILITY (-1);
+
/* Combine visibilities, using the most constraining one. */
- unsigned char hvis = ELF_ST_VISIBILITY (h->other);
- unsigned char symvis = ELF_ST_VISIBILITY (isym->st_other);
-
- if (symvis && (hvis > symvis || hvis == 0))
- h->other = isym->st_other;
-
- /* If neither has visibility, use the st_other of the
- definition. This is an arbitrary choice, since the
- other bits have no general meaning. */
- if (!symvis && !hvis
- && (definition || h->other == 0))
- h->other = isym->st_other;
+ hvis = ELF_ST_VISIBILITY (h->other);
+ symvis = ELF_ST_VISIBILITY (isym->st_other);
+
+ h->other = other | (hvis > symvis ? hvis : symvis);
}
/* Set a flag in the hash table entry indicating the type of
}
}
- /* If this is a non-traditional, non-relocateable link, try to
- optimize the handling of the .stab/.stabstr sections. */
+ /* If this is a non-traditional link, try to optimize the handling
+ of the .stab/.stabstr sections. */
if (! dynamic
- && ! info->relocateable
&& ! info->traditional_format
&& info->hash->creator->flavour == bfd_target_elf_flavour
&& is_elf_hash_table (info)
|| ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY)
|| ! bfd_set_section_alignment (abfd, s, 2))
return false;
+ elf_hash_table (info)->eh_info.hdr_sec = s;
}
/* Create sections to hold version informations. These are removed
goto error_return;
}
- if (info->eh_frame_hdr && elf_hash_table (info)->dynobj)
+ if (info->eh_frame_hdr)
{
- o = bfd_get_section_by_name (elf_hash_table (info)->dynobj,
- ".eh_frame_hdr");
- if (o
- && (elf_section_data (o)->sec_info_type
- == ELF_INFO_TYPE_EH_FRAME_HDR))
- {
- if (! _bfd_elf_write_section_eh_frame_hdr (abfd, o))
- goto error_return;
- }
+ if (! _bfd_elf_write_section_eh_frame_hdr (abfd, info))
+ goto error_return;
}
if (finfo.symstrtab != NULL)
sym.st_info = ELF_ST_INFO (bindtype, ELF_ST_TYPE (sym.st_info));
}
- /* If a symbol is not defined locally, we clear the visibility
- field. */
+ /* If a symbol is not defined locally, we clear the visibility field. */
if (! finfo->info->relocateable
&& (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
- sym.st_other ^= ELF_ST_VISIBILITY (sym.st_other);
+ sym.st_other &= ~ ELF_ST_VISIBILITY (-1);
/* 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
from discarded sections and section symbols from
removed link-once sections. Complain about relocs
against discarded sections. Zero relocs against removed
- link-once sections. We should really complain if
- anything in the final link tries to use it, but
- DWARF-based exception handling might have an entry in
- .eh_frame to describe a routine in the linkonce section,
- and it turns out to be hard to remove the .eh_frame
- entry too. FIXME. */
+ link-once sections. */
if (!finfo->info->relocateable
&& !elf_section_ignore_discarded_relocs (o))
{
{
Elf_Internal_Rela *irela;
Elf_Internal_Rela *irelaend;
+ bfd_vma last_offset;
struct elf_link_hash_entry **rel_hash;
Elf_Internal_Shdr *input_rel_hdr, *input_rel_hdr2;
unsigned int next_erel;
rel_hash = (elf_section_data (o->output_section)->rel_hashes
+ elf_section_data (o->output_section)->rel_count
+ elf_section_data (o->output_section)->rel_count2);
+ last_offset = o->output_offset;
+ if (!finfo->info->relocateable)
+ last_offset += o->output_section->vma;
for (next_erel = 0; irela < irelaend; irela++, next_erel++)
{
unsigned long r_symndx;
next_erel = 0;
}
+ irela->r_offset = _bfd_elf_section_offset (output_bfd,
+ finfo->info, o,
+ irela->r_offset);
+ if (irela->r_offset >= (bfd_vma) -2)
+ {
+ /* This is a reloc for a deleted entry or somesuch.
+ Turn it into an R_*_NONE reloc, at the same
+ offset as the last reloc. elf_eh_frame.c and
+ elf_bfd_discard_info rely on reloc offsets
+ being ordered. */
+ irela->r_offset = last_offset;
+ irela->r_info = 0;
+ irela->r_addend = 0;
+ continue;
+ }
+
irela->r_offset += o->output_offset;
/* Relocs in an executable have to be virtual addresses. */
if (!finfo->info->relocateable)
irela->r_offset += o->output_section->vma;
- r_symndx = ELF_R_SYM (irela->r_info);
+ last_offset = irela->r_offset;
- if (r_symndx == 0)
+ r_symndx = ELF_R_SYM (irela->r_info);
+ if (r_symndx == STN_UNDEF)
continue;
if (r_symndx >= locsymcount
return false;
break;
case ELF_INFO_TYPE_MERGE:
- if (! (_bfd_write_merged_section
- (output_bfd, o, elf_section_data (o)->sec_info)))
+ if (! _bfd_write_merged_section (output_bfd, o,
+ elf_section_data (o)->sec_info))
return false;
break;
case ELF_INFO_TYPE_EH_FRAME:
{
- asection *ehdrsec;
-
- ehdrsec
- = bfd_get_section_by_name (elf_hash_table (finfo->info)->dynobj,
- ".eh_frame_hdr");
- if (! (_bfd_elf_write_section_eh_frame (output_bfd, o, ehdrsec,
- contents)))
+ if (! _bfd_elf_write_section_eh_frame (output_bfd, finfo->info,
+ o, contents))
return false;
}
break;
for (; rcookie->rel < rcookie->relend; rcookie->rel++)
{
- unsigned long r_symndx = ELF_R_SYM (rcookie->rel->r_info);
+ unsigned long r_symndx;
if (! rcookie->bad_symtab)
if (rcookie->rel->r_offset > offset)
if (rcookie->rel->r_offset != offset)
continue;
+ r_symndx = ELF_R_SYM (rcookie->rel->r_info);
+ if (r_symndx == SHN_UNDEF)
+ return true;
+
if (r_symndx >= rcookie->locsymcount
|| ELF_ST_BIND (rcookie->locsyms[r_symndx].st_info) != STB_LOCAL)
{
struct bfd_link_info *info;
{
struct elf_reloc_cookie cookie;
- asection *stab, *eh, *ehdr;
+ asection *stab, *eh;
Elf_Internal_Shdr *symtab_hdr;
struct elf_backend_data *bed;
bfd *abfd;
+ unsigned int count;
boolean ret = false;
- boolean strip = info->strip == strip_all || info->strip == strip_debugger;
- if (info->relocateable
- || info->traditional_format
+ if (info->traditional_format
|| info->hash->creator->flavour != bfd_target_elf_flavour
|| ! is_elf_hash_table (info))
return false;
- ehdr = NULL;
- if (elf_hash_table (info)->dynobj != NULL)
- ehdr = bfd_get_section_by_name (elf_hash_table (info)->dynobj,
- ".eh_frame_hdr");
-
for (abfd = info->input_bfds; abfd != NULL; abfd = abfd->link_next)
{
if (bfd_get_flavour (abfd) != bfd_target_elf_flavour)
if ((abfd->flags & DYNAMIC) != 0)
continue;
- eh = NULL;
- if (ehdr)
- {
- eh = bfd_get_section_by_name (abfd, ".eh_frame");
- if (eh && (eh->_raw_size == 0
- || bfd_is_abs_section (eh->output_section)))
- eh = NULL;
- }
+ eh = bfd_get_section_by_name (abfd, ".eh_frame");
+ if (eh != NULL
+ && (eh->_raw_size == 0
+ || bfd_is_abs_section (eh->output_section)))
+ eh = NULL;
- stab = NULL;
- if (!strip)
- {
- stab = bfd_get_section_by_name (abfd, ".stab");
- if (stab && (stab->_raw_size == 0
- || bfd_is_abs_section (stab->output_section)))
- stab = NULL;
- }
- if ((! stab
- || elf_section_data(stab)->sec_info_type != ELF_INFO_TYPE_STABS)
- && ! eh
- && (strip || ! bed->elf_backend_discard_info))
+ stab = bfd_get_section_by_name (abfd, ".stab");
+ if (stab != NULL
+ && (stab->_raw_size == 0
+ || bfd_is_abs_section (stab->output_section)
+ || elf_section_data (stab)->sec_info_type != ELF_INFO_TYPE_STABS))
+ stab = NULL;
+
+ if (stab == NULL
+ && eh == NULL
+ && bed->elf_backend_discard_info == NULL)
continue;
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
cookie.bad_symtab = elf_bad_symtab (abfd);
if (cookie.bad_symtab)
{
- cookie.locsymcount =
- symtab_hdr->sh_size / sizeof (Elf_External_Sym);
+ cookie.locsymcount = symtab_hdr->sh_size / sizeof (Elf_External_Sym);
cookie.extsymoff = 0;
}
else
return false;
}
- if (stab)
+ if (stab != NULL)
{
- cookie.rels = (NAME(_bfd_elf,link_read_relocs)
- (abfd, stab, (PTR) NULL, (Elf_Internal_Rela *) NULL,
- info->keep_memory));
- if (cookie.rels)
+ cookie.rels = NULL;
+ count = stab->reloc_count;
+ if (count != 0)
+ cookie.rels = (NAME(_bfd_elf,link_read_relocs)
+ (abfd, stab, (PTR) NULL, (Elf_Internal_Rela *) NULL,
+ info->keep_memory));
+ if (cookie.rels != NULL)
{
cookie.rel = cookie.rels;
- cookie.relend =
- cookie.rels + stab->reloc_count * bed->s->int_rels_per_ext_rel;
+ cookie.relend = cookie.rels;
+ cookie.relend += count * bed->s->int_rels_per_ext_rel;
if (_bfd_discard_section_stabs (abfd, stab,
elf_section_data (stab)->sec_info,
elf_reloc_symbol_deleted_p,
}
}
- if (eh)
+ if (eh != NULL)
{
cookie.rels = NULL;
- cookie.rel = NULL;
- cookie.relend = NULL;
- if (eh->reloc_count)
+ count = eh->reloc_count;
+ if (count != 0)
cookie.rels = (NAME(_bfd_elf,link_read_relocs)
(abfd, eh, (PTR) NULL, (Elf_Internal_Rela *) NULL,
info->keep_memory));
- if (cookie.rels)
- {
- cookie.rel = cookie.rels;
- cookie.relend =
- cookie.rels + eh->reloc_count * bed->s->int_rels_per_ext_rel;
- }
- if (_bfd_elf_discard_section_eh_frame (abfd, info, eh, ehdr,
+ cookie.rel = cookie.rels;
+ cookie.relend = cookie.rels;
+ if (cookie.rels != NULL)
+ cookie.relend += count * bed->s->int_rels_per_ext_rel;
+
+ if (_bfd_elf_discard_section_eh_frame (abfd, info, eh,
elf_reloc_symbol_deleted_p,
&cookie))
- {
- /* Relocs have been edited. Ensure edited version is
- used later in relocate_section. */
- elf_section_data (eh)->relocs = cookie.rels;
- ret = true;
- }
- if (cookie.rels && elf_section_data (eh)->relocs != cookie.rels)
+ ret = true;
+
+ if (cookie.rels != NULL
+ && elf_section_data (eh)->relocs != cookie.rels)
free (cookie.rels);
}
- if (bed->elf_backend_discard_info)
- {
- if (bed->elf_backend_discard_info (abfd, &cookie, info))
- ret = true;
- }
+ if (bed->elf_backend_discard_info != NULL
+ && (*bed->elf_backend_discard_info) (abfd, &cookie, info))
+ ret = true;
if (cookie.locsyms != NULL
&& symtab_hdr->contents != (unsigned char *) cookie.locsyms)
}
}
- if (ehdr && _bfd_elf_discard_section_eh_frame_hdr (output_bfd, info, ehdr))
+ if (info->eh_frame_hdr
+ && _bfd_elf_discard_section_eh_frame_hdr (output_bfd, info))
ret = true;
+
return ret;
}