* elf64-ppc.c (bfd_elf64_mkobject): Define.
(struct ppc64_elf_obj_tdata): New. (ppc64_elf_tdata, ppc64_tlsld_got): Define. (ppc64_elf_mkobject): New function. (struct got_entry): Add "owner". Move "tls_type". (struct ppc_link_hash_table): Delete "relgot", "tlsld_got". (ppc64_elf_init_stub_bfd): New function. (create_got_section): Create header .got in dynobj. Create .got and .rela.got in each bfd. Stash pointers in ppc64_elf_obj_tdata. (ppc64_elf_create_dynamic_sections): Don't call create_got_section. Look for dynobj .got, and test it. (ppc64_elf_copy_indirect_symbol): Adjust for changed got. (update_local_sym_info): Likewise. (ppc64_elf_check_relocs): Likewise. (ppc64_elf_gc_sweep_hook): Likewise. (ppc64_elf_tls_optimize): Likewise. (allocate_dynrelocs): Likewise. (ppc64_elf_size_dynamic_sections): Likewise. (ppc64_elf_relocate_section): Likewise. (ppc64_elf_next_toc_section): Update comment. (toc_adjusting_stub_needed): Remove unneeded cast. (ppc64_elf_build_stubs): Check for stub sections in stub bfd by testing section flags. (ppc64_elf_build_stubs): Likewise. (ppc64_elf_size_stubs): Likewise. Remove stub_bfd param. (ppc64_elf_finish_dynamic_sections): Write out got sections. (func_desc_adjust): Copy over dynamic info for undef weaks. * elf64-ppc.h (ppc64_elf_init_stub_bfd): Declare. (ppc64_elf_size_stubs): Update prototype. * elflink.h (elf_link_sort_relocs): Use link_orders to find reldyn input sections rather than scanning dynobj.
This commit is contained in:
parent
149ebfb1de
commit
e717da7ead
4 changed files with 298 additions and 130 deletions
|
@ -1,3 +1,37 @@
|
|||
2003-07-10 Alan Modra <amodra@bigpond.net.au>
|
||||
|
||||
* elf64-ppc.c (bfd_elf64_mkobject): Define.
|
||||
(struct ppc64_elf_obj_tdata): New.
|
||||
(ppc64_elf_tdata, ppc64_tlsld_got): Define.
|
||||
(ppc64_elf_mkobject): New function.
|
||||
(struct got_entry): Add "owner". Move "tls_type".
|
||||
(struct ppc_link_hash_table): Delete "relgot", "tlsld_got".
|
||||
(ppc64_elf_init_stub_bfd): New function.
|
||||
(create_got_section): Create header .got in dynobj. Create .got
|
||||
and .rela.got in each bfd. Stash pointers in ppc64_elf_obj_tdata.
|
||||
(ppc64_elf_create_dynamic_sections): Don't call create_got_section.
|
||||
Look for dynobj .got, and test it.
|
||||
(ppc64_elf_copy_indirect_symbol): Adjust for changed got.
|
||||
(update_local_sym_info): Likewise.
|
||||
(ppc64_elf_check_relocs): Likewise.
|
||||
(ppc64_elf_gc_sweep_hook): Likewise.
|
||||
(ppc64_elf_tls_optimize): Likewise.
|
||||
(allocate_dynrelocs): Likewise.
|
||||
(ppc64_elf_size_dynamic_sections): Likewise.
|
||||
(ppc64_elf_relocate_section): Likewise.
|
||||
(ppc64_elf_next_toc_section): Update comment.
|
||||
(toc_adjusting_stub_needed): Remove unneeded cast.
|
||||
(ppc64_elf_build_stubs): Check for stub sections in stub bfd by
|
||||
testing section flags.
|
||||
(ppc64_elf_build_stubs): Likewise.
|
||||
(ppc64_elf_size_stubs): Likewise. Remove stub_bfd param.
|
||||
(ppc64_elf_finish_dynamic_sections): Write out got sections.
|
||||
(func_desc_adjust): Copy over dynamic info for undef weaks.
|
||||
* elf64-ppc.h (ppc64_elf_init_stub_bfd): Declare.
|
||||
(ppc64_elf_size_stubs): Update prototype.
|
||||
* elflink.h (elf_link_sort_relocs): Use link_orders to find reldyn
|
||||
input sections rather than scanning dynobj.
|
||||
|
||||
2003-07-09 Richard Sandiford <rsandifo@redhat.com>
|
||||
|
||||
* elfxx-mips.c (mips_elf_link_hash_entry): Remove min_dyn_reloc_index.
|
||||
|
|
361
bfd/elf64-ppc.c
361
bfd/elf64-ppc.c
|
@ -69,6 +69,7 @@ static bfd_reloc_status_type ppc64_elf_unhandled_reloc
|
|||
#define elf_backend_can_refcount 1
|
||||
#define elf_backend_rela_normal 1
|
||||
|
||||
#define bfd_elf64_mkobject ppc64_elf_mkobject
|
||||
#define bfd_elf64_bfd_reloc_type_lookup ppc64_elf_reloc_type_lookup
|
||||
#define bfd_elf64_bfd_merge_private_bfd_data ppc64_elf_merge_private_bfd_data
|
||||
#define bfd_elf64_new_section_hook ppc64_elf_new_section_hook
|
||||
|
@ -2316,6 +2317,40 @@ ppc64_elf_unhandled_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
|
|||
return bfd_reloc_dangerous;
|
||||
}
|
||||
|
||||
struct ppc64_elf_obj_tdata
|
||||
{
|
||||
struct elf_obj_tdata elf;
|
||||
|
||||
/* Shortcuts to dynamic linker sections. */
|
||||
asection *got;
|
||||
asection *relgot;
|
||||
|
||||
/* TLS local dynamic got entry handling. Suppose for multiple GOT
|
||||
sections means we potentially need one of these for each input bfd. */
|
||||
union {
|
||||
bfd_signed_vma refcount;
|
||||
bfd_vma offset;
|
||||
} tlsld_got;
|
||||
};
|
||||
|
||||
#define ppc64_elf_tdata(bfd) \
|
||||
((struct ppc64_elf_obj_tdata *) (bfd)->tdata.any)
|
||||
|
||||
#define ppc64_tlsld_got(bfd) \
|
||||
(&ppc64_elf_tdata (bfd)->tlsld_got)
|
||||
|
||||
/* Override the generic function because we store some extras. */
|
||||
|
||||
static bfd_boolean
|
||||
ppc64_elf_mkobject (bfd *abfd)
|
||||
{
|
||||
bfd_size_type amt = sizeof (struct ppc64_elf_obj_tdata);
|
||||
abfd->tdata.any = bfd_zalloc (abfd, amt);
|
||||
if (abfd->tdata.any == NULL)
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Fix bad default arch selected for a 64 bit input bfd when the
|
||||
default is 32 bit. */
|
||||
|
||||
|
@ -2497,16 +2532,24 @@ struct got_entry
|
|||
/* The symbol addend that we'll be placing in the GOT. */
|
||||
bfd_vma addend;
|
||||
|
||||
/* Unlike other ELF targets, we use separate GOT entries for the same
|
||||
symbol referenced from different input files. This is to support
|
||||
automatic multiple TOC/GOT sections, where the TOC base can vary
|
||||
from one input file to another.
|
||||
|
||||
Point to the BFD owning this GOT entry. */
|
||||
bfd *owner;
|
||||
|
||||
/* Zero for non-tls entries, or TLS_TLS and one of TLS_GD, TLS_LD,
|
||||
TLS_TPREL or TLS_DTPREL for tls entries. */
|
||||
char tls_type;
|
||||
|
||||
/* Reference count until size_dynamic_sections, GOT offset thereafter. */
|
||||
union
|
||||
{
|
||||
bfd_signed_vma refcount;
|
||||
bfd_vma offset;
|
||||
} got;
|
||||
|
||||
/* Zero for non-tls entries, or TLS_TLS and one of TLS_GD, TLS_LD,
|
||||
TLS_TPREL or TLS_DTPREL for tls entries. */
|
||||
char tls_type;
|
||||
};
|
||||
|
||||
/* The same for PLT. */
|
||||
|
@ -2719,7 +2762,6 @@ struct ppc_link_hash_table
|
|||
|
||||
/* Short-cuts to get to dynamic linker sections. */
|
||||
asection *got;
|
||||
asection *relgot;
|
||||
asection *plt;
|
||||
asection *relplt;
|
||||
asection *dynbss;
|
||||
|
@ -2735,12 +2777,6 @@ struct ppc_link_hash_table
|
|||
/* Shortcut to .__tls_get_addr. */
|
||||
struct elf_link_hash_entry *tls_get_addr;
|
||||
|
||||
/* TLS local dynamic got entry handling. */
|
||||
union {
|
||||
bfd_signed_vma refcount;
|
||||
bfd_vma offset;
|
||||
} tlsld_got;
|
||||
|
||||
/* Statistics. */
|
||||
unsigned long stub_count[ppc_stub_plt_call];
|
||||
|
||||
|
@ -2928,6 +2964,23 @@ ppc64_elf_link_hash_table_free (struct bfd_link_hash_table *hash)
|
|||
_bfd_generic_link_hash_table_free (hash);
|
||||
}
|
||||
|
||||
/* Satisfy the ELF linker by filling in some fields in our fake bfd. */
|
||||
|
||||
void
|
||||
ppc64_elf_init_stub_bfd (bfd *abfd, struct bfd_link_info *info)
|
||||
{
|
||||
struct ppc_link_hash_table *htab;
|
||||
|
||||
elf_elfheader (abfd)->e_ident[EI_CLASS] = ELFCLASS64;
|
||||
|
||||
/* Always hook our dynamic sections into the first bfd, which is the
|
||||
linker created stub bfd. This ensures that the GOT header is at
|
||||
the start of the output TOC section. */
|
||||
htab = ppc_hash_table (info);
|
||||
htab->stub_bfd = abfd;
|
||||
htab->elf.dynobj = abfd;
|
||||
}
|
||||
|
||||
/* Build a name for an entry in the stub hash table. */
|
||||
|
||||
static char *
|
||||
|
@ -3122,30 +3175,43 @@ create_linkage_sections (bfd *dynobj, struct bfd_link_info *info)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
/* Create .got and .rela.got sections in DYNOBJ, and set up
|
||||
shortcuts to them in our hash table. */
|
||||
/* Create .got and .rela.got sections in ABFD, and .got in dynobj if
|
||||
not already done. */
|
||||
|
||||
static bfd_boolean
|
||||
create_got_section (bfd *dynobj, struct bfd_link_info *info)
|
||||
create_got_section (bfd *abfd, struct bfd_link_info *info)
|
||||
{
|
||||
struct ppc_link_hash_table *htab;
|
||||
asection *got, *relgot;
|
||||
flagword flags;
|
||||
struct ppc_link_hash_table *htab = ppc_hash_table (info);
|
||||
|
||||
if (! _bfd_elf_create_got_section (dynobj, info))
|
||||
return FALSE;
|
||||
|
||||
htab = ppc_hash_table (info);
|
||||
htab->got = bfd_get_section_by_name (dynobj, ".got");
|
||||
if (!htab->got)
|
||||
abort ();
|
||||
{
|
||||
if (! _bfd_elf_create_got_section (htab->elf.dynobj, info))
|
||||
return FALSE;
|
||||
|
||||
htab->relgot = bfd_make_section (dynobj, ".rela.got");
|
||||
if (!htab->relgot
|
||||
|| ! bfd_set_section_flags (dynobj, htab->relgot,
|
||||
(SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS
|
||||
| SEC_IN_MEMORY | SEC_LINKER_CREATED
|
||||
| SEC_READONLY))
|
||||
|| ! bfd_set_section_alignment (dynobj, htab->relgot, 3))
|
||||
htab->got = bfd_get_section_by_name (htab->elf.dynobj, ".got");
|
||||
if (!htab->got)
|
||||
abort ();
|
||||
}
|
||||
|
||||
flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
|
||||
| SEC_LINKER_CREATED);
|
||||
|
||||
got = bfd_make_section (abfd, ".got");
|
||||
if (!got
|
||||
|| !bfd_set_section_flags (abfd, got, flags)
|
||||
|| !bfd_set_section_alignment (abfd, got, 3))
|
||||
return FALSE;
|
||||
|
||||
relgot = bfd_make_section (abfd, ".rela.got");
|
||||
if (!relgot
|
||||
|| ! bfd_set_section_flags (abfd, relgot, flags | SEC_READONLY)
|
||||
|| ! bfd_set_section_alignment (abfd, relgot, 3))
|
||||
return FALSE;
|
||||
|
||||
ppc64_elf_tdata (abfd)->got = got;
|
||||
ppc64_elf_tdata (abfd)->relgot = relgot;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -3156,20 +3222,19 @@ ppc64_elf_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info)
|
|||
{
|
||||
struct ppc_link_hash_table *htab;
|
||||
|
||||
htab = ppc_hash_table (info);
|
||||
if (!htab->got && !create_got_section (dynobj, info))
|
||||
return FALSE;
|
||||
|
||||
if (!_bfd_elf_create_dynamic_sections (dynobj, info))
|
||||
return FALSE;
|
||||
|
||||
htab = ppc_hash_table (info);
|
||||
if (!htab->got)
|
||||
htab->got = bfd_get_section_by_name (dynobj, ".got");
|
||||
htab->plt = bfd_get_section_by_name (dynobj, ".plt");
|
||||
htab->relplt = bfd_get_section_by_name (dynobj, ".rela.plt");
|
||||
htab->dynbss = bfd_get_section_by_name (dynobj, ".dynbss");
|
||||
if (!info->shared)
|
||||
htab->relbss = bfd_get_section_by_name (dynobj, ".rela.bss");
|
||||
|
||||
if (!htab->plt || !htab->relplt || !htab->dynbss
|
||||
if (!htab->got || !htab->plt || !htab->relplt || !htab->dynbss
|
||||
|| (!info->shared && !htab->relbss))
|
||||
abort ();
|
||||
|
||||
|
@ -3260,6 +3325,7 @@ ppc64_elf_copy_indirect_symbol (struct elf_backend_data *bed ATTRIBUTE_UNUSED,
|
|||
|
||||
for (dent = edir->elf.got.glist; dent != NULL; dent = dent->next)
|
||||
if (dent->addend == ent->addend
|
||||
&& dent->owner == ent->owner
|
||||
&& dent->tls_type == ent->tls_type)
|
||||
{
|
||||
dent->got.refcount += ent->got.refcount;
|
||||
|
@ -3360,7 +3426,9 @@ update_local_sym_info (bfd *abfd, Elf_Internal_Shdr *symtab_hdr,
|
|||
struct got_entry *ent;
|
||||
|
||||
for (ent = local_got_ents[r_symndx]; ent != NULL; ent = ent->next)
|
||||
if (ent->addend == r_addend && ent->tls_type == tls_type)
|
||||
if (ent->addend == r_addend
|
||||
&& ent->owner == abfd
|
||||
&& ent->tls_type == tls_type)
|
||||
break;
|
||||
if (ent == NULL)
|
||||
{
|
||||
|
@ -3370,6 +3438,7 @@ update_local_sym_info (bfd *abfd, Elf_Internal_Shdr *symtab_hdr,
|
|||
return FALSE;
|
||||
ent->next = local_got_ents[r_symndx];
|
||||
ent->addend = r_addend;
|
||||
ent->owner = abfd;
|
||||
ent->tls_type = tls_type;
|
||||
ent->got.refcount = 0;
|
||||
local_got_ents[r_symndx] = ent;
|
||||
|
@ -3460,8 +3529,6 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
|
|||
ppc64_elf_section_data (sec)->opd.func_sec = opd_sym_map;
|
||||
}
|
||||
|
||||
if (htab->elf.dynobj == NULL)
|
||||
htab->elf.dynobj = abfd;
|
||||
if (htab->sfpr == NULL
|
||||
&& !create_linkage_sections (htab->elf.dynobj, info))
|
||||
return FALSE;
|
||||
|
@ -3487,7 +3554,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
|
|||
case R_PPC64_GOT_TLSLD16_LO:
|
||||
case R_PPC64_GOT_TLSLD16_HI:
|
||||
case R_PPC64_GOT_TLSLD16_HA:
|
||||
htab->tlsld_got.refcount += 1;
|
||||
ppc64_tlsld_got (abfd)->refcount += 1;
|
||||
tls_type = TLS_TLS | TLS_LD;
|
||||
goto dogottls;
|
||||
|
||||
|
@ -3524,8 +3591,8 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
|
|||
case R_PPC64_GOT16_LO_DS:
|
||||
/* This symbol requires a global offset table entry. */
|
||||
sec->has_gp_reloc = 1;
|
||||
if (htab->got == NULL
|
||||
&& !create_got_section (htab->elf.dynobj, info))
|
||||
if (ppc64_elf_tdata (abfd)->got == NULL
|
||||
&& !create_got_section (abfd, info))
|
||||
return FALSE;
|
||||
|
||||
if (h != NULL)
|
||||
|
@ -3536,6 +3603,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
|
|||
eh = (struct ppc_link_hash_entry *) h;
|
||||
for (ent = eh->elf.got.glist; ent != NULL; ent = ent->next)
|
||||
if (ent->addend == rel->r_addend
|
||||
&& ent->owner == abfd
|
||||
&& ent->tls_type == tls_type)
|
||||
break;
|
||||
if (ent == NULL)
|
||||
|
@ -3546,6 +3614,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
|
|||
return FALSE;
|
||||
ent->next = eh->elf.got.glist;
|
||||
ent->addend = rel->r_addend;
|
||||
ent->owner = abfd;
|
||||
ent->tls_type = tls_type;
|
||||
ent->got.refcount = 0;
|
||||
eh->elf.got.glist = ent;
|
||||
|
@ -4054,7 +4123,7 @@ ppc64_elf_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info,
|
|||
case R_PPC64_GOT_TLSLD16_LO:
|
||||
case R_PPC64_GOT_TLSLD16_HI:
|
||||
case R_PPC64_GOT_TLSLD16_HA:
|
||||
htab->tlsld_got.refcount -= 1;
|
||||
ppc64_tlsld_got (abfd)->refcount -= 1;
|
||||
tls_type = TLS_TLS | TLS_LD;
|
||||
goto dogot;
|
||||
|
||||
|
@ -4096,6 +4165,7 @@ ppc64_elf_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info,
|
|||
|
||||
for (; ent != NULL; ent = ent->next)
|
||||
if (ent->addend == rel->r_addend
|
||||
&& ent->owner == abfd
|
||||
&& ent->tls_type == tls_type)
|
||||
break;
|
||||
if (ent == NULL)
|
||||
|
@ -4213,7 +4283,9 @@ func_desc_adjust (struct elf_link_hash_entry *h, void *inf)
|
|||
&& (fdh->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0
|
||||
&& (info->shared
|
||||
|| (fdh->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0
|
||||
|| (fdh->elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) != 0))
|
||||
|| (fdh->elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) != 0
|
||||
|| (fdh->root.type == bfd_link_hash_undefweak
|
||||
&& ELF_ST_VISIBILITY (fdh->other) == STV_DEFAULT)))
|
||||
{
|
||||
if (fdh->dynindx == -1)
|
||||
if (! bfd_elf64_link_record_dynamic_symbol (info, fdh))
|
||||
|
@ -5138,7 +5210,7 @@ ppc64_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
|
|||
/* These relocs should never be against a symbol
|
||||
defined in a shared lib. Leave them alone if
|
||||
that turns out to be the case. */
|
||||
htab->tlsld_got.refcount -= 1;
|
||||
ppc64_tlsld_got (ibfd)->refcount -= 1;
|
||||
if (!is_local)
|
||||
continue;
|
||||
|
||||
|
@ -5276,6 +5348,7 @@ ppc64_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
|
|||
|
||||
for (; ent != NULL; ent = ent->next)
|
||||
if (ent->addend == rel->r_addend
|
||||
&& ent->owner == ibfd
|
||||
&& ent->tls_type == tls_type)
|
||||
break;
|
||||
if (ent == NULL)
|
||||
|
@ -5431,7 +5504,8 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
|
|||
for (ent = h->got.glist; ent != NULL; ent = ent->next)
|
||||
if (ent->got.refcount > 0
|
||||
&& (ent->tls_type & TLS_TPREL) != 0
|
||||
&& ent->addend == gent->addend)
|
||||
&& ent->addend == gent->addend
|
||||
&& ent->owner == gent->owner)
|
||||
{
|
||||
gent->got.refcount = 0;
|
||||
break;
|
||||
|
@ -5460,11 +5534,11 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
|
|||
if ((gent->tls_type & TLS_LD) != 0
|
||||
&& !(h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC))
|
||||
{
|
||||
gent->got.offset = htab->tlsld_got.offset;
|
||||
gent->got.offset = ppc64_tlsld_got (gent->owner)->offset;
|
||||
continue;
|
||||
}
|
||||
|
||||
s = htab->got;
|
||||
s = ppc64_elf_tdata (gent->owner)->got;
|
||||
gent->got.offset = s->_raw_size;
|
||||
s->_raw_size
|
||||
+= (gent->tls_type & eh->tls_mask & (TLS_GD | TLS_LD)) ? 16 : 8;
|
||||
|
@ -5473,7 +5547,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
|
|||
|| WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h))
|
||||
&& (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
|
||||
|| h->root.type != bfd_link_hash_undefweak))
|
||||
htab->relgot->_raw_size
|
||||
ppc64_elf_tdata (gent->owner)->relgot->_raw_size
|
||||
+= (gent->tls_type & eh->tls_mask & TLS_GD
|
||||
? 2 * sizeof (Elf64_External_Rela)
|
||||
: sizeof (Elf64_External_Rela));
|
||||
|
@ -5618,16 +5692,6 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
|
|||
}
|
||||
}
|
||||
|
||||
if (htab->tlsld_got.refcount > 0)
|
||||
{
|
||||
htab->tlsld_got.offset = htab->got->_raw_size;
|
||||
htab->got->_raw_size += 16;
|
||||
if (info->shared)
|
||||
htab->relgot->_raw_size += sizeof (Elf64_External_Rela);
|
||||
}
|
||||
else
|
||||
htab->tlsld_got.offset = (bfd_vma) -1;
|
||||
|
||||
/* Set up .got offsets for local syms, and space for local dynamic
|
||||
relocs. */
|
||||
for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
|
||||
|
@ -5642,6 +5706,20 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
|
|||
if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour)
|
||||
continue;
|
||||
|
||||
if (ppc64_tlsld_got (ibfd)->refcount > 0)
|
||||
{
|
||||
s = ppc64_elf_tdata (ibfd)->got;
|
||||
ppc64_tlsld_got (ibfd)->offset = s->_raw_size;
|
||||
s->_raw_size += 16;
|
||||
if (info->shared)
|
||||
{
|
||||
srel = ppc64_elf_tdata (ibfd)->relgot;
|
||||
srel->_raw_size += sizeof (Elf64_External_Rela);
|
||||
}
|
||||
}
|
||||
else
|
||||
ppc64_tlsld_got (ibfd)->offset = (bfd_vma) -1;
|
||||
|
||||
for (s = ibfd->sections; s != NULL; s = s->next)
|
||||
{
|
||||
struct ppc_dyn_relocs *p;
|
||||
|
@ -5677,8 +5755,8 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
|
|||
locsymcount = symtab_hdr->sh_info;
|
||||
end_lgot_ents = lgot_ents + locsymcount;
|
||||
lgot_masks = (char *) end_lgot_ents;
|
||||
s = htab->got;
|
||||
srel = htab->relgot;
|
||||
s = ppc64_elf_tdata (ibfd)->got;
|
||||
srel = ppc64_elf_tdata (ibfd)->relgot;
|
||||
for (; lgot_ents < end_lgot_ents; ++lgot_ents, ++lgot_masks)
|
||||
{
|
||||
struct got_entry *ent;
|
||||
|
@ -5688,14 +5766,14 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
|
|||
{
|
||||
if ((ent->tls_type & *lgot_masks & TLS_LD) != 0)
|
||||
{
|
||||
if (htab->tlsld_got.offset == (bfd_vma) -1)
|
||||
if (ppc64_tlsld_got (ibfd)->offset == (bfd_vma) -1)
|
||||
{
|
||||
htab->tlsld_got.offset = s->_raw_size;
|
||||
ppc64_tlsld_got (ibfd)->offset = s->_raw_size;
|
||||
s->_raw_size += 16;
|
||||
if (info->shared)
|
||||
srel->_raw_size += sizeof (Elf64_External_Rela);
|
||||
}
|
||||
ent->got.offset = htab->tlsld_got.offset;
|
||||
ent->got.offset = ppc64_tlsld_got (ibfd)->offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -5738,16 +5816,8 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
|
|||
if (s == htab->brlt || s == htab->relbrlt)
|
||||
/* These haven't been allocated yet; don't strip. */
|
||||
continue;
|
||||
else if (s == htab->got)
|
||||
{
|
||||
/* Automatic multiple tocs aren't possible if we are using the
|
||||
GOT. The GOT is accessed via r2, so we can't adjust r2.
|
||||
FIXME: There's no reason why we couldn't lay out multiple
|
||||
GOTs too. */
|
||||
if (s->_raw_size > elf_backend_got_header_size)
|
||||
htab->no_multi_toc = 1;
|
||||
}
|
||||
else if (s == htab->plt
|
||||
else if (s == htab->got
|
||||
|| s == htab->plt
|
||||
|| s == htab->glink)
|
||||
{
|
||||
/* Strip this section if we don't need it; see the
|
||||
|
@ -5805,6 +5875,38 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
|
||||
{
|
||||
s = ppc64_elf_tdata (ibfd)->got;
|
||||
if (s != NULL && s != htab->got)
|
||||
{
|
||||
s->_cooked_size = 0;
|
||||
if (s->_raw_size == 0)
|
||||
_bfd_strip_section_from_output (info, s);
|
||||
else
|
||||
{
|
||||
s->contents = bfd_zalloc (ibfd, s->_raw_size);
|
||||
if (s->contents == NULL)
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
s = ppc64_elf_tdata (ibfd)->relgot;
|
||||
if (s != NULL)
|
||||
{
|
||||
s->_cooked_size = 0;
|
||||
if (s->_raw_size == 0)
|
||||
_bfd_strip_section_from_output (info, s);
|
||||
else
|
||||
{
|
||||
s->contents = bfd_zalloc (ibfd, s->_raw_size);
|
||||
if (s->contents == NULL)
|
||||
return FALSE;
|
||||
relocs = TRUE;
|
||||
s->reloc_count = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (htab->elf.dynamic_sections_created)
|
||||
{
|
||||
/* Add some entries to the .dynamic section. We fill in the
|
||||
|
@ -6323,10 +6425,10 @@ ppc64_elf_setup_section_lists (bfd *output_bfd, struct bfd_link_info *info)
|
|||
return 1;
|
||||
}
|
||||
|
||||
/* The linker repeatedly calls this function for each toc input
|
||||
section. Group input bfds such that the toc within a group
|
||||
is less than 64k in size. Will break with cute linker scripts
|
||||
that play games with dot in the output toc section. */
|
||||
/* The linker repeatedly calls this function for each TOC input section
|
||||
and linker generated GOT section. Group input bfds such that the toc
|
||||
within a group is less than 64k in size. Will break with cute linker
|
||||
scripts that play games with dot in the output toc section. */
|
||||
|
||||
void
|
||||
ppc64_elf_next_toc_section (struct bfd_link_info *info, asection *isec)
|
||||
|
@ -6389,7 +6491,7 @@ toc_adjusting_stub_needed (struct bfd_link_info *info, asection *isec)
|
|||
if (contents == NULL)
|
||||
return -1;
|
||||
if (! bfd_get_section_contents (isec->owner, isec, contents,
|
||||
(file_ptr) 0, isec->_raw_size))
|
||||
0, isec->_raw_size))
|
||||
{
|
||||
free (contents);
|
||||
return -1;
|
||||
|
@ -6555,7 +6657,6 @@ group_sections (struct ppc_link_hash_table *htab,
|
|||
|
||||
bfd_boolean
|
||||
ppc64_elf_size_stubs (bfd *output_bfd,
|
||||
bfd *stub_bfd,
|
||||
struct bfd_link_info *info,
|
||||
bfd_signed_vma group_size,
|
||||
asection *(*add_stub_section) (const char *, asection *),
|
||||
|
@ -6566,7 +6667,6 @@ ppc64_elf_size_stubs (bfd *output_bfd,
|
|||
struct ppc_link_hash_table *htab = ppc_hash_table (info);
|
||||
|
||||
/* Stash our params away. */
|
||||
htab->stub_bfd = stub_bfd;
|
||||
htab->add_stub_section = add_stub_section;
|
||||
htab->layout_sections_again = layout_sections_again;
|
||||
stubs_always_before_branch = group_size < 0;
|
||||
|
@ -6820,10 +6920,11 @@ ppc64_elf_size_stubs (bfd *output_bfd,
|
|||
for (stub_sec = htab->stub_bfd->sections;
|
||||
stub_sec != NULL;
|
||||
stub_sec = stub_sec->next)
|
||||
{
|
||||
stub_sec->_raw_size = 0;
|
||||
stub_sec->_cooked_size = 0;
|
||||
}
|
||||
if ((stub_sec->flags & SEC_LINKER_CREATED) == 0)
|
||||
{
|
||||
stub_sec->_raw_size = 0;
|
||||
stub_sec->_cooked_size = 0;
|
||||
}
|
||||
htab->brlt->_raw_size = 0;
|
||||
htab->brlt->_cooked_size = 0;
|
||||
|
||||
|
@ -6909,24 +7010,26 @@ ppc64_elf_build_stubs (bfd_boolean emit_stub_syms,
|
|||
struct ppc_link_hash_table *htab = ppc_hash_table (info);
|
||||
asection *stub_sec;
|
||||
bfd_byte *p;
|
||||
int stub_sec_count = 0;
|
||||
|
||||
htab->emit_stub_syms = emit_stub_syms;
|
||||
for (stub_sec = htab->stub_bfd->sections;
|
||||
stub_sec != NULL;
|
||||
stub_sec = stub_sec->next)
|
||||
{
|
||||
bfd_size_type size;
|
||||
if ((stub_sec->flags & SEC_LINKER_CREATED) == 0)
|
||||
{
|
||||
bfd_size_type size;
|
||||
|
||||
/* Allocate memory to hold the linker stubs. */
|
||||
size = stub_sec->_raw_size;
|
||||
if (size != 0)
|
||||
{
|
||||
stub_sec->contents = bfd_zalloc (htab->stub_bfd, size);
|
||||
if (stub_sec->contents == NULL)
|
||||
return FALSE;
|
||||
}
|
||||
stub_sec->_cooked_size = 0;
|
||||
}
|
||||
/* Allocate memory to hold the linker stubs. */
|
||||
size = stub_sec->_raw_size;
|
||||
if (size != 0)
|
||||
{
|
||||
stub_sec->contents = bfd_zalloc (htab->stub_bfd, size);
|
||||
if (stub_sec->contents == NULL)
|
||||
return FALSE;
|
||||
}
|
||||
stub_sec->_cooked_size = 0;
|
||||
}
|
||||
|
||||
if (htab->plt != NULL)
|
||||
{
|
||||
|
@ -7018,10 +7121,12 @@ ppc64_elf_build_stubs (bfd_boolean emit_stub_syms,
|
|||
for (stub_sec = htab->stub_bfd->sections;
|
||||
stub_sec != NULL;
|
||||
stub_sec = stub_sec->next)
|
||||
{
|
||||
if (stub_sec->_raw_size != stub_sec->_cooked_size)
|
||||
break;
|
||||
}
|
||||
if ((stub_sec->flags & SEC_LINKER_CREATED) == 0)
|
||||
{
|
||||
stub_sec_count += 1;
|
||||
if (stub_sec->_raw_size != stub_sec->_cooked_size)
|
||||
break;
|
||||
}
|
||||
|
||||
if (stub_sec != NULL
|
||||
|| htab->glink->_raw_size != htab->glink->_cooked_size)
|
||||
|
@ -7045,7 +7150,7 @@ ppc64_elf_build_stubs (bfd_boolean emit_stub_syms,
|
|||
" long branch %lu\n"
|
||||
" long toc adj %lu\n"
|
||||
" plt call %lu"),
|
||||
htab->stub_bfd->section_count,
|
||||
stub_sec_count,
|
||||
htab->stub_count[ppc_stub_long_branch - 1],
|
||||
htab->stub_count[ppc_stub_long_branch_r2off - 1],
|
||||
htab->stub_count[ppc_stub_plt_branch - 1],
|
||||
|
@ -7736,17 +7841,15 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
|||
{
|
||||
/* Relocation is to the entry for this symbol in the global
|
||||
offset table. */
|
||||
asection *got;
|
||||
bfd_vma *offp;
|
||||
bfd_vma off;
|
||||
unsigned long indx = 0;
|
||||
|
||||
if (htab->got == NULL)
|
||||
abort ();
|
||||
|
||||
if (tls_type == (TLS_TLS | TLS_LD)
|
||||
&& (h == NULL
|
||||
|| !(h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC)))
|
||||
offp = &htab->tlsld_got.offset;
|
||||
offp = &ppc64_tlsld_got (input_bfd)->offset;
|
||||
else
|
||||
{
|
||||
struct got_entry *ent;
|
||||
|
@ -7778,6 +7881,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
|||
|
||||
for (; ent != NULL; ent = ent->next)
|
||||
if (ent->addend == rel->r_addend
|
||||
&& ent->owner == input_bfd
|
||||
&& ent->tls_type == tls_type)
|
||||
break;
|
||||
if (ent == NULL)
|
||||
|
@ -7785,6 +7889,10 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
|||
offp = &ent->got.offset;
|
||||
}
|
||||
|
||||
got = ppc64_elf_tdata (input_bfd)->got;
|
||||
if (got == NULL)
|
||||
abort ();
|
||||
|
||||
/* The offset must always be a multiple of 8. We use the
|
||||
least significant bit to record whether we have already
|
||||
processed this entry. */
|
||||
|
@ -7796,14 +7904,16 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
|||
/* Generate relocs for the dynamic linker, except in
|
||||
the case of TLSLD where we'll use one entry per
|
||||
module. */
|
||||
asection *relgot = ppc64_elf_tdata (input_bfd)->relgot;
|
||||
|
||||
*offp = off | 1;
|
||||
if ((info->shared || indx != 0)
|
||||
&& (h == NULL
|
||||
|| ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
|
||||
|| h->root.type != bfd_link_hash_undefweak))
|
||||
{
|
||||
outrel.r_offset = (htab->got->output_section->vma
|
||||
+ htab->got->output_offset
|
||||
outrel.r_offset = (got->output_section->vma
|
||||
+ got->output_offset
|
||||
+ off);
|
||||
outrel.r_addend = rel->r_addend;
|
||||
if (tls_type & (TLS_LD | TLS_GD))
|
||||
|
@ -7812,8 +7922,8 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
|||
outrel.r_info = ELF64_R_INFO (indx, R_PPC64_DTPMOD64);
|
||||
if (tls_type == (TLS_TLS | TLS_GD))
|
||||
{
|
||||
loc = htab->relgot->contents;
|
||||
loc += (htab->relgot->reloc_count++
|
||||
loc = relgot->contents;
|
||||
loc += (relgot->reloc_count++
|
||||
* sizeof (Elf64_External_Rela));
|
||||
bfd_elf64_swap_reloca_out (output_bfd,
|
||||
&outrel, loc);
|
||||
|
@ -7833,7 +7943,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
|||
|
||||
/* Write the .got section contents for the sake
|
||||
of prelink. */
|
||||
loc = htab->got->contents + off;
|
||||
loc = got->contents + off;
|
||||
bfd_put_64 (output_bfd, outrel.r_addend + relocation,
|
||||
loc);
|
||||
}
|
||||
|
@ -7846,8 +7956,8 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
|||
if (tls_type & (TLS_GD | TLS_DTPREL | TLS_TPREL))
|
||||
outrel.r_addend -= htab->tls_sec->vma;
|
||||
}
|
||||
loc = htab->relgot->contents;
|
||||
loc += (htab->relgot->reloc_count++
|
||||
loc = relgot->contents;
|
||||
loc += (relgot->reloc_count++
|
||||
* sizeof (Elf64_External_Rela));
|
||||
bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc);
|
||||
}
|
||||
|
@ -7868,23 +7978,23 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
|||
if (tls_type == (TLS_TLS | TLS_GD))
|
||||
{
|
||||
bfd_put_64 (output_bfd, relocation,
|
||||
htab->got->contents + off + 8);
|
||||
got->contents + off + 8);
|
||||
relocation = 1;
|
||||
}
|
||||
}
|
||||
|
||||
bfd_put_64 (output_bfd, relocation,
|
||||
htab->got->contents + off);
|
||||
got->contents + off);
|
||||
}
|
||||
}
|
||||
|
||||
if (off >= (bfd_vma) -2)
|
||||
abort ();
|
||||
|
||||
relocation = htab->got->output_offset + off;
|
||||
relocation = got->output_offset + off;
|
||||
|
||||
/* TOC base (r2) is TOC start plus 0x8000. */
|
||||
addend = - TOC_BASE_OFF;
|
||||
addend = -TOC_BASE_OFF;
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -8626,6 +8736,29 @@ ppc64_elf_finish_dynamic_sections (bfd *output_bfd,
|
|||
= PLT_ENTRY_SIZE;
|
||||
}
|
||||
|
||||
/* We need to handle writing out multiple GOT sections ourselves,
|
||||
since we didn't add them to DYNOBJ. */
|
||||
while ((dynobj = dynobj->link_next) != NULL)
|
||||
{
|
||||
asection *s;
|
||||
s = ppc64_elf_tdata (dynobj)->got;
|
||||
if (s != NULL
|
||||
&& s->_raw_size != 0
|
||||
&& s->output_section != bfd_abs_section_ptr
|
||||
&& !bfd_set_section_contents (output_bfd, s->output_section,
|
||||
s->contents, s->output_offset,
|
||||
s->_raw_size))
|
||||
return FALSE;
|
||||
s = ppc64_elf_tdata (dynobj)->relgot;
|
||||
if (s != NULL
|
||||
&& s->_raw_size != 0
|
||||
&& s->output_section != bfd_abs_section_ptr
|
||||
&& !bfd_set_section_contents (output_bfd, s->output_section,
|
||||
s->contents, s->output_offset,
|
||||
s->_raw_size))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,8 @@ You should have received a copy of the GNU General Public License
|
|||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
void ppc64_elf_init_stub_bfd
|
||||
(bfd *, struct bfd_link_info *);
|
||||
bfd_boolean ppc64_elf_mark_entry_syms
|
||||
(struct bfd_link_info *);
|
||||
bfd_boolean ppc64_elf_edit_opd
|
||||
|
@ -36,7 +38,7 @@ void ppc64_elf_reinit_toc
|
|||
bfd_boolean ppc64_elf_next_input_section
|
||||
(struct bfd_link_info *, asection *);
|
||||
bfd_boolean ppc64_elf_size_stubs
|
||||
(bfd *, bfd *, struct bfd_link_info *, bfd_signed_vma,
|
||||
(bfd *, struct bfd_link_info *, bfd_signed_vma,
|
||||
asection *(*) (const char *, asection *), void (*) (void));
|
||||
bfd_boolean ppc64_elf_build_stubs
|
||||
(bfd_boolean, struct bfd_link_info *, char **);
|
||||
|
|
|
@ -3029,8 +3029,7 @@ elf_link_sort_relocs (abfd, info, psec)
|
|||
struct bfd_link_info *info;
|
||||
asection **psec;
|
||||
{
|
||||
bfd *dynobj = elf_hash_table (info)->dynobj;
|
||||
asection *reldyn, *o;
|
||||
asection *reldyn;
|
||||
bfd_size_type count, size;
|
||||
size_t i, ret, sort_elt, ext_size;
|
||||
bfd_byte *sort, *s_non_relative, *p;
|
||||
|
@ -3039,6 +3038,7 @@ elf_link_sort_relocs (abfd, info, psec)
|
|||
int i2e = bed->s->int_rels_per_ext_rel;
|
||||
void (*swap_in) PARAMS ((bfd *, const bfd_byte *, Elf_Internal_Rela *));
|
||||
void (*swap_out) PARAMS ((bfd *, const Elf_Internal_Rela *, bfd_byte *));
|
||||
struct bfd_link_order *lo;
|
||||
|
||||
reldyn = bfd_get_section_by_name (abfd, ".rela.dyn");
|
||||
if (reldyn == NULL || reldyn->_raw_size == 0)
|
||||
|
@ -3059,11 +3059,12 @@ elf_link_sort_relocs (abfd, info, psec)
|
|||
count = reldyn->_raw_size / ext_size;
|
||||
|
||||
size = 0;
|
||||
for (o = dynobj->sections; o != NULL; o = o->next)
|
||||
if ((o->flags & (SEC_HAS_CONTENTS|SEC_LINKER_CREATED))
|
||||
== (SEC_HAS_CONTENTS|SEC_LINKER_CREATED)
|
||||
&& o->output_section == reldyn)
|
||||
size += o->_raw_size;
|
||||
for (lo = reldyn->link_order_head; lo != NULL; lo = lo->next)
|
||||
if (lo->type == bfd_indirect_link_order)
|
||||
{
|
||||
asection *o = lo->u.indirect.section;
|
||||
size += o->_raw_size;
|
||||
}
|
||||
|
||||
if (size != reldyn->_raw_size)
|
||||
return 0;
|
||||
|
@ -3079,12 +3080,11 @@ elf_link_sort_relocs (abfd, info, psec)
|
|||
return 0;
|
||||
}
|
||||
|
||||
for (o = dynobj->sections; o != NULL; o = o->next)
|
||||
if ((o->flags & (SEC_HAS_CONTENTS|SEC_LINKER_CREATED))
|
||||
== (SEC_HAS_CONTENTS|SEC_LINKER_CREATED)
|
||||
&& o->output_section == reldyn)
|
||||
for (lo = reldyn->link_order_head; lo != NULL; lo = lo->next)
|
||||
if (lo->type == bfd_indirect_link_order)
|
||||
{
|
||||
bfd_byte *erel, *erelend;
|
||||
asection *o = lo->u.indirect.section;
|
||||
|
||||
erel = o->contents;
|
||||
erelend = o->contents + o->_raw_size;
|
||||
|
@ -3121,12 +3121,11 @@ elf_link_sort_relocs (abfd, info, psec)
|
|||
|
||||
qsort (s_non_relative, (size_t) count - ret, sort_elt, elf_link_sort_cmp2);
|
||||
|
||||
for (o = dynobj->sections; o != NULL; o = o->next)
|
||||
if ((o->flags & (SEC_HAS_CONTENTS|SEC_LINKER_CREATED))
|
||||
== (SEC_HAS_CONTENTS|SEC_LINKER_CREATED)
|
||||
&& o->output_section == reldyn)
|
||||
for (lo = reldyn->link_order_head; lo != NULL; lo = lo->next)
|
||||
if (lo->type == bfd_indirect_link_order)
|
||||
{
|
||||
bfd_byte *erel, *erelend;
|
||||
asection *o = lo->u.indirect.section;
|
||||
|
||||
erel = o->contents;
|
||||
erelend = o->contents + o->_raw_size;
|
||||
|
|
Loading…
Reference in a new issue