* elf32-cris.c (cris_elf_relocate_section) <case R_CRIS_16_GOTPLT,

R_CRIS_16_GOTPLT>: Also error if there's no PLT for a symbol
	not defined by the executable, or defined in a DSO.
	<eliding run-time relocation of .got>: Initialize GOT entry for a
	function symbol or ELF_LINK_HASH_NEEDS_PLT statically in an
	executable.
	(cris_elf_gc_sweep_hook): Improve fallthrough marking.
	(elf_cris_try_fold_plt_to_got): Improve head comment.  Do not fold
	a PLT reloc to GOT for an executable.
	(elf_cris_adjust_dynamic_symbol): Only fold a .got.plt entry with
	.got for a DSO and explain why.
	(elf_cris_discard_excess_program_dynamics): Also lose GOT-relocs
	and unreferenced symbols for which a PLT is defined.  Adjust
	dynamic-symbol pruning correspondingly, to make sure we don't lose
	a dynamic symbol also defined by a DSO.
This commit is contained in:
Hans-Peter Nilsson
2004-03-22 04:08:39 +00:00
parent 2d4b84b0f5
commit e4a2175c7d
2 changed files with 82 additions and 25 deletions

View File

@ -1,3 +1,21 @@
2004-03-22 Hans-Peter Nilsson <hp@axis.com>
* elf32-cris.c (cris_elf_relocate_section) <case R_CRIS_16_GOTPLT,
R_CRIS_16_GOTPLT>: Also error if there's no PLT for a symbol
not defined by the executable, or defined in a DSO.
<eliding run-time relocation of .got>: Initialize GOT entry for a
function symbol or ELF_LINK_HASH_NEEDS_PLT statically in an
executable.
(cris_elf_gc_sweep_hook): Improve fallthrough marking.
(elf_cris_try_fold_plt_to_got): Improve head comment. Do not fold
a PLT reloc to GOT for an executable.
(elf_cris_adjust_dynamic_symbol): Only fold a .got.plt entry with
.got for a DSO and explain why.
(elf_cris_discard_excess_program_dynamics): Also lose GOT-relocs
and unreferenced symbols for which a PLT is defined. Adjust
dynamic-symbol pruning correspondingly, to make sure we don't lose
a dynamic symbol also defined by a DSO.
2004-03-22 Alan Modra <amodra@bigpond.net.au> 2004-03-22 Alan Modra <amodra@bigpond.net.au>
* elf-bfd.h (RELOC_FOR_GLOBAL_SYMBOL): Add input_bfd, input_section * elf-bfd.h (RELOC_FOR_GLOBAL_SYMBOL): Add input_bfd, input_section

View File

