__tls_get_addr_opt stub eh_frame info
Since the __tls_get_addr_opt stub saves LR and makes a call, eh_frame info should be generated to describe how to unwind through the stub. The patch also changes the way the backend iterates over stubs, from looking at all sections in stub_bfd to which all dynamic sections are attached as well, to iterating over the group list, which gets just the stub sections. Most binaries will have just one or two stub groups, so this is a little faster. bfd/ * elf64-ppc.c (struct map_stub): Add tls_get_addr_opt_bctrl. (stub_eh_frame_size): New function. (ppc_size_one_stub): Set group tls_get_addr_opt_bctrl. (group_sections): Init group tls_get_addr_opt_bctrl. (ppc64_elf_size_stubs): Update sizing and initialization of .eh_frame. Iteration over stubs via group list. (ppc64_elf_build_stubs): Iterate over stubs via group list. (ppc64_elf_finish_dynamic_sections): Update finalization of .eh_frame. ld/ * testsuite/ld-powerpc/tlsopt5.s: Add cfi. * testsuite/ld-powerpc/tlsopt5.d: Update. * testsuite/ld-powerpc/tlsopt5.wf: New file. * testsuite/ld-powerpc/powerpc.exp: Perform new tlsopt5 test.
This commit is contained in:
parent
aafd38357a
commit
d4aaa2a074
@ -1,3 +1,15 @@
|
||||
2017-07-25 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* elf64-ppc.c (struct map_stub): Add tls_get_addr_opt_bctrl.
|
||||
(stub_eh_frame_size): New function.
|
||||
(ppc_size_one_stub): Set group tls_get_addr_opt_bctrl.
|
||||
(group_sections): Init group tls_get_addr_opt_bctrl.
|
||||
(ppc64_elf_size_stubs): Update sizing and initialization of
|
||||
.eh_frame. Iteration over stubs via group list.
|
||||
(ppc64_elf_build_stubs): Iterate over stubs via group list.
|
||||
(ppc64_elf_finish_dynamic_sections): Update finalization of
|
||||
.eh_frame.
|
||||
|
||||
2017-07-24 Nick Clifton <nickc@redhat.com>
|
||||
|
||||
PR 21813
|
||||
|
189
bfd/elf64-ppc.c
189
bfd/elf64-ppc.c
@ -3919,6 +3919,9 @@ struct map_stub
|
||||
/* Whether to emit a copy of register save/restore functions in this
|
||||
group. */
|
||||
int needs_save_res;
|
||||
/* The offset of the __tls_get_addr_opt plt stub bctrl in this group,
|
||||
or -1u if no such stub with bctrl exists. */
|
||||
unsigned int tls_get_addr_opt_bctrl;
|
||||
};
|
||||
|
||||
struct ppc_stub_hash_entry {
|
||||
@ -11386,6 +11389,15 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
|
||||
- htab->sec_info[stub_entry->group->link_sec->id].toc_off);
|
||||
|
||||
size = plt_stub_size (htab, stub_entry, off);
|
||||
if (stub_entry->h != NULL
|
||||
&& (stub_entry->h == htab->tls_get_addr_fd
|
||||
|| stub_entry->h == htab->tls_get_addr)
|
||||
&& htab->params->tls_get_addr_opt
|
||||
&& (ALWAYS_EMIT_R2SAVE
|
||||
|| stub_entry->stub_type == ppc_stub_plt_call_r2save))
|
||||
stub_entry->group->tls_get_addr_opt_bctrl
|
||||
= stub_entry->group->stub_sec->size + size - 5 * 4;
|
||||
|
||||
if (htab->params->plt_stub_align)
|
||||
size += plt_stub_pad (htab, stub_entry, off);
|
||||
if (info->emitrelocations)
|
||||
@ -12252,6 +12264,7 @@ group_sections (struct bfd_link_info *info,
|
||||
group->link_sec = curr;
|
||||
group->stub_sec = NULL;
|
||||
group->needs_save_res = 0;
|
||||
group->tls_get_addr_opt_bctrl = -1u;
|
||||
group->next = htab->group;
|
||||
htab->group = group;
|
||||
do
|
||||
@ -12302,6 +12315,27 @@ static const unsigned char glink_eh_frame_cie[] =
|
||||
DW_CFA_def_cfa, 1, 0 /* def_cfa: r1 offset 0. */
|
||||
};
|
||||
|
||||
static size_t
|
||||
stub_eh_frame_size (struct map_stub *group, size_t align)
|
||||
{
|
||||
size_t this_size = 17;
|
||||
if (group->tls_get_addr_opt_bctrl != -1u)
|
||||
{
|
||||
unsigned int to_bctrl = group->tls_get_addr_opt_bctrl / 4;
|
||||
if (to_bctrl < 64)
|
||||
this_size += 1;
|
||||
else if (to_bctrl < 256)
|
||||
this_size += 2;
|
||||
else if (to_bctrl < 65536)
|
||||
this_size += 3;
|
||||
else
|
||||
this_size += 5;
|
||||
this_size += 6;
|
||||
}
|
||||
this_size = (this_size + align - 1) & -align;
|
||||
return this_size;
|
||||
}
|
||||
|
||||
/* Stripping output sections is normally done before dynamic section
|
||||
symbols have been allocated. This function is called later, and
|
||||
handles cases like htab->brlt which is mapped to its own output
|
||||
@ -12404,7 +12438,6 @@ ppc64_elf_size_stubs (struct bfd_link_info *info)
|
||||
bfd *input_bfd;
|
||||
unsigned int bfd_indx;
|
||||
struct map_stub *group;
|
||||
asection *stub_sec;
|
||||
|
||||
htab->stub_iteration += 1;
|
||||
|
||||
@ -12722,11 +12755,11 @@ ppc64_elf_size_stubs (struct bfd_link_info *info)
|
||||
|
||||
/* We may have added some stubs. Find out the new size of the
|
||||
stub sections. */
|
||||
for (stub_sec = htab->params->stub_bfd->sections;
|
||||
stub_sec != NULL;
|
||||
stub_sec = stub_sec->next)
|
||||
if ((stub_sec->flags & SEC_LINKER_CREATED) == 0)
|
||||
for (group = htab->group; group != NULL; group = group->next)
|
||||
if (group->stub_sec != NULL)
|
||||
{
|
||||
asection *stub_sec = group->stub_sec;
|
||||
|
||||
if (htab->stub_iteration <= STUB_SHRINK_ITER
|
||||
|| stub_sec->rawsize < stub_sec->size)
|
||||
/* Past STUB_SHRINK_ITER, rawsize is the max size seen. */
|
||||
@ -12761,11 +12794,9 @@ ppc64_elf_size_stubs (struct bfd_link_info *info)
|
||||
{
|
||||
size_t size = 0, align = 4;
|
||||
|
||||
for (stub_sec = htab->params->stub_bfd->sections;
|
||||
stub_sec != NULL;
|
||||
stub_sec = stub_sec->next)
|
||||
if ((stub_sec->flags & SEC_LINKER_CREATED) == 0)
|
||||
size += (17 + align - 1) & -align;
|
||||
for (group = htab->group; group != NULL; group = group->next)
|
||||
if (group->stub_sec != NULL)
|
||||
size += stub_eh_frame_size (group, align);
|
||||
if (htab->glink != NULL && htab->glink->size != 0)
|
||||
size += (24 + align - 1) & -align;
|
||||
if (size != 0)
|
||||
@ -12777,24 +12808,20 @@ ppc64_elf_size_stubs (struct bfd_link_info *info)
|
||||
}
|
||||
|
||||
if (htab->params->plt_stub_align != 0)
|
||||
for (stub_sec = htab->params->stub_bfd->sections;
|
||||
stub_sec != NULL;
|
||||
stub_sec = stub_sec->next)
|
||||
if ((stub_sec->flags & SEC_LINKER_CREATED) == 0)
|
||||
stub_sec->size = ((stub_sec->size
|
||||
+ (1 << htab->params->plt_stub_align) - 1)
|
||||
& -(1 << htab->params->plt_stub_align));
|
||||
for (group = htab->group; group != NULL; group = group->next)
|
||||
if (group->stub_sec != NULL)
|
||||
group->stub_sec->size = ((group->stub_sec->size
|
||||
+ (1 << htab->params->plt_stub_align) - 1)
|
||||
& -(1 << htab->params->plt_stub_align));
|
||||
|
||||
for (stub_sec = htab->params->stub_bfd->sections;
|
||||
stub_sec != NULL;
|
||||
stub_sec = stub_sec->next)
|
||||
if ((stub_sec->flags & SEC_LINKER_CREATED) == 0
|
||||
&& stub_sec->rawsize != stub_sec->size
|
||||
for (group = htab->group; group != NULL; group = group->next)
|
||||
if (group->stub_sec != NULL
|
||||
&& group->stub_sec->rawsize != group->stub_sec->size
|
||||
&& (htab->stub_iteration <= STUB_SHRINK_ITER
|
||||
|| stub_sec->rawsize < stub_sec->size))
|
||||
|| group->stub_sec->rawsize < group->stub_sec->size))
|
||||
break;
|
||||
|
||||
if (stub_sec == NULL
|
||||
if (group == NULL
|
||||
&& (htab->glink_eh_frame == NULL
|
||||
|| htab->glink_eh_frame->rawsize == htab->glink_eh_frame->size))
|
||||
break;
|
||||
@ -12809,7 +12836,7 @@ ppc64_elf_size_stubs (struct bfd_link_info *info)
|
||||
bfd_vma val;
|
||||
bfd_byte *p, *last_fde;
|
||||
size_t last_fde_len, size, align, pad;
|
||||
asection *stub_sec;
|
||||
struct map_stub *group;
|
||||
|
||||
p = bfd_zalloc (htab->glink_eh_frame->owner, htab->glink_eh_frame->size);
|
||||
if (p == NULL)
|
||||
@ -12824,13 +12851,11 @@ ppc64_elf_size_stubs (struct bfd_link_info *info)
|
||||
bfd_put_32 (htab->elf.dynobj, last_fde_len, p);
|
||||
p += last_fde_len + 4;
|
||||
|
||||
for (stub_sec = htab->params->stub_bfd->sections;
|
||||
stub_sec != NULL;
|
||||
stub_sec = stub_sec->next)
|
||||
if ((stub_sec->flags & SEC_LINKER_CREATED) == 0)
|
||||
for (group = htab->group; group != NULL; group = group->next)
|
||||
if (group->stub_sec != NULL)
|
||||
{
|
||||
last_fde = p;
|
||||
last_fde_len = ((17 + align - 1) & -align) - 4;
|
||||
last_fde_len = stub_eh_frame_size (group, align) - 4;
|
||||
/* FDE length. */
|
||||
bfd_put_32 (htab->elf.dynobj, last_fde_len, p);
|
||||
p += 4;
|
||||
@ -12841,12 +12866,44 @@ ppc64_elf_size_stubs (struct bfd_link_info *info)
|
||||
/* Offset to stub section, written later. */
|
||||
p += 4;
|
||||
/* stub section size. */
|
||||
bfd_put_32 (htab->elf.dynobj, stub_sec->size, p);
|
||||
bfd_put_32 (htab->elf.dynobj, group->stub_sec->size, p);
|
||||
p += 4;
|
||||
/* Augmentation. */
|
||||
p += 1;
|
||||
if (group->tls_get_addr_opt_bctrl != -1u)
|
||||
{
|
||||
unsigned int to_bctrl = group->tls_get_addr_opt_bctrl / 4;
|
||||
|
||||
/* This FDE needs more than just the default.
|
||||
Describe __tls_get_addr_opt stub LR. */
|
||||
if (to_bctrl < 64)
|
||||
*p++ = DW_CFA_advance_loc + to_bctrl;
|
||||
else if (to_bctrl < 256)
|
||||
{
|
||||
*p++ = DW_CFA_advance_loc1;
|
||||
*p++ = to_bctrl;
|
||||
}
|
||||
else if (to_bctrl < 65536)
|
||||
{
|
||||
*p++ = DW_CFA_advance_loc2;
|
||||
bfd_put_16 (htab->elf.dynobj, to_bctrl, p);
|
||||
p += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
*p++ = DW_CFA_advance_loc4;
|
||||
bfd_put_32 (htab->elf.dynobj, to_bctrl, p);
|
||||
p += 4;
|
||||
}
|
||||
*p++ = DW_CFA_offset_extended_sf;
|
||||
*p++ = 65;
|
||||
*p++ = -(STK_LINKER (htab) / 8) & 0x7f;
|
||||
*p++ = DW_CFA_advance_loc + 4;
|
||||
*p++ = DW_CFA_restore_extended;
|
||||
*p++ = 65;
|
||||
}
|
||||
/* Pad. */
|
||||
p += ((17 + align - 1) & -align) - 17;
|
||||
p = last_fde + last_fde_len + 4;
|
||||
}
|
||||
if (htab->glink != NULL && htab->glink->size != 0)
|
||||
{
|
||||
@ -13115,10 +13172,8 @@ ppc64_elf_build_stubs (struct bfd_link_info *info,
|
||||
return FALSE;
|
||||
|
||||
/* Allocate memory to hold the linker stubs. */
|
||||
for (stub_sec = htab->params->stub_bfd->sections;
|
||||
stub_sec != NULL;
|
||||
stub_sec = stub_sec->next)
|
||||
if ((stub_sec->flags & SEC_LINKER_CREATED) == 0
|
||||
for (group = htab->group; group != NULL; group = group->next)
|
||||
if ((stub_sec = group->stub_sec) != NULL
|
||||
&& stub_sec->size != 0)
|
||||
{
|
||||
stub_sec->contents = bfd_zalloc (htab->params->stub_bfd, stub_sec->size);
|
||||
@ -13300,18 +13355,14 @@ ppc64_elf_build_stubs (struct bfd_link_info *info,
|
||||
htab->relbrlt->reloc_count = 0;
|
||||
|
||||
if (htab->params->plt_stub_align != 0)
|
||||
for (stub_sec = htab->params->stub_bfd->sections;
|
||||
stub_sec != NULL;
|
||||
stub_sec = stub_sec->next)
|
||||
if ((stub_sec->flags & SEC_LINKER_CREATED) == 0)
|
||||
for (group = htab->group; group != NULL; group = group->next)
|
||||
if ((stub_sec = group->stub_sec) != NULL)
|
||||
stub_sec->size = ((stub_sec->size
|
||||
+ (1 << htab->params->plt_stub_align) - 1)
|
||||
& -(1 << htab->params->plt_stub_align));
|
||||
|
||||
for (stub_sec = htab->params->stub_bfd->sections;
|
||||
stub_sec != NULL;
|
||||
stub_sec = stub_sec->next)
|
||||
if ((stub_sec->flags & SEC_LINKER_CREATED) == 0)
|
||||
for (group = htab->group; group != NULL; group = group->next)
|
||||
if ((stub_sec = group->stub_sec) != NULL)
|
||||
{
|
||||
stub_sec_count += 1;
|
||||
if (stub_sec->rawsize != stub_sec->size
|
||||
@ -13323,7 +13374,7 @@ ppc64_elf_build_stubs (struct bfd_link_info *info,
|
||||
/* Note that the glink_eh_frame check here is not only testing that
|
||||
the generated size matched the calculated size but also that
|
||||
bfd_elf_discard_info didn't make any changes to the section. */
|
||||
if (stub_sec != NULL
|
||||
if (group != NULL
|
||||
|| (htab->glink_eh_frame != NULL
|
||||
&& htab->glink_eh_frame->rawsize != htab->glink_eh_frame->size))
|
||||
{
|
||||
@ -15743,55 +15794,40 @@ ppc64_elf_finish_dynamic_sections (bfd *output_bfd,
|
||||
{
|
||||
bfd_vma val;
|
||||
bfd_byte *p;
|
||||
asection *stub_sec;
|
||||
struct map_stub *group;
|
||||
size_t align = 4;
|
||||
|
||||
p = htab->glink_eh_frame->contents;
|
||||
p += (sizeof (glink_eh_frame_cie) + align - 1) & -align;
|
||||
for (stub_sec = htab->params->stub_bfd->sections;
|
||||
stub_sec != NULL;
|
||||
stub_sec = stub_sec->next)
|
||||
if ((stub_sec->flags & SEC_LINKER_CREATED) == 0)
|
||||
|
||||
for (group = htab->group; group != NULL; group = group->next)
|
||||
if (group->stub_sec != NULL)
|
||||
{
|
||||
/* FDE length. */
|
||||
p += 4;
|
||||
/* CIE pointer. */
|
||||
p += 4;
|
||||
/* Offset to stub section. */
|
||||
val = (stub_sec->output_section->vma
|
||||
+ stub_sec->output_offset);
|
||||
val = (group->stub_sec->output_section->vma
|
||||
+ group->stub_sec->output_offset);
|
||||
val -= (htab->glink_eh_frame->output_section->vma
|
||||
+ htab->glink_eh_frame->output_offset
|
||||
+ (p - htab->glink_eh_frame->contents));
|
||||
+ (p + 8 - htab->glink_eh_frame->contents));
|
||||
if (val + 0x80000000 > 0xffffffff)
|
||||
{
|
||||
info->callbacks->einfo
|
||||
(_("%P: %s offset too large for .eh_frame sdata4 encoding"),
|
||||
stub_sec->name);
|
||||
group->stub_sec->name);
|
||||
return FALSE;
|
||||
}
|
||||
bfd_put_32 (dynobj, val, p);
|
||||
p += 4;
|
||||
/* stub section size. */
|
||||
p += 4;
|
||||
/* Augmentation. */
|
||||
p += 1;
|
||||
/* Pad. */
|
||||
p += ((17 + align - 1) & -align) - 17;
|
||||
bfd_put_32 (dynobj, val, p + 8);
|
||||
p += stub_eh_frame_size (group, align);
|
||||
}
|
||||
if (htab->glink != NULL && htab->glink->size != 0)
|
||||
{
|
||||
/* FDE length. */
|
||||
p += 4;
|
||||
/* CIE pointer. */
|
||||
p += 4;
|
||||
/* Offset to .glink. */
|
||||
val = (htab->glink->output_section->vma
|
||||
+ htab->glink->output_offset
|
||||
+ 8);
|
||||
val -= (htab->glink_eh_frame->output_section->vma
|
||||
+ htab->glink_eh_frame->output_offset
|
||||
+ (p - htab->glink_eh_frame->contents));
|
||||
+ (p + 8 - htab->glink_eh_frame->contents));
|
||||
if (val + 0x80000000 > 0xffffffff)
|
||||
{
|
||||
info->callbacks->einfo
|
||||
@ -15799,15 +15835,8 @@ ppc64_elf_finish_dynamic_sections (bfd *output_bfd,
|
||||
htab->glink->name);
|
||||
return FALSE;
|
||||
}
|
||||
bfd_put_32 (dynobj, val, p);
|
||||
p += 4;
|
||||
/* .glink size. */
|
||||
p += 4;
|
||||
/* Augmentation. */
|
||||
p += 1;
|
||||
/* Ops. */
|
||||
p += 7;
|
||||
p += ((24 + align - 1) & -align) - 24;
|
||||
bfd_put_32 (dynobj, val, p + 8);
|
||||
p += (24 + align - 1) & -align;
|
||||
}
|
||||
|
||||
if (htab->glink_eh_frame->sec_info_type == SEC_INFO_TYPE_EH_FRAME
|
||||
|
@ -1,3 +1,10 @@
|
||||
2017-07-25 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* testsuite/ld-powerpc/tlsopt5.s: Add cfi.
|
||||
* testsuite/ld-powerpc/tlsopt5.d: Update.
|
||||
* testsuite/ld-powerpc/tlsopt5.wf: New file.
|
||||
* testsuite/ld-powerpc/powerpc.exp: Perform new tlsopt5 test.
|
||||
|
||||
2017-07-24 Claudiu Zissulescu <claziss@synopsys.com>
|
||||
|
||||
* testsuite/ld-arc/jli-overflow.d: Force testing for little
|
||||
|
@ -211,7 +211,7 @@ set ppc64elftests {
|
||||
{"TLS DLL" "-shared -melf64ppc --version-script tlsdll.ver" "" "-a64" {tlsdll.s}
|
||||
{} "tlsdll.so"}
|
||||
{"TLS opt 5" "-melf64ppc -shared --gc-sections --no-plt-localentry tmpdir/tlsdll.so" "" "-a64" {tlsopt5.s}
|
||||
{{objdump -dr tlsopt5.d}}
|
||||
{{objdump -dr tlsopt5.d} {readelf -wf tlsopt5.wf}}
|
||||
"tlsopt5"}
|
||||
{"sym@tocbase" "-shared -melf64ppc" "" "-a64" {symtocbase-1.s symtocbase-2.s}
|
||||
{{objdump -dj.data symtocbase.d}} "symtocbase.so"}
|
||||
|
@ -31,8 +31,8 @@ Disassembly of section \.text:
|
||||
.*: (08 80 62 38|38 62 80 08) addi r3,r2,-32760
|
||||
.*: (b9 ff ff 4b|4b ff ff b9) bl .*
|
||||
.*: (00 00 00 60|60 00 00 00) nop
|
||||
.*: (f8 01 01 00|00 00 00 00) .*
|
||||
.*: (00 00 00 00|00 01 01 f8) .*
|
||||
.*: (f8 02 01 00|00 00 00 00) .*
|
||||
.*: (00 00 00 00|00 01 02 f8) .*
|
||||
|
||||
0+318 <__glink_PLTresolve>:
|
||||
.*: (a6 02 08 7c|7c 08 02 a6) mflr r0
|
||||
|
@ -1,5 +1,7 @@
|
||||
.globl _start
|
||||
_start:
|
||||
.cfi_startproc
|
||||
addi 3,2,gd@got@tlsgd
|
||||
bl __tls_get_addr(gd@tlsgd)
|
||||
nop
|
||||
.cfi_endproc
|
||||
|
32
ld/testsuite/ld-powerpc/tlsopt5.wf
Normal file
32
ld/testsuite/ld-powerpc/tlsopt5.wf
Normal file
@ -0,0 +1,32 @@
|
||||
Contents of the \.eh_frame section:
|
||||
|
||||
0+ 0+10 0+ CIE
|
||||
Version: 1
|
||||
Augmentation: "zR"
|
||||
Code alignment factor: 4
|
||||
Data alignment factor: -8
|
||||
Return address column: 65
|
||||
Augmentation data: 1b
|
||||
|
||||
DW_CFA_def_cfa: r1 ofs 0
|
||||
|
||||
0+14 0+14 0+18 FDE cie=0+ pc=0+2c0\.\.0+304
|
||||
DW_CFA_advance_loc: 48 to 0+2f0
|
||||
DW_CFA_offset_extended_sf: r65 at cfa\+8
|
||||
DW_CFA_advance_loc: 16 to 0+300
|
||||
DW_CFA_restore_extended: r65
|
||||
|
||||
0+2c 0+18 0+30 FDE cie=0+ pc=0+318\.\.0+354
|
||||
DW_CFA_advance_loc: 4 to 0+31c
|
||||
DW_CFA_register: r65 in r0
|
||||
DW_CFA_advance_loc: 28 to 0+338
|
||||
DW_CFA_restore_extended: r65
|
||||
DW_CFA_nop
|
||||
DW_CFA_nop
|
||||
DW_CFA_nop
|
||||
DW_CFA_nop
|
||||
|
||||
0+48 0+10 0+4c FDE cie=0+ pc=0+304\.\.0+310
|
||||
DW_CFA_nop
|
||||
DW_CFA_nop
|
||||
DW_CFA_nop
|
Loading…
Reference in New Issue
Block a user