diff options
author | Jez Ng <jezng@fb.com> | 2020-12-01 14:45:11 -0800 |
---|---|---|
committer | Jez Ng <jezng@fb.com> | 2020-12-01 15:05:21 -0800 |
commit | b768d57b368781e6737c403e425bd835850f3a0a (patch) | |
tree | 5aa3b66211237b32181adcfaa86e3b946de00bd1 | |
parent | [lld-macho] Emit empty string as first entry of string table (diff) | |
download | llvm-project-b768d57b368781e6737c403e425bd835850f3a0a.tar.gz llvm-project-b768d57b368781e6737c403e425bd835850f3a0a.tar.bz2 llvm-project-b768d57b368781e6737c403e425bd835850f3a0a.zip |
[lld-macho] Add archive name and file modtime to STABS output
We should also set the modtime when running LTO. That will be done in a
future diff, together with support for the `-object_path_lto` flag.
Reviewed By: clayborg
Differential Revision: https://reviews.llvm.org/D91318
-rw-r--r-- | lld/MachO/Driver.cpp | 45 | ||||
-rw-r--r-- | lld/MachO/Driver.h | 2 | ||||
-rw-r--r-- | lld/MachO/DriverUtils.cpp | 10 | ||||
-rw-r--r-- | lld/MachO/InputFiles.cpp | 14 | ||||
-rw-r--r-- | lld/MachO/InputFiles.h | 4 | ||||
-rw-r--r-- | lld/MachO/LTO.cpp | 4 | ||||
-rw-r--r-- | lld/MachO/SyntheticSections.cpp | 9 | ||||
-rw-r--r-- | lld/test/MachO/stabs.s | 24 |
8 files changed, 85 insertions, 27 deletions
diff --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp index 141082985b4e..295f2c412a7f 100644 --- a/lld/MachO/Driver.cpp +++ b/lld/MachO/Driver.cpp @@ -212,21 +212,32 @@ getFrameworkSearchPaths(opt::InputArgList &args, {"/Library/Frameworks", "/System/Library/Frameworks"}); } +namespace { +struct ArchiveMember { + MemoryBufferRef mbref; + uint32_t modTime; +}; +} // namespace + // Returns slices of MB by parsing MB as an archive file. // Each slice consists of a member file in the archive. -static std::vector<MemoryBufferRef> getArchiveMembers(MemoryBufferRef mb) { +static std::vector<ArchiveMember> getArchiveMembers(MemoryBufferRef mb) { std::unique_ptr<Archive> file = CHECK(Archive::create(mb), mb.getBufferIdentifier() + ": failed to parse archive"); - std::vector<MemoryBufferRef> v; + std::vector<ArchiveMember> v; Error err = Error::success(); for (const Archive::Child &c : file->children(err)) { MemoryBufferRef mbref = CHECK(c.getMemoryBufferRef(), mb.getBufferIdentifier() + ": could not get the buffer for a child of the archive"); - v.push_back(mbref); + uint32_t modTime = toTimeT( + CHECK(c.getLastModified(), mb.getBufferIdentifier() + + ": could not get the modification " + "time for a child of the archive")); + v.push_back({mbref, modTime}); } if (err) fatal(mb.getBufferIdentifier() + @@ -235,6 +246,16 @@ static std::vector<MemoryBufferRef> getArchiveMembers(MemoryBufferRef mb) { return v; } +static void forceLoadArchive(StringRef path) { + if (Optional<MemoryBufferRef> buffer = readFile(path)) { + for (const ArchiveMember &member : getArchiveMembers(*buffer)) { + auto file = make<ObjFile>(member.mbref, member.modTime); + file->archiveName = buffer->getBufferIdentifier(); + inputFiles.push_back(file); + } + } +} + static InputFile *addFile(StringRef path) { Optional<MemoryBufferRef> buffer = readFile(path); if (!buffer) @@ -251,9 +272,7 @@ static InputFile *addFile(StringRef path) { error(path + ": archive has no index; run ranlib to add one"); if (config->allLoad) { - if (Optional<MemoryBufferRef> buffer = readFile(path)) - for (MemoryBufferRef member : getArchiveMembers(*buffer)) - inputFiles.push_back(make<ObjFile>(member)); + forceLoadArchive(path); } else if (config->forceLoadObjC) { for (const object::Archive::Symbol &sym : file->symbols()) if (sym.getName().startswith(objc::klass)) @@ -264,16 +283,16 @@ static InputFile *addFile(StringRef path) { // consider creating a LazyObjFile class in order to avoid double-loading // these files here and below (as part of the ArchiveFile). if (Optional<MemoryBufferRef> buffer = readFile(path)) - for (MemoryBufferRef member : getArchiveMembers(*buffer)) - if (hasObjCSection(member)) - inputFiles.push_back(make<ObjFile>(member)); + for (const ArchiveMember &member : getArchiveMembers(*buffer)) + if (hasObjCSection(member.mbref)) + inputFiles.push_back(make<ObjFile>(member.mbref, member.modTime)); } newFile = make<ArchiveFile>(std::move(file)); break; } case file_magic::macho_object: - newFile = make<ObjFile>(mbref); + newFile = make<ObjFile>(mbref, getModTime(path)); break; case file_magic::macho_dynamically_linked_shared_lib: case file_magic::macho_dynamically_linked_shared_lib_stub: @@ -304,12 +323,6 @@ static void addFileList(StringRef path) { addFile(path); } -static void forceLoadArchive(StringRef path) { - if (Optional<MemoryBufferRef> buffer = readFile(path)) - for (MemoryBufferRef member : getArchiveMembers(*buffer)) - inputFiles.push_back(make<ObjFile>(member)); -} - static std::array<StringRef, 6> archNames{"arm", "arm64", "i386", "x86_64", "ppc", "ppc64"}; static bool isArchString(StringRef s) { diff --git a/lld/MachO/Driver.h b/lld/MachO/Driver.h index c06d2f9d1b3d..d5625fd3873e 100644 --- a/lld/MachO/Driver.h +++ b/lld/MachO/Driver.h @@ -43,6 +43,8 @@ llvm::Optional<std::string> resolveDylibPath(llvm::StringRef path); llvm::Optional<DylibFile *> makeDylibFromTAPI(llvm::MemoryBufferRef mbref, DylibFile *umbrella = nullptr); +uint32_t getModTime(llvm::StringRef path); + } // namespace macho } // namespace lld diff --git a/lld/MachO/DriverUtils.cpp b/lld/MachO/DriverUtils.cpp index ec57c6898129..77f76b522d7e 100644 --- a/lld/MachO/DriverUtils.cpp +++ b/lld/MachO/DriverUtils.cpp @@ -175,3 +175,13 @@ Optional<DylibFile *> macho::makeDylibFromTAPI(MemoryBufferRef mbref, } return make<DylibFile>(**result, umbrella); } + +uint32_t macho::getModTime(StringRef path) { + fs::file_status stat; + if (!fs::status(path, stat)) + if (fs::exists(stat)) + return toTimeT(stat.getLastModificationTime()); + + warn("failed to get modification time of " + path); + return 0; +} diff --git a/lld/MachO/InputFiles.cpp b/lld/MachO/InputFiles.cpp index 921b69995d43..19d531cc5028 100644 --- a/lld/MachO/InputFiles.cpp +++ b/lld/MachO/InputFiles.cpp @@ -364,7 +364,8 @@ OpaqueFile::OpaqueFile(MemoryBufferRef mb, StringRef segName, subsections.push_back({{0, isec}}); } -ObjFile::ObjFile(MemoryBufferRef mb) : InputFile(ObjKind, mb) { +ObjFile::ObjFile(MemoryBufferRef mb, uint32_t modTime) + : InputFile(ObjKind, mb), modTime(modTime) { auto *buf = reinterpret_cast<const uint8_t *>(mb.getBufferStart()); auto *hdr = reinterpret_cast<const mach_header_64 *>(mb.getBufferStart()); @@ -592,7 +593,16 @@ void ArchiveFile::fetch(const object::Archive::Symbol &sym) { toString(this) + ": could not get the buffer for the member defining symbol " + sym.getName()); - auto file = make<ObjFile>(mb); + + uint32_t modTime = toTimeT( + CHECK(c.getLastModified(), toString(this) + + ": could not get the modification time " + "for the member defining symbol " + + sym.getName())); + + auto file = make<ObjFile>(mb, modTime); + file->archiveName = getName(); + symbols.insert(symbols.end(), file->symbols.begin(), file->symbols.end()); subsections.insert(subsections.end(), file->subsections.begin(), file->subsections.end()); diff --git a/lld/MachO/InputFiles.h b/lld/MachO/InputFiles.h index 4356350e7c17..f7fd77dacff5 100644 --- a/lld/MachO/InputFiles.h +++ b/lld/MachO/InputFiles.h @@ -90,10 +90,12 @@ private: // .o file class ObjFile : public InputFile { public: - explicit ObjFile(MemoryBufferRef mb); + explicit ObjFile(MemoryBufferRef mb, uint32_t modTime); static bool classof(const InputFile *f) { return f->kind() == ObjKind; } llvm::DWARFUnit *compileUnit = nullptr; + StringRef archiveName = ""; + const uint32_t modTime; private: void parseDebugInfo(); diff --git a/lld/MachO/LTO.cpp b/lld/MachO/LTO.cpp index bf0db6175690..3050e03f2f24 100644 --- a/lld/MachO/LTO.cpp +++ b/lld/MachO/LTO.cpp @@ -73,10 +73,12 @@ std::vector<ObjFile *> BitcodeCompiler::compile() { saveBuffer(buf[i], config->outputFile + Twine(i) + ".lto.o"); } + // TODO: set modTime properly std::vector<ObjFile *> ret; for (unsigned i = 0; i != maxTasks; ++i) if (!buf[i].empty()) - ret.push_back(make<ObjFile>(MemoryBufferRef(buf[i], "lto.tmp"))); + ret.push_back( + make<ObjFile>(MemoryBufferRef(buf[i], "lto.tmp"), /*modTime=*/0)); return ret; } diff --git a/lld/MachO/SyntheticSections.cpp b/lld/MachO/SyntheticSections.cpp index 56a095c4a7e4..ae66961310c5 100644 --- a/lld/MachO/SyntheticSections.cpp +++ b/lld/MachO/SyntheticSections.cpp @@ -602,13 +602,18 @@ void SymtabSection::emitEndSourceStab() { void SymtabSection::emitObjectFileStab(ObjFile *file) { StabsEntry stab(MachO::N_OSO); stab.sect = target->cpuSubtype; - SmallString<261> path(file->getName()); + SmallString<261> path(!file->archiveName.empty() ? file->archiveName + : file->getName()); std::error_code ec = sys::fs::make_absolute(path); if (ec) - fatal("failed to get absolute path for " + file->getName()); + fatal("failed to get absolute path for " + path); + + if (!file->archiveName.empty()) + path.append({"(", file->getName(), ")"}); stab.strx = stringTableSection.addString(saver.save(path.str())); stab.desc = 1; + stab.value = file->modTime; stabs.emplace_back(std::move(stab)); } diff --git a/lld/test/MachO/stabs.s b/lld/test/MachO/stabs.s index 2c49453dcd43..81f1ecbc1e96 100644 --- a/lld/test/MachO/stabs.s +++ b/lld/test/MachO/stabs.s @@ -3,22 +3,35 @@ # RUN: split-file %s %t # RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/test.s -o %t/test.o # RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/foo.s -o %t/foo.o +## Set modtimes of the files for deterministic test output. +# RUN: env TZ=UTC touch -t "197001010000.16" %t/test.o +# RUN: env TZ=UTC touch -t "197001010000.32" %t/foo.o +# RUN: rm -f %t/foo.a +# RUN: llvm-ar rcsU %t/foo.a %t/foo.o # RUN: %lld -lSystem %t/test.o %t/foo.o -o %t/test -# RUN: llvm-nm -pa %t/test | FileCheck %s -DDIR=%t +# RUN: llvm-nm -pa %t/test | FileCheck %s -DDIR=%t -DFOO_PATH=%t/foo.o + +## Check that we emit the right modtime even when the object file is in an +## archive. +# RUN: %lld -lSystem %t/test.o %t/foo.a -o %t/test +# RUN: llvm-nm -pa %t/test | FileCheck %s -DDIR=%t -DFOO_PATH=%t/foo.a\(foo.o\) ## Check that we emit absolute paths to the object files in our OSO entries ## even if our inputs are relative paths. # RUN: cd %t && %lld -lSystem test.o foo.o -o test -# RUN: llvm-nm -pa %t/test | FileCheck %s -DDIR=%t +# RUN: llvm-nm -pa %t/test | FileCheck %s -DDIR=%t -DFOO_PATH=%t/foo.o + +# RUN: cd %t && %lld -lSystem %t/test.o %t/foo.a -o %t/test +# RUN: llvm-nm -pa %t/test | FileCheck %s -DDIR=%t -DFOO_PATH=%t/foo.a\(foo.o\) # CHECK: 0000000000000000 - 00 0000 SO /tmp/test.cpp -# CHECK-NEXT: 0000000000000000 - 03 0001 OSO [[DIR]]/test.o +# CHECK-NEXT: 0000000000000010 - 03 0001 OSO [[DIR]]/test.o # CHECK-NEXT: [[#%x, MAIN:]] - 01 0000 FUN _main -# CHECK-NEXT: 0000000000000001 - 00 0000 FUN +# CHECK-NEXT: 0000000000000006 - 00 0000 FUN # CHECK-NEXT: 0000000000000000 - 01 0000 SO # CHECK-NEXT: 0000000000000000 - 00 0000 SO /foo.cpp -# CHECK-NEXT: 0000000000000000 - 03 0001 OSO [[DIR]]/foo.o +# CHECK-NEXT: 0000000000000020 - 03 0001 OSO [[FOO_PATH]] # CHECK-NEXT: [[#%x, FOO:]] - 01 0000 FUN _foo # CHECK-NEXT: 0000000000000001 - 00 0000 FUN # CHECK-NEXT: 0000000000000000 - 01 0000 SO @@ -30,6 +43,7 @@ .globl _main _main: Lfunc_begin0: + callq _foo retq Lfunc_end0: |