{
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
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,
+ (*rel_hash)->root.root.string);
+ 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;
/* 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. */
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)
+ if (h->start_stop)
{
+ asection *s = h->u2.start_stop_section;
*start_stop = !s->gc_mark;
return s;
}
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. */
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;
}