* elf64-ppc.c (toc_adjusting_stub_needed): New function.

(ppc64_elf_next_input_section): Use it here to set has_gp_reloc.
	Return error condition.
	(ppc64_elf_size_stubs): Restrict toc adjusting stubs to sections
	that have has_gp_reloc set.
	(struct ppc_link_hash_table): Add stub_count.
	(ppc_build_one_stub): Increment it.
	(ppc64_elf_link_hash_table_create): zmalloc rather than clearing
	individual fields.
	* elf64-ppc.h (ppc64_elf_next_input_section): Update prototype.
This commit is contained in:
Alan Modra 2003-06-19 11:49:02 +00:00
parent 2c58cc864d
commit 9b5ecbd0c6
3 changed files with 134 additions and 83 deletions

View File

@ -1,3 +1,16 @@
2003-06-19 Alan Modra <amodra@bigpond.net.au>
* elf64-ppc.c (toc_adjusting_stub_needed): New function.
(ppc64_elf_next_input_section): Use it here to set has_gp_reloc.
Return error condition.
(ppc64_elf_size_stubs): Restrict toc adjusting stubs to sections
that have has_gp_reloc set.
(struct ppc_link_hash_table): Add stub_count.
(ppc_build_one_stub): Increment it.
(ppc64_elf_link_hash_table_create): zmalloc rather than clearing
individual fields.
* elf64-ppc.h (ppc64_elf_next_input_section): Update prototype.
2003-06-18 Alan Modra <amodra@bigpond.net.au>
* elflink.h (elf_gc_record_vtentry): Revert last change. Correct
@ -419,7 +432,7 @@
for X_STORMY16_REL_12 reloc.
* elf.c (bfd_elf_get_needed_list): Use is_elf_hash_table to check
the type of the has table in the bfd_link_info structure.
the type of the hash table in the bfd_link_info structure.
(bfd_elf_get_runpath_list): Likewise.
2003-05-19 Roland McGrath <roland@redhat.com>
@ -2158,9 +2171,7 @@
2003-01-23 Nick Clifton <nickc@redhat.com>
* Add sh2e support:
2002-04-02 Elena Zannoni <ezannoni@redhat.com>
* archures.c (bfd_mach_sh2e): Added.
* bfd-in2.h: Rebuilt.
* cpu-sh.c (arch_info_struct): Added SH2e.

View File

