x86: Add _bfd_x86_elf_link_setup_gnu_properties

Extract the common parts of elf_i386_link_setup_gnu_properties and
elf_x86_64_link_setup_gnu_properties into a new function.

For x86-64, since PIC PLT layouts are the same as non-PIC PLT layouts,
initialize pic_plt0_entry and pic_plt_entry fields in PLT layouts with
the non-PIC PLT entries.

	* elf32-i386.c (elf_i386_link_setup_gnu_properties): Updated.
	Call _bfd_x86_elf_link_setup_gnu_properties.
	* elf64-x86-64.c (elf_x86_lazy_plt_layout): Initialize
	pic_plt0_entry and pic_plt_entry fields with the non-PIC PLT
	entries.
	(elf_x86_64_non_lazy_plt): Likewise.
	(elf_x86_64_lazy_bnd_plt): Likewise.
	(elf_x86_64_non_lazy_bnd_plt): Likewise.
	(elf_x86_64_lazy_ibt_plt): Likewise.
	(elf_x32_lazy_ibt_plt): Likewise.
	(elf_x86_64_non_lazy_ibt_plt): Likewise.
	(elf_x32_non_lazy_ibt_plt): Likewise.
	(elf_x86_64_nacl_plt): Likewise.
	(elf_x86_64_link_setup_gnu_properties): Updated.  Call
	_bfd_x86_elf_link_setup_gnu_properties.
	* elfxx-x86.c: Include elf-vxworks.h".
	(_bfd_x86_elf_link_setup_gnu_properties): New function.
	* elfxx-x86.h (elf_x86_lazy_plt_layout): Remove "for i386 only"
	comments for pic_plt0_entry and pic_plt_entry.
	(elf_x86_non_lazy_plt_layout): Likewise.
	(elf_x86_plt_layout_table): New.
	(_bfd_x86_elf_link_setup_gnu_properties): Likewise.
This commit is contained in:
H.J. Lu 2017-09-01 08:00:36 -07:00
parent 376dc015f2
commit a6798baba2
5 changed files with 494 additions and 717 deletions

View File

@ -1,3 +1,28 @@
2017-09-01 H.J. Lu <hongjiu.lu@intel.com>
* elf32-i386.c (elf_i386_link_setup_gnu_properties): Updated.
Call _bfd_x86_elf_link_setup_gnu_properties.
* elf64-x86-64.c (elf_x86_lazy_plt_layout): Initialize
pic_plt0_entry and pic_plt_entry fields with the non-PIC PLT
entries.
(elf_x86_64_non_lazy_plt): Likewise.
(elf_x86_64_lazy_bnd_plt): Likewise.
(elf_x86_64_non_lazy_bnd_plt): Likewise.
(elf_x86_64_lazy_ibt_plt): Likewise.
(elf_x32_lazy_ibt_plt): Likewise.
(elf_x86_64_non_lazy_ibt_plt): Likewise.
(elf_x32_non_lazy_ibt_plt): Likewise.
(elf_x86_64_nacl_plt): Likewise.
(elf_x86_64_link_setup_gnu_properties): Updated. Call
_bfd_x86_elf_link_setup_gnu_properties.
* elfxx-x86.c: Include elf-vxworks.h".
(_bfd_x86_elf_link_setup_gnu_properties): New function.
* elfxx-x86.h (elf_x86_lazy_plt_layout): Remove "for i386 only"
comments for pic_plt0_entry and pic_plt_entry.
(elf_x86_non_lazy_plt_layout): Likewise.
(elf_x86_plt_layout_table): New.
(_bfd_x86_elf_link_setup_gnu_properties): Likewise.
2017-09-01 H.J. Lu <hongjiu.lu@intel.com>
PR ld/22061

View File

