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)
elf_hash_table (info)->tls_sec = tls;
- /* Ensure the alignment of the first section is the largest alignment,
- so that the tls segment starts aligned. */
+ /* Ensure the alignment of the first section (usually .tdata) is the largest
+ alignment, so that the tls segment starts aligned. */
if (tls != NULL)
tls->alignment_power = align;
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;
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)
/* If this symbol is defined in a section which we are
discarding, we don't need to keep it. */
+ if (isym->st_shndx != SHN_UNDEF
+ && isym->st_shndx < SHN_LORESERVE
+ && isec->output_section == NULL
+ && flinfo->info->non_contiguous_regions
+ && flinfo->info->non_contiguous_regions_warnings)
+ {
+ _bfd_error_handler (_("warning: --enable-non-contiguous-regions "
+ "discards section `%s' from '%s'\n"),
+ isec->name, bfd_get_filename (isec->owner));
+ continue;
+ }
+
if (isym->st_shndx != SHN_UNDEF
&& isym->st_shndx < SHN_LORESERVE
&& bfd_section_removed_from_list (output_bfd,
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);
struct bfd_link_order *p;
bfd *sub;
struct bfd_link_order **sections;
- asection *s, *other_sec, *linkorder_sec;
- bfd_vma offset;
+ asection *other_sec, *linkorder_sec;
+ bfd_vma offset; /* Octets. */
other_sec = NULL;
linkorder_sec = NULL;
{
if (p->type == bfd_indirect_link_order)
{
- s = p->u.indirect.section;
+ asection *s = p->u.indirect.section;
sub = s->owner;
if ((s->flags & SEC_LINKER_CREATED) == 0
&& bfd_get_flavour (sub) == bfd_target_elf_flavour
for (n = 0; n < seen_linkorder; n++)
{
bfd_vma mask;
- s = sections[n]->u.indirect.section;
- mask = ~(bfd_vma) 0 << s->alignment_power;
+ asection *s = sections[n]->u.indirect.section;
+ unsigned int opb = bfd_octets_per_byte (abfd, s);
+
+ mask = ~(bfd_vma) 0 << s->alignment_power * opb;
offset = (offset + ~mask) & mask;
- s->output_offset = offset / bfd_octets_per_byte (abfd, s);
- sections[n]->offset = offset;
+ sections[n]->offset = s->output_offset = offset / opb;
offset += sections[n]->size;
}
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 (htab->tls_sec)
{
- bfd_vma base, end = 0;
+ bfd_vma base, end = 0; /* Both bytes. */
asection *sec;
for (sec = htab->tls_sec;
sec = sec->next)
{
bfd_size_type size = sec->size;
+ unsigned int opb = bfd_octets_per_byte (abfd, sec);
if (size == 0
&& (sec->flags & SEC_HAS_CONTENTS) == 0)
struct bfd_link_order *ord = sec->map_tail.link_order;
if (ord != NULL)
- size = ord->offset + ord->size;
+ size = ord->offset * opb + ord->size;
}
- end = sec->vma + size;
+ end = sec->vma + size / opb;
}
base = htab->tls_sec->vma;
/* Only align end of TLS section if static TLS doesn't have special
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;
if (bed->dtrel_excludes_plt && htab->srelplt != NULL)
{
+ unsigned int opb = bfd_octets_per_byte (abfd, o);
+
/* Don't count procedure linkage table relocs in the
overall reloc count. */
sh_size -= htab->srelplt->size;
/* If .rela.plt is the first .rela section, exclude
it from DT_RELA. */
else if (sh_addr == (htab->srelplt->output_section->vma
- + htab->srelplt->output_offset))
+ + htab->srelplt->output_offset) * opb)
sh_addr += htab->srelplt->size;
}
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);
}
{
asection *i;
int eh_changed = 0;
- unsigned int eh_alignment;
+ unsigned int eh_alignment; /* Octets. */
for (i = o->map_head.s; i != NULL; i = i->map_head.s)
{
fini_reloc_cookie_for_section (&cookie, i);
}
- eh_alignment = 1 << o->alignment_power;
+ eh_alignment = ((1 << o->alignment_power)
+ * bfd_octets_per_byte (output_bfd, o));
/* Skip over zero terminator, and prevent empty sections from
adding alignment padding at the end. */
for (i = o->map_tail.s; i != NULL; i = i->map_tail.s)