@ -2803,6 +2803,9 @@ struct ppc_link_hash_table
bfd_vma offset;
} tlsld_got;
/* Statistics. */
unsigned long stub_count[ppc_stub_plt_call];
/* Set if we should emit symbols for stubs. */
unsigned int emit_stub_syms;
@ -2893,6 +2896,8 @@ static bfd_boolean ppc_build_one_stub
PARAMS ((struct bfd_hash_entry *, PTR));
static bfd_boolean ppc_size_one_stub
PARAMS ((struct bfd_hash_entry *, PTR));
static int toc_adjusting_stub_needed
PARAMS ((struct bfd_link_info *, asection *));
static void group_sections
PARAMS ((struct ppc_link_hash_table *, bfd_size_type, bfd_boolean));
static bfd_boolean ppc64_elf_relocate_section
@ -3031,7 +3036,7 @@ ppc64_elf_link_hash_table_create (abfd)
struct ppc_link_hash_table *htab;
bfd_size_type amt = sizeof (struct ppc_link_hash_table);
htab = (struct ppc_link_hash_table *) bfd_malloc (amt);
htab = (struct ppc_link_hash_table *) bfd_zmalloc (amt);
if (htab == NULL)
return NULL;
@ -3049,41 +3054,6 @@ ppc64_elf_link_hash_table_create (abfd)
if (!bfd_hash_table_init (&htab->branch_hash_table, branch_hash_newfunc))
return NULL;
htab->stub_bfd = NULL;
htab->add_stub_section = NULL;
htab->layout_sections_again = NULL;
htab->stub_group = NULL;
htab->no_multi_toc = 0;
htab->multi_toc_needed = 0;
htab->toc_curr = 0;
htab->sgot = NULL;
htab->srelgot = NULL;
htab->splt = NULL;
htab->srelplt = NULL;
htab->sdynbss = NULL;
htab->srelbss = NULL;
htab->sglink = NULL;
htab->sfpr = NULL;
htab->sbrlt = NULL;
htab->srelbrlt = NULL;
htab->tls_sec = NULL;
htab->tls_get_addr = NULL;
htab->tlsld_got.refcount = 0;
htab->emit_stub_syms = 0;
htab->stub_error = 0;
htab->has_14bit_branch = 0;
htab->have_undefweak = 0;
htab->stub_iteration = 0;
htab->sym_sec.abfd = NULL;
/* Initializing two fields of the union is just cosmetic. We really
only care about glist, but when compiled on a 32-bit host the
bfd_vma fields are larger. Setting the bfd_vma to zero makes
debugger inspection of these fields look nicer. */
htab->elf.init_refcount.refcount = 0;
htab->elf.init_refcount.glist = NULL;
htab->elf.init_offset.offset = 0;
htab->elf.init_offset.glist = NULL;
return &htab->elf.root;
}
@ -6221,6 +6191,7 @@ ppc_build_one_stub (gen_entry, in_arg)
stub_bfd = stub_sec->owner;
htab->stub_count[(int) stub_entry->stub_type - 1] += 1;
switch (stub_entry->stub_type)
{
case ppc_stub_long_branch:
@ -6598,17 +6569,77 @@ ppc64_elf_reinit_toc (output_bfd, info)
htab->toc_curr = TOC_BASE_OFF;
}
/* No toc references were found in ISEC. If the code in ISEC makes no
calls, then there's no need to use toc adjusting stubs when branching
into ISEC. Actually, indirect calls from ISEC are OK as they will
load r2. */
static int
toc_adjusting_stub_needed (info, isec)
struct bfd_link_info *info;
asection *isec;
{
bfd_byte *contents;
bfd_size_type i;
int ret;
int branch_ok;
/* Hack for linux kernel. .fixup contains branches, but only back to
the function that hit an exception. */
branch_ok = strcmp (isec->name, ".fixup") == 0;
contents = elf_section_data (isec)->this_hdr.contents;
if (contents == NULL)
{
contents = bfd_malloc (isec->_raw_size);
if (contents == NULL)
return -1;
if (! bfd_get_section_contents (isec->owner, isec, contents,
(file_ptr) 0, isec->_raw_size))
{
free (contents);
return -1;
}
if (info->keep_memory)
elf_section_data (isec)->this_hdr.contents = contents;
}
/* Code scan, because we don't necessarily have relocs on calls to
static functions. */
ret = 0;
for (i = 0; i < isec->_raw_size; i += 4)
{
unsigned long insn = bfd_get_32 (isec->owner, contents + i);
/* Is this a branch? */
if ((insn & (0x1f << 26)) == (18 << 26)
/* If branch and link, it's a function call. */
&& ((insn & 1) != 0
/* Sibling calls use a plain branch. I don't know a way
of deciding whether a branch is really a sibling call. */
|| !branch_ok))
{
ret = 1;
break;
}
}
if (elf_section_data (isec)->this_hdr.contents != contents)
free (contents);
return ret;
}
/* The linker repeatedly calls this function for each input section,
in the order that input sections are linked into output sections.
Build lists of input sections to determine groupings between which
we may insert linker stubs. */
void
bfd_boolean
ppc64_elf_next_input_section (info, isec)
struct bfd_link_info *info;
asection *isec;
{
struct ppc_link_hash_table *htab = ppc_hash_table (info);
int ret;
if ((isec->output_section->flags & SEC_CODE) != 0
&& isec->output_section->index <= htab->top_index)
@ -6626,13 +6657,20 @@ ppc64_elf_next_input_section (info, isec)
to use the right TOC (obviously). Also, make sure that .opd gets
the correct TOC value. */
if (isec->has_gp_reloc || (isec->flags & SEC_CODE) == 0)
{
if (elf_gp (isec->owner) != 0)
htab->toc_curr = elf_gp (isec->owner);
}
else if ((ret = toc_adjusting_stub_needed (info, isec)) < 0)
return FALSE;
else
isec->has_gp_reloc = ret;
/* Functions that don't use the TOC can belong in any TOC group.
Use the last TOC base. This happens to make _init and _fini
pasting work. */
htab->stub_group[isec->id].toc_off = htab->toc_curr;
return TRUE;
}
/* See whether we can group stub sections together. Grouping stub
@ -6904,7 +6942,9 @@ ppc64_elf_size_stubs (output_bfd, stub_bfd, info, group_size,
if (sym_sec != NULL
&& sym_sec->output_section != NULL
&& (htab->stub_group[sym_sec->id].toc_off
!= htab->stub_group[section->id].toc_off))
!= htab->stub_group[section->id].toc_off)
&& sym_sec->has_gp_reloc
&& section->has_gp_reloc)
stub_type = ppc_stub_long_branch_r2off;
}

View File

@ -33,7 +33,7 @@ void ppc64_elf_next_toc_section
PARAMS ((struct bfd_link_info *, asection *));
void ppc64_elf_reinit_toc
PARAMS ((bfd *, struct bfd_link_info *));
void ppc64_elf_next_input_section
bfd_boolean ppc64_elf_next_input_section
PARAMS ((struct bfd_link_info *, asection *));
bfd_boolean ppc64_elf_size_stubs
PARAMS ((bfd *, bfd *, struct bfd_link_info *, bfd_signed_vma,