aboutsummaryrefslogtreecommitdiff
path: root/bfd
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2017-01-10 13:31:59 -0800
committerH.J. Lu <hjl.tools@gmail.com>2017-01-10 13:31:59 -0800
commitfff53daefb7838b5718422c87946330e4a8288ce (patch)
tree5f78be197c91e52a9cb9aa373c37ece6d77a1527 /bfd
parent5edad15d7c1e6a2409102b3426b444d6ea98bdfc (diff)
downloadgdb-fff53daefb7838b5718422c87946330e4a8288ce.zip
gdb-fff53daefb7838b5718422c87946330e4a8288ce.tar.gz
gdb-fff53daefb7838b5718422c87946330e4a8288ce.tar.bz2
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. bfd/ 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/ 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.
Diffstat (limited to 'bfd')
-rw-r--r--bfd/ChangeLog31
-rw-r--r--bfd/elf32-i386.c116
-rw-r--r--bfd/elf64-x86-64.c128
3 files changed, 259 insertions, 16 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 09121d2..d6d340c 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,5 +1,36 @@
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-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..982bae6 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,
+ 3))
+ 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..b5a949a 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
{
@@ -2744,6 +2781,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,
+ 3))
+ goto error_return;
+ }
}
if ((r_type == R_X86_64_GOTPCREL
@@ -3788,15 +3843,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 +3883,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 +3947,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 +6426,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 +7117,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