diff options
-rw-r--r-- | bfd/elf32-i386.c | 41 | ||||
-rw-r--r-- | bfd/elf64-x86-64.c | 40 | ||||
-rw-r--r-- | ld/testsuite/ld-x86-64/protected-func-3.c | 41 | ||||
-rw-r--r-- | ld/testsuite/ld-x86-64/x86-64.exp | 18 |
4 files changed, 102 insertions, 38 deletions
diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c index fb5ed16..b034154 100644 --- a/bfd/elf32-i386.c +++ b/bfd/elf32-i386.c @@ -1772,28 +1772,14 @@ elf_i386_scan_relocs (bfd *abfd, } else { - h->pointer_equality_needed = 1; - /* R_386_32 can be resolved at run-time. */ + /* R_386_32 can be resolved at run-time. Function + pointer reference doesn't need PLT for pointer + equality. */ if (r_type == R_386_32 && (sec->flags & SEC_READONLY) == 0) func_pointer_ref = true; - } - - if (h->pointer_equality_needed - && h->type == STT_FUNC - && eh->def_protected - && elf_has_indirect_extern_access (h->root.u.def.section->owner)) - { - /* Disallow non-canonical reference to canonical - protected function. */ - _bfd_error_handler - /* xgettext:c-format */ - (_("%pB: non-canonical reference to canonical " - "protected function `%s' in %pB"), - abfd, h->root.root.string, - h->root.u.def.section->owner); - bfd_set_error (bfd_error_bad_value); - goto error_return; + else + h->pointer_equality_needed = 1; } if (!func_pointer_ref) @@ -1815,6 +1801,23 @@ elf_i386_scan_relocs (bfd *abfd, if (!h->def_regular || (sec->flags & (SEC_CODE | SEC_READONLY)) != 0) h->plt.refcount = 1; + + if (h->pointer_equality_needed + && h->type == STT_FUNC + && eh->def_protected + && elf_has_indirect_extern_access (h->root.u.def.section->owner)) + { + /* Disallow non-canonical reference to canonical + protected function. */ + _bfd_error_handler + /* xgettext:c-format */ + (_("%pB: non-canonical reference to canonical " + "protected function `%s' in %pB"), + abfd, h->root.root.string, + h->root.u.def.section->owner); + bfd_set_error (bfd_error_bad_value); + goto error_return; + } } } diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c index 6cebc7c..6d69d61 100644 --- a/bfd/elf64-x86-64.c +++ b/bfd/elf64-x86-64.c @@ -2211,33 +2211,18 @@ elf_x86_64_scan_relocs (bfd *abfd, struct bfd_link_info *info, else if (r_type != R_X86_64_PC32_BND && r_type != R_X86_64_PC64) { - h->pointer_equality_needed = 1; /* At run-time, R_X86_64_64 can be resolved for both x86-64 and x32. But R_X86_64_32 and R_X86_64_32S - can only be resolved for x32. */ + can only be resolved for x32. Function pointer + reference doesn't need PLT for pointer equality. */ if ((sec->flags & SEC_READONLY) == 0 && (r_type == R_X86_64_64 || (!ABI_64_P (abfd) && (r_type == R_X86_64_32 || r_type == R_X86_64_32S)))) func_pointer_ref = true; - } - - if (h->pointer_equality_needed - && h->type == STT_FUNC - && eh->def_protected - && elf_has_indirect_extern_access (h->root.u.def.section->owner)) - { - /* Disallow non-canonical reference to canonical - protected function. */ - _bfd_error_handler - /* xgettext:c-format */ - (_("%pB: non-canonical reference to canonical " - "protected function `%s' in %pB"), - abfd, h->root.root.string, - h->root.u.def.section->owner); - bfd_set_error (bfd_error_bad_value); - goto error_return; + else + h->pointer_equality_needed = 1; } if (!func_pointer_ref) @@ -2259,6 +2244,23 @@ elf_x86_64_scan_relocs (bfd *abfd, struct bfd_link_info *info, if (!h->def_regular || (sec->flags & (SEC_CODE | SEC_READONLY)) != 0) h->plt.refcount = 1; + + if (h->pointer_equality_needed + && h->type == STT_FUNC + && eh->def_protected + && elf_has_indirect_extern_access (h->root.u.def.section->owner)) + { + /* Disallow non-canonical reference to canonical + protected function. */ + _bfd_error_handler + /* xgettext:c-format */ + (_("%pB: non-canonical reference to canonical " + "protected function `%s' in %pB"), + abfd, h->root.root.string, + h->root.u.def.section->owner); + bfd_set_error (bfd_error_bad_value); + goto error_return; + } } } diff --git a/ld/testsuite/ld-x86-64/protected-func-3.c b/ld/testsuite/ld-x86-64/protected-func-3.c new file mode 100644 index 0000000..bbf433b --- /dev/null +++ b/ld/testsuite/ld-x86-64/protected-func-3.c @@ -0,0 +1,41 @@ +#include <stdio.h> + +#include "protected-func-1.h" + +protected_func_type protected_func_1a_ptr = protected_func_1a; +protected_func_type protected_func_1b_ptr = protected_func_1b; + +int +protected_func_1b (void) +{ + return 3; +} + +int +main (void) +{ + int res = 0; + + protected_func_1a (); + protected_func_1b (); + + /* Check if we get the same address for the protected function symbol. */ + if (protected_func_1a_ptr != protected_func_1a_p ()) + { + puts ("'protected_func_1a' in main and shared library doesn't have same address"); + res = 1; + } + + /* Check if we get the different addresses for the protected function + symbol. */ + if (protected_func_1b_ptr == protected_func_1b_p ()) + { + puts ("'protected_func_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/x86-64.exp b/ld/testsuite/ld-x86-64/x86-64.exp index 1a7d1ed..5e5636b 100644 --- a/ld/testsuite/ld-x86-64/x86-64.exp +++ b/ld/testsuite/ld-x86-64/x86-64.exp @@ -1887,6 +1887,24 @@ if { [isnative] && [check_compiler_available] } { "-fPIE" \ ] \ [list \ + "Run protected-func-3a without PIE" \ + "$NOPIE_LDFLAGS -Wl,--no-as-needed tmpdir/libprotected-func-2a.so" \ + "-Wa,-mx86-used-note=yes" \ + { protected-func-3.c } \ + "protected-func-3a" \ + "pass.out" \ + "$NOPIE_CFLAGS" \ + ] \ + [list \ + "Run protected-func-3b with PIE" \ + "-Wl,--no-as-needed -pie tmpdir/libprotected-func-2a.so" \ + "-Wa,-mx86-used-note=yes" \ + { protected-func-3.c } \ + "protected-func-2b" \ + "pass.out" \ + "-fPIE" \ + ] \ + [list \ "Run protected-data-1a without PIE" \ "$NOPIE_LDFLAGS -Wl,--no-as-needed tmpdir/libprotected-data-1a.so" \ "-Wa,-mx86-used-note=yes" \ |