diff -rup binutils.orig/bfd/elf32-i386.c binutils-2.38/bfd/elf32-i386.c --- binutils.orig/bfd/elf32-i386.c 2022-05-24 12:01:20.307998318 +0100 +++ binutils-2.38/bfd/elf32-i386.c 2022-05-24 12:04:48.789688224 +0100 @@ -1772,11 +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; + else + h->pointer_equality_needed = 1; } if (!func_pointer_ref) @@ -1798,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 -rup binutils.orig/bfd/elf64-x86-64.c binutils-2.38/bfd/elf64-x86-64.c --- binutils.orig/bfd/elf64-x86-64.c 2022-05-24 12:01:20.296998387 +0100 +++ binutils-2.38/bfd/elf64-x86-64.c 2022-05-24 12:06:07.720192208 +0100 @@ -2211,16 +2211,18 @@ elf_x86_64_scan_relocs (bfd *abfd, struc 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; + else + h->pointer_equality_needed = 1; } if (!func_pointer_ref) @@ -2242,6 +2244,23 @@ elf_x86_64_scan_relocs (bfd *abfd, struc 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; + } } }