* 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.
This commit is contained in:
Alan Modra 2001-10-23 03:55:24 +00:00
parent a1675ea138
commit ce757d1518
3 changed files with 150 additions and 139 deletions

View file

@ -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> 2001-10-22 H.J. Lu <hjl@gnu.org>
* configure.in (WIN32LIBADD): Use -L../libiberty for * configure.in (WIN32LIBADD): Use -L../libiberty for

View file

@ -213,10 +213,6 @@ struct elf32_hppa_link_hash_entry {
/* Set if this symbol is used by a plabel reloc. */ /* Set if this symbol is used by a plabel reloc. */
unsigned int plabel:1; 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 { struct elf32_hppa_link_hash_table {
@ -462,7 +458,6 @@ hppa_link_hash_newfunc (entry, table, string)
eh->maybe_pic_call = 0; eh->maybe_pic_call = 0;
eh->pic_call = 0; eh->pic_call = 0;
eh->plabel = 0; eh->plabel = 0;
eh->plt_abs = 0;
} }
return entry; return entry;
@ -2065,8 +2060,6 @@ allocate_dynrelocs (h, inf)
if (h->got.refcount > 0) if (h->got.refcount > 0)
{ {
boolean dyn;
/* Make sure this symbol is output as a dynamic symbol. /* Make sure this symbol is output as a dynamic symbol.
Undefined weak syms won't yet be marked as dynamic. */ Undefined weak syms won't yet be marked as dynamic. */
if (h->dynindx == -1 if (h->dynindx == -1
@ -2080,9 +2073,13 @@ allocate_dynrelocs (h, inf)
s = htab->sgot; s = htab->sgot;
h->got.offset = s->_raw_size; h->got.offset = s->_raw_size;
s->_raw_size += GOT_ENTRY_SIZE; s->_raw_size += GOT_ENTRY_SIZE;
dyn = htab->elf.dynamic_sections_created; if (htab->elf.dynamic_sections_created
if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, h)) && (info->shared
htab->srelgot->_raw_size += sizeof (Elf32_External_Rela); || (h->dynindx != -1
&& h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0))
{
htab->srelgot->_raw_size += sizeof (Elf32_External_Rela);
}
} }
else else
h->got.offset = (bfd_vma) -1; 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, input_section->name,
(long) rel->r_offset, (long) rel->r_offset,
stub_entry->root.string); stub_entry->root.string);
bfd_set_error (bfd_error_bad_value);
return bfd_reloc_notsupported; return bfd_reloc_notsupported;
} }
@ -3539,7 +3537,6 @@ elf32_hppa_relocate_section (output_bfd, info, input_bfd, input_section,
bfd_reloc_status_type r; bfd_reloc_status_type r;
const char *sym_name; const char *sym_name;
boolean plabel; boolean plabel;
bfd_vma off;
r_type = ELF32_R_TYPE (rel->r_info); r_type = ELF32_R_TYPE (rel->r_info);
if (r_type >= (unsigned int) R_PARISC_UNIMPLEMENTED) 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_DLTIND14F:
case R_PARISC_DLTIND14R: case R_PARISC_DLTIND14R:
case R_PARISC_DLTIND21L: case R_PARISC_DLTIND21L:
/* Relocation is to the entry for this symbol in the global {
offset table. */ bfd_vma off;
if (h != NULL) boolean do_got = 0;
{
boolean dyn;
off = h->elf.got.offset; /* Relocation is to the entry for this symbol in the
dyn = htab->elf.dynamic_sections_created; global offset table. */
if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, &h->elf)) if (h != NULL)
{ {
/* This is actually a static link, or it is a boolean dyn;
-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 off = h->elf.got.offset;
relocation entry to initialize the value. This dyn = htab->elf.dynamic_sections_created;
is done in the finish_dynamic_symbol routine. */ if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, &h->elf))
if ((off & 1) != 0) {
off &= ~1; /* If we aren't going to call finish_dynamic_symbol,
else then we need to handle initialisation of the .got
{ entry and create needed relocs here. Since the
bfd_put_32 (output_bfd, relocation, offset must always be a multiple of 4, we use the
htab->sgot->contents + off); least significant bit to record whether we have
h->elf.got.offset |= 1; initialised it already. */
} if ((off & 1) != 0)
} off &= ~1;
} else
else {
{ h->elf.got.offset |= 1;
/* Local symbol case. */ do_got = 1;
if (local_got_offsets == NULL) }
abort (); }
}
else
{
/* Local symbol case. */
if (local_got_offsets == NULL)
abort ();
off = local_got_offsets[r_symndx]; off = local_got_offsets[r_symndx];
/* The offset must always be a multiple of 4. We use /* The offset must always be a multiple of 4. We use
the least significant bit to record whether we have the least significant bit to record whether we have
already generated the necessary reloc. */ already generated the necessary reloc. */
if ((off & 1) != 0) if ((off & 1) != 0)
off &= ~1; off &= ~1;
else else
{ {
local_got_offsets[r_symndx] |= 1;
do_got = 1;
}
}
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, bfd_put_32 (output_bfd, relocation,
htab->sgot->contents + off); htab->sgot->contents + off);
}
if (info->shared) if (off >= (bfd_vma) -2)
{ abort ();
/* 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 /* Add the base of the GOT to the relocation value. */
+ htab->sgot->output_offset relocation = (off
+ htab->sgot->output_section->vma); + htab->sgot->output_offset
outrel.r_info = ELF32_R_INFO (0, R_PARISC_DIR32); + htab->sgot->output_section->vma);
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);
break; break;
case R_PARISC_SEGREL32: case R_PARISC_SEGREL32:
@ -3734,6 +3732,9 @@ elf32_hppa_relocate_section (output_bfd, info, input_bfd, input_section,
case R_PARISC_PLABEL32: case R_PARISC_PLABEL32:
if (htab->elf.dynamic_sections_created) if (htab->elf.dynamic_sections_created)
{ {
bfd_vma off;
boolean do_plt = 0;
/* If we have a global symbol with a PLT slot, then /* If we have a global symbol with a PLT slot, then
redirect this relocation to it. */ redirect this relocation to it. */
if (h != NULL) if (h != NULL)
@ -3748,13 +3749,8 @@ elf32_hppa_relocate_section (output_bfd, info, input_bfd, input_section,
off &= ~1; off &= ~1;
else 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; h->elf.plt.offset |= 1;
do_plt = 1;
} }
} }
} }
@ -3773,6 +3769,32 @@ elf32_hppa_relocate_section (output_bfd, info, input_bfd, input_section,
this local .plt entry. */ this local .plt entry. */
if ((off & 1) != 0) if ((off & 1) != 0)
off &= ~1; 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 else
{ {
bfd_put_32 (output_bfd, bfd_put_32 (output_bfd,
@ -3781,26 +3803,6 @@ elf32_hppa_relocate_section (output_bfd, info, input_bfd, input_section,
bfd_put_32 (output_bfd, bfd_put_32 (output_bfd,
elf_gp (htab->splt->output_section->owner), elf_gp (htab->splt->output_section->owner),
htab->splt->contents + off + 4); 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; skip = false;
if (elf_section_data (input_section)->stab_info != NULL) if (elf_section_data (input_section)->stab_info != NULL)
{ {
bfd_vma off;
off = (_bfd_stab_section_offset off = (_bfd_stab_section_offset
(output_bfd, &htab->elf.stab_info, (output_bfd, &htab->elf.stab_info,
input_section, input_section,
@ -4076,8 +4080,7 @@ elf32_hppa_finish_dynamic_symbol (output_bfd, info, h, sym)
rel.r_offset = (h->plt.offset rel.r_offset = (h->plt.offset
+ htab->splt->output_offset + htab->splt->output_offset
+ htab->splt->output_section->vma); + htab->splt->output_section->vma);
if (! ((struct elf32_hppa_link_hash_entry *) h)->plt_abs if (h->dynindx != -1)
&& h->dynindx != -1)
{ {
/* To support lazy linking, the function pointer is /* To support lazy linking, the function pointer is
initialised to point to a special stub stored at the 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, bfd_elf32_swap_reloca_out (htab->splt->output_section->owner,
&rel, loc); &rel, loc);
} }
else
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)
{ {
memset (htab->splt->contents + h->plt.offset + 8, bfd_put_32 (htab->splt->owner,
0, PLABEL_PLT_ENTRY_SIZE - PLT_ENTRY_SIZE); 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) if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)

View file

@ -5897,8 +5897,6 @@ elf_link_input_bfd (finfo, input_bfd)
asection *o; asection *o;
struct elf_backend_data *bed; struct elf_backend_data *bed;
boolean emit_relocs; boolean emit_relocs;
reloc_howto_type *none_howto;
bfd_vma none_r_info;
output_bfd = finfo->output_bfd; output_bfd = finfo->output_bfd;
bed = get_elf_backend_data (output_bfd); bed = get_elf_backend_data (output_bfd);
@ -6070,9 +6068,6 @@ elf_link_input_bfd (finfo, input_bfd)
return false; 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. */ /* Relocate the contents of each section. */
for (o = input_bfd->sections; o != NULL; o = o->next) 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; Elf_Internal_Rela *rel, *relend;
/* Run through the relocs looking for any against section /* Run through the relocs looking for any against section
symbols from removed link-once sections. Set any such symbols from removed link-once sections. Zero any such
relocs to be against 0. We should really complain if relocs. We should really complain if anything in the
anything in the final link tries to use it, but final link tries to use it, but DWARF-based exception
DWARF-based exception handling might have an entry in handling might have an entry in .eh_frame to describe a
.eh_frame to describe a routine in the linkonce section, routine in the linkonce section, and it turns out to be
and it turns out to be hard to remove the .eh_frame entry hard to remove the .eh_frame entry too. FIXME. */
too. FIXME. */
rel = internal_relocs; rel = internal_relocs;
relend = rel + o->reloc_count * bed->s->int_rels_per_ext_rel; relend = rel + o->reloc_count * bed->s->int_rels_per_ext_rel;
for ( ; rel < relend; rel++) for ( ; rel < relend; rel++)
@ -6151,21 +6145,20 @@ elf_link_input_bfd (finfo, input_bfd)
&& (sec->flags & SEC_LINK_ONCE) != 0 && (sec->flags & SEC_LINK_ONCE) != 0
&& bfd_is_abs_section (sec->output_section)) && bfd_is_abs_section (sec->output_section))
{ {
rel->r_info = none_r_info;
#if BFD_VERSION_DATE > 20021005 #if BFD_VERSION_DATE > 20021005
(*finfo->info->callbacks->warning) (*finfo->info->callbacks->warning)
(finfo->info, (finfo->info,
_("warning: relocation against removed section; zeroing"), _("warning: relocation against removed section; zeroing"),
NULL, input_bfd, o, rel->r_offset); NULL, input_bfd, o, rel->r_offset);
#endif #endif
memset (rel, 0, sizeof (*rel));
} }
} }
} }
} }
} }
#else #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 #endif
/* Relocate the section by invoking a back end routine. /* Relocate the section by invoking a back end routine.