Disallow copy relocation against protected data symbol
We shpouldn't generate copy relocation to resolve reference to protected data symbol defined in shared object with the NO_COPY_ON_PROTECTED property. This patch adds a bit to elf_obj_tdata as well as elf_i386_link_hash_entry and elf_x86_64_link_hash_entry to track the bfd with the NO_COPY_ON_PROTECTED property as well as protected symbol defined in shared object. extern_protected_data is set to FALSE if any input relocatable file contains the NO_COPY_ON_PROTECTED property. bfd/ PR ld/21997 * elf-bfd.h (elf_obj_tdata): Use ENUM_BITFIELD on object_id, dyn_lib_class and has_gnu_symbols. Change bad_symtab to bitfield. Add a has_no_copy_on_protected bitfield. (elf_has_no_copy_on_protected): New. * elf-properties.c (_bfd_elf_parse_gnu_properties): Set elf_has_no_copy_on_protected for GNU_PROPERTY_NO_COPY_ON_PROTECTED. (elf_merge_gnu_property_list): Likewise. (_bfd_elf_link_setup_gnu_properties): Set extern_protected_data to FALSE for elf_has_no_copy_on_protected. * elf32-i386.c (SYMBOL_NO_COPYRELOC): New. (elf_i386_link_hash_entry): Add def_protected. (elf_i386_adjust_dynamic_symbol): Also check SYMBOL_NO_COPYRELOC when checking info->nocopyreloc. (elf_i386_link_setup_gnu_properties): Don't set extern_protected_data here. (elf_i386_merge_symbol_attribute): New function. (elf_backend_merge_symbol_attribute): New. * elf64-x86-64.c (SYMBOL_NO_COPYRELOC): New. (elf_x86_64_link_hash_entry): Add def_protected. (elf_x86_64_need_pic): Report protected symbol for def_protected. (elf_x86_64_adjust_dynamic_symbol): Also check SYMBOL_NO_COPYRELOC when checking info->nocopyreloc. (elf_x86_64_relocate_section): Also check for R_X86_64_PC32 relocation run-time overflow and unresolvable R_X86_64_32S relocation against protected data symbol defined in shared object with GNU_PROPERTY_NO_COPY_ON_PROTECTED. (elf_x86_64_link_setup_gnu_properties): Don't set extern_protected_data here. (elf_x86_64_merge_symbol_attribute): New function. (elf_backend_merge_symbol_attribute): New. ld/ PR ld/21997 * testsuite/ld-i386/i386.exp: Run PR ld/21997 tests. * testsuite/ld-x86-64/x86-64.exp: Likewise. * testsuite/ld-i386/pr21997-1a.S: New file. * testsuite/ld-i386/pr21997-1b.c: Likewise. * testsuite/ld-i386/pr21997-1c.S: Likewise. * testsuite/ld-x86-64/pr21997-1a.S: Likewise. * testsuite/ld-x86-64/pr21997-1a.err: Likewise. * testsuite/ld-x86-64/pr21997-1b.c: Likewise. * testsuite/ld-x86-64/pr21997-1b.err: Likewise. * testsuite/ld-x86-64/pr21997-1c.c: Likewise.
This commit is contained in:
parent
aecbb010f9
commit
a5b4ee9451
|
@ -1,3 +1,37 @@
|
|||
2017-08-26 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
PR ld/21997
|
||||
* elf-bfd.h (elf_obj_tdata): Use ENUM_BITFIELD on object_id,
|
||||
dyn_lib_class and has_gnu_symbols. Change bad_symtab to bitfield.
|
||||
Add a has_no_copy_on_protected bitfield.
|
||||
(elf_has_no_copy_on_protected): New.
|
||||
* elf-properties.c (_bfd_elf_parse_gnu_properties): Set
|
||||
elf_has_no_copy_on_protected for GNU_PROPERTY_NO_COPY_ON_PROTECTED.
|
||||
(elf_merge_gnu_property_list): Likewise.
|
||||
(_bfd_elf_link_setup_gnu_properties): Set extern_protected_data
|
||||
to FALSE for elf_has_no_copy_on_protected.
|
||||
* elf32-i386.c (SYMBOL_NO_COPYRELOC): New.
|
||||
(elf_i386_link_hash_entry): Add def_protected.
|
||||
(elf_i386_adjust_dynamic_symbol): Also check SYMBOL_NO_COPYRELOC
|
||||
when checking info->nocopyreloc.
|
||||
(elf_i386_link_setup_gnu_properties): Don't set
|
||||
extern_protected_data here.
|
||||
(elf_i386_merge_symbol_attribute): New function.
|
||||
(elf_backend_merge_symbol_attribute): New.
|
||||
* elf64-x86-64.c (SYMBOL_NO_COPYRELOC): New.
|
||||
(elf_x86_64_link_hash_entry): Add def_protected.
|
||||
(elf_x86_64_need_pic): Report protected symbol for def_protected.
|
||||
(elf_x86_64_adjust_dynamic_symbol): Also check SYMBOL_NO_COPYRELOC
|
||||
when checking info->nocopyreloc.
|
||||
(elf_x86_64_relocate_section): Also check for R_X86_64_PC32
|
||||
relocation run-time overflow and unresolvable R_X86_64_32S
|
||||
relocation against protected data symbol defined in shared object
|
||||
with GNU_PROPERTY_NO_COPY_ON_PROTECTED.
|
||||
(elf_x86_64_link_setup_gnu_properties): Don't set
|
||||
extern_protected_data here.
|
||||
(elf_x86_64_merge_symbol_attribute): New function.
|
||||
(elf_backend_merge_symbol_attribute): New.
|
||||
|
||||
2017-08-26 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* elf32-ppc.c (must_be_dyn_reloc): Use bfd_link_dll. Comment.
|
||||
|
|
|
@ -1887,21 +1887,27 @@ struct elf_obj_tdata
|
|||
|
||||
/* An identifier used to distinguish different target
|
||||
specific extensions to this structure. */
|
||||
enum elf_target_id object_id;
|
||||
ENUM_BITFIELD (elf_target_id) object_id : 6;
|
||||
|
||||
/* Whether a dyanmic object was specified normally on the linker
|
||||
command line, or was specified when --as-needed was in effect,
|
||||
or was found via a DT_NEEDED entry. */
|
||||
enum dynamic_lib_link_class dyn_lib_class;
|
||||
ENUM_BITFIELD (dynamic_lib_link_class) dyn_lib_class : 4;
|
||||
|
||||
/* Whether if the bfd contains symbols that have the STT_GNU_IFUNC
|
||||
symbol type or STB_GNU_UNIQUE binding. */
|
||||
ENUM_BITFIELD (elf_gnu_symbols) has_gnu_symbols : 3;
|
||||
|
||||
/* Whether if the bfd contains the GNU_PROPERTY_NO_COPY_ON_PROTECTED
|
||||
property. */
|
||||
unsigned int has_no_copy_on_protected : 1;
|
||||
|
||||
/* Irix 5 often screws up the symbol table, sorting local symbols
|
||||
after global symbols. This flag is set if the symbol table in
|
||||
this BFD appears to be screwed up. If it is, we ignore the
|
||||
sh_info field in the symbol table header, and always read all the
|
||||
symbols. */
|
||||
bfd_boolean bad_symtab;
|
||||
|
||||
enum elf_gnu_symbols has_gnu_symbols;
|
||||
unsigned int bad_symtab : 1;
|
||||
|
||||
/* Information grabbed from an elf core file. */
|
||||
struct core_elf_obj_tdata *core;
|
||||
|
@ -1956,6 +1962,8 @@ struct elf_obj_tdata
|
|||
#define elf_other_obj_attributes_proc(bfd) \
|
||||
(elf_other_obj_attributes (bfd) [OBJ_ATTR_PROC])
|
||||
#define elf_properties(bfd) (elf_tdata (bfd) -> properties)
|
||||
#define elf_has_no_copy_on_protected(bfd) \
|
||||
(elf_tdata(bfd) -> has_no_copy_on_protected)
|
||||
|
||||
extern void _bfd_elf_swap_verdef_in
|
||||
(bfd *, const Elf_External_Verdef *, Elf_Internal_Verdef *);
|
||||
|
|
|
@ -168,6 +168,7 @@ bad_size:
|
|||
return FALSE;
|
||||
}
|
||||
prop = _bfd_elf_get_property (abfd, type, datasz);
|
||||
elf_has_no_copy_on_protected (abfd) = TRUE;
|
||||
prop->pr_kind = property_number;
|
||||
goto next;
|
||||
|
||||
|
@ -290,6 +291,9 @@ elf_merge_gnu_property_list (struct bfd_link_info *info, bfd *abfd,
|
|||
for (p = *listp; p != NULL; p = p->next)
|
||||
if (elf_merge_gnu_properties (info, abfd, NULL, &p->property))
|
||||
{
|
||||
if (p->property.pr_type == GNU_PROPERTY_NO_COPY_ON_PROTECTED)
|
||||
elf_has_no_copy_on_protected (abfd) = TRUE;
|
||||
|
||||
pr = _bfd_elf_get_property (abfd, p->property.pr_type,
|
||||
p->property.pr_datasz);
|
||||
/* It must be a new property. */
|
||||
|
@ -489,6 +493,11 @@ _bfd_elf_link_setup_gnu_properties (struct bfd_link_info *info)
|
|||
|
||||
/* Cache the section contents for elf_link_input_bfd. */
|
||||
elf_section_data (sec)->this_hdr.contents = contents;
|
||||
|
||||
/* If GNU_PROPERTY_NO_COPY_ON_PROTECTED is set, protected data
|
||||
symbol is defined in the shared object. */
|
||||
if (elf_has_no_copy_on_protected (first_pbfd))
|
||||
info->extern_protected_data = FALSE;
|
||||
}
|
||||
|
||||
return first_pbfd;
|
||||
|
|
121
bfd/elf32-i386.c
121
bfd/elf32-i386.c
|
@ -956,6 +956,18 @@ static const struct elf_i386_backend_data elf_i386_arch_bed =
|
|||
|| (EH)->has_non_got_reloc \
|
||||
|| !(INFO)->dynamic_undefined_weak))))
|
||||
|
||||
/* Should copy relocation be generated for a symbol. Don't generate
|
||||
copy relocation against a protected symbol defined in a shared
|
||||
object with GNU_PROPERTY_NO_COPY_ON_PROTECTED. */
|
||||
#define SYMBOL_NO_COPYRELOC(INFO, EH) \
|
||||
((EH)->def_protected \
|
||||
&& ((EH)->elf.root.type == bfd_link_hash_defined \
|
||||
|| (EH)->elf.root.type == bfd_link_hash_defweak) \
|
||||
&& elf_has_no_copy_on_protected ((EH)->elf.root.u.def.section->owner) \
|
||||
&& ((EH)->elf.root.u.def.section->owner->flags & DYNAMIC) != 0 \
|
||||
&& ((EH)->elf.root.u.def.section->flags & SEC_CODE) == 0)
|
||||
|
||||
|
||||
/* i386 ELF linker hash entry. */
|
||||
|
||||
struct elf_i386_link_hash_entry
|
||||
|
@ -998,6 +1010,9 @@ struct elf_i386_link_hash_entry
|
|||
/* TRUE if symbol is __tls_get_addr. */
|
||||
unsigned int tls_get_addr : 1;
|
||||
|
||||
/* TRUE if symbol is defined as a protected symbol. */
|
||||
unsigned int def_protected : 1;
|
||||
|
||||
/* Reference count of C/C++ function pointer relocations in read-write
|
||||
section which can be resolved at run-time. */
|
||||
bfd_signed_vma func_pointer_refcount;
|
||||
|
@ -2590,6 +2605,8 @@ elf_i386_adjust_dynamic_symbol (struct bfd_link_info *info,
|
|||
the link may change h->type. So fix it now. */
|
||||
h->plt.offset = (bfd_vma) -1;
|
||||
|
||||
eh = (struct elf_i386_link_hash_entry *) h;
|
||||
|
||||
/* If this is a weak symbol, and there is a real definition, the
|
||||
processor independent code will have arranged for us to see the
|
||||
real definition first, and we can just use the same value. */
|
||||
|
@ -2599,7 +2616,9 @@ elf_i386_adjust_dynamic_symbol (struct bfd_link_info *info,
|
|||
|| h->u.weakdef->root.type == bfd_link_hash_defweak);
|
||||
h->root.u.def.section = h->u.weakdef->root.u.def.section;
|
||||
h->root.u.def.value = h->u.weakdef->root.u.def.value;
|
||||
if (ELIMINATE_COPY_RELOCS || info->nocopyreloc)
|
||||
if (ELIMINATE_COPY_RELOCS
|
||||
|| info->nocopyreloc
|
||||
|| SYMBOL_NO_COPYRELOC (info, eh))
|
||||
h->non_got_ref = h->u.weakdef->non_got_ref;
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -2617,12 +2636,11 @@ elf_i386_adjust_dynamic_symbol (struct bfd_link_info *info,
|
|||
/* If there are no references to this symbol that do not use the
|
||||
GOT nor R_386_GOTOFF relocation, we don't need to generate a copy
|
||||
reloc. */
|
||||
eh = (struct elf_i386_link_hash_entry *) h;
|
||||
if (!h->non_got_ref && !eh->gotoff_ref)
|
||||
return TRUE;
|
||||
|
||||
/* If -z nocopyreloc was given, we won't generate them either. */
|
||||
if (info->nocopyreloc)
|
||||
if (info->nocopyreloc || SYMBOL_NO_COPYRELOC (info, eh))
|
||||
{
|
||||
h->non_got_ref = 0;
|
||||
return TRUE;
|
||||
|
@ -6802,68 +6820,39 @@ elf_i386_link_setup_gnu_properties (struct bfd_link_info *info)
|
|||
break;
|
||||
}
|
||||
|
||||
if (ebfd != NULL)
|
||||
if (ebfd != NULL && features)
|
||||
{
|
||||
if (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)
|
||||
{
|
||||
/* 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;
|
||||
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"));
|
||||
|
||||
/* Create the GNU property note section if needed. */
|
||||
if (pbfd == NULL)
|
||||
if (!bfd_set_section_alignment (ebfd, sec, 2))
|
||||
{
|
||||
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;
|
||||
info->callbacks->einfo (_("%F%A: failed to align section\n"),
|
||||
sec);
|
||||
}
|
||||
|
||||
elf_section_type (sec) = SHT_NOTE;
|
||||
}
|
||||
|
||||
/* Check GNU_PROPERTY_NO_COPY_ON_PROTECTED. */
|
||||
for (; pbfd != NULL; pbfd = pbfd->link.next)
|
||||
if (bfd_get_flavour (pbfd) == bfd_target_elf_flavour
|
||||
&& (pbfd->flags
|
||||
& (DYNAMIC | BFD_LINKER_CREATED | BFD_PLUGIN)) == 0)
|
||||
{
|
||||
elf_property_list *p;
|
||||
|
||||
/* The property list is sorted in order of type. */
|
||||
for (p = elf_properties (pbfd); p != NULL; p = p->next)
|
||||
{
|
||||
if (GNU_PROPERTY_NO_COPY_ON_PROTECTED
|
||||
== p->property.pr_type)
|
||||
{
|
||||
/* Clear extern_protected_data if
|
||||
GNU_PROPERTY_NO_COPY_ON_PROTECTED is
|
||||
set on any input relocatable file. */
|
||||
info->extern_protected_data = FALSE;
|
||||
break;
|
||||
}
|
||||
else if (GNU_PROPERTY_NO_COPY_ON_PROTECTED
|
||||
< p->property.pr_type)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pbfd = _bfd_elf_link_setup_gnu_properties (info);
|
||||
|
@ -7163,6 +7152,21 @@ elf_i386_link_check_relocs (bfd *abfd, struct bfd_link_info *info)
|
|||
return _bfd_elf_link_check_relocs (abfd, info);
|
||||
}
|
||||
|
||||
static void
|
||||
elf_i386_merge_symbol_attribute (struct elf_link_hash_entry *h,
|
||||
const Elf_Internal_Sym *isym,
|
||||
bfd_boolean definition,
|
||||
bfd_boolean dynamic ATTRIBUTE_UNUSED)
|
||||
{
|
||||
if (definition)
|
||||
{
|
||||
struct elf_i386_link_hash_entry *eh
|
||||
= (struct elf_i386_link_hash_entry *) h;
|
||||
eh->def_protected = (ELF_ST_VISIBILITY (isym->st_other)
|
||||
== STV_PROTECTED);
|
||||
}
|
||||
}
|
||||
|
||||
#define TARGET_LITTLE_SYM i386_elf32_vec
|
||||
#define TARGET_LITTLE_NAME "elf32-i386"
|
||||
#define ELF_ARCH bfd_arch_i386
|
||||
|
@ -7218,6 +7222,7 @@ elf_i386_link_check_relocs (bfd *abfd, struct bfd_link_info *info)
|
|||
#define elf_backend_parse_gnu_properties elf_i386_parse_gnu_properties
|
||||
#define elf_backend_merge_gnu_properties elf_i386_merge_gnu_properties
|
||||
#define elf_backend_setup_gnu_properties elf_i386_link_setup_gnu_properties
|
||||
#define elf_backend_merge_symbol_attribute elf_i386_merge_symbol_attribute
|
||||
|
||||
#include "elf32-target.h"
|
||||
|
||||
|
|
|
@ -1061,6 +1061,17 @@ static const struct elf_x86_64_backend_data elf_x86_64_arch_bed =
|
|||
|| (EH)->has_non_got_reloc \
|
||||
|| !(INFO)->dynamic_undefined_weak))))
|
||||
|
||||
/* Should copy relocation be generated for a symbol. Don't generate
|
||||
copy relocation against a protected symbol defined in a shared
|
||||
object with GNU_PROPERTY_NO_COPY_ON_PROTECTED. */
|
||||
#define SYMBOL_NO_COPYRELOC(INFO, EH) \
|
||||
((EH)->def_protected \
|
||||
&& ((EH)->elf.root.type == bfd_link_hash_defined \
|
||||
|| (EH)->elf.root.type == bfd_link_hash_defweak) \
|
||||
&& elf_has_no_copy_on_protected ((EH)->elf.root.u.def.section->owner) \
|
||||
&& ((EH)->elf.root.u.def.section->owner->flags & DYNAMIC) != 0 \
|
||||
&& ((EH)->elf.root.u.def.section->flags & SEC_CODE) == 0)
|
||||
|
||||
/* x86-64 ELF linker hash entry. */
|
||||
|
||||
struct elf_x86_64_link_hash_entry
|
||||
|
@ -1104,6 +1115,9 @@ struct elf_x86_64_link_hash_entry
|
|||
/* TRUE if symbol is __tls_get_addr. */
|
||||
unsigned int tls_get_addr : 1;
|
||||
|
||||
/* TRUE if symbol is defined as a protected symbol. */
|
||||
unsigned int def_protected : 1;
|
||||
|
||||
/* Reference count of C/C++ function pointer relocations in read-write
|
||||
section which can be resolved at run-time. */
|
||||
bfd_signed_vma func_pointer_refcount;
|
||||
|
@ -1908,7 +1922,10 @@ elf_x86_64_need_pic (struct bfd_link_info *info,
|
|||
v = _("protected symbol ");
|
||||
break;
|
||||
default:
|
||||
v = _("symbol ");
|
||||
if (((struct elf_x86_64_link_hash_entry *) h)->def_protected)
|
||||
v = _("protected symbol ");
|
||||
else
|
||||
v = _("symbol ");
|
||||
pic = _("; recompile with -fPIC");
|
||||
break;
|
||||
}
|
||||
|
@ -3043,6 +3060,8 @@ elf_x86_64_adjust_dynamic_symbol (struct bfd_link_info *info,
|
|||
the link may change h->type. So fix it now. */
|
||||
h->plt.offset = (bfd_vma) -1;
|
||||
|
||||
eh = (struct elf_x86_64_link_hash_entry *) h;
|
||||
|
||||
/* If this is a weak symbol, and there is a real definition, the
|
||||
processor independent code will have arranged for us to see the
|
||||
real definition first, and we can just use the same value. */
|
||||
|
@ -3052,9 +3071,10 @@ elf_x86_64_adjust_dynamic_symbol (struct bfd_link_info *info,
|
|||
|| h->u.weakdef->root.type == bfd_link_hash_defweak);
|
||||
h->root.u.def.section = h->u.weakdef->root.u.def.section;
|
||||
h->root.u.def.value = h->u.weakdef->root.u.def.value;
|
||||
if (ELIMINATE_COPY_RELOCS || info->nocopyreloc)
|
||||
if (ELIMINATE_COPY_RELOCS
|
||||
|| info->nocopyreloc
|
||||
|| SYMBOL_NO_COPYRELOC (info, eh))
|
||||
{
|
||||
eh = (struct elf_x86_64_link_hash_entry *) h;
|
||||
h->non_got_ref = h->u.weakdef->non_got_ref;
|
||||
eh->needs_copy = h->u.weakdef->needs_copy;
|
||||
}
|
||||
|
@ -3077,7 +3097,7 @@ elf_x86_64_adjust_dynamic_symbol (struct bfd_link_info *info,
|
|||
return TRUE;
|
||||
|
||||
/* If -z nocopyreloc was given, we won't generate them either. */
|
||||
if (info->nocopyreloc)
|
||||
if (info->nocopyreloc || SYMBOL_NO_COPYRELOC (info, eh))
|
||||
{
|
||||
h->non_got_ref = 0;
|
||||
return TRUE;
|
||||
|
@ -4950,7 +4970,9 @@ do_ifunc_pointer:
|
|||
&& ((bfd_link_executable (info)
|
||||
&& ((h->root.type == bfd_link_hash_undefweak
|
||||
&& !resolved_to_zero)
|
||||
|| (info->nocopyreloc
|
||||
|| ((info->nocopyreloc
|
||||
|| (eh->def_protected
|
||||
&& elf_has_no_copy_on_protected (h->root.u.def.section->owner)))
|
||||
&& h->def_dynamic
|
||||
&& !(h->root.u.def.section->flags & SEC_CODE))))
|
||||
|| bfd_link_dll (info)))
|
||||
|
@ -5724,7 +5746,10 @@ direct:
|
|||
switch (r_type)
|
||||
{
|
||||
case R_X86_64_32S:
|
||||
if (info->nocopyreloc
|
||||
sec = h->root.u.def.section;
|
||||
if ((info->nocopyreloc
|
||||
|| (eh->def_protected
|
||||
&& elf_has_no_copy_on_protected (h->root.u.def.section->owner)))
|
||||
&& !(h->root.u.def.section->flags & SEC_CODE))
|
||||
return elf_x86_64_need_pic (info, input_bfd, input_section,
|
||||
h, NULL, NULL, howto);
|
||||
|
@ -7137,6 +7162,21 @@ elf_x86_64_merge_symbol (struct elf_link_hash_entry *h,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
elf_x86_64_merge_symbol_attribute (struct elf_link_hash_entry *h,
|
||||
const Elf_Internal_Sym *isym,
|
||||
bfd_boolean definition,
|
||||
bfd_boolean dynamic ATTRIBUTE_UNUSED)
|
||||
{
|
||||
if (definition)
|
||||
{
|
||||
struct elf_x86_64_link_hash_entry *eh
|
||||
= (struct elf_x86_64_link_hash_entry *) h;
|
||||
eh->def_protected = (ELF_ST_VISIBILITY (isym->st_other)
|
||||
== STV_PROTECTED);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
elf_x86_64_additional_program_headers (bfd *abfd,
|
||||
struct bfd_link_info *info ATTRIBUTE_UNUSED)
|
||||
|
@ -7349,69 +7389,40 @@ elf_x86_64_link_setup_gnu_properties (struct bfd_link_info *info)
|
|||
break;
|
||||
}
|
||||
|
||||
if (ebfd != NULL)
|
||||
if (ebfd != NULL && features)
|
||||
{
|
||||
if (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)
|
||||
{
|
||||
/* 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;
|
||||
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"));
|
||||
|
||||
/* Create the GNU property note section if needed. */
|
||||
if (pbfd == NULL)
|
||||
if (!bfd_set_section_alignment (ebfd, sec,
|
||||
ABI_64_P (ebfd) ? 3 : 2))
|
||||
{
|
||||
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;
|
||||
info->callbacks->einfo (_("%F%A: failed to align section\n"),
|
||||
sec);
|
||||
}
|
||||
|
||||
elf_section_type (sec) = SHT_NOTE;
|
||||
}
|
||||
|
||||
/* Check GNU_PROPERTY_NO_COPY_ON_PROTECTED. */
|
||||
for (; pbfd != NULL; pbfd = pbfd->link.next)
|
||||
if (bfd_get_flavour (pbfd) == bfd_target_elf_flavour
|
||||
&& (pbfd->flags
|
||||
& (DYNAMIC | BFD_LINKER_CREATED | BFD_PLUGIN)) == 0)
|
||||
{
|
||||
elf_property_list *p;
|
||||
|
||||
/* The property list is sorted in order of type. */
|
||||
for (p = elf_properties (pbfd); p != NULL; p = p->next)
|
||||
{
|
||||
if (GNU_PROPERTY_NO_COPY_ON_PROTECTED
|
||||
== p->property.pr_type)
|
||||
{
|
||||
/* Clear extern_protected_data if
|
||||
GNU_PROPERTY_NO_COPY_ON_PROTECTED is
|
||||
set on any input relocatable file. */
|
||||
info->extern_protected_data = FALSE;
|
||||
break;
|
||||
}
|
||||
else if (GNU_PROPERTY_NO_COPY_ON_PROTECTED
|
||||
< p->property.pr_type)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pbfd = _bfd_elf_link_setup_gnu_properties (info);
|
||||
|
@ -7830,6 +7841,8 @@ elf_x86_64_special_sections[]=
|
|||
elf_x86_64_common_definition
|
||||
#define elf_backend_merge_symbol \
|
||||
elf_x86_64_merge_symbol
|
||||
#define elf_backend_merge_symbol_attribute \
|
||||
elf_x86_64_merge_symbol_attribute
|
||||
#define elf_backend_special_sections \
|
||||
elf_x86_64_special_sections
|
||||
#define elf_backend_additional_program_headers \
|
||||
|
|
14
ld/ChangeLog
14
ld/ChangeLog
|
@ -1,3 +1,17 @@
|
|||
2017-08-26 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
PR ld/21997
|
||||
* testsuite/ld-i386/i386.exp: Run PR ld/21997 tests.
|
||||
* testsuite/ld-x86-64/x86-64.exp: Likewise.
|
||||
* testsuite/ld-i386/pr21997-1a.S: New file.
|
||||
* testsuite/ld-i386/pr21997-1b.c: Likewise.
|
||||
* testsuite/ld-i386/pr21997-1c.S: Likewise.
|
||||
* testsuite/ld-x86-64/pr21997-1a.S: Likewise.
|
||||
* testsuite/ld-x86-64/pr21997-1a.err: Likewise.
|
||||
* testsuite/ld-x86-64/pr21997-1b.c: Likewise.
|
||||
* testsuite/ld-x86-64/pr21997-1b.err: Likewise.
|
||||
* testsuite/ld-x86-64/pr21997-1c.c: Likewise.
|
||||
|
||||
2017-08-24 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
* testsuite/ld-elf/pr21903c.d: Remove '\' before --.
|
||||
|
|
|
@ -1254,6 +1254,14 @@ if { [isnative]
|
|||
{} \
|
||||
"pr22001-1.so" \
|
||||
] \
|
||||
[list \
|
||||
"Build pr21997-1.so" \
|
||||
"-shared" \
|
||||
"" \
|
||||
{ property-stack.S property-no-copy.S pr21997-1a.S } \
|
||||
{} \
|
||||
"pr21997-1.so" \
|
||||
] \
|
||||
]
|
||||
|
||||
run_ld_link_exec_tests [list \
|
||||
|
@ -1309,6 +1317,49 @@ if { [isnative]
|
|||
"pass.out" \
|
||||
"-fPIC" \
|
||||
] \
|
||||
[list \
|
||||
"Run pr21997-1" \
|
||||
"$NOPIE_LDFLAGS -Wl,--no-as-needed tmpdir/pr21997-1.so" \
|
||||
"" \
|
||||
{ pr21997-1b.c } \
|
||||
"pr21997-1" \
|
||||
"pass.out" \
|
||||
"$NOPIE_CFLAGS" \
|
||||
] \
|
||||
[list \
|
||||
"Run pr21997-1 (PIC 1)" \
|
||||
"$NOPIE_LDFLAGS -Wl,--no-as-needed tmpdir/pr21997-1.so" \
|
||||
"" \
|
||||
{ pr21997-1b.c } \
|
||||
"pr21997-1-pic-1" \
|
||||
"pass.out" \
|
||||
"-fPIC" \
|
||||
] \
|
||||
[list \
|
||||
"Run pr21997-1 (PIC 2)" \
|
||||
"-pie -Wl,--no-as-needed tmpdir/pr21997-1.so" \
|
||||
"" \
|
||||
{ pr21997-1b.c } \
|
||||
"pr21997-1-pic-2" \
|
||||
"pass.out" \
|
||||
"-fPIC" \
|
||||
] \
|
||||
[list \
|
||||
"Run pr21997-1 (PIE 1)" \
|
||||
"$NOPIE_LDFLAGS -Wl,--no-as-needed tmpdir/pr21997-1.so" \
|
||||
"" \
|
||||
{ pr21997-1c.S } \
|
||||
"pr21997-1-pie-1" \
|
||||
"pass.out" \
|
||||
] \
|
||||
[list \
|
||||
"Run pr21997-1 (PIE 2)" \
|
||||
"-pie -Wl,--no-as-needed tmpdir/pr21997-1.so" \
|
||||
"" \
|
||||
{ pr21997-1c.S } \
|
||||
"pr21997-1-pie-2" \
|
||||
"pass.out" \
|
||||
] \
|
||||
]
|
||||
|
||||
if { [at_least_gcc_version 5 0] } {
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
.text
|
||||
.p2align 4,,15
|
||||
.globl get_protected
|
||||
.type get_protected, @function
|
||||
get_protected:
|
||||
call __x86.get_pc_thunk.ax
|
||||
addl $_GLOBAL_OFFSET_TABLE_, %eax
|
||||
movl protected@GOTOFF(%eax), %eax
|
||||
ret
|
||||
.size get_protected, .-get_protected
|
||||
.p2align 4,,15
|
||||
.globl get_protected_p
|
||||
.type get_protected_p, @function
|
||||
get_protected_p:
|
||||
call __x86.get_pc_thunk.ax
|
||||
addl $_GLOBAL_OFFSET_TABLE_, %eax
|
||||
leal protected@GOTOFF(%eax), %eax
|
||||
ret
|
||||
.size get_protected_p, .-get_protected_p
|
||||
.protected protected
|
||||
.globl protected
|
||||
.data
|
||||
.align 4
|
||||
.type protected, @object
|
||||
.size protected, 4
|
||||
protected:
|
||||
.long 1
|
||||
.section .text.__x86.get_pc_thunk.ax,"axG",@progbits,__x86.get_pc_thunk.ax,comdat
|
||||
.globl __x86.get_pc_thunk.ax
|
||||
.hidden __x86.get_pc_thunk.ax
|
||||
.type __x86.get_pc_thunk.ax, @function
|
||||
__x86.get_pc_thunk.ax:
|
||||
movl (%esp), %eax
|
||||
ret
|
||||
.section .note.GNU-stack,"",@progbits
|
|
@ -0,0 +1,16 @@
|
|||
#include <stdio.h>
|
||||
|
||||
extern int protected;
|
||||
extern int get_protected (void);
|
||||
extern int* get_protected_p (void);
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
|
||||
if (protected == get_protected ()
|
||||
&& &protected == get_protected_p ())
|
||||
printf ("PASS\n");
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
.section .rodata.str1.1,"aMS",@progbits,1
|
||||
.LC0:
|
||||
.string "PASS"
|
||||
.section .text.startup,"ax",@progbits
|
||||
.p2align 4,,15
|
||||
.globl main
|
||||
.type main, @function
|
||||
main:
|
||||
leal 4(%esp), %ecx
|
||||
andl $-16, %esp
|
||||
pushl -4(%ecx)
|
||||
pushl %ebp
|
||||
movl %esp, %ebp
|
||||
pushl %esi
|
||||
pushl %ebx
|
||||
pushl %ecx
|
||||
call __x86.get_pc_thunk.bx
|
||||
addl $_GLOBAL_OFFSET_TABLE_, %ebx
|
||||
subl $12, %esp
|
||||
call get_protected@PLT
|
||||
movl protected@GOT(%ebx), %esi
|
||||
cmpl (%esi), %eax
|
||||
je .L7
|
||||
.L3:
|
||||
leal -12(%ebp), %esp
|
||||
xorl %eax, %eax
|
||||
popl %ecx
|
||||
popl %ebx
|
||||
popl %esi
|
||||
popl %ebp
|
||||
leal -4(%ecx), %esp
|
||||
ret
|
||||
.L7:
|
||||
call get_protected_p@PLT
|
||||
cmpl %esi, %eax
|
||||
jne .L3
|
||||
leal .LC0@GOTOFF(%ebx), %eax
|
||||
subl $12, %esp
|
||||
pushl %eax
|
||||
call puts@PLT
|
||||
addl $16, %esp
|
||||
jmp .L3
|
||||
.size main, .-main
|
||||
.section .text.__x86.get_pc_thunk.bx,"axG",@progbits,__x86.get_pc_thunk.bx,comdat
|
||||
.globl __x86.get_pc_thunk.bx
|
||||
.hidden __x86.get_pc_thunk.bx
|
||||
.type __x86.get_pc_thunk.bx, @function
|
||||
__x86.get_pc_thunk.bx:
|
||||
movl (%esp), %ebx
|
||||
ret
|
||||
.section .note.GNU-stack,"",@progbits
|
|
@ -0,0 +1,24 @@
|
|||
.text
|
||||
.p2align 4,,15
|
||||
.globl get_protected
|
||||
.type get_protected, @function
|
||||
get_protected:
|
||||
movl protected(%rip), %eax
|
||||
ret
|
||||
.size get_protected, .-get_protected
|
||||
.p2align 4,,15
|
||||
.globl get_protected_p
|
||||
.type get_protected_p, @function
|
||||
get_protected_p:
|
||||
leaq protected(%rip), %rax
|
||||
ret
|
||||
.size get_protected_p, .-get_protected_p
|
||||
.protected protected
|
||||
.globl protected
|
||||
.data
|
||||
.align 4
|
||||
.type protected, @object
|
||||
.size protected, 4
|
||||
protected:
|
||||
.long 1
|
||||
.section .note.GNU-stack,"",@progbits
|
|
@ -0,0 +1,2 @@
|
|||
.*relocation R_X86_64_PC32 against protected symbol `protected' can not be used when making a P(D|I)E object; recompile with -fPIC
|
||||
#...
|
|
@ -0,0 +1,13 @@
|
|||
#include <stdio.h>
|
||||
|
||||
extern int protected;
|
||||
extern int get_protected (void);
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
if (protected == get_protected ())
|
||||
printf ("PASS\n");
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
.*relocation R_X86_64_32S against protected symbol `protected' can not be used when making a P(D|I)E object; recompile with -fPIC
|
||||
#...
|
|
@ -0,0 +1,13 @@
|
|||
#include <stdio.h>
|
||||
|
||||
extern int protected;
|
||||
extern int* get_protected_p (void);
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
if (&protected == get_protected_p ())
|
||||
printf ("PASS\n");
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1056,6 +1056,22 @@ if { [isnative] && [which $CC] != 0 } {
|
|||
{{error_output "pr22001-1a.err"}} \
|
||||
"pr22001-1a" \
|
||||
] \
|
||||
[list \
|
||||
"Build pr21997-1.so" \
|
||||
"-shared" \
|
||||
"" \
|
||||
{ property-stack.S property-no-copy.S pr21997-1a.S } \
|
||||
{} \
|
||||
"pr21997-1.so" \
|
||||
] \
|
||||
[list \
|
||||
"Build pr21997-1a" \
|
||||
"$NOPIE_LDFLAGS -Wl,--no-as-needed tmpdir/pr21997-1.so" \
|
||||
"$NOPIE_CFLAGS" \
|
||||
{ pr21997-1b.c } \
|
||||
{{error_output "pr21997-1a.err"}} \
|
||||
"pr21997-1a" \
|
||||
] \
|
||||
]
|
||||
|
||||
if {[istarget "x86_64-*-linux*-gnux32"]} {
|
||||
|
@ -1069,6 +1085,15 @@ if { [isnative] && [which $CC] != 0 } {
|
|||
"pass.out" \
|
||||
"$NOPIE_CFLAGS" \
|
||||
] \
|
||||
[list \
|
||||
"Run pr21997-1b" \
|
||||
"$NOPIE_LDFLAGS -Wl,--no-as-needed tmpdir/pr21997-1.so" \
|
||||
"" \
|
||||
{ pr21997-1c.c } \
|
||||
"pr21997-1b" \
|
||||
"pass.out" \
|
||||
"$NOPIE_CFLAGS" \
|
||||
] \
|
||||
]
|
||||
} else {
|
||||
run_cc_link_tests [list \
|
||||
|
@ -1080,6 +1105,14 @@ if { [isnative] && [which $CC] != 0 } {
|
|||
{{error_output "pr22001-1b.err"}} \
|
||||
"pr22001-1b" \
|
||||
] \
|
||||
[list \
|
||||
"Build pr21997-1b" \
|
||||
"$NOPIE_LDFLAGS -Wl,--no-as-needed tmpdir/pr21997-1.so" \
|
||||
"$NOPIE_CFLAGS" \
|
||||
{ pr21997-1c.c } \
|
||||
{{error_output "pr21997-1b.err"}} \
|
||||
"pr21997-1b" \
|
||||
] \
|
||||
]
|
||||
}
|
||||
|
||||
|
@ -1293,6 +1326,42 @@ if { [isnative] && [which $CC] != 0 } {
|
|||
"pass.out" \
|
||||
"-fPIC" \
|
||||
] \
|
||||
[list \
|
||||
"Run pr21997-1a (PIC 1)" \
|
||||
"$NOPIE_LDFLAGS -Wl,--no-as-needed tmpdir/pr21997-1.so" \
|
||||
"" \
|
||||
{ pr21997-1b.c } \
|
||||
"pr21997-1a-pic-1" \
|
||||
"pass.out" \
|
||||
"-fPIC" \
|
||||
] \
|
||||
[list \
|
||||
"Run pr21997-1a (PIC 2)" \
|
||||
"-pie -Wl,--no-as-needed tmpdir/pr21997-1.so" \
|
||||
"" \
|
||||
{ pr21997-1b.c } \
|
||||
"pr21997-1a-pic-2" \
|
||||
"pass.out" \
|
||||
"-fPIC" \
|
||||
] \
|
||||
[list \
|
||||
"Run pr21997-1b (PIC 1)" \
|
||||
"$NOPIE_LDFLAGS -Wl,--no-as-needed tmpdir/pr21997-1.so" \
|
||||
"" \
|
||||
{ pr21997-1c.c } \
|
||||
"pr21997-1b-pic-1" \
|
||||
"pass.out" \
|
||||
"-fPIC" \
|
||||
] \
|
||||
[list \
|
||||
"Run pr21997-1b (PIC 2)" \
|
||||
"-pie -Wl,--no-as-needed tmpdir/pr21997-1.so" \
|
||||
"" \
|
||||
{ pr21997-1c.c } \
|
||||
"pr21997-1b-pic-2" \
|
||||
"pass.out" \
|
||||
"-fPIC" \
|
||||
] \
|
||||
]
|
||||
|
||||
# Run-time tests which require working ifunc attribute support.
|
||||
|
|
Loading…
Reference in New Issue