[llvm] Reland [dsymutil] Add support for mergeable libraries (PR #70256)

Alpha Abdoulaye via llvm-commits llvm-commits at lists.llvm.org
Wed Oct 25 14:32:37 PDT 2023


https://github.com/Alpha-10000 created https://github.com/llvm/llvm-project/pull/70256

Reland https://reviews.llvm.org/D158124
Fixed `-fpermissive` error emitted by gcc only.

>From 3cfe147b58d1446dfd513824be9fb8786b87c6b6 Mon Sep 17 00:00:00 2001
From: Alpha Abdoulaye <aabdoulaye at apple.com>
Date: Tue, 24 Oct 2023 12:21:42 -0700
Subject: [PATCH] [dsymutil] Add support for mergeable libraries

---
 llvm/docs/CommandGuide/dsymutil.rst           |  15 ++
 llvm/include/llvm/BinaryFormat/Dwarf.def      |   1 +
 llvm/include/llvm/BinaryFormat/MachO.h        |   1 +
 llvm/include/llvm/DWARFLinker/DWARFLinker.h   |  23 ++
 .../llvm/DWARFLinkerParallel/AddressesMap.h   |  18 ++
 llvm/include/llvm/TargetParser/Triple.h       |   6 +-
 llvm/lib/DWARFLinker/DWARFLinker.cpp          |  61 ++++-
 llvm/lib/TargetParser/Triple.cpp              |  58 ++---
 .../Contents/Info.plist                       |  20 ++
 .../Resources/DWARF/bar-relink-variant.dylib  | Bin 0 -> 8923 bytes
 .../aarch64/bar-relink-variant.dylib.yml      |   8 +
 .../bar-relink.dylib.dSYM/Contents/Info.plist |  20 ++
 .../Contents/Resources/DWARF/bar-relink.dylib | Bin 0 -> 8923 bytes
 .../Relocations/aarch64/bar-relink.dylib.yml  |   8 +
 .../Inputs/basic-relink.macho.arm64.dylib     | Bin 0 -> 50992 bytes
 .../Inputs/basic-relink.macho.arm64.o         | Bin 0 -> 2176 bytes
 .../Contents/Info.plist                       |  20 ++
 .../Resources/DWARF/foo-relink-variant.dylib  | Bin 0 -> 9196 bytes
 .../DWARF/foo-relink-variant_debug.dylib      | Bin 0 -> 9196 bytes
 .../aarch64/foo-relink-variant.dylib.yml      |   9 +
 .../foo-relink.dylib.dSYM/Contents/Info.plist |  20 ++
 .../Contents/Resources/DWARF/foo-relink.dylib | Bin 0 -> 9292 bytes
 .../Relocations/aarch64/foo-relink.dylib.yml  |  10 +
 .../Contents/Info.plist                       |  20 ++
 .../Resources/DWARF/proxy-relink.dylib        | Bin 0 -> 10046 bytes
 .../aarch64/proxy-relink.dylib.yml            |  14 ++
 .../Inputs/two-level-relink.macho.arm64.dylib | Bin 0 -> 50944 bytes
 .../Inputs/variant-relink.macho.arm64.dylib   | Bin 0 -> 50944 bytes
 llvm/test/tools/dsymutil/basic-linking.test   | 122 ++++++++++
 llvm/test/tools/dsymutil/cmdline.test         |   2 +
 llvm/tools/dsymutil/CMakeLists.txt            |   1 +
 llvm/tools/dsymutil/DebugMap.cpp              |  23 +-
 llvm/tools/dsymutil/DebugMap.h                |  44 ++--
 llvm/tools/dsymutil/DwarfLinkerForBinary.cpp  | 202 ++++++++++++----
 llvm/tools/dsymutil/DwarfLinkerForBinary.h    | 112 +++++++--
 llvm/tools/dsymutil/LinkUtils.h               |   6 +
 llvm/tools/dsymutil/MachODebugMapParser.cpp   | 226 +++++++++++++++---
 llvm/tools/dsymutil/Options.td                |  11 +
 llvm/tools/dsymutil/RelocationMap.cpp         |  92 +++++++
 llvm/tools/dsymutil/RelocationMap.h           | 160 +++++++++++++
 llvm/tools/dsymutil/dsymutil.cpp              |  19 +-
 llvm/tools/dsymutil/dsymutil.h                |   6 +-
 llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp |  12 +
 llvm/tools/llvm-nm/llvm-nm.cpp                |  47 ++--
 44 files changed, 1218 insertions(+), 199 deletions(-)
 create mode 100644 llvm/test/tools/dsymutil/Inputs/bar-relink-variant.dylib.dSYM/Contents/Info.plist
 create mode 100644 llvm/test/tools/dsymutil/Inputs/bar-relink-variant.dylib.dSYM/Contents/Resources/DWARF/bar-relink-variant.dylib
 create mode 100644 llvm/test/tools/dsymutil/Inputs/bar-relink-variant.dylib.dSYM/Contents/Resources/Relocations/aarch64/bar-relink-variant.dylib.yml
 create mode 100644 llvm/test/tools/dsymutil/Inputs/bar-relink.dylib.dSYM/Contents/Info.plist
 create mode 100644 llvm/test/tools/dsymutil/Inputs/bar-relink.dylib.dSYM/Contents/Resources/DWARF/bar-relink.dylib
 create mode 100644 llvm/test/tools/dsymutil/Inputs/bar-relink.dylib.dSYM/Contents/Resources/Relocations/aarch64/bar-relink.dylib.yml
 create mode 100644 llvm/test/tools/dsymutil/Inputs/basic-relink.macho.arm64.dylib
 create mode 100644 llvm/test/tools/dsymutil/Inputs/basic-relink.macho.arm64.o
 create mode 100644 llvm/test/tools/dsymutil/Inputs/foo-relink-variant.dylib.dSYM/Contents/Info.plist
 create mode 100644 llvm/test/tools/dsymutil/Inputs/foo-relink-variant.dylib.dSYM/Contents/Resources/DWARF/foo-relink-variant.dylib
 create mode 100644 llvm/test/tools/dsymutil/Inputs/foo-relink-variant.dylib.dSYM/Contents/Resources/DWARF/foo-relink-variant_debug.dylib
 create mode 100644 llvm/test/tools/dsymutil/Inputs/foo-relink-variant.dylib.dSYM/Contents/Resources/Relocations/aarch64/foo-relink-variant.dylib.yml
 create mode 100644 llvm/test/tools/dsymutil/Inputs/foo-relink.dylib.dSYM/Contents/Info.plist
 create mode 100644 llvm/test/tools/dsymutil/Inputs/foo-relink.dylib.dSYM/Contents/Resources/DWARF/foo-relink.dylib
 create mode 100644 llvm/test/tools/dsymutil/Inputs/foo-relink.dylib.dSYM/Contents/Resources/Relocations/aarch64/foo-relink.dylib.yml
 create mode 100644 llvm/test/tools/dsymutil/Inputs/proxy-relink.dylib.dSYM/Contents/Info.plist
 create mode 100644 llvm/test/tools/dsymutil/Inputs/proxy-relink.dylib.dSYM/Contents/Resources/DWARF/proxy-relink.dylib
 create mode 100644 llvm/test/tools/dsymutil/Inputs/proxy-relink.dylib.dSYM/Contents/Resources/Relocations/aarch64/proxy-relink.dylib.yml
 create mode 100644 llvm/test/tools/dsymutil/Inputs/two-level-relink.macho.arm64.dylib
 create mode 100644 llvm/test/tools/dsymutil/Inputs/variant-relink.macho.arm64.dylib
 create mode 100644 llvm/tools/dsymutil/RelocationMap.cpp
 create mode 100644 llvm/tools/dsymutil/RelocationMap.h

diff --git a/llvm/docs/CommandGuide/dsymutil.rst b/llvm/docs/CommandGuide/dsymutil.rst
index 02243e227a24d4a..df621a429bb5c38 100644
--- a/llvm/docs/CommandGuide/dsymutil.rst
+++ b/llvm/docs/CommandGuide/dsymutil.rst
@@ -32,11 +32,26 @@ OPTIONS
  architectures will be linked by default and any architectures that can't be
  properly linked will cause :program:`dsymutil` to return an error.
 
+.. option:: --build-variant-suffix <suffix=buildvariant>
+
+ Specify the build variant suffix used to build the executabe file.
+ There can be multiple variants for the binary of a product, each built
+ slightly differently. The most common build variants are 'debug' and
+ 'profile'. Setting the DYLD_IMAGE_SUFFIX environment variable will
+ cause dyld to load the specified variant at runtime.
+
 .. option:: --dump-debug-map
 
  Dump the *executable*'s debug-map (the list of the object files containing the
  debug information) in YAML format and exit. No DWARF link will take place.
 
+ .. option:: -D <path>
+
+ Specify a directory that contain dSYM files to search for.
+ This is used for mergeable libraries, so dsymutil knows where to look
+ for dSYM files with  debug information about symbols present in those
+ libraries.
+
 .. option:: --fat64
 
  Use a 64-bit header when emitting universal binaries.
diff --git a/llvm/include/llvm/BinaryFormat/Dwarf.def b/llvm/include/llvm/BinaryFormat/Dwarf.def
index fb328a025773252..d1abb1f361d3edf 100644
--- a/llvm/include/llvm/BinaryFormat/Dwarf.def
+++ b/llvm/include/llvm/BinaryFormat/Dwarf.def
@@ -629,6 +629,7 @@ HANDLE_DW_AT(0x3fec, APPLE_objc_complete_type, 0, APPLE)
 HANDLE_DW_AT(0x3fed, APPLE_property, 0, APPLE)
 HANDLE_DW_AT(0x3fee, APPLE_objc_direct, 0, APPLE)
 HANDLE_DW_AT(0x3fef, APPLE_sdk, 0, APPLE)
+HANDLE_DW_AT(0x3ff0, APPLE_origin, 0, APPLE)
 
 // Attribute form encodings.
 HANDLE_DW_FORM(0x01, addr, 2, DWARF)
