From f9ecf89b16029d3eaf4ca364f75680e5c74e20fe Mon Sep 17 00:00:00 2001 From: Rui Ueyama Date: Thu, 25 Feb 2021 20:26:10 +0900 Subject: [PATCH] wip --- main.cc | 10 ++++++++++ mold.h | 3 ++- object_file.cc | 18 ++++++++++++++++++ test/shared.sh | 20 ++++++++++++++++++++ 4 files changed, 50 insertions(+), 1 deletion(-) create mode 100755 test/shared.sh diff --git a/main.cc b/main.cc index b8d21737..01500883 100644 --- a/main.cc +++ b/main.cc @@ -1287,6 +1287,16 @@ int main(int argc, char **argv) { }); } + // If we are linking a .so file, remaining undefined symbols does + // not cause a linker error. Instead, they are treated as if they + // were imported symbols. + if (config.shared) { + Timer t("claim_unresolved_symbols"); + tbb::parallel_for_each(out::objs, [](ObjectFile *file) { + file->claim_unresolved_symbols(); + }); + } + // Beyond this point, no new symbols will be added to the result. // Make sure that all symbols have been resolved. diff --git a/mold.h b/mold.h index 1154c9bd..15c2fe0d 100644 --- a/mold.h +++ b/mold.h @@ -925,6 +925,7 @@ public: void handle_undefined_weak_symbols(); void resolve_comdat_groups(); void eliminate_duplicate_comdat_groups(); + void claim_unresolved_symbols(); void scan_relocations(); void convert_common_symbols(); void compute_symtab(); @@ -1230,7 +1231,7 @@ inline bool Symbol::is_absolute() const { } inline bool Symbol::is_imported() const { - return file->is_dso; + return file->is_dso || (esym && esym->is_undef() && esym->st_bind != STB_WEAK); } inline u64 Symbol::get_addr() const { diff --git a/object_file.cc b/object_file.cc index 7dc86363..880d9147 100644 --- a/object_file.cc +++ b/object_file.cc @@ -650,6 +650,24 @@ void ObjectFile::eliminate_duplicate_comdat_groups() { } } +void ObjectFile::claim_unresolved_symbols() { + if (!is_alive) + return; + + for (i64 i = first_global; i < symbols.size(); i++) { + const ElfSym &esym = elf_syms[i]; + Symbol &sym = *symbols[i]; + std::lock_guard lock(sym.mu); + + if (esym.is_undef() && (!sym.esym || sym.esym->is_undef())) { + if (sym.file && sym.file->priority < this->priority) + continue; + sym.file = this; + sym.esym = &esym; + } + } +} + void ObjectFile::scan_relocations() { // Scan relocations against seciton contents for (InputSection *isec : sections) diff --git a/test/shared.sh b/test/shared.sh new file mode 100755 index 00000000..339cac4f --- /dev/null +++ b/test/shared.sh @@ -0,0 +1,20 @@ +#!/bin/bash +set -e +echo -n "Testing $(basename -s .sh $0) ... " +t=$(pwd)/tmp/$(basename -s .sh $0) +mkdir -p $t + +cat < $t/log + +grep -q '0000000000000000 0 NOTYPE GLOBAL DEFAULT UND fn2' $t/log +grep -q '000000000000111c 0 NOTYPE GLOBAL DEFAULT 16 fn1' $t/log + +echo OK