[ELF] Add -Bsymbolic-non-weak

This adds a new -Bsymbolic option that directly binds all non-weak
symbols. There's a couple of reasons motivating this:
* The new flag will match the default behavior on Mach-O, so you can get
  consistent behavior across platforms.
* We have use cases for which making weak data preemptible is useful,
  but we don't want to pessimize access to non-weak data. (For a large
  internal app, we measured 2000+ data symbols whose accesses would be
  unnecessarily pessimized by `-Bsymbolic-functions`.)

Reviewed By: MaskRay

Differential Revision: https://reviews.llvm.org/D158322
This commit is contained in:
Shoaib Meenai
2023-08-18 15:37:35 -07:00
parent d8e9c5d9ca
commit 97e39f96c8
6 changed files with 50 additions and 7 deletions

View File

@@ -53,8 +53,8 @@ enum ELFKind : uint8_t {
};
// For -Bno-symbolic, -Bsymbolic-non-weak-functions, -Bsymbolic-functions,
// -Bsymbolic.
enum class BsymbolicKind { None, NonWeakFunctions, Functions, All };
// -Bsymbolic-non-weak, -Bsymbolic.
enum class BsymbolicKind { None, NonWeakFunctions, Functions, NonWeak, All };
// For --build-id.
enum class BuildIdKind { None, Fast, Md5, Sha1, Hexstring, Uuid };

View File

