[llvm] [dsymutil] Provide an option to ignore object timestamp mismatches (PR #113238)

Jonas Devlieghere via llvm-commits llvm-commits at lists.llvm.org
Mon Oct 21 17:07:33 PDT 2024


https://github.com/JDevlieghere created https://github.com/llvm/llvm-project/pull/113238

Provide a option (--no-object-timestamp) to ignore object file timestamp
mismatches. We already have a similar option for Swift modules
(--no-swiftmodule-timestamp).

rdar://123975869

Depends on #113234

>From 0b225999f6738da7a107c29d3d0a0fa4e33d1b7b Mon Sep 17 00:00:00 2001
From: Jonas Devlieghere <jonas at devlieghere.com>
Date: Mon, 21 Oct 2024 16:59:17 -0700
Subject: [PATCH 1/2] [dsymutil] Share one BinaryHolder between debug map
 parsing & linking

I (re)discovered that dsymutil was instantiating two BinaryHolders: one
for parsing the debug map and one for linking. That really defeats the
purpose of the BinaryHolder as it serves as a cache. Fix the issue and
remove an old FIXME.
---
 llvm/tools/dsymutil/DebugMap.cpp            | 14 +++++------
 llvm/tools/dsymutil/DebugMap.h              |  4 +++-
 llvm/tools/dsymutil/MachODebugMapParser.cpp | 23 +++++++++---------
 llvm/tools/dsymutil/dsymutil.cpp            | 26 ++++++---------------
 llvm/tools/dsymutil/dsymutil.h              |  9 +++----
 5 files changed, 34 insertions(+), 42 deletions(-)

diff --git a/llvm/tools/dsymutil/DebugMap.cpp b/llvm/tools/dsymutil/DebugMap.cpp
index 8724b70422f326..b38d502dda7c97 100644
--- a/llvm/tools/dsymutil/DebugMap.cpp
+++ b/llvm/tools/dsymutil/DebugMap.cpp
@@ -126,6 +126,9 @@ void DebugMap::dump() const { print(errs()); }
 namespace {
 
 struct YAMLContext {
+  YAMLContext(BinaryHolder &BinHolder, StringRef PrependPath)
+      : BinHolder(BinHolder), PrependPath(PrependPath) {}
+  BinaryHolder &BinHolder;
   StringRef PrependPath;
   Triple BinaryTriple;
 };
@@ -133,15 +136,13 @@ struct YAMLContext {
 } // end anonymous namespace
 
 ErrorOr<std::vector<std::unique_ptr<DebugMap>>>
-DebugMap::parseYAMLDebugMap(StringRef InputFile, StringRef PrependPath,
-                            bool Verbose) {
+DebugMap::parseYAMLDebugMap(BinaryHolder &BinHolder, StringRef InputFile,
+                            StringRef PrependPath, bool Verbose) {
   auto ErrOrFile = MemoryBuffer::getFileOrSTDIN(InputFile);
   if (auto Err = ErrOrFile.getError())
     return Err;
 
-  YAMLContext Ctxt;
-
-  Ctxt.PrependPath = PrependPath;
+  YAMLContext Ctxt(BinHolder, PrependPath);
 
   std::unique_ptr<DebugMap> Res;
   yaml::Input yin((*ErrOrFile)->getBuffer(), &Ctxt);
@@ -244,14 +245,13 @@ MappingTraits<dsymutil::DebugMapObject>::YamlDMO::YamlDMO(
 
 dsymutil::DebugMapObject
 MappingTraits<dsymutil::DebugMapObject>::YamlDMO::denormalize(IO &IO) {
-  BinaryHolder BinHolder(vfs::getRealFileSystem(), /* Verbose =*/false);
   const auto &Ctxt = *reinterpret_cast<YAMLContext *>(IO.getContext());
   SmallString<80> Path(Ctxt.PrependPath);
   StringMap<uint64_t> SymbolAddresses;
 
   sys::path::append(Path, Filename);
 
-  auto ObjectEntry = BinHolder.getObjectEntry(Path);
+  auto ObjectEntry = Ctxt.BinHolder.getObjectEntry(Path);
   if (!ObjectEntry) {
     auto Err = ObjectEntry.takeError();
     WithColor::warning() << "Unable to open " << Path << " "
diff --git a/llvm/tools/dsymutil/DebugMap.h b/llvm/tools/dsymutil/DebugMap.h
index 9c3a698fa1191d..8e2a4de94c89ef 100644
--- a/llvm/tools/dsymutil/DebugMap.h
+++ b/llvm/tools/dsymutil/DebugMap.h
@@ -21,6 +21,7 @@
 #ifndef LLVM_TOOLS_DSYMUTIL_DEBUGMAP_H
 #define LLVM_TOOLS_DSYMUTIL_DEBUGMAP_H
 
+#include "BinaryHolder.h"
 #include "RelocationMap.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/StringMap.h"
@@ -127,7 +128,8 @@ class DebugMap {
 
   /// Read a debug map for \a InputFile.
   static ErrorOr<std::vector<std::unique_ptr<DebugMap>>>
-  parseYAMLDebugMap(StringRef InputFile, StringRef PrependPath, bool Verbose);
+  parseYAMLDebugMap(BinaryHolder &BinHolder, StringRef InputFile,
+                    StringRef PrependPath, bool Verbose);
 };
 
 /// The DebugMapObject represents one object file described by the DebugMap. It
diff --git a/llvm/tools/dsymutil/MachODebugMapParser.cpp b/llvm/tools/dsymutil/MachODebugMapParser.cpp
index 4a06731946b97d..a0ba2512e12f20 100644
--- a/llvm/tools/dsymutil/MachODebugMapParser.cpp
+++ b/llvm/tools/dsymutil/MachODebugMapParser.cpp
@@ -27,14 +27,14 @@ using namespace llvm::object;
 
 class MachODebugMapParser {
 public:
-  MachODebugMapParser(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
-                      StringRef BinaryPath, ArrayRef<std::string> Archs,
+  MachODebugMapParser(BinaryHolder &BinHolder, StringRef BinaryPath,
+                      ArrayRef<std::string> Archs,
                       ArrayRef<std::string> DSYMSearchPaths,
                       StringRef PathPrefix = "", StringRef VariantSuffix = "",
                       bool Verbose = false)
       : BinaryPath(std::string(BinaryPath)), Archs(Archs),
         DSYMSearchPaths(DSYMSearchPaths), PathPrefix(std::string(PathPrefix)),
-        VariantSuffix(std::string(VariantSuffix)), BinHolder(VFS, Verbose),
+        VariantSuffix(std::string(VariantSuffix)), BinHolder(BinHolder),
         CurrentDebugMapObject(nullptr), SkipDebugMapObject(false) {}
 
   /// Parses and returns the DebugMaps of the input binary. The binary contains
@@ -56,7 +56,7 @@ class MachODebugMapParser {
   std::string VariantSuffix;
 
   /// Owns the MemoryBuffer for the main binary.
-  BinaryHolder BinHolder;
+  BinaryHolder &BinHolder;
   /// Map of the binary symbol addresses.
   StringMap<uint64_t> MainBinarySymbolAddresses;
   StringRef MainBinaryStrings;
@@ -854,24 +854,25 @@ void MachODebugMapParser::loadMainBinarySymbols(
 namespace llvm {
 namespace dsymutil {
 llvm::ErrorOr<std::vector<std::unique_ptr<DebugMap>>>
-parseDebugMap(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
-              StringRef InputFile, ArrayRef<std::string> Archs,
+parseDebugMap(BinaryHolder &BinHolder, StringRef InputFile,
+              ArrayRef<std::string> Archs,
               ArrayRef<std::string> DSYMSearchPaths, StringRef PrependPath,
               StringRef VariantSuffix, bool Verbose, bool InputIsYAML) {
   if (InputIsYAML)
-    return DebugMap::parseYAMLDebugMap(InputFile, PrependPath, Verbose);
+    return DebugMap::parseYAMLDebugMap(BinHolder, InputFile, PrependPath,
+                                       Verbose);
 
-  MachODebugMapParser Parser(VFS, InputFile, Archs, DSYMSearchPaths,
+  MachODebugMapParser Parser(BinHolder, InputFile, Archs, DSYMSearchPaths,
                              PrependPath, VariantSuffix, Verbose);
 
   return Parser.parse();
 }
 
-bool dumpStab(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
-              StringRef InputFile, ArrayRef<std::string> Archs,
+bool dumpStab(BinaryHolder &BinHolder, StringRef InputFile,
+              ArrayRef<std::string> Archs,
               ArrayRef<std::string> DSYMSearchPaths, StringRef PrependPath,
               StringRef VariantSuffix) {
-  MachODebugMapParser Parser(VFS, InputFile, Archs, DSYMSearchPaths,
+  MachODebugMapParser Parser(BinHolder, InputFile, Archs, DSYMSearchPaths,
                              PrependPath, VariantSuffix, false);
   return Parser.dumpStab();
 }
diff --git a/llvm/tools/dsymutil/dsymutil.cpp b/llvm/tools/dsymutil/dsymutil.cpp
index 364a7d63d486e1..f510fa7f75bd87 100644
--- a/llvm/tools/dsymutil/dsymutil.cpp
+++ b/llvm/tools/dsymutil/dsymutil.cpp
@@ -180,17 +180,6 @@ static Error verifyOptions(const DsymutilOptions &Options) {
                                    errc::invalid_argument);
   }
 
-  if (Options.LinkOpts.Update && llvm::is_contained(Options.InputFiles, "-")) {
-    // FIXME: We cannot use stdin for an update because stdin will be
-    // consumed by the BinaryHolder during the debugmap parsing, and
-    // then we will want to consume it again in DwarfLinker. If we
-    // used a unique BinaryHolder object that could cache multiple
-    // binaries this restriction would go away.
-    return make_error<StringError>(
-        "standard input cannot be used as input for a dSYM update.",
-        errc::invalid_argument);
-  }
-
   if (!Options.Flat && Options.OutputFile == "-")
     return make_error<StringError>(
         "cannot emit to standard output without --flat.",
@@ -674,9 +663,12 @@ int dsymutil_main(int argc, char **argv, const llvm::ToolContext &) {
     }
 
   for (auto &InputFile : Options.InputFiles) {
+    // Shared a single binary holder for all the link steps.
+    BinaryHolder BinHolder(Options.LinkOpts.VFS, Options.LinkOpts.Verbose);
+
     // Dump the symbol table for each input file and requested arch
     if (Options.DumpStab) {
-      if (!dumpStab(Options.LinkOpts.VFS, InputFile, Options.Archs,
+      if (!dumpStab(BinHolder, InputFile, Options.Archs,
                     Options.LinkOpts.DSYMSearchPaths,
                     Options.LinkOpts.PrependPath,
                     Options.LinkOpts.BuildVariantSuffix))
@@ -685,10 +677,9 @@ int dsymutil_main(int argc, char **argv, const llvm::ToolContext &) {
     }
 
     auto DebugMapPtrsOrErr = parseDebugMap(
-        Options.LinkOpts.VFS, InputFile, Options.Archs,
-        Options.LinkOpts.DSYMSearchPaths, Options.LinkOpts.PrependPath,
-        Options.LinkOpts.BuildVariantSuffix, Options.LinkOpts.Verbose,
-        Options.InputIsYAMLDebugMap);
+        BinHolder, InputFile, Options.Archs, Options.LinkOpts.DSYMSearchPaths,
+        Options.LinkOpts.PrependPath, Options.LinkOpts.BuildVariantSuffix,
+        Options.LinkOpts.Verbose, Options.InputIsYAMLDebugMap);
 
     if (auto EC = DebugMapPtrsOrErr.getError()) {
       WithColor::error() << "cannot parse the debug map for '" << InputFile
@@ -714,9 +705,6 @@ int dsymutil_main(int argc, char **argv, const llvm::ToolContext &) {
       return EXIT_FAILURE;
     }
 
-    // Shared a single binary holder for all the link steps.
-    BinaryHolder BinHolder(Options.LinkOpts.VFS);
-
     // Compute the output location and update the resource directory.
     Expected<OutputLocation> OutputLocationOrErr =
         getOutputFileName(InputFile, Options);
diff --git a/llvm/tools/dsymutil/dsymutil.h b/llvm/tools/dsymutil/dsymutil.h
index 5504dd57c7e558..7b97b8bcd3a250 100644
--- a/llvm/tools/dsymutil/dsymutil.h
+++ b/llvm/tools/dsymutil/dsymutil.h
@@ -16,6 +16,7 @@
 #ifndef LLVM_TOOLS_DSYMUTIL_DSYMUTIL_H
 #define LLVM_TOOLS_DSYMUTIL_DSYMUTIL_H
 
+#include "BinaryHolder.h"
 #include "DebugMap.h"
 #include "LinkUtils.h"
 #include "llvm/ADT/ArrayRef.h"
@@ -33,14 +34,14 @@ namespace dsymutil {
 /// The file has to be a MachO object file. Multiple debug maps can be
 /// returned when the file is universal (aka fat) binary.
 ErrorOr<std::vector<std::unique_ptr<DebugMap>>>
-parseDebugMap(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
-              StringRef InputFile, ArrayRef<std::string> Archs,
+parseDebugMap(BinaryHolder &BinHolder, StringRef InputFile,
+              ArrayRef<std::string> Archs,
               ArrayRef<std::string> DSYMSearchPaths, StringRef PrependPath,
               StringRef VariantSuffix, bool Verbose, bool InputIsYAML);
 
 /// Dump the symbol table.
-bool dumpStab(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
-              StringRef InputFile, ArrayRef<std::string> Archs,
+bool dumpStab(BinaryHolder &BinHolder, StringRef InputFile,
+              ArrayRef<std::string> Archs,
               ArrayRef<std::string> DSYMSearchPaths, StringRef PrependPath = "",
               StringRef VariantSuffix = "");
 

>From 3abc4cad673c393f484f7cf71489064eb65fd526 Mon Sep 17 00:00:00 2001
From: Jonas Devlieghere <jonas at devlieghere.com>
Date: Mon, 21 Oct 2024 16:10:21 -0700
Subject: [PATCH 2/2] [dsymutil] Provide an option to ignore object timestamp
 mismatches

Provide a option (--no-object-timestamp) to ignore object file timestamp
mismatches. We already have a similar option for Swift modules
(--no-swiftmodule-timestamp).

rdar://123975869
---
 llvm/docs/CommandGuide/dsymutil.rst           |  4 +++
 .../dsymutil/X86/timestamp-mismatch.test      | 14 +++++---
 llvm/test/tools/dsymutil/cmdline.test         |  1 +
 llvm/tools/dsymutil/BinaryHolder.cpp          | 34 +++++++++++--------
 llvm/tools/dsymutil/BinaryHolder.h            | 19 +++++++----
 llvm/tools/dsymutil/Options.td                |  4 +++
 llvm/tools/dsymutil/dsymutil.cpp              |  7 +++-
 7 files changed, 56 insertions(+), 27 deletions(-)

diff --git a/llvm/docs/CommandGuide/dsymutil.rst b/llvm/docs/CommandGuide/dsymutil.rst
index 6026e2f534ed70..8764e1fbc7a4ce 100644
--- a/llvm/docs/CommandGuide/dsymutil.rst
+++ b/llvm/docs/CommandGuide/dsymutil.rst
@@ -83,6 +83,10 @@ OPTIONS
  used in conjunction with ``--update`` option, this option will cause redundant
  accelerator tables to be removed.
 
+.. option:: --no-object-timestamp
+
+ Don't check timestamp for object files.
+
 .. option:: --no-odr
 
  Do not use ODR (One Definition Rule) for uniquing C++ types.
diff --git a/llvm/test/tools/dsymutil/X86/timestamp-mismatch.test b/llvm/test/tools/dsymutil/X86/timestamp-mismatch.test
index e75a7f1ddde3d9..4665c75cfe0b7d 100644
--- a/llvm/test/tools/dsymutil/X86/timestamp-mismatch.test
+++ b/llvm/test/tools/dsymutil/X86/timestamp-mismatch.test
@@ -3,10 +3,14 @@ RUN: cp %p/../Inputs/basic.macho.x86_64 %t/Inputs
 RUN: cp %p/../Inputs/basic1.macho.x86_64.o %t/Inputs
 RUN: cp %p/../Inputs/basic2.macho.x86_64.o %t/Inputs
 RUN: cp %p/../Inputs/basic3.macho.x86_64.o %t/Inputs
-RUN: dsymutil -oso-prepend-path=%t %t/Inputs/basic.macho.x86_64 -o %t.dSYM 2>&1 | FileCheck %s
+RUN: dsymutil -oso-prepend-path=%t %t/Inputs/basic.macho.x86_64 -o %t.dSYM 2>&1 | FileCheck %s --check-prefix=WARN
+RUN: dsymutil -no-object-timestamp -oso-prepend-path=%t %t/Inputs/basic.macho.x86_64 -o %t.dSYM 2>&1 | FileCheck %s --allow-empty --check-prefix=NOWARN
 
-RUN: dsymutil --linker parallel -oso-prepend-path=%t %t/Inputs/basic.macho.x86_64 -o %t.dSYM 2>&1 | FileCheck %s
+RUN: dsymutil --linker parallel -oso-prepend-path=%t %t/Inputs/basic.macho.x86_64 -o %t.dSYM 2>&1 | FileCheck %s --check-prefix=WARN
+RUN: dsymutil --linker parallel -no-object-timestamp -oso-prepend-path=%t %t/Inputs/basic.macho.x86_64 -o %t.dSYM 2>&1 | FileCheck %s --allow-empty --check-prefix=NOWARN
 
-CHECK: warning: {{.*}}/Inputs/basic1.macho.x86_64.o: timestamp mismatch between object file ({{.*}}) and debug map ({{.*}})
-CHECK: warning: {{.*}}/Inputs/basic2.macho.x86_64.o: timestamp mismatch between object file ({{.*}}) and debug map ({{.*}})
-CHECK: warning: {{.*}}/Inputs/basic3.macho.x86_64.o: timestamp mismatch between object file ({{.*}}) and debug map ({{.*}})
+WARN: warning: {{.*}}/Inputs/basic1.macho.x86_64.o: timestamp mismatch between object file ({{.*}}) and debug map ({{.*}})
+WARN: warning: {{.*}}/Inputs/basic2.macho.x86_64.o: timestamp mismatch between object file ({{.*}}) and debug map ({{.*}})
+WARN: warning: {{.*}}/Inputs/basic3.macho.x86_64.o: timestamp mismatch between object file ({{.*}}) and debug map ({{.*}})
+
+NOWARN-NOT: warning: {{.*}}/Inputs/basic3.macho.x86_64.o: timestamp mismatch between object file ({{.*}}) and debug map ({{.*}})
diff --git a/llvm/test/tools/dsymutil/cmdline.test b/llvm/test/tools/dsymutil/cmdline.test
index 6c67ac7cd72387..1574fe35f52546 100644
--- a/llvm/test/tools/dsymutil/cmdline.test
+++ b/llvm/test/tools/dsymutil/cmdline.test
@@ -15,6 +15,7 @@ CHECK: -flat
 CHECK: -gen-reproducer
 CHECK: -help
 CHECK: -keep-function-for-static
+CHECK: -no-object-timestamp
 CHECK: -no-odr
 CHECK: -no-output
 CHECK: -no-swiftmodule-timestamp
diff --git a/llvm/tools/dsymutil/BinaryHolder.cpp b/llvm/tools/dsymutil/BinaryHolder.cpp
index 646fe4fc8f8043..5daaa6755b2957 100644
--- a/llvm/tools/dsymutil/BinaryHolder.cpp
+++ b/llvm/tools/dsymutil/BinaryHolder.cpp
@@ -41,9 +41,13 @@ getMachOFatMemoryBuffers(StringRef Filename, MemoryBuffer &Mem,
   return Buffers;
 }
 
+BinaryHolder::BinaryHolder(IntrusiveRefCntPtr<vfs::FileSystem> VFS,
+                           BinaryHolder::Options Opts)
+    : VFS(VFS), Opts(Opts) {}
+
 Error BinaryHolder::ArchiveEntry::load(IntrusiveRefCntPtr<vfs::FileSystem> VFS,
                                        StringRef Filename,
-                                       TimestampTy Timestamp, bool Verbose) {
+                                       TimestampTy Timestamp, Options Opts) {
   StringRef ArchiveFilename = getArchiveAndObjectName(Filename).first;
 
   // Try to load archive and force it to be memory mapped.
@@ -55,7 +59,7 @@ Error BinaryHolder::ArchiveEntry::load(IntrusiveRefCntPtr<vfs::FileSystem> VFS,
 
   MemBuffer = std::move(*ErrOrBuff);
 
-  if (Verbose)
+  if (Opts.Verbose)
     WithColor::note() << "loaded archive '" << ArchiveFilename << "'\n";
 
   // Load one or more archive buffers, depending on whether we're dealing with
@@ -88,7 +92,7 @@ Error BinaryHolder::ArchiveEntry::load(IntrusiveRefCntPtr<vfs::FileSystem> VFS,
 
 Error BinaryHolder::ObjectEntry::load(IntrusiveRefCntPtr<vfs::FileSystem> VFS,
                                       StringRef Filename, TimestampTy Timestamp,
-                                      bool Verbose) {
+                                      Options Opts) {
   // Try to load regular binary and force it to be memory mapped.
   auto ErrOrBuff = (Filename == "-")
                        ? MemoryBuffer::getSTDIN()
@@ -96,7 +100,7 @@ Error BinaryHolder::ObjectEntry::load(IntrusiveRefCntPtr<vfs::FileSystem> VFS,
   if (auto Err = ErrOrBuff.getError())
     return errorCodeToError(Err);
 
-  if (Filename != "-" && Timestamp != sys::TimePoint<>()) {
+  if (Opts.Warn && Filename != "-" && Timestamp != sys::TimePoint<>()) {
     llvm::ErrorOr<vfs::Status> Stat = VFS->status(Filename);
     if (!Stat)
       return errorCodeToError(Stat.getError());
@@ -110,7 +114,7 @@ Error BinaryHolder::ObjectEntry::load(IntrusiveRefCntPtr<vfs::FileSystem> VFS,
 
   MemBuffer = std::move(*ErrOrBuff);
 
-  if (Verbose)
+  if (Opts.Verbose)
     WithColor::note() << "loaded object.\n";
 
   // Load one or more object buffers, depending on whether we're dealing with a
@@ -164,7 +168,7 @@ BinaryHolder::ObjectEntry::getObject(const Triple &T) const {
 Expected<const BinaryHolder::ObjectEntry &>
 BinaryHolder::ArchiveEntry::getObjectEntry(StringRef Filename,
                                            TimestampTy Timestamp,
-                                           bool Verbose) {
+                                           Options Opts) {
   StringRef ArchiveFilename;
   StringRef ObjectFilename;
   std::tie(ArchiveFilename, ObjectFilename) = getArchiveAndObjectName(Filename);
@@ -192,7 +196,7 @@ BinaryHolder::ArchiveEntry::getObjectEntry(StringRef Filename,
           if (Timestamp != sys::TimePoint<>() &&
               Timestamp != std::chrono::time_point_cast<std::chrono::seconds>(
                                ModTimeOrErr.get())) {
-            if (Verbose)
+            if (Opts.Verbose)
               WithColor::warning()
                   << *NameOrErr
                   << ": timestamp mismatch between archive member ("
@@ -201,7 +205,7 @@ BinaryHolder::ArchiveEntry::getObjectEntry(StringRef Filename,
             continue;
           }
 
-          if (Verbose)
+          if (Opts.Verbose)
             WithColor::note() << "found member in archive.\n";
 
           auto ErrOrMem = Child.getMemoryBufferRef();
@@ -230,7 +234,7 @@ BinaryHolder::ArchiveEntry::getObjectEntry(StringRef Filename,
 
 Expected<const BinaryHolder::ObjectEntry &>
 BinaryHolder::getObjectEntry(StringRef Filename, TimestampTy Timestamp) {
-  if (Verbose)
+  if (Opts.Verbose)
     WithColor::note() << "trying to open '" << Filename << "'\n";
 
   // If this is an archive, we might have either the object or the archive
@@ -241,17 +245,17 @@ BinaryHolder::getObjectEntry(StringRef Filename, TimestampTy Timestamp) {
     ArchiveRefCounter[ArchiveFilename]++;
     if (ArchiveCache.count(ArchiveFilename)) {
       return ArchiveCache[ArchiveFilename]->getObjectEntry(Filename, Timestamp,
-                                                           Verbose);
+                                                           Opts);
     } else {
       auto AE = std::make_unique<ArchiveEntry>();
-      auto Err = AE->load(VFS, Filename, Timestamp, Verbose);
+      auto Err = AE->load(VFS, Filename, Timestamp, Opts);
       if (Err) {
         // Don't return the error here: maybe the file wasn't an archive.
         llvm::consumeError(std::move(Err));
       } else {
         ArchiveCache[ArchiveFilename] = std::move(AE);
-        return ArchiveCache[ArchiveFilename]->getObjectEntry(
-            Filename, Timestamp, Verbose);
+        return ArchiveCache[ArchiveFilename]->getObjectEntry(Filename,
+                                                             Timestamp, Opts);
       }
     }
   }
@@ -262,7 +266,7 @@ BinaryHolder::getObjectEntry(StringRef Filename, TimestampTy Timestamp) {
   ObjectRefCounter[Filename]++;
   if (!ObjectCache.count(Filename)) {
     auto OE = std::make_unique<ObjectEntry>();
-    auto Err = OE->load(VFS, Filename, Timestamp, Verbose);
+    auto Err = OE->load(VFS, Filename, Timestamp, Opts);
     if (Err)
       return std::move(Err);
     ObjectCache[Filename] = std::move(OE);
@@ -279,7 +283,7 @@ void BinaryHolder::clear() {
 }
 
 void BinaryHolder::eraseObjectEntry(StringRef Filename) {
-  if (Verbose)
+  if (Opts.Verbose)
     WithColor::note() << "erasing '" << Filename << "' from cache\n";
 
   if (isArchive(Filename)) {
diff --git a/llvm/tools/dsymutil/BinaryHolder.h b/llvm/tools/dsymutil/BinaryHolder.h
index c4fc5a6110e775..cb5bd959781440 100644
--- a/llvm/tools/dsymutil/BinaryHolder.h
+++ b/llvm/tools/dsymutil/BinaryHolder.h
@@ -38,8 +38,15 @@ class BinaryHolder {
 public:
   using TimestampTy = sys::TimePoint<std::chrono::seconds>;
 
-  BinaryHolder(IntrusiveRefCntPtr<vfs::FileSystem> VFS, bool Verbose = false)
-      : VFS(VFS), Verbose(Verbose) {}
+  struct Options {
+    Options(bool Verbose = false, bool Warn = true)
+        : Verbose(Verbose), Warn(Warn) {}
+    bool Verbose;
+    bool Warn;
+  };
+
+  BinaryHolder(IntrusiveRefCntPtr<vfs::FileSystem> VFS,
+               BinaryHolder::Options Opts = {});
 
   // Forward declarations for friend declaration.
   class ObjectEntry;
@@ -58,7 +65,7 @@ class BinaryHolder {
   public:
     /// Load the given object binary in memory.
     Error load(IntrusiveRefCntPtr<vfs::FileSystem> VFS, StringRef Filename,
-               TimestampTy Timestamp, bool Verbose = false);
+               TimestampTy Timestamp, BinaryHolder::Options = {});
 
     /// Access all owned ObjectFiles.
     std::vector<const object::ObjectFile *> getObjects() const;
@@ -110,11 +117,11 @@ class BinaryHolder {
 
     /// Load the given object binary in memory.
     Error load(IntrusiveRefCntPtr<vfs::FileSystem> VFS, StringRef Filename,
-               TimestampTy Timestamp, bool Verbose = false);
+               TimestampTy Timestamp, BinaryHolder::Options = {});
 
     Expected<const ObjectEntry &> getObjectEntry(StringRef Filename,
                                                  TimestampTy Timestamp,
-                                                 bool Verbose = false);
+                                                 BinaryHolder::Options = {});
 
   private:
     std::vector<std::unique_ptr<object::Archive>> Archives;
@@ -143,7 +150,7 @@ class BinaryHolder {
   /// Virtual File System instance.
   IntrusiveRefCntPtr<vfs::FileSystem> VFS;
 
-  bool Verbose;
+  Options Opts;
 };
 
 } // namespace dsymutil
diff --git a/llvm/tools/dsymutil/Options.td b/llvm/tools/dsymutil/Options.td
index 67d367565764f4..ad35e55e33b124 100644
--- a/llvm/tools/dsymutil/Options.td
+++ b/llvm/tools/dsymutil/Options.td
@@ -65,6 +65,10 @@ def no_swiftmodule_timestamp: F<"no-swiftmodule-timestamp">,
   HelpText<"Don't check timestamp for swiftmodule files.">,
   Group<grp_general>;
 
+def no_object_timestamp: F<"no-object-timestamp">,
+  HelpText<"Don't check timestamp for object files.">,
+  Group<grp_general>;
+
 def no_odr: F<"no-odr">,
   HelpText<"Do not use ODR (One Definition Rule) for type uniquing.">,
   Group<grp_general>;
diff --git a/llvm/tools/dsymutil/dsymutil.cpp b/llvm/tools/dsymutil/dsymutil.cpp
index f510fa7f75bd87..754d3a0f26c3d1 100644
--- a/llvm/tools/dsymutil/dsymutil.cpp
+++ b/llvm/tools/dsymutil/dsymutil.cpp
@@ -108,6 +108,7 @@ struct DsymutilOptions {
   bool Flat = false;
   bool InputIsYAMLDebugMap = false;
   bool ForceKeepFunctionForStatic = false;
+  bool NoObjectTimestamp = false;
   std::string OutputFile;
   std::string Toolchain;
   std::string ReproducerPath;
@@ -292,6 +293,7 @@ static Expected<DsymutilOptions> getOptions(opt::InputArgList &Args) {
   Options.DumpStab = Args.hasArg(OPT_symtab);
   Options.Flat = Args.hasArg(OPT_flat);
   Options.InputIsYAMLDebugMap = Args.hasArg(OPT_yaml_input);
+  Options.NoObjectTimestamp = Args.hasArg(OPT_no_object_timestamp);
 
   if (Expected<DWARFVerify> Verify = getVerifyKind(Args)) {
     Options.Verify = *Verify;
@@ -664,7 +666,10 @@ int dsymutil_main(int argc, char **argv, const llvm::ToolContext &) {
 
   for (auto &InputFile : Options.InputFiles) {
     // Shared a single binary holder for all the link steps.
-    BinaryHolder BinHolder(Options.LinkOpts.VFS, Options.LinkOpts.Verbose);
+    BinaryHolder::Options BinOpts;
+    BinOpts.Verbose = Options.LinkOpts.Verbose;
+    BinOpts.Warn = !Options.NoObjectTimestamp;
+    BinaryHolder BinHolder(Options.LinkOpts.VFS, BinOpts);
 
     // Dump the symbol table for each input file and requested arch
     if (Options.DumpStab) {



More information about the llvm-commits mailing list