powerpc TLS in PIEs
This patch removes unnecessary GOT IE TLS relocations in PIEs. Useful with --no-tls-optimize, or with an enormous TLS segment. With the default --tls-optimize in effect IE code sequences will be edited to LE under the same circumstances we can remove the GOT reloc. * elf32-ppc.c (got_entries_needed, got_relocs_needed): New functions. (allocate_dynrelocs, ppc_elf_size_dynamic_sections): Use them here. (ppc_elf_relocate_section): Don't output a dynamic relocation for IE GOT entries in an executable. * elf64-ppc.c (allocate_got): Trim unnecessary TPREL relocs. (ppc64_elf_size_dynamic_sections): Likewise. (ppc64_elf_relocate_section): Likewise.
This commit is contained in:
parent
98bbb1b861
commit
f15d0b545b
3 changed files with 91 additions and 45 deletions
|
@ -1,3 +1,13 @@
|
|||
2017-11-04 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* elf32-ppc.c (got_entries_needed, got_relocs_needed): New functions.
|
||||
(allocate_dynrelocs, ppc_elf_size_dynamic_sections): Use them here.
|
||||
(ppc_elf_relocate_section): Don't output a dynamic relocation
|
||||
for IE GOT entries in an executable.
|
||||
* elf64-ppc.c (allocate_got): Trim unnecessary TPREL relocs.
|
||||
(ppc64_elf_size_dynamic_sections): Likewise.
|
||||
(ppc64_elf_relocate_section): Likewise.
|
||||
|
||||
2017-11-04 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* elf32-ppc.c (readonly_dynrelocs): Delete info param. Update all
|
||||
|
|
112
bfd/elf32-ppc.c
112
bfd/elf32-ppc.c
|
@ -5751,6 +5751,45 @@ allocate_got (struct ppc_elf_link_hash_table *htab, unsigned int need)
|
|||
return where;
|
||||
}
|
||||
|
||||
/* Calculate size of GOT entries for symbol given its TLS_MASK.
|
||||
TLS_LD is excluded because those go in a special GOT slot. */
|
||||
|
||||
static inline unsigned int
|
||||
got_entries_needed (int tls_mask)
|
||||
{
|
||||
unsigned int need;
|
||||
if ((tls_mask & TLS_TLS) == 0)
|
||||
need = 4;
|
||||
else
|
||||
{
|
||||
need = 0;
|
||||
if ((tls_mask & TLS_GD) != 0)
|
||||
need += 8;
|
||||
if ((tls_mask & (TLS_TPREL | TLS_TPRELGD)) != 0)
|
||||
need += 4;
|
||||
if ((tls_mask & TLS_DTPREL) != 0)
|
||||
need += 4;
|
||||
}
|
||||
return need;
|
||||
}
|
||||
|
||||
/* Calculate size of relocs needed for symbol given its TLS_MASK and
|
||||
NEEDed GOT entries. KNOWN says a TPREL offset can be calculated at
|
||||
link time. */
|
||||
|
||||
static inline unsigned int
|
||||
got_relocs_needed (int tls_mask, unsigned int need, bfd_boolean known)
|
||||
{
|
||||
/* All the entries we allocated need relocs.
|
||||
Except IE in executable with a local symbol. We could also omit
|
||||
the DTPREL reloc on the second word of a GD entry under the same
|
||||
condition as that for IE, but ld.so needs to differentiate
|
||||
LD and GD entries. */
|
||||
if ((tls_mask & (TLS_TPREL | TLS_TPRELGD)) != 0 && known)
|
||||
need -= 4;
|
||||
return need * sizeof (Elf32_External_Rela) / 4;
|
||||
}
|
||||
|
||||
/* If H is undefined, make it dynamic if that makes sense. */
|
||||
|
||||
static bfd_boolean
|
||||
|
@ -5801,27 +5840,17 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
|
|||
return FALSE;
|
||||
|
||||
need = 0;
|
||||
if ((eh->tls_mask & TLS_TLS) != 0)
|
||||
if ((eh->tls_mask & TLS_LD) != 0)
|
||||
{
|
||||
if ((eh->tls_mask & TLS_LD) != 0)
|
||||
{
|
||||
if (!eh->elf.def_dynamic)
|
||||
/* We'll just use htab->tlsld_got.offset. This should
|
||||
always be the case. It's a little odd if we have
|
||||
a local dynamic reloc against a non-local symbol. */
|
||||
htab->tlsld_got.refcount += 1;
|
||||
else
|
||||
need += 8;
|
||||
}
|
||||
if ((eh->tls_mask & TLS_GD) != 0)
|
||||
if (!eh->elf.def_dynamic)
|
||||
/* We'll just use htab->tlsld_got.offset. This should
|
||||
always be the case. It's a little odd if we have
|
||||
a local dynamic reloc against a non-local symbol. */
|
||||
htab->tlsld_got.refcount += 1;
|
||||
else
|
||||
need += 8;
|
||||
if ((eh->tls_mask & (TLS_TPREL | TLS_TPRELGD)) != 0)
|
||||
need += 4;
|
||||
if ((eh->tls_mask & TLS_DTPREL) != 0)
|
||||
need += 4;
|
||||
}
|
||||
else
|
||||
need += 4;
|
||||
need += got_entries_needed (eh->tls_mask);
|
||||
if (need == 0)
|
||||
eh->elf.got.offset = (bfd_vma) -1;
|
||||
else
|
||||
|
@ -5833,16 +5862,18 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
|
|||
&& !SYMBOL_REFERENCES_LOCAL (info, &eh->elf)))
|
||||
&& !UNDEFWEAK_NO_DYNAMIC_RELOC (info, &eh->elf))
|
||||
{
|
||||
asection *rsec = htab->elf.srelgot;
|
||||
asection *rsec;
|
||||
bfd_boolean tprel_known = (bfd_link_executable (info)
|
||||
&& SYMBOL_REFERENCES_LOCAL (info,
|
||||
&eh->elf));
|
||||
|
||||
need = got_relocs_needed (eh->tls_mask, need, tprel_known);
|
||||
if ((eh->tls_mask & TLS_LD) != 0 && eh->elf.def_dynamic)
|
||||
need -= sizeof (Elf32_External_Rela);
|
||||
rsec = htab->elf.srelgot;
|
||||
if (eh->elf.type == STT_GNU_IFUNC)
|
||||
rsec = htab->elf.irelplt;
|
||||
/* All the entries we allocated need relocs.
|
||||
Except LD only needs one. */
|
||||
if ((eh->tls_mask & TLS_LD) != 0
|
||||
&& eh->elf.def_dynamic)
|
||||
need -= 4;
|
||||
rsec->size += need * (sizeof (Elf32_External_Rela) / 4);
|
||||
rsec->size += need;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6244,20 +6275,10 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd,
|
|||
for (; local_got < end_local_got; ++local_got, ++lgot_masks)
|
||||
if (*local_got > 0)
|
||||
{
|
||||
unsigned int need = 0;
|
||||
if ((*lgot_masks & TLS_TLS) != 0)
|
||||
{
|
||||
if ((*lgot_masks & TLS_GD) != 0)
|
||||
need += 8;
|
||||
if ((*lgot_masks & TLS_LD) != 0)
|
||||
htab->tlsld_got.refcount += 1;
|
||||
if ((*lgot_masks & (TLS_TPREL | TLS_TPRELGD)) != 0)
|
||||
need += 4;
|
||||
if ((*lgot_masks & TLS_DTPREL) != 0)
|
||||
need += 4;
|
||||
}
|
||||
else
|
||||
need += 4;
|
||||
unsigned int need;
|
||||
if ((*lgot_masks & TLS_LD) != 0)
|
||||
htab->tlsld_got.refcount += 1;
|
||||
need = got_entries_needed (*lgot_masks);
|
||||
if (need == 0)
|
||||
*local_got = (bfd_vma) -1;
|
||||
else
|
||||
|
@ -6265,10 +6286,14 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd,
|
|||
*local_got = allocate_got (htab, need);
|
||||
if (bfd_link_pic (info))
|
||||
{
|
||||
asection *srel = htab->elf.srelgot;
|
||||
asection *srel;
|
||||
bfd_boolean tprel_known = bfd_link_executable (info);
|
||||
|
||||
need = got_relocs_needed (*lgot_masks, need, tprel_known);
|
||||
srel = htab->elf.srelgot;
|
||||
if ((*lgot_masks & PLT_IFUNC) != 0)
|
||||
srel = htab->elf.irelplt;
|
||||
srel->size += need * (sizeof (Elf32_External_Rela) / 4);
|
||||
srel->size += need;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8428,7 +8453,10 @@ ppc_elf_relocate_section (bfd *output_bfd,
|
|||
|| (bfd_link_pic (info)
|
||||
&& (h == NULL
|
||||
|| !UNDEFWEAK_NO_DYNAMIC_RELOC (info, h)
|
||||
|| offp == &htab->tlsld_got.offset)))
|
||||
|| offp == &htab->tlsld_got.offset)
|
||||
&& !(tls_ty == (TLS_TLS | TLS_TPREL)
|
||||
&& bfd_link_executable (info)
|
||||
&& SYMBOL_REFERENCES_LOCAL (info, h))))
|
||||
{
|
||||
asection *rsec = htab->elf.srelgot;
|
||||
bfd_byte * loc;
|
||||
|
|
|
@ -9584,7 +9584,10 @@ allocate_got (struct elf_link_hash_entry *h,
|
|||
htab->elf.irelplt->size += rentsize;
|
||||
htab->got_reli_size += rentsize;
|
||||
}
|
||||
else if ((bfd_link_pic (info)
|
||||
else if (((bfd_link_pic (info)
|
||||
&& !((gent->tls_type & TLS_TPREL) != 0
|
||||
&& bfd_link_executable (info)
|
||||
&& SYMBOL_REFERENCES_LOCAL (info, h)))
|
||||
|| (htab->elf.dynamic_sections_created
|
||||
&& h->dynindx != -1
|
||||
&& !SYMBOL_REFERENCES_LOCAL (info, h)))
|
||||
|
@ -10072,7 +10075,9 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd,
|
|||
htab->elf.irelplt->size += rel_size;
|
||||
htab->got_reli_size += rel_size;
|
||||
}
|
||||
else if (bfd_link_pic (info))
|
||||
else if (bfd_link_pic (info)
|
||||
&& !((ent->tls_type & TLS_TPREL) != 0
|
||||
&& bfd_link_executable (info)))
|
||||
{
|
||||
asection *srel = ppc64_elf_tdata (ibfd)->relgot;
|
||||
srel->size += rel_size;
|
||||
|
@ -14514,7 +14519,10 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
|||
&& (h == NULL
|
||||
|| !UNDEFWEAK_NO_DYNAMIC_RELOC (info, &h->elf)
|
||||
|| (tls_type == (TLS_TLS | TLS_LD)
|
||||
&& !h->elf.def_dynamic))))
|
||||
&& !h->elf.def_dynamic))
|
||||
&& !(tls_type == (TLS_TLS | TLS_TPREL)
|
||||
&& bfd_link_executable (info)
|
||||
&& SYMBOL_REFERENCES_LOCAL (info, &h->elf))))
|
||||
relgot = ppc64_elf_tdata (ent->owner)->relgot;
|
||||
if (relgot != NULL)
|
||||
{
|
||||
|
|
Loading…
Add table
Reference in a new issue