diff --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp --- a/lld/MachO/Driver.cpp +++ b/lld/MachO/Driver.cpp @@ -324,7 +324,7 @@ reason = "-all_load"; break; } - if (Error e = file->fetch(c, reason)) + if (Error e = file->fetch(c, reason, true)) error(toString(file) + ": " + reason + " failed to load archive member: " + toString(std::move(e))); } diff --git a/lld/MachO/InputFiles.h b/lld/MachO/InputFiles.h --- a/lld/MachO/InputFiles.h +++ b/lld/MachO/InputFiles.h @@ -282,15 +282,12 @@ void fetch(const llvm::object::Archive::Symbol &); // LLD normally doesn't use Error for error-handling, but the underlying // Archive library does, so this is the cleanest way to wrap it. - Error fetch(const llvm::object::Archive::Child &, StringRef reason); + Error fetch(const llvm::object::Archive::Child &, StringRef reason, bool skipCache = false); const llvm::object::Archive &getArchive() const { return *file; }; static bool classof(const InputFile *f) { return f->kind() == ArchiveKind; } private: std::unique_ptr file; - // Keep track of children fetched from the archive by tracking - // which address offsets have been fetched already. - llvm::DenseSet seen; // Load all symbols with hidden visibility (-load_hidden). bool forceHidden; }; diff --git a/lld/MachO/InputFiles.cpp b/lld/MachO/InputFiles.cpp --- a/lld/MachO/InputFiles.cpp +++ b/lld/MachO/InputFiles.cpp @@ -2095,14 +2095,21 @@ } } -Error ArchiveFile::fetch(const object::Archive::Child &c, StringRef reason) { - if (!seen.insert(c.getChildOffset()).second) - return Error::success(); +// Globally keep track of children fetched from the archives by tracking +// the contents that have already been fetched (e.g. Frameworks fetched +// from LC_LINKER_OPTION should not be re-fetched from archives even with +// ObjC flag enabled irregardless whether it comes from a framework or a +// static library). +static llvm::DenseSet seen; +Error ArchiveFile::fetch(const object::Archive::Child &c, StringRef reason, bool skipCache) { Expected mb = c.getMemoryBufferRef(); if (!mb) return mb.takeError(); + if (!skipCache && !seen.insert(mb->getBuffer()).second) + return Error::success(); + // Thin archives refer to .o files, so --reproduce needs the .o files too. if (tar && c.getParent()->isThin()) tar->append(relativeToRoot(CHECK(c.getFullName(), this)), mb->getBuffer()); diff --git a/lld/test/MachO/lc-linker-option.ll b/lld/test/MachO/lc-linker-option.ll --- a/lld/test/MachO/lc-linker-option.ll +++ b/lld/test/MachO/lc-linker-option.ll @@ -70,6 +70,28 @@ ; RUN: %lld %t/load-framework-foo.o %t/main.o -o %t/main -F%t ; RUN: llvm-objdump --macho --syms %t/main | FileCheck %s --check-prefix=SYMS +;; Identical contents from different archive paths should not fail the build. +; RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/refs-foo.s -o %t/refs-foo.o +; RUN: llvm-ar rcs %t/libFoo.a %t/foo.o +; RUN: %lld -ObjC %t/refs-foo.o %t/main.o -o %t/no-dup-syms -lFoo -F%t -L%t +; RUN: llvm-objdump --section-headers --syms %t/no-dup-syms | FileCheck %s --check-prefix=NO-DUP + +; NO-DUP: Sections: +; NO-DUP-NEXT: Idx Name Size VMA Type +; NO-DUP-NEXT: 0 __text {{.*}} TEXT +; NO-DUP-NEXT: 1 __swift {{.*}} DATA +; NO-DUP-NEXT: 2 __unwind_info {{.*}} DATA +; NO-DUP-NEXT: 3 __eh_frame {{.*}} DATA +; NO-DUP-NEXT: 4 __objc_classrefs {{.*}} DATA +; NO-DUP-NEXT: 5 __objc_data {{.*}} DATA +; NO-DUP-EMPTY: +; NO-DUP-NEXT: SYMBOL TABLE: +; NO-DUP-NEXT: g F __TEXT,__text _main +; NO-DUP-NEXT: g O __DATA,__objc_data _OBJC_CLASS_$_TestClass +; NO-DUP-NEXT: g O __TEXT,__swift _$s6swifty1aSivp +; NO-DUP-NEXT: g F __TEXT,__text __mh_execute_header +; NO-DUP-NEXT: *UND* dyld_stub_binder + ;; Make sure -all_load and -ObjC have no effect on libraries loaded via ;; LC_LINKER_OPTION flags. ; RUN: llc %t/load-library-foo.ll -o %t/load-library-foo.o -filetype=obj @@ -92,6 +114,7 @@ ;; Note that _OBJC_CLASS_$_TestClass is *included* here. ; SYMS_ALL_LOAD: SYMBOL TABLE: ; SYMS_ALL_LOAD-NEXT: g F __TEXT,__text _main +; SYMS_ALL_LOAD-NEXT: g O __TEXT,__swift _$s6swifty1aSivp ; SYMS_ALL_LOAD-NEXT: g O __DATA,__objc_data _OBJC_CLASS_$_TestClass ; SYMS_ALL_LOAD-NEXT: g F __TEXT,__text __mh_execute_header ; SYMS_ALL_LOAD-NEXT: *UND* dyld_stub_binder @@ -104,6 +127,7 @@ ;; Note that _OBJC_CLASS_$_TestClass is *included* here. ; SYMS_FORCE_LOAD: SYMBOL TABLE: ; SYMS_FORCE_LOAD-NEXT: g F __TEXT,__text _main +; SYMS_FORCE_LOAD-NEXT: g O __TEXT,__swift _$s6swifty1aSivp ; SYMS_FORCE_LOAD-NEXT: g O __DATA,__objc_data _OBJC_CLASS_$_TestClass ; SYMS_FORCE_LOAD-NEXT: g F __TEXT,__text __mh_execute_header ; SYMS_FORCE_LOAD-NEXT: *UND* dyld_stub_binder @@ -116,6 +140,7 @@ ;; Note that _OBJC_CLASS_$_TestClass is *included* here. ; SYMS_OBJC_LOAD: SYMBOL TABLE: ; SYMS_OBJC_LOAD-NEXT: g F __TEXT,__text _main +; SYMS_OBJC_LOAD-NEXT: g O __TEXT,__swift _$s6swifty1aSivp ; SYMS_OBJC_LOAD-NEXT: g O __DATA,__objc_data _OBJC_CLASS_$_TestClass ; SYMS_OBJC_LOAD-NEXT: g F __TEXT,__text __mh_execute_header ; SYMS_OBJC_LOAD-NEXT: *UND* dyld_stub_binder @@ -259,3 +284,11 @@ %struct._class_t = type {} @"OBJC_CLASS_$_TestClass" = global %struct._class_t {}, section "__DATA, __objc_data", align 8 + +;; Loading special sections with -ObjC should not report duplicate symbols +%TSi = type <{ i64 }> +@"$s6swifty1aSivp" = global %TSi zeroinitializer, section "__TEXT, __swift", align 8 + +;--- refs-foo.s +.section __DATA,__objc_classrefs +.quad _OBJC_CLASS_$_TestClass diff --git a/lld/test/MachO/objc.s b/lld/test/MachO/objc.s --- a/lld/test/MachO/objc.s +++ b/lld/test/MachO/objc.s @@ -15,13 +15,13 @@ # RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/test.s -o %t/test.o # RUN: %lld -lSystem %t/test.o -o %t/test -L%t -lHasSomeObjC -ObjC -# RUN: llvm-objdump --section-headers --syms %t/test | FileCheck %s --check-prefix=OBJC +# RUN: llvm-objdump --section-headers --syms %t/test | FileCheck %s --check-prefixes=OBJC -# RUN: %lld -lSystem %t/test.o -o %t/test -L%t -lHasSomeObjC2 -ObjC -# RUN: llvm-objdump --section-headers --syms %t/test | FileCheck %s --check-prefix=OBJC +# RUN: %lld -lSystem %t/test.o -o %t/test2 -L%t -lHasSomeObjC2 -ObjC +# RUN: llvm-objdump --section-headers --syms %t/test2 | FileCheck %s --check-prefixes=OBJC -# RUN: %lld -lSystem %t/test.o -o %t/test --start-lib %t/no-objc.o %t/has-objc-symbol.o %t/has-objc-category.o %t/has-swift.o %t/has-swift-proto.o %t/wrong-arch.o --end-lib -ObjC -# RUN: llvm-objdump --section-headers --syms %t/test | FileCheck %s --check-prefix=OBJC +# RUN: %lld -lSystem %t/test.o -o %t/test3 --start-lib %t/no-objc.o %t/has-objc-symbol.o %t/has-objc-category.o %t/has-swift.o %t/has-swift-proto.o %t/wrong-arch.o --end-lib -ObjC +# RUN: llvm-objdump --section-headers --syms %t/test3 | FileCheck %s --check-prefixes=OBJC # OBJC: Sections: # OBJC-NEXT: Idx Name Size VMA Type @@ -32,12 +32,13 @@ # OBJC-NEXT: 4 has_objc_symbol {{.*}} DATA # OBJC-EMPTY: # OBJC-NEXT: SYMBOL TABLE: +# OBJC-DAG: l O __DATA,has_objc_symbol _objc_label # OBJC-DAG: g F __TEXT,__text _main # OBJC-DAG: g F __TEXT,__text _OBJC_CLASS_$_MyObject # OBJC-DAG: g O __TEXT,__swift5_fieldmd $s7somelib4Blah_pMF -# RUN: %lld -lSystem %t/test.o -o %t/test -L%t -lHasSomeObjC -# RUN: llvm-objdump --section-headers --syms %t/test | FileCheck %s --check-prefix=NO-OBJC +# RUN: %lld -lSystem %t/test.o -o %t/test4 -L%t -lHasSomeObjC +# RUN: llvm-objdump --section-headers --syms %t/test4 | FileCheck %s --check-prefix=NO-OBJC # NO-OBJC: Sections: # NO-OBJC-NEXT: Idx Name Size VMA Type @@ -69,12 +70,32 @@ # RUN: %t/has-objc-symbol.o %t/has-objc-category.o %t/has-swift.o %t/wrong-arch.o --end-lib \ # RUN: -ObjC 2>&1 | FileCheck %s --check-prefix=DUP-ERROR +## When two identical object files containing ObjC symbols are within the same archive, ld64 "dedups" +## instead of reporting duplicate syms when -ObjC is enabled. +# RUN: llvm-ar rcs %t/libHasDuplicateObjC.a %t/has-objc-symbol.o %t/has-objc-symbol.o +# RUN: %lld -lSystem %t/test.o -o %t/dup-objc-object-syms -L%t -lHasDuplicateObjC -ObjC +# RUN: llvm-objdump --section-headers --syms %t/dup-objc-object-syms | FileCheck %s --check-prefix=DUP-OBJECT-ARCHIVE + +# DUP-OBJECT-ARCHIVE: Sections: +# DUP-OBJECT-ARCHIVE-NEXT: Idx Name Size VMA Type +# DUP-OBJECT-ARCHIVE-NEXT: 0 __text {{.*}} TEXT +# DUP-OBJECT-ARCHIVE-NEXT: 1 has_objc_symbol {{.*}} DATA +# DUP-OBJECT-ARCHIVE-EMPTY: +# DUP-OBJECT-ARCHIVE-NEXT: SYMBOL TABLE: +# DUP-OBJECT-ARCHIVE-NEXT: l O __DATA,has_objc_symbol _objc_label +# DUP-OBJECT-ARCHIVE-NEXT: g F __TEXT,__text _main +# DUP-OBJECT-ARCHIVE-NEXT: g F __TEXT,__text _OBJC_CLASS_$_MyObject +# DUP-OBJECT-ARCHIVE-NEXT: g O __DATA,has_objc_symbol _has_dup +# DUP-OBJECT-ARCHIVE-NEXT: g F __TEXT,__text __mh_execute_header +# DUP-OBJECT-ARCHIVE-NEXT: *UND* dyld_stub_binder + #--- has-objc-symbol.s .globl _OBJC_CLASS_$_MyObject, _has_dup _OBJC_CLASS_$_MyObject: .section __DATA,has_objc_symbol _has_dup: +_objc_label: #--- has-objc-category.s .section __DATA,__objc_catlist @@ -88,6 +109,7 @@ .section __DATA,has_objc_symbol _has_dup: +_objc_label: .section __DATA,__objc_catlist .quad 0x1234