Index: llvm/test/tools/llvm-objcopy/MachO/copy-relocations.s
===================================================================
--- /dev/null
+++ llvm/test/tools/llvm-objcopy/MachO/copy-relocations.s
@@ -0,0 +1,30 @@
+# REQUIRES: x86-registered-target
+
+## Show that llvm-objcopy copies relocation entries where r_extern=0.
+# RUN: llvm-mc -assemble -triple x86_64-apple-darwin19 -filetype=obj %s -o %t
+# RUN: llvm-objcopy %t %t2
+# RUN: cmp %t %t2
+
+## Show that llvm-objcopy updates section indices properly.
+# RUN: llvm-objcopy --remove-section=__DATA,__foo %t %t3
+# RUN: llvm-objdump --macho --reloc %t3 | FileCheck %s
+
+# $ llvm-objdump --macho --reloc copy-relocations.o
+# Relocation information (__DATA,__bar) 2 entries
+# address  pcrel length extern type    scattered symbolnum/value
+# 00000000 False quad   False  SUB     False     3 (__DATA,__bar)
+# 00000000 False quad   False  UNSIGND False     1 (__TEXT,__text)
+.text
+L1:
+  .quad 0
+
+.section __DATA,__foo
+  .quad 0
+
+.section __DATA,__bar
+  .quad   L1 - .
+
+# CHECK:      Relocation information (__DATA,__bar) 2 entries
+# CHECK-NEXT: address  pcrel length extern type    scattered symbolnum/value
+# CHECK-NEXT: 00000000 False quad   False  SUB     False     2 (__DATA,__bar)
+# CHECK-NEXT: 00000000 False quad   False  UNSIGND False     1 (__TEXT,__text)
Index: llvm/tools/llvm-objcopy/MachO/MachOLayoutBuilder.cpp
===================================================================
--- llvm/tools/llvm-objcopy/MachO/MachOLayoutBuilder.cpp
+++ llvm/tools/llvm-objcopy/MachO/MachOLayoutBuilder.cpp
@@ -142,27 +142,27 @@
     uint64_t SegOffset = Offset;
     uint64_t SegFileSize = 0;
     uint64_t VMSize = 0;
