diff options
-rw-r--r-- | bfd/ChangeLog | 20 | ||||
-rw-r--r-- | bfd/elf32-ppc.c | 218 | ||||
-rw-r--r-- | bfd/elf32-ppc.h | 2 | ||||
-rw-r--r-- | ld/ChangeLog | 9 | ||||
-rw-r--r-- | ld/emulparams/elf32ppccommon.sh | 2 | ||||
-rw-r--r-- | ld/emultempl/ppc32elf.em | 2 | ||||
-rw-r--r-- | ld/ldlang.c | 15 |
7 files changed, 150 insertions, 118 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 976e330..5d15e64 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,23 @@ +2014-05-20 Alan Modra <amodra@gmail.com> + + PR 16952 + * elf32-ppc.c (ppc_elf_create_linker_section): Move earlier. + Remove redundant setting of htab->elf.dynobj. Don't align. + Define .sdata symbols using _bfd_elf_define_linkage_sym. + (ppc_elf_create_glink): Call ppc_elf_create_linker_section. + (create_sdata_sym): Delete. + (elf_allocate_pointer_linker_section): Rename from + elf_create_pointer_linker_section. Align section. + (ppc_elf_check_relocs): Don't call ppc_elf_creat_linker_section + directly here, or create_sdata_sym. Set ref_regular on _SDA_BASE_ + and _SDA2_BASE_. + (ppc_elf_size_dynamic_sections): Remove ATTRIBUTE_UNUSED on param. + Remove unnecessary tests on _SDA_BASE_ sym. + (maybe_strip_sdasym, ppc_elf_maybe_strip_sdata_syms): New functions. + (ppc_elf_relocate_section): Tighten SDA reloc symbol section checks. + * elf32-ppc.h (ppc_elf_set_sdata_syms): Delete. + (ppc_elf_maybe_strip_sdata_syms): Declare. + 2014-05-16 Ryan Mansfield <rmansfield@qnx.com> * config.bfd: Move QNX target_cflags from arm-*-netbsd* to arm-*-nto*. diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c index b99db68..1bea6f8 100644 --- a/bfd/elf32-ppc.c +++ b/bfd/elf32-ppc.c @@ -3338,6 +3338,36 @@ ppc_elf_create_got (bfd *abfd, struct bfd_link_info *info) return TRUE; } +/* Create a special linker section, used for R_PPC_EMB_SDAI16 and + R_PPC_EMB_SDA2I16 pointers. These sections become part of .sdata + and .sdata2. Create _SDA_BASE_ and _SDA2_BASE too. */ + +static bfd_boolean +ppc_elf_create_linker_section (bfd *abfd, + struct bfd_link_info *info, + flagword flags, + elf_linker_section_t *lsect) +{ + asection *s; + + flags |= (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY + | SEC_LINKER_CREATED); + + s = bfd_make_section_anyway_with_flags (abfd, lsect->name, flags); + if (s == NULL) + return FALSE; + lsect->section = s; + + /* Define the sym on the first section of this name. */ + s = bfd_get_section_by_name (abfd, lsect->name); + + lsect->sym = _bfd_elf_define_linkage_sym (abfd, info, s, lsect->sym_name); + if (lsect->sym == NULL) + return FALSE; + lsect->sym->root.u.def.value = 0x8000; + return TRUE; +} + static bfd_boolean ppc_elf_create_glink (bfd *abfd, struct bfd_link_info *info) { @@ -3379,6 +3409,15 @@ ppc_elf_create_glink (bfd *abfd, struct bfd_link_info *info) if (s == NULL || ! bfd_set_section_alignment (abfd, s, 2)) return FALSE; + + if (!ppc_elf_create_linker_section (abfd, info, 0, + &htab->sdata[0])) + return FALSE; + + if (!ppc_elf_create_linker_section (abfd, info, SEC_READONLY, + &htab->sdata[1])) + return FALSE; + return TRUE; } @@ -3605,51 +3644,6 @@ ppc_elf_add_symbol_hook (bfd *abfd, return TRUE; } -static bfd_boolean -create_sdata_sym (struct bfd_link_info *info, elf_linker_section_t *lsect) -{ - struct ppc_elf_link_hash_table *htab = ppc_elf_hash_table (info); - - lsect->sym = elf_link_hash_lookup (&htab->elf, lsect->sym_name, - TRUE, FALSE, TRUE); - if (lsect->sym == NULL) - return FALSE; - if (lsect->sym->root.type == bfd_link_hash_new) - lsect->sym->non_elf = 0; - lsect->sym->ref_regular = 1; - _bfd_elf_link_hash_hide_symbol (info, lsect->sym, TRUE); - return TRUE; -} - -/* Create a special linker section. */ - -static bfd_boolean -ppc_elf_create_linker_section (bfd *abfd, - struct bfd_link_info *info, - flagword flags, - elf_linker_section_t *lsect) -{ - struct ppc_elf_link_hash_table *htab = ppc_elf_hash_table (info); - asection *s; - - flags |= (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY - | SEC_LINKER_CREATED); - - /* Record the first bfd that needs the special sections. */ - if (!htab->elf.dynobj) - htab->elf.dynobj = abfd; - - s = bfd_make_section_anyway_with_flags (htab->elf.dynobj, - lsect->name, - flags); - if (s == NULL - || !bfd_set_section_alignment (htab->elf.dynobj, s, 2)) - return FALSE; - lsect->section = s; - - return create_sdata_sym (info, lsect); -} - /* Find a linker generated pointer with a given addend and type. */ static elf_linker_section_pointers_t * @@ -3668,10 +3662,10 @@ elf_find_pointer_linker_section /* Allocate a pointer to live in a linker created section. */ static bfd_boolean -elf_create_pointer_linker_section (bfd *abfd, - elf_linker_section_t *lsect, - struct elf_link_hash_entry *h, - const Elf_Internal_Rela *rel) +elf_allocate_pointer_linker_section (bfd *abfd, + elf_linker_section_t *lsect, + struct elf_link_hash_entry *h, + const Elf_Internal_Rela *rel) { elf_linker_section_pointers_t **ptr_linker_section_ptr = NULL; elf_linker_section_pointers_t *linker_section_ptr; @@ -3739,6 +3733,8 @@ elf_create_pointer_linker_section (bfd *abfd, linker_section_ptr->lsect = lsect; *ptr_linker_section_ptr = linker_section_ptr; + if (!bfd_set_section_alignment (lsect->section->owner, lsect->section, 2)) + return FALSE; linker_section_ptr->offset = lsect->section->size; lsect->section->size += 4; @@ -4074,12 +4070,9 @@ ppc_elf_check_relocs (bfd *abfd, bad_shared_reloc (abfd, r_type); return FALSE; } - if (htab->sdata[0].section == NULL - && !ppc_elf_create_linker_section (abfd, info, 0, - &htab->sdata[0])) - return FALSE; - if (!elf_create_pointer_linker_section (abfd, &htab->sdata[0], - h, rel)) + htab->sdata[0].sym->ref_regular = 1; + if (!elf_allocate_pointer_linker_section (abfd, &htab->sdata[0], + h, rel)) return FALSE; if (h != NULL) { @@ -4095,12 +4088,9 @@ ppc_elf_check_relocs (bfd *abfd, bad_shared_reloc (abfd, r_type); return FALSE; } - if (htab->sdata[1].section == NULL - && !ppc_elf_create_linker_section (abfd, info, SEC_READONLY, - &htab->sdata[1])) - return FALSE; - if (!elf_create_pointer_linker_section (abfd, &htab->sdata[1], - h, rel)) + htab->sdata[1].sym->ref_regular = 1; + if (!elf_allocate_pointer_linker_section (abfd, &htab->sdata[1], + h, rel)) return FALSE; if (h != NULL) { @@ -4109,21 +4099,16 @@ ppc_elf_check_relocs (bfd *abfd, } break; + case R_PPC_SDAREL16: + htab->sdata[0].sym->ref_regular = 1; + /* Fall thru */ + case R_PPC_VLE_SDAREL_LO16A: case R_PPC_VLE_SDAREL_LO16D: case R_PPC_VLE_SDAREL_HI16A: case R_PPC_VLE_SDAREL_HI16D: case R_PPC_VLE_SDAREL_HA16A: case R_PPC_VLE_SDAREL_HA16D: - case R_PPC_SDAREL16: - if (htab->sdata[0].sym == NULL - && !create_sdata_sym (info, &htab->sdata[0])) - return FALSE; - - if (htab->sdata[1].sym == NULL - && !create_sdata_sym (info, &htab->sdata[1])) - return FALSE; - if (h != NULL) { ppc_elf_hash_entry (h)->has_sda_refs = TRUE; @@ -4148,9 +4133,7 @@ ppc_elf_check_relocs (bfd *abfd, bad_shared_reloc (abfd, r_type); return FALSE; } - if (htab->sdata[1].sym == NULL - && !create_sdata_sym (info, &htab->sdata[1])) - return FALSE; + htab->sdata[1].sym->ref_regular = 1; if (h != NULL) { ppc_elf_hash_entry (h)->has_sda_refs = TRUE; @@ -4167,12 +4150,6 @@ ppc_elf_check_relocs (bfd *abfd, bad_shared_reloc (abfd, r_type); return FALSE; } - if (htab->sdata[0].sym == NULL - && !create_sdata_sym (info, &htab->sdata[0])) - return FALSE; - if (htab->sdata[1].sym == NULL - && !create_sdata_sym (info, &htab->sdata[1])) - return FALSE; if (h != NULL) { ppc_elf_hash_entry (h)->has_sda_refs = TRUE; @@ -6119,7 +6096,7 @@ static const unsigned char glink_eh_frame_cie[] = /* Set the sizes of the dynamic sections. */ static bfd_boolean -ppc_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, +ppc_elf_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info) { struct ppc_elf_link_hash_table *htab; @@ -6323,14 +6300,9 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, if (info->shared) { struct elf_link_hash_entry *sda = htab->sdata[0].sym; - if (sda != NULL - && !(sda->root.type == bfd_link_hash_defined - || sda->root.type == bfd_link_hash_defweak)) - { - sda->root.type = bfd_link_hash_defined; - sda->root.u.def.section = htab->elf.hgot->root.u.def.section; - sda->root.u.def.value = htab->elf.hgot->root.u.def.value; - } + + sda->root.u.def.section = htab->elf.hgot->root.u.def.section; + sda->root.u.def.value = htab->elf.hgot->root.u.def.value; } if (htab->glink != NULL @@ -6599,6 +6571,46 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, return TRUE; } +/* Arrange to have _SDA_BASE_ or _SDA2_BASE_ stripped from the output + if it looks like nothing is using them. */ + +static void +maybe_strip_sdasym (bfd *output_bfd, elf_linker_section_t *lsect) +{ + struct elf_link_hash_entry *sda = lsect->sym; + + if (sda != NULL && !sda->ref_regular && sda->dynindx == -1) + { + asection *s; + + s = bfd_get_section_by_name (output_bfd, lsect->name); + if (s == NULL || bfd_section_removed_from_list (output_bfd, s)) + { + s = bfd_get_section_by_name (output_bfd, lsect->bss_name); + if (s == NULL || bfd_section_removed_from_list (output_bfd, s)) + { + sda->def_regular = 0; + /* This is somewhat magic. See elf_link_output_extsym. */ + sda->ref_dynamic = 1; + sda->forced_local = 0; + } + } + } +} + +void +ppc_elf_maybe_strip_sdata_syms (struct bfd_link_info *info) +{ + struct ppc_elf_link_hash_table *htab = ppc_elf_hash_table (info); + + if (htab != NULL) + { + maybe_strip_sdasym (info->output_bfd, &htab->sdata[0]); + maybe_strip_sdasym (info->output_bfd, &htab->sdata[1]); + } +} + + /* Return TRUE if symbol should be hashed in the `.gnu.hash' section. */ static bfd_boolean @@ -8696,10 +8708,8 @@ ppc_elf_relocate_section (bfd *output_bfd, addend -= SYM_VAL (sda); name = bfd_get_section_name (output_bfd, sec->output_section); - if (! ((CONST_STRNEQ (name, ".sdata") - && (name[6] == 0 || name[6] == '.')) - || (CONST_STRNEQ (name, ".sbss") - && (name[5] == 0 || name[5] == '.')))) + if (!(strcmp (name, ".sdata") == 0 + || strcmp (name, ".sbss") == 0)) { info->callbacks->einfo (_("%P: %B: the target (%s) of a %s relocation is " @@ -8728,8 +8738,8 @@ ppc_elf_relocate_section (bfd *output_bfd, addend -= SYM_VAL (sda); name = bfd_get_section_name (output_bfd, sec->output_section); - if (! (CONST_STRNEQ (name, ".sdata2") - || CONST_STRNEQ (name, ".sbss2"))) + if (!(strcmp (name, ".sdata2") == 0 + || strcmp (name, ".sbss2") == 0)) { info->callbacks->einfo (_("%P: %B: the target (%s) of a %s relocation is " @@ -8796,16 +8806,14 @@ ppc_elf_relocate_section (bfd *output_bfd, } name = bfd_get_section_name (output_bfd, sec->output_section); - if (((CONST_STRNEQ (name, ".sdata") - && (name[6] == 0 || name[6] == '.')) - || (CONST_STRNEQ (name, ".sbss") - && (name[5] == 0 || name[5] == '.')))) + if (strcmp (name, ".sdata") == 0 + || strcmp (name, ".sbss") == 0) { reg = 13; sda = htab->sdata[0].sym; } - else if (CONST_STRNEQ (name, ".sdata2") - || CONST_STRNEQ (name, ".sbss2")) + else if (strcmp (name, ".sdata2") == 0 + || strcmp (name, ".sbss2") == 0) { reg = 2; sda = htab->sdata[1].sym; @@ -8897,16 +8905,14 @@ ppc_elf_relocate_section (bfd *output_bfd, } name = bfd_get_section_name (output_bfd, sec->output_section); - if (((CONST_STRNEQ (name, ".sdata") - && (name[6] == 0 || name[6] == '.')) - || (CONST_STRNEQ (name, ".sbss") - && (name[5] == 0 || name[5] == '.')))) + if (strcmp (name, ".sdata") == 0 + || strcmp (name, ".sbss") == 0) { //reg = 13; sda = htab->sdata[0].sym; } - else if (CONST_STRNEQ (name, ".sdata2") - || CONST_STRNEQ (name, ".sbss2")) + else if (strcmp (name, ".sdata2") == 0 + || strcmp (name, ".sbss2") == 0) { //reg = 2; sda = htab->sdata[1].sym; diff --git a/bfd/elf32-ppc.h b/bfd/elf32-ppc.h index e8d19ec..07dc4c8 100644 --- a/bfd/elf32-ppc.h +++ b/bfd/elf32-ppc.h @@ -50,7 +50,7 @@ void ppc_elf_link_params (struct bfd_link_info *, struct ppc_elf_params *); int ppc_elf_select_plt_layout (bfd *, struct bfd_link_info *); asection *ppc_elf_tls_setup (bfd *, struct bfd_link_info *); bfd_boolean ppc_elf_tls_optimize (bfd *, struct bfd_link_info *); -void ppc_elf_set_sdata_syms (bfd *, struct bfd_link_info *); +void ppc_elf_maybe_strip_sdata_syms (struct bfd_link_info *); extern bfd_boolean ppc_elf_modify_segment_map (bfd *, struct bfd_link_info * ATTRIBUTE_UNUSED); extern bfd_boolean ppc_elf_section_processing (bfd *, Elf_Internal_Shdr *); diff --git a/ld/ChangeLog b/ld/ChangeLog index b8e926e..53f9f94 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,12 @@ +2014-05-20 Alan Modra <amodra@gmail.com> + + PR 16952 + * emulparams/elf32ppccommon.sh (_SDA_BASE_, _SDA2_BASE_): Delete. + * emultempl/ppc32elf.em (ppc_before_allocation): Call + ppc_elf_maybe_strip_sdata_syms. + * ldlang.c (size_input_section): Correct output_offset value + for excluded input sections. + 2014-05-16 John Marino <binutils@marino.st> * configure.tgt: Add /lib to dragonfly NATIVE_LIB_DIRS. diff --git a/ld/emulparams/elf32ppccommon.sh b/ld/emulparams/elf32ppccommon.sh index 049fdb9..1f54ef8 100644 --- a/ld/emulparams/elf32ppccommon.sh +++ b/ld/emulparams/elf32ppccommon.sh @@ -13,8 +13,6 @@ ARCH=powerpc:common MACHINE= EXECUTABLE_SYMBOLS='PROVIDE (__stack = 0); PROVIDE (___stack = 0);' if test -z "${CREATE_SHLIB}"; then - SDATA_START_SYMBOLS="PROVIDE (_SDA_BASE_ = 32768);" - SDATA2_START_SYMBOLS="PROVIDE (_SDA2_BASE_ = 32768);" SBSS_START_SYMBOLS="PROVIDE (__sbss_start = .); PROVIDE (___sbss_start = .);" SBSS_END_SYMBOLS="PROVIDE (__sbss_end = .); PROVIDE (___sbss_end = .);" else diff --git a/ld/emultempl/ppc32elf.em b/ld/emultempl/ppc32elf.em index 069acd2..0e2af12 100644 --- a/ld/emultempl/ppc32elf.em +++ b/ld/emultempl/ppc32elf.em @@ -135,6 +135,8 @@ ppc_before_allocation (void) gld${EMULATION_NAME}_before_allocation (); + ppc_elf_maybe_strip_sdata_syms (&link_info); + if (RELAXATION_ENABLED) params.branch_trampolines = 1; diff --git a/ld/ldlang.c b/ld/ldlang.c index 8d1e3f7..7c076a2 100644 --- a/ld/ldlang.c +++ b/ld/ldlang.c @@ -4608,12 +4608,15 @@ size_input_section { lang_input_section_type *is = &((*this_ptr)->input_section); asection *i = is->section; + asection *o = output_section_statement->bfd_section; - if (i->sec_info_type != SEC_INFO_TYPE_JUST_SYMS - && (i->flags & SEC_EXCLUDE) == 0) + if (i->sec_info_type == SEC_INFO_TYPE_JUST_SYMS) + i->output_offset = i->vma - o->vma; + else if ((i->flags & SEC_EXCLUDE) != 0) + i->output_offset = dot - o->vma; + else { bfd_size_type alignment_needed; - asection *o; /* Align this section first to the input sections requirement, then to the output section's requirement. If this alignment @@ -4623,7 +4626,6 @@ size_input_section if (output_section_statement->subsection_alignment != -1) i->alignment_power = output_section_statement->subsection_alignment; - o = output_section_statement->bfd_section; if (o->alignment_power < i->alignment_power) o->alignment_power = i->alignment_power; @@ -4636,17 +4638,12 @@ size_input_section } /* Remember where in the output section this input section goes. */ - i->output_offset = dot - o->vma; /* Mark how big the output section must be to contain this now. */ dot += TO_ADDR (i->size); o->size = TO_SIZE (dot - o->vma); } - else - { - i->output_offset = i->vma - output_section_statement->bfd_section->vma; - } return dot; } |