Add an -object-path-prefix option to dsymutil
authorAdrian Prantl <aprantl@apple.com>
Wed, 18 Mar 2020 22:31:39 +0000 (15:31 -0700)
committerAdrian Prantl <aprantl@apple.com>
Wed, 25 Mar 2020 00:13:42 +0000 (17:13 -0700)
to remap object file paths (but no source paths) before
processing. This is meant to be used for Clang objects where the
module cache location was remapped using ``-fdebug-prefix-map``; to
help dsymutil find the Clang module cache.

<rdar://problem/55685132>

Differential Revision: https://reviews.llvm.org/D76391

llvm/docs/CommandGuide/dsymutil.rst
llvm/include/llvm/DWARFLinker/DWARFLinker.h
llvm/lib/DWARFLinker/DWARFLinker.cpp
llvm/test/tools/dsymutil/X86/object-prefix-path.test [new file with mode: 0644]
llvm/test/tools/dsymutil/cmdline.test
llvm/tools/dsymutil/DwarfLinkerForBinary.cpp
llvm/tools/dsymutil/LinkUtils.h
llvm/tools/dsymutil/Options.td
llvm/tools/dsymutil/dsymutil.cpp

index 4aa9c1c..2f638da 100644 (file)
@@ -71,6 +71,12 @@ OPTIONS
 
  Specifies a ``path`` to prepend to all debug symbol object file paths.
 
+.. option:: --object-prefix-map=<prefix=remapped>
+
+ Remap object file paths (but no source paths) before processing.  Use
+ this for Clang objects where the module cache location was remapped using
+ ``-fdebug-prefix-map``; to help dsymutil find the Clang module cache.
 .. option:: --papertrail
 
  When running dsymutil as part of your build system, it can be desirable for
index af49665..d75ed8b 100644 (file)
@@ -226,6 +226,7 @@ typedef std::function<ErrorOr<DwarfFile &>(StringRef ContainerName,
                                            StringRef Path)>
     objFileLoader;
 typedef std::map<std::string, std::string> swiftInterfacesMap;
+typedef std::map<std::string, std::string> objectPrefixMap;
 
 /// The core of the Dwarf linking logic.
 ///
@@ -311,6 +312,11 @@ public:
     Options.ParseableSwiftInterfaces = Map;
   }
 
+  /// Set prefix map for objects.
+  void setObjectPrefixMap(objectPrefixMap *Map) {
+    Options.ObjectPrefixMap = Map;
+  }
+
 private:
   /// Flags passed to DwarfLinker::lookForDIEsToKeep
   enum TraversalFlags {
@@ -783,6 +789,9 @@ private:
     /// per compile unit, which is why this is a std::map.
     /// this is dsymutil specific fag.
     swiftInterfacesMap *ParseableSwiftInterfaces = nullptr;
+
+    /// A list of remappings to apply to file paths.
+    objectPrefixMap *ObjectPrefixMap = nullptr;
   } Options;
 };
 
index ab18cb0..6444af9 100644 (file)
@@ -1918,6 +1918,14 @@ static uint64_t getDwoId(const DWARFDie &CUDie, const DWARFUnit &Unit) {
   return 0;
 }
 
