[PATCH 2/2] elf: Add GNU_PROPERTY_1_NEEDED check
H.J. Lu
hjl.tools@gmail.com
Sun Jun 20 22:50:29 GMT 2021
If GNU_PROPERTY_1_NEEDED_SINGLE_GLOBAL_DEFINITION is set on any input
relocatable files:
1. Don't generate copy relocations.
2. Turn off extern_protected_data.
3. Treate reference to protected symbols with single global definition
as local.
4. Set GNU_PROPERTY_1_NEEDED_SINGLE_GLOBAL_DEFINITION on output.
5. Add -z [no]single-global-definition to control single global definition.
bfd/
* elf-properties.c (_bfd_elf_link_setup_gnu_properties): Handle
GNU_PROPERTY_1_NEEDED_SINGLE_GLOBAL_DEFINITION for
-z single-global-definition. Set nocopyreloc to true and
extern_protected_data to false for single global definiton.
* elflink.c (_bfd_elf_symbol_refs_local_p): Return true for
STV_PROTECTED symbols with single global definition.
include/
* bfdlink.h (bfd_link_info): Add single_global_definition.
ld/
* NEWS: Mention -z [no]single-global-definition.
* ld.texi: Document -z [no]single-global-definition.
* ldmain.c (main): Initialize link_info.single_global_definition
to -1.
* lexsup.c (elf_shlib_list_options): Add
-z [no]single-global-definition.
* emultempl/elf.em (gld${EMULATION_NAME}_handle_optio): Handle
-z [no]single-global-definition.
* testsuite/ld-elf/property-1_needed-1b.d: New file.
* testsuite/ld-elf/property-1_needed-1c.d: Likewise.
* testsuite/ld-x86-64/protected-data-1.h: Likewise.
* testsuite/ld-x86-64/protected-data-1a.c: Likewise.
* testsuite/ld-x86-64/protected-data-1b.c: Likewise.
* testsuite/ld-x86-64/protected-data-2a.S: Likewise.
* testsuite/ld-x86-64/protected-data-2b.S: Likewise.
* testsuite/ld-x86-64/protected-func-2a.S: Likewise.
* testsuite/ld-x86-64/protected-func-2b.S: Likewise.
* testsuite/ld-x86-64/protected-func-2c.c: Likewise.
* testsuite/ld-x86-64/single-global-definition.rd: Likewise.
* testsuite/ld-x86-64/x86-64.exp: Run tests for protected
function and data with single global definition.
---
bfd/elf-properties.c | 103 ++++++++++++--
bfd/elflink.c | 4 +
include/bfdlink.h | 6 +
ld/NEWS | 3 +
ld/emultempl/elf.em | 4 +
ld/ld.texi | 12 ++
ld/ldmain.c | 1 +
ld/lexsup.c | 5 +
ld/testsuite/ld-elf/property-1_needed-1b.d | 16 +++
ld/testsuite/ld-elf/property-1_needed-1c.d | 17 +++
ld/testsuite/ld-x86-64/protected-data-1.h | 11 ++
ld/testsuite/ld-x86-64/protected-data-1a.c | 40 ++++++
ld/testsuite/ld-x86-64/protected-data-1b.c | 59 ++++++++
ld/testsuite/ld-x86-64/protected-data-2a.S | 109 +++++++++++++++
ld/testsuite/ld-x86-64/protected-data-2b.S | 119 ++++++++++++++++
ld/testsuite/ld-x86-64/protected-func-2a.S | 68 +++++++++
ld/testsuite/ld-x86-64/protected-func-2b.S | 83 +++++++++++
ld/testsuite/ld-x86-64/protected-func-2c.c | 29 ++++
.../ld-x86-64/single-global-definition.rd | 6 +
ld/testsuite/ld-x86-64/x86-64.exp | 131 ++++++++++++++++++
20 files changed, 811 insertions(+), 15 deletions(-)
create mode 100644 ld/testsuite/ld-elf/property-1_needed-1b.d
create mode 100644 ld/testsuite/ld-elf/property-1_needed-1c.d
create mode 100644 ld/testsuite/ld-x86-64/protected-data-1.h
create mode 100644 ld/testsuite/ld-x86-64/protected-data-1a.c
create mode 100644 ld/testsuite/ld-x86-64/protected-data-1b.c
create mode 100644 ld/testsuite/ld-x86-64/protected-data-2a.S
create mode 100644 ld/testsuite/ld-x86-64/protected-data-2b.S
create mode 100644 ld/testsuite/ld-x86-64/protected-func-2a.S
create mode 100644 ld/testsuite/ld-x86-64/protected-func-2b.S
create mode 100644 ld/testsuite/ld-x86-64/protected-func-2c.c
create mode 100644 ld/testsuite/ld-x86-64/single-global-definition.rd
diff --git a/bfd/elf-properties.c b/bfd/elf-properties.c
index 56ee91d7786..50c20964006 100644
--- a/bfd/elf-properties.c
+++ b/bfd/elf-properties.c
@@ -598,7 +598,7 @@ elf_write_gnu_properties (bfd *abfd, bfd_byte *contents,
bfd *
_bfd_elf_link_setup_gnu_properties (struct bfd_link_info *info)
{
- bfd *abfd, *first_pbfd = NULL;
+ bfd *abfd, *first_pbfd = NULL, *elf_bfd = NULL;
elf_property_list *list;
asection *sec;
bool has_properties = false;
@@ -606,32 +606,75 @@ _bfd_elf_link_setup_gnu_properties (struct bfd_link_info *info)
= get_elf_backend_data (info->output_bfd);
unsigned int elfclass = bed->s->elfclass;
int elf_machine_code = bed->elf_machine_code;
+ elf_property *p;
/* Find the first relocatable ELF input with GNU properties. */
for (abfd = info->input_bfds; abfd != NULL; abfd = abfd->link.next)
if (bfd_get_flavour (abfd) == bfd_target_elf_flavour
&& (abfd->flags & DYNAMIC) == 0
- && elf_properties (abfd) != NULL)
+ && (elf_machine_code
+ == get_elf_backend_data (abfd)->elf_machine_code)
+ && (elfclass == get_elf_backend_data (abfd)->s->elfclass))
{
- has_properties = true;
-
/* Ignore GNU properties from ELF objects with different machine
code or class. Also skip objects without a GNU_PROPERTY note
section. */
- if ((elf_machine_code
- == get_elf_backend_data (abfd)->elf_machine_code)
- && (elfclass
- == get_elf_backend_data (abfd)->s->elfclass)
- && bfd_get_section_by_name (abfd,
- NOTE_GNU_PROPERTY_SECTION_NAME) != NULL
- )
+ elf_bfd = abfd;
+
+ if (elf_properties (abfd) != NULL)
{
- /* Keep .note.gnu.property section in FIRST_PBFD. */
- first_pbfd = abfd;
- break;
+ has_properties = true;
+
+ if (bfd_get_section_by_name (abfd,
+ NOTE_GNU_PROPERTY_SECTION_NAME)
+ != NULL)
+ {
+ /* Keep .note.gnu.property section in FIRST_PBFD. */
+ first_pbfd = abfd;
+ break;
+ }
}
}
+ if (info->single_global_definition > 0 && elf_bfd != NULL)
+ {
+ /* Support -z single-global-definition. */
+ if (first_pbfd == NULL)
+ {
+ sec = bfd_make_section_with_flags (elf_bfd,
+ 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%P: failed to create GNU property section\n"));
+
+ if (!bfd_set_section_alignment (sec,
+ elfclass == ELFCLASS64 ? 3 : 2))
+ info->callbacks->einfo (_("%F%pA: failed to align section\n"),
+ sec);
+
+ elf_section_type (sec) = SHT_NOTE;
+ first_pbfd = elf_bfd;
+ has_properties = true;
+ }
+
+ p = _bfd_elf_get_property (first_pbfd, GNU_PROPERTY_1_NEEDED, 4);
+ if (p->pr_kind == property_unknown)
+ {
+ /* Create GNU_PROPERTY_1_NEEDED. */
+ p->u.number
+ = GNU_PROPERTY_1_NEEDED_SINGLE_GLOBAL_DEFINITION;
+ p->pr_kind = property_number;
+ }
+ else
+ p->u.number
+ |= GNU_PROPERTY_1_NEEDED_SINGLE_GLOBAL_DEFINITION;
+ }
+
/* Do nothing if there is no .note.gnu.property section. */
if (!has_properties)
return NULL;
@@ -695,7 +738,6 @@ _bfd_elf_link_setup_gnu_properties (struct bfd_link_info *info)
if N > 0. */
if (info->stacksize > 0)
{
- elf_property *p;
bfd_vma stacksize = info->stacksize;
p = _bfd_elf_get_property (first_pbfd, GNU_PROPERTY_STACK_SIZE,
@@ -737,6 +779,29 @@ _bfd_elf_link_setup_gnu_properties (struct bfd_link_info *info)
sec->size = size;
contents = (bfd_byte *) bfd_zalloc (first_pbfd, size);
+ if (info->single_global_definition <= 0)
+ {
+ /* Get GNU_PROPERTY_1_NEEDED properties. */
+ p = elf_find_and_remove_property (&elf_properties (first_pbfd),
+ GNU_PROPERTY_1_NEEDED, false);
+ if (p != NULL)
+ {
+ if (info->single_global_definition < 0)
+ {
+ /* Turn on single global definition based on input
+ properties. */
+ if ((p->u.number
+ & GNU_PROPERTY_1_NEEDED_SINGLE_GLOBAL_DEFINITION)
+ != 0)
+ info->single_global_definition = 1;
+ }
+ else
+ /* Turn off single global definition. */
+ p->u.number
+ &= ~GNU_PROPERTY_1_NEEDED_SINGLE_GLOBAL_DEFINITION;
+ }
+ }
+
elf_write_gnu_properties (first_pbfd, contents, list, size,
align_size);
@@ -747,6 +812,14 @@ _bfd_elf_link_setup_gnu_properties (struct bfd_link_info *info)
symbol is defined in the shared object. */
if (elf_has_no_copy_on_protected (first_pbfd))
info->extern_protected_data = false;
+
+ if (info->single_global_definition > 0)
+ {
+ /* For single global definition, don't generate copy
+ relocations. */
+ info->nocopyreloc = true;
+ info->extern_protected_data = false;
+ }
}
return first_pbfd;
diff --git a/bfd/elflink.c b/bfd/elflink.c
index 9a05208253c..21a77bf67bd 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -3331,6 +3331,10 @@ _bfd_elf_symbol_refs_local_p (struct elf_link_hash_entry *h,
if (!is_elf_hash_table (&hash_table->root))
return true;
+ /* STV_PROTECTED symbols with single global definition are local. */
+ if (info->single_global_definition > 0)
+ return true;
+
bed = get_elf_backend_data (hash_table->dynobj);
/* If extern_protected_data is false, STV_PROTECTED non-function
diff --git a/include/bfdlink.h b/include/bfdlink.h
index 7f1b12dbf37..815780091c5 100644
--- a/include/bfdlink.h
+++ b/include/bfdlink.h
@@ -639,6 +639,12 @@ struct bfd_link_info
the backend decide. */
int dynamic_undefined_weak;
+ /* GNU_PROPERTY_1_NEEDED_SINGLE_GLOBAL_DEFINITION control:
+ > 0: Turn on.
+ 0: Turn off.
+ < 0: Turn on if it is set on any inputs. */
+ int single_global_definition;
+
/* Non-zero if auto-import thunks for DATA items in pei386 DLLs
should be generated/linked against. Set to 1 if this feature
is explicitly requested by the user, -1 if enabled by default. */
diff --git a/ld/NEWS b/ld/NEWS
index a5ed9058c04..aa74d4fd6a0 100644
--- a/ld/NEWS
+++ b/ld/NEWS
@@ -1,5 +1,8 @@
-*- text -*-
+* Add -z single-global-definition/-z nosingle-global-definition to control
+ canonical function pointers and copy relocation.
+
* arm-symbianelf support removed.
* Add -z report-relative-reloc to x86 ELF linker to report dynamic
diff --git a/ld/emultempl/elf.em b/ld/emultempl/elf.em
index bfaf8130a3e..cdf5b26621a 100644
--- a/ld/emultempl/elf.em
+++ b/ld/emultempl/elf.em
@@ -848,6 +848,10 @@ fragment <<EOF
link_info.textrel_check = textrel_check_none;
else if (strcmp (optarg, "textoff") == 0)
link_info.textrel_check = textrel_check_none;
+ else if (strcmp (optarg, "single-global-definition") == 0)
+ link_info.single_global_definition = 1;
+ else if (strcmp (optarg, "nosingle-global-definition") == 0)
+ link_info.single_global_definition = 0;
EOF
fi
diff --git a/ld/ld.texi b/ld/ld.texi
index dd8f571d4e4..b847e78ee7f 100644
--- a/ld/ld.texi
+++ b/ld/ld.texi
@@ -1442,6 +1442,18 @@ Generate GNU_PROPERTY_X86_FEATURE_1_SHSTK in .note.gnu.property section
to indicate compatibility with Intel Shadow Stack. Supported for
Linux/i386 and Linux/x86_64.
+@item single-global-definition
+@itemx nosingle-global-definition
+Generate GNU_PROPERTY_1_NEEDED_SINGLE_GLOBAL_DEFINITION in
+.note.gnu.property section to indicate that object file requires
+canonical function pointers and cannot be used with copy relocation.
+This option also implies @option{noextern-protected-data} and
+@option{nocopyreloc}.
+
+@option{nosingle-global-definition} removes
+GNU_PROPERTY_1_NEEDED_SINGLE_GLOBAL_DEFINITION from .note.gnu.property
+section.
+
@item stack-size=@var{value}
Specify a stack size for an ELF @code{PT_GNU_STACK} segment.
Specifying zero will override any default non-zero sized
diff --git a/ld/ldmain.c b/ld/ldmain.c
index 42660eb9a3c..99a1b0cf5f3 100644
--- a/ld/ldmain.c
+++ b/ld/ldmain.c
@@ -346,6 +346,7 @@ main (int argc, char **argv)
link_info.relax_pass = 1;
link_info.extern_protected_data = -1;
link_info.dynamic_undefined_weak = -1;
+ link_info.single_global_definition = -1;
link_info.pei386_auto_import = -1;
link_info.spare_dynamic_tags = 5;
link_info.path_separator = ':';
diff --git a/ld/lexsup.c b/ld/lexsup.c
index 00274c500d0..abfc3766c7c 100644
--- a/ld/lexsup.c
+++ b/ld/lexsup.c
@@ -2100,6 +2100,11 @@ elf_shlib_list_options (FILE *file)
fprintf (file, _("\
-z textoff Don't treat DT_TEXTREL in output as error\n"));
}
+ fprintf (file, _("\
+ -z single-global-definition Enable single global definition\n"));
+ fprintf (file, _("\
+ -z nosingle-global-definition\n\
+ Disable single global definition\n"));
}
static void
diff --git a/ld/testsuite/ld-elf/property-1_needed-1b.d b/ld/testsuite/ld-elf/property-1_needed-1b.d
new file mode 100644
index 00000000000..2e2517f0d4f
--- /dev/null
+++ b/ld/testsuite/ld-elf/property-1_needed-1b.d
@@ -0,0 +1,16 @@
+#source: empty.s
+#as:
+#ld: -shared -z single-global-definition
+#readelf: -n
+#xfail: ![check_shared_lib_support]
+#notarget: am33_2.0-*-* hppa*-*-hpux* mn10300-*-*
+# Assembly source file for the HPPA assembler is renamed and modifed by
+# sed. mn10300 has relocations in .note.gnu.property section which
+# elf_parse_notes doesn't support.
+
+#...
+Displaying notes found in: .note.gnu.property
+[ ]+Owner[ ]+Data size[ ]+Description
+ GNU 0x[0-9a-f]+ NT_GNU_PROPERTY_TYPE_0
+ Properties: 1_needed: single global definition
+#pass
diff --git a/ld/testsuite/ld-elf/property-1_needed-1c.d b/ld/testsuite/ld-elf/property-1_needed-1c.d
new file mode 100644
index 00000000000..d26bce62edd
--- /dev/null
+++ b/ld/testsuite/ld-elf/property-1_needed-1c.d
@@ -0,0 +1,17 @@
+#source: empty.s
+#source: property-1_needed-1.s
+#as:
+#ld: -shared -z nosingle-global-definition
+#readelf: -n
+#xfail: ![check_shared_lib_support]
+#notarget: am33_2.0-*-* hppa*-*-hpux* mn10300-*-*
+# Assembly source file for the HPPA assembler is renamed and modifed by
+# sed. mn10300 has relocations in .note.gnu.property section which
+# elf_parse_notes doesn't support.
+
+#...
+Displaying notes found in: .note.gnu.property
+[ ]+Owner[ ]+Data size[ ]+Description
+ GNU 0x[0-9a-f]+ NT_GNU_PROPERTY_TYPE_0
+ Properties: 1_needed: <unknown: 2>
+#pass
diff --git a/ld/testsuite/ld-x86-64/protected-data-1.h b/ld/testsuite/ld-x86-64/protected-data-1.h
new file mode 100644
index 00000000000..a80c9769d37
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/protected-data-1.h
@@ -0,0 +1,11 @@
+extern int protected_data_1a;
+extern int protected_data_1b;
+
+extern int *protected_data_1a_p ();
+extern int *protected_data_1b_p ();
+
+extern void set_protected_data_1a (int);
+extern void set_protected_data_1b (int);
+
+extern int check_protected_data_1a (int);
+extern int check_protected_data_1b (int);
diff --git a/ld/testsuite/ld-x86-64/protected-data-1a.c b/ld/testsuite/ld-x86-64/protected-data-1a.c
new file mode 100644
index 00000000000..6942426ecb3
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/protected-data-1a.c
@@ -0,0 +1,40 @@
+#include "protected-data-1.h"
+
+int protected_data_1a __attribute__ ((visibility("protected"))) = 1;
+int protected_data_1b __attribute__ ((visibility("protected"))) = 2;
+
+int *
+protected_data_1a_p (void)
+{
+ return &protected_data_1a;
+}
+
+int *
+protected_data_1b_p (void)
+{
+ return &protected_data_1b;
+}
+
+void
+set_protected_data_1a (int i)
+{
+ protected_data_1a = i;
+}
+
+void
+set_protected_data_1b (int i)
+{
+ protected_data_1b = i;
+}
+
+int
+check_protected_data_1a (int i)
+{
+ return protected_data_1a == i ? 0 : 1;
+}
+
+int
+check_protected_data_1b (int i)
+{
+ return protected_data_1b == i ? 0 : 1;
+}
diff --git a/ld/testsuite/ld-x86-64/protected-data-1b.c b/ld/testsuite/ld-x86-64/protected-data-1b.c
new file mode 100644
index 00000000000..a4756ee08da
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/protected-data-1b.c
@@ -0,0 +1,59 @@
+#include <stdio.h>
+
+#include "protected-data-1.h"
+
+int protected_data_1b = 3;
+
+int
+main (void)
+{
+ int res = 0;
+
+ /* Check if we get the same address for the protected data symbol. */
+ if (&protected_data_1a != protected_data_1a_p ())
+ {
+ puts ("'protected_data_1a' in main and shared library doesn't have same address");
+ res = 1;
+ }
+
+ protected_data_1a = -1;
+ if (check_protected_data_1a (-1))
+ {
+ puts ("'protected_data_1a' in main and shared library doesn't have same value");
+ res = 1;
+ }
+
+ set_protected_data_1a (-3);
+ if (protected_data_1a != -3)
+ {
+ puts ("'protected_data_1a' in main and shared library doesn't have same value");
+ res = 1;
+ }
+
+ /* Check if we get the different addresses for the protected data
+ symbol. */
+ if (&protected_data_1b == protected_data_1b_p ())
+ {
+ puts ("'protected_data_1b' in main and shared library has same address");
+ res = 1;
+ }
+
+ protected_data_1b = -10;
+ if (check_protected_data_1b (2))
+ {
+ puts ("'protected_data_1b' in main and shared library has same address");
+ res = 1;
+ }
+
+ set_protected_data_1b (-30);
+ if (protected_data_1b != -10)
+ {
+ puts ("'protected_data_1b' in main and shared library has same address");
+ res = 1;
+ }
+
+ if (!res)
+ puts ("PASS");
+
+ return res;
+}
diff --git a/ld/testsuite/ld-x86-64/protected-data-2a.S b/ld/testsuite/ld-x86-64/protected-data-2a.S
new file mode 100644
index 00000000000..dcc857c165d
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/protected-data-2a.S
@@ -0,0 +1,109 @@
+ .text
+ .p2align 4
+ .protected protected_data_1a
+ .globl protected_data_1a_p
+ .type protected_data_1a_p, @function
+protected_data_1a_p:
+.LFB0:
+ .cfi_startproc
+ leaq protected_data_1a(%rip), %rax
+ ret
+ .cfi_endproc
+.LFE0:
+ .size protected_data_1a_p, .-protected_data_1a_p
+ .p2align 4
+ .protected protected_data_1b
+ .globl protected_data_1b_p
+ .type protected_data_1b_p, @function
+protected_data_1b_p:
+.LFB1:
+ .cfi_startproc
+ leaq protected_data_1b(%rip), %rax
+ ret
+ .cfi_endproc
+.LFE1:
+ .size protected_data_1b_p, .-protected_data_1b_p
+ .p2align 4
+ .globl set_protected_data_1a
+ .type set_protected_data_1a, @function
+set_protected_data_1a:
+.LFB2:
+ .cfi_startproc
+ movl %edi, protected_data_1a(%rip)
+ ret
+ .cfi_endproc
+.LFE2:
+ .size set_protected_data_1a, .-set_protected_data_1a
+ .p2align 4
+ .globl set_protected_data_1b
+ .type set_protected_data_1b, @function
+set_protected_data_1b:
+.LFB3:
+ .cfi_startproc
+ movl %edi, protected_data_1b(%rip)
+ ret
+ .cfi_endproc
+.LFE3:
+ .size set_protected_data_1b, .-set_protected_data_1b
+ .p2align 4
+ .globl check_protected_data_1a
+ .type check_protected_data_1a, @function
+check_protected_data_1a:
+.LFB4:
+ .cfi_startproc
+ xorl %eax, %eax
+ cmpl %edi, protected_data_1a(%rip)
+ setne %al
+ ret
+ .cfi_endproc
+.LFE4:
+ .size check_protected_data_1a, .-check_protected_data_1a
+ .p2align 4
+ .globl check_protected_data_1b
+ .type check_protected_data_1b, @function
+check_protected_data_1b:
+.LFB5:
+ .cfi_startproc
+ xorl %eax, %eax
+ cmpl %edi, protected_data_1b(%rip)
+ setne %al
+ ret
+ .cfi_endproc
+.LFE5:
+ .size check_protected_data_1b, .-check_protected_data_1b
+ .globl protected_data_1b
+ .data
+ .align 4
+ .type protected_data_1b, @object
+ .size protected_data_1b, 4
+protected_data_1b:
+ .long 2
+ .globl protected_data_1a
+ .align 4
+ .type protected_data_1a, @object
+ .size protected_data_1a, 4
+protected_data_1a:
+ .long 1
+ .section .note.GNU-stack,"",@progbits
+#ifdef USE_GNU_PROPERTY_1_NEEDED_SINGLE_GLOBAL_DEFINITION
+# ifdef __LP64__
+# define ALIGN 3
+# else
+# define ALIGN 2
+# endif
+ .section ".note.gnu.property", "a"
+ .p2align ALIGN
+ .long 1f - 0f /* name length */
+ .long 5f - 2f /* data length */
+ .long 5 /* note type */
+0: .asciz "GNU" /* vendor name */
+1:
+ .p2align ALIGN
+2: .long 0xb0008000 /* pr_type. */
+ .long 4f - 3f /* pr_datasz. */
+3:
+ .long 0x1
+4:
+ .p2align ALIGN
+5:
+#endif
diff --git a/ld/testsuite/ld-x86-64/protected-data-2b.S b/ld/testsuite/ld-x86-64/protected-data-2b.S
new file mode 100644
index 00000000000..da8956139fe
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/protected-data-2b.S
@@ -0,0 +1,119 @@
+ .section .rodata.str1.8,"aMS",@progbits,1
+ .align 8
+.LC0:
+ .string "'protected_data_1a' in main and shared library doesn't have same address"
+ .align 8
+.LC1:
+ .string "'protected_data_1a' in main and shared library doesn't have same value"
+ .align 8
+.LC2:
+ .string "'protected_data_1b' in main and shared library has same address"
+ .section .rodata.str1.1,"aMS",@progbits,1
+.LC3:
+ .string "PASS"
+ .section .text.startup,"ax",@progbits
+ .p2align 4,,15
+ .globl main
+ .type main, @function
+main:
+.LFB11:
+ .cfi_startproc
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset 6, -16
+ xorl %eax, %eax
+ pushq %rbx
+ .cfi_def_cfa_offset 24
+ .cfi_offset 3, -24
+ xorl %ebx, %ebx
+ subq $8, %rsp
+ .cfi_def_cfa_offset 32
+ call protected_data_1a_p
+ movq protected_data_1a@GOTPCREL(%rip), %rbp
+ cmpq %rbp, %rax
+ je .L2
+ leaq .LC0(%rip), %rdi
+ movb $1, %bl
+ call puts
+.L2:
+ movl $-1, %edi
+ movl $-1, 0(%rbp)
+ call check_protected_data_1a
+ testl %eax, %eax
+ jne .L17
+.L3:
+ movl $-3, %edi
+ call set_protected_data_1a
+ cmpl $-3, 0(%rbp)
+ je .L4
+ leaq .LC1(%rip), %rdi
+ movl $1, %ebx
+ call puts
+.L4:
+ xorl %eax, %eax
+ call protected_data_1b_p
+ leaq protected_data_1b(%rip), %rdx
+ cmpq %rdx, %rax
+ je .L18
+.L5:
+ movl $2, %edi
+ movl $-10, protected_data_1b(%rip)
+ call check_protected_data_1b
+ testl %eax, %eax
+ jne .L19
+ movl $-30, %edi
+ call set_protected_data_1b
+ cmpl $-10, protected_data_1b(%rip)
+ je .L9
+.L7:
+ leaq .LC2(%rip), %rdi
+ movl $1, %ebx
+ call puts
+.L8:
+ addq $8, %rsp
+ .cfi_remember_state
+ .cfi_def_cfa_offset 24
+ movl %ebx, %eax
+ popq %rbx
+ .cfi_def_cfa_offset 16
+ popq %rbp
+ .cfi_def_cfa_offset 8
+ ret
+.L9:
+ .cfi_restore_state
+ testl %ebx, %ebx
+ jne .L11
+ leaq .LC3(%rip), %rdi
+ call puts
+ jmp .L8
+.L19:
+ leaq .LC2(%rip), %rdi
+ call puts
+ movl $-30, %edi
+ call set_protected_data_1b
+ cmpl $-10, protected_data_1b(%rip)
+ jne .L7
+.L11:
+ movl $1, %ebx
+ jmp .L8
+.L17:
+ leaq .LC1(%rip), %rdi
+ movl $1, %ebx
+ call puts
+ jmp .L3
+.L18:
+ leaq .LC2(%rip), %rdi
+ movl $1, %ebx
+ call puts
+ jmp .L5
+ .cfi_endproc
+.LFE11:
+ .size main, .-main
+ .globl protected_data_1b
+ .data
+ .align 4
+ .type protected_data_1b, @object
+ .size protected_data_1b, 4
+protected_data_1b:
+ .long 3
+ .section .note.GNU-stack,"",@progbits
diff --git a/ld/testsuite/ld-x86-64/protected-func-2a.S b/ld/testsuite/ld-x86-64/protected-func-2a.S
new file mode 100644
index 00000000000..35c9cd121bd
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/protected-func-2a.S
@@ -0,0 +1,68 @@
+ .text
+ .p2align 4
+ .protected protected_func_1a
+ .globl protected_func_1a
+ .type protected_func_1a, @function
+protected_func_1a:
+.LFB0:
+ .cfi_startproc
+ movl $1, %eax
+ ret
+ .cfi_endproc
+.LFE0:
+ .size protected_func_1a, .-protected_func_1a
+ .p2align 4
+ .protected protected_func_1b
+ .globl protected_func_1b
+ .type protected_func_1b, @function
+protected_func_1b:
+.LFB1:
+ .cfi_startproc
+ movl $2, %eax
+ ret
+ .cfi_endproc
+.LFE1:
+ .size protected_func_1b, .-protected_func_1b
+ .p2align 4
+ .globl protected_func_1a_p
+ .type protected_func_1a_p, @function
+protected_func_1a_p:
+.LFB2:
+ .cfi_startproc
+ leaq protected_func_1a(%rip), %rax
+ ret
+ .cfi_endproc
+.LFE2:
+ .size protected_func_1a_p, .-protected_func_1a_p
+ .p2align 4
+ .globl protected_func_1b_p
+ .type protected_func_1b_p, @function
+protected_func_1b_p:
+.LFB3:
+ .cfi_startproc
+ leaq protected_func_1b(%rip), %rax
+ ret
+ .cfi_endproc
+.LFE3:
+ .size protected_func_1b_p, .-protected_func_1b_p
+ .section .note.GNU-stack,"",@progbits
+#ifdef __LP64__
+# define ALIGN 3
+#else
+# define ALIGN 2
+#endif
+ .section ".note.gnu.property", "a"
+ .p2align ALIGN
+ .long 1f - 0f /* name length */
+ .long 5f - 2f /* data length */
+ .long 5 /* note type */
+0: .asciz "GNU" /* vendor name */
+1:
+ .p2align ALIGN
+2: .long 0xb0008000 /* pr_type. */
+ .long 4f - 3f /* pr_datasz. */
+3:
+ .long 0x1
+4:
+ .p2align ALIGN
+5:
diff --git a/ld/testsuite/ld-x86-64/protected-func-2b.S b/ld/testsuite/ld-x86-64/protected-func-2b.S
new file mode 100644
index 00000000000..8fa4cbf09d6
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/protected-func-2b.S
@@ -0,0 +1,83 @@
+ .text
+ .p2align 4
+ .globl protected_func_1b
+ .type protected_func_1b, @function
+protected_func_1b:
+.LFB11:
+ .cfi_startproc
+ movl $3, %eax
+ ret
+ .cfi_endproc
+.LFE11:
+ .size protected_func_1b, .-protected_func_1b
+ .section .rodata.str1.8,"aMS",@progbits,1
+ .align 8
+.LC0:
+ .string "'protected_func_1a' in main and shared library doesn't have same address"
+ .align 8
+.LC1:
+ .string "'protected_func_1a' doesn't return the correct value"
+ .align 8
+.LC2:
+ .string "'protected_func_1b' in main and shared library has same address"
+ .section .rodata.str1.1,"aMS",@progbits,1
+.LC3:
+ .string "PASS"
+ .section .text.startup,"ax",@progbits
+ .p2align 4
+ .globl main
+ .type main, @function
+main:
+.LFB12:
+ .cfi_startproc
+ pushq %r12
+ .cfi_def_cfa_offset 16
+ .cfi_offset 12, -16
+ xorl %r12d, %r12d
+ call protected_func_1a_p
+ cmpq protected_func_1a@GOTPCREL(%rip), %rax
+ je .L4
+ leaq .LC0(%rip), %rdi
+ movl $1, %r12d
+ call puts
+.L4:
+ call protected_func_1a
+ cmpl $1, %eax
+ jne .L13
+ call protected_func_1b_p
+ leaq protected_func_1b(%rip), %rdx
+ cmpq %rax, %rdx
+ je .L6
+ testl %r12d, %r12d
+ jne .L12
+ leaq .LC3(%rip), %rdi
+ call puts
+ movl %r12d, %eax
+ popq %r12
+ .cfi_remember_state
+ .cfi_def_cfa_offset 8
+ ret
+.L13:
+ .cfi_restore_state
+ leaq .LC1(%rip), %rdi
+ call puts
+ call protected_func_1b_p
+ leaq protected_func_1b(%rip), %rdx
+ cmpq %rax, %rdx
+ je .L6
+.L12:
+ movl $1, %r12d
+ movl %r12d, %eax
+ popq %r12
+ .cfi_remember_state
+ .cfi_def_cfa_offset 8
+ ret
+.L6:
+ .cfi_restore_state
+ leaq .LC2(%rip), %rdi
+ call puts
+ jmp .L12
+ .cfi_endproc
+.LFE12:
+ .size main, .-main
+ .section .note.GNU-stack,"",@progbits
diff --git a/ld/testsuite/ld-x86-64/protected-func-2c.c b/ld/testsuite/ld-x86-64/protected-func-2c.c
new file mode 100644
index 00000000000..c5ec1eca17e
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/protected-func-2c.c
@@ -0,0 +1,29 @@
+#include "protected-func-1.h"
+
+protected_func_type protected_func_1a_ptr = protected_func_1a;
+
+__attribute__ ((visibility("protected")))
+int
+protected_func_1a (void)
+{
+ return 1;
+}
+
+__attribute__ ((visibility("protected")))
+int
+protected_func_1b (void)
+{
+ return 2;
+}
+
+protected_func_type
+protected_func_1a_p (void)
+{
+ return protected_func_1a;
+}
+
+protected_func_type
+protected_func_1b_p (void)
+{
+ return protected_func_1b;
+}
diff --git a/ld/testsuite/ld-x86-64/single-global-definition.rd b/ld/testsuite/ld-x86-64/single-global-definition.rd
new file mode 100644
index 00000000000..139dca0d6c6
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/single-global-definition.rd
@@ -0,0 +1,6 @@
+#...
+Displaying notes found in: .note.gnu.property
+[ ]+Owner[ ]+Data size[ ]+Description
+ GNU 0x[0-9a-f]+ NT_GNU_PROPERTY_TYPE_0
+ Properties: 1_needed: single global definition
+#pass
diff --git a/ld/testsuite/ld-x86-64/x86-64.exp b/ld/testsuite/ld-x86-64/x86-64.exp
index 3bf62504cf9..5fabbec6fa7 100644
--- a/ld/testsuite/ld-x86-64/x86-64.exp
+++ b/ld/testsuite/ld-x86-64/x86-64.exp
@@ -1334,6 +1334,47 @@ if { [isnative] && [check_compiler_available] } {
{} \
"libprotected-func-1.so" \
] \
+ [list \
+ "Build libprotected-func-2a.so" \
+ "-shared" \
+ "-fPIC -Wa,-mx86-used-note=yes" \
+ { protected-func-2a.S } \
+ {{readelf -n single-global-definition.rd}} \
+ "libprotected-func-2a.so" \
+ ] \
+ [list \
+ "Build libprotected-func-2b.so" \
+ "-shared -z single-global-definition" \
+ "-fPIC -Wa,-mx86-used-note=yes" \
+ { protected-func-2c.c } \
+ {{readelf -n single-global-definition.rd}} \
+ "libprotected-func-2b.so" \
+ ] \
+ [list \
+ "Build libprotected-data-1.so" \
+ "-shared" \
+ "-fPIC -Wa,-mx86-used-note=yes" \
+ { protected-data-1a.c } \
+ {} \
+ "libprotected-data-1.so" \
+ ] \
+ [list \
+ "Build libprotected-data-2a.so" \
+ "-shared" \
+ "-fPIC -Wa,-mx86-used-note=yes \
+ -DUSE_GNU_PROPERTY_1_NEEDED_SINGLE_GLOBAL_DEFINITION" \
+ { protected-data-2a.S } \
+ {{readelf -n single-global-definition.rd}} \
+ "libprotected-data-2a.so" \
+ ] \
+ [list \
+ "Build libprotected-data-2b.so" \
+ "-shared -z single-global-definition" \
+ "-fPIC -Wa,-mx86-used-note=yes" \
+ { protected-data-2a.S } \
+ {{readelf -n single-global-definition.rd}} \
+ "libprotected-data-2b.so" \
+ ] \
]
if {[istarget "x86_64-*-linux*-gnux32"]} {
@@ -1761,6 +1802,96 @@ if { [isnative] && [check_compiler_available] } {
"pass.out" \
"-fPIE" \
] \
+ [list \
+ "Run protected-func-2a without PIE" \
+ "$NOPIE_LDFLAGS -Wl,--no-as-needed tmpdir/libprotected-func-2a.so" \
+ "-Wa,-mx86-used-note=yes" \
+ { protected-func-2b.S } \
+ "protected-func-2a" \
+ "pass.out" \
+ "$NOPIE_CFLAGS" \
+ ] \
+ [list \
+ "Run protected-func-2b with PIE" \
+ "-Wl,--no-as-needed -pie tmpdir/libprotected-func-2a.so" \
+ "-Wa,-mx86-used-note=yes" \
+ { protected-func-2b.S } \
+ "protected-func-2b" \
+ "pass.out" \
+ "-fPIE" \
+ ] \
+ [list \
+ "Run protected-func-2c without PIE" \
+ "$NOPIE_LDFLAGS -Wl,--no-as-needed tmpdir/libprotected-func-2b.so" \
+ "-Wa,-mx86-used-note=yes" \
+ { protected-func-2b.S } \
+ "protected-func-2c" \
+ "pass.out" \
+ "$NOPIE_CFLAGS" \
+ ] \
+ [list \
+ "Run protected-func-2d with PIE" \
+ "-Wl,--no-as-needed -pie tmpdir/libprotected-func-2b.so" \
+ "-Wa,-mx86-used-note=yes" \
+ { protected-func-2b.S } \
+ "protected-func-2d" \
+ "pass.out" \
+ "-fPIE" \
+ ] \
+ [list \
+ "Run protected-data-1 without PIE" \
+ "$NOPIE_LDFLAGS -Wl,--no-as-needed tmpdir/libprotected-data-1.so" \
+ "-Wa,-mx86-used-note=yes" \
+ { protected-data-1b.c } \
+ "protected-data-1a" \
+ "pass.out" \
+ "$NOPIE_CFLAGS" \
+ ] \
+ [list \
+ "Run protected-data-1 with PIE" \
+ "-Wl,--no-as-needed -pie tmpdir/libprotected-data-1.so" \
+ "-Wa,-mx86-used-note=yes" \
+ { protected-data-1b.c } \
+ "protected-data-1b" \
+ "pass.out" \
+ "-fPIE" \
+ ] \
+ [list \
+ "Run protected-data-2a without PIE" \
+ "$NOPIE_LDFLAGS -Wl,--no-as-needed tmpdir/libprotected-data-2a.so" \
+ "-Wa,-mx86-used-note=yes" \
+ { protected-data-2b.S } \
+ "protected-data-2a" \
+ "pass.out" \
+ "$NOPIE_CFLAGS" \
+ ] \
+ [list \
+ "Run protected-data-2b with PIE" \
+ "-Wl,--no-as-needed -pie tmpdir/libprotected-data-2a.so" \
+ "-Wa,-mx86-used-note=yes" \
+ { protected-data-2b.S } \
+ "protected-data-2b" \
+ "pass.out" \
+ "-fPIE" \
+ ] \
+ [list \
+ "Run protected-data-2c without PIE" \
+ "$NOPIE_LDFLAGS -Wl,--no-as-needed tmpdir/libprotected-data-2b.so" \
+ "-Wa,-mx86-used-note=yes" \
+ { protected-data-2b.S } \
+ "protected-data-2c" \
+ "pass.out" \
+ "$NOPIE_CFLAGS" \
+ ] \
+ [list \
+ "Run protected-data-2d with PIE" \
+ "-Wl,--no-as-needed -pie tmpdir/libprotected-data-2b.so" \
+ "-Wa,-mx86-used-note=yes" \
+ { protected-data-2b.S } \
+ "protected-data-2d" \
+ "pass.out" \
+ "-fPIE" \
+ ] \
]
# Run-time tests which require working ifunc attribute support.
--
2.31.1
More information about the Binutils
mailing list