@ -5825,354 +5825,35 @@ elf_i386_get_synthetic_symtab (bfd *abfd,
static bfd *
elf_i386_link_setup_gnu_properties (struct bfd_link_info *info)
{
bfd_boolean normal_target;
bfd_boolean lazy_plt;
asection *sec, *pltsec;
bfd *dynobj;
bfd_boolean use_ibt_plt;
unsigned int plt_alignment, features;
struct elf_x86_link_hash_table *htab;
bfd *pbfd;
bfd *ebfd = NULL;
elf_property *prop;
features = 0;
if (info->ibt)
features = GNU_PROPERTY_X86_FEATURE_1_IBT;
if (info->shstk)
features |= GNU_PROPERTY_X86_FEATURE_1_SHSTK;
/* Find a normal input file with GNU property note. */
for (pbfd = info->input_bfds;
pbfd != NULL;
pbfd = pbfd->link.next)
if (bfd_get_flavour (pbfd) == bfd_target_elf_flavour
&& bfd_count_sections (pbfd) != 0)
{
ebfd = pbfd;
if (elf_properties (pbfd) != NULL)
break;
}
if (ebfd != NULL && features)
{
/* If features is set, add GNU_PROPERTY_X86_FEATURE_1_IBT and
GNU_PROPERTY_X86_FEATURE_1_SHSTK. */
prop = _bfd_elf_get_property (ebfd,
GNU_PROPERTY_X86_FEATURE_1_AND,
4);
prop->u.number |= features;
prop->pr_kind = property_number;
/* Create the GNU property note section if needed. */
if (pbfd == NULL)
{
sec = bfd_make_section_with_flags (ebfd,
NOTE_GNU_PROPERTY_SECTION_NAME,
(SEC_ALLOC
| SEC_LOAD
| SEC_IN_MEMORY
| SEC_READONLY
| SEC_HAS_CONTENTS
| SEC_DATA));
if (sec == NULL)
info->callbacks->einfo (_("%F: failed to create GNU property section\n"));
if (!bfd_set_section_alignment (ebfd, sec, 2))
{
error_alignment:
info->callbacks->einfo (_("%F%A: failed to align section\n"),
sec);
}
elf_section_type (sec) = SHT_NOTE;
}
}
pbfd = _bfd_elf_link_setup_gnu_properties (info);
if (bfd_link_relocatable (info))
return pbfd;
htab = elf_x86_hash_table (info, I386_ELF_DATA);
if (htab == NULL)
return pbfd;
use_ibt_plt = info->ibtplt || info->ibt;
if (!use_ibt_plt && pbfd != NULL)
{
/* Check if GNU_PROPERTY_X86_FEATURE_1_IBT is on. */
elf_property_list *p;
/* The property list is sorted in order of type. */
for (p = elf_properties (pbfd); p; p = p->next)
{
if (GNU_PROPERTY_X86_FEATURE_1_AND == p->property.pr_type)
{
use_ibt_plt = !!(p->property.u.number
& GNU_PROPERTY_X86_FEATURE_1_IBT);
break;
}
else if (GNU_PROPERTY_X86_FEATURE_1_AND < p->property.pr_type)
break;
}
}
dynobj = htab->elf.dynobj;
/* Set htab->elf.dynobj here so that there is no need to check and
set it in check_relocs. */
if (dynobj == NULL)
{
if (pbfd != NULL)
{
htab->elf.dynobj = pbfd;
dynobj = pbfd;
}
else
{
bfd *abfd;
/* Find a normal input file to hold linker created
sections. */
for (abfd = info->input_bfds;
abfd != NULL;
abfd = abfd->link.next)
if (bfd_get_flavour (abfd) == bfd_target_elf_flavour
&& (abfd->flags
& (DYNAMIC | BFD_LINKER_CREATED | BFD_PLUGIN)) == 0)
{
htab->elf.dynobj = abfd;
dynobj = abfd;
break;
}
}
}
/* Even when lazy binding is disabled by "-z now", the PLT0 entry may
still be used with LD_AUDIT or LD_PROFILE if PLT entry is used for
canonical function address. */
htab->plt.has_plt0 = 1;
normal_target = FALSE;
struct elf_x86_plt_layout_table plt_layout;
plt_layout.normal_target = FALSE;
plt_layout.is_vxworks = FALSE;
switch (get_elf_i386_backend_data (info->output_bfd)->os)
{
case is_normal:
if (use_ibt_plt)
{
htab->lazy_plt = &elf_i386_lazy_ibt_plt;
htab->non_lazy_plt = &elf_i386_non_lazy_ibt_plt;
}
else
{
htab->lazy_plt = &elf_i386_lazy_plt;
htab->non_lazy_plt = &elf_i386_non_lazy_plt;
}
normal_target = TRUE;
plt_layout.lazy_plt = &elf_i386_lazy_plt;
plt_layout.non_lazy_plt = &elf_i386_non_lazy_plt;
plt_layout.lazy_ibt_plt = &elf_i386_lazy_ibt_plt;
plt_layout.non_lazy_ibt_plt = &elf_i386_non_lazy_ibt_plt;
plt_layout.normal_target = TRUE;
break;
case is_vxworks:
htab->lazy_plt = &elf_i386_lazy_plt;
htab->non_lazy_plt = NULL;
if (!elf_vxworks_create_dynamic_sections (dynobj, info,
&htab->srelplt2))
info->callbacks->einfo (_("%F: failed to create VxWorks dynamic sections\n"));
plt_layout.lazy_plt = &elf_i386_lazy_plt;
plt_layout.non_lazy_plt = NULL;
plt_layout.lazy_ibt_plt = NULL;
plt_layout.non_lazy_ibt_plt = NULL;
plt_layout.is_vxworks = TRUE;
break;
case is_nacl:
htab->lazy_plt = &elf_i386_nacl_plt;
htab->non_lazy_plt = NULL;
plt_layout.lazy_plt = &elf_i386_nacl_plt;
plt_layout.non_lazy_plt = NULL;
plt_layout.lazy_ibt_plt = NULL;
plt_layout.non_lazy_ibt_plt = NULL;
break;
}
pltsec = htab->elf.splt;
/* If the non-lazy PLT is available, use it for all PLT entries if
there are no PLT0 or no .plt section. */
if (htab->non_lazy_plt != NULL
&& (!htab->plt.has_plt0 || pltsec == NULL))
{
lazy_plt = FALSE;
if (bfd_link_pic (info))
htab->plt.plt_entry = htab->non_lazy_plt->pic_plt_entry;
else
htab->plt.plt_entry = htab->non_lazy_plt->plt_entry;
htab->plt.plt_entry_size = htab->non_lazy_plt->plt_entry_size;
htab->plt.plt_got_offset = htab->non_lazy_plt->plt_got_offset;
htab->plt.eh_frame_plt_size
= htab->non_lazy_plt->eh_frame_plt_size;
htab->plt.eh_frame_plt = htab->non_lazy_plt->eh_frame_plt;
}
else
{
lazy_plt = TRUE;
if (bfd_link_pic (info))
{
htab->plt.plt0_entry = htab->lazy_plt->pic_plt0_entry;
htab->plt.plt_entry = htab->lazy_plt->pic_plt_entry;
}
else
{
htab->plt.plt0_entry = htab->lazy_plt->plt0_entry;
htab->plt.plt_entry = htab->lazy_plt->plt_entry;
}
htab->plt.plt_entry_size = htab->lazy_plt->plt_entry_size;
htab->plt.plt_got_offset = htab->lazy_plt->plt_got_offset;
htab->plt.eh_frame_plt_size = htab->lazy_plt->eh_frame_plt_size;
htab->plt.eh_frame_plt = htab->lazy_plt->eh_frame_plt;
}
/* This is unused for i386. */
htab->plt.plt_got_insn_size = 0;
/* Return if there are no normal input files. */
if (dynobj == NULL)
return pbfd;
/* Since create_dynamic_sections isn't always called, but GOT
relocations need GOT sections, create them here so that we
don't need to do it in check_relocs. */
if (htab->elf.sgot == NULL
&& !_bfd_elf_create_got_section (dynobj, info))
info->callbacks->einfo (_("%F: failed to create GOT sections\n"));
/* Create the ifunc sections here so that check_relocs can be
simplified. */
if (!_bfd_elf_create_ifunc_sections (dynobj, info))
info->callbacks->einfo (_("%F: failed to create ifunc sections\n"));
plt_alignment = bfd_log2 (htab->plt.plt_entry_size);
if (pltsec != NULL)
{
/* Whe creating executable, set the contents of the .interp
section to the interpreter. */
if (bfd_link_executable (info) && !info->nointerp)
{
asection *s = bfd_get_linker_section (dynobj, ".interp");
if (s == NULL)
abort ();
s->size = htab->dynamic_interpreter_size;
s->contents = (unsigned char *) htab->dynamic_interpreter;
htab->interp = s;
}
/* Don't change PLT section alignment for NaCl since it uses
64-byte PLT entry and sets PLT section alignment to 32
bytes. */
if (normal_target)
{
const struct elf_backend_data *bed
= get_elf_backend_data (dynobj);
flagword pltflags = (bed->dynamic_sec_flags
| SEC_ALLOC
| SEC_CODE
| SEC_LOAD
| SEC_READONLY);
unsigned int non_lazy_plt_alignment
= bfd_log2 (htab->non_lazy_plt->plt_entry_size);
sec = pltsec;
if (!bfd_set_section_alignment (sec->owner, sec,
plt_alignment))
goto error_alignment;
/* Create the GOT procedure linkage table. */
sec = bfd_make_section_anyway_with_flags (dynobj,
".plt.got",
pltflags);
if (sec == NULL)
info->callbacks->einfo (_("%F: failed to create GOT PLT section\n"));
if (!bfd_set_section_alignment (dynobj, sec,
non_lazy_plt_alignment))
goto error_alignment;
htab->plt_got = sec;
if (lazy_plt)
{
sec = NULL;
if (use_ibt_plt)
{
/* Create the second PLT for Intel IBT support. IBT
PLT is supported only for non-NaCl target and is
is needed only for lazy binding. */
sec = bfd_make_section_anyway_with_flags (dynobj,
".plt.sec",
pltflags);
if (sec == NULL)
info->callbacks->einfo (_("%F: failed to create IBT-enabled PLT section\n"));
if (!bfd_set_section_alignment (dynobj, sec,
plt_alignment))
goto error_alignment;
}
htab->plt_second = sec;
}
}
if (!info->no_ld_generated_unwind_info)
{
flagword flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY
| SEC_HAS_CONTENTS | SEC_IN_MEMORY
| SEC_LINKER_CREATED);
sec = bfd_make_section_anyway_with_flags (dynobj,
".eh_frame",
flags);
if (sec == NULL)
info->callbacks->einfo (_("%F: failed to create PLT .eh_frame section\n"));
if (!bfd_set_section_alignment (dynobj, sec, 2))
goto error_alignment;
htab->plt_eh_frame = sec;
if (htab->plt_got != NULL)
{
sec = bfd_make_section_anyway_with_flags (dynobj,
".eh_frame",
flags);
if (sec == NULL)
info->callbacks->einfo (_("%F: failed to create GOT PLT .eh_frame section\n"));
if (!bfd_set_section_alignment (dynobj, sec, 2))
goto error_alignment;
htab->plt_got_eh_frame = sec;
}
if (htab->plt_second != NULL)
{
sec = bfd_make_section_anyway_with_flags (dynobj,
".eh_frame",
flags);
if (sec == NULL)
info->callbacks->einfo (_("%F: failed to create the second PLT .eh_frame section\n"));
if (!bfd_set_section_alignment (dynobj, sec, 2))
goto error_alignment;
htab->plt_second_eh_frame = sec;
}
}
}
if (normal_target)
{
/* The .iplt section is used for IFUNC symbols in static
executables. */
sec = htab->elf.iplt;
if (sec != NULL
&& !bfd_set_section_alignment (sec->owner, sec,
plt_alignment))
goto error_alignment;
}
return pbfd;
return _bfd_x86_elf_link_setup_gnu_properties (info, &plt_layout);
}
#define TARGET_LITTLE_SYM i386_elf32_vec

