Index: lld/MachO/Driver.cpp =================================================================== --- lld/MachO/Driver.cpp +++ lld/MachO/Driver.cpp @@ -266,9 +266,8 @@ if (config->allLoad || forceLoadArchive) { if (Optional buffer = readFile(path)) { for (const ArchiveMember &member : getArchiveMembers(*buffer)) { - auto file = make(member.mbref, member.modTime); - file->archiveName = buffer->getBufferIdentifier(); - inputFiles.push_back(file); + inputFiles.push_back( + make(member.mbref, member.modTime, path)); } } } else if (config->forceLoadObjC) { @@ -282,15 +281,17 @@ // these files here and below (as part of the ArchiveFile). if (Optional buffer = readFile(path)) for (const ArchiveMember &member : getArchiveMembers(*buffer)) - if (hasObjCSection(member.mbref)) - inputFiles.push_back(make(member.mbref, member.modTime)); + if (hasObjCSection(member.mbref)) { + inputFiles.push_back( + make(member.mbref, member.modTime, path)); + } } newFile = make(std::move(file)); break; } case file_magic::macho_object: - newFile = make(mbref, getModTime(path)); + newFile = make(mbref, getModTime(path), ""); break; case file_magic::macho_dynamically_linked_shared_lib: case file_magic::macho_dynamically_linked_shared_lib_stub: @@ -737,7 +738,7 @@ parseOrderFile(orderFile); if (config->outputType == MH_EXECUTE && isa(config->entry)) { - error("undefined symbol: " + config->entry->getName()); + error("undefined symbol: " + toString(*config->entry)); return false; } Index: lld/MachO/InputFiles.h =================================================================== --- lld/MachO/InputFiles.h +++ lld/MachO/InputFiles.h @@ -62,12 +62,18 @@ StringRef getName() const { return name; } MemoryBufferRef mb; + std::vector symbols; ArrayRef sectionHeaders; std::vector subsections; // Provides an easy way to sort InputFiles deterministically. const int id; + // Filename of .a which contained this file. If this file was + // not in an archive file, it is the empty string. We use this + // string for creating error messages. + std::string archiveName; + protected: InputFile(Kind kind, MemoryBufferRef mb) : mb(mb), id(idCount++), fileKind(kind), name(mb.getBufferIdentifier()) {} @@ -94,11 +100,10 @@ // .o file class ObjFile : public InputFile { public: - explicit ObjFile(MemoryBufferRef mb, uint32_t modTime); + explicit ObjFile(MemoryBufferRef mb, uint32_t modTime, StringRef archiveName); static bool classof(const InputFile *f) { return f->kind() == ObjKind; } llvm::DWARFUnit *compileUnit = nullptr; - StringRef archiveName = ""; const uint32_t modTime; private: Index: lld/MachO/InputFiles.cpp =================================================================== --- lld/MachO/InputFiles.cpp +++ lld/MachO/InputFiles.cpp @@ -74,6 +74,17 @@ using namespace lld; using namespace lld::macho; +// Returns "", "foo.a(bar.o)", or "baz.o". +std::string lld::toString(const InputFile *f) { + if (!f) + return ""; + if (f->archiveName.empty()) + return std::string(f->getName()); + return (path::filename(f->archiveName) + "(" + path::filename(f->getName()) + + ")") + .str(); +} + std::vector macho::inputFiles; std::unique_ptr macho::tar; int InputFile::idCount = 0; @@ -365,8 +376,10 @@ subsections.push_back({{0, isec}}); } -ObjFile::ObjFile(MemoryBufferRef mb, uint32_t modTime) +ObjFile::ObjFile(MemoryBufferRef mb, uint32_t modTime, StringRef archiveName) : InputFile(ObjKind, mb), modTime(modTime) { + this->archiveName = std::string(archiveName); + auto *buf = reinterpret_cast(mb.getBufferStart()); auto *hdr = reinterpret_cast(mb.getBufferStart()); @@ -402,9 +415,11 @@ auto *ctx = make( std::move(dObj), "", - [&](Error err) { warn(getName() + ": " + toString(std::move(err))); }, + [&](Error err) { + warn(toString(this) + ": " + toString(std::move(err))); + }, [&](Error warning) { - warn(getName() + ": " + toString(std::move(warning))); + warn(toString(this) + ": " + toString(std::move(warning))); }); // TODO: Since object files can contain a lot of DWARF info, we should verify @@ -482,7 +497,7 @@ auto *c = reinterpret_cast(cmd); dylibName = reinterpret_cast(cmd) + read32le(&c->dylib.name); } else { - error("dylib " + getName() + " missing LC_ID_DYLIB load command"); + error("dylib " + toString(this) + " missing LC_ID_DYLIB load command"); return; } @@ -500,7 +515,7 @@ isWeakDef, isTlv)); }); } else { - error("LC_DYLD_INFO_ONLY not found in " + getName()); + error("LC_DYLD_INFO_ONLY not found in " + toString(this)); return; } @@ -601,8 +616,7 @@ "for the member defining symbol " + toMachOString(sym))); - auto file = make(mb, modTime); - file->archiveName = getName(); + auto file = make(mb, modTime, getName()); symbols.insert(symbols.end(), file->symbols.begin(), file->symbols.end()); subsections.insert(subsections.end(), file->subsections.begin(), @@ -613,8 +627,3 @@ : InputFile(BitcodeKind, mbref) { obj = check(lto::InputFile::create(mbref)); } - -// Returns "" or "baz.o". -std::string lld::toString(const InputFile *file) { - return file ? std::string(file->getName()) : ""; -} Index: lld/MachO/LTO.cpp =================================================================== --- lld/MachO/LTO.cpp +++ lld/MachO/LTO.cpp @@ -78,7 +78,7 @@ for (unsigned i = 0; i != maxTasks; ++i) if (!buf[i].empty()) ret.push_back( - make(MemoryBufferRef(buf[i], "lto.tmp"), /*modTime=*/0)); + make(MemoryBufferRef(buf[i], "lto.tmp"), /*modTime=*/0, "")); return ret; } Index: lld/MachO/Writer.cpp =================================================================== --- lld/MachO/Writer.cpp +++ lld/MachO/Writer.cpp @@ -390,7 +390,7 @@ if (auto *s = r.referent.dyn_cast()) { if (isa(s)) error("undefined symbol " + toString(*s) + ", referenced from " + - sys::path::filename(isec->file->getName())); + toString(isec->file)); else target->prepareSymbolRelocation(s, isec, r); } else { @@ -617,7 +617,7 @@ if (ssec->isNeeded()) getOrCreateOutputSegment(ssec->segname)->addOutputSection(ssec); } else { - error("section from " + it->second->firstSection()->file->getName() + + error("section from " + toString(it->second->firstSection()->file) + " conflicts with synthetic section " + ssec->segname + "," + ssec->name); } Index: lld/test/MachO/invalid/undefined-symbol.s =================================================================== --- lld/test/MachO/invalid/undefined-symbol.s +++ lld/test/MachO/invalid/undefined-symbol.s @@ -1,8 +1,25 @@ # REQUIRES: x86 -# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %s -o %t.o -# RUN: not %lld -o %t %t.o 2>&1 | FileCheck %s -DBASENAME=%basename_t -# CHECK: error: undefined symbol _foo, referenced from [[BASENAME]] +# RUN: rm -rf %t +# RUN: split-file %s %t +# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/main.s -o %t/main.o +# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/foo.s -o %t/foo.o +# RUN: llvm-ar crs %t/foo.a %t/foo.o +# RUN: not %lld -o /dev/null %t/main.o 2>&1 | \ +# RUN: FileCheck %s -DSYM=_foo -DFILENAME=%t/main.o +# RUN: not %lld -o /dev/null %t/main.o %t/foo.a 2>&1 | \ +# RUN: FileCheck %s -DSYM=_bar -DFILENAME='foo.a(foo.o)' +# RUN: not %lld -o /dev/null %t/main.o -force_load %t/foo.a 2>&1 | \ +# RUN: FileCheck %s -DSYM=_bar -DFILENAME='foo.a(foo.o)' +# CHECK: error: undefined symbol [[SYM]], referenced from [[FILENAME]] +#--- foo.s +.globl _foo +.text +_foo: + callq _bar + retq + +#--- main.s .globl _main .text _main: