mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-29 08:24:05 +08:00
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:
@ -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>
|
2017-11-04 Alan Modra <amodra@gmail.com>
|
||||||
|
|
||||||
* elf32-ppc.c (readonly_dynrelocs): Delete info param. Update all
|
* 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;
|
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. */
|
/* If H is undefined, make it dynamic if that makes sense. */
|
||||||
|
|
||||||
static bfd_boolean
|
static bfd_boolean
|
||||||
@ -5801,27 +5840,17 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
need = 0;
|
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
|
||||||
if (!eh->elf.def_dynamic)
|
always be the case. It's a little odd if we have
|
||||||
/* We'll just use htab->tlsld_got.offset. This should
|
a local dynamic reloc against a non-local symbol. */
|
||||||
always be the case. It's a little odd if we have
|
htab->tlsld_got.refcount += 1;
|
||||||
a local dynamic reloc against a non-local symbol. */
|
else
|
||||||
htab->tlsld_got.refcount += 1;
|
|
||||||
else
|
|
||||||
need += 8;
|
|
||||||
}
|
|
||||||
if ((eh->tls_mask & TLS_GD) != 0)
|
|
||||||
need += 8;
|
need += 8;
|
||||||
if ((eh->tls_mask & (TLS_TPREL | TLS_TPRELGD)) != 0)
|
|
||||||
need += 4;
|
|
||||||
if ((eh->tls_mask & TLS_DTPREL) != 0)
|
|
||||||
need += 4;
|
|
||||||
}
|
}
|
||||||
else
|
need += got_entries_needed (eh->tls_mask);
|
||||||
need += 4;
|
|
||||||
if (need == 0)
|
if (need == 0)
|
||||||
eh->elf.got.offset = (bfd_vma) -1;
|
eh->elf.got.offset = (bfd_vma) -1;
|
||||||
else
|
else
|
||||||
@ -5833,16 +5862,18 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
|
|||||||
&& !SYMBOL_REFERENCES_LOCAL (info, &eh->elf)))
|
&& !SYMBOL_REFERENCES_LOCAL (info, &eh->elf)))
|
||||||
&& !UNDEFWEAK_NO_DYNAMIC_RELOC (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)
|
if (eh->elf.type == STT_GNU_IFUNC)
|
||||||
rsec = htab->elf.irelplt;
|
rsec = htab->elf.irelplt;
|
||||||
/* All the entries we allocated need relocs.
|
rsec->size += need;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -6244,20 +6275,10 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd,
|
|||||||
for (; local_got < end_local_got; ++local_got, ++lgot_masks)
|
for (; local_got < end_local_got; ++local_got, ++lgot_masks)
|
||||||
if (*local_got > 0)
|
if (*local_got > 0)
|
||||||
{
|
{
|
||||||
unsigned int need = 0;
|
unsigned int need;
|
||||||
if ((*lgot_masks & TLS_TLS) != 0)
|
if ((*lgot_masks & TLS_LD) != 0)
|
||||||
{
|
htab->tlsld_got.refcount += 1;
|
||||||
if ((*lgot_masks & TLS_GD) != 0)
|
need = got_entries_needed (*lgot_masks);
|
||||||
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;
|
|
||||||
if (need == 0)
|
if (need == 0)
|
||||||
*local_got = (bfd_vma) -1;
|
*local_got = (bfd_vma) -1;
|
||||||
else
|
else
|
||||||
@ -6265,10 +6286,14 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd,
|
|||||||
*local_got = allocate_got (htab, need);
|
*local_got = allocate_got (htab, need);
|
||||||
if (bfd_link_pic (info))
|
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)
|
if ((*lgot_masks & PLT_IFUNC) != 0)
|
||||||
srel = htab->elf.irelplt;
|
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)
|
|| (bfd_link_pic (info)
|
||||||
&& (h == NULL
|
&& (h == NULL
|
||||||
|| !UNDEFWEAK_NO_DYNAMIC_RELOC (info, h)
|
|| !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;
|
asection *rsec = htab->elf.srelgot;
|
||||||
bfd_byte * loc;
|
bfd_byte * loc;
|
||||||
|
@ -9584,7 +9584,10 @@ allocate_got (struct elf_link_hash_entry *h,
|
|||||||
htab->elf.irelplt->size += rentsize;
|
htab->elf.irelplt->size += rentsize;
|
||||||
htab->got_reli_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
|
|| (htab->elf.dynamic_sections_created
|
||||||
&& h->dynindx != -1
|
&& h->dynindx != -1
|
||||||
&& !SYMBOL_REFERENCES_LOCAL (info, h)))
|
&& !SYMBOL_REFERENCES_LOCAL (info, h)))
|
||||||
@ -10072,7 +10075,9 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd,
|
|||||||
htab->elf.irelplt->size += rel_size;
|
htab->elf.irelplt->size += rel_size;
|
||||||
htab->got_reli_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;
|
asection *srel = ppc64_elf_tdata (ibfd)->relgot;
|
||||||
srel->size += rel_size;
|
srel->size += rel_size;
|
||||||
@ -14514,7 +14519,10 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
|||||||
&& (h == NULL
|
&& (h == NULL
|
||||||
|| !UNDEFWEAK_NO_DYNAMIC_RELOC (info, &h->elf)
|
|| !UNDEFWEAK_NO_DYNAMIC_RELOC (info, &h->elf)
|
||||||
|| (tls_type == (TLS_TLS | TLS_LD)
|
|| (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;
|
relgot = ppc64_elf_tdata (ent->owner)->relgot;
|
||||||
if (relgot != NULL)
|
if (relgot != NULL)
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user