diff --git a/lld/MachO/InputFiles.cpp b/lld/MachO/InputFiles.cpp --- a/lld/MachO/InputFiles.cpp +++ b/lld/MachO/InputFiles.cpp @@ -2106,28 +2106,34 @@ forceHidden(forceHidden) {} void ArchiveFile::addLazySymbols() { - Error err = Error::success(); - Expected mbOrErr = - this->file->child_begin(err)->getMemoryBufferRef(); + // Avoid calling getMemoryBufferRef() on zero-symbol archive + // since that crashes. + if (file->isEmpty() || file->getNumberOfSymbols() == 0) + return; + Error err = Error::success(); + auto child = file->child_begin(err); // Ignore the I/O error here - will be reported later. - if (!mbOrErr) { - llvm::consumeError(mbOrErr.takeError()); - } else if (!err) { - if (identify_magic(mbOrErr->getBuffer()) == file_magic::macho_object) { - if (target->wordSize == 8) - compatArch = compatWithTargetArch( - this, reinterpret_cast( - mbOrErr->getBufferStart())); - else - compatArch = compatWithTargetArch( - this, reinterpret_cast( - mbOrErr->getBufferStart())); - - if (!compatArch) - return; + if (!err) { + Expected mbOrErr = child->getMemoryBufferRef(); + if (!mbOrErr) { + llvm::consumeError(mbOrErr.takeError()); + } else { + if (identify_magic(mbOrErr->getBuffer()) == file_magic::macho_object) { + if (target->wordSize == 8) + compatArch = compatWithTargetArch( + this, reinterpret_cast( + mbOrErr->getBufferStart())); + else + compatArch = compatWithTargetArch( + this, reinterpret_cast( + mbOrErr->getBufferStart())); + if (!compatArch) + return; + } } } + for (const object::Archive::Symbol &sym : file->symbols()) symtab->addLazyArchive(sym.getName(), this, sym); } 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 @@ -42,6 +42,12 @@ # TWICE-DAG: __TEXT,archive _bar # TWICE-DAG: __TEXT,archive _baz +## Loading an empty-archive should not crash. +# RUN: llvm-ar --format=darwin rcs %t/libEmpty.a +# RUN: %lld -lSystem %t/test.o -force_load %t/libEmpty.a -o %t/loadEmpty.out +# RUN: llvm-objdump --macho --syms %t/loadEmpty.out | FileCheck %s --check-prefix=EMPTY +# EMPTY: F __TEXT,__text _main + #--- archive-foo.s .section __TEXT,archive .globl _foo, _bar