From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Sat, 22 May 2021 23:10:21 -0700 Subject: [PATCH] ld: Add -Bsymbolic-non-weak-functions This option is a subset of -Bsymbolic-functions: only STB_GLOBAL are considered. Vague linkage functions are STB_WEAK. A vague linkage function may have different addresses in a -Bsymbolic-functions linked shared object and outside the shared object. -Bsymbolic-non-weak-functions can keep pointer equality while providing most benefits: (a) fewer JUMP_SLOT (symbol lookups) (b) avoid PLT entries for default visibility defined functions. PR 27871 include/ * bfdlink.h (struct bfd_link_info): Add dynamic_weak_functions. ld/ * ldlex.h (enum option_values): Add OPTION_SYMBOLIC_NON_WEAK_FUNCTIONS. * lexsup.c (struct ld_options): Add -Bsymbolic-non-weak-functions. (enum symbolic_enum): Add symbolic_non_weak_functions. (parse_args): Handle -Bsymbolic-non-weak-functions. * ld.texi: Document -Bsymbolic-non-weak-functions. * NEWS: Mention -Bsymbolic-non-weak-functions. * testsuite/ld-elf/shared.exp: Add tests. * testsuite/ld-elf/symbolic-non-weak-func.s: New file. * testsuite/ld-elf/symbolic-non-weak-func-a.rd: Likewise. * testsuite/ld-elf/symbolic-non-weak-func-b.rd: Likewise. --- bfd/elflink.c | 12 +++++----- include/bfdlink.h | 3 +++ ld/NEWS | 2 ++ ld/ld.texi | 15 ++++++++++--- ld/ldlex.h | 1 + ld/lexsup.c | 17 +++++++++++--- ld/testsuite/ld-elf/shared.exp | 22 +++++++++++++++++++ .../ld-elf/symbolic-non-weak-func-a.rd | 4 ++++ .../ld-elf/symbolic-non-weak-func-b.rd | 4 ++++ ld/testsuite/ld-elf/symbolic-non-weak-func.s | 18 +++++++++++++++ 10 files changed, 85 insertions(+), 13 deletions(-) create mode 100644 ld/testsuite/ld-elf/symbolic-non-weak-func-a.rd create mode 100644 ld/testsuite/ld-elf/symbolic-non-weak-func-b.rd create mode 100644 ld/testsuite/ld-elf/symbolic-non-weak-func.s diff --git a/bfd/elflink.c b/bfd/elflink.c index 7217c2f038baf9cf1df122cc5bb82ac99c00a51e..b7f14694f277f91e6a58491548fae52382683ca6 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -608,14 +608,12 @@ bfd_elf_link_mark_dynamic_symbol (struct bfd_link_info *info, if(h->dynamic || bfd_link_relocatable (info)) return; + int type = sym != NULL ? ELF_ST_TYPE (sym->st_info) : STT_NOTYPE; if ((info->dynamic_data - && (h->type == STT_OBJECT - || h->type == STT_COMMON - || (sym != NULL - && (ELF_ST_TYPE (sym->st_info) == STT_OBJECT - || ELF_ST_TYPE (sym->st_info) == STT_COMMON)))) - || (d != NULL - && h->non_elf + && (type == STT_OBJECT || type == STT_COMMON)) + || (info->dynamic_weak_functions && type == STT_FUNC + && ELF_ST_BIND (sym->st_info) == STB_WEAK) + || (d != NULL && h->non_elf && (*d->match) (&d->head, NULL, h->root.root.string))) { h->dynamic = 1; diff --git a/include/bfdlink.h b/include/bfdlink.h index 840790a298c3f8894494c5266b2de0560ceecfd2..632bf8fdd2ec2c4bf1ee8573884c18b3a2c1bb3f 100644 --- a/include/bfdlink.h +++ b/include/bfdlink.h @@ -368,6 +368,9 @@ struct bfd_link_info /* TRUE if all data symbols should be dynamic. */ unsigned int dynamic_data: 1; + /* TRUE if all weak function symbols should be dynamic. */ + unsigned int dynamic_weak_functions: 1; + /* TRUE if section groups should be resolved. */ unsigned int resolve_section_groups: 1; diff --git a/ld/NEWS b/ld/NEWS index e1ac20b8a97399136cc04b21e677292dd3bf8c66..5e37f9d0c11f8ef8a4900a9d11ba1df50e26c3d6 100644 --- a/ld/NEWS +++ b/ld/NEWS @@ -104,6 +104,8 @@ Changes in 2.37: * Add -Bno-symbolic to cancel -Bsymbolic and -Bsymbolic-functions. +* Add -Bsymbolic-non-weak-functions as a safe subset of -Bsymbolic-functions. + Changes in 2.36: * Add libdep plugin, for linking dependencies of static libraries that diff --git a/ld/ld.texi b/ld/ld.texi index aa8b1aa86eb386358bc18662f1f0b2fce4996763..49b7dfe80d81ba59e7bd86dbae8c4dadc25b9c77 100644 --- a/ld/ld.texi +++ b/ld/ld.texi @@ -1739,7 +1739,7 @@ libraries. @kindex -Bsymbolic @item -Bsymbolic -When creating a shared library, bind references to global symbols to the +When creating a shared library, bind references to non-local symbols to the definition within the shared library, if any. Normally, it is possible for a program linked against a shared library to override the definition within the shared library. This option is only meaningful on ELF @@ -1747,11 +1747,20 @@ platforms which support shared libraries. @kindex -Bsymbolic-functions @item -Bsymbolic-functions -When creating a shared library, bind references to global function -symbols to the definition within the shared library, if any. +When creating a shared library, bind references to non-local function +symbols to the definition within the shared library, if any. A vague linkage +function definition is weak. It may have different addresses in the linked +shared library and outside the shared library. This option is only meaningful on ELF platforms which support shared libraries. +@kindex -Bsymbolic-non-weak-functions +@item -Bsymbolic-non-weak-functions +When creating a shared library, bind references to @code{STB_GLOBAL} function +symbols to the definition within the shared library, if any. Noticeably this +option skips C++ vague linkage functions and is thus safe. +This option is only meaningful on ELF platforms which support shared libraries. + @kindex -Bno-symbolic @item -Bno-symbolic This option can cancel previously specified @samp{-Bsymbolic} and diff --git a/ld/ldlex.h b/ld/ldlex.h index 87cac02141d8c8cf090001ec877dd4e458d19c1b..1a571a7ce331487b2d809bbbd562a5ce32d4e6d7 100644 --- a/ld/ldlex.h +++ b/ld/ldlex.h @@ -64,6 +64,7 @@ enum option_values OPTION_SORT_SECTION, OPTION_STATS, OPTION_SYMBOLIC, + OPTION_SYMBOLIC_NON_WEAK_FUNCTIONS, OPTION_SYMBOLIC_FUNCTIONS, OPTION_TASK_LINK, OPTION_TBSS, diff --git a/ld/lexsup.c b/ld/lexsup.c index fe8722313fedf6d72846fc45418831e5c77efab6..128ffadea5e9a8751336bcc86e3243f66a4e7411 100644 --- a/ld/lexsup.c +++ b/ld/lexsup.c @@ -315,9 +315,11 @@ static const struct ld_option ld_options[] = { {"Bno-symbolic", no_argument, NULL, OPTION_NO_SYMBOLIC}, '\0', NULL, N_("Don't bind global references locally"), ONE_DASH }, { {"Bsymbolic", no_argument, NULL, OPTION_SYMBOLIC}, - '\0', NULL, N_("Bind global references locally"), ONE_DASH }, + '\0', NULL, N_("Bind default visibility defined symbols locally for -shared"), ONE_DASH }, + { {"Bsymbolic-non-weak-functions", no_argument, NULL, OPTION_SYMBOLIC_NON_WEAK_FUNCTIONS}, + '\0', NULL, N_("Bind default visibility defined STB_GLOBAL function symbols locally for -shared"), ONE_DASH }, { {"Bsymbolic-functions", no_argument, NULL, OPTION_SYMBOLIC_FUNCTIONS}, - '\0', NULL, N_("Bind global function references locally"), ONE_DASH }, + '\0', NULL, N_("Bind default visibility defined function symbols locally for -shared"), ONE_DASH }, { {"check-sections", no_argument, NULL, OPTION_CHECK_SECTIONS}, '\0', NULL, N_("Check section addresses for overlaps (default)"), TWO_DASHES }, @@ -647,8 +649,9 @@ parse_args (unsigned argc, char **argv) enum symbolic_enum { symbolic_unset = 0, - symbolic, + symbolic_non_weak_functions, symbolic_functions, + symbolic, } opt_symbolic = symbolic_unset; enum dynamic_list_enum { @@ -1372,6 +1375,9 @@ parse_args (unsigned argc, char **argv) case OPTION_SYMBOLIC: opt_symbolic = symbolic; break; + case OPTION_SYMBOLIC_NON_WEAK_FUNCTIONS: + opt_symbolic = symbolic_non_weak_functions; + break; case OPTION_SYMBOLIC_FUNCTIONS: opt_symbolic = symbolic_functions; break; @@ -1996,6 +2002,11 @@ parse_args (unsigned argc, char **argv) link_info.dynamic = true; link_info.dynamic_data = true; break; + case symbolic_non_weak_functions: + link_info.dynamic = true; + link_info.dynamic_data = true; + link_info.dynamic_weak_functions = true; + break; } /* -z nosectionheader implies --strip-all. */ diff --git a/ld/testsuite/ld-elf/shared.exp b/ld/testsuite/ld-elf/shared.exp index cf010e5b0e59576a047476ecaa2d9a74c8cc7ed0..d5508912aa286e4a552b9b0270afa815a7d8a960 100644 --- a/ld/testsuite/ld-elf/shared.exp +++ b/ld/testsuite/ld-elf/shared.exp @@ -459,6 +459,28 @@ run_ld_link_tests [list \ "symbolic-func.so"] \ ] +if {[istarget "aarch64*-*-*"] || [istarget "powerpc*-*-*"] || + [istarget "i?86-*-*"] || [istarget "x86_64-*-*"]} { + run_ld_link_tests [list \ + [list "-Bsymbolic-non-weak-functions -Bsymbolic" \ + "-shared -Bsymbolic-non-weak-functions -Bsymbolic" "" "$AFLAGS_PIC" \ + {symbolic-non-weak-func.s} {{readelf {-r --wide} symbolic-non-weak-func-a.rd}} \ + "symbolic-non-weak-func-a.so"] \ + ] + run_ld_link_tests [list \ + [list "-Bsymbolic-non-weak-functions" \ + "-shared -Bsymbolic-non-weak-functions" "" "$AFLAGS_PIC" \ + {symbolic-non-weak-func.s} {{readelf {-r --wide} symbolic-non-weak-func-b.rd}} \ + "symbolic-non-weak-func-b.so"] \ + ] + run_ld_link_tests [list \ + [list "-Bsymbolic-functions -Bsymbolic-non-weak-functions" \ + "-shared -Bsymbolic-functions -Bsymbolic-non-weak-functions" "" "$AFLAGS_PIC" \ + {symbolic-non-weak-func.s} {{readelf {-r --wide} symbolic-non-weak-func-b.rd}} \ + "symbolic-non-weak-func-b.so"] \ + ] +} + run_ld_link_tests [list \ [list "Build pr20995.so" \ "-shared" "" "$AFLAGS_PIC" \ diff --git a/ld/testsuite/ld-elf/symbolic-non-weak-func-a.rd b/ld/testsuite/ld-elf/symbolic-non-weak-func-a.rd new file mode 100644 index 0000000000000000000000000000000000000000..ef591840f5c338a55f6d44fc372568569011c430 --- /dev/null +++ b/ld/testsuite/ld-elf/symbolic-non-weak-func-a.rd @@ -0,0 +1,4 @@ +#... +[0-9a-f]+ +[0-9a-f]+ +R_.*_RELATIVE .* +[0-9a-f]+ +[0-9a-f]+ +R_.*_RELATIVE .* +[0-9a-f]+ +[0-9a-f]+ +R_.*_RELATIVE .* diff --git a/ld/testsuite/ld-elf/symbolic-non-weak-func-b.rd b/ld/testsuite/ld-elf/symbolic-non-weak-func-b.rd new file mode 100644 index 0000000000000000000000000000000000000000..34228b0627b226cfdc76e3cedff6f515b7c27872 --- /dev/null +++ b/ld/testsuite/ld-elf/symbolic-non-weak-func-b.rd @@ -0,0 +1,4 @@ +#... +[0-9a-f]+ +[0-9a-f]+ +R_.*_RELATIVE .* +[0-9a-f]+ +[0-9a-f]+ +R_.*_RELATIVE .* +[0-9a-f]+ +[0-9a-f]+ +R_.* weak_fun.* diff --git a/ld/testsuite/ld-elf/symbolic-non-weak-func.s b/ld/testsuite/ld-elf/symbolic-non-weak-func.s new file mode 100644 index 0000000000000000000000000000000000000000..e259f12bfc126bf2ef9bf16aba64667ca4e2bfd5 --- /dev/null +++ b/ld/testsuite/ld-elf/symbolic-non-weak-func.s @@ -0,0 +1,18 @@ + .text + .global global_fun + .type global_fun, %function +global_fun: + .space 4 + .weak weak_fun + .type weak_fun, %function +weak_fun: + .space 4 + + .section .data,"aw",%progbits + .p2align 3 + .dc.a global_data + .dc.a global_fun + .dc.a weak_fun + + .global global_data +global_data: