This is the mail archive of the
binutils-cvs@sourceware.org
mailing list for the binutils project.
[binutils-gdb/binutils-2_28-branch] i386/x86-64: Add unwind info for .plt.got section
- From: H.J.Lu <hjl at sourceware dot org>
- To: bfd-cvs at sourceware dot org
- Date: 13 Jan 2017 16:28:26 -0000
- Subject: [binutils-gdb/binutils-2_28-branch] i386/x86-64: Add unwind info for .plt.got section
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=326e3a04a5fa4fbf85b4cc4188a355d2715e5d17
commit 326e3a04a5fa4fbf85b4cc4188a355d2715e5d17
Author: H.J. Lu <hjl.tools@gmail.com>
Date: Tue Jan 10 13:31:59 2017 -0800
i386/x86-64: Add unwind info for .plt.got section
When there are both PLT and GOT references to the same function symbol,
linker combines GOTPLT and GOT slots into a single GOT slot and create
an entry in .plt.got section for PLT access via the GOT slot. This
patch adds unwind info for .plt.got section and places .plt.got section
after .plt section for x32. .eh_frame section covering PLT sections
should be aligned to 4 bytes for i386 and x32.
bfd/
2017-01-13 H.J. Lu <hongjiu.lu@intel.com>
Backport from master
2017-01-10 H.J. Lu <hongjiu.lu@intel.com>
* elf32-i386.c (elf_i386_check_relocs): Align .eh_frame section
to 4 bytes.
* elf64-x86-64.c (elf_x86_64_create_dynamic_sections): Align
.eh_frame section to 4 bytes for x32.
(elf_x86_64_check_relocs): Likewise.
2017-01-10 H.J. Lu <hongjiu.lu@intel.com>
PR ld/20830
* elf32-i386.c (elf_i386_eh_frame_plt_got): New.
(PLT_GOT_FDE_LENGTH): Likewise.
(elf_i386_plt_layout): Add eh_frame_plt_got and
eh_frame_plt_got_size.
(elf_i386_plt): Updated.
(elf_i386_link_hash_table): Add plt_got_eh_frame.
(elf_i386_check_relocs): Create .eh_frame section for .plt.got.
(elf_i386_size_dynamic_sections): Allocate and initialize
.eh_frame section for .plt.got.
(elf_i386_finish_dynamic_sections): Adjust .eh_frame section for
.plt.got.
(elf_i386_nacl_plt): Add FIXME for eh_frame_plt_got and
eh_frame_plt_got_size.
* elf64-x86-64.c (elf_x86_64_eh_frame_plt_got): New.
(PLT_GOT_FDE_LENGTH): Likewise.
(elf_x86_64_backend_data): Add eh_frame_plt_got and
eh_frame_plt_got_size.
(elf_x86_64_arch_bed): Updated.
(elf_x86_64_bnd_arch_bed): Add FIXME for eh_frame_plt_got and
eh_frame_plt_got_size.
(elf_x86_64_nacl_arch_bed): Likewise.
(elf_x86_64_link_hash_table): Add plt_got_eh_frame.
(elf_x86_64_check_relocs): Create .eh_frame section for .plt.got.
(elf_x86_64_size_dynamic_sections): Allocate and initialize
.eh_frame section for .plt.got.
(elf_x86_64_finish_dynamic_sections): Adjust .eh_frame section
for .plt.got.
ld/
2017-01-13 H.J. Lu <hongjiu.lu@intel.com>
Backport from master
2017-01-10 H.J. Lu <hongjiu.lu@intel.com>
* testsuite/ld-x86-64/pr20830b.d: Updated.
2017-01-10 H.J. Lu <hongjiu.lu@intel.com>
* emulparams/elf32_x86_64.sh (TINY_READONLY_SECTION): New.
* testsuite/ld-x86-64/pr20830.d: Renamed to ...
* testsuite/ld-x86-64/pr20830a.d: This. Updated.
* testsuite/ld-x86-64/pr20830b.d: New file.
* testsuite/ld-x86-64/x86-64.exp: Rename pr20830 to pr20830a.
Run pr20830b.
2017-01-10 H.J. Lu <hongjiu.lu@intel.com>
PR ld/20830
* testsuite/ld-i386/i386.exp: Run pr20830.
* testsuite/ld-x86-64/x86-64.exp: Likewise.
* testsuite/ld-i386/pr20830.d: New file.
* testsuite/ld-i386/pr20830.s: Likewise.
* testsuite/ld-x86-64/pr20830.d: Likewise.
* testsuite/ld-x86-64/pr20830.s: Likewise.
Diff:
---
bfd/ChangeLog | 42 ++++++++++++
bfd/elf32-i386.c | 116 ++++++++++++++++++++++++++++++---
bfd/elf64-x86-64.c | 131 +++++++++++++++++++++++++++++++++++---
ld/ChangeLog | 26 ++++++++
ld/emulparams/elf32_x86_64.sh | 4 ++
ld/testsuite/ld-i386/i386.exp | 1 +
ld/testsuite/ld-i386/pr20830.d | 60 +++++++++++++++++
ld/testsuite/ld-i386/pr20830.s | 8 +++
ld/testsuite/ld-x86-64/pr20830.s | 8 +++
ld/testsuite/ld-x86-64/pr20830a.d | 72 +++++++++++++++++++++
ld/testsuite/ld-x86-64/pr20830b.d | 60 +++++++++++++++++
ld/testsuite/ld-x86-64/x86-64.exp | 2 +
12 files changed, 513 insertions(+), 17 deletions(-)
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 7f9e4ef..f1fd51f 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -3,6 +3,48 @@
Backport from master
2017-01-10 H.J. Lu <hongjiu.lu@intel.com>
+ * elf32-i386.c (elf_i386_check_relocs): Align .eh_frame section
+ to 4 bytes.
+ * elf64-x86-64.c (elf_x86_64_create_dynamic_sections): Align
+ .eh_frame section to 4 bytes for x32.
+ (elf_x86_64_check_relocs): Likewise.
+
+ 2017-01-10 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR ld/20830
+ * elf32-i386.c (elf_i386_eh_frame_plt_got): New.
+ (PLT_GOT_FDE_LENGTH): Likewise.
+ (elf_i386_plt_layout): Add eh_frame_plt_got and
+ eh_frame_plt_got_size.
+ (elf_i386_plt): Updated.
+ (elf_i386_link_hash_table): Add plt_got_eh_frame.
+ (elf_i386_check_relocs): Create .eh_frame section for .plt.got.
+ (elf_i386_size_dynamic_sections): Allocate and initialize
+ .eh_frame section for .plt.got.
+ (elf_i386_finish_dynamic_sections): Adjust .eh_frame section for
+ .plt.got.
+ (elf_i386_nacl_plt): Add FIXME for eh_frame_plt_got and
+ eh_frame_plt_got_size.
+ * elf64-x86-64.c (elf_x86_64_eh_frame_plt_got): New.
+ (PLT_GOT_FDE_LENGTH): Likewise.
+ (elf_x86_64_backend_data): Add eh_frame_plt_got and
+ eh_frame_plt_got_size.
+ (elf_x86_64_arch_bed): Updated.
+ (elf_x86_64_bnd_arch_bed): Add FIXME for eh_frame_plt_got and
+ eh_frame_plt_got_size.
+ (elf_x86_64_nacl_arch_bed): Likewise.
+ (elf_x86_64_link_hash_table): Add plt_got_eh_frame.
+ (elf_x86_64_check_relocs): Create .eh_frame section for .plt.got.
+ (elf_x86_64_size_dynamic_sections): Allocate and initialize
+ .eh_frame section for .plt.got.
+ (elf_x86_64_finish_dynamic_sections): Adjust .eh_frame section
+ for .plt.got.
+
+2017-01-13 H.J. Lu <hongjiu.lu@intel.com>
+
+ Backport from master
+ 2017-01-10 H.J. Lu <hongjiu.lu@intel.com>
+
* elf32-i386.c (elf_i386_size_dynamic_sections): Set
plt_eh_frame->size to eh_frame_plt_size and use eh_frame_plt.
diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c
index a2da987..0860ada 100644
--- a/bfd/elf32-i386.c
+++ b/bfd/elf32-i386.c
@@ -648,6 +648,32 @@ static const bfd_byte elf_i386_eh_frame_plt[] =
DW_CFA_nop, DW_CFA_nop, DW_CFA_nop, DW_CFA_nop
};
+/* .eh_frame covering the .plt.got section. */
+
+static const bfd_byte elf_i386_eh_frame_plt_got[] =
+{
+#define PLT_GOT_FDE_LENGTH 16
+ PLT_CIE_LENGTH, 0, 0, 0, /* CIE length */
+ 0, 0, 0, 0, /* CIE ID */
+ 1, /* CIE version */
+ 'z', 'R', 0, /* Augmentation string */
+ 1, /* Code alignment factor */
+ 0x7c, /* Data alignment factor */
+ 8, /* Return address column */
+ 1, /* Augmentation size */
+ DW_EH_PE_pcrel | DW_EH_PE_sdata4, /* FDE encoding */
+ DW_CFA_def_cfa, 4, 4, /* DW_CFA_def_cfa: r4 (esp) ofs 4 */
+ DW_CFA_offset + 8, 1, /* DW_CFA_offset: r8 (eip) at cfa-4 */
+ DW_CFA_nop, DW_CFA_nop,
+
+ PLT_GOT_FDE_LENGTH, 0, 0, 0, /* FDE length */
+ PLT_CIE_LENGTH + 8, 0, 0, 0, /* CIE pointer */
+ 0, 0, 0, 0, /* the start of .plt.got goes here */
+ 0, 0, 0, 0, /* .plt.got size goes here */
+ 0, /* Augmentation size */
+ DW_CFA_nop, DW_CFA_nop, DW_CFA_nop
+};
+
struct elf_i386_plt_layout
{
/* The first entry in an absolute procedure linkage table looks like this. */
@@ -679,6 +705,10 @@ struct elf_i386_plt_layout
/* .eh_frame covering the .plt section. */
const bfd_byte *eh_frame_plt;
unsigned int eh_frame_plt_size;
+
+ /* .eh_frame covering the .plt.got section. */
+ const bfd_byte *eh_frame_plt_got;
+ unsigned int eh_frame_plt_got_size;
};
#define GET_PLT_ENTRY_SIZE(abfd) \
@@ -701,6 +731,8 @@ static const struct elf_i386_plt_layout elf_i386_plt =
elf_i386_pic_plt_entry, /* pic_plt_entry */
elf_i386_eh_frame_plt, /* eh_frame_plt */
sizeof (elf_i386_eh_frame_plt), /* eh_frame_plt_size */
+ elf_i386_eh_frame_plt_got, /* eh_frame_plt_got */
+ sizeof (elf_i386_eh_frame_plt_got), /* eh_frame_plt_got_size */
};
@@ -850,6 +882,7 @@ struct elf_i386_link_hash_table
asection *interp;
asection *plt_eh_frame;
asection *plt_got;
+ asection *plt_got_eh_frame;
union
{
@@ -2347,6 +2380,24 @@ do_size:
htab->plt_got,
plt_got_align))
goto error_return;
+
+ if (!info->no_ld_generated_unwind_info
+ && htab->plt_got_eh_frame == NULL
+ && get_elf_i386_backend_data (abfd)->plt->eh_frame_plt_got != NULL)
+ {
+ flagword flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY
+ | SEC_HAS_CONTENTS | SEC_IN_MEMORY
+ | SEC_LINKER_CREATED);
+ htab->plt_got_eh_frame
+ = bfd_make_section_anyway_with_flags (htab->elf.dynobj,
+ ".eh_frame",
+ flags);
+ if (htab->plt_got_eh_frame == NULL
+ || !bfd_set_section_alignment (htab->elf.dynobj,
+ htab->plt_got_eh_frame,
+ 2))
+ goto error_return;
+ }
}
if (r_type == R_386_GOT32X
@@ -3379,14 +3430,22 @@ elf_i386_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
htab->elf.sgotplt->size = 0;
}
-
- if (htab->plt_eh_frame != NULL
- && htab->elf.splt != NULL
- && htab->elf.splt->size != 0
- && !bfd_is_abs_section (htab->elf.splt->output_section)
- && _bfd_elf_eh_frame_present (info))
- htab->plt_eh_frame->size
- = get_elf_i386_backend_data (output_bfd)->plt->eh_frame_plt_size;
+ 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
+ = get_elf_i386_backend_data (output_bfd)->plt->eh_frame_plt_size;
+
+ if (htab->plt_got_eh_frame != NULL
+ && htab->plt_got != NULL
+ && htab->plt_got->size != 0
+ && !bfd_is_abs_section (htab->plt_got->output_section))
+ htab->plt_got_eh_frame->size
+ = get_elf_i386_backend_data (output_bfd)->plt->eh_frame_plt_got_size;
+ }
/* We now have determined the sizes of the various dynamic sections.
Allocate memory for them. */
@@ -3415,6 +3474,7 @@ elf_i386_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
|| s == htab->elf.igotplt
|| s == htab->plt_got
|| s == htab->plt_eh_frame
+ || s == htab->plt_got_eh_frame
|| s == htab->elf.sdynbss
|| s == htab->elf.sdynrelro)
{
@@ -3476,6 +3536,17 @@ elf_i386_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
htab->plt_eh_frame->contents + PLT_FDE_LEN_OFFSET);
}
+ if (htab->plt_got_eh_frame != NULL
+ && htab->plt_got_eh_frame->contents != NULL)
+ {
+ memcpy (htab->plt_got_eh_frame->contents,
+ get_elf_i386_backend_data (output_bfd)->plt->eh_frame_plt_got,
+ htab->plt_got_eh_frame->size);
+ bfd_put_32 (dynobj, htab->plt_got->size,
+ (htab->plt_got_eh_frame->contents
+ + PLT_FDE_LEN_OFFSET));
+ }
+
if (htab->elf.dynamic_sections_created)
{
/* Add some entries to the .dynamic section. We fill in the
@@ -5885,6 +5956,33 @@ elf_i386_finish_dynamic_sections (bfd *output_bfd,
}
}
+ /* Adjust .eh_frame for .plt.got section. */
+ if (htab->plt_got_eh_frame != NULL
+ && htab->plt_got_eh_frame->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_eh_frame->output_section != NULL)
+ {
+ bfd_vma plt_start = htab->plt_got->output_section->vma;
+ bfd_vma eh_frame_start = htab->plt_got_eh_frame->output_section->vma
+ + htab->plt_got_eh_frame->output_offset
+ + PLT_FDE_START_OFFSET;
+ bfd_put_signed_32 (dynobj, plt_start - eh_frame_start,
+ htab->plt_got_eh_frame->contents
+ + PLT_FDE_START_OFFSET);
+ }
+ if (htab->plt_got_eh_frame->sec_info_type == SEC_INFO_TYPE_EH_FRAME)
+ {
+ if (! _bfd_elf_write_section_eh_frame (output_bfd, info,
+ htab->plt_got_eh_frame,
+ htab->plt_got_eh_frame->contents))
+ return FALSE;
+ }
+ }
+
if (htab->elf.sgot && htab->elf.sgot->size > 0)
elf_section_data (htab->elf.sgot->output_section)->this_hdr.sh_entsize = 4;
@@ -6428,6 +6526,8 @@ static const struct elf_i386_plt_layout elf_i386_nacl_plt =
elf_i386_nacl_pic_plt_entry, /* pic_plt_entry */
elf_i386_nacl_eh_frame_plt, /* eh_frame_plt */
sizeof (elf_i386_nacl_eh_frame_plt),/* eh_frame_plt_size */
+ NULL, /* eh_frame_plt_got */
+ 0, /* eh_frame_plt_got_size */
};
static const struct elf_i386_backend_data elf_i386_nacl_arch_bed =
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index 36630f8..1edab04 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -659,6 +659,33 @@ static const bfd_byte elf_x86_64_eh_frame_plt[] =
DW_CFA_nop, DW_CFA_nop, DW_CFA_nop, DW_CFA_nop
};
+/* .eh_frame covering the .plt.got section. */
+
+static const bfd_byte elf_x86_64_eh_frame_plt_got[] =
+{
+#define PLT_GOT_FDE_LENGTH 20
+ PLT_CIE_LENGTH, 0, 0, 0, /* CIE length */
+ 0, 0, 0, 0, /* CIE ID */
+ 1, /* CIE version */
+ 'z', 'R', 0, /* Augmentation string */
+ 1, /* Code alignment factor */
+ 0x78, /* Data alignment factor */
+ 16, /* Return address column */
+ 1, /* Augmentation size */
+ DW_EH_PE_pcrel | DW_EH_PE_sdata4, /* FDE encoding */
+ DW_CFA_def_cfa, 7, 8, /* DW_CFA_def_cfa: r7 (rsp) ofs 8 */
+ DW_CFA_offset + 16, 1, /* DW_CFA_offset: r16 (rip) at cfa-8 */
+ DW_CFA_nop, DW_CFA_nop,
+
+ PLT_GOT_FDE_LENGTH, 0, 0, 0, /* FDE length */
+ PLT_CIE_LENGTH + 8, 0, 0, 0, /* CIE pointer */
+ 0, 0, 0, 0, /* the start of .plt.got goes here */
+ 0, 0, 0, 0, /* .plt.got size goes here */
+ 0, /* Augmentation size */
+ DW_CFA_nop, DW_CFA_nop, DW_CFA_nop, DW_CFA_nop,
+ DW_CFA_nop, DW_CFA_nop, DW_CFA_nop
+};
+
/* Architecture-specific backend data for x86-64. */
struct elf_x86_64_backend_data
@@ -693,6 +720,10 @@ struct elf_x86_64_backend_data
/* .eh_frame covering the .plt section. */
const bfd_byte *eh_frame_plt;
unsigned int eh_frame_plt_size;
+
+ /* .eh_frame covering the .plt.got section. */
+ const bfd_byte *eh_frame_plt_got;
+ unsigned int eh_frame_plt_got_size;
};
#define get_elf_x86_64_arch_data(bed) \
@@ -721,6 +752,8 @@ static const struct elf_x86_64_backend_data elf_x86_64_arch_bed =
6, /* plt_lazy_offset */
elf_x86_64_eh_frame_plt, /* eh_frame_plt */
sizeof (elf_x86_64_eh_frame_plt), /* eh_frame_plt_size */
+ elf_x86_64_eh_frame_plt_got, /* eh_frame_plt_got */
+ sizeof (elf_x86_64_eh_frame_plt_got), /* eh_frame_plt_got_size */
};
static const struct elf_x86_64_backend_data elf_x86_64_bnd_arch_bed =
@@ -739,6 +772,9 @@ static const struct elf_x86_64_backend_data elf_x86_64_bnd_arch_bed =
0, /* plt_lazy_offset */
elf_x86_64_eh_frame_plt, /* eh_frame_plt */
sizeof (elf_x86_64_eh_frame_plt), /* eh_frame_plt_size */
+ /* FIXME: Needs .eh_frame coverage. */
+ NULL, /* eh_frame_plt_got */
+ 0, /* eh_frame_plt_got_size */
};
#define elf_backend_arch_data &elf_x86_64_arch_bed
@@ -865,6 +901,7 @@ struct elf_x86_64_link_hash_table
asection *plt_eh_frame;
asection *plt_bnd;
asection *plt_got;
+ asection *plt_got_eh_frame;
union
{
@@ -1135,7 +1172,8 @@ elf_x86_64_create_dynamic_sections (bfd *dynobj,
htab->plt_eh_frame
= bfd_make_section_anyway_with_flags (dynobj, ".eh_frame", flags);
if (htab->plt_eh_frame == NULL
- || !bfd_set_section_alignment (dynobj, htab->plt_eh_frame, 3))
+ || !bfd_set_section_alignment (dynobj, htab->plt_eh_frame,
+ ABI_64_P (dynobj) ? 3 : 2))
return FALSE;
}
@@ -2744,6 +2782,24 @@ do_size:
htab->plt_got,
plt_got_align))
goto error_return;
+
+ if (!info->no_ld_generated_unwind_info
+ && htab->plt_got_eh_frame == NULL
+ && get_elf_x86_64_backend_data (abfd)->eh_frame_plt_got != NULL)
+ {
+ flagword flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY
+ | SEC_HAS_CONTENTS | SEC_IN_MEMORY
+ | SEC_LINKER_CREATED);
+ htab->plt_got_eh_frame
+ = bfd_make_section_anyway_with_flags (htab->elf.dynobj,
+ ".eh_frame",
+ flags);
+ if (htab->plt_got_eh_frame == NULL
+ || !bfd_set_section_alignment (htab->elf.dynobj,
+ htab->plt_got_eh_frame,
+ ABI_64_P (htab->elf.dynobj) ? 3 : 2))
+ goto error_return;
+ }
}
if ((r_type == R_X86_64_GOTPCREL
@@ -3788,15 +3844,28 @@ elf_x86_64_size_dynamic_sections (bfd *output_bfd,
htab->elf.sgotplt->size = 0;
}
- if (htab->plt_eh_frame != NULL
- && htab->elf.splt != NULL
- && htab->elf.splt->size != 0
- && !bfd_is_abs_section (htab->elf.splt->output_section)
- && _bfd_elf_eh_frame_present (info))
+ if (_bfd_elf_eh_frame_present (info))
{
- const struct elf_x86_64_backend_data *arch_data
- = get_elf_x86_64_arch_data (bed);
- htab->plt_eh_frame->size = arch_data->eh_frame_plt_size;
+ if (htab->plt_eh_frame != NULL
+ && htab->elf.splt != NULL
+ && htab->elf.splt->size != 0
+ && !bfd_is_abs_section (htab->elf.splt->output_section))
+ {
+ const struct elf_x86_64_backend_data *arch_data
+ = get_elf_x86_64_arch_data (bed);
+ htab->plt_eh_frame->size = arch_data->eh_frame_plt_size;
+ }
+
+ if (htab->plt_got_eh_frame != NULL
+ && htab->plt_got != NULL
+ && htab->plt_got->size != 0
+ && !bfd_is_abs_section (htab->plt_got->output_section))
+ {
+ const struct elf_x86_64_backend_data *arch_data
+ = get_elf_x86_64_arch_data (bed);
+ htab->plt_got_eh_frame->size
+ = arch_data->eh_frame_plt_got_size;
+ }
}
/* We now have determined the sizes of the various dynamic sections.
@@ -3815,6 +3884,7 @@ elf_x86_64_size_dynamic_sections (bfd *output_bfd,
|| s == htab->plt_bnd
|| s == htab->plt_got
|| s == htab->plt_eh_frame
+ || s == htab->plt_got_eh_frame
|| s == htab->elf.sdynbss
|| s == htab->elf.sdynrelro)
{
@@ -3878,6 +3948,20 @@ elf_x86_64_size_dynamic_sections (bfd *output_bfd,
htab->plt_eh_frame->contents + PLT_FDE_LEN_OFFSET);
}
+ if (htab->plt_got_eh_frame != NULL
+ && htab->plt_got_eh_frame->contents != NULL)
+ {
+ const struct elf_x86_64_backend_data *arch_data
+ = get_elf_x86_64_arch_data (bed);
+
+ memcpy (htab->plt_got_eh_frame->contents,
+ arch_data->eh_frame_plt_got,
+ htab->plt_got_eh_frame->size);
+ bfd_put_32 (dynobj, htab->plt_got->size,
+ (htab->plt_got_eh_frame->contents
+ + PLT_FDE_LEN_OFFSET));
+ }
+
if (htab->elf.dynamic_sections_created)
{
/* Add some entries to the .dynamic section. We fill in the
@@ -6343,6 +6427,33 @@ elf_x86_64_finish_dynamic_sections (bfd *output_bfd,
}
}
+ /* Adjust .eh_frame for .plt.got section. */
+ if (htab->plt_got_eh_frame != NULL
+ && htab->plt_got_eh_frame->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_eh_frame->output_section != NULL)
+ {
+ bfd_vma plt_start = htab->plt_got->output_section->vma;
+ bfd_vma eh_frame_start = htab->plt_got_eh_frame->output_section->vma
+ + htab->plt_got_eh_frame->output_offset
+ + PLT_FDE_START_OFFSET;
+ bfd_put_signed_32 (dynobj, plt_start - eh_frame_start,
+ htab->plt_got_eh_frame->contents
+ + PLT_FDE_START_OFFSET);
+ }
+ if (htab->plt_got_eh_frame->sec_info_type == SEC_INFO_TYPE_EH_FRAME)
+ {
+ if (! _bfd_elf_write_section_eh_frame (output_bfd, info,
+ htab->plt_got_eh_frame,
+ htab->plt_got_eh_frame->contents))
+ return FALSE;
+ }
+ }
+
if (htab->elf.sgot && htab->elf.sgot->size > 0)
elf_section_data (htab->elf.sgot->output_section)->this_hdr.sh_entsize
= GOT_ENTRY_SIZE;
@@ -7007,6 +7118,8 @@ static const struct elf_x86_64_backend_data elf_x86_64_nacl_arch_bed =
32, /* plt_lazy_offset */
elf_x86_64_nacl_eh_frame_plt, /* eh_frame_plt */
sizeof (elf_x86_64_nacl_eh_frame_plt), /* eh_frame_plt_size */
+ NULL, /* eh_frame_plt_got */
+ 0, /* eh_frame_plt_got_size */
};
#undef elf_backend_arch_data
diff --git a/ld/ChangeLog b/ld/ChangeLog
index 6a61d61..03562de 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -1,3 +1,29 @@
+2017-01-13 H.J. Lu <hongjiu.lu@intel.com>
+
+ Backport from master
+ 2017-01-10 H.J. Lu <hongjiu.lu@intel.com>
+
+ * testsuite/ld-x86-64/pr20830b.d: Updated.
+
+ 2017-01-10 H.J. Lu <hongjiu.lu@intel.com>
+
+ * emulparams/elf32_x86_64.sh (TINY_READONLY_SECTION): New.
+ * testsuite/ld-x86-64/pr20830.d: Renamed to ...
+ * testsuite/ld-x86-64/pr20830a.d: This. Updated.
+ * testsuite/ld-x86-64/pr20830b.d: New file.
+ * testsuite/ld-x86-64/x86-64.exp: Rename pr20830 to pr20830a.
+ Run pr20830b.
+
+ 2017-01-10 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR ld/20830
+ * testsuite/ld-i386/i386.exp: Run pr20830.
+ * testsuite/ld-x86-64/x86-64.exp: Likewise.
+ * testsuite/ld-i386/pr20830.d: New file.
+ * testsuite/ld-i386/pr20830.s: Likewise.
+ * testsuite/ld-x86-64/pr20830.d: Likewise.
+ * testsuite/ld-x86-64/pr20830.s: Likewise.
+
2017-01-02 Alan Modra <amodra@gmail.com>
Update year range in copyright notice of all files.
diff --git a/ld/emulparams/elf32_x86_64.sh b/ld/emulparams/elf32_x86_64.sh
index 9050730..9b85239 100644
--- a/ld/emulparams/elf32_x86_64.sh
+++ b/ld/emulparams/elf32_x86_64.sh
@@ -21,6 +21,10 @@ LARGE_SECTIONS=yes
LARGE_BSS_AFTER_BSS=
SEPARATE_GOTPLT="SIZEOF (.got.plt) >= 24 ? 24 : 0"
IREL_IN_PLT=
+# Reuse TINY_READONLY_SECTION which is placed right after .plt section.
+TINY_READONLY_SECTION="
+.plt.got ${RELOCATING-0} : { *(.plt.got) }
+"
if [ "x${host}" = "x${target}" ]; then
case " $EMULATION_LIBPATH " in
diff --git a/ld/testsuite/ld-i386/i386.exp b/ld/testsuite/ld-i386/i386.exp
index e748e8b..f439411 100644
--- a/ld/testsuite/ld-i386/i386.exp
+++ b/ld/testsuite/ld-i386/i386.exp
@@ -864,3 +864,4 @@ if { !([istarget "i?86-*-linux*"]
# Linux only tests
run_dump_test "pltgot-1"
run_dump_test "pltgot-2"
+run_dump_test "pr20830"
diff --git a/ld/testsuite/ld-i386/pr20830.d b/ld/testsuite/ld-i386/pr20830.d
new file mode 100644
index 0000000..caaadd7
--- /dev/null
+++ b/ld/testsuite/ld-i386/pr20830.d
@@ -0,0 +1,60 @@
+#name: PR ld/20830 (.plt.got)
+#as: --32
+#ld: -melf_i386 -shared -z relro --ld-generated-unwind-info
+#objdump: -dw -Wf
+
+.*: +file format .*
+
+Contents of the .eh_frame section:
+
+0+ 00000014 00000000 CIE
+ Version: 1
+ Augmentation: "zR"
+ Code alignment factor: 1
+ Data alignment factor: -4
+ Return address column: 8
+ Augmentation data: 1b
+
+ DW_CFA_def_cfa: r4 \(esp\) ofs 4
+ DW_CFA_offset: r8 \(eip\) at cfa-4
+ DW_CFA_nop
+ DW_CFA_nop
+
+0+18 00000010 0000001c FDE cie=00000000 pc=00000188..00000193
+ DW_CFA_nop
+ DW_CFA_nop
+ DW_CFA_nop
+
+0+2c 00000020 00000030 FDE cie=00000000 pc=00000170..00000180
+ DW_CFA_def_cfa_offset: 8
+ DW_CFA_advance_loc: 6 to 00000176
+ DW_CFA_def_cfa_offset: 12
+ DW_CFA_advance_loc: 10 to 00000180
+ DW_CFA_def_cfa_expression \(DW_OP_breg4 \(esp\): 4; DW_OP_breg8 \(eip\): 0; DW_OP_lit15; DW_OP_and; DW_OP_lit11; DW_OP_ge; DW_OP_lit2; DW_OP_shl; DW_OP_plus\)
+
+0+50 00000010 00000054 FDE cie=00000000 pc=00000180..00000188
+ DW_CFA_nop
+ DW_CFA_nop
+ DW_CFA_nop
+
+
+Disassembly of section .plt:
+
+0+170 <.plt>:
+ +[a-f0-9]+: ff b3 04 00 00 00 pushl 0x4\(%ebx\)
+ +[a-f0-9]+: ff a3 08 00 00 00 jmp \*0x8\(%ebx\)
+ +[a-f0-9]+: 00 00 add %al,\(%eax\)
+ ...
+
+Disassembly of section .plt.got:
+
+0+180 <.plt.got>:
+ +[a-f0-9]+: ff a3 fc ff ff ff jmp \*-0x4\(%ebx\)
+ +[a-f0-9]+: 66 90 xchg %ax,%ax
+
+Disassembly of section .text:
+
+0+188 <foo>:
+ +[a-f0-9]+: e8 f3 ff ff ff call 180 <.plt.got>
+ +[a-f0-9]+: 8b 83 fc ff ff ff mov -0x4\(%ebx\),%eax
+#pass
diff --git a/ld/testsuite/ld-i386/pr20830.s b/ld/testsuite/ld-i386/pr20830.s
new file mode 100644
index 0000000..344a137
--- /dev/null
+++ b/ld/testsuite/ld-i386/pr20830.s
@@ -0,0 +1,8 @@
+ .text
+ .globl foo
+ .type foo, @function
+foo:
+ .cfi_startproc
+ call func@plt
+ movl func@GOT(%ebx), %eax
+ .cfi_endproc
diff --git a/ld/testsuite/ld-x86-64/pr20830.s b/ld/testsuite/ld-x86-64/pr20830.s
new file mode 100644
index 0000000..d9a1b4c
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr20830.s
@@ -0,0 +1,8 @@
+ .text
+ .globl foo
+ .type foo, @function
+foo:
+ .cfi_startproc
+ call func@plt
+ movq func@GOTPCREL(%rip), %rax
+ .cfi_endproc
diff --git a/ld/testsuite/ld-x86-64/pr20830a.d b/ld/testsuite/ld-x86-64/pr20830a.d
new file mode 100644
index 0000000..87ea25d
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr20830a.d
@@ -0,0 +1,72 @@
+#name: PR ld/20830 (.plt.got)
+#source: pr20830.s
+#as: --64
+#ld: -melf_x86_64 -shared -z relro --ld-generated-unwind-info
+#objdump: -dw -Wf
+
+.*: +file format .*
+
+Contents of the .eh_frame section:
+
+0+ 0000000000000014 00000000 CIE
+ Version: 1
+ Augmentation: "zR"
+ Code alignment factor: 1
+ Data alignment factor: -8
+ Return address column: 16
+ Augmentation data: 1b
+
+ DW_CFA_def_cfa: r7 \(rsp\) ofs 8
+ DW_CFA_offset: r16 \(rip\) at cfa-8
+ DW_CFA_nop
+ DW_CFA_nop
+
+0+18 0000000000000014 0000001c FDE cie=00000000 pc=0000000000000238..0000000000000244
+ DW_CFA_nop
+ DW_CFA_nop
+ DW_CFA_nop
+ DW_CFA_nop
+ DW_CFA_nop
+ DW_CFA_nop
+ DW_CFA_nop
+
+0+30 0000000000000024 00000034 FDE cie=00000000 pc=0000000000000220..0000000000000230
+ DW_CFA_def_cfa_offset: 16
+ DW_CFA_advance_loc: 6 to 0000000000000226
+ DW_CFA_def_cfa_offset: 24
+ DW_CFA_advance_loc: 10 to 0000000000000230
+ DW_CFA_def_cfa_expression \(DW_OP_breg7 \(rsp\): 8; DW_OP_breg16 \(rip\): 0; DW_OP_lit15; DW_OP_and; DW_OP_lit11; DW_OP_ge; DW_OP_lit3; DW_OP_shl; DW_OP_plus\)
+ DW_CFA_nop
+ DW_CFA_nop
+ DW_CFA_nop
+ DW_CFA_nop
+
+0+58 0000000000000014 0000005c FDE cie=00000000 pc=0000000000000230..0000000000000238
+ DW_CFA_nop
+ DW_CFA_nop
+ DW_CFA_nop
+ DW_CFA_nop
+ DW_CFA_nop
+ DW_CFA_nop
+ DW_CFA_nop
+
+
+Disassembly of section .plt:
+
+0+220 <.plt>:
+ +[a-f0-9]+: ff 35 e2 0d 20 00 pushq 0x200de2\(%rip\) # 201008 <_GLOBAL_OFFSET_TABLE_\+0x8>
+ +[a-f0-9]+: ff 25 e4 0d 20 00 jmpq \*0x200de4\(%rip\) # 201010 <_GLOBAL_OFFSET_TABLE_\+0x10>
+ +[a-f0-9]+: 0f 1f 40 00 nopl 0x0\(%rax\)
+
+Disassembly of section .plt.got:
+
+0+230 <.plt.got>:
+ +[a-f0-9]+: ff 25 c2 0d 20 00 jmpq \*0x200dc2\(%rip\) # 200ff8 <func>
+ +[a-f0-9]+: 66 90 xchg %ax,%ax
+
+Disassembly of section .text:
+
+0+238 <foo>:
+ +[a-f0-9]+: e8 f3 ff ff ff callq 230 <.plt.got>
+ +[a-f0-9]+: 48 8b 05 b4 0d 20 00 mov 0x200db4\(%rip\),%rax # 200ff8 <func>
+#pass
diff --git a/ld/testsuite/ld-x86-64/pr20830b.d b/ld/testsuite/ld-x86-64/pr20830b.d
new file mode 100644
index 0000000..218a56e
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr20830b.d
@@ -0,0 +1,60 @@
+#name: PR ld/20830 (.plt.got)
+#source: pr20830.s
+#as: --x32
+#ld: -melf32_x86_64 -shared -z relro --ld-generated-unwind-info
+#objdump: -dw -Wf
+
+.*: +file format .*
+
+Contents of the .eh_frame section:
+
+0+ 0000000000000014 00000000 CIE
+ Version: 1
+ Augmentation: "zR"
+ Code alignment factor: 1
+ Data alignment factor: -8
+ Return address column: 16
+ Augmentation data: 1b
+
+ DW_CFA_def_cfa: r7 \(rsp\) ofs 8
+ DW_CFA_offset: r16 \(rip\) at cfa-8
+ DW_CFA_nop
+ DW_CFA_nop
+
+0+18 0000000000000010 0000001c FDE cie=00000000 pc=0000000000000188..0000000000000194
+ DW_CFA_nop
+ DW_CFA_nop
+ DW_CFA_nop
+
+0+2c 0000000000000020 00000030 FDE cie=00000000 pc=0000000000000170..0000000000000180
+ DW_CFA_def_cfa_offset: 16
+ DW_CFA_advance_loc: 6 to 0000000000000176
+ DW_CFA_def_cfa_offset: 24
+ DW_CFA_advance_loc: 10 to 0000000000000180
+ DW_CFA_def_cfa_expression \(DW_OP_breg7 \(rsp\): 8; DW_OP_breg16 \(rip\): 0; DW_OP_lit15; DW_OP_and; DW_OP_lit11; DW_OP_ge; DW_OP_lit3; DW_OP_shl; DW_OP_plus\)
+
+0+50 0000000000000010 00000054 FDE cie=00000000 pc=0000000000000180..0000000000000188
+ DW_CFA_nop
+ DW_CFA_nop
+ DW_CFA_nop
+
+
+Disassembly of section .plt:
+
+0+170 <.plt>:
+ +[a-f0-9]+: ff 35 92 0e 20 00 pushq 0x200e92\(%rip\) # 201008 <_GLOBAL_OFFSET_TABLE_\+0x8>
+ +[a-f0-9]+: ff 25 94 0e 20 00 jmpq \*0x200e94\(%rip\) # 201010 <_GLOBAL_OFFSET_TABLE_\+0x10>
+ +[a-f0-9]+: 0f 1f 40 00 nopl 0x0\(%rax\)
+
+Disassembly of section .plt.got:
+
+0+180 <.plt.got>:
+ +[a-f0-9]+: ff 25 72 0e 20 00 jmpq \*0x200e72\(%rip\) # 200ff8 <func>
+ +[a-f0-9]+: 66 90 xchg %ax,%ax
+
+Disassembly of section .text:
+
+0+188 <foo>:
+ +[a-f0-9]+: e8 f3 ff ff ff callq 180 <.plt.got>
+ +[a-f0-9]+: 48 8b 05 64 0e 20 00 mov 0x200e64\(%rip\),%rax # 200ff8 <func>
+#pass
diff --git a/ld/testsuite/ld-x86-64/x86-64.exp b/ld/testsuite/ld-x86-64/x86-64.exp
index ac63a1d..3a7ba38 100644
--- a/ld/testsuite/ld-x86-64/x86-64.exp
+++ b/ld/testsuite/ld-x86-64/x86-64.exp
@@ -1017,3 +1017,5 @@ if { ![istarget "x86_64-*-linux*"]} {
run_dump_test "pr17618"
run_dump_test "pltgot-1"
run_dump_test "pltgot-2"
+run_dump_test "pr20830a"
+run_dump_test "pr20830b"