[lld] b768d57 - [lld-macho] Add archive name and file modtime to STABS output

Jez Ng via llvm-commits llvm-commits at lists.llvm.org
Tue Dec 1 15:05:40 PST 2020


Author: Jez Ng
Date: 2020-12-01T15:05:21-08:00
New Revision: b768d57b368781e6737c403e425bd835850f3a0a

URL: https://github.com/llvm/llvm-project/commit/b768d57b368781e6737c403e425bd835850f3a0a
DIFF: https://github.com/llvm/llvm-project/commit/b768d57b368781e6737c403e425bd835850f3a0a.diff

LOG: [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

Added: 
    

Modified: 
    lld/MachO/Driver.cpp
    lld/MachO/Driver.h
    lld/MachO/DriverUtils.cpp
    lld/MachO/InputFiles.cpp
    lld/MachO/InputFiles.h
    lld/MachO/LTO.cpp
    lld/MachO/SyntheticSections.cpp
    lld/test/MachO/stabs.s

Removed: 
    


################################################################################
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 @@ class InputFile {
 // .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:
 


        


More information about the llvm-commits mailing list