mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-27 06:17:47 +08:00
bfd/
PR ld/11378 * elf64-ppc.h (ppc64_elf_check_init_fini): Declare. * elf64-ppc.c (call_check_done): Define. (ppc64_elf_add_symbol_hook): Substitute bfd_get_section_name macro. (ppc64_elf_check_relocs, ppc64_elf_size_dynamic_sections): Likewise. (ppc64_elf_finish_multitoc_partition): Remove unnecessary check. (toc_adjusting_stub_needed): Use call_check_done rather than toc_off. Simplify return logic. Iterate over all .init and .fini fragments by recursion. Set makes_toc_func_call here.. (ppc64_elf_next_input_section): ..rather than here. (check_pasted_section, ppc64_elf_check_init_fini): New functions. ld/ PR ld/11378 * emultempl/ppc64elf.em (gld${EMULATION_NAME}_after_allocation): Call ppc64_elf_check_init_fini and warn if .init/.fini use different TOCs.
This commit is contained in:
@ -1,3 +1,17 @@
|
|||||||
|
2010-03-14 Alan Modra <amodra@gmail.com>
|
||||||
|
|
||||||
|
PR ld/11378
|
||||||
|
* elf64-ppc.h (ppc64_elf_check_init_fini): Declare.
|
||||||
|
* elf64-ppc.c (call_check_done): Define.
|
||||||
|
(ppc64_elf_add_symbol_hook): Substitute bfd_get_section_name macro.
|
||||||
|
(ppc64_elf_check_relocs, ppc64_elf_size_dynamic_sections): Likewise.
|
||||||
|
(ppc64_elf_finish_multitoc_partition): Remove unnecessary check.
|
||||||
|
(toc_adjusting_stub_needed): Use call_check_done rather than toc_off.
|
||||||
|
Simplify return logic. Iterate over all .init and .fini fragments
|
||||||
|
by recursion. Set makes_toc_func_call here..
|
||||||
|
(ppc64_elf_next_input_section): ..rather than here.
|
||||||
|
(check_pasted_section, ppc64_elf_check_init_fini): New functions.
|
||||||
|
|
||||||
2010-03-13 Alan Modra <amodra@gmail.com>
|
2010-03-13 Alan Modra <amodra@gmail.com>
|
||||||
|
|
||||||
PR ld/11375
|
PR ld/11375
|
||||||
|
382
bfd/elf64-ppc.c
382
bfd/elf64-ppc.c
@ -3820,6 +3820,7 @@ struct ppc_link_hash_table
|
|||||||
|
|
||||||
/* Recursion protection when determining above flag. */
|
/* Recursion protection when determining above flag. */
|
||||||
#define call_check_in_progress sec_flg4
|
#define call_check_in_progress sec_flg4
|
||||||
|
#define call_check_done sec_flg5
|
||||||
|
|
||||||
/* Get the ppc64 ELF linker hash table from a link_info structure. */
|
/* Get the ppc64 ELF linker hash table from a link_info structure. */
|
||||||
|
|
||||||
@ -4573,7 +4574,7 @@ ppc64_elf_add_symbol_hook (bfd *ibfd,
|
|||||||
else if (ELF_ST_TYPE (isym->st_info) == STT_FUNC)
|
else if (ELF_ST_TYPE (isym->st_info) == STT_FUNC)
|
||||||
;
|
;
|
||||||
else if (*sec != NULL
|
else if (*sec != NULL
|
||||||
&& strcmp (bfd_get_section_name (ibfd, *sec), ".opd") == 0)
|
&& strcmp ((*sec)->name, ".opd") == 0)
|
||||||
isym->st_info = ELF_ST_INFO (ELF_ST_BIND (isym->st_info), STT_FUNC);
|
isym->st_info = ELF_ST_INFO (ELF_ST_BIND (isym->st_info), STT_FUNC);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@ -4880,7 +4881,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
|
|||||||
|
|
||||||
sreloc = NULL;
|
sreloc = NULL;
|
||||||
opd_sym_map = NULL;
|
opd_sym_map = NULL;
|
||||||
if (strcmp (bfd_get_section_name (abfd, sec), ".opd") == 0)
|
if (strcmp (sec->name, ".opd") == 0)
|
||||||
{
|
{
|
||||||
/* Garbage collection needs some extra help with .opd sections.
|
/* Garbage collection needs some extra help with .opd sections.
|
||||||
We don't want to necessarily keep everything referenced by
|
We don't want to necessarily keep everything referenced by
|
||||||
@ -8811,7 +8812,7 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
|
|||||||
/* Strip this section if we don't need it; see the
|
/* Strip this section if we don't need it; see the
|
||||||
comment below. */
|
comment below. */
|
||||||
}
|
}
|
||||||
else if (CONST_STRNEQ (bfd_get_section_name (dynobj, s), ".rela"))
|
else if (CONST_STRNEQ (s->name, ".rela"))
|
||||||
{
|
{
|
||||||
if (s->size != 0)
|
if (s->size != 0)
|
||||||
{
|
{
|
||||||
@ -10125,9 +10126,6 @@ ppc64_elf_finish_multitoc_partition (struct bfd_link_info *info)
|
|||||||
{
|
{
|
||||||
struct ppc_link_hash_table *htab = ppc_hash_table (info);
|
struct ppc_link_hash_table *htab = ppc_hash_table (info);
|
||||||
|
|
||||||
if (htab == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* After the second pass, toc_curr tracks the TOC offset used
|
/* After the second pass, toc_curr tracks the TOC offset used
|
||||||
for code sections below in ppc64_elf_next_input_section. */
|
for code sections below in ppc64_elf_next_input_section. */
|
||||||
htab->toc_curr = TOC_BASE_OFF;
|
htab->toc_curr = TOC_BASE_OFF;
|
||||||
@ -10144,10 +10142,10 @@ ppc64_elf_finish_multitoc_partition (struct bfd_link_info *info)
|
|||||||
static int
|
static int
|
||||||
toc_adjusting_stub_needed (struct bfd_link_info *info, asection *isec)
|
toc_adjusting_stub_needed (struct bfd_link_info *info, asection *isec)
|
||||||
{
|
{
|
||||||
Elf_Internal_Rela *relstart, *rel;
|
|
||||||
Elf_Internal_Sym *local_syms;
|
|
||||||
int ret;
|
int ret;
|
||||||
struct ppc_link_hash_table *htab;
|
|
||||||
|
/* Mark this section as checked. */
|
||||||
|
isec->call_check_done = 1;
|
||||||
|
|
||||||
/* We know none of our code bearing sections will need toc stubs. */
|
/* We know none of our code bearing sections will need toc stubs. */
|
||||||
if ((isec->flags & SEC_LINKER_CREATED) != 0)
|
if ((isec->flags & SEC_LINKER_CREATED) != 0)
|
||||||
@ -10159,179 +10157,189 @@ toc_adjusting_stub_needed (struct bfd_link_info *info, asection *isec)
|
|||||||
if (isec->output_section == NULL)
|
if (isec->output_section == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (isec->reloc_count == 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
relstart = _bfd_elf_link_read_relocs (isec->owner, isec, NULL, NULL,
|
|
||||||
info->keep_memory);
|
|
||||||
if (relstart == NULL)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
/* Look for branches to outside of this section. */
|
|
||||||
local_syms = NULL;
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
htab = ppc_hash_table (info);
|
if (isec->reloc_count != 0)
|
||||||
if (htab == NULL)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
for (rel = relstart; rel < relstart + isec->reloc_count; ++rel)
|
|
||||||
{
|
{
|
||||||
enum elf_ppc64_reloc_type r_type;
|
Elf_Internal_Rela *relstart, *rel;
|
||||||
unsigned long r_symndx;
|
Elf_Internal_Sym *local_syms;
|
||||||
struct elf_link_hash_entry *h;
|
struct ppc_link_hash_table *htab;
|
||||||
struct ppc_link_hash_entry *eh;
|
|
||||||
Elf_Internal_Sym *sym;
|
|
||||||
asection *sym_sec;
|
|
||||||
struct _opd_sec_data *opd;
|
|
||||||
bfd_vma sym_value;
|
|
||||||
bfd_vma dest;
|
|
||||||
|
|
||||||
r_type = ELF64_R_TYPE (rel->r_info);
|
relstart = _bfd_elf_link_read_relocs (isec->owner, isec, NULL, NULL,
|
||||||
if (r_type != R_PPC64_REL24
|
info->keep_memory);
|
||||||
&& r_type != R_PPC64_REL14
|
if (relstart == NULL)
|
||||||
&& r_type != R_PPC64_REL14_BRTAKEN
|
return -1;
|
||||||
&& r_type != R_PPC64_REL14_BRNTAKEN)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
r_symndx = ELF64_R_SYM (rel->r_info);
|
/* Look for branches to outside of this section. */
|
||||||
if (!get_sym_h (&h, &sym, &sym_sec, NULL, &local_syms, r_symndx,
|
local_syms = NULL;
|
||||||
isec->owner))
|
htab = ppc_hash_table (info);
|
||||||
|
if (htab == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
for (rel = relstart; rel < relstart + isec->reloc_count; ++rel)
|
||||||
{
|
{
|
||||||
ret = -1;
|
enum elf_ppc64_reloc_type r_type;
|
||||||
break;
|
unsigned long r_symndx;
|
||||||
}
|
struct elf_link_hash_entry *h;
|
||||||
|
struct ppc_link_hash_entry *eh;
|
||||||
|
Elf_Internal_Sym *sym;
|
||||||
|
asection *sym_sec;
|
||||||
|
struct _opd_sec_data *opd;
|
||||||
|
bfd_vma sym_value;
|
||||||
|
bfd_vma dest;
|
||||||
|
|
||||||
/* Calls to dynamic lib functions go through a plt call stub
|
r_type = ELF64_R_TYPE (rel->r_info);
|
||||||
that uses r2. */
|
if (r_type != R_PPC64_REL24
|
||||||
eh = (struct ppc_link_hash_entry *) h;
|
&& r_type != R_PPC64_REL14
|
||||||
if (eh != NULL
|
&& r_type != R_PPC64_REL14_BRTAKEN
|
||||||
&& (eh->elf.plt.plist != NULL
|
&& r_type != R_PPC64_REL14_BRNTAKEN)
|
||||||
|| (eh->oh != NULL
|
|
||||||
&& ppc_follow_link (eh->oh)->elf.plt.plist != NULL)))
|
|
||||||
{
|
|
||||||
ret = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sym_sec == NULL)
|
|
||||||
/* Ignore other undefined symbols. */
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* Assume branches to other sections not included in the link need
|
|
||||||
stubs too, to cover -R and absolute syms. */
|
|
||||||
if (sym_sec->output_section == NULL)
|
|
||||||
{
|
|
||||||
ret = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (h == NULL)
|
|
||||||
sym_value = sym->st_value;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (h->root.type != bfd_link_hash_defined
|
|
||||||
&& h->root.type != bfd_link_hash_defweak)
|
|
||||||
abort ();
|
|
||||||
sym_value = h->root.u.def.value;
|
|
||||||
}
|
|
||||||
sym_value += rel->r_addend;
|
|
||||||
|
|
||||||
/* If this branch reloc uses an opd sym, find the code section. */
|
|
||||||
opd = get_opd_info (sym_sec);
|
|
||||||
if (opd != NULL)
|
|
||||||
{
|
|
||||||
if (h == NULL && opd->adjust != NULL)
|
|
||||||
{
|
|
||||||
long adjust;
|
|
||||||
|
|
||||||
adjust = opd->adjust[sym->st_value / 8];
|
|
||||||
if (adjust == -1)
|
|
||||||
/* Assume deleted functions won't ever be called. */
|
|
||||||
continue;
|
|
||||||
sym_value += adjust;
|
|
||||||
}
|
|
||||||
|
|
||||||
dest = opd_entry_value (sym_sec, sym_value, &sym_sec, NULL);
|
|
||||||
if (dest == (bfd_vma) -1)
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
else
|
|
||||||
dest = (sym_value
|
|
||||||
+ sym_sec->output_offset
|
|
||||||
+ sym_sec->output_section->vma);
|
|
||||||
|
|
||||||
/* Ignore branch to self. */
|
r_symndx = ELF64_R_SYM (rel->r_info);
|
||||||
if (sym_sec == isec)
|
if (!get_sym_h (&h, &sym, &sym_sec, NULL, &local_syms, r_symndx,
|
||||||
continue;
|
isec->owner))
|
||||||
|
|
||||||
/* If the called function uses the toc, we need a stub. */
|
|
||||||
if (sym_sec->has_toc_reloc
|
|
||||||
|| sym_sec->makes_toc_func_call)
|
|
||||||
{
|
|
||||||
ret = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Assume any branch that needs a long branch stub might in fact
|
|
||||||
need a plt_branch stub. A plt_branch stub uses r2. */
|
|
||||||
else if (dest - (isec->output_offset
|
|
||||||
+ isec->output_section->vma
|
|
||||||
+ rel->r_offset) + (1 << 25) >= (2 << 25))
|
|
||||||
{
|
|
||||||
ret = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If calling back to a section in the process of being tested, we
|
|
||||||
can't say for sure that no toc adjusting stubs are needed, so
|
|
||||||
don't return zero. */
|
|
||||||
else if (sym_sec->call_check_in_progress)
|
|
||||||
ret = 2;
|
|
||||||
|
|
||||||
/* Branches to another section that itself doesn't have any TOC
|
|
||||||
references are OK. Recursively call ourselves to check. */
|
|
||||||
else if (sym_sec->id <= htab->top_id
|
|
||||||
&& htab->stub_group[sym_sec->id].toc_off == 0)
|
|
||||||
{
|
|
||||||
int recur;
|
|
||||||
|
|
||||||
/* Mark current section as indeterminate, so that other
|
|
||||||
sections that call back to current won't be marked as
|
|
||||||
known. */
|
|
||||||
isec->call_check_in_progress = 1;
|
|
||||||
recur = toc_adjusting_stub_needed (info, sym_sec);
|
|
||||||
isec->call_check_in_progress = 0;
|
|
||||||
|
|
||||||
if (recur < 0)
|
|
||||||
{
|
{
|
||||||
/* An error. Exit. */
|
|
||||||
ret = -1;
|
ret = -1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (recur <= 1)
|
|
||||||
|
/* Calls to dynamic lib functions go through a plt call stub
|
||||||
|
that uses r2. */
|
||||||
|
eh = (struct ppc_link_hash_entry *) h;
|
||||||
|
if (eh != NULL
|
||||||
|
&& (eh->elf.plt.plist != NULL
|
||||||
|
|| (eh->oh != NULL
|
||||||
|
&& ppc_follow_link (eh->oh)->elf.plt.plist != NULL)))
|
||||||
{
|
{
|
||||||
/* Known result. Mark as checked and set section flag. */
|
ret = 1;
|
||||||
htab->stub_group[sym_sec->id].toc_off = 1;
|
break;
|
||||||
if (recur != 0)
|
|
||||||
{
|
|
||||||
sym_sec->makes_toc_func_call = 1;
|
|
||||||
ret = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sym_sec == NULL)
|
||||||
|
/* Ignore other undefined symbols. */
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Assume branches to other sections not included in the
|
||||||
|
link need stubs too, to cover -R and absolute syms. */
|
||||||
|
if (sym_sec->output_section == NULL)
|
||||||
|
{
|
||||||
|
ret = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (h == NULL)
|
||||||
|
sym_value = sym->st_value;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Unknown result. Continue checking. */
|
if (h->root.type != bfd_link_hash_defined
|
||||||
ret = 2;
|
&& h->root.type != bfd_link_hash_defweak)
|
||||||
|
abort ();
|
||||||
|
sym_value = h->root.u.def.value;
|
||||||
}
|
}
|
||||||
|
sym_value += rel->r_addend;
|
||||||
|
|
||||||
|
/* If this branch reloc uses an opd sym, find the code section. */
|
||||||
|
opd = get_opd_info (sym_sec);
|
||||||
|
if (opd != NULL)
|
||||||
|
{
|
||||||
|
if (h == NULL && opd->adjust != NULL)
|
||||||
|
{
|
||||||
|
long adjust;
|
||||||
|
|
||||||
|
adjust = opd->adjust[sym->st_value / 8];
|
||||||
|
if (adjust == -1)
|
||||||
|
/* Assume deleted functions won't ever be called. */
|
||||||
|
continue;
|
||||||
|
sym_value += adjust;
|
||||||
|
}
|
||||||
|
|
||||||
|
dest = opd_entry_value (sym_sec, sym_value, &sym_sec, NULL);
|
||||||
|
if (dest == (bfd_vma) -1)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
dest = (sym_value
|
||||||
|
+ sym_sec->output_offset
|
||||||
|
+ sym_sec->output_section->vma);
|
||||||
|
|
||||||
|
/* Ignore branch to self. */
|
||||||
|
if (sym_sec == isec)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* If the called function uses the toc, we need a stub. */
|
||||||
|
if (sym_sec->has_toc_reloc
|
||||||
|
|| sym_sec->makes_toc_func_call)
|
||||||
|
{
|
||||||
|
ret = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Assume any branch that needs a long branch stub might in fact
|
||||||
|
need a plt_branch stub. A plt_branch stub uses r2. */
|
||||||
|
else if (dest - (isec->output_offset
|
||||||
|
+ isec->output_section->vma
|
||||||
|
+ rel->r_offset) + (1 << 25) >= (2 << 25))
|
||||||
|
{
|
||||||
|
ret = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If calling back to a section in the process of being
|
||||||
|
tested, we can't say for sure that no toc adjusting stubs
|
||||||
|
are needed, so don't return zero. */
|
||||||
|
else if (sym_sec->call_check_in_progress)
|
||||||
|
ret = 2;
|
||||||
|
|
||||||
|
/* Branches to another section that itself doesn't have any TOC
|
||||||
|
references are OK. Recursively call ourselves to check. */
|
||||||
|
else if (!sym_sec->call_check_done)
|
||||||
|
{
|
||||||
|
int recur;
|
||||||
|
|
||||||
|
/* Mark current section as indeterminate, so that other
|
||||||
|
sections that call back to current won't be marked as
|
||||||
|
known. */
|
||||||
|
isec->call_check_in_progress = 1;
|
||||||
|
recur = toc_adjusting_stub_needed (info, sym_sec);
|
||||||
|
isec->call_check_in_progress = 0;
|
||||||
|
|
||||||
|
if (recur != 0)
|
||||||
|
{
|
||||||
|
ret = recur;
|
||||||
|
if (recur != 2)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (local_syms != NULL
|
||||||
|
&& (elf_symtab_hdr (isec->owner).contents
|
||||||
|
!= (unsigned char *) local_syms))
|
||||||
|
free (local_syms);
|
||||||
|
if (elf_section_data (isec)->relocs != relstart)
|
||||||
|
free (relstart);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((ret & 1) == 0
|
||||||
|
&& isec->map_head.s != NULL
|
||||||
|
&& (strcmp (isec->output_section->name, ".init") == 0
|
||||||
|
|| strcmp (isec->output_section->name, ".fini") == 0))
|
||||||
|
{
|
||||||
|
if (isec->map_head.s->has_toc_reloc
|
||||||
|
|| isec->map_head.s->makes_toc_func_call)
|
||||||
|
ret = 1;
|
||||||
|
else if (!isec->map_head.s->call_check_done)
|
||||||
|
{
|
||||||
|
int recur;
|
||||||
|
isec->call_check_in_progress = 1;
|
||||||
|
recur = toc_adjusting_stub_needed (info, isec->map_head.s);
|
||||||
|
isec->call_check_in_progress = 0;
|
||||||
|
if (recur != 0)
|
||||||
|
ret = recur;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (local_syms != NULL
|
if (ret == 1)
|
||||||
&& (elf_symtab_hdr (isec->owner).contents != (unsigned char *) local_syms))
|
isec->makes_toc_func_call = 1;
|
||||||
free (local_syms);
|
|
||||||
if (elf_section_data (isec)->relocs != relstart)
|
|
||||||
free (relstart);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -10377,23 +10385,55 @@ ppc64_elf_next_input_section (struct bfd_link_info *info, asection *isec)
|
|||||||
if (elf_gp (isec->owner) != 0)
|
if (elf_gp (isec->owner) != 0)
|
||||||
htab->toc_curr = elf_gp (isec->owner);
|
htab->toc_curr = elf_gp (isec->owner);
|
||||||
}
|
}
|
||||||
else if (htab->stub_group[isec->id].toc_off == 0)
|
else if (!isec->call_check_done
|
||||||
{
|
&& toc_adjusting_stub_needed (info, isec) < 0)
|
||||||
int ret = toc_adjusting_stub_needed (info, isec);
|
return FALSE;
|
||||||
if (ret < 0)
|
|
||||||
return FALSE;
|
|
||||||
else
|
|
||||||
isec->makes_toc_func_call = ret & 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Functions that don't use the TOC can belong in any TOC group.
|
/* 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
|
Use the last TOC base. This happens to make _init and _fini
|
||||||
pasting work. */
|
pasting work, because the fragments generally don't use the TOC. */
|
||||||
htab->stub_group[isec->id].toc_off = htab->toc_curr;
|
htab->stub_group[isec->id].toc_off = htab->toc_curr;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Check that all .init and .fini sections use the same toc, if they
|
||||||
|
have toc relocs. */
|
||||||
|
|
||||||
|
static bfd_boolean
|
||||||
|
check_pasted_section (struct bfd_link_info *info, const char *name)
|
||||||
|
{
|
||||||
|
asection *o = bfd_get_section_by_name (info->output_bfd, name);
|
||||||
|
|
||||||
|
if (o != NULL)
|
||||||
|
{
|
||||||
|
struct ppc_link_hash_table *htab = ppc_hash_table (info);
|
||||||
|
bfd_vma toc_off = 0;
|
||||||
|
asection *i;
|
||||||
|
|
||||||
|
for (i = o->map_head.s; i != NULL; i = i->map_head.s)
|
||||||
|
if (i->has_toc_reloc)
|
||||||
|
{
|
||||||
|
if (toc_off == 0)
|
||||||
|
toc_off = htab->stub_group[i->id].toc_off;
|
||||||
|
else if (toc_off != htab->stub_group[i->id].toc_off)
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
/* Make sure the whole pasted function uses the same toc offset. */
|
||||||
|
if (toc_off != 0)
|
||||||
|
for (i = o->map_head.s; i != NULL; i = i->map_head.s)
|
||||||
|
htab->stub_group[i->id].toc_off = toc_off;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
bfd_boolean
|
||||||
|
ppc64_elf_check_init_fini (struct bfd_link_info *info)
|
||||||
|
{
|
||||||
|
return (check_pasted_section (info, ".init")
|
||||||
|
& check_pasted_section (info, ".fini"));
|
||||||
|
}
|
||||||
|
|
||||||
/* See whether we can group stub sections together. Grouping stub
|
/* See whether we can group stub sections together. Grouping stub
|
||||||
sections may result in fewer stubs. More importantly, we need to
|
sections may result in fewer stubs. More importantly, we need to
|
||||||
put all .init* and .fini* stubs at the beginning of the .init or
|
put all .init* and .fini* stubs at the beginning of the .init or
|
||||||
|
@ -42,6 +42,8 @@ bfd_boolean ppc64_elf_layout_multitoc
|
|||||||
(struct bfd_link_info *);
|
(struct bfd_link_info *);
|
||||||
void ppc64_elf_finish_multitoc_partition
|
void ppc64_elf_finish_multitoc_partition
|
||||||
(struct bfd_link_info *);
|
(struct bfd_link_info *);
|
||||||
|
bfd_boolean ppc64_elf_check_init_fini
|
||||||
|
(struct bfd_link_info *);
|
||||||
bfd_boolean ppc64_elf_next_input_section
|
bfd_boolean ppc64_elf_next_input_section
|
||||||
(struct bfd_link_info *, asection *);
|
(struct bfd_link_info *, asection *);
|
||||||
bfd_boolean ppc64_elf_size_stubs
|
bfd_boolean ppc64_elf_size_stubs
|
||||||
|
@ -1,3 +1,9 @@
|
|||||||
|
2010-03-14 Alan Modra <amodra@gmail.com>
|
||||||
|
|
||||||
|
PR ld/11378
|
||||||
|
* emultempl/ppc64elf.em (gld${EMULATION_NAME}_after_allocation): Call
|
||||||
|
ppc64_elf_check_init_fini and warn if .init/.fini use different TOCs.
|
||||||
|
|
||||||
2010-03-11 George Gensure <werkt0@gmail.com>
|
2010-03-11 George Gensure <werkt0@gmail.com>
|
||||||
|
|
||||||
PR ld/11367
|
PR ld/11367
|
||||||
|
@ -346,6 +346,9 @@ gld${EMULATION_NAME}_after_allocation (void)
|
|||||||
|
|
||||||
lang_for_each_statement (build_section_lists);
|
lang_for_each_statement (build_section_lists);
|
||||||
|
|
||||||
|
if (!ppc64_elf_check_init_fini (&link_info))
|
||||||
|
einfo ("%P: .init/.fini fragments use differing TOC pointers\n");
|
||||||
|
|
||||||
/* Call into the BFD backend to do the real work. */
|
/* Call into the BFD backend to do the real work. */
|
||||||
if (!ppc64_elf_size_stubs (&link_info, group_size))
|
if (!ppc64_elf_size_stubs (&link_info, group_size))
|
||||||
einfo ("%X%P: can not size stub section: %E\n");
|
einfo ("%X%P: can not size stub section: %E\n");
|
||||||
|
Reference in New Issue
Block a user