Skip to content

Commit

Permalink
Add --Bsymbolic-non-weak and --Bsymbolic-non-weak-functions
Browse files Browse the repository at this point in the history
GNU ld doesn't support these options, but LLVM lld do.
  • Loading branch information
rui314 committed Apr 10, 2024
1 parent 7835e45 commit 7d17aa8
Show file tree
Hide file tree
Showing 6 changed files with 139 additions and 15 deletions.
12 changes: 11 additions & 1 deletion docs/mold.md
Original file line number Diff line number Diff line change
Expand Up @@ -350,8 +350,18 @@ but as `-o magic`.
This option has the same effect as `--Bsymbolic` but works only for function
symbols. Data symbols remain being both imported and exported.

* `--Bsymbolic-non-weak`:
This option has the same effect as `--Bsymbolic` but works only for non-weak
symbols. Weak symbols remain being both imported and exported.

* `--Bsymbolic-non-weak-functions`:
This option has the same effect as `--Bsymbolic` but works only for non-weak
function symbols. Data symbols and weak function symbols remain being both
imported and exported.

* `--Bno-symbolic`:
Cancel `--Bsymbolic` and `--Bsymbolic-functions`.
Cancel `--Bsymbolic`, `--Bsymbolic-functions`, `--Bsymbolic-non-weak` and
`--Bsymbolic-non-weak-functions`.

