mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-23 01:53:38 +08:00
ld: generate SFrame stack trace info for .plt.got
PR/32298 sframe: no SFrame stack trace info generated for .plt.got Add support to generate SFrame stack trace info for .plt.got section. Enhance the current definition of struct elf_x86_sframe_plt to include initialized SFrame FDE/FREs applicable for .plt.got section. There are two variants of .plt.got entries: 16 byte and 8 byte. 8 byte: ff 25 00 00 00 00 jmpq *name@GOTPCREL(%rip) 66 90 xchg %ax,%ax 16 byte: f3 0f 1e fa endbr64 ff 25 66 2f 00 00 jmpq *name@GOTPCREL(%rip) 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1) For the testcase, define some application symbols such that their PLT entry is placed in .plt.got and ensure SFrame information is generated with and without -z ibtplt. ChangeLog: PR/32298 * bfd/elf64-x86-64.c (elf_x86_64_link_setup_gnu_properties): PLT GOT entry size is different for IBT vs non IBT PLTs. * bfd/elfxx-x86.c (enum dynobj_sframe_plt_type): New enum for SFRAME_PLT_GOT. (_bfd_x86_elf_create_sframe_plt): Handle SFRAME_PLT_GOT. (_bfd_x86_elf_write_sframe_plt): Likewise. (_bfd_x86_elf_late_size_sections): Likewise. (_bfd_x86_elf_finish_dynamic_sections): Likewise. * bfd/elfxx-x86.h (struct elf_x86_sframe_plt): Add new members to keep information about PLT GOT entries. (struct elf_x86_link_hash_table): Add support for creating SFrame section for .plt.got. * ld/testsuite/ld-x86-64/x86-64.exp: Add new tests. * ld/testsuite/ld-x86-64/sframe-pltgot-1.d: New test. * ld/testsuite/ld-x86-64/sframe-pltgot-1.s: New test. * ld/testsuite/ld-x86-64/sframe-pltgot-2.d: New test.
This commit is contained in:
parent
938fb51218
commit
47c88752f9
@ -922,7 +922,7 @@ static const sframe_frame_row_entry elf_x86_64_sframe_sec_pltn_fre1 =
|
||||
SFRAME_V1_FRE_INFO (SFRAME_BASE_REG_SP, 1, SFRAME_FRE_OFFSET_1B) /* FRE info. */
|
||||
};
|
||||
|
||||
/* SFrame helper object for non-lazy PLT. Also used for IBT enabled PLT. */
|
||||
/* SFrame helper object for non-lazy PLT. */
|
||||
static const struct elf_x86_sframe_plt elf_x86_64_sframe_non_lazy_plt =
|
||||
{
|
||||
LAZY_PLT_ENTRY_SIZE,
|
||||
@ -935,7 +935,31 @@ static const struct elf_x86_sframe_plt elf_x86_64_sframe_non_lazy_plt =
|
||||
{ &elf_x86_64_sframe_sec_pltn_fre1, &elf_x86_64_sframe_null_fre },
|
||||
0,
|
||||
0, /* There is no second PLT necessary. */
|
||||
{ &elf_x86_64_sframe_null_fre }
|
||||
{ &elf_x86_64_sframe_null_fre },
|
||||
NON_LAZY_PLT_ENTRY_SIZE,
|
||||
1, /* Number of FREs for PLT GOT. */
|
||||
/* Array of SFrame FREs for PLT GOT. */
|
||||
{ &elf_x86_64_sframe_null_fre },
|
||||
};
|
||||
|
||||
/* SFrame helper object for non-lazy IBT enabled PLT. */
|
||||
static const struct elf_x86_sframe_plt elf_x86_64_sframe_non_lazy_ibt_plt =
|
||||
{
|
||||
LAZY_PLT_ENTRY_SIZE,
|
||||
2, /* Number of FREs for PLT0. */
|
||||
/* Array of SFrame FREs for plt0. */
|
||||
{ &elf_x86_64_sframe_plt0_fre1, &elf_x86_64_sframe_plt0_fre2 },
|
||||
LAZY_PLT_ENTRY_SIZE,
|
||||
1, /* Number of FREs for PLTn. */
|
||||
/* Array of SFrame FREs for plt. */
|
||||
{ &elf_x86_64_sframe_sec_pltn_fre1, &elf_x86_64_sframe_null_fre },
|
||||
0,
|
||||
0, /* There is no second PLT necessary. */
|
||||
{ &elf_x86_64_sframe_null_fre },
|
||||
LAZY_PLT_ENTRY_SIZE,
|
||||
1, /* Number of FREs for PLT GOT. */
|
||||
/* Array of SFrame FREs for PLT GOT. */
|
||||
{ &elf_x86_64_sframe_null_fre },
|
||||
};
|
||||
|
||||
/* SFrame helper object for lazy PLT. */
|
||||
@ -952,7 +976,11 @@ static const struct elf_x86_sframe_plt elf_x86_64_sframe_plt =
|
||||
NON_LAZY_PLT_ENTRY_SIZE,
|
||||
1, /* Number of FREs for second PLT. */
|
||||
/* Array of SFrame FREs for second PLT. */
|
||||
{ &elf_x86_64_sframe_sec_pltn_fre1 }
|
||||
{ &elf_x86_64_sframe_sec_pltn_fre1 },
|
||||
NON_LAZY_PLT_ENTRY_SIZE,
|
||||
1, /* Number of FREs for PLT GOT. */
|
||||
/* Array of SFrame FREs for PLT GOT. */
|
||||
{ &elf_x86_64_sframe_null_fre },
|
||||
};
|
||||
|
||||
/* SFrame helper object for lazy PLT with IBT. */
|
||||
@ -969,7 +997,11 @@ static const struct elf_x86_sframe_plt elf_x86_64_sframe_ibt_plt =
|
||||
LAZY_PLT_ENTRY_SIZE,
|
||||
1, /* Number of FREs for second PLT. */
|
||||
/* Array of SFrame FREs for second plt. */
|
||||
{ &elf_x86_64_sframe_sec_pltn_fre1 }
|
||||
{ &elf_x86_64_sframe_sec_pltn_fre1 },
|
||||
LAZY_PLT_ENTRY_SIZE,
|
||||
1, /* Number of FREs for PLT GOT. */
|
||||
/* Array of SFrame FREs for PLT GOT. */
|
||||
{ &elf_x86_64_sframe_null_fre },
|
||||
};
|
||||
|
||||
/* These are the standard parameters. */
|
||||
@ -5703,7 +5735,7 @@ elf_x86_64_link_setup_gnu_properties (struct bfd_link_info *info)
|
||||
init_table.sframe_lazy_plt = &elf_x86_64_sframe_plt;
|
||||
init_table.sframe_non_lazy_plt = &elf_x86_64_sframe_non_lazy_plt;
|
||||
init_table.sframe_lazy_ibt_plt = &elf_x86_64_sframe_ibt_plt;
|
||||
init_table.sframe_non_lazy_ibt_plt = &elf_x86_64_sframe_non_lazy_plt;
|
||||
init_table.sframe_non_lazy_ibt_plt = &elf_x86_64_sframe_non_lazy_ibt_plt;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1817,7 +1817,8 @@ elf_x86_relative_reloc_compare (const void *pa, const void *pb)
|
||||
enum dynobj_sframe_plt_type
|
||||
{
|
||||
SFRAME_PLT = 1,
|
||||
SFRAME_PLT_SEC = 2
|
||||
SFRAME_PLT_SEC = 2,
|
||||
SFRAME_PLT_GOT = 3,
|
||||
};
|
||||
|
||||
/* Create SFrame stack trace info for the plt entries in the .plt section
|
||||
@ -1880,6 +1881,21 @@ _bfd_x86_elf_create_sframe_plt (bfd *output_bfd,
|
||||
|
||||
break;
|
||||
}
|
||||
case SFRAME_PLT_GOT:
|
||||
{
|
||||
ectx = &htab->plt_got_cfe_ctx;
|
||||
dpltsec = htab->plt_got;
|
||||
|
||||
plt0_entry_size = 0;
|
||||
|
||||
plt_entry_size = htab->sframe_plt->plt_got_entry_size;
|
||||
pltn_fres = htab->sframe_plt->plt_got_fres;
|
||||
num_pltn_fres = htab->sframe_plt->plt_got_num_fres;
|
||||
num_pltn_entries = dpltsec->size / plt_entry_size;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
/* No other value is possible. */
|
||||
return false;
|
||||
@ -1984,6 +2000,10 @@ _bfd_x86_elf_write_sframe_plt (bfd *output_bfd,
|
||||
ectx = htab->plt_second_cfe_ctx;
|
||||
sec = htab->plt_second_sframe;
|
||||
break;
|
||||
case SFRAME_PLT_GOT:
|
||||
ectx = htab->plt_got_cfe_ctx;
|
||||
sec = htab->plt_got_sframe;
|
||||
break;
|
||||
default:
|
||||
/* No other value is possible. */
|
||||
return false;
|
||||
@ -2511,7 +2531,18 @@ _bfd_x86_elf_late_size_sections (bfd *output_bfd,
|
||||
htab->plt_sframe->size = sizeof (sframe_header) + 1;
|
||||
}
|
||||
|
||||
/* FIXME - generate for .plt.got ? */
|
||||
if (htab->plt_got_sframe != NULL
|
||||
&& htab->plt_got != NULL
|
||||
&& htab->plt_got->size != 0
|
||||
&& !bfd_is_abs_section (htab->plt_got->output_section))
|
||||
{
|
||||
_bfd_x86_elf_create_sframe_plt (output_bfd, info, SFRAME_PLT_GOT);
|
||||
/* FIXME - Dirty Hack. Set the size to something non-zero for now,
|
||||
so that the section does not get stripped out below. The precise
|
||||
size of this section is known only when the contents are
|
||||
serialized in _bfd_x86_elf_write_sframe_plt. */
|
||||
htab->plt_got_sframe->size = sizeof (sframe_header) + 1;
|
||||
}
|
||||
|
||||
if (htab->plt_second_sframe != NULL
|
||||
&& htab->plt_second != NULL
|
||||
@ -2578,6 +2609,7 @@ _bfd_x86_elf_late_size_sections (bfd *output_bfd,
|
||||
|| s == htab->plt_second_eh_frame
|
||||
|| s == htab->plt_sframe
|
||||
|| s == htab->plt_second_sframe
|
||||
|| s == htab->plt_got_sframe
|
||||
|| s == htab->elf.sdynbss
|
||||
|| s == htab->elf.sdynrelro)
|
||||
{
|
||||
@ -2622,7 +2654,8 @@ _bfd_x86_elf_late_size_sections (bfd *output_bfd,
|
||||
|
||||
/* Skip allocating contents for .sframe section as it is written
|
||||
out differently. See below. */
|
||||
if ((s == htab->plt_sframe) || (s == htab->plt_second_sframe))
|
||||
if ((s == htab->plt_sframe) || (s == htab->plt_second_sframe)
|
||||
|| (s == htab->plt_got_sframe))
|
||||
continue;
|
||||
|
||||
/* NB: Initially, the iplt section has minimal alignment to
|
||||
@ -2687,6 +2720,12 @@ _bfd_x86_elf_late_size_sections (bfd *output_bfd,
|
||||
&& htab->plt_second->size != 0
|
||||
&& htab->plt_second_sframe->contents == NULL)
|
||||
_bfd_x86_elf_write_sframe_plt (output_bfd, info, SFRAME_PLT_SEC);
|
||||
|
||||
if (htab->plt_got_sframe != NULL
|
||||
&& htab->plt_got != NULL
|
||||
&& htab->plt_got->size != 0
|
||||
&& htab->plt_got_sframe->contents == NULL)
|
||||
_bfd_x86_elf_write_sframe_plt (output_bfd, info, SFRAME_PLT_GOT);
|
||||
}
|
||||
|
||||
if (resolved_plt != NULL
|
||||
@ -2997,6 +3036,34 @@ _bfd_x86_elf_finish_dynamic_sections (bfd *output_bfd,
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (htab->plt_got_sframe != NULL
|
||||
&& htab->plt_got_sframe->contents != NULL)
|
||||
{
|
||||
if (htab->plt_got != NULL
|
||||
&& htab->plt_got->size != 0
|
||||
&& (htab->plt_got->flags & SEC_EXCLUDE) == 0
|
||||
&& htab->plt_got->output_section != NULL
|
||||
&& htab->plt_got_sframe->output_section != NULL)
|
||||
{
|
||||
bfd_vma plt_start = htab->plt_got->output_section->vma;
|
||||
bfd_vma sframe_start
|
||||
= (htab->plt_got_sframe->output_section->vma
|
||||
+ htab->plt_got_sframe->output_offset
|
||||
+ PLT_SFRAME_FDE_START_OFFSET);
|
||||
bfd_put_signed_32 (dynobj, plt_start - sframe_start,
|
||||
htab->plt_got_sframe->contents
|
||||
+ PLT_SFRAME_FDE_START_OFFSET);
|
||||
}
|
||||
if (htab->plt_got_sframe->sec_info_type == SEC_INFO_TYPE_SFRAME)
|
||||
{
|
||||
if (! _bfd_elf_merge_section_sframe (output_bfd, info,
|
||||
htab->plt_got_sframe,
|
||||
htab->plt_got_sframe->contents))
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (htab->elf.sgot && htab->elf.sgot->size > 0)
|
||||
elf_section_data (htab->elf.sgot->output_section)->this_hdr.sh_entsize
|
||||
= htab->got_entry_size;
|
||||
@ -4764,7 +4831,18 @@ _bfd_x86_elf_link_setup_gnu_properties
|
||||
|
||||
htab->plt_second_sframe = sec;
|
||||
}
|
||||
/* FIXME - add later for plt_got. */
|
||||
|
||||
/* .plt.got. */
|
||||
if (htab->plt_got != NULL)
|
||||
{
|
||||
sec = bfd_make_section_anyway_with_flags (dynobj,
|
||||
".sframe",
|
||||
flags);
|
||||
if (sec == NULL)
|
||||
info->callbacks->einfo (_("%F%P: failed to create PLT GOT .sframe section\n"));
|
||||
|
||||
htab->plt_got_sframe = sec;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -401,6 +401,10 @@ struct elf_x86_sframe_plt
|
||||
unsigned int sec_pltn_entry_size;
|
||||
unsigned int sec_pltn_num_fres;
|
||||
const sframe_frame_row_entry *sec_pltn_fres[SFRAME_PLTN_MAX_NUM_FRES];
|
||||
|
||||
unsigned int plt_got_entry_size;
|
||||
unsigned int plt_got_num_fres;
|
||||
const sframe_frame_row_entry *plt_got_fres[SFRAME_PLTN_MAX_NUM_FRES];
|
||||
};
|
||||
|
||||
struct elf_x86_lazy_plt_layout
|
||||
@ -606,6 +610,8 @@ struct elf_x86_link_hash_table
|
||||
asection *plt_sframe;
|
||||
sframe_encoder_ctx *plt_second_cfe_ctx;
|
||||
asection *plt_second_sframe;
|
||||
sframe_encoder_ctx *plt_got_cfe_ctx;
|
||||
asection *plt_got_sframe;
|
||||
|
||||
/* Parameters describing PLT generation, lazy or non-lazy. */
|
||||
struct elf_x86_plt_layout plt;
|
||||
|
28
ld/testsuite/ld-x86-64/sframe-pltgot-1.d
Normal file
28
ld/testsuite/ld-x86-64/sframe-pltgot-1.d
Normal file
@ -0,0 +1,28 @@
|
||||
#as: --gsframe
|
||||
#source: sframe-pltgot-1.s
|
||||
#objdump: --sframe=.sframe
|
||||
#ld: -shared -z ibtplt --no-rosegment
|
||||
#name: SFrame for IBT .plt.got
|
||||
|
||||
.*: +file format .*
|
||||
|
||||
Contents of the SFrame section .sframe:
|
||||
Header :
|
||||
|
||||
Version: SFRAME_VERSION_2
|
||||
Flags: SFRAME_F_FDE_SORTED
|
||||
CFA fixed RA offset: \-8
|
||||
#...
|
||||
|
||||
Function Index :
|
||||
|
||||
func idx \[0\]: pc = 0x1000, size = 16 bytes
|
||||
STARTPC +CFA +FP +RA +
|
||||
0+1000 +sp\+16 +u +f +
|
||||
0+1006 +sp\+24 +u +f +
|
||||
|
||||
func idx \[1\]: pc = 0x1010, size = 64 bytes
|
||||
STARTPC\[m\] +CFA +FP +RA +
|
||||
0+0000 +sp\+16 +u +f +
|
||||
|
||||
#...
|
15
ld/testsuite/ld-x86-64/sframe-pltgot-1.s
Normal file
15
ld/testsuite/ld-x86-64/sframe-pltgot-1.s
Normal file
@ -0,0 +1,15 @@
|
||||
.text
|
||||
.globl foo
|
||||
.type foo, @function
|
||||
foo:
|
||||
.cfi_startproc
|
||||
call func1@plt
|
||||
movq func1@GOTPCREL(%rip), %rax
|
||||
call func2@plt
|
||||
movq func2@GOTPCREL(%rip), %rax
|
||||
call func3@plt
|
||||
movq func3@GOTPCREL(%rip), %rax
|
||||
call func4@plt
|
||||
movq func4@GOTPCREL(%rip), %rax
|
||||
.cfi_endproc
|
||||
.section .note.GNU-stack,"",@progbits
|
28
ld/testsuite/ld-x86-64/sframe-pltgot-2.d
Normal file
28
ld/testsuite/ld-x86-64/sframe-pltgot-2.d
Normal file
@ -0,0 +1,28 @@
|
||||
#as: --gsframe
|
||||
#source: sframe-pltgot-1.s
|
||||
#objdump: --sframe=.sframe
|
||||
#ld: -shared --no-rosegment
|
||||
#name: SFrame for .plt.got
|
||||
|
||||
.*: +file format .*
|
||||
|
||||
Contents of the SFrame section .sframe:
|
||||
Header :
|
||||
|
||||
Version: SFRAME_VERSION_2
|
||||
Flags: SFRAME_F_FDE_SORTED
|
||||
CFA fixed RA offset: \-8
|
||||
#...
|
||||
|
||||
Function Index :
|
||||
|
||||
func idx \[0\]: pc = 0x1000, size = 16 bytes
|
||||
STARTPC +CFA +FP +RA +
|
||||
0+1000 +sp\+16 +u +f +
|
||||
0+1006 +sp\+24 +u +f +
|
||||
|
||||
func idx \[1\]: pc = 0x1010, size = 32 bytes
|
||||
STARTPC\[m\] +CFA +FP +RA +
|
||||
0+0000 +sp\+16 +u +f +
|
||||
|
||||
#...
|
@ -549,6 +549,8 @@ if { ![skip_sframe_tests] } {
|
||||
run_dump_test "sframe-simple-1"
|
||||
run_dump_test "sframe-plt-1"
|
||||
run_dump_test "sframe-ibt-plt-1"
|
||||
run_dump_test "sframe-pltgot-1"
|
||||
run_dump_test "sframe-pltgot-2"
|
||||
}
|
||||
|
||||
if ![istarget "x86_64-*-linux*"] {
|
||||
|
Loading…
Reference in New Issue
Block a user