diff --git a/llvm/docs/CommandGuide/dsymutil.rst b/llvm/docs/CommandGuide/dsymutil.rst --- a/llvm/docs/CommandGuide/dsymutil.rst +++ b/llvm/docs/CommandGuide/dsymutil.rst @@ -71,6 +71,12 @@ Specifies a ``path`` to prepend to all debug symbol object file paths. +.. option:: --object-prefix-map= + + 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 diff --git a/llvm/include/llvm/DWARFLinker/DWARFLinker.h b/llvm/include/llvm/DWARFLinker/DWARFLinker.h --- a/llvm/include/llvm/DWARFLinker/DWARFLinker.h +++ b/llvm/include/llvm/DWARFLinker/DWARFLinker.h @@ -226,6 +226,7 @@ StringRef Path)> objFileLoader; typedef std::map swiftInterfacesMap; +typedef std::map objectPrefixMap; /// The core of the Dwarf linking logic. /// @@ -311,6 +312,11 @@ 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 @@ /// 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; }; diff --git a/llvm/lib/DWARFLinker/DWARFLinker.cpp b/llvm/lib/DWARFLinker/DWARFLinker.cpp --- a/llvm/lib/DWARFLinker/DWARFLinker.cpp +++ b/llvm/lib/DWARFLinker/DWARFLinker.cpp @@ -1918,6 +1918,14 @@ 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 @@ 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 --- /dev/null +++ b/llvm/test/tools/dsymutil/X86/object-prefix-path.test @@ -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: diff --git a/llvm/test/tools/dsymutil/cmdline.test b/llvm/test/tools/dsymutil/cmdline.test --- a/llvm/test/tools/dsymutil/cmdline.test +++ b/llvm/test/tools/dsymutil/cmdline.test @@ -12,6 +12,7 @@ HELP: -no-output HELP: -no-swiftmodule-timestamp HELP: -num-threads +HELP: -object-prefix-map HELP: -oso-prepend-path HELP: -o HELP: -papertrail diff --git a/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp b/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp --- a/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp +++ b/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp @@ -297,6 +297,7 @@ remarks::RemarkLinker RL; if (!Options.RemarksPrependPath.empty()) RL.setExternalFilePrependPath(Options.RemarksPrependPath); + GeneralLinker.setObjectPrefixMap(&Options.ObjectPrefixMap); std::function TranslationLambda = [&](StringRef Input) { assert(Options.Translator); diff --git a/llvm/tools/dsymutil/LinkUtils.h b/llvm/tools/dsymutil/LinkUtils.h --- a/llvm/tools/dsymutil/LinkUtils.h +++ b/llvm/tools/dsymutil/LinkUtils.h @@ -57,6 +57,9 @@ /// -oso-prepend-path std::string PrependPath; + /// The -object-prefix-map. + std::map ObjectPrefixMap; + /// The Resources directory in the .dSYM bundle. Optional ResourceDir; diff --git a/llvm/tools/dsymutil/Options.td b/llvm/tools/dsymutil/Options.td --- a/llvm/tools/dsymutil/Options.td +++ b/llvm/tools/dsymutil/Options.td @@ -110,6 +110,15 @@ Group; def: Joined<["--", "-"], "oso-prepend-path=">, Alias; +def object_prefix_map: Separate<["--", "-"], "object-prefix-map">, + MetaVarName<"">, + 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; +def: Joined<["--", "-"], "object-prefix-map=">, Alias; + def symbolmap: Separate<["--", "-"], "symbol-map">, MetaVarName<"">, HelpText<"Updates the existing dSYMs inplace using symbol map specified.">, diff --git a/llvm/tools/dsymutil/dsymutil.cpp b/llvm/tools/dsymutil/dsymutil.cpp --- a/llvm/tools/dsymutil/dsymutil.cpp +++ b/llvm/tools/dsymutil/dsymutil.cpp @@ -246,6 +246,12 @@ 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();