mirror of
https://github.com/bminor/binutils-gdb.git
synced 2025-12-26 09:08:59 +00:00
s390: Generate .eh_frame unwind information for .plt section
Enable unwinding using .eh_frame information through PLT entries. Based on x86-64. This enhances stack traces if the instruction pointer is in a PLT entry. For instance perf call graphs, when using --call-graph=dwarf, and Glibc backtraces, when using backtrace() e.g. from a signal handler. Note that GDB could already unwind through PLT entries using its s390- specific prologue unwinder. Furthermore this lays the foundation to generate SFrame information for the PLT section in the future. bfd/ * elf64-s390.c: Include dwarf2.h. (PLT_CIE_SIZE, PLT_FDE_SIZE, PLT_FDE_START_OFFSET, PLT_FDE_LEN_OFFSET, elf_s390x_eh_frame_plt): New .eh_frame template for .plt section. (elf_s390_link_hash_table): Add plt_eh_frame field. (elf_s390_create_dynamic_sections): New s390-specific wrapper around _bfd_elf_create_dynamic_sections. Create .eh_frame section for .plt section. (elf_backend_create_dynamic_sections): Register s390-specific elf_s390_create_dynamic_sections. (elf_s390_late_size_sections): Fill in .eh_frame section for .plt section. Write .plt section size into .eh_frame FDE covering .plt section. (elf_s390_finish_dynamic_sections): Write .plt section start into .eh_frame FDE covering .plt section. Call _bfd_elf_write_section_eh_frame on on htab->plt_eh_frame section. ld/ * NEWS: Add news entry. * emulparams/elf64_s390.sh: Include plt_unwind.sh. ld/testsuite/ * ld-s390/plt_64-1_eh.wf: New PLT .eh_frame generation test. * ld-s390/s390.exp: Link some existing test cases with --no-ld-generated-unwind-info so that they do not fail. Run new PLT .eh_frame generation test. Signed-off-by: Jens Remus <jremus@linux.ibm.com>
This commit is contained in:
126
bfd/elf64-s390.c
126
bfd/elf64-s390.c
@@ -26,6 +26,7 @@
|
||||
#include "elf-bfd.h"
|
||||
#include "elf/s390.h"
|
||||
#include "elf-s390.h"
|
||||
#include "dwarf2.h"
|
||||
#include <stdarg.h>
|
||||
|
||||
/* In case we're on a 32-bit machine, construct a 64-bit "-1" value
|
||||
@@ -564,6 +565,35 @@ static const bfd_byte elf_s390x_first_plt_entry[PLT_FIRST_ENTRY_SIZE] =
|
||||
0x07, 0x00 /* nopr %r0 */
|
||||
};
|
||||
|
||||
/* .eh_frame covering the .plt section. */
|
||||
|
||||
#define PLT_CIE_SIZE 24
|
||||
#define PLT_FDE_SIZE 20
|
||||
#define PLT_FDE_START_OFFSET (PLT_CIE_SIZE + 8)
|
||||
#define PLT_FDE_LEN_OFFSET (PLT_CIE_SIZE + 12)
|
||||
|
||||
static const bfd_byte elf_s390x_eh_frame_plt[] =
|
||||
{
|
||||
0, 0, 0, PLT_CIE_SIZE - 4, /* CIE length */
|
||||
0, 0, 0, 0, /* CIE ID */
|
||||
1, /* CIE version */
|
||||
'z', 'R', 0, /* Augmentation string */
|
||||
1, /* Code alignment factor */
|
||||
0x78, /* Data alignment factor */
|
||||
14, /* Return address column */
|
||||
1, /* Augmentation size */
|
||||
DW_EH_PE_pcrel | DW_EH_PE_sdata4, /* FDE encoding */
|
||||
DW_CFA_def_cfa, 15, 0xa0, 0x01, /* DW_CFA_def_cfa: r15 ofs 160 */
|
||||
DW_CFA_nop, DW_CFA_nop, DW_CFA_nop,
|
||||
|
||||
0, 0, 0, PLT_FDE_SIZE - 4, /* FDE length */
|
||||
0, 0, 0, PLT_CIE_SIZE + 4, /* CIE pointer */
|
||||
0, 0, 0, 0, /* R_S390_PC32 .plt goes here */
|
||||
0, 0, 0, 0, /* .plt size goes here */
|
||||
0, /* Augmentation size */
|
||||
DW_CFA_nop, DW_CFA_nop, DW_CFA_nop
|
||||
};
|
||||
|
||||
|
||||
/* s390 ELF linker hash entry. */
|
||||
|
||||
@@ -656,6 +686,7 @@ struct elf_s390_link_hash_table
|
||||
|
||||
/* Short-cuts to get to dynamic linker sections. */
|
||||
asection *irelifunc;
|
||||
asection *plt_eh_frame;
|
||||
|
||||
union {
|
||||
bfd_signed_vma refcount;
|
||||
@@ -1852,6 +1883,15 @@ elf_s390_late_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
|
||||
sym dynamic relocs. */
|
||||
elf_link_hash_traverse (&htab->elf, allocate_dynrelocs, info);
|
||||
|
||||
if (_bfd_elf_eh_frame_present (info))
|
||||
{
|
||||
if (htab->plt_eh_frame != NULL
|
||||
&& htab->elf.splt != NULL
|
||||
&& htab->elf.splt->size != 0
|
||||
&& !bfd_is_abs_section (htab->elf.splt->output_section))
|
||||
htab->plt_eh_frame->size = sizeof (elf_s390x_eh_frame_plt);
|
||||
}
|
||||
|
||||
/* We now have determined the sizes of the various dynamic sections.
|
||||
Allocate memory for them. */
|
||||
relocs = false;
|
||||
@@ -1863,6 +1903,7 @@ elf_s390_late_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
|
||||
if (s == htab->elf.splt
|
||||
|| s == htab->elf.sgot
|
||||
|| s == htab->elf.sgotplt
|
||||
|| s == htab->plt_eh_frame
|
||||
|| s == htab->elf.sdynbss
|
||||
|| s == htab->elf.sdynrelro
|
||||
|| s == htab->elf.iplt
|
||||
@@ -1930,6 +1971,16 @@ elf_s390_late_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
|
||||
s->alloced = 1;
|
||||
}
|
||||
|
||||
if (htab->plt_eh_frame != NULL
|
||||
&& htab->plt_eh_frame->contents != NULL)
|
||||
{
|
||||
memcpy (htab->plt_eh_frame->contents,
|
||||
elf_s390x_eh_frame_plt,
|
||||
htab->plt_eh_frame->size);
|
||||
bfd_put_32 (dynobj, htab->elf.splt->size,
|
||||
htab->plt_eh_frame->contents + PLT_FDE_LEN_OFFSET);
|
||||
}
|
||||
|
||||
return _bfd_elf_add_dynamic_tags (output_bfd, info, relocs);
|
||||
}
|
||||
|
||||
@@ -3703,6 +3754,38 @@ elf_s390_finish_dynamic_sections (bfd *output_bfd,
|
||||
}
|
||||
}
|
||||
|
||||
/* Adjust .eh_frame for .plt section. */
|
||||
if (htab->plt_eh_frame != NULL
|
||||
&& htab->plt_eh_frame->contents != NULL)
|
||||
{
|
||||
if (htab->elf.splt != NULL
|
||||
&& htab->elf.splt->size != 0
|
||||
&& (htab->elf.splt->flags & SEC_EXCLUDE) == 0
|
||||
&& htab->elf.splt->output_section != NULL
|
||||
&& htab->plt_eh_frame->output_section != NULL)
|
||||
{
|
||||
bfd_vma plt_start = htab->elf.splt->output_section->vma;
|
||||
bfd_vma eh_frame_start = htab->plt_eh_frame->output_section->vma
|
||||
+ htab->plt_eh_frame->output_offset
|
||||
+ PLT_FDE_START_OFFSET;
|
||||
/* Note: Linker may have discarded the FDE, so that store may
|
||||
be beyond current htab->plt_eh_frame->size. Can be ignored,
|
||||
as htab->plt_eh_frame->contents got allocated with
|
||||
sizeof (elf_s390x_eh_frame_plt). See PR 12570. */
|
||||
bfd_put_signed_32 (dynobj, plt_start - eh_frame_start,
|
||||
htab->plt_eh_frame->contents
|
||||
+ PLT_FDE_START_OFFSET);
|
||||
}
|
||||
|
||||
if (htab->plt_eh_frame->sec_info_type == SEC_INFO_TYPE_EH_FRAME)
|
||||
{
|
||||
if (! _bfd_elf_write_section_eh_frame (output_bfd, info,
|
||||
htab->plt_eh_frame,
|
||||
htab->plt_eh_frame->contents))
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -3926,6 +4009,47 @@ bfd_elf_s390_set_options (struct bfd_link_info *info,
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Create .plt, .rela.plt, .got, .got.plt, .rela.got, .dynbss, and
|
||||
.rela.bss sections in DYNOBJ, and set up shortcuts to them in our
|
||||
hash table. */
|
||||
|
||||
static bool
|
||||
elf_s390_create_dynamic_sections (bfd *dynobj,
|
||||
struct bfd_link_info *info)
|
||||
{
|
||||
struct elf_s390_link_hash_table *htab;
|
||||
|
||||
if (!_bfd_elf_create_dynamic_sections (dynobj, info))
|
||||
return false;
|
||||
|
||||
htab = elf_s390_hash_table (info);
|
||||
if (htab == NULL)
|
||||
return false;
|
||||
|
||||
if (htab->elf.splt != NULL)
|
||||
{
|
||||
/* Create .eh_frame section for .plt section. */
|
||||
if (!info->no_ld_generated_unwind_info)
|
||||
{
|
||||
flagword flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY
|
||||
| SEC_HAS_CONTENTS | SEC_IN_MEMORY
|
||||
| SEC_LINKER_CREATED);
|
||||
|
||||
if (htab->plt_eh_frame == NULL)
|
||||
{
|
||||
htab->plt_eh_frame
|
||||
= bfd_make_section_anyway_with_flags (dynobj,
|
||||
".eh_frame",
|
||||
flags);
|
||||
if (htab->plt_eh_frame == NULL
|
||||
|| !bfd_set_section_alignment (htab->plt_eh_frame, 3))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Why was the hash table entry size definition changed from
|
||||
ARCH_SIZE/8 to 4? This breaks the 64 bit dynamic linker and
|
||||
@@ -3992,7 +4116,7 @@ const struct elf_size_info s390_elf64_size_info =
|
||||
#define elf_backend_adjust_dynamic_symbol elf_s390_adjust_dynamic_symbol
|
||||
#define elf_backend_check_relocs elf_s390_check_relocs
|
||||
#define elf_backend_copy_indirect_symbol elf_s390_copy_indirect_symbol
|
||||
#define elf_backend_create_dynamic_sections _bfd_elf_create_dynamic_sections
|
||||
#define elf_backend_create_dynamic_sections elf_s390_create_dynamic_sections
|
||||
#define elf_backend_finish_dynamic_sections elf_s390_finish_dynamic_sections
|
||||
#define elf_backend_finish_dynamic_symbol elf_s390_finish_dynamic_symbol
|
||||
#define elf_backend_gc_mark_hook elf_s390_gc_mark_hook
|
||||
|
||||
6
ld/NEWS
6
ld/NEWS
@@ -1,5 +1,11 @@
|
||||
-*- text -*-
|
||||
|
||||
* On s390, generate ".eh_frame" unwind information for the linker generated
|
||||
.plt section. Enabled by default. Can be disabled using linker option
|
||||
--no-ld-generated-unwind-info.
|
||||
|
||||
* On s390, add support for linker option --[no-]ld-generated-unwind-info.
|
||||
|
||||
Changes in 2.44:
|
||||
|
||||
* Support for Nios II target has been removed, as this architecture has been
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
source_sh ${srcdir}/emulparams/plt_unwind.sh
|
||||
SCRIPT_NAME=elf
|
||||
ELFSIZE=64
|
||||
OUTPUT_FORMAT="elf64-s390"
|
||||
|
||||
31
ld/testsuite/ld-s390/plt_64-1_eh.wf
Normal file
31
ld/testsuite/ld-s390/plt_64-1_eh.wf
Normal file
@@ -0,0 +1,31 @@
|
||||
#source: plt_64-1.s
|
||||
#as: -m64
|
||||
#ld: -m elf64_s390
|
||||
#readelf: -wf
|
||||
#target: s390x-*-*
|
||||
|
||||
Contents of the .eh_frame section:
|
||||
|
||||
|
||||
00000000 0000000000000014 00000000 CIE
|
||||
Version: 1
|
||||
Augmentation: "zR"
|
||||
Code alignment factor: 1
|
||||
Data alignment factor: -8
|
||||
Return address column: 14
|
||||
Augmentation data: 1b
|
||||
DW_CFA_def_cfa: r15 ofs 160
|
||||
DW_CFA_nop
|
||||
DW_CFA_nop
|
||||
DW_CFA_nop
|
||||
|
||||
00000018 0000000000000014 0000001c FDE cie=00000000 pc=0000000001000258..00000000010002b8
|
||||
DW_CFA_nop
|
||||
DW_CFA_nop
|
||||
DW_CFA_nop
|
||||
DW_CFA_nop
|
||||
DW_CFA_nop
|
||||
DW_CFA_nop
|
||||
DW_CFA_nop
|
||||
|
||||
#...
|
||||
@@ -74,7 +74,7 @@ set s390tests {
|
||||
}
|
||||
|
||||
set s390xtests {
|
||||
{"TLS -fpic -shared transitions" "-shared -melf64_s390 --hash-style=sysv" ""
|
||||
{"TLS -fpic -shared transitions" "-shared -melf64_s390 --hash-style=sysv --no-ld-generated-unwind-info" ""
|
||||
"-m64 -Aesame" {tlspic1_64.s tlspic2_64.s}
|
||||
{{readelf -WSsrl tlspic_64.rd} {objdump -dzrj.text tlspic_64.dd}
|
||||
{objdump -sj.got tlspic_64.sd} {objdump -sj.tdata tlspic_64.td}}
|
||||
@@ -82,7 +82,7 @@ set s390xtests {
|
||||
{"Helper shared library" "-shared -melf64_s390" ""
|
||||
"-m64 -Aesame" {tlslib_64.s} {} "libtlslib_64.so"}
|
||||
{"TLS -fpic and -fno-pic exec transitions"
|
||||
"-melf64_s390 tmpdir/libtlslib_64.so --hash-style=sysv" ""
|
||||
"-melf64_s390 tmpdir/libtlslib_64.so --hash-style=sysv --no-ld-generated-unwind-info" ""
|
||||
"-m64 -Aesame" {tlsbinpic_64.s tlsbin_64.s}
|
||||
{{readelf -WSsrl tlsbin_64.rd} {objdump -dzrj.text tlsbin_64.dd}
|
||||
{objdump -sj.got tlsbin_64.sd} {objdump -sj.tdata tlsbin_64.td}}
|
||||
@@ -117,10 +117,14 @@ set s390xtests {
|
||||
"-shared -m elf64_s390" "" "-m64" {pltlib.s}
|
||||
{}
|
||||
"libpltlib_64.so"}
|
||||
{"PLT: PLT generation"
|
||||
"-m elf64_s390 tmpdir/libpltlib_64.so" "" "-m64" {plt_64-1.s}
|
||||
{"PLT: PLT generation without .eh_frame unwind info"
|
||||
"-m elf64_s390 tmpdir/libpltlib_64.so --no-ld-generated-unwind-info" "" "-m64" {plt_64-1.s}
|
||||
{{objdump "-dzrj.plt" plt_64-1.pd} {readelf "-wf" plt_64-1.wf}}
|
||||
"plt_64-1"}
|
||||
{"PLT: PLT generation with .eh_frame unwind info"
|
||||
"-m elf64_s390 tmpdir/libpltlib_64.so" "" "-m64" {plt_64-1.s}
|
||||
{{objdump "-dzrj.plt" plt_64-1.pd} {readelf "-wf" plt_64-1_eh.wf}}
|
||||
"plt_64-1_eh"}
|
||||
}
|
||||
|
||||
if [istarget "s390-*-*"] {
|
||||
|
||||
Reference in New Issue
Block a user