diff --git a/CMakeLists.txt b/CMakeLists.txt index ae53f76b..1a1b6b02 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -346,6 +346,7 @@ target_sources(mold PRIVATE common/filepath.cc common/glob.cc common/hyperloglog.cc + common/malloc.cc common/multi-glob.cc common/perf.cc common/tar.cc @@ -362,6 +363,7 @@ target_sources(mold PRIVATE elf/arch-sh4.cc elf/arch-sparc64.cc elf/arch-x86-64.cc + elf/config.cc elf/elf.cc git-hash.cc third-party/rust-demangle/rust-demangle.c diff --git a/common/common.h b/common/common.h index af3477aa..0968e879 100644 --- a/common/common.h +++ b/common/common.h @@ -401,13 +401,11 @@ inline std::vector flatten(std::vector> &vec) { return ret; } -template -inline void sort(T &vec) { +inline void sort(auto &vec) { std::stable_sort(vec.begin(), vec.end()); } -template -inline void sort(T &vec, U less) { +inline void sort(auto &vec, auto less) { std::stable_sort(vec.begin(), vec.end(), less); } @@ -535,6 +533,9 @@ inline bool remove_prefix(std::string_view &s, std::string_view prefix) { // So you need to give a correct estimation of the final size before // using it. We use this hash map to uniquify pieces of data in // mergeable sections. +// +// We've implemented this ourselves because the performance of +// conrurent hash map is critical for our linker. template class ConcurrentMap { public: @@ -840,8 +841,7 @@ std::array get_uuid_v4(); // filepath.cc // -template -std::filesystem::path filepath(const T &path) { +std::filesystem::path filepath(const auto &path) { return {path, std::filesystem::path::format::generic_format}; } diff --git a/common/malloc.cc b/common/malloc.cc new file mode 100644 index 00000000..fc2f0afc --- /dev/null +++ b/common/malloc.cc @@ -0,0 +1,5 @@ +#include "config.h" + +#ifdef USE_SYSTEM_MIMALLOC +# include +#endif diff --git a/elf/config.cc b/elf/config.cc new file mode 100644 index 00000000..55db9603 --- /dev/null +++ b/elf/config.cc @@ -0,0 +1,13 @@ +#include "mold.h" +#include "config.h" + +namespace mold::elf { + +std::string get_mold_version() { + if (mold_git_hash.empty()) + return "mold "s + MOLD_VERSION + " (compatible with GNU ld)"; + return "mold "s + MOLD_VERSION + " (" + mold_git_hash + + "; compatible with GNU ld)"; +} + +} // namespace mold::elf diff --git a/elf/elf.cc b/elf/elf.cc index ab5fa5cc..2ce2ec47 100644 --- a/elf/elf.cc +++ b/elf/elf.cc @@ -1,15 +1,7 @@ #include "mold.h" -#include "config.h" namespace mold::elf { -std::string get_mold_version() { - if (mold_git_hash.empty()) - return "mold "s + MOLD_VERSION + " (compatible with GNU ld)"; - return "mold "s + MOLD_VERSION + " (" + mold_git_hash + - "; compatible with GNU ld)"; -} - static std::string unknown_type(u32 r_type) { char buf[50]; snprintf(buf, sizeof(buf), "unknown (0x%x)", r_type); diff --git a/elf/input-files.cc b/elf/input-files.cc index 68a5e8b1..d1f71c3d 100644 --- a/elf/input-files.cc +++ b/elf/input-files.cc @@ -98,22 +98,6 @@ ElfShdr *InputFile::find_section(i64 type) { return nullptr; } -template -void InputFile::clear_symbols() { - for (Symbol *sym : get_global_syms()) { - if (__atomic_load_n(&sym->file, __ATOMIC_ACQUIRE) == this) { - sym->origin = 0; - sym->value = -1; - sym->sym_idx = -1; - sym->ver_idx = VER_NDX_UNSPECIFIED; - sym->is_weak = false; - sym->is_imported = false; - sym->is_exported = false; - __atomic_store_n(&sym->file, nullptr, __ATOMIC_RELEASE); - } - } -} - // Find the source filename. It should be listed in symtab as STT_FILE. template std::string_view InputFile::get_source_name() const { @@ -1512,7 +1496,7 @@ std::span *> SharedFile::find_aliases(Symbol *sym) { return x->esym().st_value < y->esym().st_value; }); - return {&*begin, &*end}; + return {&*begin, (size_t)(end - begin)}; } // Infer an alignment of a DSO symbol. An alignment of a symbol in other diff --git a/elf/main.cc b/elf/main.cc index e0793521..68060f3a 100644 --- a/elf/main.cc +++ b/elf/main.cc @@ -21,8 +21,10 @@ # include #endif -#if defined(USE_SYSTEM_MIMALLOC) && defined(MOLD_X86_64) -# include +#ifdef MOLD_X86_64 +int main(int argc, char **argv) { + return mold::elf::elf_main(argc, argv); +} #endif namespace mold::elf { @@ -718,9 +720,3 @@ using E = MOLD_TARGET; template int elf_main(int, char **); } // namespace mold::elf - -#ifdef MOLD_X86_64 -int main(int argc, char **argv) { - return mold::elf::elf_main(argc, argv); -} -#endif diff --git a/elf/mapfile.cc b/elf/mapfile.cc index 1a894f52..c5805581 100644 --- a/elf/mapfile.cc +++ b/elf/mapfile.cc @@ -54,6 +54,8 @@ static Map get_map(Context &ctx) { template void print_map(Context &ctx) { + Timer t(ctx, "print_map"); + std::ostream *out = &std::cout; std::unique_ptr file; diff --git a/elf/mold.h b/elf/mold.h index d3039771..3046b4d9 100644 --- a/elf/mold.h +++ b/elf/mold.h @@ -1100,7 +1100,6 @@ public: ElfShdr *find_section(i64 type); virtual void resolve_symbols(Context &ctx) = 0; - void clear_symbols(); virtual void mark_live_objects(Context &ctx, @@ -2043,7 +2042,7 @@ public: // A symbol is owned by a file. If two or more files define the // same symbol, the one with the strongest definition owns the symbol. - // If `file` is null, the symbol is equivalent to nonexistent. + // If `file` is null, the symbol is not defined by any input file. InputFile *file = nullptr; // A symbol usually belongs to an input section, but it can belong diff --git a/elf/output-chunks.cc b/elf/output-chunks.cc index b36cc8c2..0a22fd9a 100644 --- a/elf/output-chunks.cc +++ b/elf/output-chunks.cc @@ -971,7 +971,7 @@ void OutputSection::construct_relr(Context &ctx) { return; for (const ElfRel &r : isec.get_rels(ctx)) - if (r.r_type == E::R_ABS && (r.r_offset % sizeof(Word)) == 0) + if (r.r_type == E::R_ABS && r.r_offset % sizeof(Word) == 0) if (Symbol &sym = *isec.file.symbols[r.r_sym]; !sym.is_absolute() && !sym.is_imported) shards[i].push_back(isec.offset + r.r_offset); @@ -2337,8 +2337,8 @@ void CopyrelSection::copy_buf(Context &ctx) { this->reldyn_offset); for (Symbol *sym : symbols) - *rel++ = ElfRel(sym->get_addr(ctx), E::R_COPY, sym->get_dynsym_idx(ctx), - 0); + *rel++ = ElfRel(sym->get_addr(ctx), E::R_COPY, + sym->get_dynsym_idx(ctx), 0); } template diff --git a/elf/passes.cc b/elf/passes.cc index 86e06594..75ae7242 100644 --- a/elf/passes.cc +++ b/elf/passes.cc @@ -229,6 +229,28 @@ static void mark_live_objects(Context &ctx) { }); } +template +static void clear_symbols(Context &ctx) { + std::vector *> files; + append(files, ctx.objs); + append(files, ctx.dsos); + + tbb::parallel_for_each(files, [](InputFile *file) { + for (Symbol *sym : file->get_global_syms()) { + if (__atomic_load_n(&sym->file, __ATOMIC_ACQUIRE) == file) { + sym->origin = 0; + sym->value = -1; + sym->sym_idx = -1; + sym->ver_idx = VER_NDX_UNSPECIFIED; + sym->is_weak = false; + sym->is_imported = false; + sym->is_exported = false; + __atomic_store_n(&sym->file, nullptr, __ATOMIC_RELEASE); + } + } + }); +} + template void do_resolve_symbols(Context &ctx) { std::vector *> files; @@ -269,9 +291,7 @@ void do_resolve_symbols(Context &ctx) { // Cleanup. The rule used for archive extraction isn't accurate for the // general case of symbol extraction, so reset the resolution to be redone // later. - tbb::parallel_for_each(files, [&](InputFile *file) { - file->clear_symbols(); - }); + clear_symbols(ctx); // Now that the symbol references are gone, remove the eliminated files from // the file list. @@ -349,13 +369,7 @@ void resolve_symbols(Context &ctx) { append(ctx.objs, lto_objs); // Redo name resolution from scratch. - tbb::parallel_for_each(ctx.objs, [&](ObjectFile *file) { - file->clear_symbols(); - }); - - tbb::parallel_for_each(ctx.dsos, [&](SharedFile *file) { - file->clear_symbols(); - }); + clear_symbols(ctx); // Remove IR object files. for (ObjectFile *file : ctx.objs) @@ -864,8 +878,8 @@ void add_synthetic_symbols(Context &ctx) { } if constexpr (is_ppc64v2) - for (auto [label, insn] : ppc64_save_restore_insns) - if (!label.empty()) + for (std::pair p : ppc64_save_restore_insns) + if (std::string_view label = p.first; !label.empty()) add(label); obj.elf_syms = ctx.internal_esyms; @@ -2855,7 +2869,8 @@ void fix_synthetic_symbols(Context &ctx) { // PPC64's _{save,rest}gpr{0,1}_{14,15,16,...,31} symbols if constexpr (is_ppc64v2) { i64 offset = 0; - for (auto [label, insn] : ppc64_save_restore_insns) { + for (std::pair p : ppc64_save_restore_insns) { + std::string_view label = p.first; if (!label.empty()) if (Symbol *sym = get_symbol(ctx, label); sym->file == ctx.internal_obj) diff --git a/test/elf/aarch64_variant-pcs.sh b/test/elf/aarch64_variant-pcs.sh index 6b5e4e8a..12361b79 100755 --- a/test/elf/aarch64_variant-pcs.sh +++ b/test/elf/aarch64_variant-pcs.sh @@ -1,8 +1,6 @@ #!/bin/bash . $(dirname $0)/common.inc -[ $MACHINE = aarch64 ] || skip - cat < /dev/null || skip .global foo .type foo, %function diff --git a/test/elf/arm_range-extension-thunk-disassembly.sh b/test/elf/arm_range-extension-thunk-disassembly.sh index 9f3dcc59..b1f28d79 100755 --- a/test/elf/arm_range-extension-thunk-disassembly.sh +++ b/test/elf/arm_range-extension-thunk-disassembly.sh @@ -1,8 +1,6 @@ #!/bin/bash . $(dirname $0)/common.inc -[ $MACHINE = arm ] || skip - cat < diff --git a/test/elf/arm_range-extension-thunk.sh b/test/elf/arm_range-extension-thunk.sh index ddf01313..191b1c51 100755 --- a/test/elf/arm_range-extension-thunk.sh +++ b/test/elf/arm_range-extension-thunk.sh @@ -1,8 +1,6 @@ #!/bin/bash . $(dirname $0)/common.inc -[ $MACHINE = arm ] || skip - echo 'int main() {}' | $CC -c -o /dev/null -xc - -O0 -mthumb >& /dev/null \ || skip diff --git a/test/elf/arm_thumb-interwork.sh b/test/elf/arm_thumb-interwork.sh index baf8e04e..aed7b236 100755 --- a/test/elf/arm_thumb-interwork.sh +++ b/test/elf/arm_thumb-interwork.sh @@ -1,8 +1,6 @@ #!/bin/bash . $(dirname $0)/common.inc -[[ $MACHINE == arm* ]] || skip - echo 'int foo() { return 0; }' | $CC -o /dev/null -c -xc - -mthumb 2> /dev/null || skip cat <& /dev/null \ diff --git a/test/elf/i686_tls-module-base.sh b/test/elf/i686_tls-module-base.sh index f0bc4fea..2e906ca7 100755 --- a/test/elf/i686_tls-module-base.sh +++ b/test/elf/i686_tls-module-base.sh @@ -1,8 +1,6 @@ #!/bin/bash . $(dirname $0)/common.inc -[ $MACHINE = i686 ] || skip - cat <<'EOF' | $CC -fPIC -o $t/a.o -c -xassembler - .globl get_foo .type get_foo, @function diff --git a/test/elf/riscv64_norvc.sh b/test/elf/riscv64_norvc.sh index c679f64b..1383d4e0 100755 --- a/test/elf/riscv64_norvc.sh +++ b/test/elf/riscv64_norvc.sh @@ -1,8 +1,6 @@ #!/bin/bash . $(dirname $0)/common.inc -[ $MACHINE = riscv64 -o $MACHINE = riscv32 ] || skip - # Disable C extension if [ $MACHINE = riscv32 ]; then ISA=rv32g diff --git a/test/elf/riscv64_relax-got.sh b/test/elf/riscv64_relax-got.sh index 0acc11a6..14e33355 100755 --- a/test/elf/riscv64_relax-got.sh +++ b/test/elf/riscv64_relax-got.sh @@ -1,8 +1,6 @@ #!/bin/bash . $(dirname $0)/common.inc -[[ $MACHINE = riscv* ]] || skip - cat <