flags = bed->dynamic_sec_flags;
- s = bfd_make_section_with_flags (abfd,
- (bed->rela_plts_and_copies_p
- ? ".rela.got" : ".rel.got"),
- (bed->dynamic_sec_flags
- | SEC_READONLY));
+ s = bfd_make_section_anyway_with_flags (abfd,
+ (bed->rela_plts_and_copies_p
+ ? ".rela.got" : ".rel.got"),
+ (bed->dynamic_sec_flags
+ | SEC_READONLY));
if (s == NULL
|| ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align))
return FALSE;
htab->srelgot = s;
- s = bfd_make_section_with_flags (abfd, ".got", flags);
+ s = bfd_make_section_anyway_with_flags (abfd, ".got", flags);
if (s == NULL
|| !bfd_set_section_alignment (abfd, s, bed->s->log_file_align))
return FALSE;
if (bed->want_got_plt)
{
- s = bfd_make_section_with_flags (abfd, ".got.plt", flags);
+ s = bfd_make_section_anyway_with_flags (abfd, ".got.plt", flags);
if (s == NULL
|| !bfd_set_section_alignment (abfd, s,
bed->s->log_file_align))
shared library does not. */
if (info->executable)
{
- s = bfd_make_section_with_flags (abfd, ".interp",
- flags | SEC_READONLY);
+ s = bfd_make_section_anyway_with_flags (abfd, ".interp",
+ flags | SEC_READONLY);
if (s == NULL)
return FALSE;
}
/* Create sections to hold version informations. These are removed
if they are not needed. */
- s = bfd_make_section_with_flags (abfd, ".gnu.version_d",
- flags | SEC_READONLY);
+ s = bfd_make_section_anyway_with_flags (abfd, ".gnu.version_d",
+ flags | SEC_READONLY);
if (s == NULL
|| ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align))
return FALSE;
- s = bfd_make_section_with_flags (abfd, ".gnu.version",
- flags | SEC_READONLY);
+ s = bfd_make_section_anyway_with_flags (abfd, ".gnu.version",
+ flags | SEC_READONLY);
if (s == NULL
|| ! bfd_set_section_alignment (abfd, s, 1))
return FALSE;
- s = bfd_make_section_with_flags (abfd, ".gnu.version_r",
- flags | SEC_READONLY);
+ s = bfd_make_section_anyway_with_flags (abfd, ".gnu.version_r",
+ flags | SEC_READONLY);
if (s == NULL
|| ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align))
return FALSE;
- s = bfd_make_section_with_flags (abfd, ".dynsym",
- flags | SEC_READONLY);
+ s = bfd_make_section_anyway_with_flags (abfd, ".dynsym",
+ flags | SEC_READONLY);
if (s == NULL
|| ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align))
return FALSE;
- s = bfd_make_section_with_flags (abfd, ".dynstr",
- flags | SEC_READONLY);
+ s = bfd_make_section_anyway_with_flags (abfd, ".dynstr",
+ flags | SEC_READONLY);
if (s == NULL)
return FALSE;
- s = bfd_make_section_with_flags (abfd, ".dynamic", flags);
+ s = bfd_make_section_anyway_with_flags (abfd, ".dynamic", flags);
if (s == NULL
|| ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align))
return FALSE;
if (info->emit_hash)
{
- s = bfd_make_section_with_flags (abfd, ".hash", flags | SEC_READONLY);
+ s = bfd_make_section_anyway_with_flags (abfd, ".hash",
+ flags | SEC_READONLY);
if (s == NULL
|| ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align))
return FALSE;
if (info->emit_gnu_hash)
{
- s = bfd_make_section_with_flags (abfd, ".gnu.hash",
- flags | SEC_READONLY);
+ s = bfd_make_section_anyway_with_flags (abfd, ".gnu.hash",
+ flags | SEC_READONLY);
if (s == NULL
|| ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align))
return FALSE;
if (bed->plt_readonly)
pltflags |= SEC_READONLY;
- s = bfd_make_section_with_flags (abfd, ".plt", pltflags);
+ s = bfd_make_section_anyway_with_flags (abfd, ".plt", pltflags);
if (s == NULL
|| ! bfd_set_section_alignment (abfd, s, bed->plt_alignment))
return FALSE;
return FALSE;
}
- s = bfd_make_section_with_flags (abfd,
- (bed->rela_plts_and_copies_p
- ? ".rela.plt" : ".rel.plt"),
- flags | SEC_READONLY);
+ s = bfd_make_section_anyway_with_flags (abfd,
+ (bed->rela_plts_and_copies_p
+ ? ".rela.plt" : ".rel.plt"),
+ flags | SEC_READONLY);
if (s == NULL
|| ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align))
return FALSE;
image and use a R_*_COPY reloc to tell the dynamic linker to
initialize them at run time. The linker script puts the .dynbss
section into the .bss section of the final image. */
- s = bfd_make_section_with_flags (abfd, ".dynbss",
- (SEC_ALLOC
- | SEC_LINKER_CREATED));
+ s = bfd_make_section_anyway_with_flags (abfd, ".dynbss",
+ (SEC_ALLOC | SEC_LINKER_CREATED));
if (s == NULL)
return FALSE;
copy relocs. */
if (! info->shared)
{
- s = bfd_make_section_with_flags (abfd,
- (bed->rela_plts_and_copies_p
- ? ".rela.bss" : ".rel.bss"),
- flags | SEC_READONLY);
+ s = bfd_make_section_anyway_with_flags (abfd,
+ (bed->rela_plts_and_copies_p
+ ? ".rela.bss" : ".rel.bss"),
+ flags | SEC_READONLY);
if (s == NULL
|| ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align))
return FALSE;
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);
dynsym = TRUE;
}
+ /* We don't want to make debug symbol dynamic. */
if (definition && (sec->flags & SEC_DEBUGGING) && !info->relocatable)
- {
- /* We don't want to make debug symbol dynamic. */
- dynsym = FALSE;
- }
+ dynsym = FALSE;
+
+ /* Nor should we make plugin symbols dynamic. */
+ if ((abfd->flags & BFD_PLUGIN) != 0)
+ dynsym = FALSE;
if (definition)
h->target_internal = isym->st_target_internal;
{
struct bfd_hash_entry *p;
struct elf_link_hash_entry *h;
+ bfd_size_type size;
+ unsigned int alignment_power;
for (p = htab->root.table.table[i]; p != NULL; p = p->next)
{
if (h->dynindx >= old_dynsymcount)
_bfd_elf_strtab_delref (htab->dynstr, h->dynstr_index);
+ /* Preserve the maximum alignment and size for common
+ symbols even if this dynamic lib isn't on DT_NEEDED
+ since it can still be loaded at the run-time by another
+ dynamic lib. */
+ if (h->root.type == bfd_link_hash_common)
+ {
+ size = h->root.u.c.size;
+ alignment_power = h->root.u.c.p->alignment_power;
+ }
+ else
+ {
+ size = 0;
+ alignment_power = 0;
+ }
memcpy (p, old_ent, htab->root.table.entsize);
old_ent = (char *) old_ent + htab->root.table.entsize;
h = (struct elf_link_hash_entry *) p;
memcpy (h->root.u.i.link, old_ent, htab->root.table.entsize);
old_ent = (char *) old_ent + htab->root.table.entsize;
}
+ else if (h->root.type == bfd_link_hash_common)
+ {
+ if (size > h->root.u.c.size)
+ h->root.u.c.size = size;
+ if (alignment_power > h->root.u.c.p->alignment_power)
+ h->root.u.c.p->alignment_power = alignment_power;
+ }
}
}
/* We should also warn if a forced local symbol is referenced from
shared libraries. */
- if (! finfo->info->relocatable
- && (! finfo->info->shared)
+ if (!finfo->info->relocatable
+ && finfo->info->executable
&& h->forced_local
&& h->ref_dynamic
+ && h->def_regular
&& !h->dynamic_def
&& !h->dynamic_weak
&& ! elf_link_check_versioned_symbol (finfo->info, bed, h))
/* 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;
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);
}
}
{
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. */
}
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)
+ 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)
if (dyn.d_tag == DT_TEXTREL)
{
- info->callbacks->einfo
- (_("%P: warning: creating a DT_TEXTREL in a shared object.\n"));
+ if (info->error_textrel)
+ info->callbacks->einfo
+ (_("%P%X: read-only segment has dynamic relocations.\n"));
+ else
+ info->callbacks->einfo
+ (_("%P: warning: creating a DT_TEXTREL in a shared object.\n"));
break;
}
}
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;
+ 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;
static bfd_boolean
elf_gc_sweep_symbol (struct elf_link_hash_entry *h, void *data)
{
- if (((h->root.type == bfd_link_hash_defined
- || h->root.type == bfd_link_hash_defweak)
- && !h->root.u.def.section->gc_mark
- && (!(h->root.u.def.section->owner->flags & DYNAMIC)
- || (h->plt.refcount <= 0
- && h->got.refcount <= 0)))
- || (h->root.type == bfd_link_hash_undefined
- && h->plt.refcount <= 0
- && h->got.refcount <= 0))
- {
- struct elf_gc_sweep_symbol_info *inf =
- (struct elf_gc_sweep_symbol_info *) data;
+ if (!h->mark
+ && (((h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ && !(h->def_regular
+ && h->root.u.def.section->gc_mark))
+ || h->root.type == bfd_link_hash_undefined
+ || h->root.type == bfd_link_hash_undefweak))
+ {
+ struct elf_gc_sweep_symbol_info *inf;
+
+ inf = (struct elf_gc_sweep_symbol_info *) data;
(*inf->hide_symbol) (inf->info, h, TRUE);
+ h->def_regular = 0;
+ h->ref_regular = 0;
+ h->ref_regular_nonweak = 0;
}
return TRUE;
if ((h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak)
&& (h->ref_dynamic
- || (!info->executable
+ || ((!info->executable || info->export_dynamic)
&& h->def_regular
&& ELF_ST_VISIBILITY (h->other) != STV_INTERNAL
&& ELF_ST_VISIBILITY (h->other) != STV_HIDDEN