@@ -1155,13 +1155,15 @@ static void readConfigs(opt::InputArgList &args) {
config->androidMemtagMode = getMemtagMode(args);
config->auxiliaryList = args::getStrings(args, OPT_auxiliary);
config->armBe8 = args.hasArg(OPT_be8);
if (opt::Arg *arg =
args.getLastArg(OPT_Bno_symbolic, OPT_Bsymbolic_non_weak_functions,
OPT_Bsymbolic_functions, OPT_Bsymbolic)) {
if (opt::Arg *arg = args.getLastArg(
OPT_Bno_symbolic, OPT_Bsymbolic_non_weak_functions,
OPT_Bsymbolic_functions, OPT_Bsymbolic_non_weak, OPT_Bsymbolic)) {
if (arg->getOption().matches(OPT_Bsymbolic_non_weak_functions))
config->bsymbolic = BsymbolicKind::NonWeakFunctions;
else if (arg->getOption().matches(OPT_Bsymbolic_functions))
config->bsymbolic = BsymbolicKind::Functions;
else if (arg->getOption().matches(OPT_Bsymbolic_non_weak))
config->bsymbolic = BsymbolicKind::NonWeak;
else if (arg->getOption().matches(OPT_Bsymbolic))
config->bsymbolic = BsymbolicKind::All;
}

View File

@@ -42,6 +42,9 @@ def Bno_symbolic: F<"Bno-symbolic">, HelpText<"Don't bind default visibility def
def Bsymbolic: F<"Bsymbolic">, HelpText<"Bind default visibility defined symbols locally for -shared">;
def Bsymbolic_non_weak: F<"Bsymbolic-non-weak">,
HelpText<"Bind default visibility defined STB_GLOBAL symbols locally for -shared">;
def Bsymbolic_functions: F<"Bsymbolic-functions">,
HelpText<"Bind default visibility defined function symbols locally for -shared">;

View File

@@ -365,6 +365,8 @@ bool elf::computeIsPreemptible(const Symbol &sym) {
// in the dynamic list. -Bsymbolic-non-weak-functions is a non-weak subset of
// -Bsymbolic-functions.
if (config->symbolic ||
(config->bsymbolic == BsymbolicKind::NonWeak &&
sym.binding != STB_WEAK) ||
(config->bsymbolic == BsymbolicKind::Functions && sym.isFunc()) ||
(config->bsymbolic == BsymbolicKind::NonWeakFunctions && sym.isFunc() &&
sym.binding != STB_WEAK))

View File

@@ -82,6 +82,9 @@ Bind default visibility defined symbols locally for
Also set the
.Dv DF_SYMBOLIC
flag.
.It Fl Bsymbolic-non-weak
Bind default visibility defined STB_GLOBAL symbols locally for
.Fl shared.
.It Fl Bsymbolic-functions
Bind default visibility defined function symbols locally for
.Fl shared.

View File

@@ -6,7 +6,7 @@
# RUN: llvm-readobj -r %t0.so | FileCheck %s --check-prefix=REL_DEF
# RUN: llvm-objdump -d %t0.so | FileCheck %s --check-prefix=ASM_DEF
## -Bsymbolic-functions makes all STB_GLOBAL STT_FUNC definitions non-preemptible.
## -Bsymbolic-non-weak-functions makes all STB_GLOBAL STT_FUNC definitions non-preemptible.
# RUN: ld.lld -shared -Bsymbolic-non-weak-functions %t/a.o %t/b.o -o %t1.so
# RUN: llvm-readobj -r %t1.so | FileCheck %s --check-prefix=REL_GFUN
# RUN: llvm-objdump -d %t1.so | FileCheck %s --check-prefix=ASM_GFUN
@@ -21,6 +21,11 @@
# RUN: llvm-readobj -r %t3.so | FileCheck %s --check-prefix=REL_ALL
# RUN: llvm-objdump -d %t3.so | FileCheck %s --check-prefix=ASM_ALL
## -Bsymbolic-non-weak makes all STB_GLOBAL definitions non-preemptible.
# RUN: ld.lld -shared -Bsymbolic-non-weak %t/a.o %t/b.o -o %t4.so
# RUN: llvm-readobj -r %t4.so | FileCheck %s --check-prefix=REL_GALL
# RUN: llvm-objdump -d %t4.so | FileCheck %s --check-prefix=ASM_GALL
# RUN: ld.lld -shared -Bsymbolic-functions -Bsymbolic %t/a.o %t/b.o -o %t.so
# RUN: cmp %t.so %t3.so
# RUN: ld.lld -shared -Bsymbolic -Bsymbolic-functions %t/a.o %t/b.o -o %t.so
@@ -37,6 +42,7 @@
# REL_DEF: .rela.dyn {
# REL_DEF-NEXT: R_X86_64_RELATIVE -
# REL_DEF-NEXT: R_X86_64_RELATIVE -
# REL_DEF-NEXT: R_X86_64_64 data_weak_default
# REL_DEF-NEXT: R_X86_64_64 data_default
# REL_DEF-NEXT: }
# REL_DEF-NEXT: .rela.plt {
@@ -59,6 +65,7 @@
# REL_GFUN: .rela.dyn {
# REL_GFUN-NEXT: R_X86_64_RELATIVE -
# REL_GFUN-NEXT: R_X86_64_RELATIVE -
# REL_GFUN-NEXT: R_X86_64_64 data_weak_default
# REL_GFUN-NEXT: R_X86_64_64 data_default
# REL_GFUN-NEXT: }
# REL_GFUN-NEXT: .rela.plt {
@@ -79,6 +86,7 @@
# REL_FUN: .rela.dyn {
# REL_FUN-NEXT: R_X86_64_RELATIVE -
# REL_FUN-NEXT: R_X86_64_RELATIVE -
# REL_FUN-NEXT: R_X86_64_64 data_weak_default
# REL_FUN-NEXT: R_X86_64_64 data_default
# REL_FUN-NEXT: }
# REL_FUN-NEXT: .rela.plt {
@@ -99,6 +107,7 @@
# REL_ALL-NEXT: R_X86_64_RELATIVE -
# REL_ALL-NEXT: R_X86_64_RELATIVE -
# REL_ALL-NEXT: R_X86_64_RELATIVE -
# REL_ALL-NEXT: R_X86_64_RELATIVE -
# REL_ALL-NEXT: }
# REL_ALL-NEXT: .rela.plt {
# REL_ALL-NEXT: R_X86_64_JUMP_SLOT undef
@@ -113,6 +122,26 @@
# ASM_ALL-NEXT: callq {{.*}} <notype_default>
# ASM_ALL-NEXT: callq {{.*}} <undef@plt>
# REL_GALL: .rela.dyn {
# REL_GALL-NEXT: R_X86_64_RELATIVE -
# REL_GALL-NEXT: R_X86_64_RELATIVE -
# REL_GALL-NEXT: R_X86_64_RELATIVE -
# REL_GALL-NEXT: R_X86_64_64 data_weak_default
# REL_GALL-NEXT: }
# REL_GALL-NEXT: .rela.plt {
# REL_GALL-NEXT: R_X86_64_JUMP_SLOT weak_default
# REL_GALL-NEXT: R_X86_64_JUMP_SLOT undef
# REL_GALL-NEXT: }
# ASM_GALL: <_start>:
# ASM_GALL-NEXT: callq {{.*}} <default>
# ASM_GALL-NEXT: callq {{.*}} <protected>
# ASM_GALL-NEXT: callq {{.*}} <hidden>
# ASM_GALL-NEXT: callq {{.*}} <weak_default@plt>
# ASM_GALL-NEXT: callq {{.*}} <ext_default>
# ASM_GALL-NEXT: callq {{.*}} <notype_default>
# ASM_GALL-NEXT: callq {{.*}} <undef@plt>
#--- a.s
.globl default, protected, hidden, notype_default
.weak weak_default
@@ -144,16 +173,20 @@ _start:
.data
.quad data_default
.quad data_weak_default
.quad data_protected
.quad data_hidden
.globl data_default, data_protected, data_hidden
.globl data_default, data_weak_default, data_protected, data_hidden
.weak data_weak_default
.protected data_protected
.hidden data_hidden
.type data_default, @object
.type data_weak_default, @object
.type data_protected, @object
.type data_hidden, @object
data_default: .byte 0
data_weak_default: .byte 0
data_protected: .byte 0
data_hidden: .byte 0