aboutsummaryrefslogtreecommitdiff
path: root/bfd
diff options
context:
space:
mode:
Diffstat (limited to 'bfd')
-rw-r--r--bfd/ChangeLog20
-rw-r--r--bfd/elf32-hppa.c252
-rw-r--r--bfd/elflink.h23
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.