aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosh Poimboeuf <jpoimboe@kernel.org>2024-10-22 15:39:46 -0700
committerIndu Bhagat <indu.bhagat@oracle.com>2024-10-30 08:41:32 -0700
commita36d6ffd9be00657c0e2e650e8a6f7b8433cb4d3 (patch)
treed5c8c553aabdccd941b183e455ad2cc3cd2b6c61
parent395515de82fbc9d1c34ca77d742c8bd6504154b5 (diff)
downloadgdb-a36d6ffd9be00657c0e2e650e8a6f7b8433cb4d3.zip
gdb-a36d6ffd9be00657c0e2e650e8a6f7b8433cb4d3.tar.gz
gdb-a36d6ffd9be00657c0e2e650e8a6f7b8433cb4d3.tar.bz2
ld: fix wrong SFrame info for lazy IBT PLT
Fix PR/32296 sframe: wrong SFrame info for pltN and .plt.sec for -z ibtplt The x86 psABI defines a 2-PLT scheme for IBT which uses .plt and .plt.sec entries. It was observed that SFrame information for .plt.sec section was incorrect. The erroneous assumption was that SFrame stack trace information for .plt.sec with lazy binding is the same as SFrame stack trace information for .plt with lazy binding. This is corrected now by initializing a new SFrame PLT helper object elf_x86_64_sframe_ibt_plt for lazy PLT with IBT. Add a testcase where linking with -z ibtplt generates .plt.sec entries and ensure correct SFrame information for it. ChangeLog: PR/32296 * bfd/elf64-x86-64.c (elf_x86_64_sframe_ibt_pltn_fre2): New definition elf_x86_64_sframe_ibt_plt. Use it in elf_x86_64_sframe_plt. (elf_x86_64_link_setup_gnu_properties): Lazy IBT PLT entries are different from lazy PLT. * bfd/elfxx-x86.c (_bfd_x86_elf_create_sframe_plt): Adjust for SFrame for IBT PLT. * ld/testsuite/ld-x86-64/x86-64.exp: Add new test. * ld/testsuite/ld-x86-64/sframe-ibt-plt-1.d: New test.
-rw-r--r--bfd/elf64-x86-64.c34
-rw-r--r--bfd/elfxx-x86.c29
-rw-r--r--ld/testsuite/ld-x86-64/sframe-ibt-plt-1.d33
-rw-r--r--ld/testsuite/ld-x86-64/x86-64.exp1
4 files changed, 79 insertions, 18 deletions
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index 4330bbd..abbebbe 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -906,6 +906,14 @@ static const sframe_frame_row_entry elf_x86_64_sframe_pltn_fre2 =
SFRAME_V1_FRE_INFO (SFRAME_BASE_REG_SP, 1, SFRAME_FRE_OFFSET_1B) /* FRE info. */
};
+/* .sframe FRE covering the .plt section entry for IBT. */
+static const sframe_frame_row_entry elf_x86_64_sframe_ibt_pltn_fre2 =
+{
+ 9, /* SFrame FRE start address. */
+ {16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* 12 bytes. */
+ SFRAME_V1_FRE_INFO (SFRAME_BASE_REG_SP, 1, SFRAME_FRE_OFFSET_1B) /* FRE info. */
+};
+
/* .sframe FRE covering the second .plt section entry. */
static const sframe_frame_row_entry elf_x86_64_sframe_sec_pltn_fre1 =
{
@@ -930,7 +938,7 @@ static const struct elf_x86_sframe_plt elf_x86_64_sframe_non_lazy_plt =
{ &elf_x86_64_sframe_null_fre }
};
-/* SFrame helper object for lazy PLT. Also used for IBT enabled PLT. */
+/* SFrame helper object for lazy PLT. */
static const struct elf_x86_sframe_plt elf_x86_64_sframe_plt =
{
LAZY_PLT_ENTRY_SIZE,
@@ -942,9 +950,25 @@ static const struct elf_x86_sframe_plt elf_x86_64_sframe_plt =
/* Array of SFrame FREs for plt. */
{ &elf_x86_64_sframe_pltn_fre1, &elf_x86_64_sframe_pltn_fre2 },
NON_LAZY_PLT_ENTRY_SIZE,
- 1, /* Number of FREs for PLTn for second PLT. */
- /* FREs for second plt (stack trace info for .plt.got is
- identical). Used when IBT or non-lazy PLT is in effect. */
+ 1, /* Number of FREs for second PLT. */
+ /* Array of SFrame FREs for second PLT. */
+ { &elf_x86_64_sframe_sec_pltn_fre1 }
+};
+
+/* SFrame helper object for lazy PLT with IBT. */
+static const struct elf_x86_sframe_plt elf_x86_64_sframe_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,
+ 2, /* Number of FREs for PLTn. */
+ /* Array of SFrame FREs for plt. */
+ { &elf_x86_64_sframe_pltn_fre1, &elf_x86_64_sframe_ibt_pltn_fre2 },
+ 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 }
};
@@ -5678,7 +5702,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_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;
}
else
diff --git a/bfd/elfxx-x86.c b/bfd/elfxx-x86.c
index 0d83ce5..cb90f68 100644
--- a/bfd/elfxx-x86.c
+++ b/bfd/elfxx-x86.c
@@ -1831,7 +1831,6 @@ _bfd_x86_elf_create_sframe_plt (bfd *output_bfd,
struct elf_x86_link_hash_table *htab;
const struct elf_backend_data *bed;
- bool plt0_generated_p;
unsigned int plt0_entry_size;
unsigned char func_info;
uint32_t fre_type;
@@ -1845,14 +1844,11 @@ _bfd_x86_elf_create_sframe_plt (bfd *output_bfd,
unsigned plt_entry_size = 0;
unsigned int num_pltn_fres = 0;
unsigned int num_pltn_entries = 0;
+ const sframe_frame_row_entry * const *pltn_fres;
bed = get_elf_backend_data (output_bfd);
htab = elf_x86_hash_table (info, bed->target_id);
/* Whether SFrame stack trace info for plt0 is to be generated. */
- plt0_generated_p = htab->plt.has_plt0;
- plt0_entry_size
- = (plt0_generated_p) ? htab->sframe_plt->plt0_entry_size : 0;
-
switch (plt_sec_type)
{
case SFRAME_PLT:
@@ -1860,7 +1856,10 @@ _bfd_x86_elf_create_sframe_plt (bfd *output_bfd,
ectx = &htab->plt_cfe_ctx;
dpltsec = htab->elf.splt;
- plt_entry_size = htab->plt.plt_entry_size;
+ plt0_entry_size
+ = htab->plt.has_plt0 ? htab->sframe_plt->plt0_entry_size : 0;
+ plt_entry_size = htab->sframe_plt->pltn_entry_size;
+ pltn_fres = htab->sframe_plt->pltn_fres;
num_pltn_fres = htab->sframe_plt->pltn_num_fres;
num_pltn_entries
= (dpltsec->size - plt0_entry_size) / plt_entry_size;
@@ -1870,12 +1869,15 @@ _bfd_x86_elf_create_sframe_plt (bfd *output_bfd,
case SFRAME_PLT_SEC:
{
ectx = &htab->plt_second_cfe_ctx;
- /* FIXME - this or htab->plt_second_sframe ? */
- dpltsec = htab->plt_second_eh_frame;
+ dpltsec = htab->plt_second;
+
+ plt0_entry_size = 0;
plt_entry_size = htab->sframe_plt->sec_pltn_entry_size;
+ pltn_fres = htab->sframe_plt->sec_pltn_fres;
num_pltn_fres = htab->sframe_plt->sec_pltn_num_fres;
num_pltn_entries = dpltsec->size / plt_entry_size;
+
break;
}
default:
@@ -1897,7 +1899,7 @@ _bfd_x86_elf_create_sframe_plt (bfd *output_bfd,
/* Add SFrame FDE and the associated FREs for plt0 if plt0 has been
generated. */
- if (plt0_generated_p)
+ if (plt0_entry_size)
{
/* Add SFrame FDE for plt0, the function start address is updated later
at _bfd_elf_merge_section_sframe time. */
@@ -1934,16 +1936,17 @@ _bfd_x86_elf_create_sframe_plt (bfd *output_bfd,
plt0_entry_size, /* func start addr. */
dpltsec->size - plt0_entry_size,
func_info,
- 16,
+ plt_entry_size,
0 /* Num FREs. */);
sframe_frame_row_entry pltn_fre;
- /* Now add the FREs for pltn. Simply adding the two FREs suffices due
+ /* Now add the FREs for pltn. Simply adding the FREs suffices due
to the usage of SFRAME_FDE_TYPE_PCMASK above. */
for (unsigned int j = 0; j < num_pltn_fres; j++)
{
- pltn_fre = *(htab->sframe_plt->pltn_fres[j]);
- sframe_encoder_add_fre (*ectx, 1, &pltn_fre);
+ unsigned int func_idx = plt0_entry_size ? 1 : 0;
+ pltn_fre = *(pltn_fres[j]);
+ sframe_encoder_add_fre (*ectx, func_idx, &pltn_fre);
}
}
diff --git a/ld/testsuite/ld-x86-64/sframe-ibt-plt-1.d b/ld/testsuite/ld-x86-64/sframe-ibt-plt-1.d
new file mode 100644
index 0000000..26be4df
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/sframe-ibt-plt-1.d
@@ -0,0 +1,33 @@
+#as: --gsframe
+#source: ibt-plt-3.s
+#objdump: --sframe=.sframe
+#ld: -shared -z ibtplt --no-rosegment
+#name: SFrame for IBT PLT .plt.sec
+
+.*: +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\+8 +u +f +
+ 0+0009 +sp\+16 +u +f +
+
+ func idx \[2\]: pc = 0x1030, size = 32 bytes
+ STARTPC\[m\] +CFA +FP +RA +
+ 0+0000 +sp\+8 +u +f +
+
+#...
diff --git a/ld/testsuite/ld-x86-64/x86-64.exp b/ld/testsuite/ld-x86-64/x86-64.exp
index bd7574d..0632397 100644
--- a/ld/testsuite/ld-x86-64/x86-64.exp
+++ b/ld/testsuite/ld-x86-64/x86-64.exp
@@ -547,6 +547,7 @@ run_dump_test "pr32191-x32"
if { ![skip_sframe_tests] } {
run_dump_test "sframe-simple-1"
run_dump_test "sframe-plt-1"
+ run_dump_test "sframe-ibt-plt-1"
}
if ![istarget "x86_64-*-linux*"] {