@ -960,11 +960,25 @@ cris_elf_relocate_section (output_bfd, info, input_bfd, input_section,
statically linking PIC code, or when using -Bsymbolic. Check statically linking PIC code, or when using -Bsymbolic. Check
that we instead have a GOT entry as done for us by that we instead have a GOT entry as done for us by
elf_cris_adjust_dynamic_symbol, and drop through into the elf_cris_adjust_dynamic_symbol, and drop through into the
ordinary GOT cases. */ ordinary GOT cases. This must not happen for the
if (h != NULL && h->got.offset == (bfd_vma) -1) executable, because any reference it does to a function
that is satisfied by a DSO must generate a PLT. We assume
these call-specific relocs don't address non-functions. */
if (h != NULL
&& (h->got.offset == (bfd_vma) -1
|| (!info->shared
&& !((h->elf_link_hash_flags
& ELF_LINK_HASH_DEF_REGULAR) != 0
|| ((h->elf_link_hash_flags
& ELF_LINK_HASH_DEF_DYNAMIC) == 0
&& h->root.type == bfd_link_hash_undefweak)))))
{ {
(*_bfd_error_handler) (*_bfd_error_handler)
(_("%s: No PLT nor GOT for relocation %s against symbol `%s' from %s section"), ((h->got.offset == (bfd_vma) -1)
? _("%s: No PLT nor GOT for relocation %s against\
symbol `%s' from %s section")
: _("%s: No PLT for relocation %s against\
symbol `%s' from %s section"),
bfd_archive_filename (input_bfd), bfd_archive_filename (input_bfd),
cris_elf_howto_table[r_type].name, cris_elf_howto_table[r_type].name,
symname[0] != '\0' ? symname : _("[whose name is lost]"), symname[0] != '\0' ? symname : _("[whose name is lost]"),
@ -996,18 +1010,25 @@ cris_elf_relocate_section (output_bfd, info, input_bfd, input_section,
if (!elf_hash_table (info)->dynamic_sections_created if (!elf_hash_table (info)->dynamic_sections_created
|| (! info->shared || (! info->shared
&& (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)) && ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)
|| h->type == STT_FUNC
|| (h->elf_link_hash_flags
& ELF_LINK_HASH_NEEDS_PLT)))
|| (info->shared || (info->shared
&& (info->symbolic || h->dynindx == -1) && (info->symbolic || h->dynindx == -1)
&& (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR))) && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)))
{ {
/* This wasn't checked above for ! info->shared, but /* This wasn't checked above for ! info->shared, but
must hold there if we get here; the symbol must be must hold there if we get here; the symbol must
defined in the regular program, or be undefweak. */ be defined in the regular program or be undefweak
or be a function or otherwise need a PLT. */
BFD_ASSERT (!elf_hash_table (info)->dynamic_sections_created BFD_ASSERT (!elf_hash_table (info)->dynamic_sections_created
|| info->shared || info->shared
|| (h->elf_link_hash_flags || (h->elf_link_hash_flags
& ELF_LINK_HASH_DEF_REGULAR) != 0 & ELF_LINK_HASH_DEF_REGULAR) != 0
|| h->type == STT_FUNC
|| (h->elf_link_hash_flags
& ELF_LINK_HASH_NEEDS_PLT)
|| h->root.type == bfd_link_hash_undefweak); || h->root.type == bfd_link_hash_undefweak);
/* This is actually a static link, or it is a /* This is actually a static link, or it is a
@ -1511,12 +1532,15 @@ elf_cris_finish_dynamic_symbol (output_bfd, info, h, sym)
} }
} }
/* We don't emit .got relocs for symbols that aren't in the /* For an ordinary program, we emit .got relocs only for symbols that
dynamic-symbols table for an ordinary program and are either defined are in the dynamic-symbols table and are either defined by the
by the program or are undefined weak symbols. */ program or are undefined weak symbols, or are function symbols
where we do not output a PLT: the PLT reloc was output above and all
references to the function symbol are redirected to the PLT. */
if (h->got.offset != (bfd_vma) -1 if (h->got.offset != (bfd_vma) -1
&& (info->shared && (info->shared
|| (h->dynindx != -1 || (h->dynindx != -1
&& h->plt.offset == (bfd_vma) -1
&& (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0 && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0
&& h->root.type != bfd_link_hash_undefweak))) && h->root.type != bfd_link_hash_undefweak)))
{ {
@ -1838,13 +1862,12 @@ cris_elf_gc_sweep_hook (abfd, info, sec, relocs)
r_symndx = ELF32_R_SYM (rel->r_info); r_symndx = ELF32_R_SYM (rel->r_info);
if (r_symndx < symtab_hdr->sh_info) if (r_symndx < symtab_hdr->sh_info)
goto local_got_reloc; goto local_got_reloc;
/* Fall through. */
case R_CRIS_32_PLT_GOTREL: case R_CRIS_32_PLT_GOTREL:
/* FIXME: We don't garbage-collect away the .got section. */ /* FIXME: We don't garbage-collect away the .got section. */
if (local_got_refcounts != NULL) if (local_got_refcounts != NULL)
local_got_refcounts[-1]--; local_got_refcounts[-1]--;
/* Fall through. */ /* Fall through. */
case R_CRIS_8_PCREL: case R_CRIS_8_PCREL:
case R_CRIS_16_PCREL: case R_CRIS_16_PCREL:
case R_CRIS_32_PCREL: case R_CRIS_32_PCREL:
@ -1929,16 +1952,22 @@ elf_cris_adjust_gotplt_to_got (h, p)
want to do this: want to do this:
- When all PLT references are GOTPLT references, and there are GOT - When all PLT references are GOTPLT references, and there are GOT
references. We don't have to generate a PLT at all. references, and this is not the executable. We don't have to
generate a PLT at all.
- When there are both (ordinary) PLT references and GOT references. - When there are both (ordinary) PLT references and GOT references,
and this isn't the executable.
We want to make the PLT reference use the ordinary GOT entry rather We want to make the PLT reference use the ordinary GOT entry rather
than a run-time dynamically resolved GOTPLT entry (since the GOT than R_CRIS_JUMP_SLOT, a run-time dynamically resolved GOTPLT entry,
entry will have to be resolved at startup anyway). since the GOT entry will have to be resolved at startup anyway.
Though the latter case is handled when room for the PLT is allocated, Though the latter case is handled when room for the PLT is allocated,
not here. not here.
By folding into the GOT, we may need a round-trip to a PLT in the
executable for calls, a loss in performance. Still, losing a
reloc is a win in size and at least in start-up time.
Note that this function is called before symbols are forced local by Note that this function is called before symbols are forced local by
version scripts. The differing cases are handled by version scripts. The differing cases are handled by
elf_cris_hide_symbol. */ elf_cris_hide_symbol. */
@ -2045,9 +2074,13 @@ elf_cris_adjust_dynamic_symbol (info, h)
info); info);
} }
/* If there are only GOT references and GOTPLT references to this /* If we had a R_CRIS_GLOB_DAT that didn't have to point to a PLT;
PLT entry, get rid of the PLT. */ where a pointer-equivalent symbol was unimportant (i.e. more
if (! elf_cris_try_fold_plt_to_got ((struct elf_cris_link_hash_entry *) like R_CRIS_JUMP_SLOT after symbol evaluation) we could get rid
of the PLT. We can't for the executable, because the GOT
entries will point to the PLT there (and be constant). */
if (info->shared
&& !elf_cris_try_fold_plt_to_got ((struct elf_cris_link_hash_entry*)
h, info)) h, info))
return FALSE; return FALSE;
@ -2086,8 +2119,11 @@ elf_cris_adjust_dynamic_symbol (info, h)
/* If there's already a GOT entry, use that, not a .got.plt. A /* If there's already a GOT entry, use that, not a .got.plt. A
GOT field still has a reference count when we get here; it's GOT field still has a reference count when we get here; it's
not yet changed to an offset. */ not yet changed to an offset. We can't do this for an
if (h->got.refcount > 0) executable, because then the reloc associated with the PLT
would get a non-PLT reloc pointing to the PLT. FIXME: Move
this to elf_cris_try_fold_plt_to_got. */
if (info->shared && h->got.refcount > 0)
{ {
h->got.refcount += h->plt.refcount; h->got.refcount += h->plt.refcount;
@ -2860,9 +2896,11 @@ elf_cris_discard_excess_program_dynamics (h, inf)
/* If we're not creating a shared library and have a symbol which is /* If we're not creating a shared library and have a symbol which is
referred to by .got references, but the symbol is defined locally, referred to by .got references, but the symbol is defined locally,
(or rather, not not defined by a DSO) then lose the reloc for the (or rather, not defined by a DSO) then lose the reloc for the .got
.got (don't allocate room for it). */ (don't allocate room for it). Likewise for relocs for something
if ((h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) == 0) for which we create a PLT. */
if ((h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) == 0
|| h->root.plt.refcount > 0)
{ {
if (h->root.got.refcount > 0 if (h->root.got.refcount > 0
/* The size of this section is only valid and in sync with the /* The size of this section is only valid and in sync with the
@ -2888,7 +2926,8 @@ elf_cris_discard_excess_program_dynamics (h, inf)
introduce new problems. Of course we don't do this if we're introduce new problems. Of course we don't do this if we're
exporting all dynamic symbols. */ exporting all dynamic symbols. */
if (! info->export_dynamic if (! info->export_dynamic
&& (h->root.elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) == 0) && (h->root.elf_link_hash_flags
& (ELF_LINK_HASH_DEF_DYNAMIC|ELF_LINK_HASH_REF_DYNAMIC)) == 0)
{ {
h->root.dynindx = -1; h->root.dynindx = -1;
_bfd_elf_strtab_delref (elf_hash_table (info)->dynstr, _bfd_elf_strtab_delref (elf_hash_table (info)->dynstr,