View File

@ -848,8 +848,8 @@ static const struct elf_x86_lazy_plt_layout elf_x86_64_lazy_plt =
6, /* plt_got_insn_size */
LAZY_PLT_ENTRY_SIZE, /* plt_plt_insn_end */
6, /* plt_lazy_offset */
NULL, /* pic_plt0_entry */
NULL, /* pic_plt_entry */
elf_x86_64_lazy_plt0_entry, /* pic_plt0_entry */
elf_x86_64_lazy_plt_entry, /* pic_plt_entry */
elf_x86_64_eh_frame_lazy_plt, /* eh_frame_plt */
sizeof (elf_x86_64_eh_frame_lazy_plt) /* eh_frame_plt_size */
};
@ -857,7 +857,7 @@ static const struct elf_x86_lazy_plt_layout elf_x86_64_lazy_plt =
static const struct elf_x86_non_lazy_plt_layout elf_x86_64_non_lazy_plt =
{
elf_x86_64_non_lazy_plt_entry, /* plt_entry */
NULL, /* pic_plt_entry */
elf_x86_64_non_lazy_plt_entry, /* pic_plt_entry */
NON_LAZY_PLT_ENTRY_SIZE, /* plt_entry_size */
2, /* plt_got_offset */
6, /* plt_got_insn_size */
@ -880,8 +880,8 @@ static const struct elf_x86_lazy_plt_layout elf_x86_64_lazy_bnd_plt =
1+6, /* plt_got_insn_size */
11, /* plt_plt_insn_end */
0, /* plt_lazy_offset */
NULL, /* pic_plt0_entry */
NULL, /* pic_plt_entry */
elf_x86_64_lazy_bnd_plt0_entry, /* pic_plt0_entry */
elf_x86_64_lazy_bnd_plt_entry, /* pic_plt_entry */
elf_x86_64_eh_frame_lazy_bnd_plt, /* eh_frame_plt */
sizeof (elf_x86_64_eh_frame_lazy_bnd_plt) /* eh_frame_plt_size */
};
@ -889,7 +889,7 @@ static const struct elf_x86_lazy_plt_layout elf_x86_64_lazy_bnd_plt =
static const struct elf_x86_non_lazy_plt_layout elf_x86_64_non_lazy_bnd_plt =
{
elf_x86_64_non_lazy_bnd_plt_entry, /* plt_entry */
NULL, /* pic_plt_entry */
elf_x86_64_non_lazy_bnd_plt_entry, /* pic_plt_entry */
NON_LAZY_PLT_ENTRY_SIZE, /* plt_entry_size */
1+2, /* plt_got_offset */
1+6, /* plt_got_insn_size */
@ -912,8 +912,8 @@ static const struct elf_x86_lazy_plt_layout elf_x86_64_lazy_ibt_plt =
4+1+6, /* plt_got_insn_size */
4+1+5+5, /* plt_plt_insn_end */
0, /* plt_lazy_offset */
NULL, /* pic_plt0_entry */
NULL, /* pic_plt_entry */
elf_x86_64_lazy_bnd_plt0_entry, /* pic_plt0_entry */
elf_x86_64_lazy_ibt_plt_entry, /* pic_plt_entry */
elf_x86_64_eh_frame_lazy_ibt_plt, /* eh_frame_plt */
sizeof (elf_x86_64_eh_frame_lazy_ibt_plt) /* eh_frame_plt_size */
};
@ -933,8 +933,8 @@ static const struct elf_x86_lazy_plt_layout elf_x32_lazy_ibt_plt =
4+6, /* plt_got_insn_size */
4+5+5, /* plt_plt_insn_end */
0, /* plt_lazy_offset */
NULL, /* pic_plt0_entry */
NULL, /* pic_plt_entry */
elf_x86_64_lazy_plt0_entry, /* pic_plt0_entry */
elf_x32_lazy_ibt_plt_entry, /* pic_plt_entry */
elf_x32_eh_frame_lazy_ibt_plt, /* eh_frame_plt */
sizeof (elf_x32_eh_frame_lazy_ibt_plt) /* eh_frame_plt_size */
};
@ -942,7 +942,7 @@ static const struct elf_x86_lazy_plt_layout elf_x32_lazy_ibt_plt =
static const struct elf_x86_non_lazy_plt_layout elf_x86_64_non_lazy_ibt_plt =
{
elf_x86_64_non_lazy_ibt_plt_entry, /* plt_entry */
NULL, /* pic_plt_entry */
elf_x86_64_non_lazy_ibt_plt_entry, /* pic_plt_entry */
LAZY_PLT_ENTRY_SIZE, /* plt_entry_size */
4+1+2, /* plt_got_offset */
4+1+6, /* plt_got_insn_size */
@ -953,7 +953,7 @@ static const struct elf_x86_non_lazy_plt_layout elf_x86_64_non_lazy_ibt_plt =
static const struct elf_x86_non_lazy_plt_layout elf_x32_non_lazy_ibt_plt =
{
elf_x32_non_lazy_ibt_plt_entry, /* plt_entry */
NULL, /* pic_plt_entry */
elf_x32_non_lazy_ibt_plt_entry, /* pic_plt_entry */
LAZY_PLT_ENTRY_SIZE, /* plt_entry_size */
4+2, /* plt_got_offset */
4+6, /* plt_got_insn_size */
@ -6380,386 +6380,44 @@ elf_x86_64_relocs_compatible (const bfd_target *input,
static bfd *
elf_x86_64_link_setup_gnu_properties (struct bfd_link_info *info)
{
bfd_boolean normal_target;
bfd_boolean lazy_plt;
asection *sec, *pltsec;
bfd *dynobj;
bfd_boolean use_ibt_plt;
unsigned int plt_alignment, features;
struct elf_x86_link_hash_table *htab;
bfd *pbfd;
bfd *ebfd = NULL;
elf_property *prop;
struct elf_x86_plt_layout_table plt_layout;
features = 0;
if (info->ibt)
features = GNU_PROPERTY_X86_FEATURE_1_IBT;
if (info->shstk)
features |= GNU_PROPERTY_X86_FEATURE_1_SHSTK;
/* Find a normal input file with GNU property note. */
for (pbfd = info->input_bfds;
pbfd != NULL;
pbfd = pbfd->link.next)
if (bfd_get_flavour (pbfd) == bfd_target_elf_flavour
&& bfd_count_sections (pbfd) != 0)
{
ebfd = pbfd;
if (elf_properties (pbfd) != NULL)
break;
}
if (ebfd != NULL && features)
plt_layout.is_vxworks = FALSE;
if (get_elf_x86_64_backend_data (info->output_bfd)->os == is_normal)
{
/* If features is set, add GNU_PROPERTY_X86_FEATURE_1_IBT and
GNU_PROPERTY_X86_FEATURE_1_SHSTK. */
prop = _bfd_elf_get_property (ebfd,
GNU_PROPERTY_X86_FEATURE_1_AND,
4);
prop->u.number |= features;
prop->pr_kind = property_number;
/* Create the GNU property note section if needed. */
if (pbfd == NULL)
if (info->bndplt)
{
sec = bfd_make_section_with_flags (ebfd,
NOTE_GNU_PROPERTY_SECTION_NAME,
(SEC_ALLOC
| SEC_LOAD
| SEC_IN_MEMORY
| SEC_READONLY
| SEC_HAS_CONTENTS
| SEC_DATA));
if (sec == NULL)
info->callbacks->einfo (_("%F: failed to create GNU property section\n"));
if (!bfd_set_section_alignment (ebfd, sec,
ABI_64_P (ebfd) ? 3 : 2))
{
error_alignment:
info->callbacks->einfo (_("%F%A: failed to align section\n"),
sec);
}
elf_section_type (sec) = SHT_NOTE;
}
}
pbfd = _bfd_elf_link_setup_gnu_properties (info);
if (bfd_link_relocatable (info))
return pbfd;
htab = elf_x86_hash_table (info, X86_64_ELF_DATA);
if (htab == NULL)
return pbfd;
use_ibt_plt = info->ibtplt || info->ibt;
if (!use_ibt_plt && pbfd != NULL)
{
/* Check if GNU_PROPERTY_X86_FEATURE_1_IBT is on. */
elf_property_list *p;
/* The property list is sorted in order of type. */
for (p = elf_properties (pbfd); p; p = p->next)
{
if (GNU_PROPERTY_X86_FEATURE_1_AND == p->property.pr_type)
{
use_ibt_plt = !!(p->property.u.number
& GNU_PROPERTY_X86_FEATURE_1_IBT);
break;
}
else if (GNU_PROPERTY_X86_FEATURE_1_AND < p->property.pr_type)
break;
}
}
dynobj = htab->elf.dynobj;
/* Set htab->elf.dynobj here so that there is no need to check and
set it in check_relocs. */
if (dynobj == NULL)
{
if (pbfd != NULL)
{
htab->elf.dynobj = pbfd;
dynobj = pbfd;
plt_layout.lazy_plt = &elf_x86_64_lazy_bnd_plt;
plt_layout.non_lazy_plt = &elf_x86_64_non_lazy_bnd_plt;
}
else
{
bfd *abfd;
/* Find a normal input file to hold linker created
sections. */
for (abfd = info->input_bfds;
abfd != NULL;
abfd = abfd->link.next)
if (bfd_get_flavour (abfd) == bfd_target_elf_flavour
&& (abfd->flags
& (DYNAMIC | BFD_LINKER_CREATED | BFD_PLUGIN)) == 0)
{
htab->elf.dynobj = abfd;
dynobj = abfd;
break;
}
plt_layout.lazy_plt = &elf_x86_64_lazy_plt;
plt_layout.non_lazy_plt = &elf_x86_64_non_lazy_plt;
}
}
/* Even when lazy binding is disabled by "-z now", the PLT0 entry may
still be used with LD_AUDIT or LD_PROFILE if PLT entry is used for
canonical function address. */
htab->plt.has_plt0 = 1;
if (get_elf_x86_64_backend_data (info->output_bfd)->os
== is_normal)
{
if (use_ibt_plt)
if (ABI_64_P (info->output_bfd))
{
if (ABI_64_P (dynobj))
{
htab->lazy_plt
= &elf_x86_64_lazy_ibt_plt;
htab->non_lazy_plt
= &elf_x86_64_non_lazy_ibt_plt;
}
else
{
htab->lazy_plt
= &elf_x32_lazy_ibt_plt;
htab->non_lazy_plt
= &elf_x32_non_lazy_ibt_plt;
}
}
else if (info->bndplt)
{
htab->lazy_plt = &elf_x86_64_lazy_bnd_plt;
htab->non_lazy_plt = &elf_x86_64_non_lazy_bnd_plt;
plt_layout.lazy_ibt_plt = &elf_x86_64_lazy_ibt_plt;
plt_layout.non_lazy_ibt_plt = &elf_x86_64_non_lazy_ibt_plt;
}
else
{
htab->lazy_plt = &elf_x86_64_lazy_plt;
htab->non_lazy_plt = &elf_x86_64_non_lazy_plt;
plt_layout.lazy_ibt_plt = &elf_x32_lazy_ibt_plt;
plt_layout.non_lazy_ibt_plt = &elf_x32_non_lazy_ibt_plt;
}
normal_target = TRUE;
plt_layout.normal_target = TRUE;
}
else
{
htab->lazy_plt = &elf_x86_64_nacl_plt;
htab->non_lazy_plt = NULL;
normal_target = FALSE;
plt_layout.lazy_plt = &elf_x86_64_nacl_plt;
plt_layout.non_lazy_plt = NULL;
plt_layout.lazy_ibt_plt = NULL;
plt_layout.non_lazy_ibt_plt = NULL;
plt_layout.normal_target = FALSE;
}
pltsec = htab->elf.splt;
/* If the non-lazy PLT is available, use it for all PLT entries if
there are no PLT0 or no .plt section. */
if (htab->non_lazy_plt != NULL
&& (!htab->plt.has_plt0 || pltsec == NULL))
{
lazy_plt = FALSE;
htab->plt.plt_entry = htab->non_lazy_plt->plt_entry;
htab->plt.plt_entry_size = htab->non_lazy_plt->plt_entry_size;
htab->plt.plt_got_offset = htab->non_lazy_plt->plt_got_offset;
htab->plt.plt_got_insn_size
= htab->non_lazy_plt->plt_got_insn_size;
htab->plt.eh_frame_plt_size
= htab->non_lazy_plt->eh_frame_plt_size;
htab->plt.eh_frame_plt = htab->non_lazy_plt->eh_frame_plt;
}
else
{
lazy_plt = TRUE;
htab->plt.plt_entry = htab->lazy_plt->plt_entry;
htab->plt.plt_entry_size = htab->lazy_plt->plt_entry_size;
htab->plt.plt_got_offset = htab->lazy_plt->plt_got_offset;
htab->plt.plt_got_insn_size
= htab->lazy_plt->plt_got_insn_size;
htab->plt.eh_frame_plt_size
= htab->lazy_plt->eh_frame_plt_size;
htab->plt.eh_frame_plt = htab->lazy_plt->eh_frame_plt;
}
/* This is unused for x86-64. */
htab->plt.plt0_entry = NULL;
/* Return if there are no normal input files. */
if (dynobj == NULL)
return pbfd;
/* Since create_dynamic_sections isn't always called, but GOT
relocations need GOT relocations, create them here so that we
don't need to do it in check_relocs. */
if (htab->elf.sgot == NULL
&& !_bfd_elf_create_got_section (dynobj, info))
info->callbacks->einfo (_("%F: failed to create GOT sections\n"));
/* Align .got and .got.plt sections to their entry size. Do it here
instead of in create_dynamic_sections so that they are always
properly aligned even if create_dynamic_sections isn't called. */
sec = htab->elf.sgot;
if (!bfd_set_section_alignment (dynobj, sec, 3))
goto error_alignment;
sec = htab->elf.sgotplt;
if (!bfd_set_section_alignment (dynobj, sec, 3))
goto error_alignment;
/* Create the ifunc sections here so that check_relocs can be
simplified. */
if (!_bfd_elf_create_ifunc_sections (dynobj, info))
info->callbacks->einfo (_("%F: failed to create ifunc sections\n"));
plt_alignment = bfd_log2 (htab->plt.plt_entry_size);
if (pltsec != NULL)
{
/* Whe creating executable, set the contents of the .interp
section to the interpreter. */
if (bfd_link_executable (info) && !info->nointerp)
{
asection *s = bfd_get_linker_section (dynobj, ".interp");
if (s == NULL)
abort ();
s->size = htab->dynamic_interpreter_size;
s->contents = (unsigned char *) htab->dynamic_interpreter;
htab->interp = s;
}
/* Don't change PLT section alignment for NaCl since it uses
64-byte PLT entry and sets PLT section alignment to 32
bytes. Don't create additional PLT sections for NaCl. */
if (normal_target)
{
const struct elf_backend_data *bed
= get_elf_backend_data (dynobj);
flagword pltflags = (bed->dynamic_sec_flags
| SEC_ALLOC
| SEC_CODE
| SEC_LOAD
| SEC_READONLY);
unsigned int non_lazy_plt_alignment
= bfd_log2 (htab->non_lazy_plt->plt_entry_size);
sec = pltsec;
if (!bfd_set_section_alignment (sec->owner, sec,
plt_alignment))
goto error_alignment;
/* Create the GOT procedure linkage table. */
sec = bfd_make_section_anyway_with_flags (dynobj,
".plt.got",
pltflags);
if (sec == NULL)
info->callbacks->einfo (_("%F: failed to create GOT PLT section\n"));
if (!bfd_set_section_alignment (dynobj, sec,
non_lazy_plt_alignment))
goto error_alignment;
htab->plt_got = sec;
if (lazy_plt)
{
sec = NULL;
if (use_ibt_plt)
{
/* Create the second PLT for Intel IBT support. IBT
PLT is supported only for non-NaCl target and is
is needed only for lazy binding. */
sec = bfd_make_section_anyway_with_flags (dynobj,
".plt.sec",
pltflags);
if (sec == NULL)
info->callbacks->einfo (_("%F: failed to create IBT-enabled PLT section\n"));
if (!bfd_set_section_alignment (dynobj, sec,
plt_alignment))
goto error_alignment;
}
else if (info->bndplt && ABI_64_P (dynobj))
{
/* Create the second PLT for Intel MPX support. MPX
PLT is supported only for non-NaCl target in 64-bit
mode and is needed only for lazy binding. */
sec = bfd_make_section_anyway_with_flags (dynobj,
".plt.sec",
pltflags);
if (sec == NULL)
info->callbacks->einfo (_("%F: failed to create BND PLT section\n"));
if (!bfd_set_section_alignment (dynobj, sec,
non_lazy_plt_alignment))
goto error_alignment;
}
htab->plt_second = sec;
}
}
if (!info->no_ld_generated_unwind_info)
{
flagword flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY
| SEC_HAS_CONTENTS | SEC_IN_MEMORY
| SEC_LINKER_CREATED);
sec = bfd_make_section_anyway_with_flags (dynobj,
".eh_frame",
flags);
if (sec == NULL)
info->callbacks->einfo (_("%F: failed to create PLT .eh_frame section\n"));
if (!bfd_set_section_alignment (dynobj, sec,
ABI_64_P (dynobj) ? 3 : 2))
goto error_alignment;
htab->plt_eh_frame = sec;
if (htab->plt_got != NULL)
{
sec = bfd_make_section_anyway_with_flags (dynobj,
".eh_frame",
flags);
if (sec == NULL)
info->callbacks->einfo (_("%F: failed to create GOT PLT .eh_frame section\n"));
if (!bfd_set_section_alignment (dynobj, sec,
ABI_64_P (dynobj) ? 3 : 2))
goto error_alignment;
htab->plt_got_eh_frame = sec;
}
if (htab->plt_second != NULL)
{
sec = bfd_make_section_anyway_with_flags (dynobj,
".eh_frame",
flags);
if (sec == NULL)
info->callbacks->einfo (_("%F: failed to create the second PLT .eh_frame section\n"));
if (!bfd_set_section_alignment (dynobj, sec,
ABI_64_P (dynobj) ? 3 : 2))
goto error_alignment;
htab->plt_second_eh_frame = sec;
}
}
}
if (normal_target)
{
/* The .iplt section is used for IFUNC symbols in static
executables. */
sec = htab->elf.iplt;
if (sec != NULL
&& !bfd_set_section_alignment (sec->owner, sec,
plt_alignment))
goto error_alignment;
}
return pbfd;
return _bfd_x86_elf_link_setup_gnu_properties (info, &plt_layout);
}
static const struct bfd_elf_special_section
@ -7062,8 +6720,8 @@ static const struct elf_x86_lazy_plt_layout elf_x86_64_nacl_plt =
7, /* plt_got_insn_size */
42, /* plt_plt_insn_end */
32, /* plt_lazy_offset */
NULL, /* pic_plt0_entry */
NULL, /* pic_plt_entry */
elf_x86_64_nacl_plt0_entry, /* pic_plt0_entry */
elf_x86_64_nacl_plt_entry, /* pic_plt_entry */
elf_x86_64_nacl_eh_frame_plt, /* eh_frame_plt */
sizeof (elf_x86_64_nacl_eh_frame_plt) /* eh_frame_plt_size */
};

View File

@ -19,6 +19,7 @@
MA 02110-1301, USA. */
#include "elfxx-x86.h"
#include "elf-vxworks.h"
#include "objalloc.h"
#include "elf/i386.h"
#include "elf/x86-64.h"
@ -900,3 +901,392 @@ _bfd_x86_elf_merge_gnu_properties (struct bfd_link_info *info,
return updated;
}
/* Set up x86 GNU properties. Return the first relocatable ELF input
with GNU properties if found. Otherwise, return NULL. */
bfd *
_bfd_x86_elf_link_setup_gnu_properties
(struct bfd_link_info *info,
struct elf_x86_plt_layout_table *plt_layout)
{
bfd_boolean normal_target;
bfd_boolean lazy_plt;
asection *sec, *pltsec;
bfd *dynobj;
bfd_boolean use_ibt_plt;
unsigned int plt_alignment, features;
struct elf_x86_link_hash_table *htab;
bfd *pbfd;
bfd *ebfd = NULL;
elf_property *prop;
const struct elf_backend_data *bed;
unsigned int class_align = ABI_64_P (info->output_bfd) ? 3 : 2;
unsigned int got_align;
features = 0;
if (info->ibt)
features = GNU_PROPERTY_X86_FEATURE_1_IBT;
if (info->shstk)
features |= GNU_PROPERTY_X86_FEATURE_1_SHSTK;
/* Find a normal input file with GNU property note. */
for (pbfd = info->input_bfds;
pbfd != NULL;
pbfd = pbfd->link.next)
if (bfd_get_flavour (pbfd) == bfd_target_elf_flavour
&& bfd_count_sections (pbfd) != 0)
{
ebfd = pbfd;
if (elf_properties (pbfd) != NULL)
break;
}
if (ebfd != NULL && features)
{
/* If features is set, add GNU_PROPERTY_X86_FEATURE_1_IBT and
GNU_PROPERTY_X86_FEATURE_1_SHSTK. */
prop = _bfd_elf_get_property (ebfd,
GNU_PROPERTY_X86_FEATURE_1_AND,
4);
prop->u.number |= features;
prop->pr_kind = property_number;
/* Create the GNU property note section if needed. */
if (pbfd == NULL)
{
sec = bfd_make_section_with_flags (ebfd,
NOTE_GNU_PROPERTY_SECTION_NAME,
(SEC_ALLOC
| SEC_LOAD
| SEC_IN_MEMORY
| SEC_READONLY
| SEC_HAS_CONTENTS
| SEC_DATA));
if (sec == NULL)
info->callbacks->einfo (_("%F: failed to create GNU property section\n"));
if (!bfd_set_section_alignment (ebfd, sec, class_align))
{
error_alignment:
info->callbacks->einfo (_("%F%A: failed to align section\n"),
sec);
}
elf_section_type (sec) = SHT_NOTE;
}
}
pbfd = _bfd_elf_link_setup_gnu_properties (info);
if (bfd_link_relocatable (info))
return pbfd;
bed = get_elf_backend_data (info->output_bfd);
htab = elf_x86_hash_table (info, bed->target_id);
if (htab == NULL)
return pbfd;
use_ibt_plt = info->ibtplt || info->ibt;
if (!use_ibt_plt && pbfd != NULL)
{
/* Check if GNU_PROPERTY_X86_FEATURE_1_IBT is on. */
elf_property_list *p;
/* The property list is sorted in order of type. */
for (p = elf_properties (pbfd); p; p = p->next)
{
if (GNU_PROPERTY_X86_FEATURE_1_AND == p->property.pr_type)
{
use_ibt_plt = !!(p->property.u.number
& GNU_PROPERTY_X86_FEATURE_1_IBT);
break;
}
else if (GNU_PROPERTY_X86_FEATURE_1_AND < p->property.pr_type)
break;
}
}
dynobj = htab->elf.dynobj;
/* Set htab->elf.dynobj here so that there is no need to check and
set it in check_relocs. */
if (dynobj == NULL)
{
if (pbfd != NULL)
{
htab->elf.dynobj = pbfd;
dynobj = pbfd;
}
else
{
bfd *abfd;
/* Find a normal input file to hold linker created
sections. */
for (abfd = info->input_bfds;
abfd != NULL;
abfd = abfd->link.next)
if (bfd_get_flavour (abfd) == bfd_target_elf_flavour
&& (abfd->flags
& (DYNAMIC | BFD_LINKER_CREATED | BFD_PLUGIN)) == 0)
{
htab->elf.dynobj = abfd;
dynobj = abfd;
break;
}
}
}
/* Even when lazy binding is disabled by "-z now", the PLT0 entry may
still be used with LD_AUDIT or LD_PROFILE if PLT entry is used for
canonical function address. */
htab->plt.has_plt0 = 1;
normal_target = plt_layout->normal_target;
if (normal_target)
{
if (use_ibt_plt)
{
htab->lazy_plt = plt_layout->lazy_ibt_plt;
htab->non_lazy_plt = plt_layout->non_lazy_ibt_plt;
}
else
{
htab->lazy_plt = plt_layout->lazy_plt;
htab->non_lazy_plt = plt_layout->non_lazy_plt;
}
}
else
{
htab->lazy_plt = plt_layout->lazy_plt;
htab->non_lazy_plt = NULL;
}
pltsec = htab->elf.splt;
/* If the non-lazy PLT is available, use it for all PLT entries if
there are no PLT0 or no .plt section. */
if (htab->non_lazy_plt != NULL
&& (!htab->plt.has_plt0 || pltsec == NULL))
{
lazy_plt = FALSE;
if (bfd_link_pic (info))
htab->plt.plt_entry = htab->non_lazy_plt->pic_plt_entry;
else
htab->plt.plt_entry = htab->non_lazy_plt->plt_entry;
htab->plt.plt_entry_size = htab->non_lazy_plt->plt_entry_size;
htab->plt.plt_got_offset = htab->non_lazy_plt->plt_got_offset;
htab->plt.plt_got_insn_size
= htab->non_lazy_plt->plt_got_insn_size;
htab->plt.eh_frame_plt_size
= htab->non_lazy_plt->eh_frame_plt_size;
htab->plt.eh_frame_plt = htab->non_lazy_plt->eh_frame_plt;
}
else
{
lazy_plt = TRUE;
if (bfd_link_pic (info))
{
htab->plt.plt0_entry = htab->lazy_plt->pic_plt0_entry;
htab->plt.plt_entry = htab->lazy_plt->pic_plt_entry;
}
else
{
htab->plt.plt0_entry = htab->lazy_plt->plt0_entry;
htab->plt.plt_entry = htab->lazy_plt->plt_entry;
}
htab->plt.plt_entry_size = htab->lazy_plt->plt_entry_size;
htab->plt.plt_got_offset = htab->lazy_plt->plt_got_offset;
htab->plt.plt_got_insn_size
= htab->lazy_plt->plt_got_insn_size;
htab->plt.eh_frame_plt_size
= htab->lazy_plt->eh_frame_plt_size;
htab->plt.eh_frame_plt = htab->lazy_plt->eh_frame_plt;
}
/* Return if there are no normal input files. */
if (dynobj == NULL)
return pbfd;
if (plt_layout->is_vxworks
&& !elf_vxworks_create_dynamic_sections (dynobj, info,
&htab->srelplt2))
{
info->callbacks->einfo (_("%F: failed to create VxWorks dynamic sections\n"));
return pbfd;
}
/* Since create_dynamic_sections isn't always called, but GOT
relocations need GOT relocations, create them here so that we
don't need to do it in check_relocs. */
if (htab->elf.sgot == NULL
&& !_bfd_elf_create_got_section (dynobj, info))
info->callbacks->einfo (_("%F: failed to create GOT sections\n"));
got_align = (bed->target_id == X86_64_ELF_DATA) ? 3 : 2;
/* Align .got and .got.plt sections to their entry size. Do it here
instead of in create_dynamic_sections so that they are always
properly aligned even if create_dynamic_sections isn't called. */
sec = htab->elf.sgot;
if (!bfd_set_section_alignment (dynobj, sec, got_align))
goto error_alignment;
sec = htab->elf.sgotplt;
if (!bfd_set_section_alignment (dynobj, sec, got_align))
goto error_alignment;
/* Create the ifunc sections here so that check_relocs can be
simplified. */
if (!_bfd_elf_create_ifunc_sections (dynobj, info))
info->callbacks->einfo (_("%F: failed to create ifunc sections\n"));
plt_alignment = bfd_log2 (htab->plt.plt_entry_size);
if (pltsec != NULL)
{
/* Whe creating executable, set the contents of the .interp
section to the interpreter. */
if (bfd_link_executable (info) && !info->nointerp)
{
asection *s = bfd_get_linker_section (dynobj, ".interp");
if (s == NULL)
abort ();
s->size = htab->dynamic_interpreter_size;
s->contents = (unsigned char *) htab->dynamic_interpreter;
htab->interp = s;
}
/* Don't change PLT section alignment for NaCl since it uses
64-byte PLT entry and sets PLT section alignment to 32
bytes. Don't create additional PLT sections for NaCl. */
if (normal_target)
{
flagword pltflags = (bed->dynamic_sec_flags
| SEC_ALLOC
| SEC_CODE
| SEC_LOAD
| SEC_READONLY);
unsigned int non_lazy_plt_alignment
= bfd_log2 (htab->non_lazy_plt->plt_entry_size);
sec = pltsec;
if (!bfd_set_section_alignment (sec->owner, sec,
plt_alignment))
goto error_alignment;
/* Create the GOT procedure linkage table. */
sec = bfd_make_section_anyway_with_flags (dynobj,
".plt.got",
pltflags);
if (sec == NULL)
info->callbacks->einfo (_("%F: failed to create GOT PLT section\n"));
if (!bfd_set_section_alignment (dynobj, sec,
non_lazy_plt_alignment))
goto error_alignment;
htab->plt_got = sec;
if (lazy_plt)
{
sec = NULL;
if (use_ibt_plt)
{
/* Create the second PLT for Intel IBT support. IBT
PLT is supported only for non-NaCl target and is
is needed only for lazy binding. */
sec = bfd_make_section_anyway_with_flags (dynobj,
".plt.sec",
pltflags);
if (sec == NULL)
info->callbacks->einfo (_("%F: failed to create IBT-enabled PLT section\n"));
if (!bfd_set_section_alignment (dynobj, sec,
plt_alignment))
goto error_alignment;
}
else if (info->bndplt && ABI_64_P (dynobj))
{
/* Create the second PLT for Intel MPX support. MPX
PLT is supported only for non-NaCl target in 64-bit
mode and is needed only for lazy binding. */
sec = bfd_make_section_anyway_with_flags (dynobj,
".plt.sec",
pltflags);
if (sec == NULL)
info->callbacks->einfo (_("%F: failed to create BND PLT section\n"));
if (!bfd_set_section_alignment (dynobj, sec,
non_lazy_plt_alignment))
goto error_alignment;
}
htab->plt_second = sec;
}
}
if (!info->no_ld_generated_unwind_info)
{
flagword flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY
| SEC_HAS_CONTENTS | SEC_IN_MEMORY
| SEC_LINKER_CREATED);
sec = bfd_make_section_anyway_with_flags (dynobj,
".eh_frame",
flags);
if (sec == NULL)
info->callbacks->einfo (_("%F: failed to create PLT .eh_frame section\n"));
if (!bfd_set_section_alignment (dynobj, sec, class_align))
goto error_alignment;
htab->plt_eh_frame = sec;
if (htab->plt_got != NULL)
{
sec = bfd_make_section_anyway_with_flags (dynobj,
".eh_frame",
flags);
if (sec == NULL)
info->callbacks->einfo (_("%F: failed to create GOT PLT .eh_frame section\n"));
if (!bfd_set_section_alignment (dynobj, sec, class_align))
goto error_alignment;
htab->plt_got_eh_frame = sec;
}
if (htab->plt_second != NULL)
{
sec = bfd_make_section_anyway_with_flags (dynobj,
".eh_frame",
flags);
if (sec == NULL)
info->callbacks->einfo (_("%F: failed to create the second PLT .eh_frame section\n"));
if (!bfd_set_section_alignment (dynobj, sec, class_align))
goto error_alignment;
htab->plt_second_eh_frame = sec;
}
}
}
if (normal_target)
{
/* The .iplt section is used for IFUNC symbols in static
executables. */
sec = htab->elf.iplt;
if (sec != NULL
&& !bfd_set_section_alignment (sec->owner, sec,
plt_alignment))
goto error_alignment;
}
return pbfd;
}