-    for (auto &Sec : LC.Sections) {
+    for (std::unique_ptr<Section> &Sec : LC.Sections) {
       if (IsObjectFile) {
-        if (Sec.isVirtualSection()) {
-          Sec.Offset = 0;
+        if (Sec->isVirtualSection()) {
+          Sec->Offset = 0;
         } else {
           uint64_t PaddingSize =
-              offsetToAlignment(SegFileSize, Align(1ull << Sec.Align));
-          Sec.Offset = SegOffset + SegFileSize + PaddingSize;
-          Sec.Size = Sec.Content.size();
-          SegFileSize += PaddingSize + Sec.Size;
+              offsetToAlignment(SegFileSize, Align(1ull << Sec->Align));
+          Sec->Offset = SegOffset + SegFileSize + PaddingSize;
+          Sec->Size = Sec->Content.size();
+          SegFileSize += PaddingSize + Sec->Size;
         }
-        VMSize = std::max(VMSize, Sec.Addr + Sec.Size);
+        VMSize = std::max(VMSize, Sec->Addr + Sec->Size);
       } else {
-        if (Sec.isVirtualSection()) {
-          Sec.Offset = 0;
-          VMSize += Sec.Size;
+        if (Sec->isVirtualSection()) {
+          Sec->Offset = 0;
+          VMSize += Sec->Size;
         } else {
-          uint32_t SectOffset = Sec.Addr - SegmentVmAddr;
-          Sec.Offset = SegOffset + SectOffset;
-          Sec.Size = Sec.Content.size();
-          SegFileSize = std::max(SegFileSize, SectOffset + Sec.Size);
+          uint32_t SectOffset = Sec->Addr - SegmentVmAddr;
+          Sec->Offset = SegOffset + SectOffset;
+          Sec->Size = Sec->Content.size();
+          SegFileSize = std::max(SegFileSize, SectOffset + Sec->Size);
           VMSize = std::max(VMSize, SegFileSize);
         }
       }
@@ -205,10 +205,10 @@
 
 uint64_t MachOLayoutBuilder::layoutRelocations(uint64_t Offset) {
   for (auto &LC : O.LoadCommands)
-    for (auto &Sec : LC.Sections) {
-      Sec.RelOff = Sec.Relocations.empty() ? 0 : Offset;
-      Sec.NReloc = Sec.Relocations.size();
-      Offset += sizeof(MachO::any_relocation_info) * Sec.NReloc;
+    for (std::unique_ptr<Section> &Sec : LC.Sections) {
+      Sec->RelOff = Sec->Relocations.empty() ? 0 : Offset;
+      Sec->NReloc = Sec->Relocations.size();
+      Offset += sizeof(MachO::any_relocation_info) * Sec->NReloc;
     }
 
   return Offset;
Index: llvm/tools/llvm-objcopy/MachO/MachOObjcopy.cpp
===================================================================
--- llvm/tools/llvm-objcopy/MachO/MachOObjcopy.cpp
+++ llvm/tools/llvm-objcopy/MachO/MachOObjcopy.cpp
@@ -18,21 +18,23 @@
 namespace macho {
 
 using namespace object;
-using SectionPred = std::function<bool(const Section &Sec)>;
+using SectionPred = std::function<bool(const std::unique_ptr<Section> &Sec)>;
 
 static void removeSections(const CopyConfig &Config, Object &Obj) {
-  SectionPred RemovePred = [](const Section &) { return false; };
+  SectionPred RemovePred = [](const std::unique_ptr<Section> &) {
+    return false;
+  };
 
   if (!Config.ToRemove.empty()) {
-    RemovePred = [&Config, RemovePred](const Section &Sec) {
-      return Config.ToRemove.matches(Sec.CanonicalName);
+    RemovePred = [&Config, RemovePred](const std::unique_ptr<Section> &Sec) {
+      return Config.ToRemove.matches(Sec->CanonicalName);
     };
   }
 
   if (Config.StripAll || Config.StripDebug) {
     // Remove all debug sections.
-    RemovePred = [RemovePred](const Section &Sec) {
-      if (Sec.Segname == "__DWARF")
+    RemovePred = [RemovePred](const std::unique_ptr<Section> &Sec) {
+      if (Sec->Segname == "__DWARF")
         return true;
 
       return RemovePred(Sec);
@@ -41,8 +43,8 @@
 
   if (!Config.OnlySection.empty()) {
     // Overwrite RemovePred because --only-section takes priority.
-    RemovePred = [&Config](const Section &Sec) {
-      return !Config.OnlySection.matches(Sec.CanonicalName);
+    RemovePred = [&Config](const std::unique_ptr<Section> &Sec) {
+      return !Config.OnlySection.matches(Sec->CanonicalName);
     };
   }
 
@@ -87,14 +89,14 @@
 static Error dumpSectionToFile(StringRef SecName, StringRef Filename,
                                Object &Obj) {
   for (LoadCommand &LC : Obj.LoadCommands)
-    for (Section &Sec : LC.Sections) {
-      if (Sec.CanonicalName == SecName) {
+    for (std::unique_ptr<Section> &Sec : LC.Sections) {
+      if (Sec->CanonicalName == SecName) {
         Expected<std::unique_ptr<FileOutputBuffer>> BufferOrErr =
-            FileOutputBuffer::create(Filename, Sec.Content.size());
+            FileOutputBuffer::create(Filename, Sec->Content.size());
         if (!BufferOrErr)
           return BufferOrErr.takeError();
         std::unique_ptr<FileOutputBuffer> Buf = std::move(*BufferOrErr);
-        llvm::copy(Sec.Content, Buf->getBufferStart());
+        llvm::copy(Sec->Content, Buf->getBufferStart());
 
         if (Error E = Buf->commit())
           return E;
@@ -122,7 +124,7 @@
   for (LoadCommand &LC : Obj.LoadCommands) {
     Optional<StringRef> SegName = LC.getSegmentName();
     if (SegName && SegName == TargetSegName) {
-      LC.Sections.push_back(Sec);
+      LC.Sections.push_back(std::make_unique<Section>(Sec));
       return Error::success();
     }
   }
@@ -130,7 +132,7 @@
   // There's no segment named TargetSegName. Create a new load command and
   // Insert a new section into it.
   LoadCommand &NewSegment = Obj.addSegment(TargetSegName);
-  NewSegment.Sections.push_back(Sec);
+  NewSegment.Sections.push_back(std::make_unique<Section>(Sec));
   return Error::success();
 }
 
@@ -187,8 +189,8 @@
 
   if (Config.StripAll)
     for (LoadCommand &LC : Obj.LoadCommands)
-      for (Section &Sec : LC.Sections)
-        Sec.Relocations.clear();
+      for (std::unique_ptr<Section> &Sec : LC.Sections)
+        Sec->Relocations.clear();
 
   for (const StringRef &Flag : Config.DumpSection) {
     std::pair<StringRef, StringRef> SecPair = Flag.split("=");
Index: llvm/tools/llvm-objcopy/MachO/MachOReader.cpp
===================================================================
--- llvm/tools/llvm-objcopy/MachO/MachOReader.cpp
+++ llvm/tools/llvm-objcopy/MachO/MachOReader.cpp
@@ -59,25 +59,25 @@
 
 // TODO: get rid of reportError and make MachOReader return Expected<> instead.
 template <typename SectionType, typename SegmentType>
-std::vector<Section>
+std::vector<std::unique_ptr<Section>>
 extractSections(const object::MachOObjectFile::LoadCommandInfo &LoadCmd,
                 const object::MachOObjectFile &MachOObj,
                 size_t &NextSectionIndex) {
   auto End = LoadCmd.Ptr + LoadCmd.C.cmdsize;
   const SectionType *Curr =
       reinterpret_cast<const SectionType *>(LoadCmd.Ptr + sizeof(SegmentType));
-  std::vector<Section> Sections;
+  std::vector<std::unique_ptr<Section>> Sections;
   for (; reinterpret_cast<const void *>(Curr) < End; Curr++) {
     if (MachOObj.isLittleEndian() != sys::IsLittleEndianHost) {
       SectionType Sec;
       memcpy((void *)&Sec, Curr, sizeof(SectionType));
       MachO::swapStruct(Sec);
-      Sections.push_back(constructSection(Sec));
+      Sections.push_back(std::make_unique<Section>(constructSection(Sec)));
     } else {
-      Sections.push_back(constructSection(*Curr));
+      Sections.push_back(std::make_unique<Section>(constructSection(*Curr)));
     }
 
-    Section &S = Sections.back();
+    std::unique_ptr<Section> &S = Sections.back();
 
     Expected<object::SectionRef> SecRef =
         MachOObj.getSection(NextSectionIndex++);
@@ -86,12 +86,12 @@
 
     if (Expected<ArrayRef<uint8_t>> E =
             MachOObj.getSectionContents(SecRef->getRawDataRefImpl()))
-      S.Content =
+      S->Content =
           StringRef(reinterpret_cast<const char *>(E->data()), E->size());
     else
       reportError(MachOObj.getFileName(), E.takeError());
 
-    S.Relocations.reserve(S.NReloc);
+    S->Relocations.reserve(S->NReloc);
     for (auto RI = MachOObj.section_rel_begin(SecRef->getRawDataRefImpl()),
               RE = MachOObj.section_rel_end(SecRef->getRawDataRefImpl());
          RI != RE; ++RI) {
@@ -99,10 +99,12 @@
       R.Symbol = nullptr; // We'll fill this field later.
       R.Info = MachOObj.getRelocation(RI->getRawDataRefImpl());
       R.Scattered = MachOObj.isRelocationScattered(R.Info);
-      S.Relocations.push_back(R);
+      R.Extern =
+          R.Scattered ? false : MachOObj.getPlainRelocationExternal(R.Info);
+      S->Relocations.push_back(R);
     }
 
-    assert(S.NReloc == S.Relocations.size() &&
+    assert(S->NReloc == S->Relocations.size() &&
            "Incorrect number of relocations");
   }
   return Sections;
@@ -201,12 +203,24 @@
 }
 
 void MachOReader::setSymbolInRelocationInfo(Object &O) const {
+  std::vector<const Section *> Sections;
+
+  for (auto &LC : O.LoadCommands)
+    for (std::unique_ptr<Section> &Sec : LC.Sections)
+      Sections.push_back(Sec.get());
+
   for (auto &LC : O.LoadCommands)
     for (auto &Sec : LC.Sections)
-      for (auto &Reloc : Sec.Relocations)
+      for (auto &Reloc : Sec->Relocations)
         if (!Reloc.Scattered) {
           auto *Info = reinterpret_cast<MachO::relocation_info *>(&Reloc.Info);
-          Reloc.Symbol = O.SymTable.getSymbolByIndex(Info->r_symbolnum);
+          if (Reloc.Extern)
+            Reloc.Symbol = O.SymTable.getSymbolByIndex(Info->r_symbolnum);
+          else {
+            assert(Info->r_symbolnum <= Sections.size() &&
+                   "Invalid section index.");
+            Reloc.Section = Sections[Info->r_symbolnum - 1];
+          }
         }
 }
 
Index: llvm/tools/llvm-objcopy/MachO/MachOWriter.cpp
===================================================================
--- llvm/tools/llvm-objcopy/MachO/MachOWriter.cpp
+++ llvm/tools/llvm-objcopy/MachO/MachOWriter.cpp
@@ -112,10 +112,10 @@
   // Otherwise, use the last section / reloction.
   for (const auto &LC : O.LoadCommands)
     for (const auto &S : LC.Sections) {
-      Ends.push_back(S.Offset + S.Size);
-      if (S.RelOff)
-        Ends.push_back(S.RelOff +
-                       S.NReloc * sizeof(MachO::any_relocation_info));
+      Ends.push_back(S->Offset + S->Size);
+      if (S->RelOff)
+        Ends.push_back(S->RelOff +
+                       S->NReloc * sizeof(MachO::any_relocation_info));
     }
 
   if (!Ends.empty())
@@ -157,8 +157,8 @@
       memcpy(Begin, &MLC.segment_command_data, sizeof(MachO::segment_command));
       Begin += sizeof(MachO::segment_command);
 
-      for (const auto &Sec : LC.Sections)
-        writeSectionInLoadCommand<MachO::section>(Sec, Begin);
+      for (const std::unique_ptr<Section> &Sec : LC.Sections)
+        writeSectionInLoadCommand<MachO::section>(*Sec, Begin);
       continue;
     case MachO::LC_SEGMENT_64:
       if (IsLittleEndian != sys::IsLittleEndianHost)
@@ -167,8 +167,8 @@
              sizeof(MachO::segment_command_64));
       Begin += sizeof(MachO::segment_command_64);
 
-      for (const auto &Sec : LC.Sections)
-        writeSectionInLoadCommand<MachO::section_64>(Sec, Begin);
+      for (const std::unique_ptr<Section> &Sec : LC.Sections)
+        writeSectionInLoadCommand<MachO::section_64>(*Sec, Begin);
       continue;
     }
 
@@ -229,27 +229,35 @@
 }
 
 void MachOWriter::writeSections() {
+  uint32_t SectionIndex = 1;
   for (const auto &LC : O.LoadCommands)
-    for (const auto &Sec : LC.Sections) {
-      if (Sec.isVirtualSection())
+    for (const std::unique_ptr<Section> &Sec : LC.Sections)
+      Sec->Index = SectionIndex++;
+
+  for (const auto &LC : O.LoadCommands)
+    for (const std::unique_ptr<Section> &Sec : LC.Sections) {
+      if (Sec->isVirtualSection())
         continue;
 
-      assert(Sec.Offset && "Section offset can not be zero");
-      assert((Sec.Size == Sec.Content.size()) && "Incorrect section size");
-      memcpy(B.getBufferStart() + Sec.Offset, Sec.Content.data(),
-             Sec.Content.size());
-      for (size_t Index = 0; Index < Sec.Relocations.size(); ++Index) {
-        auto RelocInfo = Sec.Relocations[Index];
+      assert(Sec->Offset && "Section offset can not be zero");
+      assert((Sec->Size == Sec->Content.size()) && "Incorrect section size");
+      memcpy(B.getBufferStart() + Sec->Offset, Sec->Content.data(),
+             Sec->Content.size());
+      for (size_t Index = 0; Index < Sec->Relocations.size(); ++Index) {
+        auto RelocInfo = Sec->Relocations[Index];
         if (!RelocInfo.Scattered) {
           auto *Info =
               reinterpret_cast<MachO::relocation_info *>(&RelocInfo.Info);
-          Info->r_symbolnum = RelocInfo.Symbol->Index;
+          if (RelocInfo.Extern)
+            Info->r_symbolnum = (*RelocInfo.Symbol)->Index;
+          else
+            Info->r_symbolnum = (*RelocInfo.Section)->Index;
         }
 
         if (IsLittleEndian != sys::IsLittleEndianHost)
           MachO::swapStruct(
               reinterpret_cast<MachO::any_relocation_info &>(RelocInfo.Info));
-        memcpy(B.getBufferStart() + Sec.RelOff +
+        memcpy(B.getBufferStart() + Sec->RelOff +
                    Index * sizeof(MachO::any_relocation_info),
                &RelocInfo.Info, sizeof(RelocInfo.Info));
       }
Index: llvm/tools/llvm-objcopy/MachO/Object.h
===================================================================
--- llvm/tools/llvm-objcopy/MachO/Object.h
+++ llvm/tools/llvm-objcopy/MachO/Object.h
@@ -37,6 +37,7 @@
 
 struct RelocationInfo;
 struct Section {
+  uint32_t Index;
   std::string Segname;
   std::string Sectname;
   // CanonicalName is a string formatted as “<Segname>,<Sectname>".
@@ -83,13 +84,13 @@
   // The raw content of the payload of the load command (located right after the
   // corresponding struct). In some cases it is either empty or can be
   // copied-over without digging into its structure.
-  std::vector<uint8_t> Payload; 
+  std::vector<uint8_t> Payload;
 
   // Some load commands can contain (inside the payload) an array of sections,
   // though the contents of the sections are stored separately. The struct
   // Section describes only sections' metadata and where to find the
   // corresponding content inside the binary.
-  std::vector<Section> Sections;
+  std::vector<std::unique_ptr<Section>> Sections;
 
   // Returns the segment name if the load command is a segment command.
   Optional<StringRef> getSegmentName() const;
@@ -157,9 +158,14 @@
 };
 
 struct RelocationInfo {
-  const SymbolEntry *Symbol;
+  // The referenced symbol entry. Set if !Scattered && Extern.
+  Optional<const SymbolEntry *> Symbol;
+  // The referenced section. Set if !Scattered && !Extern.
+  Optional<const Section *> Section;
   // True if Info is a scattered_relocation_info.
   bool Scattered;
+  // True if the r_symbolnum points to a section number (i.e. r_extern=0).
+  bool Extern;
   MachO::any_relocation_info Info;
 };
 
@@ -292,7 +298,8 @@
 
   Object() : NewSectionsContents(Alloc) {}
 
-  void removeSections(function_ref<bool(const Section &)> ToRemove);
+  void
+  removeSections(function_ref<bool(const std::unique_ptr<Section> &)> ToRemove);
   void addLoadCommand(LoadCommand LC);
 
   /// Creates a new segment load command in the object and returns a reference
Index: llvm/tools/llvm-objcopy/MachO/Object.cpp
===================================================================
--- llvm/tools/llvm-objcopy/MachO/Object.cpp
+++ llvm/tools/llvm-objcopy/MachO/Object.cpp
@@ -22,7 +22,8 @@
       std::end(Symbols));
 }
 
-void Object::removeSections(function_ref<bool(const Section &)> ToRemove) {
+void Object::removeSections(
+    function_ref<bool(const std::unique_ptr<Section> &)> ToRemove) {
   for (LoadCommand &LC : LoadCommands)
     LC.Sections.erase(std::remove_if(std::begin(LC.Sections),
                                      std::end(LC.Sections), ToRemove),
@@ -52,7 +53,7 @@
     constructSegment(LC.MachOLoadCommand.segment_command_data,
                      MachO::LC_SEGMENT, SegName);
 
-  LoadCommands.push_back(LC);
+  LoadCommands.push_back(std::move(LC));
   return LoadCommands.back();
 }