+static std::string remapPath(StringRef Path,
+                             const objectPrefixMap &ObjectPrefixMap) {
+  for (const auto &Entry : ObjectPrefixMap)
+    if (Path.startswith(Entry.first))
+      return (Twine(Entry.second) + Path.substr(Entry.first.size())).str();
+  return Path.str();
+}
+
 bool DWARFLinker::registerModuleReference(
     DWARFDie CUDie, const DWARFUnit &Unit, const DwarfFile &File,
     OffsetsStringPool &StringPool, UniquingStringPool &UniquingStringPool,
@@ -1927,6 +1935,8 @@ bool DWARFLinker::registerModuleReference(
       CUDie.find({dwarf::DW_AT_dwo_name, dwarf::DW_AT_GNU_dwo_name}), "");
   if (PCMfile.empty())
     return false;
+  if (Options.ObjectPrefixMap)
+    PCMfile = remapPath(PCMfile, *Options.ObjectPrefixMap);
 
   // Clang module DWARF skeleton CUs abuse this for the path to the module.
   uint64_t DwoId = getDwoId(CUDie, Unit);
diff --git a/llvm/test/tools/dsymutil/X86/object-prefix-path.test b/llvm/test/tools/dsymutil/X86/object-prefix-path.test
new file mode 100644 (file)
index 0000000..16956e0
--- /dev/null
@@ -0,0 +1,11 @@
+RUN: rm -rf %t.dir && mkdir %t.dir && mkdir %t.dir/ModuleCacheRenamed
+RUN: cp %p/../Inputs/module-warnings/1.o %t.dir
+RUN: cp %p/../Inputs/module-warnings/Foo.pcm %t.dir/ModuleCacheRenamed
+
+RUN: dsymutil -verify -f -oso-prepend-path=%t.dir -y \
+RUN:   %p/dummy-debug-map.map -o %t \
+RUN:   -object-prefix-map=/ModuleCache=/ModuleCacheRenamed \
+RUN:   2>&1 | FileCheck %s
+
+CHECK:     warning: {{.*}}Bar.pcm:
+CHECK-NOT: warning: {{.*}}Foo.pcm:
index fc3f00b..701de29 100644 (file)
@@ -12,6 +12,7 @@ HELP: -no-odr
 HELP: -no-output
 HELP: -no-swiftmodule-timestamp
 HELP: -num-threads <threads>
+HELP: -object-prefix-map <prefix=remapped>
 HELP: -oso-prepend-path <path>
 HELP: -o <filename>
 HELP: -papertrail
index 51912c7..c1c247d 100644 (file)
@@ -297,6 +297,7 @@ bool DwarfLinkerForBinary::link(const DebugMap &Map) {
   remarks::RemarkLinker RL;
   if (!Options.RemarksPrependPath.empty())
     RL.setExternalFilePrependPath(Options.RemarksPrependPath);
+  GeneralLinker.setObjectPrefixMap(&Options.ObjectPrefixMap);
 
   std::function<StringRef(StringRef)> TranslationLambda = [&](StringRef Input) {
     assert(Options.Translator);
index 92de81d..0339f44 100644 (file)
@@ -57,6 +57,9 @@ struct LinkOptions {
   /// -oso-prepend-path
   std::string PrependPath;
 
+  /// The -object-prefix-map.
+  std::map<std::string, std::string> ObjectPrefixMap;
+
   /// The Resources directory in the .dSYM bundle.
   Optional<std::string> ResourceDir;
 
index eb86c2f..5360bf0 100644 (file)
@@ -110,6 +110,15 @@ def oso_prepend_path: Separate<["--", "-"], "oso-prepend-path">,
   Group<grp_general>;
 def: Joined<["--", "-"], "oso-prepend-path=">, Alias<oso_prepend_path>;
 
+def object_prefix_map: Separate<["--", "-"], "object-prefix-map">,
+    MetaVarName<"<prefix=remapped>">,
+    HelpText<"Remap object file paths (but no source paths) before processing."
+             "Use this for Clang objects where the module cache location was"
+             "remapped using -fdebug-prefix-map; to help dsymutil"
+             "find the Clang module cache.">,
+    Group<grp_general>;
+def: Joined<["--", "-"], "object-prefix-map=">, Alias<object_prefix_map>;
+
 def symbolmap: Separate<["--", "-"], "symbol-map">,
   MetaVarName<"<bcsymbolmap>">,
   HelpText<"Updates the existing dSYMs inplace using symbol map specified.">,
index 54adeaa..8b70673 100644 (file)
@@ -246,6 +246,12 @@ static Expected<DsymutilOptions> getOptions(opt::InputArgList &Args) {
   if (opt::Arg *OsoPrependPath = Args.getLastArg(OPT_oso_prepend_path))
     Options.LinkOpts.PrependPath = OsoPrependPath->getValue();
 
+  for (const auto &Arg : Args.getAllArgValues(OPT_object_prefix_map)) {
+    auto Split = StringRef(Arg).split('=');
+    Options.LinkOpts.ObjectPrefixMap.insert(
+        {std::string(Split.first), std::string(Split.second)});
+  }
+
   if (opt::Arg *OutputFile = Args.getLastArg(OPT_output))
     Options.OutputFile = OutputFile->getValue();