X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=bfd%2Felflink.c;h=6624864bf540bd1bedc2c14b9950d52a33da9a21;hb=af2d5cd8e9f81832b04af6cd0e51def4065bbf71;hp=369f3cb3e7bef6baa0e5e23d4bb2bfe2a7b20db0;hpb=502794d4321dc17d5c9fb591bedc8761118b2943;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elflink.c b/bfd/elflink.c index 369f3cb3e7..6624864bf5 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -3323,8 +3323,8 @@ _bfd_elf_tls_setup (bfd *obfd, struct bfd_link_info *info) 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; @@ -3501,6 +3501,104 @@ _bfd_elf_add_dynamic_entry (struct bfd_link_info *info, 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. */ @@ -9886,11 +9984,13 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data) && (!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) @@ -10567,6 +10667,18 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd) /* 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, isec->owner->filename); + continue; + } + if (isym->st_shndx != SHN_UNDEF && isym->st_shndx < SHN_LORESERVE && bfd_section_removed_from_list (output_bfd, @@ -11566,8 +11678,8 @@ elf_fixup_link_order (bfd *abfd, asection *o) 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; @@ -11577,7 +11689,7 @@ elf_fixup_link_order (bfd *abfd, asection *o) { 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 @@ -11632,11 +11744,12 @@ elf_fixup_link_order (bfd *abfd, asection *o) 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; } @@ -12247,7 +12360,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) if (htab->tls_sec) { - bfd_vma base, end = 0; + bfd_vma base, end = 0; /* Both bytes. */ asection *sec; for (sec = htab->tls_sec; @@ -12255,6 +12368,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) 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) @@ -12262,9 +12376,9 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) 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 @@ -12777,6 +12891,8 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) 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; @@ -12796,7 +12912,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) /* 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; } @@ -14251,7 +14367,7 @@ bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info) { 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) { @@ -14278,7 +14394,8 @@ bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info) 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)