&& (ELF_ST_TYPE (sym->st_info) == STT_OBJECT
|| ELF_ST_TYPE (sym->st_info) == STT_COMMON))))
|| (d != NULL
- && h->root.type == bfd_link_hash_new
+ && h->non_elf
&& (*d->match) (&d->head, NULL, h->root.root.string)))
h->dynamic = 1;
}
}
}
+ /* Symbols defined in a linker script but not referenced anywhere
+ else will have non_elf set. */
+ if (h->non_elf)
+ {
+ bfd_elf_link_mark_dynamic_symbol (info, h, NULL);
+ h->non_elf = 0;
+ }
+
switch (h->root.type)
{
case bfd_link_hash_defined:
bfd_link_repair_undef_list (&htab->root);
break;
case bfd_link_hash_new:
- bfd_elf_link_mark_dynamic_symbol (info, h, NULL);
- h->non_elf = 0;
break;
case bfd_link_hash_indirect:
/* We had a versioned symbol in a dynamic library. We make the
oldfunc = (h->type != STT_NOTYPE
&& bed->is_function_type (h->type));
- /* If creating a default indirect symbol ("foo" or "foo@") from a
- dynamic versioned definition ("foo@@") skip doing so if there is
- an existing regular definition with a different type. We don't
- want, for example, a "time" variable in the executable overriding
- a "time" function in a shared library. */
- if (pold_alignment == NULL
- && newdyn
- && newdef
- && !olddyn
- && (olddef || h->root.type == bfd_link_hash_common)
+ if (!(newfunc && oldfunc)
&& ELF_ST_TYPE (sym->st_info) != h->type
&& ELF_ST_TYPE (sym->st_info) != STT_NOTYPE
&& h->type != STT_NOTYPE
- && !(newfunc && oldfunc))
+ && (newdef || bfd_is_com_section (sec))
+ && (olddef || h->root.type == bfd_link_hash_common))
{
- *skip = TRUE;
- return TRUE;
+ /* If creating a default indirect symbol ("foo" or "foo@") from
+ a dynamic versioned definition ("foo@@") skip doing so if
+ there is an existing regular definition with a different
+ type. We don't want, for example, a "time" variable in the
+ executable overriding a "time" function in a shared library. */
+ if (newdyn
+ && !olddyn)
+ {
+ *skip = TRUE;
+ return TRUE;
+ }
+
+ /* When adding a symbol from a regular object file after we have
+ created indirect symbols, undo the indirection and any
+ dynamic state. */
+ if (hi != h
+ && !newdyn
+ && olddyn)
+ {
+ h = hi;
+ (*bed->elf_backend_hide_symbol) (info, h, TRUE);
+ h->forced_local = 0;
+ h->ref_dynamic = 0;
+ h->def_dynamic = 0;
+ h->dynamic_def = 0;
+ if (h->root.u.undef.next || info->hash->undefs_tail == &h->root)
+ {
+ h->root.type = bfd_link_hash_undefined;
+ h->root.u.undef.abfd = abfd;
+ }
+ else
+ {
+ h->root.type = bfd_link_hash_new;
+ h->root.u.undef.abfd = NULL;
+ }
+ return TRUE;
+ }
}
/* Check TLS symbols. We don't check undefined symbols introduced
/* xgettext:c-format */
(_("%s: TLS definition in %B section %A "
"mismatches non-TLS definition in %B section %A"),
- tbfd, tsec, ntbfd, ntsec, h->root.root.string);
+ h->root.root.string, tbfd, tsec, ntbfd, ntsec);
else if (!tdef && !ntdef)
_bfd_error_handler
/* xgettext:c-format */
(_("%s: TLS reference in %B "
"mismatches non-TLS reference in %B"),
- tbfd, ntbfd, h->root.root.string);
+ h->root.root.string, tbfd, ntbfd);
else if (tdef)
_bfd_error_handler
/* xgettext:c-format */
(_("%s: TLS definition in %B section %A "
"mismatches non-TLS reference in %B"),
- tbfd, tsec, ntbfd, h->root.root.string);
+ h->root.root.string, tbfd, tsec, ntbfd);
else
_bfd_error_handler
/* xgettext:c-format */
(_("%s: TLS reference in %B "
"mismatches non-TLS definition in %B section %A"),
- tbfd, ntbfd, ntsec, h->root.root.string);
+ h->root.root.string, tbfd, ntbfd, ntsec);
bfd_set_error (bfd_error_bad_value);
return FALSE;
represent variables; this can cause confusion in principle, but
any such confusion would seem to indicate an erroneous program or
shared library. We also permit a common symbol in a regular
- object to override a weak symbol in a shared object. A common
- symbol in executable also overrides a symbol in a shared object. */
+ object to override a weak symbol in a shared object. */
if (newdyn
&& newdef
&& (olddef
|| (h->root.type == bfd_link_hash_common
- && (newweak
- || newfunc
- || (!olddyn && bfd_link_executable (info))))))
+ && (newweak || newfunc))))
{
*override = TRUE;
newdef = FALSE;
/* xgettext:c-format */
(_("%B: bad reloc symbol index (0x%lx >= 0x%lx)"
" for offset 0x%lx in section `%A'"),
- abfd, sec,
- (unsigned long) r_symndx, (unsigned long) nsyms, irela->r_offset);
+ abfd, (unsigned long) r_symndx, (unsigned long) nsyms,
+ irela->r_offset, sec);
bfd_set_error (bfd_error_bad_value);
return FALSE;
}
{
_bfd_error_handler
/* xgettext:c-format */
- (_("%B: non-zero symbol index (0x%lx) for offset 0x%lx in section `%A'"
+ (_("%B: non-zero symbol index (0x%lx)"
+ " for offset 0x%lx in section `%A'"
" when the object file has no symbol table"),
- abfd, sec,
- (unsigned long) r_symndx, (unsigned long) nsyms, irela->r_offset);
+ abfd, (unsigned long) r_symndx, (unsigned long) nsyms,
+ irela->r_offset, sec);
bfd_set_error (bfd_error_bad_value);
return FALSE;
}
if (! _bfd_elf_fix_symbol_flags (h, eif))
return FALSE;
+ if (h->root.type == bfd_link_hash_undefweak)
+ {
+ if (eif->info->dynamic_undefined_weak == 0)
+ _bfd_elf_link_hash_hide_symbol (eif->info, h, TRUE);
+ else if (eif->info->dynamic_undefined_weak > 0
+ && h->ref_regular
+ && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+ && !bfd_hide_sym_by_version (eif->info->version_info,
+ h->root.root.string))
+ {
+ if (!bfd_elf_link_record_dynamic_symbol (eif->info, h))
+ {
+ eif->failed = TRUE;
+ return FALSE;
+ }
+ }
+ }
+
/* If this symbol does not require a PLT entry, and it is not
defined by a dynamic object, or is not referenced by a regular
object, ignore it. We do have to handle a weak defined symbol,
to resolve local to the current module, and false otherwise. Differs
from (the inverse of) _bfd_elf_dynamic_symbol_p in the treatment of
undefined symbols. The two functions are virtually identical except
- for the place where forced_local and dynindx == -1 are tested. If
- either of those tests are true, _bfd_elf_dynamic_symbol_p will say
- the symbol is local, while _bfd_elf_symbol_refs_local_p will say
- the symbol is local only for defined symbols.
+ for the place where dynindx == -1 is tested. If that test is true,
+ _bfd_elf_dynamic_symbol_p will say the symbol is local, while
+ _bfd_elf_symbol_refs_local_p will say the symbol is local only for
+ defined symbols.
It might seem that _bfd_elf_dynamic_symbol_p could be rewritten as
!_bfd_elf_symbol_refs_local_p, except that targets differ in their
treatment of undefined weak symbols. For those that do not make
|| ELF_ST_VISIBILITY (h->other) == STV_INTERNAL)
return TRUE;
+ /* Forced local symbols resolve locally. */
+ if (h->forced_local)
+ return TRUE;
+
/* Common symbols that become definitions don't get the DEF_REGULAR
flag set, so test it first, and don't bail out. */
if (ELF_COMMON_DEF_P (h))
else if (!h->def_regular)
return FALSE;
- /* Forced local symbols resolve locally. */
- if (h->forced_local)
- return TRUE;
-
- /* As do non-dynamic symbols. */
+ /* Non-dynamic symbols resolve locally. */
if (h->dynindx == -1)
return TRUE;
if (!just_syms
&& (bfd_link_pic (info)
|| (!bfd_link_relocatable (info)
+ && info->nointerp
&& (info->export_dynamic || info->dynamic)))
&& is_elf_hash_table (htab)
&& info->output_bfd->xvec == abfd->xvec
/* xgettext:c-format */
(_("Warning: alignment %u of common symbol `%s' in %B is"
" greater than the alignment (%u) of its section %A"),
- common_bfd, h->root.u.def.section,
- 1 << common_align, name, 1 << normal_align);
+ 1 << common_align, name, common_bfd,
+ 1 << normal_align, h->root.u.def.section);
else
_bfd_error_handler
/* xgettext:c-format */
(_("Warning: alignment %u of symbol `%s' in %B"
" is smaller than %u in %B"),
- normal_bfd, common_bfd,
- 1 << normal_align, name, 1 << common_align);
+ 1 << normal_align, name, normal_bfd,
+ 1 << common_align, common_bfd);
}
}
/* xgettext:c-format */
(_("Warning: size of symbol `%s' changed"
" from %lu in %B to %lu in %B"),
- old_bfd, abfd,
- name, (unsigned long) h->size,
- (unsigned long) isym->st_size);
+ name, (unsigned long) h->size, old_bfd,
+ (unsigned long) isym->st_size, abfd);
h->size = isym->st_size;
}
_bfd_error_handler
(_("Warning: type of symbol `%s' changed"
" from %d to %d in %B"),
- abfd, name, h->type, type);
+ name, h->type, type, abfd);
h->type = type;
}
struct elf_link_hash_entry *h;
bfd_size_type size;
unsigned int alignment_power;
+ unsigned int non_ir_ref_dynamic;
for (p = htab->root.table.table[i]; p != NULL; p = p->next)
{
size = 0;
alignment_power = 0;
}
+ /* Preserve non_ir_ref_dynamic so that this symbol
+ will be exported when the dynamic lib becomes needed
+ in the second pass. */
+ non_ir_ref_dynamic = h->root.non_ir_ref_dynamic;
memcpy (p, old_ent, htab->root.table.entsize);
old_ent = (char *) old_ent + htab->root.table.entsize;
h = (struct elf_link_hash_entry *) p;
if (alignment_power > h->root.u.c.p->alignment_power)
h->root.u.c.p->alignment_power = alignment_power;
}
+ h->root.non_ir_ref_dynamic = non_ir_ref_dynamic;
}
}
struct bfd_link_info *info,
asection **sinterpptr)
{
- size_t soname_indx;
bfd *dynobj;
const struct elf_backend_data *bed;
*sinterpptr = NULL;
- soname_indx = (size_t) -1;
-
if (!is_elf_hash_table (info->hash))
return TRUE;
struct elf_info_failed eif;
bfd_boolean all_defined;
asection *s;
+ size_t soname_indx;
eif.info = info;
eif.failed = FALSE;
return FALSE;
}
+ if (soname != NULL)
+ {
+ soname_indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr,
+ soname, TRUE);
+ if (soname_indx == (size_t) -1
+ || !_bfd_elf_add_dynamic_entry (info, DT_SONAME, soname_indx))
+ return FALSE;
+ }
+ else
+ soname_indx = (size_t) -1;
+
/* Make all global versions with definition. */
for (t = info->version_info; t != NULL; t = t->next)
for (d = t->globals.list; d != NULL; d = d->next)
elf_link_hash_traverse (elf_hash_table (info), elf_gc_sweep_symbol,
&sweep_info);
- _bfd_elf_link_renumber_dynsyms (output_bfd, info, §ion_sym_count);
+ /* We need to reassign dynsym indices now that symbols may have
+ been removed. See the call in `bfd_elf_size_dynsym_hash_dynstr'
+ for the details of the conditions used here. */
+ if (elf_hash_table (info)->dynamic_sections_created
+ || bed->always_renumber_dynsyms)
+ _bfd_elf_link_renumber_dynsyms (output_bfd, info, §ion_sym_count);
}
/* Any syms created from now on start with -1 in
*sinterpptr = bfd_get_linker_section (dynobj, ".interp");
BFD_ASSERT (*sinterpptr != NULL || !bfd_link_executable (info) || info->nointerp);
- if (soname != NULL)
- {
- soname_indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr,
- soname, TRUE);
- if (soname_indx == (size_t) -1
- || !_bfd_elf_add_dynamic_entry (info, DT_SONAME, soname_indx))
- return FALSE;
- }
-
if (info->symbolic)
{
if (!_bfd_elf_add_dynamic_entry (info, DT_SYMBOLIC, 0))
bfd_elf_size_dynsym_hash_dynstr (bfd *output_bfd, struct bfd_link_info *info)
{
const struct elf_backend_data *bed;
+ unsigned long section_sym_count;
+ bfd_size_type dynsymcount;
if (!is_elf_hash_table (info->hash))
return TRUE;
bed = get_elf_backend_data (output_bfd);
(*bed->elf_backend_init_index_section) (output_bfd, info);
+ /* Assign dynsym indices. In a shared library we generate a section
+ symbol for each output section, which come first. Next come all
+ of the back-end allocated local dynamic syms, followed by the rest
+ of the global symbols.
+
+ This is usually not needed for static binaries, however backends
+ can request to always do it, e.g. the MIPS backend uses dynamic
+ symbol counts to lay out GOT, which will be produced in the
+ presence of GOT relocations even in static binaries (holding fixed
+ data in that case, to satisfy those relocations). */
+
+ if (elf_hash_table (info)->dynamic_sections_created
+ || bed->always_renumber_dynsyms)
+ dynsymcount = _bfd_elf_link_renumber_dynsyms (output_bfd, info,
+ §ion_sym_count);
+
if (elf_hash_table (info)->dynamic_sections_created)
{
bfd *dynobj;
asection *s;
- bfd_size_type dynsymcount;
- unsigned long section_sym_count;
unsigned int dtagcount;
dynobj = elf_hash_table (info)->dynobj;
- /* Assign dynsym indicies. In a shared library we generate a
- section symbol for each output section, which come first.
- Next come all of the back-end allocated local dynamic syms,
- followed by the rest of the global symbols. */
-
- dynsymcount = _bfd_elf_link_renumber_dynsyms (output_bfd, info,
- §ion_sym_count);
-
/* Work out the size of the symbol version section. */
s = bfd_get_linker_section (dynobj, ".gnu.version");
BFD_ASSERT (s != NULL);
h->forced_local = 1;
if (h->dynindx != -1)
{
- h->dynindx = -1;
_bfd_elf_strtab_delref (elf_hash_table (info)->dynstr,
h->dynstr_index);
+ h->dynindx = -1;
+ h->dynstr_index = 0;
}
}
}
else
{
/* Section size is only divisible by rela. */
- if (use_rela_initialised && (use_rela == FALSE))
+ if (use_rela_initialised && !use_rela)
{
_bfd_error_handler (_("%B: Unable to sort relocs - "
"they are in more than one size"),
else if ((o->size % bed->s->sizeof_rel) == 0)
{
/* Section size is only divisible by rel. */
- if (use_rela_initialised && (use_rela == TRUE))
+ if (use_rela_initialised && use_rela)
{
_bfd_error_handler (_("%B: Unable to sort relocs - "
"they are in more than one size"),
else
{
/* Section size is only divisible by rela. */
- if (use_rela_initialised && (use_rela == FALSE))
+ if (use_rela_initialised && !use_rela)
{
_bfd_error_handler (_("%B: Unable to sort relocs - "
"they are in more than one size"),
else if ((o->size % bed->s->sizeof_rel) == 0)
{
/* Section size is only divisible by rel. */
- if (use_rela_initialised && (use_rela == TRUE))
+ if (use_rela_initialised && use_rela)
{
_bfd_error_handler (_("%B: Unable to sort relocs - "
"they are in more than one size"),
def_bfd = flinfo->output_bfd;
if (hi->root.u.def.section != bfd_abs_section_ptr)
def_bfd = hi->root.u.def.section->owner;
- _bfd_error_handler (msg, flinfo->output_bfd, def_bfd,
- h->root.root.string);
+ _bfd_error_handler (msg, flinfo->output_bfd,
+ h->root.root.string, def_bfd);
bfd_set_error (bfd_error_bad_value);
eoinfo->failed = TRUE;
return FALSE;
/* xgettext:c-format */
(_("error: %B contains a reloc (0x%s) for section %A "
"that references a non-existent global symbol"),
- input_bfd, o, buffer);
+ input_bfd, buffer, o);
bfd_set_error (bfd_error_bad_value);
return FALSE;
}
linker may attach linker created dynamic sections
to the plugin bfd. Symbols defined in linker
created sections are not plugin symbols. */
- if (h->root.non_ir_ref
+ if ((h->root.non_ir_ref_regular
+ || h->root.non_ir_ref_dynamic)
&& (h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak)
&& (h->root.u.def.section->flags
/* xgettext:c-format */
(_("%A has both ordered [`%A' in %B] "
"and unordered [`%A' in %B] sections"),
- o, linkorder_sec,
- linkorder_sec->owner, other_sec,
- other_sec->owner);
+ o, linkorder_sec, linkorder_sec->owner,
+ other_sec, other_sec->owner);
else
_bfd_error_handler
(_("%A has both ordered and unordered sections"), o);
if (!bfd_set_format (implib_bfd, bfd_object))
return FALSE;
+ /* Use flag from executable but make it a relocatable object. */
flags = bfd_get_file_flags (abfd);
flags &= ~HAS_RELOC;
if (!bfd_set_start_address (implib_bfd, 0)
- || !bfd_set_file_flags (implib_bfd, flags))
+ || !bfd_set_file_flags (implib_bfd, flags & ~EXEC_P))
return FALSE;
/* Copy architecture of output file to import library file. */
return NULL;
}
+/* Return the global debug definition section. */
+
+static asection *
+elf_gc_mark_debug_section (asection *sec ATTRIBUTE_UNUSED,
+ struct bfd_link_info *info ATTRIBUTE_UNUSED,
+ Elf_Internal_Rela *rel ATTRIBUTE_UNUSED,
+ struct elf_link_hash_entry *h,
+ Elf_Internal_Sym *sym ATTRIBUTE_UNUSED)
+{
+ if (h != NULL
+ && (h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ && (h->root.u.def.section->flags & SEC_DEBUGGING) != 0)
+ return h->root.u.def.section;
+
+ return NULL;
+}
+
/* For undefined __start_<name> and __stop_<name> symbols, return the
first input section matching <name>. Return NULL otherwise. */
asection *isec;
bfd_boolean some_kept;
bfd_boolean debug_frag_seen;
+ bfd_boolean has_kept_debug_info;
if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour)
continue;
/* Ensure all linker created sections are kept,
see if any other section is already marked,
and note if we have any fragmented debug sections. */
- debug_frag_seen = some_kept = FALSE;
+ debug_frag_seen = some_kept = has_kept_debug_info = FALSE;
for (isec = ibfd->sections; isec != NULL; isec = isec->next)
{
if ((isec->flags & SEC_LINKER_CREATED) != 0)
isec->gc_mark = 1;
- else if (isec->gc_mark)
+ else if (isec->gc_mark
+ && (isec->flags & SEC_ALLOC) != 0
+ && elf_section_type (isec) != SHT_NOTE)
some_kept = TRUE;
- if (debug_frag_seen == FALSE
+ if (!debug_frag_seen
&& (isec->flags & SEC_DEBUGGING)
&& CONST_STRNEQ (isec->name, ".debug_line."))
debug_frag_seen = TRUE;
}
- /* If no section in this file will be kept, then we can
- toss out the debug and special sections. */
+ /* If no non-note alloc section in this file will be kept, then
+ we can toss out the debug and special sections. */
if (!some_kept)
continue;
|| (isec->flags & (SEC_ALLOC | SEC_LOAD | SEC_RELOC)) == 0)
&& elf_next_in_group (isec) == NULL)
isec->gc_mark = 1;
+ if (isec->gc_mark && (isec->flags & SEC_DEBUGGING) != 0)
+ has_kept_debug_info = TRUE;
}
- if (! debug_frag_seen)
- continue;
-
/* Look for CODE sections which are going to be discarded,
and find and discard any fragmented debug sections which
are associated with that code section. */
- for (isec = ibfd->sections; isec != NULL; isec = isec->next)
- if ((isec->flags & SEC_CODE) != 0
- && isec->gc_mark == 0)
- {
- unsigned int ilen;
- asection *dsec;
+ if (debug_frag_seen)
+ for (isec = ibfd->sections; isec != NULL; isec = isec->next)
+ if ((isec->flags & SEC_CODE) != 0
+ && isec->gc_mark == 0)
+ {
+ unsigned int ilen;
+ asection *dsec;
- ilen = strlen (isec->name);
+ ilen = strlen (isec->name);
- /* Association is determined by the name of the debug section
- containing the name of the code section as a suffix. For
- example .debug_line.text.foo is a debug section associated
- with .text.foo. */
- for (dsec = ibfd->sections; dsec != NULL; dsec = dsec->next)
- {
- unsigned int dlen;
+ /* Association is determined by the name of the debug
+ section containing the name of the code section as
+ a suffix. For example .debug_line.text.foo is a
+ debug section associated with .text.foo. */
+ for (dsec = ibfd->sections; dsec != NULL; dsec = dsec->next)
+ {
+ unsigned int dlen;
- if (dsec->gc_mark == 0
- || (dsec->flags & SEC_DEBUGGING) == 0)
- continue;
+ if (dsec->gc_mark == 0
+ || (dsec->flags & SEC_DEBUGGING) == 0)
+ continue;
- dlen = strlen (dsec->name);
+ dlen = strlen (dsec->name);
- if (dlen > ilen
- && strncmp (dsec->name + (dlen - ilen),
- isec->name, ilen) == 0)
- {
+ if (dlen > ilen
+ && strncmp (dsec->name + (dlen - ilen),
+ isec->name, ilen) == 0)
dsec->gc_mark = 0;
- }
- }
+ }
}
+
+ /* Mark debug sections referenced by kept debug sections. */
+ if (has_kept_debug_info)
+ for (isec = ibfd->sections; isec != NULL; isec = isec->next)
+ if (isec->gc_mark
+ && (isec->flags & SEC_DEBUGGING) != 0)
+ if (!_bfd_elf_gc_mark (info, isec,
+ elf_gc_mark_debug_section))
+ return FALSE;
}
return TRUE;
}
if (info->print_gc_sections && o->size != 0)
/* xgettext:c-format */
- _bfd_error_handler (_("Removing unused section '%s' in file '%B'"),
- sub, o->name);
+ _bfd_error_handler (_("Removing unused section '%A' in file '%B'"),
+ o, sub);
/* But we also have to update some of the relocation
info we collected before. */
if (o != NULL)
{
asection *i;
+ int eh_changed = 0;
for (i = o->map_head.s; i != NULL; i = i->map_head.s)
{
if (_bfd_elf_discard_section_eh_frame (abfd, info, i,
bfd_elf_reloc_symbol_deleted_p,
&cookie))
- changed = 1;
+ {
+ eh_changed = 1;
+ if (i->size != i->rawsize)
+ changed = 1;
+ }
fini_reloc_cookie_for_section (&cookie, i);
}
+ if (eh_changed)
+ elf_link_hash_traverse (elf_hash_table (info),
+ _bfd_elf_adjust_eh_frame_global_symbol, NULL);
}
for (abfd = info->input_bfds; abfd != NULL; abfd = abfd->link.next)