* `--Map`=_file_:
Write map file to _file_.
Expand Down
22 changes: 14 additions & 8 deletions elf/cmdline.cc
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,12 @@ inline const char helpmsg[] = R"(
Trace references to SYMBOL
--Bdynamic, --dy Link against shared libraries (default)
--Bstatic, --dn, --static Do not link against shared libraries
--Bsymbolic Bind global symbols locally
--Bsymbolic-functions Bind global functions locally
--Bno-symbolic Cancel --Bsymbolic and --Bsymbolic-functions
--Bsymbolic Bind all symbols locally
--Bsymbolic-functions Bind function symbols locally
--Bsymbolic-non-weak Bind all but weak symbols locally
--Bsymbolic-non-weak-functions
Bind all but weak function symbols locally
--Bno-symbolic Cancel --Bsymbolic options
--Map FILE Write map file to a given file
--Tbss=ADDR Set address to .bss
--Tdata=ADDR Set address to .data
Expand Down Expand Up @@ -684,12 +687,15 @@ std::vector<std::string> parse_nonpositional_args(Context<E> &ctx) {
} else if (read_flag("no-export-dynamic")) {
ctx.arg.export_dynamic = false;
} else if (read_flag("Bsymbolic")) {
ctx.arg.Bsymbolic = true;
ctx.arg.Bsymbolic = BSYMBOLIC_ALL;
} else if (read_flag("Bsymbolic-functions")) {
ctx.arg.Bsymbolic_functions = true;
ctx.arg.Bsymbolic = BSYMBOLIC_FUNCTIONS;
} else if (read_flag("Bsymbolic-non-weak")) {
ctx.arg.Bsymbolic = BSYMBOLIC_NON_WEAK;
} else if (read_flag("Bsymbolic-non-weak-functions")) {
ctx.arg.Bsymbolic = BSYMBOLIC_NON_WEAK_FUNCTIONS;
} else if (read_flag("Bno-symbolic")) {
ctx.arg.Bsymbolic = false;
ctx.arg.Bsymbolic_functions = false;
ctx.arg.Bsymbolic = BSYMBOLIC_NONE;
} else if (read_arg("exclude-libs")) {
append(ctx.arg.exclude_libs, split_by_comma_or_colon(arg));
} else if (read_flag("q") || read_flag("emit-relocs")) {
Expand Down Expand Up @@ -1235,7 +1241,7 @@ std::vector<std::string> parse_nonpositional_args(Context<E> &ctx) {
// cannot be done right here.
remaining.push_back("--version-script=" + std::string(arg));
} else if (read_arg("dynamic-list")) {
ctx.arg.Bsymbolic = true;
ctx.arg.Bsymbolic = BSYMBOLIC_ALL;
append(ctx.dynamic_list_patterns, parse_dynamic_list(ctx, arg));
} else if (read_arg("export-dynamic-symbol")) {
ctx.dynamic_list_patterns.push_back({arg, "<command line>"});
Expand Down
11 changes: 9 additions & 2 deletions elf/mold.h
Original file line number Diff line number Diff line change
Expand Up @@ -1549,6 +1549,14 @@ typedef enum {
UNRESOLVED_IGNORE,
} UnresolvedKind;

typedef enum {
BSYMBOLIC_NONE,
BSYMBOLIC_ALL,
BSYMBOLIC_FUNCTIONS,
BSYMBOLIC_NON_WEAK,
BSYMBOLIC_NON_WEAK_FUNCTIONS,
} BsymbolicKind;

typedef enum {
SEPARATE_LOADABLE_SEGMENTS,
SEPARATE_CODE,
Expand Down Expand Up @@ -1652,8 +1660,7 @@ struct Context {
Symbol<E> *fini = nullptr;
Symbol<E> *init = nullptr;
UnresolvedKind unresolved_symbols = UNRESOLVED_ERROR;
bool Bsymbolic = false;
bool Bsymbolic_functions = false;
BsymbolicKind Bsymbolic = BSYMBOLIC_NONE;
bool allow_multiple_definition = false;
bool apply_dynamic_relocs = true;
bool color_diagnostics = false;
Expand Down
25 changes: 21 additions & 4 deletions elf/passes.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1899,6 +1899,26 @@ void compute_import_export(Context<E> &ctx) {
}
};

auto is_protected = [&](Symbol<E> &sym) {
if (sym.visibility == STV_PROTECTED)
return true;

switch (ctx.arg.Bsymbolic) {
case BSYMBOLIC_ALL:
return true;
case BSYMBOLIC_NONE:
return false;
case BSYMBOLIC_FUNCTIONS:
return sym.get_type() == STT_FUNC;
case BSYMBOLIC_NON_WEAK:
return !sym.is_weak;
case BSYMBOLIC_NON_WEAK_FUNCTIONS:
return !sym.is_weak && sym.get_type() == STT_FUNC;
default:
unreachable();
}
};

// Export symbols that are not hidden or marked as local.
// We also want to mark imported symbols as such.
tbb::parallel_for_each(ctx.objs, [&](ObjectFile<E> *file) {
Expand All @@ -1916,10 +1936,7 @@ void compute_import_export(Context<E> &ctx) {

// Exported symbols are marked as imported as well by default
// for DSOs.
if (ctx.arg.shared &&
sym->visibility != STV_PROTECTED &&
!ctx.arg.Bsymbolic &&
!(ctx.arg.Bsymbolic_functions && sym->get_type() == STT_FUNC))
if (ctx.arg.shared && !is_protected(*sym))
sym->is_imported = true;
}
}
Expand Down
42 changes: 42 additions & 0 deletions test/elf/bsymbolic-non-weak-functions.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#!/bin/bash
. $(dirname $0)/common.inc

cat <<EOF | $CC -c -o $t/a.o -fPIC -xc -
__attribute__((weak)) int foo = 4;
int bar = 4;
__attribute__((weak)) int baz = 4;
int get_foo1() { return foo; }
int get_bar1() { return bar; }
__attribute__((weak)) int get_baz1() { return baz; }
int get_foo2() { return get_foo1(); }
int get_bar2() { return get_bar1(); }
int get_baz2() { return get_baz1(); }
EOF

$CC -B. -shared -o $t/b.so $t/a.o -Wl,-Bsymbolic-non-weak-functions

cat <<EOF | $CC -c -o $t/c.o -xc -
#include <stdio.h>
int foo = 3;
int bar = 3;
int baz = 3;
int get_foo1() { return 7; }
int get_bar1() { return 7; }
int get_baz1() { return 7; }
int get_foo2();
int get_bar2();
int get_baz2();
int main() {
printf("%d %d %d %d %d %d\n", foo, bar, baz,
get_foo2(), get_bar2(), get_baz2());
}
EOF

$CC -B. -o $t/exe $t/c.o $t/b.so
$QEMU $t/exe | grep -q '^3 3 3 3 3 7$'
42 changes: 42 additions & 0 deletions test/elf/bsymbolic-non-weak.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#!/bin/bash
. $(dirname $0)/common.inc

cat <<EOF | $CC -c -o $t/a.o -fPIC -xc -
__attribute__((weak)) int foo = 4;
int bar = 4;
__attribute__((weak)) int baz = 4;
int get_foo1() { return foo; }
int get_bar1() { return bar; }
__attribute__((weak)) int get_baz1() { return baz; }
int get_foo2() { return get_foo1(); }
int get_bar2() { return get_bar1(); }
int get_baz2() { return get_baz1(); }
EOF

$CC -B. -shared -o $t/b.so $t/a.o -Wl,-Bsymbolic-non-weak

cat <<EOF | $CC -c -o $t/c.o -xc -
#include <stdio.h>
int foo = 3;
int bar = 3;
int baz = 3;
int get_foo1() { return 7; }
int get_bar1() { return 7; }
int get_baz1() { return 7; }
int get_foo2();
int get_bar2();
int get_baz2();
int main() {
printf("%d %d %d %d %d %d\n", foo, bar, baz,
get_foo2(), get_bar2(), get_baz2());
}
EOF

$CC -B. -o $t/exe $t/c.o $t/b.so
$QEMU $t/exe | grep -q '^3 3 3 3 4 7$'

0 comments on commit 7d17aa8

Please sign in to comment.