aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIndu Bhagat <indu.bhagat@oracle.com>2024-10-22 23:04:26 -0700
committerIndu Bhagat <indu.bhagat@oracle.com>2024-10-30 08:42:25 -0700
commit5ab84cb8c82f4b61eb72728cc9b4bd9a11bc9c15 (patch)
treec2536b9e82d29dc1754bebfff63b0802bd7078b9
parenta36d6ffd9be00657c0e2e650e8a6f7b8433cb4d3 (diff)
downloadgdb-users/ibhagat/try-sframe-plt-fixes.zip
gdb-users/ibhagat/try-sframe-plt-fixes.tar.gz
gdb-users/ibhagat/try-sframe-plt-fixes.tar.bz2
ld: generate SFrame stack trace info for .plt.gotusers/ibhagat/try-sframe-plt-fixes
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.
-rw-r--r--bfd/elf64-x86-64.c42
-rw-r--r--bfd/elfxx-x86.c86
-rw-r--r--bfd/elfxx-x86.h6
-rw-r--r--ld/testsuite/ld-x86-64/sframe-pltgot-1.d28
-rw-r--r--ld/testsuite/ld-x86-64/sframe-pltgot-1.s15
-rw-r--r--ld/testsuite/ld-x86-64/sframe-pltgot-2.d28
-rw-r--r--ld/testsuite/ld-x86-64/x86-64.exp2
7 files changed, 198 insertions, 9 deletions
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index abbebbe..a62fa62 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -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
{
diff --git a/bfd/elfxx-x86.c b/bfd/elfxx-x86.c
index cb90f68..0843803 100644
--- a/bfd/elfxx-x86.c
+++ b/bfd/elfxx-x86.c
@@ -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;
+ }
}
}
diff --git a/bfd/elfxx-x86.h b/bfd/elfxx-x86.h
index b042d45..cd26e8f 100644
--- a/bfd/elfxx-x86.h
+++ b/bfd/elfxx-x86.h
@@ -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;
diff --git a/ld/testsuite/ld-x86-64/sframe-pltgot-1.d b/ld/testsuite/ld-x86-64/sframe-pltgot-1.d
new file mode 100644
index 0000000..23ff5d5
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/sframe-pltgot-1.d
@@ -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 +
+
+#...
diff --git a/ld/testsuite/ld-x86-64/sframe-pltgot-1.s b/ld/testsuite/ld-x86-64/sframe-pltgot-1.s
new file mode 100644
index 0000000..e596e84
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/sframe-pltgot-1.s
@@ -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
diff --git a/ld/testsuite/ld-x86-64/sframe-pltgot-2.d b/ld/testsuite/ld-x86-64/sframe-pltgot-2.d
new file mode 100644
index 0000000..7a99d12
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/sframe-pltgot-2.d
@@ -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 +
+
+#...
diff --git a/ld/testsuite/ld-x86-64/x86-64.exp b/ld/testsuite/ld-x86-64/x86-64.exp
index 0632397..a66d28e 100644
--- a/ld/testsuite/ld-x86-64/x86-64.exp
+++ b/ld/testsuite/ld-x86-64/x86-64.exp
@@ -548,6 +548,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*"] {