diff --git a/llvm/include/llvm/BinaryFormat/MachO.h b/llvm/include/llvm/BinaryFormat/MachO.h
index 49991ebe7bfaf27..bef70f869520b78 100644
--- a/llvm/include/llvm/BinaryFormat/MachO.h
+++ b/llvm/include/llvm/BinaryFormat/MachO.h
@@ -373,6 +373,7 @@ enum StabType {
   N_SSYM = 0x60u,
   N_SO = 0x64u,
   N_OSO = 0x66u,
+  N_LIB = 0x68u,
   N_LSYM = 0x80u,
   N_BINCL = 0x82u,
   N_SOL = 0x84u,
diff --git a/llvm/include/llvm/DWARFLinker/DWARFLinker.h b/llvm/include/llvm/DWARFLinker/DWARFLinker.h
index e5797514165a22b..a5721184a6a2f09 100644
--- a/llvm/include/llvm/DWARFLinker/DWARFLinker.h
+++ b/llvm/include/llvm/DWARFLinker/DWARFLinker.h
@@ -62,6 +62,9 @@ class AddressesMap {
   virtual std::optional<int64_t>
   getSubprogramRelocAdjustment(const DWARFDie &DIE) = 0;
 
+  /// Returns the file name associated to the AddessesMap
+  virtual std::optional<StringRef> getLibraryInstallName() = 0;
+
   /// Apply the valid relocations to the buffer \p Data, taking into
   /// account that Data is at \p BaseOffset in the .debug_info section.
   ///
@@ -69,6 +72,23 @@ class AddressesMap {
   virtual bool applyValidRelocs(MutableArrayRef<char> Data, uint64_t BaseOffset,
                                 bool IsLittleEndian) = 0;
 
+  /// Check if the linker needs to gather and save relocation info.
+  virtual bool needToSaveValidRelocs() = 0;
+
+  /// Update and save original relocations located in between StartOffset and
+  /// EndOffset. LinkedOffset is the value which should be added to the original
+  /// relocation offset to get new relocation offset in linked binary.
+  virtual void updateAndSaveValidRelocs(bool IsDWARF5,
+                                        uint64_t OriginalUnitOffset,
+                                        int64_t LinkedOffset,
+                                        uint64_t StartOffset,
+                                        uint64_t EndOffset) = 0;
+
+  /// Update the valid relocations that used OriginalUnitOffset as the compile
+  /// unit offset, and update their values to reflect OutputUnitOffset.
+  virtual void updateRelocationsWithUnitOffset(uint64_t OriginalUnitOffset,
+                                               uint64_t OutputUnitOffset) = 0;
+
   /// Erases all data.
   virtual void clear() = 0;
 };
@@ -752,6 +772,9 @@ class DWARFLinker {
       /// Is there a DW_AT_str_offsets_base in the CU?
       bool AttrStrOffsetBaseSeen = false;
 
+      /// Is there a DW_AT_APPLE_origin in the CU?
+      bool HasAppleOrigin = false;
+
       AttributesInfo() = default;
     };
 
diff --git a/llvm/include/llvm/DWARFLinkerParallel/AddressesMap.h b/llvm/include/llvm/DWARFLinkerParallel/AddressesMap.h
index 22fbec20d7d3766..b451fee4e0b723a 100644
--- a/llvm/include/llvm/DWARFLinkerParallel/AddressesMap.h
+++ b/llvm/include/llvm/DWARFLinkerParallel/AddressesMap.h
@@ -55,6 +55,9 @@ class AddressesMap {
   virtual std::optional<int64_t>
   getSubprogramRelocAdjustment(const DWARFDie &DIE) = 0;
 
+  // Returns the library install name associated to the AddessesMap.
+  virtual std::optional<StringRef> getLibraryInstallName() = 0;
+
   /// Apply the valid relocations to the buffer \p Data, taking into
   /// account that Data is at \p BaseOffset in the .debug_info section.
   ///
@@ -62,6 +65,21 @@ class AddressesMap {
   virtual bool applyValidRelocs(MutableArrayRef<char> Data, uint64_t BaseOffset,
                                 bool IsLittleEndian) = 0;
 
+  /// Check if the linker needs to gather and save relocation info.
+  virtual bool needToSaveValidRelocs() = 0;
+
+  /// Update and save relocation values to be serialized
+  virtual void updateAndSaveValidRelocs(bool IsDWARF5,
+                                        uint64_t OriginalUnitOffset,
+                                        int64_t LinkedOffset,
+                                        uint64_t StartOffset,
+                                        uint64_t EndOffset) = 0;
+
+  /// Update the valid relocations that used OriginalUnitOffset as the compile
+  /// unit offset, and update their values to reflect OutputUnitOffset.
+  virtual void updateRelocationsWithUnitOffset(uint64_t OriginalUnitOffset,
+                                               uint64_t OutputUnitOffset) = 0;
+
   /// Erases all data.
   virtual void clear() = 0;
 
diff --git a/llvm/include/llvm/TargetParser/Triple.h b/llvm/include/llvm/TargetParser/Triple.h
index 53cef0abbe0e139..0f56ac68c851f67 100644
--- a/llvm/include/llvm/TargetParser/Triple.h
+++ b/llvm/include/llvm/TargetParser/Triple.h
@@ -418,9 +418,6 @@ class Triple {
   /// Get the architecture (first) component of the triple.
   StringRef getArchName() const;
 
-  /// Get the architecture name based on Kind and SubArch.
-  StringRef getArchName(ArchType Kind, SubArchType SubArch = NoSubArch) const;
-
   /// Get the vendor (second) component of the triple.
   StringRef getVendorName() const;
 
@@ -1118,6 +1115,9 @@ class Triple {
   /// Get the canonical name for the \p Kind architecture.
   static StringRef getArchTypeName(ArchType Kind);
 
+  /// Get the architecture name based on \p Kind and \p SubArch.
+  static StringRef getArchName(ArchType Kind, SubArchType SubArch = NoSubArch);
+
   /// Get the "prefix" canonical name for the \p Kind architecture. This is the
   /// prefix used by the architecture specific builtins, and is suitable for
   /// passing to \see Intrinsic::getIntrinsicForClangBuiltin().
diff --git a/llvm/lib/DWARFLinker/DWARFLinker.cpp b/llvm/lib/DWARFLinker/DWARFLinker.cpp
index 2d8360f100c1172..80a4e2adefa6cb6 100644
--- a/llvm/lib/DWARFLinker/DWARFLinker.cpp
+++ b/llvm/lib/DWARFLinker/DWARFLinker.cpp
@@ -1026,6 +1026,15 @@ unsigned DWARFLinker::DIECloner::cloneStringAttribute(DIE &Die,
     StringEntry = DebugLineStrPool.getEntry(*String);
   } else {
     StringEntry = DebugStrPool.getEntry(*String);
+
+    if (AttrSpec.Attr == dwarf::DW_AT_APPLE_origin) {
+      Info.HasAppleOrigin = true;
+      if (std::optional<StringRef> FileName =
+              ObjFile.Addresses->getLibraryInstallName()) {
+        StringEntry = DebugStrPool.getEntry(*FileName);
+      }
+    }
+
     // Update attributes info.
     if (AttrSpec.Attr == dwarf::DW_AT_name)
       Info.Name = StringEntry;
@@ -1637,6 +1646,12 @@ shouldSkipAttribute(bool Update,
   }
 }
 
+struct AttributeLinkedOffsetFixup {
+  int64_t LinkedOffsetFixupVal;
+  uint64_t InputAttrStartOffset;
+  uint64_t InputAttrEndOffset;
+};
+
 DIE *DWARFLinker::DIECloner::cloneDIE(const DWARFDie &InputDIE,
                                       const DWARFFile &File, CompileUnit &Unit,
                                       int64_t PCOffset, uint32_t OutOffset,
@@ -1720,6 +1735,9 @@ DIE *DWARFLinker::DIECloner::cloneDIE(const DWARFDie &InputDIE,
       Flags |= TF_SkipPC;
   }
 
+  std::optional<StringRef> LibraryInstallName =
+      ObjFile.Addresses->getLibraryInstallName();
+  SmallVector<AttributeLinkedOffsetFixup> AttributesFixups;
   for (const auto &AttrSpec : Abbrev->attributes()) {
     if (shouldSkipAttribute(Update, AttrSpec, Flags & TF_SkipPC)) {
       DWARFFormValue::skipValue(AttrSpec.Form, Data, &Offset,
@@ -1727,17 +1745,41 @@ DIE *DWARFLinker::DIECloner::cloneDIE(const DWARFDie &InputDIE,
       continue;
     }
 
+    AttributeLinkedOffsetFixup CurAttrFixup;
+    CurAttrFixup.InputAttrStartOffset = InputDIE.getOffset() + Offset;
+    CurAttrFixup.LinkedOffsetFixupVal =
+        Unit.getStartOffset() + OutOffset - CurAttrFixup.InputAttrStartOffset;
+
     DWARFFormValue Val = AttrSpec.getFormValue();
     uint64_t AttrSize = Offset;
     Val.extractValue(Data, &Offset, U.getFormParams(), &U);
+    CurAttrFixup.InputAttrEndOffset = InputDIE.getOffset() + Offset;
     AttrSize = Offset - AttrSize;
 
-    OutOffset += cloneAttribute(*Die, InputDIE, File, Unit, Val, AttrSpec,
-                                AttrSize, AttrInfo, IsLittleEndian);
+    uint64_t FinalAttrSize =
+        cloneAttribute(*Die, InputDIE, File, Unit, Val, AttrSpec, AttrSize,
+                       AttrInfo, IsLittleEndian);
+    if (FinalAttrSize != 0 && ObjFile.Addresses->needToSaveValidRelocs())
+      AttributesFixups.push_back(CurAttrFixup);
+
+    OutOffset += FinalAttrSize;
   }
 
-  // Look for accelerator entries.
   uint16_t Tag = InputDIE.getTag();
+  // Add the DW_AT_APPLE_origin attribute to Compile Unit die if we have
+  // an install name and the DWARF doesn't have the attribute yet.
+  const bool NeedsAppleOrigin = (Tag == dwarf::DW_TAG_compile_unit) &&
+                                LibraryInstallName.has_value() &&
+                                !AttrInfo.HasAppleOrigin;
+  if (NeedsAppleOrigin) {
+    auto StringEntry = DebugStrPool.getEntry(LibraryInstallName.value());
+    Die->addValue(DIEAlloc, dwarf::Attribute(dwarf::DW_AT_APPLE_origin),
+                  dwarf::DW_FORM_strp, DIEInteger(StringEntry.getOffset()));
+    AttrInfo.Name = StringEntry;
+    OutOffset += 4;
+  }
+
+  // Look for accelerator entries.
   // FIXME: This is slightly wrong. An inline_subroutine without a
   // low_pc, but with AT_ranges might be interesting to get into the
   // accelerator tables too. For now stick with dsymutil's behavior.
@@ -1806,8 +1848,19 @@ DIE *DWARFLinker::DIECloner::cloneDIE(const DWARFDie &InputDIE,
   Linker.assignAbbrev(NewAbbrev);
   Die->setAbbrevNumber(NewAbbrev.getNumber());
 
+  uint64_t AbbrevNumberSize = getULEB128Size(Die->getAbbrevNumber());
+
   // Add the size of the abbreviation number to the output offset.
-  OutOffset += getULEB128Size(Die->getAbbrevNumber());
+  OutOffset += AbbrevNumberSize;
+
+  // Update fixups with the size of the abbreviation number
+  for (AttributeLinkedOffsetFixup &F : AttributesFixups)
+    F.LinkedOffsetFixupVal += AbbrevNumberSize;
+
+  for (AttributeLinkedOffsetFixup &F : AttributesFixups)
+    ObjFile.Addresses->updateAndSaveValidRelocs(
+        Unit.getOrigUnit().getVersion() >= 5, Unit.getOrigUnit().getOffset(),
+        F.LinkedOffsetFixupVal, F.InputAttrStartOffset, F.InputAttrEndOffset);
 
   if (!HasChildren) {
     // Update our size.
diff --git a/llvm/lib/TargetParser/Triple.cpp b/llvm/lib/TargetParser/Triple.cpp
index b9fab469f747607..5d4eb79675f8916 100644
--- a/llvm/lib/TargetParser/Triple.cpp
+++ b/llvm/lib/TargetParser/Triple.cpp
@@ -90,6 +90,36 @@ StringRef Triple::getArchTypeName(ArchType Kind) {
   llvm_unreachable("Invalid ArchType!");
 }
 
+StringRef Triple::getArchName(ArchType Kind, SubArchType SubArch) {
+  switch (Kind) {
+  case Triple::mips:
+    if (SubArch == MipsSubArch_r6)
+      return "mipsisa32r6";
+    break;
+  case Triple::mipsel:
+    if (SubArch == MipsSubArch_r6)
+      return "mipsisa32r6el";
+    break;
+  case Triple::mips64:
+    if (SubArch == MipsSubArch_r6)
+      return "mipsisa64r6";
+    break;
+  case Triple::mips64el:
+    if (SubArch == MipsSubArch_r6)
+      return "mipsisa64r6el";
+    break;
+  case Triple::aarch64:
+    if (SubArch == AArch64SubArch_arm64ec)
+      return "arm64ec";
+    if (SubArch == AArch64SubArch_arm64e)
+      return "arm64e";
+    break;
+  default:
+    break;
+  }
+  return getArchTypeName(Kind);
+}
+
 StringRef Triple::getArchTypePrefix(ArchType Kind) {
   switch (Kind) {
   default:
@@ -1143,34 +1173,6 @@ StringRef Triple::getArchName() const {
   return StringRef(Data).split('-').first;           // Isolate first component
 }
 
-StringRef Triple::getArchName(ArchType Kind, SubArchType SubArch) const {
-  switch (Kind) {
-  case Triple::mips:
-    if (SubArch == MipsSubArch_r6)
-      return "mipsisa32r6";
-    break;
-  case Triple::mipsel:
-    if (SubArch == MipsSubArch_r6)
-      return "mipsisa32r6el";
-    break;
-  case Triple::mips64:
-    if (SubArch == MipsSubArch_r6)
-      return "mipsisa64r6";
-    break;
-  case Triple::mips64el:
-    if (SubArch == MipsSubArch_r6)
-      return "mipsisa64r6el";
-    break;
-  case Triple::aarch64:
-    if (SubArch == AArch64SubArch_arm64ec)
-      return "arm64ec";
-    break;
-  default:
-    break;
-  }
-  return getArchTypeName(Kind);
-}
-
 StringRef Triple::getVendorName() const {
   StringRef Tmp = StringRef(Data).split('-').second; // Strip first component
   return Tmp.split('-').first;                       // Isolate second component
diff --git a/llvm/test/tools/dsymutil/Inputs/bar-relink-variant.dylib.dSYM/Contents/Info.plist b/llvm/test/tools/dsymutil/Inputs/bar-relink-variant.dylib.dSYM/Contents/Info.plist
new file mode 100644
index 000000000000000..14d6272d3f8d97f
--- /dev/null
+++ b/llvm/test/tools/dsymutil/Inputs/bar-relink-variant.dylib.dSYM/Contents/Info.plist
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+	<dict>
+		<key>CFBundleDevelopmentRegion</key>
+		<string>English</string>
+		<key>CFBundleIdentifier</key>
+		<string>com.apple.xcode.dsym.bar-relink-variant.dylib</string>
+		<key>CFBundleInfoDictionaryVersion</key>
+		<string>6.0</string>
+		<key>CFBundlePackageType</key>
+		<string>dSYM</string>
+		<key>CFBundleSignature</key>
+		<string>????</string>
+		<key>CFBundleShortVersionString</key>
+		<string>1.0</string>
+		<key>CFBundleVersion</key>
+		<string>1</string>
+	</dict>
+</plist>
diff --git a/llvm/test/tools/dsymutil/Inputs/bar-relink-variant.dylib.dSYM/Contents/Resources/DWARF/bar-relink-variant.dylib b/llvm/test/tools/dsymutil/Inputs/bar-relink-variant.dylib.dSYM/Contents/Resources/DWARF/bar-relink-variant.dylib
new file mode 100644
index 0000000000000000000000000000000000000000..ec2e06a231f88946e6a74540c847fa801fcbbb45
GIT binary patch
literal 8923
zcmeHN%}*0S6rb(32o#qhF+#Xhf(azDZ3#^bMrqTcG$<G#vA1>GE>J1E&F+FoOlUk9
zZ+ at ISa`52IBZ(eN^bhb4;NVdY81EWC-rJceOKW4jX)=$z&YL&y{r1gomc#Db_g_E%
z=pjTRAl;xRKu1G3qcQ};0O*6E#nSF}GFnr<e|VI1hbNfdOC$=+PzecuVmygZI|?J<
zlR?l=pqjQklV1j-QBsW#I>%B_5f??%Tw~j%Hk}{G+nc6qokt<{T+bCGHQy58ZJKw=
zW=SiXD;6v?*7t(p<$X!K7N4tb;y#~&YFakEoUXeGNimy`z9lqerj$?2FX^s+6x0eY
zcocGcpFTgDSl2A5rd`X;&&_0W{0wT~M1gbigpKFf6zkzNp$l;apjfEqW_s}ox~M#6
zBgcu-`2iyf?<?G67j@(QjKb!sRw<hXx?167SUibx<M$)S({0^cHJm2A4685B(lc%1
zvD=~v&tZ6L49{s3PcIZ~W2<?;2MlkX;T^Pz=eV|)(a7J}6AJW>;f<YTMvFny^lG(Y
zXr{hlI90vah<C{FMp*vg-{3(`BVObw1>*l#k>M7FF*mQzy<3ITZN^(;cnd6ktxY_u
zaJz^pjrHv_Jig!kKj5*;ia{_S7!V8y1_T3w0l|P^Krrx6GZ294df@?&KR4rZS}#7R
zr9eH=3c5|;XNNn)C>Rh72nGZLf&syRU_dY+7!V8y1_T3w0l~n3#sIdrg9N)=k|cdo
zPT~Ns1F+{S5qR<+w+(2~uB%>?4BEE={-WS?Nba5s1R)+<#rPV55ZZL-5&jmux6FP@
zFa|xl)4Nm;!KUmb&^^yf$V;?+jr_nqIIe<9on112Ga<hQM<^Kd2TIl(jFK^yNPW^d
zr9UJq_wOlRc9qDPA*D|`)d9s$5?RUhPY+IoFNOo~wSqhXj?3Y27z$Gf27TNeOby5i
z24En<rLjL6Emokv9NjW(r)-(gL{g2b@#v`M9Zw|VFjFVvYGUj-cQH&Z7j+ksoLIhS
zl?)a7t+9+{x`ydGv8=IWRII9D$8J<~cg3<doY-}}xUiI0tIXkxS<24w<-{ah(J8GH
z8eN~pa%OeYb)bwLQZ`*Ihs-XeXW7}}hP>}GaHPHt@)Lx|;DMszw;L!t25pRcb?agH
zE$9W9<97uf?=bTIHJ%veOn{<rTz-9E-4nbKB+>!j287@*3>F*^NW4a|@sKeGPZaLb
R=c7|zMSeI~X(|&-`~`Fg`G)`i

literal 0
HcmV?d00001

diff --git a/llvm/test/tools/dsymutil/Inputs/bar-relink-variant.dylib.dSYM/Contents/Resources/Relocations/aarch64/bar-relink-variant.dylib.yml b/llvm/test/tools/dsymutil/Inputs/bar-relink-variant.dylib.dSYM/Contents/Resources/Relocations/aarch64/bar-relink-variant.dylib.yml
new file mode 100644
index 000000000000000..68fd250cdf2a8a7
--- /dev/null
+++ b/llvm/test/tools/dsymutil/Inputs/bar-relink-variant.dylib.dSYM/Contents/Resources/Relocations/aarch64/bar-relink-variant.dylib.yml
@@ -0,0 +1,8 @@
+---
+triple:          'arm64-apple-darwin'
+binary-path:     bar-relink-variant.dylib
+relocations:
+  - { offset: 0x26, size: 0x8, addend: 0x0, symName: _bar, symObjAddr: 0x0, symBinAddr: 0x3FA0, symSize: 0x8 }
+  - { offset: 0x3F, size: 0x8, addend: 0x0, symName: _baz, symObjAddr: 0x8, symBinAddr: 0x4000, symSize: 0x0 }
+  - { offset: 0x4F, size: 0x8, addend: 0x0, symName: _bar, symObjAddr: 0x0, symBinAddr: 0x3FA0, symSize: 0x8 }
+...
diff --git a/llvm/test/tools/dsymutil/Inputs/bar-relink.dylib.dSYM/Contents/Info.plist b/llvm/test/tools/dsymutil/Inputs/bar-relink.dylib.dSYM/Contents/Info.plist
new file mode 100644
index 000000000000000..37c2a8aebe4c6ff
--- /dev/null
+++ b/llvm/test/tools/dsymutil/Inputs/bar-relink.dylib.dSYM/Contents/Info.plist
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+	<dict>
+		<key>CFBundleDevelopmentRegion</key>
+		<string>English</string>
+		<key>CFBundleIdentifier</key>
+		<string>com.apple.xcode.dsym.bar-relink.dylib</string>
+		<key>CFBundleInfoDictionaryVersion</key>
+		<string>6.0</string>
+		<key>CFBundlePackageType</key>
+		<string>dSYM</string>
+		<key>CFBundleSignature</key>
+		<string>????</string>
+		<key>CFBundleShortVersionString</key>
+		<string>1.0</string>
+		<key>CFBundleVersion</key>
+		<string>1</string>
+	</dict>
+</plist>
diff --git a/llvm/test/tools/dsymutil/Inputs/bar-relink.dylib.dSYM/Contents/Resources/DWARF/bar-relink.dylib b/llvm/test/tools/dsymutil/Inputs/bar-relink.dylib.dSYM/Contents/Resources/DWARF/bar-relink.dylib
new file mode 100644
index 0000000000000000000000000000000000000000..9ebd56ecb00a482b3694f1ef2f27dea726effc43
GIT binary patch
literal 8923
zcmeHN&rcIU6rSz22o#qhF+#Xh0|`xJ+Y(3&{-8~Z(tu!u#NO6zyFjJvHoFTbF at YFk
zJgSKa2M-)Pc=Jf2F(!I7 at eknWK@S at 5nyByX%#@|I5pSBzBd_!3&3oUz`DQunzJ34g
z%a0C1Bm&Y7dIWSZgfl9AF!X?~KmHI4zB^aA`(!&baPQUhF!OtfM1dJ9ApuZ~ClP8#
zVFY~A3;GFE)8;4g^I+6Vs at _58SPClQqG+0H+;pi;=Lhk2#_3w?en>6Xa|OwkZwc^L
z&GoWb(#qz71q=1{J!5!zUlOmy=c<{w&uvgm%ckekH8&wCX7kavgr>}t@`?E+-PQMl
zn&AcaLk{lK=SLIkngrFf>D<iJL^j9IU<;fma891E at id!aJ-jA#Ax;kz3-w$}U%iMf
zDi7GmaiVm-$H>C_3isGX-MBxau)3&K%BF#?W_TGEPomuT{mAijTQ?UCrvWd+>PxWn
z%pvjEZP9?|FuWy(=NuAGFBEKJt#QA53~z?v?Hv-&acwW7p1;^b3iOuY#ZEG#$)IU^
zwOTPWQ(rNhs$Q(e`^@nAS^nq0!GoN7yvQR8#Q(1%r<xST+`K;bRuxXS5pRj%&9eBV
zL*iM58%0d1uWy&(@%`@p0gqi)41xi{fM7r{AQ%t~2nGZLf`NaUfdEw32 at iPuxf!3+
zI`Kg*1?q`b&}{-g8{8pA!GK^uFd!HZ3<w4U1A+m;fM7r{AQ%t~2nPN$2C%&yB-rJW
zB<Z_y6bE=6fIVM{z?1)wZ9t25S at oJ^(7p}u7X`;da{E*u2=Uk|#@7gh(55?&@VDT-
zW%g5oG3eQ?-laMSHf7I)?s#58o}=w+<Og=aaS2pvZIk(%3Hc>BLcyRvP_kZQl#H=N
z>XHVO?vSk9xvhNNR3az(lrHI53luv-WF^-<-a8gP8xFwN3UWU<E`-BjC`=_7^l`H{
z)gvnyfPn~?#{OuuSb_d>bj`4xvSmh-qiRA;L<c?ZP;xW at Gj$}PCSwP=i(_)RsJoEl
z#Pda~WT?<@jb|*=HB8ruXN@(ZVpR=0ex;(j3zog&#4qc`*}1%0We#7=Ty}~tCr99l
zPHCCY=-M=%Gpnnv17&QGvgu+uWO6P&$<7ux<b9WcBlWeApCCL24-^%@-9X_nXk*-q
z>-WQNK+nJ&zbo)~hmrTM at x(A^7!-x$^6LZZp5TojkrwziAOwG5u;73|5?d4-4;gdt
UMBy%dIymN4<cEWmhBC3lU-{Jf7XSbN

literal 0
HcmV?d00001

diff --git a/llvm/test/tools/dsymutil/Inputs/bar-relink.dylib.dSYM/Contents/Resources/Relocations/aarch64/bar-relink.dylib.yml b/llvm/test/tools/dsymutil/Inputs/bar-relink.dylib.dSYM/Contents/Resources/Relocations/aarch64/bar-relink.dylib.yml
new file mode 100644
index 000000000000000..d47e5f9e2e8d276
--- /dev/null
+++ b/llvm/test/tools/dsymutil/Inputs/bar-relink.dylib.dSYM/Contents/Resources/Relocations/aarch64/bar-relink.dylib.yml
@@ -0,0 +1,8 @@
+---
+triple:          'arm64-apple-darwin'
+binary-path:     bar-relink.dylib
+relocations:
+  - { offset: 0x26, size: 0x8, addend: 0x0, symName: _bar, symObjAddr: 0x0, symBinAddr: 0x3FA0, symSize: 0x8 }
+  - { offset: 0x3F, size: 0x8, addend: 0x0, symName: _baz, symObjAddr: 0x8, symBinAddr: 0x4000, symSize: 0x0 }
+  - { offset: 0x4F, size: 0x8, addend: 0x0, symName: _bar, symObjAddr: 0x0, symBinAddr: 0x3FA0, symSize: 0x8 }
+...
diff --git a/llvm/test/tools/dsymutil/Inputs/basic-relink.macho.arm64.dylib b/llvm/test/tools/dsymutil/Inputs/basic-relink.macho.arm64.dylib
new file mode 100644
index 0000000000000000000000000000000000000000..a813562d59671ca36aa860a69b007b7719ec669e
GIT binary patch
literal 50992
zcmeI5Yiv|S6vt0 at x3x-NV2zOSSe`*C+Xgno;DZI)2tt5JLuyF4?4zZdZg-n~SPBRm
z1OrhcMNRnP2jK&lpeckXC_)X7#7I<>M`Egypnx$LNK6zGz;o`MX{YNpH6h`P|ABL7
z{xfIJocYbY`)$&1ZePD!LR3Ipir6aH+C4;D?H17}*4ud0vKs0e8(8F)Ku(9!h1 at O1
zq3mK=>87=5CAi9sS24#KYgaC!UH$G7C~Hc~N~JTQR9{zaysV1Hd$WsZGhVTZr^hWT
zoJuF7 at iodnH{Kg6o?DG;t>l2%(q~zjct<oIv7+(jgslhi+o9s={faj8({Xhz=djC;
zQ#ZF^t~Gz at lI6~61eC`hwd5-%2P|i6S!)u;F|f`bub6%95^&}#Wxpf#%c434=B2&3
z&Z>4m)j8VCOFS$q5=;k`udOAoey!u__eu0nycXDT7B5_~sJ?EYes_CR%z&zuu6 at YS
zvNv;orL3P~8=2D|3Z|mr>B**8G~ViK3x-<~zF at L#mfsiYj7394ekLHisfTDaS2LAf
z&06x3+$Cl=>sqc4pWuF8co?^ru}OJSnS4hzY-V082b6A}pN~fsd&xSdHVr>LZMlET
zcK5N`^PVqXnZbQtHYa8ox616coC_8G<(9SW{6%w-??iKO){&V7RFg?1Yk0?E%R5u)
zrZ(R^%|PZ&VUsxfdWhtmdO~U0x0Eq#_ByASL%t2zUU+~22!H?xfB*=900 at 8p2!H?x
zfB*=900 at 8p2!H?xfB*=900 at 8p2!H?xfB*=900 at 8p2!H?xfB*=900 at 8p2!H?xfB*=9
z00 at 8p2!H?xfB*=900{hF3EWwK{DV7g>f-(HpxWoU`0ngGch-Ngug7g&xHq59-Ycgg
z*UAG&iVJD at HEv(xHurbQc%UHrqV}6g*%2~6s4qFbeD}4x!WFnhu5lNZE^_YUj^@SX
zD(ob62vV!7u`a$W>yo?ia)($<-*cC?S>zsX3E#l?IyZb>9JAmV?yKXv#c}i){#m1q
zCJ2B42!H?xfB*=900 at 8p2!H?xfB*=900 at 8p2!H?xfB*=900 at 8p2!H?xfB*=900 at 8p
z2!H?xfB*=900 at 8p2!H?xfB*=900 at 8p2!H?xfB*=900 at 8p2!H?xfWQMLVE?`E2fQYh
z0|5{K0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X009sH
z0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5coF%FLy0tYh)`>
z#+6+>svfCoUD-NNL=@0HYOYIZt38uWal62xY0~AUa~t{b_eSziHp^bFB$chBN8PkT
z`uA at n@&se)=0t)X4h3mcB${fE1v_cH^h{x=(ca=oL{mA`SWa^B90}^I8Ihz_ at pB!~
zg6n5<wCu5&cUjqc)pnDqK7LfFc$KUt8Cu49SsKkIMf8%KadZ7H9&ZsxRn~KD=CdV7
z?`EAZpK6uQ7#^2=wAT4}xnGLT#~hdaXg;5?kIdIv&o8!T_s=)S&HePUpShnCtj+zL
z$<fzY=i5(%+K;>*l8 at FpA7Ly-wD2{@&3vkO%*>~dwV6*@j;>~%FQ2t4pGSB-$wzB$
z+UK3iM~|2DxR*^A at i+66{grd4&R^n-Hs_b~XG2*wF7m#~xPJfSyhZEtoWPnT|946a
zS7KhW)YoE#f=S}XI<oXPW63w;e1OulGVx5RDMB?1<ML6~P$-y+hNmZ+V$pc3uPqpE
zN%(@vwpo5(xX))$mqecnacCVRY>G%{EE?)_GrTydeCaqF`46E6IvSZUg8u1-7?_DM
zkWe`3_D>}}{97bHQJQfj_wg~h9w(QFEB;5+!6rW)Qc8(Vk=I2fjvVsYt~~~2>ZJM6
zXXCHz-LUvTm1p9?Gtra3_*U1)CVzV4*zLzEzdrQix4j>3+JCSyar(FB9?!+IXIouM
z8w>AkIJ9Bi)*n89eZltXy+e(A-#)$SN=MnQ%a_LVw!XTetKNSr^U{IiFTWSRF}>=r
zH~jPY-(S1=ZnOLS>Y`bHhQ~GEEFE_E+#h?sTe<ntuRC3bt`8Oee#gsv<8H0k)3x)f
zkKddyV(MF0SI$Vy?mjv1$c^X6PJY3?dH4OsA8P*7yY80UO&z^lcVg!G1I?v-6CFn<
U#^<k^xvl=<Z2$Lb<(Hi3AJ02HlmGw#

literal 0
HcmV?d00001

diff --git a/llvm/test/tools/dsymutil/Inputs/basic-relink.macho.arm64.o b/llvm/test/tools/dsymutil/Inputs/basic-relink.macho.arm64.o
new file mode 100644
index 0000000000000000000000000000000000000000..b1b517d11172fd24d038d0d7dc8fde8b2084be34
GIT binary patch
literal 2176
zcmb7F-)|IE6uz^wyDcmXKPmwugf&*951rj5MH`9G4K1{^q)m6Di$<@rv(vJ&JG0rD
z76>FIJn`UzB=E#P00|^K@<5^{Jm`bbC-6ZCPsSIc(Kk)i at 7y_eTP8*8NzVPwJ@=e%
z&YgSi%(s91{MQyC3<04b4IQB&4~4u4y=N+O-J!~BHOhhLc^_=j962FUM&7w7w&Qtq
zyjESEYilnX#Fv777bNNtX>m!%5K8HWQMc(Yuv5xs`81C%J>vQ_2XU_zDH~pWaX~uu
zde>Vb{;~JUbH{oi``P-K at oa(*?q?`9U(=rtC?(0a%se6EBj)=`@Ao-;*tE(>^8Lm<
zKQf-ku(1k>`kYRu<w at UZdsIV`?|an|Lex0Fm|Z1eYhAve{)tQLNxmXS4|4LA4f3h_
zI*yy<t0wqvZ;&rK-&uFR=a_Gv>-+9M`P`t5x+1ygpKbaLDW}IcRl!r{%d>NY&-E#g
zUoA((0lHsWP2VF=a=-B<!2M#r8hA*4dJf+KtnGou&$3{V#!W^3Uy(;!ob4B)2&8*D
z3nigeB&A$xBd!<L#%1Ng=eJf&aTOV#K?$#|T=??l7p8nTGbM~2#;evq#<VV9w0>E(
zw(ow)+F|TOL8)OeIq-JwP%eckO~aTRKrJuB_ZBM53<}daoXf$?l9|gLhS_He${pQf
zT9kN%K3R0<XbVF0tLnFi0_+peJLH7ik3o&}u}B at oU}QF#y)VZM9O-v4m?HB4kTtSj
z1N!^;)eAwPM*9hkrYO^W%DXMcU&t?c-LM(>`O-nVXczOZEALS0U=cHWxM-K&5OpVP
zx<g$L2Y$wGJMQVgcDn61hiz9Bh^py25h%h!%?%o!joVr{8u*dtM`2;iTk={#$Lkhm
zTTV0|blYL!q~p$1YIcVmYho&6Q+l~HjOT}qGa`=eO$(ELXE6$ed)n!u^~!T|<x{dU
z`Tn at 9o|+w(Qiw(~1oe3_Q7KQ*8>QwY#lJ%d`3!W_-w<+Sb_sFg_%}O8U{63FLn(&(
zl0>~U;D>6480J-{1>btS|0hP*_X6|Ne}L-4S)ws=y*l0e^@|^bpZ+k4^$L^@nrfiK
zAA~~a(8)!uz%E!U+%0K6*GP9Mt#)e|#-G+!0U#2n at o#6Z@;CK94ZAYw&A(@isZ>7*
zXl*+bcXEi{4;<6DzJ%|56l3-f5ZT$+cn+ZT>=DLSfR<vSm6*>$g6{f#@U5Niruk+e
l^!JQXx2?&?67jE!)SV(#N42C)zpPf&?i^5KNsUFF at DKB93~c}a

literal 0
HcmV?d00001

diff --git a/llvm/test/tools/dsymutil/Inputs/foo-relink-variant.dylib.dSYM/Contents/Info.plist b/llvm/test/tools/dsymutil/Inputs/foo-relink-variant.dylib.dSYM/Contents/Info.plist
new file mode 100644
index 000000000000000..7e84e95bd3f48cc
--- /dev/null
+++ b/llvm/test/tools/dsymutil/Inputs/foo-relink-variant.dylib.dSYM/Contents/Info.plist
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+	<dict>
+		<key>CFBundleDevelopmentRegion</key>
+		<string>English</string>
+		<key>CFBundleIdentifier</key>
+		<string>com.apple.xcode.dsym.foo-relink-variant.dylib</string>
+		<key>CFBundleInfoDictionaryVersion</key>
+		<string>6.0</string>
+		<key>CFBundlePackageType</key>
+		<string>dSYM</string>
+		<key>CFBundleSignature</key>
+		<string>????</string>
+		<key>CFBundleShortVersionString</key>
+		<string>1.0</string>
+		<key>CFBundleVersion</key>
+		<string>1</string>
+	</dict>
+</plist>
diff --git a/llvm/test/tools/dsymutil/Inputs/foo-relink-variant.dylib.dSYM/Contents/Resources/DWARF/foo-relink-variant.dylib b/llvm/test/tools/dsymutil/Inputs/foo-relink-variant.dylib.dSYM/Contents/Resources/DWARF/foo-relink-variant.dylib
new file mode 100644
index 0000000000000000000000000000000000000000..523f85712de567adb16857bb2603c07d64bc4638
GIT binary patch
literal 9196
zcmeHNJ8Tn47 at qZdlMp)#1OY)%EH44#upJa6;B=612E`;igG5Aeduw|WnV4P6y9u0h
z5(p at u195Gn6clubiUOKQAR!tmI$CsBfRIvx;O_f(W*mE+=yKN~%}BHVWB&h}na@*r
z9&bK>{FY`+V<_FI9jNz`Wbv{Yq7U`hlMm+}7`gi0-lua at htBNXFZ@v=GhtC>EP+b#
zYz@~f$ki}6q5g$x+ZT?HUw{%XgK-D94G5})OU1TB_gctxZnxr<kMg$sVn`!5awXY~
zrY7J`dsi!7*{*mKJ{scVdnEA2o08;Mnp_Q)<~fXN+oOfkBggXvIoClE0zRT5WLB8O
zBj=Jk2&YdcoczV1^Cv_U#95(A9E;l at 5KE;KmDE*apxAcVEly9`)r#kGduhDcC>kG2
zDoaa==hPi<(hb_iH!H^Xt4N=<md24 at i6`i9!}}`mUWkORE5vh(#kxDw&fokw4m2w8
z=C=xE86n3Pg!L#Q{(JPC=ZWt{e$TdLfP~w&om#Ex+MaX84Qfs)j<+E2c8K_e|AL2{
zINpXa4kXv_hV24)86n3P{#L`U+m7c6yh|eATOpobyj-G``1oE4JUQQ2|AHsFRYEbK
z7*Gr-1{4E|0mXn~Krx^g_#X_=UUoG$p0~w5m(BplmiuV at V|S|Igzqz(KB_1N6a$I@
z#eiZ!F`yVw3 at 8Q^1BwB~fMP%~@EtNxz?hSaZr?Ob`(pNx!1kZ+qBVvc|Gv75tK+Fm
zba{ts<%B#KSZ{Q8j~HDeM)xyA?>L$0LMC0RCfTl~!T2#k8=gFPAiP^fss--{Ao0ug
zE at +E~5>{lje|UTm4Ln|A%ge=h#xHOrBWG7M=`_p1`U!O|@-p at qQqI_d-k3fan*Wr(
zI^BipiTmkiWEs)TXmTF9k!0;XyhMZS;S_Z0p?RE%W<&GeqIt20cVxBppsm$*n(GYR
zy!pHN>AJaQ<7RWM){AExi42;0JN~@BX|PW>52t=i71kZavjTm9B^nOQe+SdeBdJsh
z&}@kArma#Hcl*|iTMsI}XZ0V*<T5#HcjVpIe;@}dGmy*l?`d5hSxT;yoDfMtcD&@5
z-3;!!vp at S@=z3w0&AT&h)vvkr?AfY=Bc=M4AbZLwof#X?)P$ocW-LD<oBIdQV^E%A
zJi1|K3tnwH3}_gv>X)1<t9T)cuQPFc1;Jy6$A*T*3a2Tvbo2$UkQ&~<{EZ at GXz@{v
z$50BzzuwZha5uP<ItZO!eMG+&<R7S1qV)kuuVtu6T-ks0QU-ongw(f=w=M=tL8Es#
hjOA`{?0M)k4q97S%nx at TPCs8%p|v2B9Un2x>K|G$6=DDY

literal 0
HcmV?d00001

diff --git a/llvm/test/tools/dsymutil/Inputs/foo-relink-variant.dylib.dSYM/Contents/Resources/DWARF/foo-relink-variant_debug.dylib b/llvm/test/tools/dsymutil/Inputs/foo-relink-variant.dylib.dSYM/Contents/Resources/DWARF/foo-relink-variant_debug.dylib
new file mode 100644
index 0000000000000000000000000000000000000000..523f85712de567adb16857bb2603c07d64bc4638
GIT binary patch
literal 9196
zcmeHNJ8Tn47 at qZdlMp)#1OY)%EH44#upJa6;B=612E`;igG5Aeduw|WnV4P6y9u0h
z5(p at u195Gn6clubiUOKQAR!tmI$CsBfRIvx;O_f(W*mE+=yKN~%}BHVWB&h}na@*r
z9&bK>{FY`+V<_FI9jNz`Wbv{Yq7U`hlMm+}7`gi0-lua at htBNXFZ@v=GhtC>EP+b#
zYz@~f$ki}6q5g$x+ZT?HUw{%XgK-D94G5})OU1TB_gctxZnxr<kMg$sVn`!5awXY~
zrY7J`dsi!7*{*mKJ{scVdnEA2o08;Mnp_Q)<~fXN+oOfkBggXvIoClE0zRT5WLB8O
zBj=Jk2&YdcoczV1^Cv_U#95(A9E;l at 5KE;KmDE*apxAcVEly9`)r#kGduhDcC>kG2
zDoaa==hPi<(hb_iH!H^Xt4N=<md24 at i6`i9!}}`mUWkORE5vh(#kxDw&fokw4m2w8
z=C=xE86n3Pg!L#Q{(JPC=ZWt{e$TdLfP~w&om#Ex+MaX84Qfs)j<+E2c8K_e|AL2{
zINpXa4kXv_hV24)86n3P{#L`U+m7c6yh|eATOpobyj-G``1oE4JUQQ2|AHsFRYEbK
z7*Gr-1{4E|0mXn~Krx^g_#X_=UUoG$p0~w5m(BplmiuV at V|S|Igzqz(KB_1N6a$I@
z#eiZ!F`yVw3 at 8Q^1BwB~fMP%~@EtNxz?hSaZr?Ob`(pNx!1kZ+qBVvc|Gv75tK+Fm
zba{ts<%B#KSZ{Q8j~HDeM)xyA?>L$0LMC0RCfTl~!T2#k8=gFPAiP^fss--{Ao0ug
zE at +E~5>{lje|UTm4Ln|A%ge=h#xHOrBWG7M=`_p1`U!O|@-p at qQqI_d-k3fan*Wr(
zI^BipiTmkiWEs)TXmTF9k!0;XyhMZS;S_Z0p?RE%W<&GeqIt20cVxBppsm$*n(GYR
zy!pHN>AJaQ<7RWM){AExi42;0JN~@BX|PW>52t=i71kZavjTm9B^nOQe+SdeBdJsh
z&}@kArma#Hcl*|iTMsI}XZ0V*<T5#HcjVpIe;@}dGmy*l?`d5hSxT;yoDfMtcD&@5
z-3;!!vp at S@=z3w0&AT&h)vvkr?AfY=Bc=M4AbZLwof#X?)P$ocW-LD<oBIdQV^E%A
zJi1|K3tnwH3}_gv>X)1<t9T)cuQPFc1;Jy6$A*T*3a2Tvbo2$UkQ&~<{EZ at GXz@{v
z$50BzzuwZha5uP<ItZO!eMG+&<R7S1qV)kuuVtu6T-ks0QU-ongw(f=w=M=tL8Es#
hjOA`{?0M)k4q97S%nx at TPCs8%p|v2B9Un2x>K|G$6=DDY

literal 0
HcmV?d00001

diff --git a/llvm/test/tools/dsymutil/Inputs/foo-relink-variant.dylib.dSYM/Contents/Resources/Relocations/aarch64/foo-relink-variant.dylib.yml b/llvm/test/tools/dsymutil/Inputs/foo-relink-variant.dylib.dSYM/Contents/Resources/Relocations/aarch64/foo-relink-variant.dylib.yml
new file mode 100644
index 000000000000000..0bc06e9a9e857ac
--- /dev/null
+++ b/llvm/test/tools/dsymutil/Inputs/foo-relink-variant.dylib.dSYM/Contents/Resources/Relocations/aarch64/foo-relink-variant.dylib.yml
@@ -0,0 +1,9 @@
+---
+triple:          'arm64-apple-darwin'
+binary-path:     foo-relink-variant.dylib
+relocations:
+  - { offset: 0x26, size: 0x8, addend: 0x0, symName: _foo, symObjAddr: 0x0, symBinAddr: 0x3F64, symSize: 0x20 }
+  - { offset: 0x33, size: 0x8, addend: 0x0, symName: _foo, symObjAddr: 0x0, symBinAddr: 0x3F64, symSize: 0x20 }
+  - { offset: 0x88, size: 0x8, addend: 0x0, symName: _altfoo, symObjAddr: 0x0, symBinAddr: 0x3F84, symSize: 0x24 }
+  - { offset: 0x95, size: 0x8, addend: 0x0, symName: _altfoo, symObjAddr: 0x0, symBinAddr: 0x3F84, symSize: 0x24 }
+...
diff --git a/llvm/test/tools/dsymutil/Inputs/foo-relink.dylib.dSYM/Contents/Info.plist b/llvm/test/tools/dsymutil/Inputs/foo-relink.dylib.dSYM/Contents/Info.plist
new file mode 100644
index 000000000000000..e91926013155858
--- /dev/null
+++ b/llvm/test/tools/dsymutil/Inputs/foo-relink.dylib.dSYM/Contents/Info.plist
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+	<dict>
+		<key>CFBundleDevelopmentRegion</key>
+		<string>English</string>
+		<key>CFBundleIdentifier</key>
+		<string>com.apple.xcode.dsym.foo-relink.dylib</string>
+		<key>CFBundleInfoDictionaryVersion</key>
+		<string>6.0</string>
+		<key>CFBundlePackageType</key>
+		<string>dSYM</string>
+		<key>CFBundleSignature</key>
+		<string>????</string>
+		<key>CFBundleShortVersionString</key>
+		<string>1.0</string>
+		<key>CFBundleVersion</key>
+		<string>1</string>
+	</dict>
+</plist>
diff --git a/llvm/test/tools/dsymutil/Inputs/foo-relink.dylib.dSYM/Contents/Resources/DWARF/foo-relink.dylib b/llvm/test/tools/dsymutil/Inputs/foo-relink.dylib.dSYM/Contents/Resources/DWARF/foo-relink.dylib
new file mode 100644
index 0000000000000000000000000000000000000000..94480df788f119b27746827f6ace437ef091891c
GIT binary patch
literal 9292
zcmeHN&u<e)6rS~ZlhkXLUqTH^52g*Ok;vLX394udiE5&x4wRB0q8wN at _JRy%*Ya*c
zE0936s_3ni_yagJr>gYW11C6E6>veEkPsItRTZemf?B?}GvnB6N6I0`8EN*-d-L8m
zGoN=Q&%Al~@8ADr8Pga_2DK0Mhcs!t3_%Q{j*Q=Wyl3^38 at K*C{q4^~cb*&&_BfDP
z(5Nz&LM4B;jWHdf2uT>bQU64BocW^*^JpZ?MAE=@1A;2yQgNKf`zqpXu6N?iAK`to
zYc8$W*pz11+q!_a>|d_=Rj1~k3(%3A-)(_+wk=4`rOni8(mJP69cOmtc=>2)My_>2
zxPXti2w4^?@yNO42ErKxfsRu;J$Z6UctM;HO^K7^`mFfP`k at l<?{G8XtKQP`d8c0U
zJu<C_w<`QuPBwZ=iRU(5|GXD=;jN1KofYA$x!yR^D)9vUU3kWq-1DgjF!spE-csVZ
zOG`~}rF*^41zuHzKi?o;7&YUFB!5#UInXPCH}$?~tRo!9Z8Ykh<GYu<u;Esccn9Zr
z;IN24_`y0r!rXxeTM}<k;K@&Baf5i#*A4u--FOcK-l7=)!3Obyr3)1bNzN}Xz7M(H
zyle=3B at _dS0mXn~Krx^gPz)#r6a$KZ&0~P}vRkq7yejs&bOu1W+(&N}dL;Vs58kau
z=YoJa at _`-na_Gqo)#go2At?qF1BwB~fMP%~pcqgLC<YV*iUGxdVn8vlNeoarG|edK
zrfJ%1YYPc%|0x%(G3 at Y1njTWe7wtHChqQ7^9t`X<`ZHx?ploFB8hYR72J8FI&@<&!
z8VHnpPqPnugYx5pE?jv4LAc)-ro>GR0B=8#c+!0Ut+m66e5`dpxc?P&aDR!tUT*O+
zJkv4EK)m=YD?<Ae^>%D!>{m#+avHToLk@}-{6<fm@}+v}$Lw9w4ANLyo}17_wBQ~+
zGt^`JL60;$1JOD3BUt3nr_iRM+ZT{(SG3?6x;35Bu{87x(u_DcD at V|_YkRGohHl-s
zYQ4N>ZF_gf+OF-uJ&%-)t{r_ZuI-)})U8A2$L7q=Be-{<kFiwCfZ5rsr<*a%bnCEb
zni!HzQc^otspC>WZpCYcwZPAfj at w1Mn9Il3k<sxYG<&RQkM8Syu?iGitGE$@!oor&
zsCqV%<b}@yKl1!2ER?(zuO2kKX5mEL#o1HyQdl_VR=${9up7eA<}+6+%kI%Jj2Kog
zGVa|{3p0LWISOeStR7U{I<@36R?UxC@*NdNUJ%@UdTw%Bd?mDcmW`jF9#X>{n*ULx
zj}9Bvqz{FVAH{qh-ZbCbAM<~Ium7JCbV`a>QRDXtl5X2jiQgYcnSFnTHpTyfN=1&z
z=OJ$5z)o)%%}d8!8iSc=(LEpB&bfZm{0Nd>M*6_$%^YUzr~IMp<FzJQ9mu37S3 at g#
E3#bn*PXGV_

literal 0
HcmV?d00001

diff --git a/llvm/test/tools/dsymutil/Inputs/foo-relink.dylib.dSYM/Contents/Resources/Relocations/aarch64/foo-relink.dylib.yml b/llvm/test/tools/dsymutil/Inputs/foo-relink.dylib.dSYM/Contents/Resources/Relocations/aarch64/foo-relink.dylib.yml
new file mode 100644
index 000000000000000..0db1b30e9d126ee
--- /dev/null
+++ b/llvm/test/tools/dsymutil/Inputs/foo-relink.dylib.dSYM/Contents/Resources/Relocations/aarch64/foo-relink.dylib.yml
@@ -0,0 +1,10 @@
+---
+triple:          'arm64-apple-darwin'
+binary-path:     foo-relink.dylib
+relocations:
+  - { offset: 0x26, size: 0x8, addend: 0x0, symName: _foo, symObjAddr: 0x0, symBinAddr: 0x3F54, symSize: 0x20 }
+  - { offset: 0x33, size: 0x8, addend: 0x0, symName: _foo, symObjAddr: 0x0, symBinAddr: 0x3F54, symSize: 0x20 }
+  - { offset: 0x5B, size: 0x8, addend: 0x0, symName: _foo_unused, symObjAddr: 0x20, symBinAddr: 0x3F74, symSize: 0x8 }
+  - { offset: 0xA1, size: 0x8, addend: 0x0, symName: _altfoo, symObjAddr: 0x0, symBinAddr: 0x3F7C, symSize: 0x24 }
+  - { offset: 0xAE, size: 0x8, addend: 0x0, symName: _altfoo, symObjAddr: 0x0, symBinAddr: 0x3F7C, symSize: 0x24 }
+...
diff --git a/llvm/test/tools/dsymutil/Inputs/proxy-relink.dylib.dSYM/Contents/Info.plist b/llvm/test/tools/dsymutil/Inputs/proxy-relink.dylib.dSYM/Contents/Info.plist
new file mode 100644
index 000000000000000..425df2f6c841d8a
--- /dev/null
+++ b/llvm/test/tools/dsymutil/Inputs/proxy-relink.dylib.dSYM/Contents/Info.plist
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+	<dict>
+		<key>CFBundleDevelopmentRegion</key>
+		<string>English</string>
+		<key>CFBundleIdentifier</key>
+		<string>com.apple.xcode.dsym.proxy-relink.dylib</string>
+		<key>CFBundleInfoDictionaryVersion</key>
+		<string>6.0</string>
+		<key>CFBundlePackageType</key>
+		<string>dSYM</string>
+		<key>CFBundleSignature</key>
+		<string>????</string>
+		<key>CFBundleShortVersionString</key>
+		<string>1.0</string>
+		<key>CFBundleVersion</key>
+		<string>1</string>
+	</dict>
+</plist>
diff --git a/llvm/test/tools/dsymutil/Inputs/proxy-relink.dylib.dSYM/Contents/Resources/DWARF/proxy-relink.dylib b/llvm/test/tools/dsymutil/Inputs/proxy-relink.dylib.dSYM/Contents/Resources/DWARF/proxy-relink.dylib
new file mode 100644
index 0000000000000000000000000000000000000000..c79d8f7825b58cc9ad52b2d9d014ee99089a5e4a
GIT binary patch
literal 10046
zcmeHNUuYaf7 at xhny}RV%*|dZ<ZG;n3tzz#INlIEF$<ajfr?xeTZCXpGdw1L9+RN>6
zyJ at Xf8Z49uMGz|#DilFPP!Rg42>pW(3R=ZKeeuZ`MG-|GEDGxH+nKp+Hg~2z`La{K
ze1GRR-+Vi_bY}MEA3y!o!kEU;nn7{Uktk`RZ35c>dTOlo!;XRN&IgCC6w{qMetbmQ
z-Ht2?jfk-jh~n8Afwcg>4{AGT5y6~K4Np%|fUgbubgAm#L=mZT?wHRwQUUYhbqok!
zX(`0bsisEQLQRIix$Vs7?3&4sw<z&Yqgtamsuq`c%FlV;cB;klj12JOU66QT1>oae
zY;tivUp`qZ7kIIJ)N=LZ^}8tXW<5B543Eow4i{aVq3l$a at 7%L{Qap`88Kt;X6{CEK
z=y~IjBCi?C^BADl$D{S6ns?5$#KhVWURobZd8r=Y3sN4G+{e6mk&E+!;TTInBCjP~
z;i>gRp4I9#f*8(sjqV;F9vW3^_bT;7qhe5#{A;1PbMwz{1Cm8P`?C{|$tbYTq^NLG
zLhp|WPK at T*BvhK8nVX;CrDEA6QzN`SHF!#PY`_$rQ8mglro95M?{m at ds_fr)Zv!A{
zR(Nu`uE4u3 at m`Yo-M&LSBbTe1Csxk)+!tctcjfr!?z^-6 at FR5t{q^hpQuIG2^Xu(g
z4bP}lN+vHGbEaJ}@_xL_Uy1$-=JMwMfQL{&-VKTOj)b{!hj`AZ3ZCvtJWDRvw<Vr+
zzZ4oU&c%GK+_5}``19L%OLSE8-S|KQpuikdAgDl4fuI6G1%e6$6$mQuzf^$sKHj}!
z$13_Z`0vL5jSF($*)R1zsqZA6Hg^jkG}=2+yxNyPDfK}a&se5nII|hY%H)jd)~bn(
z&GB^MRH>L-@*K6S<sNR792gl#ANunw<AtJKDH*32CwtI>3Ir7hDiBm4s6bGGpaMY!
zf(ir`2r3X%AgDl40dEE9Iy1s(SFdT>pUJz3(bX47W6nuyYsoxemelTh&dASNX`?!~
zttahX|KMUWq_*~LdZhU`T^kR at 0YcmR2%}q|I=G&lehoz(AhhY>=J8Mj-A4Zn!gC~0
zgHUG*>-AXkSv at kYH@~lkqhoG9yIe53jH;85I89KKtl_CMjy4xBu?+8FAc=cpal@^O
zK<6j*nuy;Amxx!>723)kBK~?UUd>J2tND9~_$_#B0#W7OD1HI}5f>!xKJOOR1#J)L
zifd);8n|~>p^spQYT-}8;<1R=rOkZ{qZW2gk|e55tEh$jfWHcL8Zx1J=l(nNXe(mJ
zA!zZYFk66t7HWf0kHoyen$- at Y7N%I111%rx9yrxlm*Bky^49Gk_~TxKW(^UZei(sG
zp_f}mNQ;rChOaZq7=qL&-y`xG$Xji96t6+E4iauyjbf1Ij#(Q;Yt=R<*XiNp3#XGm
zpGmG+zbV<Ot;I1~sFQ`0{fR^ZUjdMqNc2ODq#3yfH-wWr5|1VZ at bQFRAK{lX_$(*d
zgPx=72HGh&gs*dAqW^bi+7$$OQJgdqSsPtpZ|Y$oIo9Yps!o>fyi at rSz8OfJFspXa
zDyO=8(_QJV)E3vewY#?qTDqqz-TmNd?~x3_74wDz7&|kaw+dz&x6GNHR at pJjj-45z
zcaT*vtC_te0|$TAIXm-&k>4{poyM7;Yw*NO4vi~!cMo!~3&)v=uBn;Pa%JAJS$>wz
z4|#TCB71;OjvgH5QwR1AbI#Oh;<7hY<C97{fh?9CM#quM-b}SF9;-Oqq+?2h`QJS9
zTobHh<&6>>nat9ntbHoeLe)nTwkZ1>O~ue>QbhG)D31COr at q&ZEGFIqy=X5cE<OIq
z+K)S8zaE0U1Ud~m4|)wmzf6iJotpdm1Aoia7;}F=kZ()feGfn$l)Ag}As;3XG?i-@
zG7%P|+vta^u_$ah{v{xZxv9Ln78Vov)T^hTw$FdF7qQQSE`aDIK{&62IvIOo%Z`>5
uOj10zB*M?=1qKVFZ`Tm9|JHM_Kw|VlBlC6;%s0=Dya}n6D!HiDE9*b6pWSEx

literal 0
HcmV?d00001

diff --git a/llvm/test/tools/dsymutil/Inputs/proxy-relink.dylib.dSYM/Contents/Resources/Relocations/aarch64/proxy-relink.dylib.yml b/llvm/test/tools/dsymutil/Inputs/proxy-relink.dylib.dSYM/Contents/Resources/Relocations/aarch64/proxy-relink.dylib.yml
new file mode 100644
index 000000000000000..44dd0a2342da84b
--- /dev/null
+++ b/llvm/test/tools/dsymutil/Inputs/proxy-relink.dylib.dSYM/Contents/Resources/Relocations/aarch64/proxy-relink.dylib.yml
@@ -0,0 +1,14 @@
+---
+triple:          'arm64-apple-darwin'
+binary-path:     proxy-relink.dylib
+relocations:
+  - { offset: 0x26, size: 0x8, addend: 0x0, symName: _display, symObjAddr: 0x0, symBinAddr: 0x3F1C, symSize: 0x1C }
+  - { offset: 0x41, size: 0x8, addend: 0x0, symName: _display, symObjAddr: 0x0, symBinAddr: 0x3F1C, symSize: 0x1C }
+  - { offset: 0x7C, size: 0x8, addend: 0x0, symName: _bar, symObjAddr: 0x3FA0, symBinAddr: 0x3F38, symSize: 0x8 }
+  - { offset: 0x99, size: 0x8, addend: 0x0, symName: _baz, symObjAddr: 0x4000, symBinAddr: 0x8000, symSize: 0x0 }
+  - { offset: 0xA9, size: 0x8, addend: 0x0, symName: _bar, symObjAddr: 0x3FA0, symBinAddr: 0x3F38, symSize: 0x8 }
+  - { offset: 0xE8, size: 0x8, addend: 0x0, symName: _foo, symObjAddr: 0x3F60, symBinAddr: 0x3F40, symSize: 0x24 }
+  - { offset: 0xF9, size: 0x8, addend: 0x0, symName: _foo, symObjAddr: 0x3F60, symBinAddr: 0x3F40, symSize: 0x24 }
+  - { offset: 0x14E, size: 0x8, addend: 0x0, symName: _altfoo, symObjAddr: 0x3F84, symBinAddr: 0x3F64, symSize: 0x24 }
+  - { offset: 0x15F, size: 0x8, addend: 0x0, symName: _altfoo, symObjAddr: 0x3F84, symBinAddr: 0x3F64, symSize: 0x24 }
+...
diff --git a/llvm/test/tools/dsymutil/Inputs/two-level-relink.macho.arm64.dylib b/llvm/test/tools/dsymutil/Inputs/two-level-relink.macho.arm64.dylib
new file mode 100644
index 0000000000000000000000000000000000000000..333ac9f5d904ce2e802bee5ce44bc0346498c85b
GIT binary patch
literal 50944
zcmeI*e{54#6bJCLwwqJNhCp-+!%aj2!diYTWYI**uK=R33}R;Z<I$}hYu2?(+p%8+
zD~KX$bbt{fe+U>Hi5h~$z#qgC77<B=5y9vmNEQ&3KqS#jND$9??_RiT#zsQIKYp*?
z-goZ3 at 4WLqecgXAoVao2-#nr$;+DgG1ou`C(FXg7sEFf at ylPp?=T|T1AhY>1CRCiw
z)6zMW-7G5^YE7zuhs=D%vz)bv+9I**&UQ(ZGDFKsB%5mzx2H1mZB+UA-s~o^nJ-u6
z)9aR1n at GmP(N$`HX1=W|pIfc#ScUy^%baC3M_a<tpcRhR#q7Ah-!_%6UL}y&tWQnf
z9^`x2#@({!&0ap+n!9w#GUwayt1WjKrC#as1<QA9S*v2k*KpT-xxCkIe&>7 at +0Tgm
zu&9atb?IF^rqr=tjTy07m+Y{tU?3S#d+k{6^G>Yu>E}t}p}ZE_d0t$!WbyoYi}bUb
zRyqA@)bT at 3Eca&K-*Aro+zT`2lP$5bNN9B^QWg(I!qEnAW1zM^<_*LfXO??|ZIN&d
zpTMo0CB&W5L at Rliq2iSsOMP+=l6x=5Q+RAWLR85G4CCWU?$RcxF2ASA+|Bwp?AMz3
z{DEA?@GiMd#raddBgdz8?EKW{zdXNc*>s*O<?iIn=c9c4SiT?1>2p8BgI&MG+~oIC
z!Ci7W*O4=`$k&{R`}nS<FKbIALyg`!ri0vr<mpNi$+I;{#d6=$#&VbSlifs92f6{-
zga!c!KmY;|fB*y_009U<00Izz00bZa0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;|
zfB*y_009U<00Izz00bZa0SG_<0uX=z1R(Ig7P#5*&7PZX>SToXsq*>G$BDMy>^R(&
zc3Wrsl&X^P)?Di8;^RvNbnsGv|6p!5Ju1iN_?Xu^^`4288adb=e)o0n2$%mlxk}C~
zUF^J%TdefWQC^LecjNs$O4skX%dy$y{oOo%^SjV~`<u_<l;fROcI6dn7r$(4zGa&-
z&&4qWAOHafKmY;|fB*y_009U<00Izz00bZa0SG_<0uX=z1Rwwb2tWV=5P$##AOHaf
zKmY;|fB*y_009U<00Izz00bZa0SG_<0uX=z1Rwwb2tWV=4_3hbcfKF&C2=(fKmY;|
zfB*y_009U<00Izz00bZa0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U<
z00Izz00bZa0SG_<0uX=z1Rwwb2tWV=5P$##1`sIaxk~QU+_O~Y!EPQk7OGJXcI?j~
z^6MFOu1m#MQ*$!G$5|FlmMJ%#U&|i{){=)(Dc<FZQ+_**a?^I1Pp>8N1R}}0Sd1R7
z2~bfmoM?&!+UQA{nZTQhbH__M?m_ubP3o at K0gn^82aR}IMqJBr9cL;3<D$JyQhE8K
zc$Rb0XdcEJv8>B=i=Acr`b#p_&3ZoJeP%tII5z9qk`aH!vD7moqn-*?&m+7p_2^jF
zlgsncB$j&gdI86!+;x+6v%a$&oArGs>v}VfJsI&ejt8pGuj(7i>r$VN<$B^JU7EyF
zpSf<<Q^IRzJvkhk^%P{p(>Wffo}j8n9zUr^$9y<oJ?6SukDPB`)9{zr^ey1Wo>JVo
z$@3!X`uPzLiS_-C<CsJK-)Zt&kX}lbdfKg;K%Draoh<##Tk_01KOo<tsQi$8lx&HW
zMMA4Xk+OIw5{@=_8w0iVF>fH=IJ4YaOHJ`uYnxsQwnf4<q)#36%-HR1#C7NdgXS~#
z8E13J_jI<g&p6w$xTggDx5kvK9&Vh?OY`3rAII8!G|$Q3n=$0_ at WB5Ob#RwIchZIv
zb)PJCQJxbH`5DnW28DILgRbW;zf|=@d-l{XUw`fUUTb9G?%t!peJ56|e{)Y&#j#E6
zzj*cYebupVf3Hh>e(LFIa4oIQzO`omn)VI99C~}<TT?z8YJGP at cK4x=C-oN0F1yg$
z>*+Y!Tr}+1=65c%<Q;zO>XCnnem#BpjcXs&xpz#-nfX_3N!_*K!w&p-b=RpC>&{)+
z?Am{2sQmZ4p6 at NW{_?KQ&BwofcihN{?_FFmJ at M?`?l}klT=2xxFSyt3yx;soo&U<b
mu}^I|`Ey_8hoeI4`#$RZJHLGUf~wOeE>@)uwC(sUi~a-1bU{D>

literal 0
HcmV?d00001

diff --git a/llvm/test/tools/dsymutil/Inputs/variant-relink.macho.arm64.dylib b/llvm/test/tools/dsymutil/Inputs/variant-relink.macho.arm64.dylib
new file mode 100644
index 0000000000000000000000000000000000000000..3c434096f7dc9736894757e70a423396128c57be
GIT binary patch
literal 50944
zcmeI5U2IfE6vxkg&{ioeLPKb5?Mi at Dpu38Qd?^c-NPz%>MyrUox80U**zS_uTci|W
zLsG0Us3n*XpFpA_(Le~{BSEcFQG-SxiqW8=#sDfPiHU)T^_+WWy0 at D)eIVh*|ADhJ
z|Cw{oJ at cE{eVg=)>zDt{C-M+m4*PKSb$+6DyGK;ax`Ss8qk3LVHH&NuXALMlgonjB
zm2HM$HLSCg;3hj?V74>Yq(Ve{GvSgb?Usg-vRdj=y+hggI#fPhn{A at q`SMggJ#QHG
zDJvO`uTt^Z`L?TkJ~gkkl6`W^m|?WUpNYmJMl{}-uytR4J5)ZsUeWIQbY9)cKJ2jb
zRL-fMV?45C at p5N3!YX2bR_Ya(4VJw%j8zHOHn8qLUmnNW7IvOj%046ZVNnBp>(Wu&
zrd2<z+AQs^OCk&-Vp^t(wYAih(K??#Pof9oHQ&y&sA}=Td6iZA>~^V~VbyA#>u6b<
zdws)LhuKGGjjuJ6Q8R8;BpYJU`08M at S>Kchn#ty=Q-YD!ShSAAZJWX*ggbQ+)pB#c
z(zUFmK3Rk0-p_g>w at t^{xqzYEU&<~vPPu%aCa}BfW7)@Q`T731+{sb$p6x%+?8yCW
z*4`Ia20t{5o|`_I#{%q5&I0Zg*nQa_%K6(T at 3ZR{%_iTMY3!2Ad5=8lp- at XI8RB(|
zFK<m*4b8#1ZW7};O7iUKB9gOpkJ7Sku~K%KKh;fiZ+{DrAQ%XM00 at 8p2!H?xfB*=9
z00 at 8p2!H?xfB*=900 at 8p2!H?xfB*=900 at 8p2!H?xfB*=900 at 8p2!H?xfB*=900 at 8p
z2!H?xfB*=900 at 8p2!H?xfWZHrz>T)|- at 4(WP6qKZEq%Ci6knme(e}ZfE}wC>=Mg&H
zQ%FZI7KV at J4WT<Oa{oN{dAw84ms5I#j1LqOrt~t2<-4!@hkL`<$Xj-H$wKEoZi%Ar
zZslsM+>H-&E3WUkOW$pBe>b0Revh_qe-m*IPpxxh*UuMiC5^bYwC<n<0T2KI5C8!X
z009sH0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X009sH
z0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!Xxb+0=zw>?TUyC<_00 at 8p2!H?x
zfB*=900 at 8p2!H?xfB*=900 at 8p2!H?xfB*=900 at 8p2!H?xfB*=900 at 8p2!H?xfB*=9
z00 at 8p2!H?xfB*=900 at 8p2!H?xfB*=900 at 8p2!H?xWDy9kUdmp>?orN-ZGP2`R;_Mq
z9nK*N>k;*=S7~ESi<RQO$DoNa<fC&N`6IoF{FF{}ls8EQ>uIEqcFOp%jYNJkW;G at f
zbX%QC#gS-gP0VbiyJciN2bBcIN;>w4d?+jDHlhW$_hsottQ+~M$dwCrm^>QfkHBp1
zuobb7b!nNG_mr at UiC&yF?|y$f&o at b+vIMv8de&v>eXRSdXO^m`l;@=$t#v&C9v9Q~
zxaZyVe8(~Fdb(M=>-juO=W at dS>Um1lBikwUXszoJMq;`i_q at BF2ROi8PZ?`>J>^+i
zSoc>?TGewqzf<bbn!EOX<w-GYq9uo(FJv8H*CzAs`ec2DJgDoJ{G#2 at 7xFQuG&`G|
z7nu*Z_Dl3ErN{6*OaAZJ1a8CwWT?|^)R{@*kM(5eGj7NkcfK&8s<?b{LR4p_qV*NY
zhFCPdI at oO1Hzk5*vU%#1U_I%W0YehKA;g(=5`M6`H584fEHf4htud{pP-eDbt(lCP
zaVr>UjYaEvpU(sYT}hpl+)UoS8C<CuP9|?g3{YMsfXlP(`uF)={M%B&LhnHlkIC;%
zF?s#m at IRtfcKNvz8%ET9D&VDjM-KYgdz=+AU9WqS9Eu+;n4Wj2aOJ9LzgK?ZJFs=$
z8_PaEeEG_e;*OsldivA7rQPprdiy|4;>4xKF8|l3Pp|easTtC<;oye#?ccup!u;na
zy*b!?#d|q5zqS`W{=|h#m9KibPyBP~u;-YybLfnHBXf6o&XxY~)o)v_zS8L1H7RH6
zU-e~;SBDKf^5vD?XI5-J|I0S-!OMf?zuEbMVA-|Dc6V+&d1&jH5#=vkSTQ*@V}JMD
zqklen*SH0~&9B{T{=uIAW8#x}B|VF*O4GY#)Q{C|ueWVE8K_FktUZ3_SkHssJj+}C
EA1fw95C8xG

literal 0
HcmV?d00001

diff --git a/llvm/test/tools/dsymutil/basic-linking.test b/llvm/test/tools/dsymutil/basic-linking.test
index cc521430b0c8715..88cd3293efa2427 100644
--- a/llvm/test/tools/dsymutil/basic-linking.test
+++ b/llvm/test/tools/dsymutil/basic-linking.test
@@ -2,6 +2,9 @@ RUN: dsymutil -no-output -verbose -oso-prepend-path=%p %p/Inputs/basic.macho.x86
 RUN: dsymutil -no-output -verbose -oso-prepend-path=%p %p/Inputs/basic-lto.macho.x86_64 | FileCheck %s --check-prefix=CHECK-LTO
 RUN: dsymutil -no-output -verbose -oso-prepend-path=%p %p/Inputs/basic-archive.macho.x86_64 | FileCheck %s --check-prefix=CHECK-ARCHIVE
 RUN: dsymutil -no-output -verbose -oso-prepend-path=%p %p/Inputs/basic.macho.x86_64 %p/Inputs/basic-lto.macho.x86_64 %p/Inputs/basic-archive.macho.x86_64 | FileCheck %s --check-prefixes=CHECK,CHECK-LTO,CHECK-ARCHIVE
+RUN: dsymutil -no-output -verbose -oso-prepend-path=%p -D %p/Inputs %p/Inputs/basic-relink.macho.arm64.dylib | FileCheck %s --check-prefix=CHECK-RELINK
+RUN: dsymutil -no-output -verbose -oso-prepend-path=%p -D %p/Inputs %p/Inputs/two-level-relink.macho.arm64.dylib | FileCheck %s --check-prefix=CHECK-RELINK-TWO
+RUN: dsymutil -no-output -verbose -oso-prepend-path=%p -build-variant-suffix=_debug -D WrongPath -D %p/Inputs %p/Inputs/variant-relink.macho.arm64.dylib | FileCheck %s --check-prefix=CHECK-RELINK-VARIANT
 
 This test check the basic Dwarf linking process through the debug dumps.
 
@@ -175,3 +178,122 @@ CHECK-ARCHIVE: Found valid debug map entry: _inc	0x0000000000000070 => 0x0000000
 CHECK-ARCHIVE-NEXT: Keeping subprogram DIE:
 CHECK-ARCHIVE-NEXT: DW_TAG_subprogram
 CHECK-ARCHIVE-NEXT:   DW_AT_name {{.*}}"inc")
+
+
+================================= Simple relink ================================
+CHECK-RELINK: DEBUG MAP OBJECT: {{.*}}basic-relink.macho.arm64.o
+CHECK-RELINK: Input compilation unit:
+CHECK-RELINK-NEXT: TAG_compile_unit
+CHECK-RELINK-NOT: TAG
+CHECK-RELINK: AT_name {{.*}}basic-relink.macho.arm64.c
+
+CHECK-RELINK: DEBUG MAP OBJECT: {{.*}}foo-relink.dylib
+CHECK-RELINK: Input compilation unit:
+CHECK-RELINK-NEXT: TAG_compile_unit
+CHECK-RELINK-NOT: TAG
+CHECK-RELINK: AT_name {{.*}}foo-relink.c
+
+CHECK-RELINK: Input compilation unit:
+CHECK-RELINK-NEXT: TAG_compile_unit
+CHECK-RELINK-NOT: TAG
+CHECK-RELINK: AT_name {{.*}}altfoo-relink.c
+
+CHECK-RELINK: DEBUG MAP OBJECT: {{.*}}bar-relink.dylib
+CHECK-RELINK: Input compilation unit:
+CHECK-RELINK-NEXT: TAG_compile_unit
+CHECK-RELINK-NOT: TAG
+CHECK-RELINK: AT_name {{.*}}bar-relink.c
+
+CHECK-RELINK-NOT: Found valid debug map entry
+CHECK-RELINK: Found valid debug map entry: _display	0x0000000000000000 => 0x0000000000003f10
+CHECK-RELINK-NEXT: Keeping subprogram DIE:
+CHECK-RELINK-NEXT: DW_TAG_subprogram
+CHECK-RELINK:   DW_AT_name{{.*}}"display"
+
+CHECK-RELINK: Found valid debug map entry: _foo	0x0000000000003f54 => 0x0000000000003f2c
+CHECK-RELINK-NEXT: Keeping subprogram DIE:
+CHECK-RELINK-NEXT: DW_TAG_subprogram
+CHECK-RELINK:   DW_AT_name {{.*}}"foo"
+
+CHECK-RELINK-NOT: Found valid debug map entry
+CHECK-RELINK: Found valid debug map entry: _foo_unused	0x0000000000003f74 => 0x0000000000003f4c
+CHECK-RELINK-NEXT: Keeping subprogram DIE:
+CHECK-RELINK-NEXT: DW_TAG_subprogram
+CHECK-RELINK:   DW_AT_name {{.*}}"foo_unused"
+
+CHECK-RELINK-NOT: Found valid debug map entry
+CHECK-RELINK: Found valid debug map entry: _altfoo	0x0000000000003f7c => 0x0000000000003f54
+CHECK-RELINK-NEXT: Keeping subprogram DIE:
+CHECK-RELINK-NEXT: DW_TAG_subprogram
+CHECK-RELINK:   DW_AT_name {{.*}}"altfoo"
+
+CHECK-RELINK-NOT: Found valid debug map entry
+CHECK-RELINK: Found valid debug map entry: _baz	0x0000000000004000 => 0x0000000000008000
+CHECK-RELINK-NEXT: Keeping variable DIE:
+CHECK-RELINK-NEXT: DW_TAG_variable
+CHECK-RELINK-NEXT:   DW_AT_name {{.*}}"baz"
+
+CHECK-RELINK-NOT: Found valid debug map entry
+CHECK-RELINK: Found valid debug map entry: _bar	0x0000000000003fa0 => 0x0000000000003f78
+CHECK-RELINK-NEXT: Keeping subprogram DIE:
+CHECK-RELINK-NEXT: DW_TAG_subprogram
+CHECK-RELINK:   DW_AT_name {{.*}}"bar"
+
+================================= Two level relink ================================
+CHECK-RELINK-TWO: DEBUG MAP OBJECT: {{.*}}proxy-relink.dylib
+CHECK-RELINK-TWO: Input compilation unit:
+CHECK-RELINK-TWO-NEXT: TAG_compile_unit
+CHECK-RELINK-TWO-NOT: TAG
+CHECK-RELINK-TWO: AT_name {{.*}}two-level-relink.macho.arm64.c
+
+CHECK-RELINK-TWO: Input compilation unit:
+CHECK-RELINK-TWO-NEXT: TAG_compile_unit
+CHECK-RELINK-TWO-NOT: TAG
+CHECK-RELINK-TWO: AT_name {{.*}}bar-relink.c
+CHECK-RELINK-TWO: DW_AT_APPLE_origin {{.*}}/path/to/bar-relink.dylib
+
+CHECK-RELINK-TWO: Input compilation unit:
+CHECK-RELINK-TWO-NEXT: TAG_compile_unit
+CHECK-RELINK-TWO-NOT: TAG
+CHECK-RELINK-TWO: AT_name {{.*}}foo-relink.c
+CHECK-RELINK-TWO: DW_AT_APPLE_origin {{.*}}/path/to/foo-relink.dylib
+
+CHECK-RELINK-TWO: Input compilation unit:
+CHECK-RELINK-TWO-NEXT: TAG_compile_unit
+CHECK-RELINK-TWO-NOT: TAG
+CHECK-RELINK-TWO: AT_name {{.*}}altfoo-relink.c
+CHECK-RELINK-TWO: DW_AT_APPLE_origin {{.*}}/path/to/foo-relink.dylib
+
+CHECK-RELINK-TWO-NOT: Found valid debug map entry
+CHECK-RELINK-TWO: Found valid debug map entry: _display	0x0000000000003f1c => 0x0000000000003f1c
+CHECK-RELINK-TWO-NEXT: Keeping subprogram DIE:
+CHECK-RELINK-TWO-NEXT: DW_TAG_subprogram
+CHECK-RELINK-TWO:   DW_AT_name{{.*}}"display"
+
+CHECK-RELINK-TWO-NOT: Found valid debug map entry
+CHECK-RELINK-TWO: Found valid debug map entry: _baz	0x0000000000008000 => 0x0000000000008000
+CHECK-RELINK-TWO-NEXT: Keeping variable DIE:
+CHECK-RELINK-TWO-NEXT: DW_TAG_variable
+CHECK-RELINK-TWO-NEXT:   DW_AT_name {{.*}}"baz"
+
+CHECK-RELINK-TWO-NOT: Found valid debug map entry
+CHECK-RELINK-TWO: Found valid debug map entry: _bar	0x0000000000003f38 => 0x0000000000003f38
+CHECK-RELINK-TWO-NEXT: Keeping subprogram DIE:
+CHECK-RELINK-TWO-NEXT: DW_TAG_subprogram
+CHECK-RELINK-TWO:   DW_AT_name {{.*}}"bar"
+
+CHECK-RELINK-TWO: Found valid debug map entry: _foo	0x0000000000003f40 => 0x0000000000003f40
+CHECK-RELINK-TWO-NEXT: Keeping subprogram DIE:
+CHECK-RELINK-TWO-NEXT: DW_TAG_subprogram
+CHECK-RELINK-TWO:   DW_AT_name {{.*}}"foo"
+
+CHECK-RELINK-TWO-NOT: Found valid debug map entry
+CHECK-RELINK-TWO: Found valid debug map entry: _altfoo	0x0000000000003f64 => 0x0000000000003f64
+CHECK-RELINK-TWO-NEXT: Keeping subprogram DIE:
+CHECK-RELINK-TWO-NEXT: DW_TAG_subprogram
+CHECK-RELINK-TWO:   DW_AT_name {{.*}}"altfoo"
+
+================================= Build variants relink ================================
+CHECK-RELINK-VARIANT: DEBUG MAP OBJECT: {{.*}}basic-relink.macho.arm64.o
+CHECK-RELINK-VARIANT: DEBUG MAP OBJECT: {{.*}}foo-relink-variant_debug.dylib
+CHECK-RELINK-VARIANT: DEBUG MAP OBJECT: {{.*}}bar-relink-variant.dylib
diff --git a/llvm/test/tools/dsymutil/cmdline.test b/llvm/test/tools/dsymutil/cmdline.test
index 2317852f3c489e2..36cf3f542695ca4 100644
--- a/llvm/test/tools/dsymutil/cmdline.test
+++ b/llvm/test/tools/dsymutil/cmdline.test
@@ -7,7 +7,9 @@ HELP-NOT: -reverse-iterate
 HELP: Dsymutil Options:
 CHECK: -accelerator
 CHECK: -arch <arch>
+CHECK: -build-variant-suffix <suffix=buildvariant>
 CHECK: -dump-debug-map
+CHECK: -D <path>
 CHECK: -fat64
 CHECK: -flat
 CHECK: -gen-reproducer
diff --git a/llvm/tools/dsymutil/CMakeLists.txt b/llvm/tools/dsymutil/CMakeLists.txt
index 3cb7594d2fd920d..c612bfd9150c47f 100644
--- a/llvm/tools/dsymutil/CMakeLists.txt
+++ b/llvm/tools/dsymutil/CMakeLists.txt
@@ -30,6 +30,7 @@ add_llvm_tool(dsymutil
   MachODebugMapParser.cpp
   MachOUtils.cpp
   Reproducer.cpp
+  RelocationMap.cpp
   SymbolMap.cpp
 
   DEPENDS
diff --git a/llvm/tools/dsymutil/DebugMap.cpp b/llvm/tools/dsymutil/DebugMap.cpp
index d4e2c2b2cfac7d2..dcdecdfe8210b11 100644
--- a/llvm/tools/dsymutil/DebugMap.cpp
+++ b/llvm/tools/dsymutil/DebugMap.cpp
@@ -45,6 +45,11 @@ DebugMapObject::DebugMapObject(StringRef ObjectFilename,
 bool DebugMapObject::addSymbol(StringRef Name,
                                std::optional<uint64_t> ObjectAddress,
                                uint64_t LinkedAddress, uint32_t Size) {
+  if (Symbols.count(Name)) {
+    // Symbol was previously added.
+    return true;
+  }
+
   auto InsertResult = Symbols.insert(
       std::make_pair(Name, SymbolMapping(ObjectAddress, LinkedAddress, Size)));
 
@@ -53,6 +58,12 @@ bool DebugMapObject::addSymbol(StringRef Name,
   return InsertResult.second;
 }
 
+void DebugMapObject::setRelocationMap(dsymutil::RelocationMap &RM) {
+  RelocMap.emplace(RM);
+}
+
+void DebugMapObject::setInstallName(StringRef IN) { InstallName.emplace(IN); }
+
 void DebugMapObject::print(raw_ostream &OS) const {
   OS << getObjectFilename() << ":\n";
   // Sort the symbols in alphabetical order, like llvm-nm (and to get
@@ -158,8 +169,8 @@ struct MappingTraits<dsymutil::DebugMapObject>::YamlDMO {
   std::vector<dsymutil::DebugMapObject::YAMLSymbolMapping> Entries;
 };
 
-void MappingTraits<std::pair<std::string, DebugMapObject::SymbolMapping>>::
-    mapping(IO &io, std::pair<std::string, DebugMapObject::SymbolMapping> &s) {
+void MappingTraits<std::pair<std::string, SymbolMapping>>::mapping(
+    IO &io, std::pair<std::string, SymbolMapping> &s) {
   io.mapRequired("sym", s.first);
   io.mapOptional("objAddr", s.second.ObjectAddress);
   io.mapRequired("binAddr", s.second.BinaryAddress);
@@ -275,7 +286,13 @@ MappingTraits<dsymutil::DebugMapObject>::YamlDMO::denormalize(IO &IO) {
     }
   }
 
-  dsymutil::DebugMapObject Res(Path, sys::toTimePoint(Timestamp), MachO::N_OSO);
+  uint8_t Type = MachO::N_OSO;
+  if (Path.endswith(".dylib")) {
+    // FIXME: find a more resilient way
+    Type = MachO::N_LIB;
+  }
+  dsymutil::DebugMapObject Res(Path, sys::toTimePoint(Timestamp), Type);
+
   for (auto &Entry : Entries) {
     auto &Mapping = Entry.second;
     std::optional<uint64_t> ObjAddress;
diff --git a/llvm/tools/dsymutil/DebugMap.h b/llvm/tools/dsymutil/DebugMap.h
index 86cb88d32492d3d..9c3a698fa1191d0 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 "RelocationMap.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
@@ -134,22 +135,6 @@ class DebugMap {
 /// linked binary for all the linked atoms in this object file.
 class DebugMapObject {
 public:
-  struct SymbolMapping {
-    std::optional<yaml::Hex64> ObjectAddress;
-    yaml::Hex64 BinaryAddress;
-    yaml::Hex32 Size;
-
-    SymbolMapping(std::optional<uint64_t> ObjectAddr, uint64_t BinaryAddress,
-                  uint32_t Size)
-        : BinaryAddress(BinaryAddress), Size(Size) {
-      if (ObjectAddr)
-        ObjectAddress = *ObjectAddr;
-    }
-
-    /// For YAML IO support
-    SymbolMapping() = default;
-  };
-
   using YAMLSymbolMapping = std::pair<std::string, SymbolMapping>;
   using DebugMapEntry = StringMapEntry<SymbolMapping>;
 
@@ -182,6 +167,16 @@ class DebugMapObject {
   }
   const std::vector<std::string> &getWarnings() const { return Warnings; }
 
+  const std::optional<RelocationMap> &getRelocationMap() const {
+    return RelocMap;
+  }
+  void setRelocationMap(dsymutil::RelocationMap &RM);
+
+  const std::optional<std::string> &getInstallName() const {
+    return InstallName;
+  }
+  void setInstallName(StringRef IN);
+
   void print(raw_ostream &OS) const;
 #ifndef NDEBUG
   void dump() const;
@@ -196,10 +191,13 @@ class DebugMapObject {
 
   std::string Filename;
   sys::TimePoint<std::chrono::seconds> Timestamp;
-  StringMap<SymbolMapping> Symbols;
+  StringMap<struct SymbolMapping> Symbols;
   DenseMap<uint64_t, DebugMapEntry *> AddressToMapping;
   uint8_t Type;
 
+  std::optional<RelocationMap> RelocMap;
+  std::optional<std::string> InstallName;
+
   std::vector<std::string> Warnings;
 
   /// For YAMLIO support.
@@ -225,10 +223,8 @@ namespace yaml {
 
 using namespace llvm::dsymutil;
 
-template <>
-struct MappingTraits<std::pair<std::string, DebugMapObject::SymbolMapping>> {
-  static void mapping(IO &io,
-                      std::pair<std::string, DebugMapObject::SymbolMapping> &s);
+template <> struct MappingTraits<std::pair<std::string, SymbolMapping>> {
+  static void mapping(IO &io, std::pair<std::string, SymbolMapping> &s);
   static const bool flow = true;
 };
 
@@ -237,12 +233,6 @@ template <> struct MappingTraits<dsymutil::DebugMapObject> {
   static void mapping(IO &io, dsymutil::DebugMapObject &DMO);
 };
 
-template <> struct ScalarTraits<Triple> {
-  static void output(const Triple &val, void *, raw_ostream &out);
-  static StringRef input(StringRef scalar, void *, Triple &value);
-  static QuotingType mustQuote(StringRef) { return QuotingType::Single; }
-};
-
 template <>
 struct SequenceTraits<std::vector<std::unique_ptr<dsymutil::DebugMapObject>>> {
   static size_t
diff --git a/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp b/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp
index 39776ae5a92000b..a8fea1e2712271d 100644
--- a/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp
+++ b/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp
@@ -189,6 +189,44 @@ static Error remarksErrorHandler(const DebugMapObject &DMO,
 
   return createFileError(FE->getFileName(), std::move(NewE));
 }
+template <typename OutDwarfFile, typename AddressMap>
+Error DwarfLinkerForBinary::emitRelocations(
+    const DebugMap &DM,
+    std::vector<ObjectWithRelocMap<OutDwarfFile>> &ObjectsForLinking) {
+  // Return early if the "Resources" directory is not being written to.
+  if (!Options.ResourceDir)
+    return Error::success();
+
+  RelocationMap RM(DM.getTriple(), DM.getBinaryPath());
+  for (auto &Obj : ObjectsForLinking) {
+    if (!Obj.OutRelocs->isInitialized())
+      continue;
+    Obj.OutRelocs->addValidRelocs(RM);
+  }
+
+  SmallString<128> InputPath;
+  SmallString<128> Path;
+  // Create the "Relocations" directory in the "Resources" directory, and
+  // create an architecture-specific directory in the "Relocations" directory.
+  StringRef ArchName = Triple::getArchName(RM.getTriple().getArch(),
+                                           RM.getTriple().getSubArch());
+  sys::path::append(Path, *Options.ResourceDir, "Relocations", ArchName);
+  if (std::error_code EC = sys::fs::create_directories(Path.str(), true,
+                                                       sys::fs::perms::all_all))
+    return errorCodeToError(EC);
+
+  // Append the file name.
+  sys::path::append(Path, sys::path::filename(DM.getBinaryPath()));
+  Path.append(".yml");
+
+  std::error_code EC;
+  raw_fd_ostream OS(Path.str(), EC, sys::fs::OF_Text);
+  if (EC)
+    return errorCodeToError(EC);
+
+  RM.print(OS);
+  return Error::success();
+}
 
 static Error emitRemarks(const LinkOptions &Options, StringRef BinaryPath,
                          StringRef ArchName, const remarks::RemarkLinker &RL) {
@@ -229,30 +267,31 @@ static Error emitRemarks(const LinkOptions &Options, StringRef BinaryPath,
 }
 
 template <typename OutDWARFFile, typename AddressesMap>
-ErrorOr<std::unique_ptr<OutDWARFFile>>
-DwarfLinkerForBinary::loadObject(const DebugMapObject &Obj,
-                                 const DebugMap &DebugMap,
-                                 remarks::RemarkLinker &RL) {
+ErrorOr<std::unique_ptr<OutDWARFFile>> DwarfLinkerForBinary::loadObject(
+    const DebugMapObject &Obj, const DebugMap &DebugMap,
+    remarks::RemarkLinker &RL,
+    std::shared_ptr<DwarfLinkerForBinaryRelocationMap> DLBRM) {
   auto ErrorOrObj = loadObject(Obj, DebugMap.getTriple());
   std::unique_ptr<OutDWARFFile> Res;
 
   if (ErrorOrObj) {
+    auto Context = DWARFContext::create(
+        *ErrorOrObj, DWARFContext::ProcessDebugRelocations::Process, nullptr,
+        "",
+        [&](Error Err) {
+          handleAllErrors(std::move(Err), [&](ErrorInfoBase &Info) {
+            reportError(Info.message());
+          });
+        },
+        [&](Error Warning) {
+          handleAllErrors(std::move(Warning), [&](ErrorInfoBase &Info) {
+            reportWarning(Info.message());
+          });
+        });
+    DLBRM->init(*Context);
     Res = std::make_unique<OutDWARFFile>(
-        Obj.getObjectFilename(),
-        DWARFContext::create(
-            *ErrorOrObj, DWARFContext::ProcessDebugRelocations::Process,
-            nullptr, "",
-            [&](Error Err) {
-              handleAllErrors(std::move(Err), [&](ErrorInfoBase &Info) {
-                reportError(Info.message());
-              });
-            },
-            [&](Error Warning) {
-              handleAllErrors(std::move(Warning), [&](ErrorInfoBase &Info) {
-                reportWarning(Info.message());
-              });
-            }),
-        std::make_unique<AddressesMap>(*this, *ErrorOrObj, Obj),
+        Obj.getObjectFilename(), std::move(Context),
+        std::make_unique<AddressesMap>(*this, *ErrorOrObj, Obj, DLBRM),
         [&](StringRef FileName) { BinHolder.eraseObjectEntry(FileName); });
 
     Error E = RL.link(*ErrorOrObj);
@@ -614,7 +653,7 @@ template <typename Linker, typename OutDwarfFile, typename AddressMap>
 bool DwarfLinkerForBinary::linkImpl(
     const DebugMap &Map, typename Linker::OutputFileType ObjectType) {
 
-  std::vector<std::unique_ptr<OutDwarfFile>> ObjectsForLinking;
+  std::vector<ObjectWithRelocMap<OutDwarfFile>> ObjectsForLinking;
 
   DebugMap DebugMap(Map.getTriple(), Map.getBinaryPath());
 
@@ -668,10 +707,12 @@ bool DwarfLinkerForBinary::linkImpl(
     auto &Obj = DebugMap.addDebugMapObject(
         Path, sys::TimePoint<std::chrono::seconds>(), MachO::N_OSO);
 
+    auto DLBRelocMap = std::make_shared<DwarfLinkerForBinaryRelocationMap>();
     if (ErrorOr<std::unique_ptr<OutDwarfFile>> ErrorOrObj =
-            loadObject<OutDwarfFile, AddressMap>(Obj, DebugMap, RL)) {
-      ObjectsForLinking.emplace_back(std::move(*ErrorOrObj));
-      return *ObjectsForLinking.back();
+            loadObject<OutDwarfFile, AddressMap>(Obj, DebugMap, RL,
+                                                 DLBRelocMap)) {
+      ObjectsForLinking.emplace_back(std::move(*ErrorOrObj), DLBRelocMap);
+      return *ObjectsForLinking.back().Object;
     } else {
       // Try and emit more helpful warnings by applying some heuristics.
       StringRef ObjFile = ContainerName;
@@ -782,15 +823,18 @@ bool DwarfLinkerForBinary::linkImpl(
       continue;
     }
 
+    auto DLBRelocMap = std::make_shared<DwarfLinkerForBinaryRelocationMap>();
     if (ErrorOr<std::unique_ptr<OutDwarfFile>> ErrorOrObj =
-            loadObject<OutDwarfFile, AddressMap>(*Obj, Map, RL)) {
-      ObjectsForLinking.emplace_back(std::move(*ErrorOrObj));
-      GeneralLinker->addObjectFile(*ObjectsForLinking.back(), Loader,
+            loadObject<OutDwarfFile, AddressMap>(*Obj, Map, RL, DLBRelocMap)) {
+      ObjectsForLinking.emplace_back(std::move(*ErrorOrObj), DLBRelocMap);
+      GeneralLinker->addObjectFile(*ObjectsForLinking.back().Object, Loader,
                                    OnCUDieLoaded);
     } else {
-      ObjectsForLinking.push_back(std::make_unique<OutDwarfFile>(
-          Obj->getObjectFilename(), nullptr, nullptr));
-      GeneralLinker->addObjectFile(*ObjectsForLinking.back());
+      ObjectsForLinking.push_back(
+          {std::make_unique<OutDwarfFile>(Obj->getObjectFilename(), nullptr,
+                                          nullptr),
+           DLBRelocMap});
+      GeneralLinker->addObjectFile(*ObjectsForLinking.back().Object);
     }
   }
 
@@ -815,6 +859,10 @@ bool DwarfLinkerForBinary::linkImpl(
   if (Options.NoOutput)
     return true;
 
+  if (Error E =
+          emitRelocations<OutDwarfFile, AddressMap>(Map, ObjectsForLinking))
+    return error(toString(std::move(E)));
+
   if (Options.ResourceDir && !ParseableSwiftInterfaces.empty()) {
     StringRef ArchName = Triple::getArchTypeName(Map.getTriple().getArch());
     if (auto E = copySwiftInterfaces(ArchName))
@@ -903,12 +951,14 @@ void DwarfLinkerForBinary::AddressManager<AddressesMapBase>::
         continue;
       }
       if (const auto *Mapping = DMO.lookupSymbol(*SymbolName))
-        ValidRelocs.emplace_back(Offset64, RelocSize, Addend, Mapping);
+        ValidRelocs.emplace_back(Offset64, RelocSize, Addend, Mapping->getKey(),
+                                 Mapping->getValue());
     } else if (const auto *Mapping = DMO.lookupObjectAddress(SymAddress)) {
       // Do not store the addend. The addend was the address of the symbol in
       // the object file, the address in the binary that is stored in the debug
       // map doesn't need to be offset.
-      ValidRelocs.emplace_back(Offset64, RelocSize, SymOffset, Mapping);
+      ValidRelocs.emplace_back(Offset64, RelocSize, SymOffset,
+                               Mapping->getKey(), Mapping->getValue());
     }
   }
 }
@@ -966,20 +1016,17 @@ bool DwarfLinkerForBinary::AddressManager<AddressesMapBase>::
 }
 
 template <typename AddressesMapBase>
-std::vector<
-    typename DwarfLinkerForBinary::AddressManager<AddressesMapBase>::ValidReloc>
+std::vector<ValidReloc>
 DwarfLinkerForBinary::AddressManager<AddressesMapBase>::getRelocations(
     const std::vector<ValidReloc> &Relocs, uint64_t StartPos, uint64_t EndPos) {
-  std::vector<
-      DwarfLinkerForBinary::AddressManager<AddressesMapBase>::ValidReloc>
-      Res;
+  std::vector<ValidReloc> Res;
 
   auto CurReloc = partition_point(Relocs, [StartPos](const ValidReloc &Reloc) {
-    return Reloc.Offset < StartPos;
+    return (uint64_t)Reloc.Offset < StartPos;
   });
 
   while (CurReloc != Relocs.end() && CurReloc->Offset >= StartPos &&
-         CurReloc->Offset < EndPos) {
+         (uint64_t)CurReloc->Offset < EndPos) {
     Res.push_back(*CurReloc);
     CurReloc++;
   }
@@ -990,12 +1037,12 @@ DwarfLinkerForBinary::AddressManager<AddressesMapBase>::getRelocations(
 template <typename AddressesMapBase>
 void DwarfLinkerForBinary::AddressManager<AddressesMapBase>::printReloc(
     const ValidReloc &Reloc) {
-  const auto &Mapping = Reloc.Mapping->getValue();
+  const auto &Mapping = Reloc.SymbolMapping;
   const uint64_t ObjectAddress = Mapping.ObjectAddress
                                      ? uint64_t(*Mapping.ObjectAddress)
                                      : std::numeric_limits<uint64_t>::max();
 
-  outs() << "Found valid debug map entry: " << Reloc.Mapping->getKey() << "\t"
+  outs() << "Found valid debug map entry: " << Reloc.SymbolName << "\t"
          << format("0x%016" PRIx64 " => 0x%016" PRIx64 "\n", ObjectAddress,
                    uint64_t(Mapping.BinaryAddress));
 }
@@ -1004,8 +1051,8 @@ template <typename AddressesMapBase>
 int64_t DwarfLinkerForBinary::AddressManager<AddressesMapBase>::getRelocValue(
     const ValidReloc &Reloc) {
   int64_t AddrAdjust = relocate(Reloc);
-  if (Reloc.Mapping->getValue().ObjectAddress)
-    AddrAdjust -= uint64_t(*Reloc.Mapping->getValue().ObjectAddress);
+  if (Reloc.SymbolMapping.ObjectAddress)
+    AddrAdjust -= uint64_t(*Reloc.SymbolMapping.ObjectAddress);
   return AddrAdjust;
 }
 
@@ -1116,12 +1163,40 @@ std::optional<int64_t> DwarfLinkerForBinary::AddressManager<
   }
 }
 
+template <typename AddressesMapBase>
+std::optional<StringRef> DwarfLinkerForBinary::AddressManager<
+    AddressesMapBase>::getLibraryInstallName() {
+  return LibInstallName;
+}
+
 template <typename AddressesMapBase>
 uint64_t DwarfLinkerForBinary::AddressManager<AddressesMapBase>::relocate(
     const ValidReloc &Reloc) const {
-  return Reloc.Mapping->getValue().BinaryAddress + Reloc.Addend;
+  return Reloc.SymbolMapping.BinaryAddress + Reloc.Addend;
+}
+
+template <typename AddressesMapBase>
+void DwarfLinkerForBinary::AddressManager<
+    AddressesMapBase>::updateAndSaveValidRelocs(bool IsDWARF5,
+                                                uint64_t OriginalUnitOffset,
+                                                int64_t LinkedOffset,
+                                                uint64_t StartOffset,
+                                                uint64_t EndOffset) {
+  std::vector<ValidReloc> InRelocs =
+      getRelocations(ValidDebugInfoRelocs, StartOffset, EndOffset);
+  if (IsDWARF5)
+    InRelocs = getRelocations(ValidDebugAddrRelocs, StartOffset, EndOffset);
+  DwarfLinkerRelocMap->updateAndSaveValidRelocs(
+      IsDWARF5, InRelocs, OriginalUnitOffset, LinkedOffset);
 }
 
+template <typename AddressesMapBase>
+void DwarfLinkerForBinary::AddressManager<AddressesMapBase>::
+    updateRelocationsWithUnitOffset(uint64_t OriginalUnitOffset,
+                                    uint64_t OutputUnitOffset) {
+  DwarfLinkerRelocMap->updateRelocationsWithUnitOffset(OriginalUnitOffset,
+                                                       OutputUnitOffset);
+}
 /// Apply the valid relocations found by findValidRelocs() to
 /// the buffer \p Data, taking into account that Data is at \p BaseOffset
 /// in the debug_info section.
@@ -1133,6 +1208,7 @@ uint64_t DwarfLinkerForBinary::AddressManager<AddressesMapBase>::relocate(
 template <typename AddressesMapBase>
 bool DwarfLinkerForBinary::AddressManager<AddressesMapBase>::applyValidRelocs(
     MutableArrayRef<char> Data, uint64_t BaseOffset, bool IsLittleEndian) {
+
   std::vector<ValidReloc> Relocs = getRelocations(
       ValidDebugInfoRelocs, BaseOffset, BaseOffset + Data.size());
 
@@ -1148,9 +1224,47 @@ bool DwarfLinkerForBinary::AddressManager<AddressesMapBase>::applyValidRelocs(
     assert(CurReloc.Size <= sizeof(Buf));
     memcpy(&Data[CurReloc.Offset - BaseOffset], Buf, CurReloc.Size);
   }
-
   return Relocs.size() > 0;
 }
 
+void DwarfLinkerForBinaryRelocationMap::init(DWARFContext &Context) {
+  for (const std::unique_ptr<DWARFUnit> &CU : Context.compile_units())
+    StoredValidDebugInfoRelocsMap.insert(
+        std::make_pair(CU->getOffset(), std::vector<ValidReloc>()));
+  // FIXME: Support relocations debug_addr (DWARF5).
+}
+
+void DwarfLinkerForBinaryRelocationMap::addValidRelocs(RelocationMap &RM) {
+  for (const auto &DebugInfoRelocs : StoredValidDebugInfoRelocsMap) {
+    for (const auto &InfoReloc : DebugInfoRelocs.second)
+      RM.addRelocationMapEntry(InfoReloc);
+  }
+  // FIXME: Support relocations debug_addr (DWARF5).
+}
+
+void DwarfLinkerForBinaryRelocationMap::updateRelocationsWithUnitOffset(
+    uint64_t OriginalUnitOffset, uint64_t OutputUnitOffset) {
+  std::vector<ValidReloc> &StoredValidDebugInfoRelocs =
+      StoredValidDebugInfoRelocsMap[OriginalUnitOffset];
+  for (ValidReloc &R : StoredValidDebugInfoRelocs) {
+    R.Offset = (uint64_t)R.Offset + OutputUnitOffset;
+  }
+  // FIXME: Support relocations debug_addr (DWARF5).
+}
+
+void DwarfLinkerForBinaryRelocationMap::updateAndSaveValidRelocs(
+    bool IsDWARF5, std::vector<ValidReloc> &InRelocs, uint64_t UnitOffset,
+    int64_t LinkedOffset) {
+  std::vector<ValidReloc> &OutRelocs =
+      StoredValidDebugInfoRelocsMap[UnitOffset];
+  if (IsDWARF5)
+    OutRelocs = StoredValidDebugAddrRelocsMap[UnitOffset];
+
+  for (ValidReloc &R : InRelocs) {
+    OutRelocs.emplace_back(R.Offset + LinkedOffset, R.Size, R.Addend,
+                           R.SymbolName, R.SymbolMapping);
+  }
+}
+
 } // namespace dsymutil
 } // namespace llvm
diff --git a/llvm/tools/dsymutil/DwarfLinkerForBinary.h b/llvm/tools/dsymutil/DwarfLinkerForBinary.h
index 230f569a6988c32..328cd9197d0d170 100644
--- a/llvm/tools/dsymutil/DwarfLinkerForBinary.h
+++ b/llvm/tools/dsymutil/DwarfLinkerForBinary.h
@@ -13,6 +13,7 @@
 #include "DebugMap.h"
 #include "LinkUtils.h"
 #include "MachOUtils.h"
+#include "RelocationMap.h"
 #include "llvm/DWARFLinker/DWARFLinker.h"
 #include "llvm/DWARFLinker/DWARFLinkerCompileUnit.h"
 #include "llvm/DWARFLinker/DWARFLinkerDeclContext.h"
@@ -21,10 +22,48 @@
 #include "llvm/Remarks/RemarkFormat.h"
 #include "llvm/Remarks/RemarkLinker.h"
 #include <mutex>
+#include <optional>
 
 namespace llvm {
 namespace dsymutil {
 
+/// DwarfLinkerForBinaryRelocationMap contains the logic to handle the
+/// relocations and to store them inside an associated RelocationMap.
+class DwarfLinkerForBinaryRelocationMap {
+public:
+  void init(DWARFContext &Context);
+
+  bool isInitialized() {
+    return StoredValidDebugInfoRelocsMap.getMemorySize() != 0;
+  }
+
+  void addValidRelocs(RelocationMap &RM);
+
+  void updateAndSaveValidRelocs(bool IsDWARF5,
+                                std::vector<ValidReloc> &InRelocs,
+                                uint64_t UnitOffset, int64_t LinkedOffset);
+
+  void updateRelocationsWithUnitOffset(uint64_t OriginalUnitOffset,
+                                       uint64_t OutputUnitOffset);
+
+  /// Map compilation unit offset to the valid relocations to store
+  /// @{
+  DenseMap<uint64_t, std::vector<ValidReloc>> StoredValidDebugInfoRelocsMap;
+  DenseMap<uint64_t, std::vector<ValidReloc>> StoredValidDebugAddrRelocsMap;
+  /// @}
+
+  DwarfLinkerForBinaryRelocationMap() = default;
+};
+
+template <typename OutDwarfFile> struct ObjectWithRelocMap {
+  ObjectWithRelocMap(
+      std::unique_ptr<OutDwarfFile> Object,
+      std::shared_ptr<DwarfLinkerForBinaryRelocationMap> OutRelocs)
+      : Object(std::move(Object)), OutRelocs(OutRelocs) {}
+  std::unique_ptr<OutDwarfFile> Object;
+  std::shared_ptr<DwarfLinkerForBinaryRelocationMap> OutRelocs;
+};
+
 /// The core of the Dsymutil Dwarf linking logic.
 ///
 /// The link of the dwarf information from the object files will be
@@ -67,26 +106,11 @@ class DwarfLinkerForBinary {
   /// Keeps track of relocations.
   template <typename AddressesMapBase>
   class AddressManager : public AddressesMapBase {
-    struct ValidReloc {
-      uint64_t Offset;
-      uint32_t Size;
-      uint64_t Addend;
-      const DebugMapObject::DebugMapEntry *Mapping;
-
-      ValidReloc(uint64_t Offset, uint32_t Size, uint64_t Addend,
-                 const DebugMapObject::DebugMapEntry *Mapping)
-          : Offset(Offset), Size(Size), Addend(Addend), Mapping(Mapping) {}
-
-      bool operator<(const ValidReloc &RHS) const {
-        return Offset < RHS.Offset;
-      }
-      bool operator<(uint64_t RHS) const { return Offset < RHS; }
-    };
 
     const DwarfLinkerForBinary &Linker;
 
     /// The valid relocations for the current DebugMapObject.
-    /// This vector is sorted by relocation offset.
+    /// These vectors are sorted by relocation offset.
     /// {
     std::vector<ValidReloc> ValidDebugInfoRelocs;
     std::vector<ValidReloc> ValidDebugAddrRelocs;
@@ -94,6 +118,12 @@ class DwarfLinkerForBinary {
 
     StringRef SrcFileName;
 
+    uint8_t DebugMapObjectType;
+
+    std::shared_ptr<DwarfLinkerForBinaryRelocationMap> DwarfLinkerRelocMap;
+
+    std::optional<std::string> LibInstallName;
+
     /// Returns list of valid relocations from \p Relocs,
     /// between \p StartOffset and \p NextOffset.
     ///
@@ -115,9 +145,29 @@ class DwarfLinkerForBinary {
 
   public:
     AddressManager(DwarfLinkerForBinary &Linker, const object::ObjectFile &Obj,
-                   const DebugMapObject &DMO)
-        : Linker(Linker), SrcFileName(DMO.getObjectFilename()) {
-      findValidRelocsInDebugSections(Obj, DMO);
+                   const DebugMapObject &DMO,
+                   std::shared_ptr<DwarfLinkerForBinaryRelocationMap> DLBRM)
+        : Linker(Linker), SrcFileName(DMO.getObjectFilename()),
+          DebugMapObjectType(MachO::N_OSO), DwarfLinkerRelocMap(DLBRM) {
+      if (DMO.getRelocationMap().has_value()) {
+        DebugMapObjectType = MachO::N_LIB;
+        LibInstallName.emplace(DMO.getInstallName().value());
+        const RelocationMap &RM = DMO.getRelocationMap().value();
+        for (const auto &Reloc : RM.relocations()) {
+          const auto *DebugMapEntry = DMO.lookupSymbol(Reloc.SymbolName);
+          if (!DebugMapEntry)
+            continue;
+          std::optional<uint64_t> ObjAddress;
+          ObjAddress.emplace(DebugMapEntry->getValue().ObjectAddress.value());
+          ValidDebugInfoRelocs.emplace_back(
+              Reloc.Offset, Reloc.Size, Reloc.Addend, Reloc.SymbolName,
+              SymbolMapping(ObjAddress, DebugMapEntry->getValue().BinaryAddress,
+                            DebugMapEntry->getValue().Size));
+          // FIXME: Support relocations debug_addr.
+        }
+      } else {
+        findValidRelocsInDebugSections(Obj, DMO);
+      }
     }
     ~AddressManager() override { clear(); }
 
@@ -158,9 +208,20 @@ class DwarfLinkerForBinary {
     std::optional<int64_t>
     getSubprogramRelocAdjustment(const DWARFDie &DIE) override;
 
+    std::optional<StringRef> getLibraryInstallName() override;
+
     bool applyValidRelocs(MutableArrayRef<char> Data, uint64_t BaseOffset,
                           bool IsLittleEndian) override;
 
+    bool needToSaveValidRelocs() override { return true; }
+
+    void updateAndSaveValidRelocs(bool IsDWARF5, uint64_t OriginalUnitOffset,
+                                  int64_t LinkedOffset, uint64_t StartOffset,
+                                  uint64_t EndOffset) override;
+
+    void updateRelocationsWithUnitOffset(uint64_t OriginalUnitOffset,
+                                         uint64_t OutputUnitOffset) override;
+
     void clear() override {
       ValidDebugInfoRelocs.clear();
       ValidDebugAddrRelocs.clear();
@@ -180,11 +241,11 @@ class DwarfLinkerForBinary {
   /// Attempt to load a debug object from disk.
   ErrorOr<const object::ObjectFile &> loadObject(const DebugMapObject &Obj,
                                                  const Triple &triple);
-
   template <typename OutDWARFFile, typename AddressesMap>
-  ErrorOr<std::unique_ptr<OutDWARFFile>> loadObject(const DebugMapObject &Obj,
-                                                    const DebugMap &DebugMap,
-                                                    remarks::RemarkLinker &RL);
+  ErrorOr<std::unique_ptr<OutDWARFFile>>
+  loadObject(const DebugMapObject &Obj, const DebugMap &DebugMap,
+             remarks::RemarkLinker &RL,
+             std::shared_ptr<DwarfLinkerForBinaryRelocationMap> DLBRM);
 
   void collectRelocationsToApplyToSwiftReflectionSections(
       const object::SectionRef &Section, StringRef &Contents,
@@ -207,6 +268,11 @@ class DwarfLinkerForBinary {
   bool linkImpl(const DebugMap &Map,
                 typename Linker::OutputFileType ObjectType);
 
+  template <typename OutDwarfFile, typename AddressMap>
+  Error emitRelocations(
+      const DebugMap &DM,
+      std::vector<ObjectWithRelocMap<OutDwarfFile>> &ObjectsForLinking);
+
   raw_fd_ostream &OutFile;
   BinaryHolder &BinHolder;
   LinkOptions Options;
diff --git a/llvm/tools/dsymutil/LinkUtils.h b/llvm/tools/dsymutil/LinkUtils.h
index 88c17d503689951..0bf6d9aac1a3f3b 100644
--- a/llvm/tools/dsymutil/LinkUtils.h
+++ b/llvm/tools/dsymutil/LinkUtils.h
@@ -93,6 +93,12 @@ struct LinkOptions {
   llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS =
       vfs::getRealFileSystem();
 
+  /// -build-variant-suffix.
+  std::string BuildVariantSuffix;
+
+  /// Paths where to search for the .dSYM files of merged libraries.
+  std::vector<std::string> DSYMSearchPaths;
+
   /// Fields used for linking and placing remarks into the .dSYM bundle.
   /// @{
 
diff --git a/llvm/tools/dsymutil/MachODebugMapParser.cpp b/llvm/tools/dsymutil/MachODebugMapParser.cpp
index d9bf2301e21e55f..9623b71714582d5 100644
--- a/llvm/tools/dsymutil/MachODebugMapParser.cpp
+++ b/llvm/tools/dsymutil/MachODebugMapParser.cpp
@@ -9,6 +9,7 @@
 #include "BinaryHolder.h"
 #include "DebugMap.h"
 #include "MachOUtils.h"
+#include "RelocationMap.h"
 #include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/SmallSet.h"
 #include "llvm/Object/MachO.h"
@@ -28,9 +29,13 @@ class MachODebugMapParser {
 public:
   MachODebugMapParser(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
                       StringRef BinaryPath, ArrayRef<std::string> Archs,
-                      StringRef PathPrefix = "", bool Verbose = false)
+                      ArrayRef<std::string> DSYMSearchPaths,
+                      StringRef PathPrefix = "", StringRef VariantSuffix = "",
+                      bool Verbose = false)
       : BinaryPath(std::string(BinaryPath)), Archs(Archs.begin(), Archs.end()),
-        PathPrefix(std::string(PathPrefix)), BinHolder(VFS, Verbose),
+        DSYMSearchPaths(DSYMSearchPaths.begin(), DSYMSearchPaths.end()),
+        PathPrefix(std::string(PathPrefix)),
+        VariantSuffix(std::string(VariantSuffix)), BinHolder(VFS, Verbose),
         CurrentDebugMapObject(nullptr), SkipDebugMapObject(false) {}
 
   /// Parses and returns the DebugMaps of the input binary. The binary contains
@@ -47,7 +52,9 @@ class MachODebugMapParser {
 private:
   std::string BinaryPath;
   SmallVector<StringRef, 1> Archs;
+  SmallVector<StringRef, 1> DSYMSearchPaths;
   std::string PathPrefix;
+  std::string VariantSuffix;
 
   /// Owns the MemoryBuffer for the main binary.
   BinaryHolder BinHolder;
@@ -87,6 +94,9 @@ class MachODebugMapParser {
   void
   switchToNewDebugMapObject(StringRef Filename,
                             sys::TimePoint<std::chrono::seconds> Timestamp);
+  void
+  switchToNewLibDebugMapObject(StringRef Filename,
+                               sys::TimePoint<std::chrono::seconds> Timestamp);
   void resetParserState();
   uint64_t getMainBinarySymbolAddress(StringRef Name);
   std::vector<StringRef> getMainBinarySymbolNames(uint64_t Value);
@@ -176,8 +186,6 @@ void MachODebugMapParser::addCommonSymbols() {
 /// everything up to add symbols to the new one.
 void MachODebugMapParser::switchToNewDebugMapObject(
     StringRef Filename, sys::TimePoint<std::chrono::seconds> Timestamp) {
-  addCommonSymbols();
-  resetParserState();
 
   SmallString<80> Path(PathPrefix);
   sys::path::append(Path, Filename);
@@ -198,11 +206,138 @@ void MachODebugMapParser::switchToNewDebugMapObject(
     return;
   }
 
+  addCommonSymbols();
+  resetParserState();
+
   CurrentDebugMapObject =
       &Result->addDebugMapObject(Path, Timestamp, MachO::N_OSO);
+
   loadCurrentObjectFileSymbols(*Object);
 }
 
+/// Create a new DebugMapObject of type MachO::N_LIB.
+/// This function resets the state of the parser that was
+/// referring to the last object file and sets everything
+/// up to add symbols to the new one.
+void MachODebugMapParser::switchToNewLibDebugMapObject(
+    StringRef Filename, sys::TimePoint<std::chrono::seconds> Timestamp) {
+
+  if (DSYMSearchPaths.empty()) {
+    Warning("no dSYM search path was specified");
+    return;
+  }
+
+  StringRef LeafName = sys::path::filename(Filename);
+  SmallString<128> VariantLeafName;
+  SmallString<128> ProductName(LeafName);
+
+  // For Framework.framework/Framework and -build-variant-suffix=_debug,
+  // look in the following order:
+  // 1) Framework.framework.dSYM/Contents/Resources/DWARF/Framework_debug
+  // 2) Framework.framework.dSYM/Contents/Resources/DWARF/Framework
+  //
+  // For libName.dylib and -build-variant-suffix=_debug,
+  // look in the following order:
+  // 1) libName.dylib.dSYM/Contents/Resources/DWARF/libName_debug.dylib
+  // 2) libName.dylib.dSYM/Contents/Resources/DWARF/libName.dylib
+
+  size_t libExt = LeafName.rfind(".dylib");
+  if (libExt != StringRef::npos) {
+    if (!VariantSuffix.empty()) {
+      VariantLeafName.append(LeafName.substr(0, libExt));
+      VariantLeafName.append(VariantSuffix);
+      VariantLeafName.append(".dylib");
+    }
+  } else {
+    // Expected to be a framework
+    ProductName.append(".framework");
+    if (!VariantSuffix.empty()) {
+      VariantLeafName.append(LeafName);
+      VariantLeafName.append(VariantSuffix);
+    }
+  }
+
+  for (auto DSYMSearchPath : DSYMSearchPaths) {
+    SmallString<256> Path(DSYMSearchPath);
+    SmallString<256> FallbackPath(Path);
+
+    SmallString<256> DSYMPath(ProductName);
+    DSYMPath.append(".dSYM");
+    sys::path::append(DSYMPath, "Contents", "Resources", "DWARF");
+
+    if (!VariantSuffix.empty()) {
+      sys::path::append(Path, DSYMPath, VariantLeafName);
+      sys::path::append(FallbackPath, DSYMPath, LeafName);
+    } else {
+      sys::path::append(Path, DSYMPath, LeafName);
+    }
+
+    auto ObjectEntry = BinHolder.getObjectEntry(Path, Timestamp);
+    if (!ObjectEntry) {
+      auto Err = ObjectEntry.takeError();
+      Warning("unable to open object file: " + toString(std::move(Err)),
+              Path.str());
+      if (!VariantSuffix.empty()) {
+        ObjectEntry = BinHolder.getObjectEntry(FallbackPath, Timestamp);
+        if (!ObjectEntry) {
+          auto Err = ObjectEntry.takeError();
+          Warning("unable to open object file: " + toString(std::move(Err)),
+                  FallbackPath.str());
+          continue;
+        }
+        Path.assign(FallbackPath);
+      } else {
+        continue;
+      }
+    }
+
+    auto Object =
+        ObjectEntry->getObjectAs<MachOObjectFile>(Result->getTriple());
+    if (!Object) {
+      auto Err = Object.takeError();
+      Warning("unable to open object file: " + toString(std::move(Err)),
+              Path.str());
+      continue;
+    }
+
+    if (CurrentDebugMapObject &&
+        CurrentDebugMapObject->getType() == MachO::N_LIB &&
+        CurrentDebugMapObject->getObjectFilename().compare(Path.str()) == 0) {
+      return;
+    }
+
+    addCommonSymbols();
+    resetParserState();
+
+    CurrentDebugMapObject =
+        &Result->addDebugMapObject(Path, Timestamp, MachO::N_LIB);
+
+    CurrentDebugMapObject->setInstallName(Filename);
+
+    SmallString<256> RMPath(DSYMSearchPath);
+    sys::path::append(RMPath, ProductName);
+    RMPath.append(".dSYM");
+    StringRef ArchName = Triple::getArchName(Result->getTriple().getArch(),
+                                             Result->getTriple().getSubArch());
+    sys::path::append(RMPath, "Contents", "Resources", "Relocations", ArchName);
+    sys::path::append(RMPath, LeafName);
+    RMPath.append(".yml");
+    const auto &RelocMapPtrOrErr =
+        RelocationMap::parseYAMLRelocationMap(RMPath, PathPrefix);
+    if (auto EC = RelocMapPtrOrErr.getError()) {
+      Warning("cannot parse relocation map file: " + EC.message(),
+              RMPath.str());
+      return;
+    }
+    CurrentDebugMapObject->setRelocationMap(*RelocMapPtrOrErr->get());
+
+    loadCurrentObjectFileSymbols(*Object);
+
+    // Found and loaded new dSYM file
+    return;
+  }
+}
+
 static std::string getArchName(const object::MachOObjectFile &Obj) {
   Triple T = Obj.getArchTriple();
   return std::string(T.getArchName());
@@ -275,23 +410,39 @@ struct DarwinStabName {
   const char *Name;
 };
 
-const struct DarwinStabName DarwinStabNames[] = {
-    {MachO::N_GSYM, "N_GSYM"},    {MachO::N_FNAME, "N_FNAME"},
-    {MachO::N_FUN, "N_FUN"},      {MachO::N_STSYM, "N_STSYM"},
-    {MachO::N_LCSYM, "N_LCSYM"},  {MachO::N_BNSYM, "N_BNSYM"},
-    {MachO::N_PC, "N_PC"},        {MachO::N_AST, "N_AST"},
-    {MachO::N_OPT, "N_OPT"},      {MachO::N_RSYM, "N_RSYM"},
-    {MachO::N_SLINE, "N_SLINE"},  {MachO::N_ENSYM, "N_ENSYM"},
-    {MachO::N_SSYM, "N_SSYM"},    {MachO::N_SO, "N_SO"},
-    {MachO::N_OSO, "N_OSO"},      {MachO::N_LSYM, "N_LSYM"},
-    {MachO::N_BINCL, "N_BINCL"},  {MachO::N_SOL, "N_SOL"},
-    {MachO::N_PARAMS, "N_PARAM"}, {MachO::N_VERSION, "N_VERS"},
-    {MachO::N_OLEVEL, "N_OLEV"},  {MachO::N_PSYM, "N_PSYM"},
-    {MachO::N_EINCL, "N_EINCL"},  {MachO::N_ENTRY, "N_ENTRY"},
-    {MachO::N_LBRAC, "N_LBRAC"},  {MachO::N_EXCL, "N_EXCL"},
-    {MachO::N_RBRAC, "N_RBRAC"},  {MachO::N_BCOMM, "N_BCOMM"},
-    {MachO::N_ECOMM, "N_ECOMM"},  {MachO::N_ECOML, "N_ECOML"},
-    {MachO::N_LENG, "N_LENG"},    {0, nullptr}};
+const struct DarwinStabName DarwinStabNames[] = {{MachO::N_GSYM, "N_GSYM"},
+                                                 {MachO::N_FNAME, "N_FNAME"},
+                                                 {MachO::N_FUN, "N_FUN"},
+                                                 {MachO::N_STSYM, "N_STSYM"},
+                                                 {MachO::N_LCSYM, "N_LCSYM"},
+                                                 {MachO::N_BNSYM, "N_BNSYM"},
+                                                 {MachO::N_PC, "N_PC"},
+                                                 {MachO::N_AST, "N_AST"},
+                                                 {MachO::N_OPT, "N_OPT"},
+                                                 {MachO::N_RSYM, "N_RSYM"},
+                                                 {MachO::N_SLINE, "N_SLINE"},
+                                                 {MachO::N_ENSYM, "N_ENSYM"},
+                                                 {MachO::N_SSYM, "N_SSYM"},
+                                                 {MachO::N_SO, "N_SO"},
+                                                 {MachO::N_OSO, "N_OSO"},
+                                                 {MachO::N_LIB, "N_LIB"},
+                                                 {MachO::N_LSYM, "N_LSYM"},
+                                                 {MachO::N_BINCL, "N_BINCL"},
+                                                 {MachO::N_SOL, "N_SOL"},
+                                                 {MachO::N_PARAMS, "N_PARAM"},
+                                                 {MachO::N_VERSION, "N_VERS"},
+                                                 {MachO::N_OLEVEL, "N_OLEV"},
+                                                 {MachO::N_PSYM, "N_PSYM"},
+                                                 {MachO::N_EINCL, "N_EINCL"},
+                                                 {MachO::N_ENTRY, "N_ENTRY"},
+                                                 {MachO::N_LBRAC, "N_LBRAC"},
+                                                 {MachO::N_EXCL, "N_EXCL"},
+                                                 {MachO::N_RBRAC, "N_RBRAC"},
+                                                 {MachO::N_BCOMM, "N_BCOMM"},
+                                                 {MachO::N_ECOMM, "N_ECOMM"},
+                                                 {MachO::N_ECOML, "N_ECOML"},
+                                                 {MachO::N_LENG, "N_LENG"},
+                                                 {0, nullptr}};
 
 static const char *getDarwinStabString(uint8_t NType) {
   for (unsigned i = 0; DarwinStabNames[i].Name; i++) {
@@ -477,13 +628,25 @@ void MachODebugMapParser::handleStabSymbolTableEntry(
 
   const char *Name = &MainBinaryStrings.data()[StringIndex];
 
+  // An N_LIB entry represents the start of a new library file description.
+  if (Type == MachO::N_LIB) {
+    switchToNewLibDebugMapObject(Name, sys::toTimePoint(Value));
+    return;
+  }
+
   // An N_OSO entry represents the start of a new object file description.
+  // If an N_LIB entry was present, this is parsed only if the library
+  // dSYM file could not be found.
   if (Type == MachO::N_OSO) {
-    if (Duplicates.count(OSO(Name, Value))) {
-      SkipDebugMapObject = true;
-      return;
+    if (!CurrentDebugMapObject ||
+        CurrentDebugMapObject->getType() != MachO::N_LIB) {
+      if (Duplicates.count(OSO(Name, Value))) {
+        SkipDebugMapObject = true;
+        return;
+      }
+      switchToNewDebugMapObject(Name, sys::toTimePoint(Value));
     }
-    return switchToNewDebugMapObject(Name, sys::toTimePoint(Value));
+    return;
   }
 
   if (SkipDebugMapObject)
@@ -694,18 +857,23 @@ namespace dsymutil {
 llvm::ErrorOr<std::vector<std::unique_ptr<DebugMap>>>
 parseDebugMap(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
               StringRef InputFile, ArrayRef<std::string> Archs,
-              StringRef PrependPath, bool Verbose, bool InputIsYAML) {
+              ArrayRef<std::string> DSYMSearchPaths, StringRef PrependPath,
+              StringRef VariantSuffix, bool Verbose, bool InputIsYAML) {
   if (InputIsYAML)
     return DebugMap::parseYAMLDebugMap(InputFile, PrependPath, Verbose);
 
-  MachODebugMapParser Parser(VFS, InputFile, Archs, PrependPath, Verbose);
+  MachODebugMapParser Parser(VFS, InputFile, Archs, DSYMSearchPaths,
+                             PrependPath, VariantSuffix, Verbose);
+
   return Parser.parse();
 }
 
 bool dumpStab(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
               StringRef InputFile, ArrayRef<std::string> Archs,
-              StringRef PrependPath) {
-  MachODebugMapParser Parser(VFS, InputFile, Archs, PrependPath, false);
+              ArrayRef<std::string> DSYMSearchPaths, StringRef PrependPath,
+              StringRef VariantSuffix) {
+  MachODebugMapParser Parser(VFS, InputFile, Archs, DSYMSearchPaths,
+                             PrependPath, VariantSuffix, false);
   return Parser.dumpStab();
 }
 } // namespace dsymutil
diff --git a/llvm/tools/dsymutil/Options.td b/llvm/tools/dsymutil/Options.td
index 79f04fdfb036055..da071341cc01f21 100644
--- a/llvm/tools/dsymutil/Options.td
+++ b/llvm/tools/dsymutil/Options.td
@@ -201,3 +201,14 @@ def linker: Separate<["--", "-"], "linker">,
   HelpText<"Specify the desired type of DWARF linker. Defaults to 'apple'">,
   Group<grp_general>;
 def: Joined<["--", "-"], "linker=">, Alias<linker>;
+
+def build_variant_suffix: Separate<["--", "-"], "build-variant-suffix">,
+  MetaVarName<"<suffix=buildvariant>">,
+  HelpText<"Specify the build variant suffix used to build the executabe file.">,
+  Group<grp_general>;
+def: Joined<["--", "-"], "build-variant-suffix=">, Alias<build_variant_suffix>;
+
+def dsym_search_path: Separate<["-", "--"], "D">,
+  MetaVarName<"<path>">,
+  HelpText<"Specify a directory that contain dSYM files to search for.">,
+  Group<grp_general>;
diff --git a/llvm/tools/dsymutil/RelocationMap.cpp b/llvm/tools/dsymutil/RelocationMap.cpp
new file mode 100644
index 000000000000000..5921e7c9c249521
--- /dev/null
+++ b/llvm/tools/dsymutil/RelocationMap.cpp
@@ -0,0 +1,92 @@
+//===- tools/dsymutil/RelocationMap.cpp - Relocation map representation---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "RelocationMap.h"
+
+namespace llvm {
+
+namespace dsymutil {
+
+void RelocationMap::print(raw_ostream &OS) const {
+  yaml::Output yout(OS, /* Ctxt = */ nullptr, /* WrapColumn = */ 0);
+  yout << const_cast<RelocationMap &>(*this);
+}
+
+#ifndef NDEBUG
+void RelocationMap::dump() const { print(errs()); }
+#endif
+
+void RelocationMap::addRelocationMapEntry(const ValidReloc &Relocation) {
+  Relocations.push_back(Relocation);
+}
+
+namespace {
+
+struct YAMLContext {
+  StringRef PrependPath;
+  Triple BinaryTriple;
+};
+
+} // end anonymous namespace
+
+ErrorOr<std::unique_ptr<RelocationMap>>
+RelocationMap::parseYAMLRelocationMap(StringRef InputFile,
+                                      StringRef PrependPath) {
+  auto ErrOrFile = MemoryBuffer::getFileOrSTDIN(InputFile);
+  if (auto Err = ErrOrFile.getError())
+    return Err;
+
+  YAMLContext Ctxt;
+
+  Ctxt.PrependPath = PrependPath;
+
+  std::unique_ptr<RelocationMap> Result;
+  yaml::Input yin((*ErrOrFile)->getBuffer(), &Ctxt);
+  yin >> Result;
+
+  if (auto EC = yin.error())
+    return EC;
+  return std::move(Result);
+}
+
+} // end namespace dsymutil
+
+namespace yaml {
+
+void MappingTraits<dsymutil::ValidReloc>::mapping(IO &io,
+                                                  dsymutil::ValidReloc &VR) {
+  io.mapRequired("offset", VR.Offset);
+  io.mapRequired("size", VR.Size);
+  io.mapRequired("addend", VR.Addend);
+  io.mapRequired("symName", VR.SymbolName);
+  io.mapOptional("symObjAddr", VR.SymbolMapping.ObjectAddress);
+  io.mapRequired("symBinAddr", VR.SymbolMapping.BinaryAddress);
+  io.mapRequired("symSize", VR.SymbolMapping.Size);
+}
+
+void MappingTraits<dsymutil::RelocationMap>::mapping(
+    IO &io, dsymutil::RelocationMap &RM) {
+  io.mapRequired("triple", RM.BinaryTriple);
+  io.mapRequired("binary-path", RM.BinaryPath);
+  if (void *Ctxt = io.getContext())
+    reinterpret_cast<YAMLContext *>(Ctxt)->BinaryTriple = RM.BinaryTriple;
+  io.mapRequired("relocations", RM.Relocations);
+}
+
+void MappingTraits<std::unique_ptr<dsymutil::RelocationMap>>::mapping(
+    IO &io, std::unique_ptr<dsymutil::RelocationMap> &RM) {
+  if (!RM)
+    RM.reset(new RelocationMap());
+  io.mapRequired("triple", RM->BinaryTriple);
+  io.mapRequired("binary-path", RM->BinaryPath);
+  if (void *Ctxt = io.getContext())
+    reinterpret_cast<YAMLContext *>(Ctxt)->BinaryTriple = RM->BinaryTriple;
+  io.mapRequired("relocations", RM->Relocations);
+}
+} // end namespace yaml
+} // end namespace llvm
diff --git a/llvm/tools/dsymutil/RelocationMap.h b/llvm/tools/dsymutil/RelocationMap.h
new file mode 100644
index 000000000000000..3d851acf2b89264
--- /dev/null
+++ b/llvm/tools/dsymutil/RelocationMap.h
@@ -0,0 +1,160 @@
+//===- tools/dsymutil/RelocationMap.h -------------------------- *- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+/// \file
+///
+/// This file contains the class declaration of the RelocationMap
+/// entity. RelocationMap lists all the relocations of all the
+/// atoms used in the object files linked together to
+/// produce an executable.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_DSYMUTIL_RELOCATIONMAP_H
+#define LLVM_TOOLS_DSYMUTIL_RELOCATIONMAP_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/Support/YAMLTraits.h"
+#include "llvm/TargetParser/Triple.h"
+
+#include <optional>
+#include <string>
+#include <vector>
+
+namespace llvm {
+
+class raw_ostream;
+
+namespace dsymutil {
+
+struct SymbolMapping {
+  std::optional<yaml::Hex64> ObjectAddress;
+  yaml::Hex64 BinaryAddress;
+  yaml::Hex32 Size;
+
+  SymbolMapping(std::optional<uint64_t> ObjectAddr, uint64_t BinaryAddress,
+                uint32_t Size)
+      : BinaryAddress(BinaryAddress), Size(Size) {
+    if (ObjectAddr)
+      ObjectAddress = *ObjectAddr;
+  }
+
+  /// For YAML IO support
+  SymbolMapping() = default;
+};
+
+/// ValidReloc represents one relocation entry described by the RelocationMap.
+/// It contains a list of DWARF relocations to apply to a linked binary.
+class ValidReloc {
+public:
+  yaml::Hex64 Offset;
+  yaml::Hex32 Size;
+  yaml::Hex64 Addend;
+  std::string SymbolName;
+  struct SymbolMapping SymbolMapping;
+
+  struct SymbolMapping getSymbolMapping() const { return SymbolMapping; }
+
+  ValidReloc(uint64_t Offset, uint32_t Size, uint64_t Addend,
+             StringRef SymbolName, struct SymbolMapping SymbolMapping)
+      : Offset(Offset), Size(Size), Addend(Addend), SymbolName(SymbolName),
+        SymbolMapping(SymbolMapping) {}
+
+  bool operator<(const ValidReloc &RHS) const { return Offset < RHS.Offset; }
+
+  /// For YAMLIO support.
+  ValidReloc() = default;
+};
+
+/// The RelocationMap object stores the list of relocation entries for a binary
+class RelocationMap {
+  Triple BinaryTriple;
+  std::string BinaryPath;
+  using RelocContainer = std::vector<ValidReloc>;
+
+  RelocContainer Relocations;
+
+  /// For YAML IO support.
+  ///@{
+  friend yaml::MappingTraits<std::unique_ptr<RelocationMap>>;
+  friend yaml::MappingTraits<RelocationMap>;
+
+  RelocationMap() = default;
+  ///@}
+
+public:
+  RelocationMap(const Triple &BinaryTriple, StringRef BinaryPath)
+      : BinaryTriple(BinaryTriple), BinaryPath(std::string(BinaryPath)) {}
+
+  using const_iterator = RelocContainer::const_iterator;
+
+  iterator_range<const_iterator> relocations() const {
+    return make_range(begin(), end());
+  }
+
+  const_iterator begin() const { return Relocations.begin(); }
+
+  const_iterator end() const { return Relocations.end(); }
+
+  size_t getNumberOfEntries() const { return Relocations.size(); }
+
+  /// This function adds a ValidReloc to the list owned by this
+  /// relocation map.
+  void addRelocationMapEntry(const ValidReloc &Relocation);
+
+  const Triple &getTriple() const { return BinaryTriple; }
+
+  StringRef getBinaryPath() const { return BinaryPath; }
+
+  void print(raw_ostream &OS) const;
+
+#ifndef NDEBUG
+  void dump() const;
+#endif
+
+  /// Read a relocation map from \a InputFile.
+  static ErrorOr<std::unique_ptr<RelocationMap>>
+  parseYAMLRelocationMap(StringRef InputFile, StringRef PrependPath);
+};
+
+} // end namespace dsymutil
+} // end namespace llvm
+
+LLVM_YAML_IS_SEQUENCE_VECTOR(dsymutil::ValidReloc)
+
+namespace llvm {
+namespace yaml {
+
+using namespace llvm::dsymutil;
+
+template <> struct MappingTraits<dsymutil::ValidReloc> {
+  static void mapping(IO &io, dsymutil::ValidReloc &VR);
+  static const bool flow = true;
+};
+
+template <> struct MappingTraits<dsymutil::RelocationMap> {
+  struct YamlRM;
+  static void mapping(IO &io, dsymutil::RelocationMap &RM);
+};
+
+template <> struct MappingTraits<std::unique_ptr<dsymutil::RelocationMap>> {
+  struct YamlRM;
+  static void mapping(IO &io, std::unique_ptr<dsymutil::RelocationMap> &RM);
+};
+
+template <> struct ScalarTraits<Triple> {
+  static void output(const Triple &val, void *, raw_ostream &out);
+  static StringRef input(StringRef scalar, void *, Triple &value);
+  static QuotingType mustQuote(StringRef) { return QuotingType::Single; }
+};
+
+} // end namespace yaml
+} // end namespace llvm
+
+#endif // LLVM_TOOLS_DSYMUTIL_RELOCATIONMAP_H
diff --git a/llvm/tools/dsymutil/dsymutil.cpp b/llvm/tools/dsymutil/dsymutil.cpp
index 104895b1a90bdaa..2dd123318e00bd0 100644
--- a/llvm/tools/dsymutil/dsymutil.cpp
+++ b/llvm/tools/dsymutil/dsymutil.cpp
@@ -398,6 +398,12 @@ static Expected<DsymutilOptions> getOptions(opt::InputArgList &Args) {
   Options.LinkOpts.RemarksKeepAll =
       !Args.hasArg(OPT_remarks_drop_without_debug);
 
+  if (opt::Arg *BuildVariantSuffix = Args.getLastArg(OPT_build_variant_suffix))
+    Options.LinkOpts.BuildVariantSuffix = BuildVariantSuffix->getValue();
+
+  for (auto *SearchPath : Args.filtered(OPT_dsym_search_path))
+    Options.LinkOpts.DSYMSearchPaths.push_back(SearchPath->getValue());
+
   if (Error E = verifyOptions(Options))
     return std::move(E);
   return Options;
@@ -670,15 +676,18 @@ int dsymutil_main(int argc, char **argv, const llvm::ToolContext &) {
     // Dump the symbol table for each input file and requested arch
     if (Options.DumpStab) {
       if (!dumpStab(Options.LinkOpts.VFS, InputFile, Options.Archs,
-                    Options.LinkOpts.PrependPath))
+                    Options.LinkOpts.DSYMSearchPaths,
+                    Options.LinkOpts.PrependPath,
+                    Options.LinkOpts.BuildVariantSuffix))
         return EXIT_FAILURE;
       continue;
     }
 
-    auto DebugMapPtrsOrErr =
-        parseDebugMap(Options.LinkOpts.VFS, InputFile, Options.Archs,
-                      Options.LinkOpts.PrependPath, Options.LinkOpts.Verbose,
-                      Options.InputIsYAMLDebugMap);
+    auto DebugMapPtrsOrErr = parseDebugMap(
+        Options.LinkOpts.VFS, 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
diff --git a/llvm/tools/dsymutil/dsymutil.h b/llvm/tools/dsymutil/dsymutil.h
index ddecd8a76c7fc96..5504dd57c7e558a 100644
--- a/llvm/tools/dsymutil/dsymutil.h
+++ b/llvm/tools/dsymutil/dsymutil.h
@@ -35,12 +35,14 @@ namespace dsymutil {
 ErrorOr<std::vector<std::unique_ptr<DebugMap>>>
 parseDebugMap(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
               StringRef InputFile, ArrayRef<std::string> Archs,
-              StringRef PrependPath, bool Verbose, bool InputIsYAML);
+              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,
-              StringRef PrependPath = "");
+              ArrayRef<std::string> DSYMSearchPaths, StringRef PrependPath = "",
+              StringRef VariantSuffix = "");
 
 } // end namespace dsymutil
 } // end namespace llvm
diff --git a/llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp b/llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp
index d97dd7392b0dfd8..02a94596ec7644d 100644
--- a/llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp
+++ b/llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp
@@ -132,11 +132,23 @@ class ObjFileAddressMap : public AddressMapBase {
     return std::nullopt;
   }
 
+  std::optional<StringRef> getLibraryInstallName() override {
+    return std::nullopt;
+  }
+
   bool applyValidRelocs(MutableArrayRef<char>, uint64_t, bool) override {
     // no need to apply relocations to the linked binary.
     return false;
   }
 
+  bool needToSaveValidRelocs() override { return false; }
+
+  void updateAndSaveValidRelocs(bool, uint64_t, int64_t, uint64_t,
+                                uint64_t) override {}
+
+  void updateRelocationsWithUnitOffset(uint64_t OriginalUnitOffset,
+                                       uint64_t OutputUnitOffset) override {}
+
   void clear() override {}
 
 protected:
diff --git a/llvm/tools/llvm-nm/llvm-nm.cpp b/llvm/tools/llvm-nm/llvm-nm.cpp
index e32aa8ab8f5bf50..fede89e9c1167df 100644
--- a/llvm/tools/llvm-nm/llvm-nm.cpp
+++ b/llvm/tools/llvm-nm/llvm-nm.cpp
@@ -561,37 +561,22 @@ struct DarwinStabName {
   const char *Name;
 };
 const struct DarwinStabName DarwinStabNames[] = {
-    {MachO::N_GSYM, "GSYM"},
-    {MachO::N_FNAME, "FNAME"},
-    {MachO::N_FUN, "FUN"},
-    {MachO::N_STSYM, "STSYM"},
-    {MachO::N_LCSYM, "LCSYM"},
-    {MachO::N_BNSYM, "BNSYM"},
-    {MachO::N_PC, "PC"},
-    {MachO::N_AST, "AST"},
-    {MachO::N_OPT, "OPT"},
-    {MachO::N_RSYM, "RSYM"},
-    {MachO::N_SLINE, "SLINE"},
-    {MachO::N_ENSYM, "ENSYM"},
-    {MachO::N_SSYM, "SSYM"},
-    {MachO::N_SO, "SO"},
-    {MachO::N_OSO, "OSO"},
-    {MachO::N_LSYM, "LSYM"},
-    {MachO::N_BINCL, "BINCL"},
-    {MachO::N_SOL, "SOL"},
-    {MachO::N_PARAMS, "PARAM"},
-    {MachO::N_VERSION, "VERS"},
-    {MachO::N_OLEVEL, "OLEV"},
-    {MachO::N_PSYM, "PSYM"},
-    {MachO::N_EINCL, "EINCL"},
-    {MachO::N_ENTRY, "ENTRY"},
-    {MachO::N_LBRAC, "LBRAC"},
-    {MachO::N_EXCL, "EXCL"},
-    {MachO::N_RBRAC, "RBRAC"},
-    {MachO::N_BCOMM, "BCOMM"},
-    {MachO::N_ECOMM, "ECOMM"},
-    {MachO::N_ECOML, "ECOML"},
-    {MachO::N_LENG, "LENG"},
+    {MachO::N_GSYM, "GSYM"},    {MachO::N_FNAME, "FNAME"},
+    {MachO::N_FUN, "FUN"},      {MachO::N_STSYM, "STSYM"},
+    {MachO::N_LCSYM, "LCSYM"},  {MachO::N_BNSYM, "BNSYM"},
+    {MachO::N_PC, "PC"},        {MachO::N_AST, "AST"},
+    {MachO::N_OPT, "OPT"},      {MachO::N_RSYM, "RSYM"},
+    {MachO::N_SLINE, "SLINE"},  {MachO::N_ENSYM, "ENSYM"},
+    {MachO::N_SSYM, "SSYM"},    {MachO::N_SO, "SO"},
+    {MachO::N_OSO, "OSO"},      {MachO::N_LIB, "LIB"},
+    {MachO::N_LSYM, "LSYM"},    {MachO::N_BINCL, "BINCL"},
+    {MachO::N_SOL, "SOL"},      {MachO::N_PARAMS, "PARAM"},
+    {MachO::N_VERSION, "VERS"}, {MachO::N_OLEVEL, "OLEV"},
+    {MachO::N_PSYM, "PSYM"},    {MachO::N_EINCL, "EINCL"},
+    {MachO::N_ENTRY, "ENTRY"},  {MachO::N_LBRAC, "LBRAC"},
+    {MachO::N_EXCL, "EXCL"},    {MachO::N_RBRAC, "RBRAC"},
+    {MachO::N_BCOMM, "BCOMM"},  {MachO::N_ECOMM, "ECOMM"},
+    {MachO::N_ECOML, "ECOML"},  {MachO::N_LENG, "LENG"},
 };
 
 static const char *getDarwinStabString(uint8_t NType) {



More information about the llvm-commits mailing list