diff options
Diffstat (limited to 'bfd')
-rw-r--r-- | bfd/ChangeLog | 20 | ||||
-rw-r--r-- | bfd/elf32-hppa.c | 252 | ||||
-rw-r--r-- | bfd/elflink.h | 23 |
3 files changed, 153 insertions, 142 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index b41c6de..fe0399f 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,23 @@ +2001-10-23 Alan Modra <amodra@bigpond.net.au> + + * elflink.h (elf_link_input_bfd): Zero the reloc instead of doing + bfd_reloc_type_lookup (bfd, BFD_RELOC_NONE) as bfd_reloc_type_lookup + doesn't accept BFD_RELOC_* on some targets, eg. hppa. + + * elf32-hppa.c (elf32_hppa_link_hash_entry): Remove plt_abs. + (hppa_link_hash_newfunc): Likewise. + (elf32_hppa_finish_dynamic_symbol): Likewise. + (allocate_dynrelocs): Always allocate .got relocs if shared. + (elf32_hppa_relocate_section): Output them too. Similarly + consolidate .plt reloc code, and no longer initialise .plt + when a reloc is output. + (elf32_hppa_finish_dynamic_symbol): Only initialise .plt entries + when no reloc is output. + + From Herbert Xu <herbert@gondor.apana.org.au> + * elf32-hppa.c (final_link_relocate): Call bfd_set_error for + unreachable branches. + 2001-10-22 H.J. Lu <hjl@gnu.org> * configure.in (WIN32LIBADD): Use -L../libiberty for diff --git a/bfd/elf32-hppa.c b/bfd/elf32-hppa.c index 1417023..c10e892 100644 --- a/bfd/elf32-hppa.c +++ b/bfd/elf32-hppa.c @@ -213,10 +213,6 @@ struct elf32_hppa_link_hash_entry { /* Set if this symbol is used by a plabel reloc. */ unsigned int plabel:1; - - /* Set if this symbol is an init or fini function and thus should - use an absolute reloc. */ - unsigned int plt_abs:1; }; struct elf32_hppa_link_hash_table { @@ -462,7 +458,6 @@ hppa_link_hash_newfunc (entry, table, string) eh->maybe_pic_call = 0; eh->pic_call = 0; eh->plabel = 0; - eh->plt_abs = 0; } return entry; @@ -2065,8 +2060,6 @@ allocate_dynrelocs (h, inf) if (h->got.refcount > 0) { - boolean dyn; - /* Make sure this symbol is output as a dynamic symbol. Undefined weak syms won't yet be marked as dynamic. */ if (h->dynindx == -1 @@ -2080,9 +2073,13 @@ allocate_dynrelocs (h, inf) s = htab->sgot; h->got.offset = s->_raw_size; s->_raw_size += GOT_ENTRY_SIZE; - dyn = htab->elf.dynamic_sections_created; - if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, h)) - htab->srelgot->_raw_size += sizeof (Elf32_External_Rela); + if (htab->elf.dynamic_sections_created + && (info->shared + || (h->dynindx != -1 + && h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)) + { + htab->srelgot->_raw_size += sizeof (Elf32_External_Rela); + } } else h->got.offset = (bfd_vma) -1; @@ -3468,6 +3465,7 @@ final_link_relocate (input_section, contents, rel, value, htab, sym_sec, h) input_section->name, (long) rel->r_offset, stub_entry->root.string); + bfd_set_error (bfd_error_bad_value); return bfd_reloc_notsupported; } @@ -3539,7 +3537,6 @@ elf32_hppa_relocate_section (output_bfd, info, input_bfd, input_section, bfd_reloc_status_type r; const char *sym_name; boolean plabel; - bfd_vma off; r_type = ELF32_R_TYPE (rel->r_info); if (r_type >= (unsigned int) R_PARISC_UNIMPLEMENTED) @@ -3639,87 +3636,88 @@ elf32_hppa_relocate_section (output_bfd, info, input_bfd, input_section, case R_PARISC_DLTIND14F: case R_PARISC_DLTIND14R: case R_PARISC_DLTIND21L: - /* Relocation is to the entry for this symbol in the global - offset table. */ - if (h != NULL) - { - boolean dyn; - - off = h->elf.got.offset; - dyn = htab->elf.dynamic_sections_created; - if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, &h->elf)) - { - /* This is actually a static link, or it is a - -Bsymbolic link and the symbol is defined - locally, or the symbol was forced to be local - because of a version file. We must initialize - this entry in the global offset table. Since the - offset must always be a multiple of 4, we use the - least significant bit to record whether we have - initialized it already. - - When doing a dynamic link, we create a .rela.got - relocation entry to initialize the value. This - is done in the finish_dynamic_symbol routine. */ - if ((off & 1) != 0) - off &= ~1; - else - { - bfd_put_32 (output_bfd, relocation, - htab->sgot->contents + off); - h->elf.got.offset |= 1; - } - } - } - else - { - /* Local symbol case. */ - if (local_got_offsets == NULL) - abort (); - - off = local_got_offsets[r_symndx]; + { + bfd_vma off; + boolean do_got = 0; + + /* Relocation is to the entry for this symbol in the + global offset table. */ + if (h != NULL) + { + boolean dyn; + + off = h->elf.got.offset; + dyn = htab->elf.dynamic_sections_created; + if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, &h->elf)) + { + /* If we aren't going to call finish_dynamic_symbol, + then we need to handle initialisation of the .got + entry and create needed relocs here. Since the + offset must always be a multiple of 4, we use the + least significant bit to record whether we have + initialised it already. */ + if ((off & 1) != 0) + off &= ~1; + else + { + h->elf.got.offset |= 1; + do_got = 1; + } + } + } + else + { + /* Local symbol case. */ + if (local_got_offsets == NULL) + abort (); + + off = local_got_offsets[r_symndx]; + + /* The offset must always be a multiple of 4. We use + the least significant bit to record whether we have + already generated the necessary reloc. */ + if ((off & 1) != 0) + off &= ~1; + else + { + local_got_offsets[r_symndx] |= 1; + do_got = 1; + } + } - /* The offset must always be a multiple of 4. We use - the least significant bit to record whether we have - already generated the necessary reloc. */ - if ((off & 1) != 0) - off &= ~1; - else - { + if (do_got) + { + if (info->shared) + { + /* Output a dynamic relocation for this GOT entry. + In this case it is relative to the base of the + object because the symbol index is zero. */ + Elf_Internal_Rela outrel; + asection *srelgot = htab->srelgot; + Elf32_External_Rela *loc; + + outrel.r_offset = (off + + htab->sgot->output_offset + + htab->sgot->output_section->vma); + outrel.r_info = ELF32_R_INFO (0, R_PARISC_DIR32); + outrel.r_addend = relocation; + loc = (Elf32_External_Rela *) srelgot->contents; + loc += srelgot->reloc_count++; + bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc); + } + else bfd_put_32 (output_bfd, relocation, htab->sgot->contents + off); + } - if (info->shared) - { - /* Output a dynamic relocation for this GOT - entry. In this case it is relative to the - base of the object because the symbol index - is zero. */ - Elf_Internal_Rela outrel; - asection *srelgot = htab->srelgot; - Elf32_External_Rela *loc; + if (off >= (bfd_vma) -2) + abort (); - outrel.r_offset = (off - + htab->sgot->output_offset - + htab->sgot->output_section->vma); - outrel.r_info = ELF32_R_INFO (0, R_PARISC_DIR32); - outrel.r_addend = relocation; - loc = (Elf32_External_Rela *) srelgot->contents; - loc += srelgot->reloc_count++; - bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc); - } - - local_got_offsets[r_symndx] |= 1; - } - } - - if (off >= (bfd_vma) -2) - abort (); - - /* Add the base of the GOT to the relocation value. */ - relocation = (off - + htab->sgot->output_offset - + htab->sgot->output_section->vma); + /* Add the base of the GOT to the relocation value. */ + relocation = (off + + htab->sgot->output_offset + + htab->sgot->output_section->vma); + } break; case R_PARISC_SEGREL32: @@ -3734,6 +3732,9 @@ elf32_hppa_relocate_section (output_bfd, info, input_bfd, input_section, case R_PARISC_PLABEL32: if (htab->elf.dynamic_sections_created) { + bfd_vma off; + boolean do_plt = 0; + /* If we have a global symbol with a PLT slot, then redirect this relocation to it. */ if (h != NULL) @@ -3748,13 +3749,8 @@ elf32_hppa_relocate_section (output_bfd, info, input_bfd, input_section, off &= ~1; else { - bfd_put_32 (output_bfd, - relocation, - htab->splt->contents + off); - bfd_put_32 (output_bfd, - elf_gp (htab->splt->output_section->owner), - htab->splt->contents + off + 4); h->elf.plt.offset |= 1; + do_plt = 1; } } } @@ -3775,32 +3771,38 @@ elf32_hppa_relocate_section (output_bfd, info, input_bfd, input_section, off &= ~1; else { + local_plt_offsets[r_symndx] |= 1; + do_plt = 1; + } + } + + if (do_plt) + { + if (info->shared) + { + /* Output a dynamic IPLT relocation for this + PLT entry. */ + Elf_Internal_Rela outrel; + asection *srelplt = htab->srelplt; + Elf32_External_Rela *loc; + + outrel.r_offset = (off + + htab->splt->output_offset + + htab->splt->output_section->vma); + outrel.r_info = ELF32_R_INFO (0, R_PARISC_IPLT); + outrel.r_addend = relocation; + loc = (Elf32_External_Rela *) srelplt->contents; + loc += srelplt->reloc_count++; + bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc); + } + else + { bfd_put_32 (output_bfd, relocation, htab->splt->contents + off); bfd_put_32 (output_bfd, elf_gp (htab->splt->output_section->owner), htab->splt->contents + off + 4); - - if (info->shared) - { - /* Output a dynamic IPLT relocation for this - PLT entry. */ - Elf_Internal_Rela outrel; - asection *srelplt = htab->srelplt; - Elf32_External_Rela *loc; - - outrel.r_offset = (off - + htab->splt->output_offset - + htab->splt->output_section->vma); - outrel.r_info = ELF32_R_INFO (0, R_PARISC_IPLT); - outrel.r_addend = relocation; - loc = (Elf32_External_Rela *) srelplt->contents; - loc += srelplt->reloc_count++; - bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc); - } - - local_plt_offsets[r_symndx] |= 1; } } @@ -3881,6 +3883,8 @@ elf32_hppa_relocate_section (output_bfd, info, input_bfd, input_section, skip = false; if (elf_section_data (input_section)->stab_info != NULL) { + bfd_vma off; + off = (_bfd_stab_section_offset (output_bfd, &htab->elf.stab_info, input_section, @@ -4076,8 +4080,7 @@ elf32_hppa_finish_dynamic_symbol (output_bfd, info, h, sym) rel.r_offset = (h->plt.offset + htab->splt->output_offset + htab->splt->output_section->vma); - if (! ((struct elf32_hppa_link_hash_entry *) h)->plt_abs - && h->dynindx != -1) + if (h->dynindx != -1) { /* To support lazy linking, the function pointer is initialised to point to a special stub stored at the @@ -4104,19 +4107,14 @@ elf32_hppa_finish_dynamic_symbol (output_bfd, info, h, sym) bfd_elf32_swap_reloca_out (htab->splt->output_section->owner, &rel, loc); } - - bfd_put_32 (htab->splt->owner, - value, - htab->splt->contents + h->plt.offset); - bfd_put_32 (htab->splt->owner, - elf_gp (htab->splt->output_section->owner), - htab->splt->contents + h->plt.offset + 4); - if (PLABEL_PLT_ENTRY_SIZE != PLT_ENTRY_SIZE - && ((struct elf32_hppa_link_hash_entry *) h)->plabel - && h->dynindx != -1) + else { - memset (htab->splt->contents + h->plt.offset + 8, - 0, PLABEL_PLT_ENTRY_SIZE - PLT_ENTRY_SIZE); + bfd_put_32 (htab->splt->owner, + value, + htab->splt->contents + h->plt.offset); + bfd_put_32 (htab->splt->owner, + elf_gp (htab->splt->output_section->owner), + htab->splt->contents + h->plt.offset + 4); } if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0) diff --git a/bfd/elflink.h b/bfd/elflink.h index 7cfa0fb..fd251b0 100644 --- a/bfd/elflink.h +++ b/bfd/elflink.h @@ -5897,8 +5897,6 @@ elf_link_input_bfd (finfo, input_bfd) asection *o; struct elf_backend_data *bed; boolean emit_relocs; - reloc_howto_type *none_howto; - bfd_vma none_r_info; output_bfd = finfo->output_bfd; bed = get_elf_backend_data (output_bfd); @@ -6070,9 +6068,6 @@ elf_link_input_bfd (finfo, input_bfd) return false; } - none_howto = bfd_reloc_type_lookup (output_bfd, BFD_RELOC_NONE); - none_r_info = ELF_R_INFO (0, none_howto->type); - /* Relocate the contents of each section. */ for (o = input_bfd->sections; o != NULL; o = o->next) { @@ -6125,13 +6120,12 @@ elf_link_input_bfd (finfo, input_bfd) { Elf_Internal_Rela *rel, *relend; /* Run through the relocs looking for any against section - symbols from removed link-once sections. Set any such - relocs to be against 0. We should really complain if - anything in the final link tries to use it, but - DWARF-based exception handling might have an entry in - .eh_frame to describe a routine in the linkonce section, - and it turns out to be hard to remove the .eh_frame entry - too. FIXME. */ + symbols from removed link-once sections. Zero any such + relocs. We should really complain if anything in the + final link tries to use it, but DWARF-based exception + handling might have an entry in .eh_frame to describe a + routine in the linkonce section, and it turns out to be + hard to remove the .eh_frame entry too. FIXME. */ rel = internal_relocs; relend = rel + o->reloc_count * bed->s->int_rels_per_ext_rel; for ( ; rel < relend; rel++) @@ -6151,21 +6145,20 @@ elf_link_input_bfd (finfo, input_bfd) && (sec->flags & SEC_LINK_ONCE) != 0 && bfd_is_abs_section (sec->output_section)) { - rel->r_info = none_r_info; - #if BFD_VERSION_DATE > 20021005 (*finfo->info->callbacks->warning) (finfo->info, _("warning: relocation against removed section; zeroing"), NULL, input_bfd, o, rel->r_offset); #endif + memset (rel, 0, sizeof (*rel)); } } } } } #else -#error "This kludge ought to be fixed properly in gcc by now" +#error "gcc should be fixed by now, and this kludge no longer needed" #endif /* Relocate the section by invoking a back end routine. |