View File

@ -159,11 +159,11 @@ struct elf_x86_lazy_plt_layout
unsigned int plt_lazy_offset;
/* The first entry in a PIC lazy procedure linkage table looks like
this. This is used for i386 only. */
this. */
const bfd_byte *pic_plt0_entry;
/* Subsequent entries in a PIC lazy procedure linkage table look
like this. This is used for i386 only. */
like this. */
const bfd_byte *pic_plt_entry;
/* .eh_frame covering the lazy .plt section. */
@ -176,8 +176,7 @@ struct elf_x86_non_lazy_plt_layout
/* Entries in an absolute non-lazy procedure linkage table look like
this. */
const bfd_byte *plt_entry;
/* Entries in a PIC non-lazy procedure linkage table look like this.
This is used for i386 only. */
/* Entries in a PIC non-lazy procedure linkage table look like this. */
const bfd_byte *pic_plt_entry;
unsigned int plt_entry_size; /* Size of each PLT entry. */
@ -304,6 +303,27 @@ struct elf_x86_link_hash_table
const char *tls_get_addr;
};
struct elf_x86_plt_layout_table
{
/* The lazy PLT layout. */
const struct elf_x86_lazy_plt_layout *lazy_plt;
/* The non-lazy PLT layout. */
const struct elf_x86_non_lazy_plt_layout *non_lazy_plt;
/* The lazy PLT layout for IBT. */
const struct elf_x86_lazy_plt_layout *lazy_ibt_plt;
/* The non-lazy PLT layout for IBT. */
const struct elf_x86_non_lazy_plt_layout *non_lazy_ibt_plt;
/* TRUE if this is an normal x86 target. */
bfd_boolean normal_target;
/* TRUE if this is a VxWorks x86 target. */
bfd_boolean is_vxworks;
};
struct elf_x86_obj_tdata
{
struct elf_obj_tdata root;
@ -403,6 +423,9 @@ extern enum elf_property_kind _bfd_x86_elf_parse_gnu_properties
extern bfd_boolean _bfd_x86_elf_merge_gnu_properties
(struct bfd_link_info *, bfd *, elf_property *, elf_property *);
extern bfd * _bfd_x86_elf_link_setup_gnu_properties
(struct bfd_link_info *, struct elf_x86_plt_layout_table *);
#define bfd_elf64_bfd_link_hash_table_create \
_bfd_x86_elf_link_hash_table_create
#define bfd_elf32_bfd_link_hash_table_create \