diff options
author | Sam James <sam@gentoo.org> | 2023-11-13 02:10:14 +0000 |
---|---|---|
committer | Sam James <sam@gentoo.org> | 2023-11-13 02:10:14 +0000 |
commit | 2fc10cbc98bebe136012849b28f6969327d6613b (patch) | |
tree | 3fba205d72c1746f5352a2c1e4d7bfe83b7668ec /sys-devel/mold | |
parent | sys-fs/erofs-utils: Keyword 1.7 arm64, #917253 (diff) | |
download | gentoo-2fc10cbc98bebe136012849b28f6969327d6613b.tar.gz gentoo-2fc10cbc98bebe136012849b28f6969327d6613b.tar.bz2 gentoo-2fc10cbc98bebe136012849b28f6969327d6613b.zip |
sys-devel/mold: backport symbol interposition fix (e.g. mimalloc/musl segfault)
Closes: https://bugs.gentoo.org/917089
Signed-off-by: Sam James <sam@gentoo.org>
Diffstat (limited to 'sys-devel/mold')
-rw-r--r-- | sys-devel/mold/files/mold-2.3.2-mimalloc-visibility-interposition.patch | 495 | ||||
-rw-r--r-- | sys-devel/mold/mold-2.3.2-r1.ebuild | 96 |
2 files changed, 591 insertions, 0 deletions
diff --git a/sys-devel/mold/files/mold-2.3.2-mimalloc-visibility-interposition.patch b/sys-devel/mold/files/mold-2.3.2-mimalloc-visibility-interposition.patch new file mode 100644 index 000000000000..e569bfaf3013 --- /dev/null +++ b/sys-devel/mold/files/mold-2.3.2-mimalloc-visibility-interposition.patch @@ -0,0 +1,495 @@ +https://bugs.gentoo.org/917089 +https://github.com/microsoft/mimalloc/issues/360 +https://github.com/rui314/mold/issues/1071 +https://github.com/rui314/mold/commit/da3f5dd4ecf4faaba466ba41c7c30ba4f8f73bfd + +From da3f5dd4ecf4faaba466ba41c7c30ba4f8f73bfd Mon Sep 17 00:00:00 2001 +From: Rui Ueyama <ruiu@cs.stanford.edu> +Date: Sat, 11 Nov 2023 17:59:54 +0900 +Subject: [PATCH] Fix --dynamic-list for DSOs + +--dynamic-list, --export-dynamic-symbol and --export-dynamic-symbol-list +have different semantics for executables and DSOs. If the output is an +executable, they specify a list of symbols that are to be exported. +If the output is a shared object, they specify the list of symbols that +are to be interposable. + +mold havne't implemented the latter semantics. This commit fixes that +issue. + +Fixes https://github.com/rui314/mold/issues/1071 +--- + elf/cmdline.cc | 25 +++----- + elf/linker-script.cc | 35 ++++++----- + elf/main.cc | 16 ----- + elf/mold.h | 17 +++-- + elf/output-chunks.cc | 8 ++- + elf/passes.cc | 122 +++++++++++++++++++++++++++++------- + test/elf/dynamic-list4.sh | 44 +++++++++++++ + test/elf/version-script6.sh | 4 +- + 8 files changed, 194 insertions(+), 77 deletions(-) + create mode 100755 test/elf/dynamic-list4.sh + +diff --git a/elf/cmdline.cc b/elf/cmdline.cc +index 6bc13a300..6c06b4b14 100644 +--- a/elf/cmdline.cc ++++ b/elf/cmdline.cc +@@ -1104,21 +1104,21 @@ std::vector<std::string> parse_nonpositional_args(Context<E> &ctx) { + } else if (read_flag("no-keep-memory")) { + } else if (read_arg("max-cache-size")) { + } else if (read_arg("version-script")) { +- // --version-script, --dynamic-list and --export-dynamic-symbol[-list] +- // are treated as positional arguments even though they are actually not +- // positional. This is because linker scripts (a positional argument) +- // can also specify a version script, and it's better to consolidate +- // parsing in read_input_files. In particular, version scripts can +- // modify ctx.default_version which we initialize *after* parsing +- // non-positional args, so the parsing cannot be done right here. ++ // --version-script is treated as positional arguments even though ++ // they are actually not positional. This is because linker scripts ++ // (a positional argument) can also specify a version script, and ++ // it's better to consolidate parsing in read_input_files. In ++ // particular, version scripts can modify ctx.default_version which ++ // we initialize *after* parsing non-positional args, so the parsing ++ // cannot be done right here. + remaining.push_back("--version-script=" + std::string(arg)); + } else if (read_arg("dynamic-list")) { + ctx.arg.Bsymbolic = true; +- remaining.push_back("--dynamic-list=" + std::string(arg)); ++ append(ctx.dynamic_list_patterns, parse_dynamic_list(ctx, arg)); + } else if (read_arg("export-dynamic-symbol")) { +- remaining.push_back("--export-dynamic-symbol=" + std::string(arg)); ++ ctx.dynamic_list_patterns.push_back({arg, "<command line>"}); + } else if (read_arg("export-dynamic-symbol-list")) { +- remaining.push_back("--export-dynamic-symbol-list=" + std::string(arg)); ++ append(ctx.dynamic_list_patterns, parse_dynamic_list(ctx, arg)); + } else if (read_flag("as-needed")) { + remaining.push_back("--as-needed"); + } else if (read_flag("no-as-needed")) { +@@ -1228,11 +1228,6 @@ std::vector<std::string> parse_nonpositional_args(Context<E> &ctx) { + if (char *env = getenv("MOLD_REPRO"); env && env[0]) + ctx.arg.repro = true; + +- if (ctx.arg.shared || ctx.arg.export_dynamic) +- ctx.default_version = VER_NDX_GLOBAL; +- else +- ctx.default_version = VER_NDX_LOCAL; +- + if (ctx.arg.default_symver) { + std::string ver = ctx.arg.soname.empty() ? + filepath(ctx.arg.output).filename().string() : std::string(ctx.arg.soname); +diff --git a/elf/linker-script.cc b/elf/linker-script.cc +index 4bdc19e7c..7ad500bb8 100644 +--- a/elf/linker-script.cc ++++ b/elf/linker-script.cc +@@ -312,7 +312,6 @@ read_version_script_commands(Context<E> &ctx, std::span<std::string_view> &tok, + + if (tok[0] == "*") { + ctx.default_version = (is_global ? ver_idx : (u32)VER_NDX_LOCAL); +- ctx.default_version_from_version_script = true; + } else if (is_global) { + ctx.version_patterns.push_back({unquote(tok[0]), current_file<E>->name, + ver_str, ver_idx, is_cpp}); +@@ -367,7 +366,9 @@ void parse_version_script(Context<E> &ctx, MappedFile<Context<E>> *mf) { + } + + template <typename E> +-void read_dynamic_list_commands(Context<E> &ctx, std::span<std::string_view> &tok, ++void read_dynamic_list_commands(Context<E> &ctx, ++ std::vector<DynamicPattern> &result, ++ std::span<std::string_view> &tok, + bool is_cpp) { + while (!tok.empty() && tok[0] != "}") { + if (tok[0] == "extern") { +@@ -376,11 +377,11 @@ void read_dynamic_list_commands(Context<E> &ctx, std::span<std::string_view> &to + if (!tok.empty() && tok[0] == "\"C\"") { + tok = tok.subspan(1); + tok = skip(ctx, tok, "{"); +- read_dynamic_list_commands(ctx, tok, false); ++ read_dynamic_list_commands(ctx, result, tok, false); + } else { + tok = skip(ctx, tok, "\"C++\""); + tok = skip(ctx, tok, "{"); +- read_dynamic_list_commands(ctx, tok, true); ++ read_dynamic_list_commands(ctx, result, tok, true); + } + + tok = skip(ctx, tok, "}"); +@@ -388,29 +389,32 @@ void read_dynamic_list_commands(Context<E> &ctx, std::span<std::string_view> &to + continue; + } + +- if (tok[0] == "*") +- ctx.default_version = VER_NDX_GLOBAL; +- else +- ctx.version_patterns.push_back({unquote(tok[0]), current_file<E>->name, +- "global", VER_NDX_GLOBAL, is_cpp}); +- ++ result.push_back({unquote(tok[0]), "", is_cpp}); + tok = skip(ctx, tok.subspan(1), ";"); + } + } + + template <typename E> +-void parse_dynamic_list(Context<E> &ctx, MappedFile<Context<E>> *mf) { +- current_file<E> = mf; +- std::vector<std::string_view> vec = tokenize(ctx, mf->get_contents()); ++std::vector<DynamicPattern> ++parse_dynamic_list(Context<E> &ctx, std::string_view path) { ++ std::string_view contents = ++ MappedFile<Context<E>>::must_open(ctx, std::string(path))->get_contents(); ++ std::vector<std::string_view> vec = tokenize(ctx, contents); + std::span<std::string_view> tok = vec; ++ std::vector<DynamicPattern> result; + + tok = skip(ctx, tok, "{"); +- read_dynamic_list_commands(ctx, tok, false); ++ read_dynamic_list_commands(ctx, result, tok, false); + tok = skip(ctx, tok, "}"); + tok = skip(ctx, tok, ";"); + + if (!tok.empty()) + SyntaxError(ctx, tok[0]) << "trailing garbage token"; ++ ++ for (DynamicPattern &p : result) ++ p.source = path; ++ ++ return result; + } + + using E = MOLD_TARGET; +@@ -418,6 +422,7 @@ using E = MOLD_TARGET; + template void parse_linker_script(Context<E> &, MappedFile<Context<E>> *); + template std::string_view get_script_output_type(Context<E> &, MappedFile<Context<E>> *); + template void parse_version_script(Context<E> &, MappedFile<Context<E>> *); +-template void parse_dynamic_list(Context<E> &, MappedFile<Context<E>> *); ++template std::vector<DynamicPattern> parse_dynamic_list(Context<E> &, std::string_view); ++ + + } // namespace mold::elf +diff --git a/elf/main.cc b/elf/main.cc +index c4f3cd6ff..6df00cfe9 100644 +--- a/elf/main.cc ++++ b/elf/main.cc +@@ -299,22 +299,6 @@ static void read_input_files(Context<E> &ctx, std::span<std::string> args) { + if (!mf) + Fatal(ctx) << "--version-script: file not found: " << arg; + parse_version_script(ctx, mf); +- } else if (remove_prefix(arg, "--dynamic-list=")) { +- MappedFile<Context<E>> *mf = find_from_search_paths(ctx, std::string(arg)); +- if (!mf) +- Fatal(ctx) << "--dynamic-list: file not found: " << arg; +- parse_dynamic_list(ctx, mf); +- } else if (remove_prefix(arg, "--export-dynamic-symbol=")) { +- if (arg == "*") +- ctx.default_version = VER_NDX_GLOBAL; +- else +- ctx.version_patterns.push_back({arg, "--export-dynamic-symbol", +- "global", VER_NDX_GLOBAL, false}); +- } else if (remove_prefix(arg, "--export-dynamic-symbol-list=")) { +- MappedFile<Context<E>> *mf = find_from_search_paths(ctx, std::string(arg)); +- if (!mf) +- Fatal(ctx) << "--export-dynamic-symbol-list: file not found: " << arg; +- parse_dynamic_list(ctx, mf); + } else if (arg == "--push-state") { + state.push_back({ctx.as_needed, ctx.whole_archive, ctx.is_static, + ctx.in_lib}); +diff --git a/elf/mold.h b/elf/mold.h +index 7ff7c2e6f..d593f6840 100644 +--- a/elf/mold.h ++++ b/elf/mold.h +@@ -1281,8 +1281,15 @@ get_script_output_type(Context<E> &ctx, MappedFile<Context<E>> *mf); + template <typename E> + void parse_version_script(Context<E> &ctx, MappedFile<Context<E>> *mf); + ++struct DynamicPattern { ++ std::string_view pattern; ++ std::string_view source; ++ bool is_cpp = false; ++}; ++ + template <typename E> +-void parse_dynamic_list(Context<E> &ctx, MappedFile<Context<E>> *mf); ++std::vector<DynamicPattern> ++parse_dynamic_list(Context<E> &ctx, std::string_view path); + + // + // lto.cc +@@ -1733,13 +1740,11 @@ struct Context { + } arg; + + std::vector<VersionPattern> version_patterns; +- u16 default_version = VER_NDX_GLOBAL; ++ std::vector<DynamicPattern> dynamic_list_patterns; ++ i64 default_version = -1; + i64 page_size = E::page_size; + std::optional<int> global_lock_fd; + +- // true if default_version is set by a wildcard in version script. +- bool default_version_from_version_script = false; +- + // Reader context + bool as_needed = false; + bool whole_archive = false; +@@ -2034,7 +2039,7 @@ class Symbol { + i32 sym_idx = -1; + + i32 aux_idx = -1; +- u16 ver_idx = 0; ++ i32 ver_idx = -1; + + // `flags` has NEEDS_ flags. + Atomic<u8> flags = 0; +diff --git a/elf/output-chunks.cc b/elf/output-chunks.cc +index f44d448ac..00d5538df 100644 +--- a/elf/output-chunks.cc ++++ b/elf/output-chunks.cc +@@ -2550,8 +2550,12 @@ void VerdefSection<E>::construct(Context<E> &ctx) { + for (std::string_view verstr : ctx.arg.version_definitions) + write(verstr, idx++, 0); + +- for (Symbol<E> *sym : std::span<Symbol<E> *>(ctx.dynsym->symbols).subspan(1)) +- ctx.versym->contents[sym->get_dynsym_idx(ctx)] = sym->ver_idx; ++ for (Symbol<E> *sym : std::span<Symbol<E> *>(ctx.dynsym->symbols).subspan(1)) { ++ i64 ver = sym->ver_idx; ++ if (ver == -1) ++ ver = VER_NDX_GLOBAL; ++ ctx.versym->contents[sym->get_dynsym_idx(ctx)] = ver; ++ } + } + + template <typename E> +diff --git a/elf/passes.cc b/elf/passes.cc +index c6ee0f66b..8c7d5d0f5 100644 +--- a/elf/passes.cc ++++ b/elf/passes.cc +@@ -1612,9 +1612,6 @@ template <typename E> + void apply_version_script(Context<E> &ctx) { + Timer t(ctx, "apply_version_script"); + +- // If all patterns are simple (i.e. not containing any meta- +- // characters and is not a C++ name), we can simply look up +- // symbols. + auto is_simple = [&] { + for (VersionPattern &v : ctx.version_patterns) + if (v.is_cpp || v.pattern.find_first_of("*?[") != v.pattern.npos) +@@ -1622,6 +1619,9 @@ void apply_version_script(Context<E> &ctx) { + return true; + }; + ++ // If all patterns are simple (i.e. not containing any meta- ++ // characters and is not a C++ name), we can simply look up ++ // symbols. + if (is_simple()) { + for (VersionPattern &v : ctx.version_patterns) { + Symbol<E> *sym = get_symbol(ctx, v.pattern); +@@ -1747,44 +1747,124 @@ void compute_import_export(Context<E> &ctx) { + if (!ctx.arg.shared) { + tbb::parallel_for_each(ctx.dsos, [&](SharedFile<E> *file) { + for (Symbol<E> *sym : file->symbols) { +- if (sym->file && !sym->file->is_dso && sym->visibility != STV_HIDDEN) { +- if (sym->ver_idx != VER_NDX_LOCAL || +- !ctx.default_version_from_version_script) { +- std::scoped_lock lock(sym->mu); +- sym->is_exported = true; +- } ++ if (sym->file && !sym->file->is_dso && sym->visibility != STV_HIDDEN && ++ sym->ver_idx != VER_NDX_LOCAL) { ++ std::scoped_lock lock(sym->mu); ++ sym->is_exported = true; + } + } + }); + } + ++ auto should_export = [&](Symbol<E> &sym) { ++ if (sym.visibility == STV_HIDDEN) ++ return false; ++ ++ switch (sym.ver_idx) { ++ case -1: ++ if (ctx.arg.shared) ++ return !((ObjectFile<E> *)sym.file)->exclude_libs; ++ return ctx.arg.export_dynamic; ++ case VER_NDX_LOCAL: ++ return false; ++ default: ++ return true; ++ } ++ }; ++ + // 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) { + for (Symbol<E> *sym : file->get_global_syms()) { +- if (!sym->file || sym->visibility == STV_HIDDEN || +- sym->ver_idx == VER_NDX_LOCAL) +- continue; +- +- // If we are using a symbol in a DSO, we need to import it at runtime. +- if (sym->file != file && sym->file->is_dso && !sym->is_absolute()) { +- std::scoped_lock lock(sym->mu); +- sym->is_imported = true; ++ // If we are using a symbol in a DSO, we need to import it. ++ if (sym->file && sym->file->is_dso) { ++ if (!sym->is_absolute()) { ++ std::scoped_lock lock(sym->mu); ++ sym->is_imported = true; ++ } + continue; + } + +- // If we are creating a DSO, all global symbols are exported by default. +- if (sym->file == file) { +- std::scoped_lock lock(sym->mu); ++ // If we have a definition of a symbol, we may want to export it. ++ if (sym->file == file && should_export(*sym)) { + sym->is_exported = true; + +- if (ctx.arg.shared && sym->visibility != STV_PROTECTED && ++ // 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)) + sym->is_imported = true; + } + } + }); ++ ++ ++ // Apply --dynamic-list, --export-dynamic-symbol and ++ // --export-dynamic-symbol-list options. ++ // ++ // The semantics of these options vary depending on whether we are ++ // creating an executalbe or a shared object. ++ // ++ // For executable, matched symbols are exported. ++ // ++ // For shared objects, matched symbols are imported if it is already ++ // exported so that they are interposable. In other words, symbols ++ // that did not match will be bound locally within the output file, ++ // effectively turning them into protected symbols. ++ MultiGlob matcher; ++ MultiGlob cpp_matcher; ++ ++ auto handle_match = [&](Symbol<E> *sym) { ++ if (ctx.arg.shared) { ++ if (sym->is_exported) ++ sym->is_imported = true; ++ } else { ++ if (sym->file && !sym->file->is_dso && sym->visibility != STV_HIDDEN) ++ sym->is_exported = true; ++ } ++ }; ++ ++ for (DynamicPattern &p : ctx.dynamic_list_patterns) { ++ if (p.is_cpp) { ++ if (!cpp_matcher.add(p.pattern, 1)) ++ Fatal(ctx) << p.source << ": invalid dynamic list entry: " ++ << p.pattern; ++ continue; ++ } ++ ++ if (p.pattern.find_first_of("*?[") != p.pattern.npos) { ++ if (!matcher.add(p.pattern, 1)) ++ Fatal(ctx) << p.source << ": invalid dynamic list entry: " ++ << p.pattern; ++ continue; ++ } ++ ++ handle_match(get_symbol(ctx, p.pattern)); ++ } ++ ++ if (!matcher.empty() || !cpp_matcher.empty()) { ++ tbb::parallel_for_each(ctx.objs, [&](ObjectFile<E> *file) { ++ for (Symbol<E> *sym : file->get_global_syms()) { ++ if (sym->file != file) ++ continue; ++ if (ctx.arg.shared && !sym->is_exported) ++ continue; ++ ++ std::string_view name = sym->name(); ++ ++ if (matcher.find(name)) { ++ handle_match(sym); ++ } else if (!cpp_matcher.empty()) { ++ if (std::optional<std::string_view> s = cpp_demangle(name)) ++ name = *s; ++ if (cpp_matcher.find(name)) ++ handle_match(sym); ++ } ++ } ++ }); ++ } + } + + // Compute the "address-taken" bit for each input section. +diff --git a/test/elf/dynamic-list4.sh b/test/elf/dynamic-list4.sh +new file mode 100755 +index 000000000..83d88887e +--- /dev/null ++++ b/test/elf/dynamic-list4.sh +@@ -0,0 +1,44 @@ ++#!/bin/bash ++. $(dirname $0)/common.inc ++ ++cat <<EOF | $CC -o $t/a.o -c -xc - -fPIC ++#include <stdio.h> ++ ++void foo() { printf("foo1 "); } ++void bar() { printf("bar1 "); } ++void baz() { printf("baz1 "); } ++ ++void print() { ++ foo(); ++ bar(); ++ baz(); ++ printf("\n"); ++} ++EOF ++ ++cat <<EOF > $t/dyn ++{ foo; bar; }; ++EOF ++ ++$CC -B. -shared -o $t/b.so $t/a.o -Wl,--dynamic-list=$t/dyn ++ ++cat <<EOF | $CC -o $t/c.o -c -xc - -fPIC ++#include <stdio.h> ++void foo() { printf("foo2 "); } ++void bar() { printf("bar2 "); } ++void baz() { printf("baz2 "); } ++EOF ++ ++$CC -B. -shared -o $t/d.so $t/c.o ++ ++cat <<EOF | $CC -o $t/e.o -c -xc - ++#include <stdio.h> ++void print(); ++int main() { print(); } ++EOF ++ ++$CC -B. -o $t/exe1 $t/e.o -Wl,-push-state,-no-as-needed $t/b.so -Wl,-pop-state ++$QEMU $t/exe1 | grep -q 'foo1 bar1 baz1' ++ ++$CC -B. -o $t/exe2 $t/e.o -Wl,-push-state,-no-as-needed $t/d.so $t/b.so -Wl,-pop-state ++$QEMU $t/exe2 | grep -q 'foo2 bar2 baz1' +diff --git a/test/elf/version-script6.sh b/test/elf/version-script6.sh +index 74e2f9a89..44f809ef3 100755 +--- a/test/elf/version-script6.sh ++++ b/test/elf/version-script6.sh +@@ -9,10 +9,10 @@ EOF + cat <<EOF | $CXX -fPIC -c -o $t/b.o -xc - + int foo = 5; + int bar = 6; ++int quux = 100; + EOF + +-$CC -B. -shared -Wl,--version-script=$t/a.ver \ +- -o $t/c.so $t/b.o ++$CC -B. -shared -Wl,--version-script=$t/a.ver -o $t/c.so $t/b.o + + cat <<'EOF' > $t/d.ver + VER_Y1 { local; *; }; diff --git a/sys-devel/mold/mold-2.3.2-r1.ebuild b/sys-devel/mold/mold-2.3.2-r1.ebuild new file mode 100644 index 000000000000..26a184843d8c --- /dev/null +++ b/sys-devel/mold/mold-2.3.2-r1.ebuild @@ -0,0 +1,96 @@ +# Copyright 2021-2023 Gentoo Authors +# Distributed under the terms of the GNU General Public License v2 + +EAPI=8 + +inherit cmake toolchain-funcs + +DESCRIPTION="A Modern Linker" +HOMEPAGE="https://github.com/rui314/mold" +if [[ ${PV} == 9999 ]] ; then + EGIT_REPO_URI="https://github.com/rui314/mold.git" + inherit git-r3 +else + SRC_URI="https://github.com/rui314/mold/archive/refs/tags/v${PV}.tar.gz -> ${P}.tar.gz" + KEYWORDS="~amd64 ~arm64 ~loong ~riscv ~x86" +fi + +# mold (MIT) +# - xxhash (BSD-2) +LICENSE="MIT BSD-2" +SLOT="0" + +RDEPEND=" + app-arch/zstd:= + >=dev-cpp/tbb-2021.7.0-r1:= + dev-libs/blake3:= + sys-libs/zlib + !kernel_Darwin? ( + >=dev-libs/mimalloc-2:= + ) +" +DEPEND="${RDEPEND}" + +PATCHES=( + "${FILESDIR}"/${PN}-2.3.0-no-pch.patch + "${FILESDIR}"/${P}-mimalloc-visibility-interposition.patch +) + +pkg_pretend() { + # Requires a c++20 compiler, see #831473 + if [[ ${MERGE_TYPE} != binary ]]; then + if tc-is-gcc && [[ $(gcc-major-version) -lt 10 ]]; then + die "${PN} needs at least gcc 10" + elif tc-is-clang && [[ $(clang-major-version) -lt 12 ]]; then + die "${PN} needs at least clang 12" + fi + fi +} + +src_prepare() { + cmake_src_prepare + + # Needs unpackaged dwarfdump + rm test/elf/{{dead,compress}-debug-sections,compressed-debug-info}.sh || die + + # Heavy tests, need qemu + rm test/elf/gdb-index-{compress-output,dwarf{2,3,4,5}}.sh || die + rm test/elf/lto-{archive,dso,gcc,llvm,version-script}.sh || die + + # Sandbox sadness + rm test/elf/run.sh || die + sed -i 's|`pwd`/mold-wrapper.so|"& ${LD_PRELOAD}"|' \ + test/elf/mold-wrapper{,2}.sh || die + + # static-pie tests require glibc built with static-pie support + if ! has_version -d 'sys-libs/glibc[static-pie(+)]'; then + rm test/elf/{,ifunc-}static-pie.sh || die + fi +} + +src_configure() { + local mycmakeargs=( + -DCMAKE_DISABLE_PRECOMPILE_HEADERS=ON + -DMOLD_ENABLE_QEMU_TESTS=OFF + -DMOLD_LTO=OFF # Should be up to the user to decide this with CXXFLAGS. + -DMOLD_USE_MIMALLOC=$(usex !kernel_Darwin) + -DMOLD_USE_SYSTEM_MIMALLOC=ON + -DMOLD_USE_SYSTEM_TBB=ON + ) + cmake_src_configure +} + +src_install() { + dobin "${BUILD_DIR}"/${PN} + + # https://bugs.gentoo.org/872773 + insinto /usr/$(get_libdir)/mold + doins "${BUILD_DIR}"/${PN}-wrapper.so + + dodoc docs/{design,execstack}.md + doman docs/${PN}.1 + + dosym ${PN} /usr/bin/ld.${PN} + dosym ${PN} /usr/bin/ld64.${PN} + dosym ../../../usr/bin/${PN} /usr/libexec/${PN}/ld +} |