if (keep_memory)
esdo->relocs = internal_relocs;
- if (alloc1 != NULL)
- free (alloc1);
+ free (alloc1);
/* Don't free alloc2, since if it was allocated we are passing it
back (under the name of internal_relocs). */
return internal_relocs;
error_return:
- if (alloc1 != NULL)
- free (alloc1);
+ free (alloc1);
if (alloc2 != NULL)
{
if (keep_memory)
return TRUE;
}
+/* Strip zero-sized dynamic sections. */
+
+bfd_boolean
+_bfd_elf_strip_zero_sized_dynamic_sections (struct bfd_link_info *info)
+{
+ struct elf_link_hash_table *hash_table;
+ const struct elf_backend_data *bed;
+ asection *s, *sdynamic, **pp;
+ asection *rela_dyn, *rel_dyn;
+ Elf_Internal_Dyn dyn;
+ bfd_byte *extdyn, *next;
+ void (*swap_dyn_in) (bfd *, const void *, Elf_Internal_Dyn *);
+ bfd_boolean strip_zero_sized;
+ bfd_boolean strip_zero_sized_plt;
+
+ if (bfd_link_relocatable (info))
+ return TRUE;
+
+ hash_table = elf_hash_table (info);
+ if (!is_elf_hash_table (hash_table))
+ return FALSE;
+
+ if (!hash_table->dynobj)
+ return TRUE;
+
+ sdynamic= bfd_get_linker_section (hash_table->dynobj, ".dynamic");
+ if (!sdynamic)
+ return TRUE;
+
+ bed = get_elf_backend_data (hash_table->dynobj);
+ swap_dyn_in = bed->s->swap_dyn_in;
+
+ strip_zero_sized = FALSE;
+ strip_zero_sized_plt = FALSE;
+
+ /* Strip zero-sized dynamic sections. */
+ rela_dyn = bfd_get_section_by_name (info->output_bfd, ".rela.dyn");
+ rel_dyn = bfd_get_section_by_name (info->output_bfd, ".rel.dyn");
+ for (pp = &info->output_bfd->sections; (s = *pp) != NULL;)
+ if (s->size == 0
+ && (s == rela_dyn
+ || s == rel_dyn
+ || s == hash_table->srelplt->output_section
+ || s == hash_table->splt->output_section))
+ {
+ *pp = s->next;
+ info->output_bfd->section_count--;
+ strip_zero_sized = TRUE;
+ if (s == rela_dyn)
+ s = rela_dyn;
+ if (s == rel_dyn)
+ s = rel_dyn;
+ else if (s == hash_table->splt->output_section)
+ {
+ s = hash_table->splt;
+ strip_zero_sized_plt = TRUE;
+ }
+ else
+ s = hash_table->srelplt;
+ s->flags |= SEC_EXCLUDE;
+ s->output_section = bfd_abs_section_ptr;
+ }
+ else
+ pp = &s->next;
+
+ if (strip_zero_sized_plt)
+ for (extdyn = sdynamic->contents;
+ extdyn < sdynamic->contents + sdynamic->size;
+ extdyn = next)
+ {
+ next = extdyn + bed->s->sizeof_dyn;
+ swap_dyn_in (hash_table->dynobj, extdyn, &dyn);
+ switch (dyn.d_tag)
+ {
+ default:
+ break;
+ case DT_JMPREL:
+ case DT_PLTRELSZ:
+ case DT_PLTREL:
+ /* Strip DT_PLTRELSZ, DT_JMPREL and DT_PLTREL entries if
+ the procedure linkage table (the .plt section) has been
+ removed. */
+ memmove (extdyn, next,
+ sdynamic->size - (next - sdynamic->contents));
+ next = extdyn;
+ }
+ }
+
+ if (strip_zero_sized)
+ {
+ /* Regenerate program headers. */
+ elf_seg_map (info->output_bfd) = NULL;
+ return _bfd_elf_map_sections_to_segments (info->output_bfd, info);
+ }
+
+ return TRUE;
+}
+
/* Add a DT_NEEDED entry for this dynamic object. Returns -1 on error,
1 if a DT_NEEDED tag already exists, and 0 on success. */
}
}
- if (extversym != NULL)
- {
- free (extversym);
- extversym = NULL;
- }
-
- if (isymbuf != NULL)
- {
- free (isymbuf);
- isymbuf = NULL;
- }
+ free (extversym);
+ extversym = NULL;
+ free (isymbuf);
+ isymbuf = NULL;
if ((elf_dyn_lib_class (abfd) & DYN_AS_NEEDED) != 0)
{
free (old_tab);
objalloc_free_block ((struct objalloc *) htab->root.table.memory,
alloc_mark);
- if (nondeflt_vers != NULL)
- free (nondeflt_vers);
+ free (nondeflt_vers);
return TRUE;
}
return TRUE;
error_free_vers:
- if (old_tab != NULL)
- free (old_tab);
- if (old_strtab != NULL)
- free (old_strtab);
- if (nondeflt_vers != NULL)
- free (nondeflt_vers);
- if (extversym != NULL)
- free (extversym);
+ free (old_tab);
+ free (old_strtab);
+ free (nondeflt_vers);
+ free (extversym);
error_free_sym:
- if (isymbuf != NULL)
- free (isymbuf);
+ free (isymbuf);
error_return:
return FALSE;
}
while (loop);
free (included);
-
return TRUE;
error_return:
- if (included != NULL)
- free (included);
+ free (included);
return FALSE;
}
later. */
h->u.elf_hash_value = ha;
- if (alc != NULL)
- free (alc);
-
+ free (alc);
return TRUE;
}
if (s->min_dynindx < 0 || s->min_dynindx > h->dynindx)
s->min_dynindx = h->dynindx;
- if (alc != NULL)
- free (alc);
-
+ free (alc);
return TRUE;
}
{
size_t indx;
- name = lbasename (output_bfd->filename);
+ name = lbasename (bfd_get_filename (output_bfd));
def.vd_hash = bfd_elf_hash (name);
indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr,
name, FALSE);
indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr,
elf_dt_name (vn->vn_bfd) != NULL
? elf_dt_name (vn->vn_bfd)
- : lbasename (vn->vn_bfd->filename),
+ : lbasename (bfd_get_filename
+ (vn->vn_bfd)),
FALSE);
if (indx == (size_t) -1)
return FALSE;
{
struct elf_link_hash_table *htab;
+ if (ind->dyn_relocs != NULL)
+ {
+ if (dir->dyn_relocs != NULL)
+ {
+ struct elf_dyn_relocs **pp;
+ struct elf_dyn_relocs *p;
+
+ /* Add reloc counts against the indirect sym to the direct sym
+ list. Merge any entries against the same section. */
+ for (pp = &ind->dyn_relocs; (p = *pp) != NULL; )
+ {
+ struct elf_dyn_relocs *q;
+
+ for (q = dir->dyn_relocs; q != NULL; q = q->next)
+ if (q->sec == p->sec)
+ {
+ q->pc_count += p->pc_count;
+ q->count += p->count;
+ *pp = p->next;
+ break;
+ }
+ if (q == NULL)
+ pp = &p->next;
+ }
+ *pp = dir->dyn_relocs;
+ }
+
+ dir->dyn_relocs = ind->dyn_relocs;
+ ind->dyn_relocs = NULL;
+ }
+
/* Copy down any references that we may have already seen to the
symbol which just became indirect. */
return TRUE;
error_return:
- if (dynbuf != NULL)
- free (dynbuf);
+ free (dynbuf);
return FALSE;
}
result = TRUE;
done:
- if (symtable1)
- free (symtable1);
- if (symtable2)
- free (symtable2);
- if (isymbuf1)
- free (isymbuf1);
- if (isymbuf2)
- free (isymbuf2);
+ free (symtable1);
+ free (symtable2);
+ free (isymbuf1);
+ free (isymbuf2);
return result;
}
&& (!h->ref_regular || flinfo->info->gc_sections)
&& !elf_link_check_versioned_symbol (flinfo->info, bed, h)
&& flinfo->info->unresolved_syms_in_shared_libs != RM_IGNORE)
- (*flinfo->info->callbacks->undefined_symbol)
- (flinfo->info, h->root.root.string,
- h->ref_regular ? NULL : h->root.u.undef.abfd,
- NULL, 0,
- flinfo->info->unresolved_syms_in_shared_libs == RM_GENERATE_ERROR);
+ {
+ flinfo->info->callbacks->undefined_symbol
+ (flinfo->info, h->root.root.string,
+ h->ref_regular ? NULL : h->root.u.undef.abfd, NULL, 0,
+ flinfo->info->unresolved_syms_in_shared_libs == RM_DIAGNOSE
+ && !flinfo->info->warn_unresolved_syms);
+ }
/* Strip a global symbol defined in a discarded section. */
if (h->indx == -3)
{
_bfd_error_handler (_("warning: --enable-non-contiguous-regions "
"discards section `%s' from '%s'\n"),
- isec->name, isec->owner->filename);
+ isec->name, bfd_get_filename (isec->owner));
continue;
}
osym.st_shndx = SHN_ABS;
if (!elf_link_output_symstrtab (flinfo,
(input_bfd->lto_output ? NULL
- : input_bfd->filename),
+ : bfd_get_filename (input_bfd)),
&osym, bfd_abs_section_ptr,
NULL))
return FALSE;
#ifdef DEBUG
printf ("Encountered a complex symbol!");
printf (" (input_bfd %s, section %s, reloc %ld\n",
- input_bfd->filename, o->name,
+ bfd_get_filename (input_bfd), o->name,
(long) (rel - internal_relocs));
printf (" symbol: idx %8.8lx, name %s\n",
r_symndx, sym_name);
if (flinfo->symstrtab != NULL)
_bfd_elf_strtab_free (flinfo->symstrtab);
- if (flinfo->contents != NULL)
- free (flinfo->contents);
- if (flinfo->external_relocs != NULL)
- free (flinfo->external_relocs);
- if (flinfo->internal_relocs != NULL)
- free (flinfo->internal_relocs);
- if (flinfo->external_syms != NULL)
- free (flinfo->external_syms);
- if (flinfo->locsym_shndx != NULL)
- free (flinfo->locsym_shndx);
- if (flinfo->internal_syms != NULL)
- free (flinfo->internal_syms);
- if (flinfo->indices != NULL)
- free (flinfo->indices);
- if (flinfo->sections != NULL)
- free (flinfo->sections);
- if (flinfo->symshndxbuf != NULL
- && flinfo->symshndxbuf != (Elf_External_Sym_Shndx *) -1)
+ free (flinfo->contents);
+ free (flinfo->external_relocs);
+ free (flinfo->internal_relocs);
+ free (flinfo->external_syms);
+ free (flinfo->locsym_shndx);
+ free (flinfo->internal_syms);
+ free (flinfo->indices);
+ free (flinfo->sections);
+ if (flinfo->symshndxbuf != (Elf_External_Sym_Shndx *) -1)
free (flinfo->symshndxbuf);
for (o = obfd->sections; o != NULL; o = o->next)
{
struct bfd_elf_section_data *esdo = elf_section_data (o);
- if ((o->flags & SEC_RELOC) != 0 && esdo->rel.hashes != NULL)
- free (esdo->rel.hashes);
- if ((o->flags & SEC_RELOC) != 0 && esdo->rela.hashes != NULL)
- free (esdo->rela.hashes);
+ free (esdo->rel.hashes);
+ free (esdo->rela.hashes);
}
}
if (!info->reduce_memory_overheads)
{
for (sub = info->input_bfds; sub != NULL; sub = sub->link.next)
- if (bfd_get_flavour (sub) == bfd_target_elf_flavour
- && elf_tdata (sub)->symbuf)
+ if (bfd_get_flavour (sub) == bfd_target_elf_flavour)
{
free (elf_tdata (sub)->symbuf);
elf_tdata (sub)->symbuf = NULL;
goto error_return;
/* Check for DT_TEXTREL (late, in case the backend removes it). */
- if (((info->warn_shared_textrel && bfd_link_pic (info))
- || info->error_textrel)
+ if (bfd_link_textrel_check (info)
&& (o = bfd_get_linker_section (dynobj, ".dynamic")) != NULL)
{
bfd_byte *dyncon, *dynconend;
if (dyn.d_tag == DT_TEXTREL)
{
- if (info->error_textrel)
+ if (info->textrel_check == textrel_check_error)
info->callbacks->einfo
(_("%P%X: read-only segment has dynamic relocations\n"));
+ else if (bfd_link_dll (info))
+ info->callbacks->einfo
+ (_("%P: warning: creating DT_TEXTREL in a shared object\n"));
else
info->callbacks->einfo
- (_("%P: warning: creating a DT_TEXTREL in a shared object\n"));
+ (_("%P: warning: creating DT_TEXTREL in a PIE\n"));
break;
}
}
Elf_Internal_Shdr *symtab_hdr;
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
- if (cookie->locsyms != NULL
- && symtab_hdr->contents != (unsigned char *) cookie->locsyms)
+ if (symtab_hdr->contents != (unsigned char *) cookie->locsyms)
free (cookie->locsyms);
}
fini_reloc_cookie_rels (struct elf_reloc_cookie *cookie,
asection *sec)
{
- if (cookie->rels && elf_section_data (sec)->relocs != cookie->rels)
+ if (elf_section_data (sec)->relocs != cookie->rels)
free (cookie->rels);
}
}
return NULL;
}
+
+/* Find dynamic relocs for H that apply to read-only sections. */
+
+asection *
+_bfd_elf_readonly_dynrelocs (struct elf_link_hash_entry *h)
+{
+ struct elf_dyn_relocs *p;
+
+ for (p = h->dyn_relocs; p != NULL; p = p->next)
+ {
+ asection *s = p->sec->output_section;
+
+ if (s != NULL && (s->flags & SEC_READONLY) != 0)
+ return p->sec;
+ }
+ return NULL;
+}
+
+/* Set DF_TEXTREL if we find any dynamic relocs that apply to
+ read-only sections. */
+
+bfd_boolean
+_bfd_elf_maybe_set_textrel (struct elf_link_hash_entry *h, void *inf)
+{
+ asection *sec;
+
+ if (h->root.type == bfd_link_hash_indirect)
+ return TRUE;
+
+ sec = _bfd_elf_readonly_dynrelocs (h);
+ if (sec != NULL)
+ {
+ struct bfd_link_info *info = (struct bfd_link_info *) inf;
+
+ info->flags |= DF_TEXTREL;
+ /* xgettext:c-format */
+ info->callbacks->minfo (_("%pB: dynamic relocation against `%pT' "
+ "in read-only section `%pA'\n"),
+ sec->owner, h->root.root.string, sec);
+
+ if (bfd_link_textrel_check (info))
+ /* xgettext:c-format */
+ info->callbacks->einfo (_("%P: %pB: warning: relocation against `%s' "
+ "in read-only section `%pA'\n"),
+ sec->owner, h->root.root.string, sec);
+
+ /* Not an error, just cut short the traversal. */
+ return FALSE;
+ }
+ return TRUE;
+}