if ((abfd->flags & (DYNAMIC | BFD_PLUGIN)) != 0)
{
bfd *ibfd;
+ asection *s;
for (ibfd = info->input_bfds; ibfd; ibfd = ibfd->link.next)
if ((ibfd->flags
- & (DYNAMIC | BFD_LINKER_CREATED | BFD_PLUGIN)) == 0)
+ & (DYNAMIC | BFD_LINKER_CREATED | BFD_PLUGIN)) == 0
+ && bfd_get_flavour (ibfd) == bfd_target_elf_flavour
+ && !((s = ibfd->sections) != NULL
+ && s->sec_info_type == SEC_INFO_TYPE_JUST_SYMS))
{
abfd = ibfd;
break;
{
_bfd_error_handler
/* xgettext:c-format */
- (_("%B: bad reloc symbol index (0x%lx >= 0x%lx)"
- " for offset 0x%lx in section `%A'"),
- abfd, (unsigned long) r_symndx, (unsigned long) nsyms,
+ (_("%B: bad reloc symbol index (%#Lx >= %#lx)"
+ " for offset %#Lx in section `%A'"),
+ abfd, 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 (%#Lx)"
+ " for offset %#Lx in section `%A'"
" when the object file has no symbol table"),
- abfd, (unsigned long) r_symndx, (unsigned long) nsyms,
+ abfd, r_symndx,
irela->r_offset, sec);
bfd_set_error (bfd_error_bad_value);
return FALSE;
{
bfd_size_type size;
- size = o->reloc_count;
- size *= bed->s->int_rels_per_ext_rel * sizeof (Elf_Internal_Rela);
+ size = (bfd_size_type) o->reloc_count * sizeof (Elf_Internal_Rela);
if (keep_memory)
internal_relocs = alloc2 = (Elf_Internal_Rela *) bfd_alloc (abfd, size);
else
bfd_vma mask;
asection *sec = h->root.u.def.section;
- /* The section aligment of definition is the maximum alignment
+ /* The section alignment of the definition is the maximum alignment
requirement of symbols defined in the section. Since we don't
know the symbol alignment requirement, we start with the
maximum alignment and check low bits of the symbol address
_bfd_error_handler
/* xgettext:c-format */
(_("Warning: size of symbol `%s' changed"
- " from %lu in %B to %lu in %B"),
- name, (unsigned long) h->size, old_bfd,
- (unsigned long) isym->st_size, abfd);
+ " from %Lu in %B to %Lu in %B"),
+ name, h->size, old_bfd, isym->st_size, abfd);
h->size = isym->st_size;
}
_bfd_elf_size_group_sections (struct bfd_link_info *info)
{
bfd *ibfd;
+ asection *s;
for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next)
if (bfd_get_flavour (ibfd) == bfd_target_elf_flavour
+ && (s = ibfd->sections) != NULL
+ && s->sec_info_type != SEC_INFO_TYPE_JUST_SYMS
&& !_bfd_elf_fixup_group_sections (ibfd, bfd_abs_section_ptr))
return FALSE;
return TRUE;
if (inputobj->flags
& (DYNAMIC | EXEC_P | BFD_PLUGIN | BFD_LINKER_CREATED))
continue;
+ s = inputobj->sections;
+ if (s == NULL || s->sec_info_type == SEC_INFO_TYPE_JUST_SYMS)
+ continue;
+
s = bfd_get_section_by_name (inputobj, ".note.GNU-stack");
if (s)
{
bfd *sub;
asection *o;
- for (sub = info->input_bfds; sub != NULL;
- sub = sub->link.next)
- if (bfd_get_flavour (sub) == bfd_target_elf_flavour)
+ for (sub = info->input_bfds; sub != NULL; sub = sub->link.next)
+ if (bfd_get_flavour (sub) == bfd_target_elf_flavour
+ && (o = sub->sections) != NULL
+ && o->sec_info_type != SEC_INFO_TYPE_JUST_SYMS)
for (o = sub->sections; o != NULL; o = o->next)
if (elf_section_data (o)->this_hdr.sh_type
== SHT_PREINIT_ARRAY)
= compute_bucket_count (info, hashcodes, nsyms, 0);
free (hashcodes);
- if (bucketcount == 0)
+ if (bucketcount == 0 && nsyms > 0)
return FALSE;
elf_hash_table (info)->bucketcount = bucketcount;
elf_link_adjust_relocs (bfd *abfd,
asection *sec,
struct bfd_elf_section_reloc_data *reldata,
- bfd_boolean sort)
+ bfd_boolean sort,
+ struct bfd_link_info *info)
{
unsigned int i;
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
if (*rel_hash == NULL)
continue;
+ if ((*rel_hash)->indx == -2
+ && info->gc_sections
+ && ! info->gc_keep_exported)
+ {
+ /* PR 21524: Let the user know if a symbol was removed by garbage collection. */
+ _bfd_error_handler (_("%B:%A: error: relocation references symbol %s which was removed by garbage collection."),
+ abfd, sec,
+ (*rel_hash)->root.root.string);
+ _bfd_error_handler (_("%B:%A: error: try relinking with --gc-keep-exported enabled."),
+ abfd, sec);
+ bfd_set_error (bfd_error_invalid_operation);
+ return FALSE;
+ }
BFD_ASSERT ((*rel_hash)->indx >= 0);
(*swap_in) (abfd, erela, irela);
continue;
}
- if (bfd_link_relocatable (flinfo->info)
+ if (!flinfo->info->resolve_section_groups
&& (o->flags & (SEC_LINKER_CREATED | SEC_GROUP)) == SEC_GROUP)
{
/* Deal with the group signature symbol. */
unsigned long symndx = sec_data->this_hdr.sh_info;
asection *osec = o->output_section;
+ BFD_ASSERT (bfd_link_relocatable (flinfo->info));
if (symndx >= locsymcount
|| (elf_bad_symtab (input_bfd)
&& flinfo->sections[symndx] == NULL))
".fini_array") == 0))
&& (o->name[6] == 0 || o->name[6] == '.'))
{
- if (o->size != o->reloc_count * address_size)
+ if (o->size * bed->s->int_rels_per_ext_rel
+ != o->reloc_count * address_size)
{
_bfd_error_handler
/* xgettext:c-format */
relocs against removed link-once sections. */
rel = internal_relocs;
- relend = rel + o->reloc_count * bed->s->int_rels_per_ext_rel;
+ relend = rel + o->reloc_count;
for ( ; rel < relend; rel++)
{
unsigned long r_symndx = rel->r_info >> r_sym_shift;
we do not seg fault. */
if (h == NULL)
{
- char buffer [32];
-
- sprintf_vma (buffer, rel->r_info);
_bfd_error_handler
/* xgettext:c-format */
- (_("error: %B contains a reloc (0x%s) for section %A "
+ (_("error: %B contains a reloc (%#Lx) for section %A "
"that references a non-existent global symbol"),
- input_bfd, buffer, o);
+ input_bfd, rel->r_info, o);
bfd_set_error (bfd_error_bad_value);
return FALSE;
}
/* Adjust the reloc addresses and symbol indices. */
irela = internal_relocs;
- irelaend = irela + o->reloc_count * bed->s->int_rels_per_ext_rel;
+ irelaend = irela + o->reloc_count;
rel_hash = esdo->rel.hashes + esdo->rel.count;
/* We start processing the REL relocs, if any. When we reach
IRELAMID in the loop, we switch to the RELA relocs. */
used by a reloc. */
BFD_ASSERT (rh->indx < 0);
rh->indx = -2;
-
*rel_hash = rh;
continue;
if (max_internal_reloc_count != 0)
{
- amt = max_internal_reloc_count * bed->s->int_rels_per_ext_rel;
- amt *= sizeof (Elf_Internal_Rela);
+ amt = max_internal_reloc_count * sizeof (Elf_Internal_Rela);
flinfo.internal_relocs = (Elf_Internal_Rela *) bfd_malloc (amt);
if (flinfo.internal_relocs == NULL)
goto error_return;
{
struct bfd_elf_section_data *esdo = elf_section_data (o);
bfd_boolean sort;
+
if ((o->flags & SEC_RELOC) == 0)
continue;
sort = bed->sort_relocs_p == NULL || (*bed->sort_relocs_p) (o);
if (esdo->rel.hdr != NULL
- && !elf_link_adjust_relocs (abfd, o, &esdo->rel, sort))
+ && !elf_link_adjust_relocs (abfd, o, &esdo->rel, sort, info))
return FALSE;
if (esdo->rela.hdr != NULL
- && !elf_link_adjust_relocs (abfd, o, &esdo->rela, sort))
+ && !elf_link_adjust_relocs (abfd, o, &esdo->rela, sort, info))
return FALSE;
/* Set the reloc_count field to 0 to prevent write_relocs from
}
}
- if (bfd_link_relocatable (info))
+ if (!info->resolve_section_groups)
{
bfd_boolean failed = FALSE;
+ BFD_ASSERT (bfd_link_relocatable (info));
bfd_map_over_sections (abfd, bfd_elf_set_group_contents, &failed);
if (failed)
goto error_return;
struct bfd_link_info *info, bfd *abfd,
asection *sec)
{
- const struct elf_backend_data *bed;
-
if (sec->reloc_count == 0)
{
cookie->rels = NULL;
}
else
{
- bed = get_elf_backend_data (abfd);
-
cookie->rels = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL,
info->keep_memory);
if (cookie->rels == NULL)
return FALSE;
cookie->rel = cookie->rels;
- cookie->relend = (cookie->rels
- + sec->reloc_count * bed->s->int_rels_per_ext_rel);
+ cookie->relend = cookie->rels + sec->reloc_count;
}
cookie->rel = cookie->rels;
return TRUE;
return NULL;
}
-/* For undefined __start_<name> and __stop_<name> symbols, return the
- first input section matching <name>. Return NULL otherwise. */
-
-asection *
-_bfd_elf_is_start_stop (const struct bfd_link_info *info,
- struct elf_link_hash_entry *h)
-{
- asection *s;
- const char *sec_name;
-
- if (h->root.type != bfd_link_hash_undefined
- && h->root.type != bfd_link_hash_undefweak)
- return NULL;
-
- s = h->root.u.undef.section;
- if (s != NULL)
- {
- if (s == (asection *) 0 - 1)
- return NULL;
- return s;
- }
-
- sec_name = NULL;
- if (strncmp (h->root.root.string, "__start_", 8) == 0)
- sec_name = h->root.root.string + 8;
- else if (strncmp (h->root.root.string, "__stop_", 7) == 0)
- sec_name = h->root.root.string + 7;
-
- if (sec_name != NULL && *sec_name != '\0')
- {
- bfd *i;
-
- for (i = info->input_bfds; i != NULL; i = i->link.next)
- {
- s = bfd_get_section_by_name (i, sec_name);
- if (s != NULL)
- {
- h->root.u.undef.section = s;
- break;
- }
- }
- }
-
- if (s == NULL)
- h->root.u.undef.section = (asection *) 0 - 1;
-
- return s;
-}
-
/* COOKIE->rel describes a relocation against section SEC, which is
a section we've decided to keep. Return the section that contains
the relocation symbol, or NULL if no section contains it. */
if (start_stop != NULL)
{
- /* To work around a glibc bug, mark all XXX input sections
- when there is an as yet undefined reference to __start_XXX
- or __stop_XXX symbols. The linker will later define such
- symbols for orphan input sections that have a name
- representable as a C identifier. */
- asection *s = _bfd_elf_is_start_stop (info, h);
-
- if (s != NULL)
+ /* To work around a glibc bug, mark XXX input sections
+ when there is a reference to __start_XXX or __stop_XXX
+ symbols. */
+ if (h->start_stop)
{
+ asection *s = h->u2.start_stop_section;
*start_stop = !s->gc_mark;
return s;
}
if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour)
continue;
+ isec = ibfd->sections;
+ if (isec == NULL || isec->sec_info_type == SEC_INFO_TYPE_JUST_SYMS)
+ continue;
/* Ensure all linker created sections are kept,
see if any other section is already marked,
{
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
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;
if (bfd_get_flavour (sub) != bfd_target_elf_flavour
|| !(*bed->relocs_compatible) (sub->xvec, abfd->xvec))
continue;
+ o = sub->sections;
+ if (o == NULL || o->sec_info_type == SEC_INFO_TYPE_JUST_SYMS)
+ continue;
for (o = sub->sections; o != NULL; o = o->next)
{
elf_gc_propagate_vtable_entries_used (struct elf_link_hash_entry *h, void *okp)
{
/* Those that are not vtables. */
- if (h->vtable == NULL || h->vtable->parent == NULL)
+ if (h->start_stop
+ || h->u2.vtable == NULL
+ || h->u2.vtable->parent == NULL)
return TRUE;
/* Those vtables that do not have parents, we cannot merge. */
- if (h->vtable->parent == (struct elf_link_hash_entry *) -1)
+ if (h->u2.vtable->parent == (struct elf_link_hash_entry *) -1)
return TRUE;
/* If we've already been done, exit. */
- if (h->vtable->used && h->vtable->used[-1])
+ if (h->u2.vtable->used && h->u2.vtable->used[-1])
return TRUE;
/* Make sure the parent's table is up to date. */
- elf_gc_propagate_vtable_entries_used (h->vtable->parent, okp);
+ elf_gc_propagate_vtable_entries_used (h->u2.vtable->parent, okp);
- if (h->vtable->used == NULL)
+ if (h->u2.vtable->used == NULL)
{
/* None of this table's entries were referenced. Re-use the
parent's table. */
- h->vtable->used = h->vtable->parent->vtable->used;
- h->vtable->size = h->vtable->parent->vtable->size;
+ h->u2.vtable->used = h->u2.vtable->parent->u2.vtable->used;
+ h->u2.vtable->size = h->u2.vtable->parent->u2.vtable->size;
}
else
{
bfd_boolean *cu, *pu;
/* Or the parent's entries into ours. */
- cu = h->vtable->used;
+ cu = h->u2.vtable->used;
cu[-1] = TRUE;
- pu = h->vtable->parent->vtable->used;
+ pu = h->u2.vtable->parent->u2.vtable->used;
if (pu != NULL)
{
const struct elf_backend_data *bed;
bed = get_elf_backend_data (h->root.u.def.section->owner);
log_file_align = bed->s->log_file_align;
- n = h->vtable->parent->vtable->size >> log_file_align;
+ n = h->u2.vtable->parent->u2.vtable->size >> log_file_align;
while (n--)
{
if (*pu)
/* Take care of both those symbols that do not describe vtables as
well as those that are not loaded. */
- if (h->vtable == NULL || h->vtable->parent == NULL)
+ if (h->start_stop
+ || h->u2.vtable == NULL
+ || h->u2.vtable->parent == NULL)
return TRUE;
BFD_ASSERT (h->root.type == bfd_link_hash_defined
bed = get_elf_backend_data (sec->owner);
log_file_align = bed->s->log_file_align;
- relend = relstart + sec->reloc_count * bed->s->int_rels_per_ext_rel;
+ relend = relstart + sec->reloc_count;
for (rel = relstart; rel < relend; ++rel)
if (rel->r_offset >= hstart && rel->r_offset < hend)
{
/* If the entry is in use, do nothing. */
- if (h->vtable->used
- && (rel->r_offset - hstart) < h->vtable->size)
+ if (h->u2.vtable->used
+ && (rel->r_offset - hstart) < h->u2.vtable->size)
{
bfd_vma entry = (rel->r_offset - hstart) >> log_file_align;
- if (h->vtable->used[entry])
+ if (h->u2.vtable->used[entry])
continue;
}
/* Otherwise, kill it. */
if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour)
continue;
+ sec = ibfd->sections;
+ if (sec == NULL || sec->sec_info_type == SEC_INFO_TYPE_JUST_SYMS)
+ continue;
if (!init_reloc_cookie (&cookie, info, ibfd))
return FALSE;
asection *sec;
struct elf_reloc_cookie cookie;
+ sec = sub->sections;
+ if (sec == NULL || sec->sec_info_type == SEC_INFO_TYPE_JUST_SYMS)
+ continue;
sec = bfd_get_section_by_name (sub, ".eh_frame");
while (sec && init_reloc_cookie_for_section (&cookie, info, sec))
{
|| !(*bed->relocs_compatible) (sub->xvec, abfd->xvec))
continue;
+ o = sub->sections;
+ if (o == NULL || o->sec_info_type == SEC_INFO_TYPE_JUST_SYMS)
+ continue;
+
/* Start at sections marked with SEC_KEEP (ref _bfd_elf_gc_keep).
Also treat note sections as a root, if the section is not part
of a group. */
}
/* xgettext:c-format */
- _bfd_error_handler (_("%B: %A+%lu: No symbol found for INHERIT"),
- abfd, sec, (unsigned long) offset);
+ _bfd_error_handler (_("%B: %A+%#Lx: No symbol found for INHERIT"),
+ abfd, sec, offset);
bfd_set_error (bfd_error_invalid_operation);
return FALSE;
win:
- if (!child->vtable)
+ if (!child->u2.vtable)
{
- child->vtable = ((struct elf_link_virtual_table_entry *)
- bfd_zalloc (abfd, sizeof (*child->vtable)));
- if (!child->vtable)
+ child->u2.vtable = ((struct elf_link_virtual_table_entry *)
+ bfd_zalloc (abfd, sizeof (*child->u2.vtable)));
+ if (!child->u2.vtable)
return FALSE;
}
if (!h)
would be bad. It isn't worth paging in the local symbols to be
sure though; that case should simply be handled by the assembler. */
- child->vtable->parent = (struct elf_link_hash_entry *) -1;
+ child->u2.vtable->parent = (struct elf_link_hash_entry *) -1;
}
else
- child->vtable->parent = h;
+ child->u2.vtable->parent = h;
return TRUE;
}
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
unsigned int log_file_align = bed->s->log_file_align;
- if (!h->vtable)
+ if (!h->u2.vtable)
{
- h->vtable = ((struct elf_link_virtual_table_entry *)
- bfd_zalloc (abfd, sizeof (*h->vtable)));
- if (!h->vtable)
+ h->u2.vtable = ((struct elf_link_virtual_table_entry *)
+ bfd_zalloc (abfd, sizeof (*h->u2.vtable)));
+ if (!h->u2.vtable)
return FALSE;
}
- if (addend >= h->vtable->size)
+ if (addend >= h->u2.vtable->size)
{
size_t size, bytes, file_align;
- bfd_boolean *ptr = h->vtable->used;
+ bfd_boolean *ptr = h->u2.vtable->used;
/* While the symbol is undefined, we have to be prepared to handle
a zero size. */
{
size_t oldbytes;
- oldbytes = (((h->vtable->size >> log_file_align) + 1)
+ oldbytes = (((h->u2.vtable->size >> log_file_align) + 1)
* sizeof (bfd_boolean));
memset (((char *) ptr) + oldbytes, 0, bytes - oldbytes);
}
return FALSE;
/* And arrange for that done flag to be at index -1. */
- h->vtable->used = ptr + 1;
- h->vtable->size = size;
+ h->u2.vtable->used = ptr + 1;
+ h->u2.vtable->size = size;
}
- h->vtable->used[addend >> log_file_align] = TRUE;
+ h->u2.vtable->used[addend >> log_file_align] = TRUE;
return TRUE;
}
for (abfd = info->input_bfds; abfd != NULL; abfd = abfd->link.next)
{
const struct elf_backend_data *bed;
+ asection *s;
if (bfd_get_flavour (abfd) != bfd_target_elf_flavour)
continue;
+ s = abfd->sections;
+ if (s == NULL || s->sec_info_type == SEC_INFO_TYPE_JUST_SYMS)
+ continue;
bed = get_elf_backend_data (abfd);
BFD_ASSERT (loc + bed->s->sizeof_rel <= s->contents + s->size);
bed->s->swap_reloc_out (abfd, rel, loc);
}
+
+/* Define __start, __stop, .startof. or .sizeof. symbol. */
+
+struct bfd_link_hash_entry *
+bfd_elf_define_start_stop (struct bfd_link_info *info,
+ const char *symbol, asection *sec)
+{
+ struct bfd_link_hash_entry *h;
+
+ h = bfd_generic_define_start_stop (info, symbol, sec);
+ if (h != NULL)
+ {
+ struct elf_link_hash_entry *eh = (struct elf_link_hash_entry *) h;
+ eh->start_stop = 1;
+ eh->u2.start_stop_section = sec;
+ _bfd_elf_link_hash_hide_symbol (info, eh, TRUE);
+ if (ELF_ST_VISIBILITY (eh->other) != STV_INTERNAL)
+ eh->other = ((eh->other & ~ELF_ST_VISIBILITY (-1))
+ | STV_HIDDEN);
+ }
+ return h;
+}