Projects
openEuler:24.03:SP1:Everything
binutils
_service:tar_scm:LoongArch-Make-protected-funct...
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File _service:tar_scm:LoongArch-Make-protected-function-symbols-local-for-.patch of Package binutils
From a95555b83c866216189dde969ab7b76ebd57c60c Mon Sep 17 00:00:00 2001 From: Xi Ruoyao <xry111@xry111.site> Date: Sun, 30 Jun 2024 15:18:23 +0800 Subject: [PATCH 097/123] LoongArch: Make protected function symbols local for -shared On LoongArch there is no reason to treat STV_PROTECTED STT_FUNC symbols as preemptible. See the comment above LARCH_REF_LOCAL for detailed explanation. Signed-off-by: Xi Ruoyao <xry111@xry111.site> --- bfd/elfnn-loongarch.c | 76 ++++++++++++++----- ld/testsuite/ld-loongarch-elf/ifunc-reloc.d | 2 +- .../ld-loongarch-elf/ld-loongarch-elf.exp | 1 + .../ld-loongarch-elf/protected-func.d | 6 ++ .../ld-loongarch-elf/protected-func.s | 17 +++++ 5 files changed, 81 insertions(+), 21 deletions(-) create mode 100644 ld/testsuite/ld-loongarch-elf/protected-func.d create mode 100644 ld/testsuite/ld-loongarch-elf/protected-func.s diff --git a/bfd/elfnn-loongarch.c b/bfd/elfnn-loongarch.c index 6b1a4ecc..2bdd7be2 100644 --- a/bfd/elfnn-loongarch.c +++ b/bfd/elfnn-loongarch.c @@ -181,6 +181,44 @@ struct loongarch_elf_link_hash_table } \ while (0) +/* TL;DR always use it in this file instead when you want to type + SYMBOL_REFERENCES_LOCAL. + + It's like SYMBOL_REFERENCES_LOCAL, but it returns true for local + protected functions. It happens to be same as SYMBOL_CALLS_LOCAL but + let's not reuse SYMBOL_CALLS_LOCAL or "CALLS" may puzzle people. + + We do generate a PLT entry when someone attempts to la.pcrel an external + function. But we never really implemented "R_LARCH_COPY", thus we've + never supported la.pcrel an external symbol unless the loaded address is + only used for locating a function to be called. Thus the PLT entry is + a normal PLT entry, not intended to be a so-called "canonical PLT entry" + on the ports supporting copy relocation. So attempting to la.pcrel an + external function will just break pointer equality, even it's a + STV_DEFAULT function: + + $ cat t.c + #include <assert.h> + void check(void *p) {assert(p == check);} + $ cat main.c + extern void check(void *); + int main(void) { check(check); } + $ cc t.c -fPIC -shared -o t.so + $ cc main.c -mdirect-extern-access t.so -Wl,-rpath=. -fpie -pie + $ ./a.out + a.out: t.c:2: check: Assertion `p == check' failed. + Aborted + + Thus handling STV_PROTECTED function specially just fixes nothing: + adding -fvisibility=protected compiling t.c will not magically fix + the inequality. The only possible and correct fix is not to use + -mdirect-extern-access. + + So we should remove this special handling, because it's only an + unsuccessful workaround for invalid code and it's penalizing valid + code. */ +#define LARCH_REF_LOCAL(info, h) \ + (_bfd_elf_symbol_refs_local_p ((h), (info), true)) /* Generate a PLT header. */ @@ -712,7 +750,7 @@ loongarch_tls_transition_without_check (struct bfd_link_info *info, struct elf_link_hash_entry *h) { bool local_exec = bfd_link_executable (info) - && SYMBOL_REFERENCES_LOCAL (info, h); + && LARCH_REF_LOCAL (info, h); switch (r_type) { @@ -1221,7 +1259,7 @@ loongarch_elf_adjust_dynamic_symbol (struct bfd_link_info *info, { if (h->plt.refcount <= 0 || (h->type != STT_GNU_IFUNC - && (SYMBOL_REFERENCES_LOCAL (info, h) + && (LARCH_REF_LOCAL (info, h) || (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT && h->root.type == bfd_link_hash_undefweak)))) { @@ -1739,14 +1777,14 @@ elfNN_allocate_ifunc_dynrelocs (struct elf_link_hash_entry *h, here if it is defined and referenced in a non-shared object. */ if (h->type == STT_GNU_IFUNC && h->def_regular) { - if (ref_local && SYMBOL_REFERENCES_LOCAL (info, h)) + if (ref_local && LARCH_REF_LOCAL (info, h)) return local_allocate_ifunc_dyn_relocs (info, h, &h->dyn_relocs, PLT_ENTRY_SIZE, PLT_HEADER_SIZE, GOT_ENTRY_SIZE, false); - else if (!ref_local && !SYMBOL_REFERENCES_LOCAL (info, h)) + else if (!ref_local && !LARCH_REF_LOCAL (info, h)) return _bfd_elf_allocate_ifunc_dyn_relocs (info, h, &h->dyn_relocs, PLT_ENTRY_SIZE, @@ -1774,7 +1812,6 @@ elfNN_allocate_ifunc_dynrelocs_ref_global (struct elf_link_hash_entry *h, false); } - /* Allocate space in .plt, .got and associated reloc sections for ifunc dynamic relocs. */ @@ -2686,7 +2723,6 @@ tlsoff (struct bfd_link_info *info, bfd_vma addr) return addr - elf_hash_table (info)->tls_sec->vma; } - static int loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info, bfd *input_bfd, asection *input_section, @@ -2812,7 +2848,7 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info, { defined_local = !unresolved_reloc && !ignored; resolved_local = - defined_local && SYMBOL_REFERENCES_LOCAL (info, h); + defined_local && LARCH_REF_LOCAL (info, h); resolved_dynly = !resolved_local; resolved_to_const = !resolved_local && !resolved_dynly; } @@ -2901,7 +2937,7 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info, outrel.r_addend = 0; } - if (SYMBOL_REFERENCES_LOCAL (info, h)) + if (LARCH_REF_LOCAL (info, h)) { if (htab->elf.splt != NULL) @@ -3251,7 +3287,7 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info, if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL (is_dyn, bfd_link_pic (info), h) && ((bfd_link_pic (info) - && SYMBOL_REFERENCES_LOCAL (info, h)))) + && LARCH_REF_LOCAL (info, h)))) { /* This is actually a static link, or it is a -Bsymbolic link and the symbol is defined @@ -3396,7 +3432,7 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info, asection *srel = htab->elf.srelgot; bfd_vma tls_block_off = 0; - if (SYMBOL_REFERENCES_LOCAL (info, h)) + if (LARCH_REF_LOCAL (info, h)) { BFD_ASSERT (elf_hash_table (info)->tls_sec); tls_block_off = relocation @@ -3407,7 +3443,7 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info, { rela.r_offset = sec_addr (got) + got_off; rela.r_addend = 0; - if (SYMBOL_REFERENCES_LOCAL (info, h)) + if (LARCH_REF_LOCAL (info, h)) { /* Local sym, used in exec, set module id 1. */ if (bfd_link_executable (info)) @@ -3440,7 +3476,7 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info, if (tls_type & GOT_TLS_IE) { rela.r_offset = sec_addr (got) + got_off + ie_off; - if (SYMBOL_REFERENCES_LOCAL (info, h)) + if (LARCH_REF_LOCAL (info, h)) { /* Local sym, used in exec, set module id 1. */ if (!bfd_link_executable (info)) @@ -3642,7 +3678,7 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info, bfd_link_pic (info), h) && bfd_link_pic (info) - && SYMBOL_REFERENCES_LOCAL (info, h)) + && LARCH_REF_LOCAL (info, h)) { Elf_Internal_Rela rela; rela.r_offset = sec_addr (got) + got_off; @@ -4183,7 +4219,7 @@ loongarch_tls_perform_trans (bfd *abfd, asection *sec, { unsigned long insn; bool local_exec = bfd_link_executable (info) - && SYMBOL_REFERENCES_LOCAL (info, h); + && LARCH_REF_LOCAL (info, h); bfd_byte *contents = elf_section_data (sec)->this_hdr.contents; unsigned long r_type = ELFNN_R_TYPE (rel->r_info); unsigned long r_symndx = ELFNN_R_SYM (rel->r_info); @@ -4895,7 +4931,7 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec, else continue; - if (h && SYMBOL_REFERENCES_LOCAL (info, h)) + if (h && LARCH_REF_LOCAL (info, h)) local_got = true; symtype = h->type; } @@ -5032,12 +5068,12 @@ loongarch_elf_finish_dynamic_symbol (bfd *output_bfd, if (htab->elf.splt) { BFD_ASSERT ((h->type == STT_GNU_IFUNC - && SYMBOL_REFERENCES_LOCAL (info, h)) + && LARCH_REF_LOCAL (info, h)) || h->dynindx != -1); plt = htab->elf.splt; gotplt = htab->elf.sgotplt; - if (h->type == STT_GNU_IFUNC && SYMBOL_REFERENCES_LOCAL (info, h)) + if (h->type == STT_GNU_IFUNC && LARCH_REF_LOCAL (info, h)) relplt = htab->elf.srelgot; else relplt = htab->elf.srelplt; @@ -5048,7 +5084,7 @@ loongarch_elf_finish_dynamic_symbol (bfd *output_bfd, else /* if (htab->elf.iplt) */ { BFD_ASSERT (h->type == STT_GNU_IFUNC - && SYMBOL_REFERENCES_LOCAL (info, h)); + && LARCH_REF_LOCAL (info, h)); plt = htab->elf.iplt; gotplt = htab->elf.igotplt; @@ -5136,7 +5172,7 @@ loongarch_elf_finish_dynamic_symbol (bfd *output_bfd, if (htab->elf.splt == NULL) srela = htab->elf.irelplt; - if (SYMBOL_REFERENCES_LOCAL (info, h)) + if (LARCH_REF_LOCAL (info, h)) { asection *sec = h->root.u.def.section; rela.r_info = ELFNN_R_INFO (0, R_LARCH_IRELATIVE); @@ -5173,7 +5209,7 @@ loongarch_elf_finish_dynamic_symbol (bfd *output_bfd, return true; } } - else if (bfd_link_pic (info) && SYMBOL_REFERENCES_LOCAL (info, h)) + else if (bfd_link_pic (info) && LARCH_REF_LOCAL (info, h)) { asection *sec = h->root.u.def.section; rela.r_info = ELFNN_R_INFO (0, R_LARCH_RELATIVE); diff --git a/ld/testsuite/ld-loongarch-elf/ifunc-reloc.d b/ld/testsuite/ld-loongarch-elf/ifunc-reloc.d index cb592874..968e7564 100644 --- a/ld/testsuite/ld-loongarch-elf/ifunc-reloc.d +++ b/ld/testsuite/ld-loongarch-elf/ifunc-reloc.d @@ -8,6 +8,7 @@ .* R_LARCH_IRELATIVE .* .* R_LARCH_IRELATIVE .* .* R_LARCH_IRELATIVE .* +.* R_LARCH_IRELATIVE .* #... .*'\.rela\.plt'.* #... @@ -16,4 +17,3 @@ .* R_LARCH_JUMP_SLOT .* .* R_LARCH_JUMP_SLOT .* .* R_LARCH_JUMP_SLOT .* -.* R_LARCH_JUMP_SLOT .* diff --git a/ld/testsuite/ld-loongarch-elf/ld-loongarch-elf.exp b/ld/testsuite/ld-loongarch-elf/ld-loongarch-elf.exp index 506dac3e..30d7bc03 100644 --- a/ld/testsuite/ld-loongarch-elf/ld-loongarch-elf.exp +++ b/ld/testsuite/ld-loongarch-elf/ld-loongarch-elf.exp @@ -134,6 +134,7 @@ if [istarget "loongarch64-*-*"] { run_dump_test "reloc_abs_with_shared" run_dump_test "r_larch_32_elf64" run_dump_test "ifunc-reloc" + run_dump_test "protected-func" } if [check_pie_support] { diff --git a/ld/testsuite/ld-loongarch-elf/protected-func.d b/ld/testsuite/ld-loongarch-elf/protected-func.d new file mode 100644 index 00000000..501c7cb5 --- /dev/null +++ b/ld/testsuite/ld-loongarch-elf/protected-func.d @@ -0,0 +1,6 @@ +#ld: -shared +#readelf: -Wr + +#... +.* R_LARCH_RELATIVE .* +.* R_LARCH_RELATIVE .* diff --git a/ld/testsuite/ld-loongarch-elf/protected-func.s b/ld/testsuite/ld-loongarch-elf/protected-func.s new file mode 100644 index 00000000..8f28f925 --- /dev/null +++ b/ld/testsuite/ld-loongarch-elf/protected-func.s @@ -0,0 +1,17 @@ +# protected function should be non-preemptible and relocated with +# R_LARCH_RELATIVE in shared library, for both GOT and pointer data + +.globl x +.protected x +.type x, @function +x: + ret + +.globl _start +_start: + la.got $a0, x + ret + +.data +p: + .quad x -- 2.33.0
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.
浙ICP备2022010568号-2