diff --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp --- a/lld/MachO/Driver.cpp +++ b/lld/MachO/Driver.cpp @@ -235,6 +235,8 @@ return v; } +static DenseMap loadedArchives; + static InputFile *addFile(StringRef path, bool forceLoadArchive, bool isExplicit = true, bool isBundleLoader = false) { @@ -247,6 +249,13 @@ file_magic magic = identify_magic(mbref.getBuffer()); switch (magic) { case file_magic::archive: { + // Avoid loading archives twice. If the archives are being force-loaded, + // loading them twice would create duplicate symbol errors. In the + // non-force-loading case, this is just a minor performance optimization. + ArchiveFile *&cachedFile = loadedArchives[path]; + if (cachedFile) + return cachedFile; + std::unique_ptr file = CHECK( object::Archive::create(mbref), path + ": failed to parse archive"); @@ -286,7 +295,7 @@ } } - newFile = make(std::move(file)); + newFile = cachedFile = make(std::move(file)); break; } case file_magic::macho_object: diff --git a/lld/test/MachO/force-load.s b/lld/test/MachO/force-load.s --- a/lld/test/MachO/force-load.s +++ b/lld/test/MachO/force-load.s @@ -13,11 +13,19 @@ # RUN: llvm-objdump --syms %t/test-force-load-second | FileCheck %s --check-prefix=FORCE-LOAD-SECOND # FORCE-LOAD-SECOND: __TEXT,obj _foo +## Force-loading the same path twice is fine +# RUN: %lld %t/foo.o -force_load %t/foo.a -force_load %t/foo.a %t/test.o -o /dev/null + +## Note that we do not call realpath() before dedup'ing the force-load +## arguments, so this is an error. +# RUN: cd %t; not %lld %t/foo.o -force_load %t/foo.a -force_load foo.a %t/test.o -o /dev/null + #--- archive-foo.s .section __TEXT,archive -.globl _foo +.globl _foo, _bar .weak_definition _foo _foo: +_bar: #--- foo.s .section __TEXT,obj