Bug 1471698 - Switch the mingw clang compiler to the 8 branch r=froydnj a=jcristau
authorTom Ritter <tom@mozilla.com>
Fri, 17 May 2019 19:21:15 +0000
changeset 536398 53f8a0553b0e74e4764a49983d63e9f89136bfd5
parent 536397 fc4e6975d7fec01df2324aa508b67445554b5c8c
child 536399 438492603ace6b0739168979fff3a2fb039db111
push id2082
push userffxbld-merge
push dateMon, 01 Jul 2019 08:34:18 +0000
treeherdermozilla-release@2fb19d0466d2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfroydnj, jcristau
bugs1471698
milestone68.0
Bug 1471698 - Switch the mingw clang compiler to the 8 branch r=froydnj a=jcristau This will match the compiler version Tor would like. We backport several llvm-objcopy patches that landed right after the 8 branch though. We also grab some upstream changes from mingw-clang in the build script Differential Revision: https://phabricator.services.mozilla.com/D31347
build/build-clang/clang-8-mingw.json
build/build-clang/mingwclang-Reapply-llvm-objcopy-COFF-Implement-add-gnu-debuglin.patch
build/build-clang/mingwclang-llvm-objcopy-COFF-Add-support-for-removing-sections.patch
build/build-clang/mingwclang-llvm-objcopy-COFF-Clear-the-unwritten-tail-of-coff_s.patch
build/build-clang/mingwclang-llvm-objcopy-COFF-Error-out-on-use-of-unhandled-opti.patch
build/build-clang/mingwclang-llvm-objcopy-COFF-Fix-handling-of-aux-symbols-for-bi.patch
build/build-clang/mingwclang-llvm-objcopy-COFF-Implement-only-keep-debug.patch
build/build-clang/mingwclang-llvm-objcopy-COFF-Implement-only-section.patch
build/build-clang/mingwclang-llvm-objcopy-COFF-Implement-strip-debug.patch
build/build-clang/mingwclang-llvm-objcopy-COFF-Remove-a-superfluous-namespace-qua.patch
build/build-clang/mingwclang-llvm-objcopy-COFF-Update-symbol-indices-in-weak-exte.patch
build/build-clang/mingwclang-llvm-objcopy-Consistently-use-createStringError-inst.patch
build/build-clang/mingwclang-llvm-objcopy-Return-Error-from-Buffer-allocate-ELF-W.patch
taskcluster/scripts/misc/build-clang-8-mingw.sh
old mode 100644
new mode 100755
--- a/build/build-clang/clang-8-mingw.json
+++ b/build/build-clang/clang-8-mingw.json
@@ -1,20 +1,32 @@
 {
-    "llvm_revision": "348363",
+    "llvm_revision": "356265",
     "stages": "3",
     "build_libcxx": true,
     "build_type": "Release",
     "assertions": false,
-    "llvm_repo": "https://llvm.org/svn/llvm-project/llvm/trunk",
-    "clang_repo": "https://llvm.org/svn/llvm-project/cfe/trunk",
-    "lld_repo": "https://llvm.org/svn/llvm-project/lld/trunk",
-    "compiler_repo": "https://llvm.org/svn/llvm-project/compiler-rt/trunk",
-    "libcxx_repo": "https://llvm.org/svn/llvm-project/libcxx/trunk",
-    "libcxxabi_repo": "https://llvm.org/svn/llvm-project/libcxxabi/trunk",
+    "llvm_repo": "https://llvm.org/svn/llvm-project/llvm/tags/RELEASE_800/final",
+    "clang_repo": "https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_800/final",
+    "lld_repo": "https://llvm.org/svn/llvm-project/lld/tags/RELEASE_800/final",
+    "compiler_repo": "https://llvm.org/svn/llvm-project/compiler-rt/tags/RELEASE_800/final",
+    "libcxx_repo": "https://llvm.org/svn/llvm-project/libcxx/tags/RELEASE_800/final",
+    "libcxxabi_repo": "https://llvm.org/svn/llvm-project/libcxxabi/tags/RELEASE_800/final",
     "python_path": "/usr/bin/python2.7",
     "gcc_dir": "/builds/worker/workspace/build/src/gcc",
     "cc": "/builds/worker/workspace/build/src/gcc/bin/gcc",
     "cxx": "/builds/worker/workspace/build/src/gcc/bin/g++",
     "as": "/builds/worker/workspace/build/src/gcc/bin/gcc",
     "patches": [
+        "mingwclang-llvm-objcopy-COFF-Remove-a-superfluous-namespace-qua.patch",
+        "mingwclang-llvm-objcopy-COFF-Add-support-for-removing-sections.patch",
+        "mingwclang-llvm-objcopy-COFF-Implement-strip-debug.patch",
+        "mingwclang-llvm-objcopy-COFF-Implement-only-keep-debug.patch",
+        "mingwclang-llvm-objcopy-COFF-Implement-only-section.patch",
+        "mingwclang-llvm-objcopy-Consistently-use-createStringError-inst.patch",
+        "mingwclang-llvm-objcopy-COFF-Update-symbol-indices-in-weak-exte.patch",
+        "mingwclang-llvm-objcopy-Return-Error-from-Buffer-allocate-ELF-W.patch",
+        "mingwclang-Reapply-llvm-objcopy-COFF-Implement-add-gnu-debuglin.patch",
+        "mingwclang-llvm-objcopy-COFF-Clear-the-unwritten-tail-of-coff_s.patch",
+        "mingwclang-llvm-objcopy-COFF-Fix-handling-of-aux-symbols-for-bi.patch",
+        "mingwclang-llvm-objcopy-COFF-Error-out-on-use-of-unhandled-opti.patch"
     ]
 }
new file mode 100644
--- /dev/null
+++ b/build/build-clang/mingwclang-Reapply-llvm-objcopy-COFF-Implement-add-gnu-debuglin.patch
@@ -0,0 +1,260 @@
+From 840d70f854a1d550924ced1d00160efcc7b8549a Mon Sep 17 00:00:00 2001
+From: Martin Storsjo <martin@martin.st>
+Date: Wed, 23 Jan 2019 08:25:28 +0000
+Subject: [PATCH] Reapply: [llvm-objcopy] [COFF] Implement --add-gnu-debuglink
+
+This was reverted since it broke a couple buildbots. The reason
+for the breakage is not yet known, but this time, the test has
+got more diagnostics added, to hopefully allow figuring out
+what goes wrong.
+
+Differential Revision: https://reviews.llvm.org/D57007
+
+git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@351931 91177308-0d34-0410-b5e6-96231b3b80d8
+---
+ .../llvm-objcopy/COFF/add-gnu-debuglink.test  | 48 +++++++++++++++
+ tools/llvm-objcopy/COFF/COFFObjcopy.cpp       | 61 +++++++++++++++++++
+ tools/llvm-objcopy/COFF/Object.cpp            |  2 +-
+ tools/llvm-objcopy/COFF/Object.h              | 26 +++++++-
+ tools/llvm-objcopy/COFF/Reader.cpp            |  4 +-
+ tools/llvm-objcopy/COFF/Writer.cpp            |  9 +--
+ 6 files changed, 143 insertions(+), 7 deletions(-)
+ create mode 100644 test/tools/llvm-objcopy/COFF/add-gnu-debuglink.test
+
+diff --git a/llvm/test/tools/llvm-objcopy/COFF/add-gnu-debuglink.test b/llvm/test/tools/llvm-objcopy/COFF/add-gnu-debuglink.test
+new file mode 100644
+index 00000000000..cf3a9bba920
+--- /dev/null
++++ b/llvm/test/tools/llvm-objcopy/COFF/add-gnu-debuglink.test
+@@ -0,0 +1,48 @@
++RUN: yaml2obj %p/Inputs/x86_64-exe.yaml > %t.in123.exe
++
++# Using a debuglink filename with a length that is a multiple of 4, to
++# showcase padding in CONTENTS below.
++
++RUN: llvm-objcopy --add-gnu-debuglink=%t.in123.exe %t.in123.exe %t.out.exe
++
++# Temporary debugging of issues with this test:
++RUN: ls -l %t.out.exe || true
++RUN: od -Ax -t x1 %t.out.exe || true
++RUN: llvm-readobj -sections %t.out.exe || true
++
++RUN: llvm-readobj -sections %t.out.exe | FileCheck %s --check-prefix=SECTIONS
++RUN: llvm-objdump -s %t.out.exe | FileCheck %s --check-prefix=CONTENTS
++
++# Show the last of the preexisting sections, which is used for choosing
++# a virtual address for the generated one.
++
++SECTIONS:        Section {
++SECTIONS:          Number: 4
++SECTIONS-NEXT:     Name: .pdata
++SECTIONS-NEXT:     VirtualSize: 0x18
++SECTIONS-NEXT:     VirtualAddress: 0x4000
++SECTIONS-NEXT:     RawDataSize: 512
++SECTIONS:        Section {
++SECTIONS-NEXT:     Number: 5
++SECTIONS-NEXT:     Name: .gnu_debuglink
++SECTIONS-NEXT:     VirtualSize: 0x2C
++SECTIONS-NEXT:     VirtualAddress: 0x5000
++SECTIONS-NEXT:     RawDataSize: 512
++SECTIONS-NEXT:     PointerToRawData:
++SECTIONS-NEXT:     PointerToRelocations:
++SECTIONS-NEXT:     PointerToLineNumbers:
++SECTIONS-NEXT:     RelocationCount:
++SECTIONS-NEXT:     LineNumberCount:
++SECTIONS-NEXT:     Characteristics [ (0x42000040)
++SECTIONS-NEXT:       IMAGE_SCN_CNT_INITIALIZED_DATA (0x40)
++SECTIONS-NEXT:       IMAGE_SCN_MEM_DISCARDABLE (0x2000000)
++SECTIONS-NEXT:       IMAGE_SCN_MEM_READ (0x40000000)
++SECTIONS-NEXT:     ]
++
++# Note: The last 4 bytes here are the crc of the referenced file - if the
++# yaml2obj generated file changes, this crc changes.
++
++CONTENTS: Contents of section .gnu_debuglink:
++CONTENTS:  40005000 6164642d 676e752d 64656275 676c696e  add-gnu-debuglin
++CONTENTS:  40005010 6b2e7465 73742e74 6d702e69 6e313233  k.test.tmp.in123
++CONTENTS:  40005020 2e657865 00000000 7929adc3           .exe
+diff --git a/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp b/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp
+index 8d8f53d13d8..20adbe11e7a 100644
+--- a/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp
++++ b/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp
+@@ -17,6 +17,8 @@
+ #include "llvm/Object/Binary.h"
+ #include "llvm/Object/COFF.h"
+ #include "llvm/Support/Errc.h"
++#include "llvm/Support/JamCRC.h"
++#include "llvm/Support/Path.h"
+ #include <cassert>
+ 
+ namespace llvm {
+@@ -30,6 +32,61 @@ static bool isDebugSection(const Section &Sec) {
+   return Sec.Name.startswith(".debug");
+ }
+ 
++static uint64_t getNextRVA(const Object &Obj) {
++  if (Obj.getSections().empty())
++    return 0;
++  const Section &Last = Obj.getSections().back();
++  return alignTo(Last.Header.VirtualAddress + Last.Header.VirtualSize,
++                 Obj.PeHeader.SectionAlignment);
++}
++
++static uint32_t getCRC32(StringRef Data) {
++  JamCRC CRC;
++  CRC.update(ArrayRef<char>(Data.data(), Data.size()));
++  // The CRC32 value needs to be complemented because the JamCRC dosn't
++  // finalize the CRC32 value. It also dosn't negate the initial CRC32 value
++  // but it starts by default at 0xFFFFFFFF which is the complement of zero.
++  return ~CRC.getCRC();
++}
++
++static std::vector<uint8_t> createGnuDebugLinkSectionContents(StringRef File) {
++  ErrorOr<std::unique_ptr<MemoryBuffer>> LinkTargetOrErr =
++      MemoryBuffer::getFile(File);
++  if (!LinkTargetOrErr)
++    error("'" + File + "': " + LinkTargetOrErr.getError().message());
++  auto LinkTarget = std::move(*LinkTargetOrErr);
++  uint32_t CRC32 = getCRC32(LinkTarget->getBuffer());
++
++  StringRef FileName = sys::path::filename(File);
++  size_t CRCPos = alignTo(FileName.size() + 1, 4);
++  std::vector<uint8_t> Data(CRCPos + 4);
++  memcpy(Data.data(), FileName.data(), FileName.size());
++  support::endian::write32le(Data.data() + CRCPos, CRC32);
++  return Data;
++}
++
++static void addGnuDebugLink(Object &Obj, StringRef DebugLinkFile) {
++  uint32_t StartRVA = getNextRVA(Obj);
++
++  std::vector<Section> Sections;
++  Section Sec;
++  Sec.setOwnedContents(createGnuDebugLinkSectionContents(DebugLinkFile));
++  Sec.Name = ".gnu_debuglink";
++  Sec.Header.VirtualSize = Sec.getContents().size();
++  Sec.Header.VirtualAddress = StartRVA;
++  Sec.Header.SizeOfRawData =
++      alignTo(Sec.Header.VirtualSize, Obj.PeHeader.FileAlignment);
++  // Sec.Header.PointerToRawData is filled in by the writer.
++  Sec.Header.PointerToRelocations = 0;
++  Sec.Header.PointerToLinenumbers = 0;
++  // Sec.Header.NumberOfRelocations is filled in by the writer.
++  Sec.Header.NumberOfLinenumbers = 0;
++  Sec.Header.Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA |
++                               IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_DISCARDABLE;
++  Sections.push_back(Sec);
++  Obj.addSections(Sections);
++}
++
+ static Error handleArgs(const CopyConfig &Config, Object &Obj) {
+   // Perform the actual section removals.
+   Obj.removeSections([&Config](const Section &Sec) {
+@@ -109,6 +166,10 @@ static Error handleArgs(const CopyConfig &Config, Object &Obj) {
+ 
+     return false;
+   });
++
++  if (!Config.AddGnuDebugLink.empty())
++    addGnuDebugLink(Obj, Config.AddGnuDebugLink);
++
+   return Error::success();
+ }
+ 
+diff --git a/llvm/tools/llvm-objcopy/COFF/Object.cpp b/llvm/tools/llvm-objcopy/COFF/Object.cpp
+index 83435dffa98..8c382c1faef 100644
+--- a/llvm/tools/llvm-objcopy/COFF/Object.cpp
++++ b/llvm/tools/llvm-objcopy/COFF/Object.cpp
+@@ -129,7 +129,7 @@ void Object::removeSections(function_ref<bool(const Section &)> ToRemove) {
+ void Object::truncateSections(function_ref<bool(const Section &)> ToTruncate) {
+   for (Section &Sec : Sections) {
+     if (ToTruncate(Sec)) {
+-      Sec.Contents = ArrayRef<uint8_t>();
++      Sec.clearContents();
+       Sec.Relocs.clear();
+       Sec.Header.SizeOfRawData = 0;
+     }
+diff --git a/llvm/tools/llvm-objcopy/COFF/Object.h b/llvm/tools/llvm-objcopy/COFF/Object.h
+index 0630f9c5ff8..afa272286ef 100644
+--- a/llvm/tools/llvm-objcopy/COFF/Object.h
++++ b/llvm/tools/llvm-objcopy/COFF/Object.h
+@@ -35,11 +35,35 @@ struct Relocation {
+ 
+ struct Section {
+   object::coff_section Header;
+-  ArrayRef<uint8_t> Contents;
+   std::vector<Relocation> Relocs;
+   StringRef Name;
+   ssize_t UniqueId;
+   size_t Index;
++
++  ArrayRef<uint8_t> getContents() const {
++    if (!OwnedContents.empty())
++      return OwnedContents;
++    return ContentsRef;
++  }
++
++  void setContentsRef(ArrayRef<uint8_t> Data) {
++    OwnedContents.clear();
++    ContentsRef = Data;
++  }
++
++  void setOwnedContents(std::vector<uint8_t> &&Data) {
++    ContentsRef = ArrayRef<uint8_t>();
++    OwnedContents = std::move(Data);
++  }
++
++  void clearContents() {
++    ContentsRef = ArrayRef<uint8_t>();
++    OwnedContents.clear();
++  }
++
++private:
++  ArrayRef<uint8_t> ContentsRef;
++  std::vector<uint8_t> OwnedContents;
+ };
+ 
+ struct Symbol {
+diff --git a/llvm/tools/llvm-objcopy/COFF/Reader.cpp b/llvm/tools/llvm-objcopy/COFF/Reader.cpp
+index 2446277cc2b..87dd60a43cf 100644
+--- a/llvm/tools/llvm-objcopy/COFF/Reader.cpp
++++ b/llvm/tools/llvm-objcopy/COFF/Reader.cpp
+@@ -69,8 +69,10 @@ Error COFFReader::readSections(Object &Obj) const {
+     Sections.push_back(Section());
+     Section &S = Sections.back();
+     S.Header = *Sec;
+-    if (auto EC = COFFObj.getSectionContents(Sec, S.Contents))
++    ArrayRef<uint8_t> Contents;
++    if (auto EC = COFFObj.getSectionContents(Sec, Contents))
+       return errorCodeToError(EC);
++    S.setContentsRef(Contents);
+     ArrayRef<coff_relocation> Relocs = COFFObj.getRelocations(Sec);
+     for (const coff_relocation &R : Relocs)
+       S.Relocs.push_back(R);
+diff --git a/llvm/tools/llvm-objcopy/COFF/Writer.cpp b/llvm/tools/llvm-objcopy/COFF/Writer.cpp
+index db3589bb119..05e46291c39 100644
+--- a/llvm/tools/llvm-objcopy/COFF/Writer.cpp
++++ b/llvm/tools/llvm-objcopy/COFF/Writer.cpp
+@@ -286,14 +286,15 @@ void COFFWriter::writeHeaders(bool IsBigObj) {
+ void COFFWriter::writeSections() {
+   for (const auto &S : Obj.getSections()) {
+     uint8_t *Ptr = Buf.getBufferStart() + S.Header.PointerToRawData;
+-    std::copy(S.Contents.begin(), S.Contents.end(), Ptr);
++    ArrayRef<uint8_t> Contents = S.getContents();
++    std::copy(Contents.begin(), Contents.end(), Ptr);
+ 
+     // For executable sections, pad the remainder of the raw data size with
+     // 0xcc, which is int3 on x86.
+     if ((S.Header.Characteristics & IMAGE_SCN_CNT_CODE) &&
+-        S.Header.SizeOfRawData > S.Contents.size())
+-      memset(Ptr + S.Contents.size(), 0xcc,
+-             S.Header.SizeOfRawData - S.Contents.size());
++        S.Header.SizeOfRawData > Contents.size())
++      memset(Ptr + Contents.size(), 0xcc,
++             S.Header.SizeOfRawData - Contents.size());
+ 
+     Ptr += S.Header.SizeOfRawData;
+     for (const auto &R : S.Relocs) {
+-- 
+2.17.1
+
new file mode 100644
--- /dev/null
+++ b/build/build-clang/mingwclang-llvm-objcopy-COFF-Add-support-for-removing-sections.patch
@@ -0,0 +1,665 @@
+From 2ccafacb7ddd740054dbee06655749ebc55a4d86 Mon Sep 17 00:00:00 2001
+From: Martin Storsjo <martin@martin.st>
+Date: Sat, 19 Jan 2019 19:42:35 +0000
+Subject: [PATCH] [llvm-objcopy] [COFF] Add support for removing sections
+
+Differential Revision: https://reviews.llvm.org/D56683
+
+git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@351660 91177308-0d34-0410-b5e6-96231b3b80d8
+---
+ .../llvm-objcopy/COFF/remove-section.test     | 210 ++++++++++++++++++
+ tools/llvm-objcopy/COFF/COFFObjcopy.cpp       |  10 +-
+ tools/llvm-objcopy/COFF/Object.cpp            |  63 ++++++
+ tools/llvm-objcopy/COFF/Object.h              |  27 ++-
+ tools/llvm-objcopy/COFF/Reader.cpp            |  31 ++-
+ tools/llvm-objcopy/COFF/Writer.cpp            |  68 ++++--
+ tools/llvm-objcopy/COFF/Writer.h              |   1 +
+ 7 files changed, 391 insertions(+), 19 deletions(-)
+ create mode 100644 test/tools/llvm-objcopy/COFF/remove-section.test
+
+diff --git a/llvm/test/tools/llvm-objcopy/COFF/remove-section.test b/llvm/test/tools/llvm-objcopy/COFF/remove-section.test
+new file mode 100644
+index 00000000000..b3dfb0b98cb
+--- /dev/null
++++ b/llvm/test/tools/llvm-objcopy/COFF/remove-section.test
+@@ -0,0 +1,210 @@
++# RUN: yaml2obj %s > %t.in.o
++#
++# RUN: llvm-objdump -section-headers %t.in.o | FileCheck %s --check-prefixes=SECTIONS-PRE
++# RUN: llvm-objdump -t %t.in.o | FileCheck %s --check-prefixes=SYMBOLS-PRE
++#
++# RUN: llvm-objcopy -R .bss %t.in.o %t.remove-bss.o
++# RUN: llvm-objdump -section-headers %t.remove-bss.o | FileCheck %s --check-prefix=SECTIONS-REMOVE-BSS
++# RUN: llvm-objdump -t %t.remove-bss.o | FileCheck %s --check-prefix=SYMBOLS-REMOVE-BSS
++#
++# RUN: llvm-objcopy --remove-section .bss %t.in.o %t.cmp.o
++# RUN: cmp %t.remove-bss.o %t.cmp.o
++#
++# RUN: llvm-objcopy -R .text %t.in.o %t.remove-text.o
++# RUN: llvm-objdump -section-headers %t.remove-text.o | FileCheck %s --check-prefix=SECTIONS-REMOVE-TEXT
++# RUN: llvm-objdump -t %t.remove-text.o | FileCheck %s --check-prefix=SYMBOLS-REMOVE-TEXT
++#
++# RUN: not llvm-objcopy -R .comdat %t.in.o %t.remove-comdat.o 2>&1 | FileCheck %s --check-prefix=ERROR-RELOC
++#
++# RUN: llvm-objcopy -R .text -R .comdat %t.in.o %t.remove-text-comdat.o
++# RUN: llvm-objdump -section-headers %t.remove-text-comdat.o | FileCheck %s --check-prefix=SECTIONS-REMOVE-TEXT-COMDAT
++# RUN: llvm-objdump -t %t.remove-text-comdat.o | FileCheck %s --check-prefix=SYMBOLS-REMOVE-TEXT-COMDAT
++#
++#
++# SECTIONS-PRE: Sections:
++# SECTIONS-PRE-NEXT: Idx Name
++# SECTIONS-PRE-NEXT: 0 .text
++# SECTIONS-PRE-NEXT: 1 .bss
++# SECTIONS-PRE-NEXT: 2 .comdat
++# SECTIONS-PRE-NEXT: 3 .associative
++# SECTIONS-PRE-EMPTY:
++#
++# SYMBOLS-PRE: SYMBOL TABLE:
++# SYMBOLS-PRE-NEXT: {{.*}}(sec -1){{.*}} @feat.00
++# SYMBOLS-PRE-NEXT: {{.*}}(sec 1){{.*}} .text
++# SYMBOLS-PRE-NEXT: AUX scnlen {{.*}} assoc 1 comdat 0
++# SYMBOLS-PRE-NEXT: {{.*}}(sec 2){{.*}} .bss
++# SYMBOLS-PRE-NEXT: AUX scnlen {{.*}} assoc 2 comdat 0
++# SYMBOLS-PRE-NEXT: {{.*}}(sec 4){{.*}} .associative
++# SYMBOLS-PRE-NEXT: AUX scnlen {{.*}} assoc 3 comdat 5
++# SYMBOLS-PRE-NEXT: {{.*}}(sec 3){{.*}} .comdat
++# SYMBOLS-PRE-NEXT: AUX scnlen {{.*}} assoc 3 comdat 2
++# SYMBOLS-PRE-NEXT: {{.*}}(sec 3){{.*}} foo
++# SYMBOLS-PRE-NEXT: {{.*}}(sec 1){{.*}} main
++# SYMBOLS-PRE-EMPTY:
++#
++#
++# Removing the .bss section removes one symbol and its aux symbol,
++# and updates the section indices in symbols pointing to later
++# symbols, including the aux section defintitions.
++#
++# Testing that the absolute symbol @feat.00 survives the section number
++# mangling.
++#
++# SECTIONS-REMOVE-BSS: Sections:
++# SECTIONS-REMOVE-BSS-NEXT: Idx Name
++# SECTIONS-REMOVE-BSS-NEXT: 0 .text
++# SECTIONS-REMOVE-BSS-NEXT: 1 .comdat
++# SECTIONS-REMOVE-BSS-NEXT: 2 .associative
++# SECTIONS-REMOVE-BSS-EMPTY:
++#
++# SYMBOLS-REMOVE-BSS: SYMBOL TABLE:
++# SYMBOLS-REMOVE-BSS-NEXT: {{.*}}(sec -1){{.*}} @feat.00
++# SYMBOLS-REMOVE-BSS-NEXT: {{.*}}(sec 1){{.*}} .text
++# SYMBOLS-REMOVE-BSS-NEXT: AUX scnlen {{.*}} assoc 1 comdat 0
++# SYMBOLS-REMOVE-BSS-NEXT: {{.*}}(sec 3){{.*}} .associative
++# SYMBOLS-REMOVE-BSS-NEXT: AUX scnlen {{.*}} assoc 2 comdat 5
++# SYMBOLS-REMOVE-BSS-NEXT: {{.*}}(sec 2){{.*}} .comdat
++# SYMBOLS-REMOVE-BSS-NEXT: AUX scnlen {{.*}} assoc 2 comdat 2
++# SYMBOLS-REMOVE-BSS-NEXT: {{.*}}(sec 2){{.*}} foo
++# SYMBOLS-REMOVE-BSS-NEXT: {{.*}}(sec 1){{.*}} main
++# SYMBOLS-REMOVE-BSS-EMPTY:
++#
++#
++# Removing the .text section is ok and just removes the external symbol
++# referring to it.
++#
++# SECTIONS-REMOVE-TEXT: Sections:
++# SECTIONS-REMOVE-TEXT-NEXT: Idx Name
++# SECTIONS-REMOVE-TEXT-NEXT: 0 .bss
++# SECTIONS-REMOVE-TEXT-NEXT: 1 .comdat
++# SECTIONS-REMOVE-TEXT-NEXT: 2 .associative
++# SECTIONS-REMOVE-TEXT-EMPTY:
++#
++# SYMBOLS-REMOVE-TEXT: SYMBOL TABLE:
++# SYMBOLS-REMOVE-TEXT-NEXT: {{.*}}(sec -1){{.*}} @feat.00
++# SYMBOLS-REMOVE-TEXT-NEXT: {{.*}}(sec 1){{.*}} .bss
++# SYMBOLS-REMOVE-TEXT-NEXT: AUX scnlen {{.*}} assoc 1 comdat 0
++# SYMBOLS-REMOVE-TEXT-NEXT: {{.*}}(sec 3){{.*}} .associative
++# SYMBOLS-REMOVE-TEXT-NEXT: AUX scnlen {{.*}} assoc 2 comdat 5
++# SYMBOLS-REMOVE-TEXT-NEXT: {{.*}}(sec 2){{.*}} .comdat
++# SYMBOLS-REMOVE-TEXT-NEXT: AUX scnlen {{.*}} assoc 2 comdat 2
++# SYMBOLS-REMOVE-TEXT-NEXT: {{.*}}(sec 2){{.*}} foo
++# SYMBOLS-REMOVE-TEXT-EMPTY:
++#
++#
++# Removing the .comdat section fails, since the .text section has relocations
++# against it.
++#
++# ERROR-RELOC: Relocation target foo ({{.*}}) not found
++#
++#
++# Removing the .comdat section and .text (with a relocation against .comdat)
++# works, as it also removes the .associative section transitively.
++#
++# SECTIONS-REMOVE-TEXT-COMDAT: Sections:
++# SECTIONS-REMOVE-TEXT-COMDAT-NEXT: Idx Name
++# SECTIONS-REMOVE-TEXT-COMDAT-NEXT: 0 .bss
++# SECTIONS-REMOVE-TEXT-COMDAT-EMPTY:
++#
++# SYMBOLS-REMOVE-TEXT-COMDAT: SYMBOL TABLE:
++# SYMBOLS-REMOVE-TEXT-COMDAT-NEXT: {{.*}}(sec -1){{.*}} @feat.00
++# SYMBOLS-REMOVE-TEXT-COMDAT-NEXT: {{.*}}(sec 1){{.*}} .bss
++# SYMBOLS-REMOVE-TEXT-COMDAT-NEXT: AUX scnlen {{.*}} assoc 1 comdat 0
++# SYMBOLS-REMOVE-TEXT-COMDAT-EMPTY:
++
++--- !COFF
++header:          
++  Machine:         IMAGE_FILE_MACHINE_AMD64
++  Characteristics: [  ]
++sections:        
++  - Name:            .text
++    Characteristics: [  ]
++    Alignment:       4
++    SectionData:     488B0500000000C3
++    Relocations:     
++      - VirtualAddress:  3
++        SymbolName:      foo
++        Type:            IMAGE_REL_AMD64_REL32
++  - Name:            .bss
++    Characteristics: [  ]
++    Alignment:       4
++    SectionData:     ''
++  - Name:            .comdat
++    Characteristics: [ IMAGE_SCN_LNK_COMDAT ]
++    Alignment:       1
++    SectionData:     '2A000000'
++  - Name:            .associative
++    Characteristics: [ IMAGE_SCN_LNK_COMDAT ]
++    Alignment:       1
++    SectionData:     '0000000000000000'
++symbols:         
++  - Name:            '@feat.00'
++    Value:           0
++    SectionNumber:   -1
++    SimpleType:      IMAGE_SYM_TYPE_NULL
++    ComplexType:     IMAGE_SYM_DTYPE_NULL
++    StorageClass:    IMAGE_SYM_CLASS_STATIC
++  - Name:            .text
++    Value:           0
++    SectionNumber:   1
++    SimpleType:      IMAGE_SYM_TYPE_NULL
++    ComplexType:     IMAGE_SYM_DTYPE_NULL
++    StorageClass:    IMAGE_SYM_CLASS_STATIC
++    SectionDefinition: 
++      Length:          8
++      NumberOfRelocations: 1
++      NumberOfLinenumbers: 0
++      CheckSum:        583624169
++      Number:          1
++  - Name:            .bss
++    Value:           0
++    SectionNumber:   2
++    SimpleType:      IMAGE_SYM_TYPE_NULL
++    ComplexType:     IMAGE_SYM_DTYPE_NULL
++    StorageClass:    IMAGE_SYM_CLASS_STATIC
++    SectionDefinition: 
++      Length:          0
++      NumberOfRelocations: 0
++      NumberOfLinenumbers: 0
++      CheckSum:        0
++      Number:          2
++  - Name:            .associative
++    Value:           0
++    SectionNumber:   4
++    SimpleType:      IMAGE_SYM_TYPE_NULL
++    ComplexType:     IMAGE_SYM_DTYPE_NULL
++    StorageClass:    IMAGE_SYM_CLASS_STATIC
++    SectionDefinition: 
++      Length:          8
++      NumberOfRelocations: 0
++      NumberOfLinenumbers: 0
++      CheckSum:        0
++      Number:          3
++      Selection:       IMAGE_COMDAT_SELECT_ASSOCIATIVE
++  - Name:            .comdat
++    Value:           0
++    SectionNumber:   3
++    SimpleType:      IMAGE_SYM_TYPE_NULL
++    ComplexType:     IMAGE_SYM_DTYPE_NULL
++    StorageClass:    IMAGE_SYM_CLASS_STATIC
++    SectionDefinition: 
++      Length:          4
++      NumberOfRelocations: 0
++      NumberOfLinenumbers: 0
++      CheckSum:        3482275674
++      Number:          3
++      Selection:       IMAGE_COMDAT_SELECT_ANY
++  - Name:            foo
++    Value:           0
++    SectionNumber:   3
++    SimpleType:      IMAGE_SYM_TYPE_NULL
++    ComplexType:     IMAGE_SYM_DTYPE_NULL
++    StorageClass:    IMAGE_SYM_CLASS_EXTERNAL
++  - Name:            main
++    Value:           0
++    SectionNumber:   1
++    SimpleType:      IMAGE_SYM_TYPE_NULL
++    ComplexType:     IMAGE_SYM_DTYPE_NULL
++    StorageClass:    IMAGE_SYM_CLASS_EXTERNAL
++...
+diff --git a/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp b/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp
+index 437dccbd3d5..dd2e4829218 100644
+--- a/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp
++++ b/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp
+@@ -27,9 +27,17 @@ using namespace object;
+ using namespace COFF;
+ 
+ static Error handleArgs(const CopyConfig &Config, Object &Obj) {
++  // Perform the actual section removals.
++  Obj.removeSections([&Config](const Section &Sec) {
++    if (is_contained(Config.ToRemove, Sec.Name))
++      return true;
++
++    return false;
++  });
++
+   // StripAll removes all symbols and thus also removes all relocations.
+   if (Config.StripAll || Config.StripAllGNU)
+-    for (Section &Sec : Obj.Sections)
++    for (Section &Sec : Obj.getMutableSections())
+       Sec.Relocs.clear();
+ 
+   // If we need to do per-symbol removals, initialize the Referenced field.
+diff --git a/llvm/tools/llvm-objcopy/COFF/Object.cpp b/llvm/tools/llvm-objcopy/COFF/Object.cpp
+index e58e161e7d2..e19cea6aa9d 100644
+--- a/llvm/tools/llvm-objcopy/COFF/Object.cpp
++++ b/llvm/tools/llvm-objcopy/COFF/Object.cpp
+@@ -7,6 +7,7 @@
+ //===----------------------------------------------------------------------===//
+ 
+ #include "Object.h"
++#include "llvm/ADT/DenseSet.h"
+ #include <algorithm>
+ 
+ namespace llvm {
+@@ -64,6 +65,68 @@ Error Object::markSymbols() {
+   return Error::success();
+ }
+ 
++void Object::addSections(ArrayRef<Section> NewSections) {
++  for (Section S : NewSections) {
++    S.UniqueId = NextSectionUniqueId++;
++    Sections.emplace_back(S);
++  }
++  updateSections();
++}
++
++void Object::updateSections() {
++  SectionMap = DenseMap<ssize_t, Section *>(Sections.size());
++  size_t Index = 1;
++  for (Section &S : Sections) {
++    SectionMap[S.UniqueId] = &S;
++    S.Index = Index++;
++  }
++}
++
++const Section *Object::findSection(ssize_t UniqueId) const {
++  auto It = SectionMap.find(UniqueId);
++  if (It == SectionMap.end())
++    return nullptr;
++  return It->second;
++}
++
++void Object::removeSections(function_ref<bool(const Section &)> ToRemove) {
++  DenseSet<ssize_t> AssociatedSections;
++  auto RemoveAssociated = [&AssociatedSections](const Section &Sec) {
++    return AssociatedSections.count(Sec.UniqueId) == 1;
++  };
++  do {
++    DenseSet<ssize_t> RemovedSections;
++    Sections.erase(
++        std::remove_if(std::begin(Sections), std::end(Sections),
++                       [ToRemove, &RemovedSections](const Section &Sec) {
++                         bool Remove = ToRemove(Sec);
++                         if (Remove)
++                           RemovedSections.insert(Sec.UniqueId);
++                         return Remove;
++                       }),
++        std::end(Sections));
++    // Remove all symbols referring to the removed sections.
++    AssociatedSections.clear();
++    Symbols.erase(
++        std::remove_if(
++            std::begin(Symbols), std::end(Symbols),
++            [&RemovedSections, &AssociatedSections](const Symbol &Sym) {
++              // If there are sections that are associative to a removed
++              // section,
++              // remove those as well as nothing will include them (and we can't
++              // leave them dangling).
++              if (RemovedSections.count(Sym.AssociativeComdatTargetSectionId) ==
++                  1)
++                AssociatedSections.insert(Sym.TargetSectionId);
++              return RemovedSections.count(Sym.TargetSectionId) == 1;
++            }),
++        std::end(Symbols));
++    ToRemove = RemoveAssociated;
++  } while (!AssociatedSections.empty());
++  updateSections();
++  updateSymbols();
++}
++
+ } // end namespace coff
+ } // end namespace objcopy
+ } // end namespace llvm
+diff --git a/llvm/tools/llvm-objcopy/COFF/Object.h b/llvm/tools/llvm-objcopy/COFF/Object.h
+index e6147c40b7c..a73e93620d3 100644
+--- a/llvm/tools/llvm-objcopy/COFF/Object.h
++++ b/llvm/tools/llvm-objcopy/COFF/Object.h
+@@ -37,12 +37,16 @@ struct Section {
+   ArrayRef<uint8_t> Contents;
+   std::vector<Relocation> Relocs;
+   StringRef Name;
++  ssize_t UniqueId;
++  size_t Index;
+ };
+ 
+ struct Symbol {
+   object::coff_symbol32 Sym;
+   StringRef Name;
+-  ArrayRef<uint8_t> AuxData;
++  std::vector<uint8_t> AuxData;
++  ssize_t TargetSectionId;
++  ssize_t AssociativeComdatTargetSectionId = 0;
+   size_t UniqueId;
+   size_t RawIndex;
+   bool Referenced;
+@@ -61,7 +65,6 @@ struct Object {
+   uint32_t BaseOfData = 0; // pe32plus_header lacks this field.
+ 
+   std::vector<object::data_directory> DataDirectories;
+-  std::vector<Section> Sections;
+ 
+   ArrayRef<Symbol> getSymbols() const { return Symbols; }
+   // This allows mutating individual Symbols, but not mutating the list
+@@ -79,14 +82,34 @@ struct Object {
+   // all sections.
+   Error markSymbols();
+ 
++  ArrayRef<Section> getSections() const { return Sections; }
++  // This allows mutating individual Sections, but not mutating the list
++  // of symbols itself.
++  iterator_range<std::vector<Section>::iterator> getMutableSections() {
++    return make_range(Sections.begin(), Sections.end());
++  }
++
++  const Section *findSection(ssize_t UniqueId) const;
++
++  void addSections(ArrayRef<Section> NewSections);
++  void removeSections(function_ref<bool(const Section &)> ToRemove);
++
+ private:
+   std::vector<Symbol> Symbols;
+   DenseMap<size_t, Symbol *> SymbolMap;
+ 
+   size_t NextSymbolUniqueId = 0;
+ 
++  std::vector<Section> Sections;
++  DenseMap<ssize_t, Section *> SectionMap;
++
++  ssize_t NextSectionUniqueId = 1; // Allow a UniqueId 0 to mean undefined.
++
+   // Update SymbolMap and RawIndex in each Symbol.
+   void updateSymbols();
++
++  // Update SectionMap and Index in each Section.
++  void updateSections();
+ };
+ 
+ // Copy between coff_symbol16 and coff_symbol32.
+diff --git a/llvm/tools/llvm-objcopy/COFF/Reader.cpp b/llvm/tools/llvm-objcopy/COFF/Reader.cpp
+index d794042ae24..c8abe2913a2 100644
+--- a/llvm/tools/llvm-objcopy/COFF/Reader.cpp
++++ b/llvm/tools/llvm-objcopy/COFF/Reader.cpp
+@@ -11,6 +11,7 @@
+ #include "llvm-objcopy.h"
+ #include "llvm/ADT/ArrayRef.h"
+ #include "llvm/ADT/StringRef.h"
++#include "llvm/BinaryFormat/COFF.h"
+ #include "llvm/Object/COFF.h"
+ #include "llvm/Support/ErrorHandling.h"
+ #include <cstddef>
+@@ -21,6 +22,7 @@ namespace objcopy {
+ namespace coff {
+ 
+ using namespace object;
++using namespace COFF;
+ 
+ Error COFFReader::readExecutableHeaders(Object &Obj) const {
+   const dos_header *DH = COFFObj.getDOSHeader();
+@@ -58,13 +60,14 @@ Error COFFReader::readExecutableHeaders(Object &Obj) const {
+ }
+ 
+ Error COFFReader::readSections(Object &Obj) const {
++  std::vector<Section> Sections;
+   // Section indexing starts from 1.
+   for (size_t I = 1, E = COFFObj.getNumberOfSections(); I <= E; I++) {
+     const coff_section *Sec;
+     if (auto EC = COFFObj.getSection(I, Sec))
+       return errorCodeToError(EC);
+-    Obj.Sections.push_back(Section());
+-    Section &S = Obj.Sections.back();
++    Sections.push_back(Section());
++    Section &S = Sections.back();
+     S.Header = *Sec;
+     if (auto EC = COFFObj.getSectionContents(Sec, S.Contents))
+       return errorCodeToError(EC);
+@@ -77,12 +80,14 @@ Error COFFReader::readSections(Object &Obj) const {
+       return make_error<StringError>("Extended relocations not supported yet",
+                                      object_error::parse_failed);
+   }
++  Obj.addSections(Sections);
+   return Error::success();
+ }
+ 
+ Error COFFReader::readSymbols(Object &Obj, bool IsBigObj) const {
+   std::vector<Symbol> Symbols;
+   Symbols.reserve(COFFObj.getRawNumberOfSymbols());
++  ArrayRef<Section> Sections = Obj.getSections();
+   for (uint32_t I = 0, E = COFFObj.getRawNumberOfSymbols(); I < E;) {
+     Expected<COFFSymbolRef> SymOrErr = COFFObj.getSymbol(I);
+     if (!SymOrErr)
+@@ -103,6 +108,26 @@ Error COFFReader::readSymbols(Object &Obj, bool IsBigObj) const {
+     Sym.AuxData = COFFObj.getSymbolAuxData(SymRef);
+     assert((Sym.AuxData.size() %
+             (IsBigObj ? sizeof(coff_symbol32) : sizeof(coff_symbol16))) == 0);
++    // Find the unique id of the section
++    if (SymRef.getSectionNumber() <=
++        0) // Special symbol (undefined/absolute/debug)
++      Sym.TargetSectionId = SymRef.getSectionNumber();
++    else if (static_cast<uint32_t>(SymRef.getSectionNumber() - 1) <
++             Sections.size())
++      Sym.TargetSectionId = Sections[SymRef.getSectionNumber() - 1].UniqueId;
++    else
++      return make_error<StringError>("Section number out of range",
++                                     object_error::parse_failed);
++    // For section definitions, check if it is comdat associative, and if
++    // it is, find the target section unique id.
++    const coff_aux_section_definition *SD = SymRef.getSectionDefinition();
++    if (SD && SD->Selection == IMAGE_COMDAT_SELECT_ASSOCIATIVE) {
++      int32_t Index = SD->getNumber(IsBigObj);
++      if (Index <= 0 || static_cast<uint32_t>(Index - 1) >= Sections.size())
++        return make_error<StringError>("Unexpected associative section index",
++                                       object_error::parse_failed);
++      Sym.AssociativeComdatTargetSectionId = Sections[Index - 1].UniqueId;
++    }
+     I += 1 + SymRef.getNumberOfAuxSymbols();
+   }
+   Obj.addSymbols(Symbols);
+@@ -116,7 +141,7 @@ Error COFFReader::setRelocTargets(Object &Obj) const {
+     for (size_t I = 0; I < Sym.Sym.NumberOfAuxSymbols; I++)
+       RawSymbolTable.push_back(nullptr);
+   }
+-  for (Section &Sec : Obj.Sections) {
++  for (Section &Sec : Obj.getMutableSections()) {
+     for (Relocation &R : Sec.Relocs) {
+       if (R.Reloc.SymbolTableIndex >= RawSymbolTable.size())
+         return make_error<StringError>("SymbolTableIndex out of range",
+diff --git a/llvm/tools/llvm-objcopy/COFF/Writer.cpp b/llvm/tools/llvm-objcopy/COFF/Writer.cpp
+index c347810dd24..9fb7812672b 100644
+--- a/llvm/tools/llvm-objcopy/COFF/Writer.cpp
++++ b/llvm/tools/llvm-objcopy/COFF/Writer.cpp
+@@ -25,7 +25,7 @@ using namespace object;
+ using namespace COFF;
+ 
+ Error COFFWriter::finalizeRelocTargets() {
+-  for (Section &Sec : Obj.Sections) {
++  for (Section &Sec : Obj.getMutableSections()) {
+     for (Relocation &R : Sec.Relocs) {
+       const Symbol *Sym = Obj.findSymbol(R.Target);
+       if (Sym == nullptr)
+@@ -39,8 +39,48 @@ Error COFFWriter::finalizeRelocTargets() {
+   return Error::success();
+ }
+ 
++Error COFFWriter::finalizeSectionNumbers() {
++  for (Symbol &Sym : Obj.getMutableSymbols()) {
++    if (Sym.TargetSectionId <= 0) {
++      // Undefined, or a special kind of symbol. These negative values
++      // are stored in the SectionNumber field which is unsigned.
++      Sym.Sym.SectionNumber = static_cast<uint32_t>(Sym.TargetSectionId);
++    } else {
++      const Section *Sec = Obj.findSection(Sym.TargetSectionId);
++      if (Sec == nullptr)
++        return make_error<StringError>("Symbol " + Sym.Name +
++                                           " points to a removed section",
++                                       object_error::invalid_symbol_index);
++      Sym.Sym.SectionNumber = Sec->Index;
++
++      if (Sym.Sym.NumberOfAuxSymbols == 1 &&
++          Sym.Sym.StorageClass == IMAGE_SYM_CLASS_STATIC) {
++        coff_aux_section_definition *SD =
++            reinterpret_cast<coff_aux_section_definition *>(Sym.AuxData.data());
++        uint32_t SDSectionNumber;
++        if (Sym.AssociativeComdatTargetSectionId == 0) {
++          // Not a comdat associative section; just set the Number field to
++          // the number of the section itself.
++          SDSectionNumber = Sec->Index;
++        } else {
++          Sec = Obj.findSection(Sym.AssociativeComdatTargetSectionId);
++          if (Sec == nullptr)
++            return make_error<StringError>(
++                "Symbol " + Sym.Name + " is associative to a removed section",
++                object_error::invalid_symbol_index);
++          SDSectionNumber = Sec->Index;
++        }
++        // Update the section definition with the new section number.
++        SD->NumberLowPart = static_cast<uint16_t>(SDSectionNumber);
++        SD->NumberHighPart = static_cast<uint16_t>(SDSectionNumber >> 16);
++      }
++    }
++  }
++  return Error::success();
++}
++
+ void COFFWriter::layoutSections() {
+-  for (auto &S : Obj.Sections) {
++  for (auto &S : Obj.getMutableSections()) {
+     if (S.Header.SizeOfRawData > 0)
+       S.Header.PointerToRawData = FileSize;
+     FileSize += S.Header.SizeOfRawData; // For executables, this is already
+@@ -57,7 +97,7 @@ void COFFWriter::layoutSections() {
+ }
+ 
+ size_t COFFWriter::finalizeStringTable() {
+-  for (auto &S : Obj.Sections)
++  for (const auto &S : Obj.getSections())
+     if (S.Name.size() > COFF::NameSize)
+       StrTabBuilder.add(S.Name);
+ 
+@@ -67,7 +107,7 @@ size_t COFFWriter::finalizeStringTable() {
+ 
+   StrTabBuilder.finalize();
+ 
+-  for (auto &S : Obj.Sections) {
++  for (auto &S : Obj.getMutableSections()) {
+     if (S.Name.size() > COFF::NameSize) {
+       snprintf(S.Header.Name, sizeof(S.Header.Name), "/%d",
+                (int)StrTabBuilder.getOffset(S.Name));
+@@ -97,6 +137,8 @@ std::pair<size_t, size_t> COFFWriter::finalizeSymbolTable() {
+ Error COFFWriter::finalize(bool IsBigObj) {
+   if (Error E = finalizeRelocTargets())
+     return E;
++  if (Error E = finalizeSectionNumbers())
++    return E;
+ 
+   size_t SizeOfHeaders = 0;
+   FileAlignment = 1;
+@@ -113,10 +155,10 @@ Error COFFWriter::finalize(bool IsBigObj) {
+     SizeOfHeaders +=
+         PeHeaderSize + sizeof(data_directory) * Obj.DataDirectories.size();
+   }
+-  Obj.CoffFileHeader.NumberOfSections = Obj.Sections.size();
++  Obj.CoffFileHeader.NumberOfSections = Obj.getSections().size();
+   SizeOfHeaders +=
+       IsBigObj ? sizeof(coff_bigobj_file_header) : sizeof(coff_file_header);
+-  SizeOfHeaders += sizeof(coff_section) * Obj.Sections.size();
++  SizeOfHeaders += sizeof(coff_section) * Obj.getSections().size();
+   SizeOfHeaders = alignTo(SizeOfHeaders, FileAlignment);
+ 
+   Obj.CoffFileHeader.SizeOfOptionalHeader =
+@@ -131,8 +173,8 @@ Error COFFWriter::finalize(bool IsBigObj) {
+     Obj.PeHeader.SizeOfHeaders = SizeOfHeaders;
+     Obj.PeHeader.SizeOfInitializedData = SizeOfInitializedData;
+ 
+-    if (!Obj.Sections.empty()) {
+-      const Section &S = Obj.Sections.back();
++    if (!Obj.getSections().empty()) {
++      const Section &S = Obj.getSections().back();
+       Obj.PeHeader.SizeOfImage =
+           alignTo(S.Header.VirtualAddress + S.Header.VirtualSize,
+                   Obj.PeHeader.SectionAlignment);
+@@ -198,7 +240,7 @@ void COFFWriter::writeHeaders(bool IsBigObj) {
+     BigObjHeader.unused4 = 0;
+     // The value in Obj.CoffFileHeader.NumberOfSections is truncated, thus
+     // get the original one instead.
+-    BigObjHeader.NumberOfSections = Obj.Sections.size();
++    BigObjHeader.NumberOfSections = Obj.getSections().size();
+     BigObjHeader.PointerToSymbolTable = Obj.CoffFileHeader.PointerToSymbolTable;
+     BigObjHeader.NumberOfSymbols = Obj.CoffFileHeader.NumberOfSymbols;
+ 
+@@ -223,14 +265,14 @@ void COFFWriter::writeHeaders(bool IsBigObj) {
+       Ptr += sizeof(DD);
+     }
+   }
+-  for (const auto &S : Obj.Sections) {
++  for (const auto &S : Obj.getSections()) {
+     memcpy(Ptr, &S.Header, sizeof(S.Header));
+     Ptr += sizeof(S.Header);
+   }
+ }
+ 
+ void COFFWriter::writeSections() {
+-  for (const auto &S : Obj.Sections) {
++  for (const auto &S : Obj.getSections()) {
+     uint8_t *Ptr = Buf.getBufferStart() + S.Header.PointerToRawData;
+     std::copy(S.Contents.begin(), S.Contents.end(), Ptr);
+ 
+@@ -295,7 +337,7 @@ Error COFFWriter::patchDebugDirectory() {
+   const data_directory *Dir = &Obj.DataDirectories[DEBUG_DIRECTORY];
+   if (Dir->Size <= 0)
+     return Error::success();
+-  for (const auto &S : Obj.Sections) {
++  for (const auto &S : Obj.getSections()) {
+     if (Dir->RelativeVirtualAddress >= S.Header.VirtualAddress &&
+         Dir->RelativeVirtualAddress <
+             S.Header.VirtualAddress + S.Header.SizeOfRawData) {
+@@ -324,7 +366,7 @@ Error COFFWriter::patchDebugDirectory() {
+ }
+ 
+ Error COFFWriter::write() {
+-  bool IsBigObj = Obj.Sections.size() > MaxNumberOfSections16;
++  bool IsBigObj = Obj.getSections().size() > MaxNumberOfSections16;
+   if (IsBigObj && Obj.IsPE)
+     return make_error<StringError>("Too many sections for executable",
+                                    object_error::parse_failed);
+diff --git a/llvm/tools/llvm-objcopy/COFF/Writer.h b/llvm/tools/llvm-objcopy/COFF/Writer.h
+index 52fef385926..a967a103df9 100644
+--- a/llvm/tools/llvm-objcopy/COFF/Writer.h
++++ b/llvm/tools/llvm-objcopy/COFF/Writer.h
+@@ -31,6 +31,7 @@ class COFFWriter {
+   StringTableBuilder StrTabBuilder;
+ 
+   Error finalizeRelocTargets();
++  Error finalizeSectionNumbers();
+   void layoutSections();
+   size_t finalizeStringTable();
+   template <class SymbolTy> std::pair<size_t, size_t> finalizeSymbolTable();
+-- 
+2.17.1
+
new file mode 100644
--- /dev/null
+++ b/build/build-clang/mingwclang-llvm-objcopy-COFF-Clear-the-unwritten-tail-of-coff_s.patch
@@ -0,0 +1,28 @@
+From 1284ee3c47bab17ec081b5169633aea4f8abfd30 Mon Sep 17 00:00:00 2001
+From: Martin Storsjo <martin@martin.st>
+Date: Wed, 23 Jan 2019 09:12:53 +0000
+Subject: [PATCH] [llvm-objcopy] [COFF] Clear the unwritten tail of
+ coff_section::Header::Name
+
+This should fix the add-gnu-debuglink test on all buildbots.
+
+git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@351934 91177308-0d34-0410-b5e6-96231b3b80d8
+---
+ tools/llvm-objcopy/COFF/Writer.cpp | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/llvm/tools/llvm-objcopy/COFF/Writer.cpp b/llvm/tools/llvm-objcopy/COFF/Writer.cpp
+index 05e46291c39..db897e2ff33 100644
+--- a/llvm/tools/llvm-objcopy/COFF/Writer.cpp
++++ b/llvm/tools/llvm-objcopy/COFF/Writer.cpp
+@@ -121,6 +121,7 @@ size_t COFFWriter::finalizeStringTable() {
+ 
+   for (auto &S : Obj.getMutableSections()) {
+     if (S.Name.size() > COFF::NameSize) {
++      memset(S.Header.Name, 0, sizeof(S.Header.Name));
+       snprintf(S.Header.Name, sizeof(S.Header.Name), "/%d",
+                (int)StrTabBuilder.getOffset(S.Name));
+     } else {
+-- 
+2.17.1
+
new file mode 100644
--- /dev/null
+++ b/build/build-clang/mingwclang-llvm-objcopy-COFF-Error-out-on-use-of-unhandled-opti.patch
@@ -0,0 +1,43 @@
+From abacd83232acf69d7cbacd53fc2f9aae66c1a32e Mon Sep 17 00:00:00 2001
+From: Martin Storsjo <martin@martin.st>
+Date: Wed, 23 Jan 2019 11:54:55 +0000
+Subject: [PATCH] [llvm-objcopy] [COFF] Error out on use of unhandled options
+
+Prefer erroring out than silently not doing what was requested.
+
+Differential Revision: https://reviews.llvm.org/D57045
+
+git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@351948 91177308-0d34-0410-b5e6-96231b3b80d8
+---
+ tools/llvm-objcopy/COFF/COFFObjcopy.cpp | 15 +++++++++++++++
+ 1 file changed, 15 insertions(+)
+
+diff --git a/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp b/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp
+index 64b4e79a4e0..b7b3d3cb629 100644
+--- a/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp
++++ b/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp
+@@ -170,6 +170,21 @@ static Error handleArgs(const CopyConfig &Config, Object &Obj) {
+   if (!Config.AddGnuDebugLink.empty())
+     addGnuDebugLink(Obj, Config.AddGnuDebugLink);
+ 
++  if (!Config.BuildIdLinkDir.empty() || Config.BuildIdLinkInput ||
++      Config.BuildIdLinkOutput || !Config.SplitDWO.empty() ||
++      !Config.SymbolsPrefix.empty() || !Config.AddSection.empty() ||
++      !Config.DumpSection.empty() || !Config.KeepSection.empty() ||
++      !Config.SymbolsToGlobalize.empty() || !Config.SymbolsToKeep.empty() ||
++      !Config.SymbolsToLocalize.empty() || !Config.SymbolsToWeaken.empty() ||
++      !Config.SymbolsToKeepGlobal.empty() || !Config.SectionsToRename.empty() ||
++      !Config.SymbolsToRename.empty() || Config.ExtractDWO ||
++      Config.KeepFileSymbols || Config.LocalizeHidden || Config.PreserveDates ||
++      Config.StripDWO || Config.StripNonAlloc || Config.StripSections ||
++      Config.Weaken || Config.DecompressDebugSections) {
++    return createStringError(llvm::errc::invalid_argument,
++                             "Option not supported by llvm-objcopy for COFF");
++  }
++
+   return Error::success();
+ }
+ 
+-- 
+2.17.1
+
new file mode 100644
--- /dev/null
+++ b/build/build-clang/mingwclang-llvm-objcopy-COFF-Fix-handling-of-aux-symbols-for-bi.patch
@@ -0,0 +1,377 @@
+From 74c7d422cba163635394ec32f2b243b1de502a18 Mon Sep 17 00:00:00 2001
+From: Martin Storsjo <martin@martin.st>
+Date: Wed, 23 Jan 2019 11:54:51 +0000
+Subject: [PATCH] [llvm-objcopy] [COFF] Fix handling of aux symbols for big
+ objects
+
+The aux symbols were stored in an opaque std::vector<uint8_t>,
+with contents interpreted according to the rest of the symbol.
+
+All aux symbol types but one fit in 18 bytes (sizeof(coff_symbol16)),
+and if written to a bigobj, two extra padding bytes are written (as
+sizeof(coff_symbol32) is 20). In the storage agnostic intermediate
+representation, store the aux symbols as a series of coff_symbol16
+sized opaque blobs. (In practice, all such aux symbols only consist
+of one aux symbol, so this is more flexible than what reality needs.)
+
+The special case is the file aux symbols, which are written in
+potentially more than one aux symbol slot, without any padding,
+as one single long string. This can't be stored in the same opaque
+vector of fixed sized aux symbol entries. The file aux symbols will
+occupy a different number of aux symbol slots depending on the type
+of output object file. As nothing in the intermediate process needs
+to have accurate raw symbol indices, updating that is moved into the
+writer class.
+
+Differential Revision: https://reviews.llvm.org/D57009
+
+git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@351947 91177308-0d34-0410-b5e6-96231b3b80d8
+---
+ .../llvm-objcopy/COFF/Inputs/bigobj.o.gz      | Bin 0 -> 7841 bytes
+ test/tools/llvm-objcopy/COFF/bigobj.test      |  35 +++++++++++++
+ .../llvm-objcopy/ELF/auto-remove-shndx.test   |   2 +-
+ .../tools/llvm-objcopy/ELF/many-sections.test |   2 +-
+ test/tools/llvm-objcopy/ELF/remove-shndx.test |   2 +-
+ .../tools/llvm-objcopy/ELF/strict-no-add.test |   2 +-
+ .../llvm-objcopy/{ELF => }/Inputs/ungzip.py   |   0
+ tools/llvm-objcopy/COFF/COFFObjcopy.cpp       |   6 +--
+ tools/llvm-objcopy/COFF/Object.cpp            |   6 +--
+ tools/llvm-objcopy/COFF/Object.h              |  18 ++++++-
+ tools/llvm-objcopy/COFF/Reader.cpp            |  21 ++++++--
+ tools/llvm-objcopy/COFF/Writer.cpp            |  49 +++++++++++++-----
+ tools/llvm-objcopy/COFF/Writer.h              |   2 +-
+ 13 files changed, 115 insertions(+), 30 deletions(-)
+ create mode 100644 test/tools/llvm-objcopy/COFF/Inputs/bigobj.o.gz
+ create mode 100644 test/tools/llvm-objcopy/COFF/bigobj.test
+ rename test/tools/llvm-objcopy/{ELF => }/Inputs/ungzip.py (100%)
+
+diff --git a/llvm/test/tools/llvm-objcopy/COFF/Inputs/bigobj.o.gz b/llvm/test/tools/llvm-objcopy/COFF/Inputs/bigobj.o.gz
+new file mode 100644
+index 0000000000000000000000000000000000000000..6435f4785ff76e0c6bca12f3e57bc6ad8888bece
+GIT binary patch
+literal 7841
+zcmb2|=3r3v^@w3&etUMmo^zoH`-kGKM_vfJsF<z%6+Sz#g6qq)pf0Hj#_r`4B7DML
+zW(h1l`+!x)t@&W-R@I~lyKmU3Ti&1Z=iKur;uBMy1MR!_ywlsouYY&-*4H1mU!Qw=
+z`RpIDkw;!V4(WOF_)B3`(Vt|~S>?L-b)Wx@^wig`HIMAw|N8V<v65oeyETs611{)_
+zm27RwTe)ENN|7SLgM~83N6}~qjE2By2#kinXb6mkz-S1JhQMeDjE2By2#kinXb6mk
+zz-S1JhQMeDjE2By2#kinXb6mkz-S1JhQMeDjE2By2#kgRokHNw|D97mKRo|%+Z6Ym
+z*X{Ku$4#4*Vqm}gyYR^b^Sc?_E*<<cFE#Q=*rt6OBmJeLZ=aoe_u9R>-w!^l5biDe
+p{d@nvw*mU6<NG83=jxn4_wt_G?yUy#YeOF~KhH^=cj<;Y0{~9Br>p<~
+
+literal 0
+HcmV?d00001
+
+diff --git a/llvm/test/tools/llvm-objcopy/COFF/bigobj.test b/llvm/test/tools/llvm-objcopy/COFF/bigobj.test
+new file mode 100644
+index 00000000000..17968f12b8a
+--- /dev/null
++++ b/llvm/test/tools/llvm-objcopy/COFF/bigobj.test
+@@ -0,0 +1,35 @@
++RUN: %python %p/../Inputs/ungzip.py %p/Inputs/bigobj.o.gz > %t.in.o
++
++RUN: llvm-objdump -t %t.in.o | FileCheck %s --check-prefixes=SYMBOLS,SYMBOLS-BIG,SYMBOLS-ORIG
++
++# Do a plain copy, to check that section numbers in symbols referring
++# to sections outside of the small object format are handled correctly.
++RUN: llvm-objcopy -R '.text$4' %t.in.o %t.small.o
++RUN: llvm-objdump -t %t.in.o | FileCheck %s --check-prefixes=SYMBOLS,SYMBOLS-BIG,SYMBOLS-ORIG
++
++# Remove a section, making the section count fit into a small object.
++RUN: llvm-objcopy -R '.text$4' %t.in.o %t.small.o
++RUN: llvm-objdump -t %t.small.o | FileCheck %s --check-prefixes=SYMBOLS,SYMBOLS-SMALL,SYMBOLS-REMOVED-SMALL
++
++# Add a .gnu_debuglink section, forcing the object back to big format.
++RUN: llvm-objcopy --add-gnu-debuglink=%t.in.o %t.small.o %t.big.o
++ llvm-objdump -t %t.big.o | FileCheck %s --check-prefixes=SYMBOLS,SYMBOLS-BIG,SYMBOLS-REMOVED-BIG
++
++# In big object format, the .file symbol occupies one symbol table entry for
++# the auxillary data, but needs two entries in the small format, forcing the
++# raw symbol indices of later symbols to change.
++SYMBOLS:            SYMBOL TABLE:
++SYMBOLS-NEXT:       [ 0]{{.*}} (nx 1) {{.*}} .text
++SYMBOLS-NEXT:       AUX scnlen
++SYMBOLS-SMALL-NEXT: [ 2]{{.*}} (nx 2) {{.*}} .file
++SYMBOLS-BIG-NEXT:   [ 2]{{.*}} (nx 1) {{.*}} .file
++SYMBOLS-NEXT:       AUX abcdefghijklmnopqrs
++SYMBOLS-SMALL-NEXT: [ 5]{{.*}} (nx 0) {{.*}} foo
++SYMBOLS-BIG-NEXT:   [ 4]{{.*}} (nx 0) {{.*}} foo
++
++# Check that the section numbers outside of signed 16 bit int range
++# are represented properly. After removing one section, the section
++# numbers decrease.
++SYMBOLS-ORIG:          [ 5](sec 65280){{.*}} symbol65280
++SYMBOLS-REMOVED-SMALL: [ 6](sec 65279){{.*}} symbol65280
++SYMBOLS-REMOVED-BIG:   [ 5](sec 65279){{.*}} symbol65280
+diff --git a/llvm/test/tools/llvm-objcopy/ELF/auto-remove-shndx.test b/llvm/test/tools/llvm-objcopy/ELF/auto-remove-shndx.test
+index 5a23493fa94..8e6c788bf48 100644
+--- a/llvm/test/tools/llvm-objcopy/ELF/auto-remove-shndx.test
++++ b/llvm/test/tools/llvm-objcopy/ELF/auto-remove-shndx.test
+@@ -1,4 +1,4 @@
+-# RUN: %python %p/Inputs/ungzip.py %p/Inputs/many-sections.o.gz > %t
++# RUN: %python %p/../Inputs/ungzip.py %p/Inputs/many-sections.o.gz > %t
+ # RUN: llvm-objcopy -R .text -R s0 -R s1 -R s2 -R s3 -R s4 -R s5 -R s6 %t %t2
+ # RUN: llvm-readobj --sections %t2 | FileCheck --check-prefix=SECS %s
+ 
+diff --git a/llvm/test/tools/llvm-objcopy/ELF/many-sections.test b/llvm/test/tools/llvm-objcopy/ELF/many-sections.test
+index 57239f32e4a..1dd41cfb10c 100644
+--- a/llvm/test/tools/llvm-objcopy/ELF/many-sections.test
++++ b/llvm/test/tools/llvm-objcopy/ELF/many-sections.test
+@@ -1,4 +1,4 @@
+-RUN: %python %p/Inputs/ungzip.py %p/Inputs/many-sections.o.gz > %t
++RUN: %python %p/../Inputs/ungzip.py %p/Inputs/many-sections.o.gz > %t
+ RUN: llvm-objcopy %t %t2
+ RUN: llvm-readobj --file-headers %t2 | FileCheck --check-prefix=EHDR %s
+ RUN: llvm-readobj --sections %t2 | FileCheck --check-prefix=SECS %s
+diff --git a/llvm/test/tools/llvm-objcopy/ELF/remove-shndx.test b/llvm/test/tools/llvm-objcopy/ELF/remove-shndx.test
+index 6cc3a1a291f..53ca8e7f220 100644
+--- a/llvm/test/tools/llvm-objcopy/ELF/remove-shndx.test
++++ b/llvm/test/tools/llvm-objcopy/ELF/remove-shndx.test
+@@ -1,6 +1,6 @@
+ # This test checks to see that a .symtab_shndx section is added to any binary
+ # that needs it, even if the original was removed.
+-RUN: %python %p/Inputs/ungzip.py %p/Inputs/many-sections.o.gz > %t
++RUN: %python %p/../Inputs/ungzip.py %p/Inputs/many-sections.o.gz > %t
+ RUN: llvm-objcopy -R .symtab_shndx %t %t2
+ RUN: llvm-readobj --sections %t2 | FileCheck %s
+ 
+diff --git a/llvm/test/tools/llvm-objcopy/ELF/strict-no-add.test b/llvm/test/tools/llvm-objcopy/ELF/strict-no-add.test
+index 4f24df31bf9..348ab7c4fbd 100644
+--- a/llvm/test/tools/llvm-objcopy/ELF/strict-no-add.test
++++ b/llvm/test/tools/llvm-objcopy/ELF/strict-no-add.test
+@@ -1,7 +1,7 @@
+ # This test makes sure that sections added at the end that don't have symbols
+ # defined in them don't trigger the creation of a large index table.
+ 
+-RUN: %python %p/Inputs/ungzip.py %p/Inputs/many-sections.o.gz > %t.0
++RUN: %python %p/../Inputs/ungzip.py %p/Inputs/many-sections.o.gz > %t.0
+ RUN: cat %p/Inputs/alloc-symtab.o > %t
+ RUN: llvm-objcopy -R .text -R s0 -R s1 -R s2 -R s3 -R s4 -R s5 -R s6 %t.0 %t2
+ RUN: llvm-objcopy --add-section=.s0=%t --add-section=.s1=%t --add-section=.s2=%t %t2 %t2
+diff --git a/llvm/test/tools/llvm-objcopy/ELF/Inputs/ungzip.py b/llvm/test/tools/llvm-objcopy/Inputs/ungzip.py
+similarity index 100%
+rename from test/tools/llvm-objcopy/ELF/Inputs/ungzip.py
+rename to test/tools/llvm-objcopy/Inputs/ungzip.py
+diff --git a/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp b/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp
+index 20adbe11e7a..64b4e79a4e0 100644
+--- a/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp
++++ b/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp
+@@ -37,7 +37,7 @@ static uint64_t getNextRVA(const Object &Obj) {
+     return 0;
+   const Section &Last = Obj.getSections().back();
+   return alignTo(Last.Header.VirtualAddress + Last.Header.VirtualSize,
+-                 Obj.PeHeader.SectionAlignment);
++                 Obj.IsPE ? Obj.PeHeader.SectionAlignment : 1);
+ }
+ 
+ static uint32_t getCRC32(StringRef Data) {
+@@ -74,8 +74,8 @@ static void addGnuDebugLink(Object &Obj, StringRef DebugLinkFile) {
+   Sec.Name = ".gnu_debuglink";
+   Sec.Header.VirtualSize = Sec.getContents().size();
+   Sec.Header.VirtualAddress = StartRVA;
+-  Sec.Header.SizeOfRawData =
+-      alignTo(Sec.Header.VirtualSize, Obj.PeHeader.FileAlignment);
++  Sec.Header.SizeOfRawData = alignTo(Sec.Header.VirtualSize,
++                                     Obj.IsPE ? Obj.PeHeader.FileAlignment : 1);
+   // Sec.Header.PointerToRawData is filled in by the writer.
+   Sec.Header.PointerToRelocations = 0;
+   Sec.Header.PointerToLinenumbers = 0;
+diff --git a/llvm/tools/llvm-objcopy/COFF/Object.cpp b/llvm/tools/llvm-objcopy/COFF/Object.cpp
+index 8c382c1faef..0ad5a05a144 100644
+--- a/llvm/tools/llvm-objcopy/COFF/Object.cpp
++++ b/llvm/tools/llvm-objcopy/COFF/Object.cpp
+@@ -26,12 +26,8 @@ void Object::addSymbols(ArrayRef<Symbol> NewSymbols) {
+ 
+ void Object::updateSymbols() {
+   SymbolMap = DenseMap<size_t, Symbol *>(Symbols.size());
+-  size_t RawSymIndex = 0;
+-  for (Symbol &Sym : Symbols) {
++  for (Symbol &Sym : Symbols)
+     SymbolMap[Sym.UniqueId] = &Sym;
+-    Sym.RawIndex = RawSymIndex;
+-    RawSymIndex += 1 + Sym.Sym.NumberOfAuxSymbols;
+-  }
+ }
+ 
+ const Symbol *Object::findSymbol(size_t UniqueId) const {
+diff --git a/llvm/tools/llvm-objcopy/COFF/Object.h b/llvm/tools/llvm-objcopy/COFF/Object.h
+index afa272286ef..21475b06862 100644
+--- a/llvm/tools/llvm-objcopy/COFF/Object.h
++++ b/llvm/tools/llvm-objcopy/COFF/Object.h
+@@ -66,10 +66,24 @@ private:
+   std::vector<uint8_t> OwnedContents;
+ };
+ 
++struct AuxSymbol {
++  AuxSymbol(ArrayRef<uint8_t> In) {
++    assert(In.size() == sizeof(Opaque));
++    std::copy(In.begin(), In.end(), Opaque);
++  }
++
++  ArrayRef<uint8_t> getRef() const {
++    return ArrayRef<uint8_t>(Opaque, sizeof(Opaque));
++  }
++
++  uint8_t Opaque[sizeof(object::coff_symbol16)];
++};
++
+ struct Symbol {
+   object::coff_symbol32 Sym;
+   StringRef Name;
+-  std::vector<uint8_t> AuxData;
++  std::vector<AuxSymbol> AuxData;
++  StringRef AuxFile;
+   ssize_t TargetSectionId;
+   ssize_t AssociativeComdatTargetSectionId = 0;
+   Optional<size_t> WeakTargetSymbolId;
+@@ -132,7 +146,7 @@ private:
+ 
+   ssize_t NextSectionUniqueId = 1; // Allow a UniqueId 0 to mean undefined.
+ 
+-  // Update SymbolMap and RawIndex in each Symbol.
++  // Update SymbolMap.
+   void updateSymbols();
+ 
+   // Update SectionMap and Index in each Section.
+diff --git a/llvm/tools/llvm-objcopy/COFF/Reader.cpp b/llvm/tools/llvm-objcopy/COFF/Reader.cpp
+index 87dd60a43cf..7270bbf94de 100644
+--- a/llvm/tools/llvm-objcopy/COFF/Reader.cpp
++++ b/llvm/tools/llvm-objcopy/COFF/Reader.cpp
+@@ -107,9 +107,24 @@ Error COFFReader::readSymbols(Object &Obj, bool IsBigObj) const {
+                  *reinterpret_cast<const coff_symbol16 *>(SymRef.getRawPtr()));
+     if (auto EC = COFFObj.getSymbolName(SymRef, Sym.Name))
+       return errorCodeToError(EC);
+-    Sym.AuxData = COFFObj.getSymbolAuxData(SymRef);
+-    assert((Sym.AuxData.size() %
+-            (IsBigObj ? sizeof(coff_symbol32) : sizeof(coff_symbol16))) == 0);
++
++    ArrayRef<uint8_t> AuxData = COFFObj.getSymbolAuxData(SymRef);
++    size_t SymSize = IsBigObj ? sizeof(coff_symbol32) : sizeof(coff_symbol16);
++    assert(AuxData.size() == SymSize * SymRef.getNumberOfAuxSymbols());
++    // The auxillary symbols are structs of sizeof(coff_symbol16) each.
++    // In the big object format (where symbols are coff_symbol32), each
++    // auxillary symbol is padded with 2 bytes at the end. Copy each
++    // auxillary symbol to the Sym.AuxData vector. For file symbols,
++    // the whole range of aux symbols are interpreted as one null padded
++    // string instead.
++    if (SymRef.isFileRecord())
++      Sym.AuxFile = StringRef(reinterpret_cast<const char *>(AuxData.data()),
++                              AuxData.size())
++                        .rtrim('\0');
++    else
++      for (size_t I = 0; I < SymRef.getNumberOfAuxSymbols(); I++)
++        Sym.AuxData.push_back(AuxData.slice(I * SymSize, sizeof(AuxSymbol)));
++
+     // Find the unique id of the section
+     if (SymRef.getSectionNumber() <=
+         0) // Special symbol (undefined/absolute/debug)
+diff --git a/llvm/tools/llvm-objcopy/COFF/Writer.cpp b/llvm/tools/llvm-objcopy/COFF/Writer.cpp
+index db897e2ff33..6e69c597217 100644
+--- a/llvm/tools/llvm-objcopy/COFF/Writer.cpp
++++ b/llvm/tools/llvm-objcopy/COFF/Writer.cpp
+@@ -55,7 +55,8 @@ Error COFFWriter::finalizeSymbolContents() {
+       if (Sym.Sym.NumberOfAuxSymbols == 1 &&
+           Sym.Sym.StorageClass == IMAGE_SYM_CLASS_STATIC) {
+         coff_aux_section_definition *SD =
+-            reinterpret_cast<coff_aux_section_definition *>(Sym.AuxData.data());
++            reinterpret_cast<coff_aux_section_definition *>(
++                Sym.AuxData[0].Opaque);
+         uint32_t SDSectionNumber;
+         if (Sym.AssociativeComdatTargetSectionId == 0) {
+           // Not a comdat associative section; just set the Number field to
+@@ -79,7 +80,7 @@ Error COFFWriter::finalizeSymbolContents() {
+     // we want to set. Only >= 1 would be required, but only == 1 makes sense.
+     if (Sym.WeakTargetSymbolId && Sym.Sym.NumberOfAuxSymbols == 1) {
+       coff_aux_weak_external *WE =
+-          reinterpret_cast<coff_aux_weak_external *>(Sym.AuxData.data());
++          reinterpret_cast<coff_aux_weak_external *>(Sym.AuxData[0].Opaque);
+       const Symbol *Target = Obj.findSymbol(*Sym.WeakTargetSymbolId);
+       if (Target == nullptr)
+         return createStringError(object_error::invalid_symbol_index,
+@@ -141,13 +142,26 @@ size_t COFFWriter::finalizeStringTable() {
+ 
+ template <class SymbolTy>
+ std::pair<size_t, size_t> COFFWriter::finalizeSymbolTable() {
+-  size_t SymTabSize = Obj.getSymbols().size() * sizeof(SymbolTy);
+-  for (const auto &S : Obj.getSymbols())
+-    SymTabSize += S.AuxData.size();
+-  return std::make_pair(SymTabSize, sizeof(SymbolTy));
++  size_t RawSymIndex = 0;
++  for (auto &S : Obj.getMutableSymbols()) {
++    // Symbols normally have NumberOfAuxSymbols set correctly all the time.
++    // For file symbols, we need to know the output file's symbol size to be
++    // able to calculate the number of slots it occupies.
++    if (!S.AuxFile.empty())
++      S.Sym.NumberOfAuxSymbols =
++          alignTo(S.AuxFile.size(), sizeof(SymbolTy)) / sizeof(SymbolTy);
++    S.RawIndex = RawSymIndex;
++    RawSymIndex += 1 + S.Sym.NumberOfAuxSymbols;
++  }
++  return std::make_pair(RawSymIndex * sizeof(SymbolTy), sizeof(SymbolTy));
+ }
+ 
+ Error COFFWriter::finalize(bool IsBigObj) {
++  size_t SymTabSize, SymbolSize;
++  std::tie(SymTabSize, SymbolSize) = IsBigObj
++                                         ? finalizeSymbolTable<coff_symbol32>()
++                                         : finalizeSymbolTable<coff_symbol16>();
++
+   if (Error E = finalizeRelocTargets())
+     return E;
+   if (Error E = finalizeSymbolContents())
+@@ -199,10 +213,6 @@ Error COFFWriter::finalize(bool IsBigObj) {
+   }
+ 
+   size_t StrTabSize = finalizeStringTable();
+-  size_t SymTabSize, SymbolSize;
+-  std::tie(SymTabSize, SymbolSize) = IsBigObj
+-                                         ? finalizeSymbolTable<coff_symbol32>()
+-                                         : finalizeSymbolTable<coff_symbol16>();
+ 
+   size_t PointerToSymbolTable = FileSize;
+   // StrTabSize <= 4 is the size of an empty string table, only consisting
+@@ -312,8 +322,23 @@ template <class SymbolTy> void COFFWriter::writeSymbolStringTables() {
+     copySymbol<SymbolTy, coff_symbol32>(*reinterpret_cast<SymbolTy *>(Ptr),
+                                         S.Sym);
+     Ptr += sizeof(SymbolTy);
+-    std::copy(S.AuxData.begin(), S.AuxData.end(), Ptr);
+-    Ptr += S.AuxData.size();
++    if (!S.AuxFile.empty()) {
++      // For file symbols, just write the string into the aux symbol slots,
++      // assuming that the unwritten parts are initialized to zero in the memory
++      // mapped file.
++      std::copy(S.AuxFile.begin(), S.AuxFile.end(), Ptr);
++      Ptr += S.Sym.NumberOfAuxSymbols * sizeof(SymbolTy);
++    } else {
++      // For other auxillary symbols, write their opaque payload into one symbol
++      // table slot each. For big object files, the symbols are larger than the
++      // opaque auxillary symbol struct and we leave padding at the end of each
++      // entry.
++      for (const AuxSymbol &AuxSym : S.AuxData) {
++        ArrayRef<uint8_t> Ref = AuxSym.getRef();
++        std::copy(Ref.begin(), Ref.end(), Ptr);
++        Ptr += sizeof(SymbolTy);
++      }
++    }
+   }
+   if (StrTabBuilder.getSize() > 4 || !Obj.IsPE) {
+     // Always write a string table in object files, even an empty one.
+diff --git a/llvm/tools/llvm-objcopy/COFF/Writer.h b/llvm/tools/llvm-objcopy/COFF/Writer.h
+index 9b1cfa91d00..681a8d5e4a6 100644
+--- a/llvm/tools/llvm-objcopy/COFF/Writer.h
++++ b/llvm/tools/llvm-objcopy/COFF/Writer.h
+@@ -30,11 +30,11 @@ class COFFWriter {
+   size_t SizeOfInitializedData;
+   StringTableBuilder StrTabBuilder;
+ 
++  template <class SymbolTy> std::pair<size_t, size_t> finalizeSymbolTable();
+   Error finalizeRelocTargets();
+   Error finalizeSymbolContents();
+   void layoutSections();
+   size_t finalizeStringTable();
+-  template <class SymbolTy> std::pair<size_t, size_t> finalizeSymbolTable();
+ 
+   Error finalize(bool IsBigObj);
+ 
+-- 
+2.17.1
+
new file mode 100644
--- /dev/null
+++ b/build/build-clang/mingwclang-llvm-objcopy-COFF-Implement-only-keep-debug.patch
@@ -0,0 +1,222 @@
+From 526aa2e94355b7feb3bf7774a6e1899f68e94ad8 Mon Sep 17 00:00:00 2001
+From: Martin Storsjo <martin@martin.st>
+Date: Sat, 19 Jan 2019 19:42:48 +0000
+Subject: [PATCH] [llvm-objcopy] [COFF] Implement --only-keep-debug
+
+Differential Revision: https://reviews.llvm.org/D56840
+
+git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@351662 91177308-0d34-0410-b5e6-96231b3b80d8
+---
+ .../COFF/Inputs/only-keep-sections.yaml       | 77 +++++++++++++++++++
+ .../llvm-objcopy/COFF/only-keep-debug.test    | 58 ++++++++++++++
+ tools/llvm-objcopy/COFF/COFFObjcopy.cpp       | 10 +++
+ tools/llvm-objcopy/COFF/Object.cpp            | 10 +++
+ tools/llvm-objcopy/COFF/Object.h              |  1 +
+ 5 files changed, 156 insertions(+)
+ create mode 100644 test/tools/llvm-objcopy/COFF/Inputs/only-keep-sections.yaml
+ create mode 100644 test/tools/llvm-objcopy/COFF/only-keep-debug.test
+
+diff --git a/llvm/test/tools/llvm-objcopy/COFF/Inputs/only-keep-sections.yaml b/llvm/test/tools/llvm-objcopy/COFF/Inputs/only-keep-sections.yaml
+new file mode 100644
+index 00000000000..b5437e10763
+--- /dev/null
++++ b/llvm/test/tools/llvm-objcopy/COFF/Inputs/only-keep-sections.yaml
+@@ -0,0 +1,77 @@
++--- !COFF
++OptionalHeader:  
++  AddressOfEntryPoint: 4144
++  ImageBase:       1073741824
++  SectionAlignment: 4096
++  FileAlignment:   512
++  MajorOperatingSystemVersion: 6
++  MinorOperatingSystemVersion: 0
++  MajorImageVersion: 0
++  MinorImageVersion: 0
++  MajorSubsystemVersion: 6
++  MinorSubsystemVersion: 0
++  Subsystem:       IMAGE_SUBSYSTEM_WINDOWS_CUI
++  DLLCharacteristics: [  ]
++  SizeOfStackReserve: 1048576
++  SizeOfStackCommit: 4096
++  SizeOfHeapReserve: 1048576
++  SizeOfHeapCommit: 4096
++header:          
++  Machine:         IMAGE_FILE_MACHINE_AMD64
++  Characteristics: [  ]
++sections:        
++  - Name:            .text
++    Characteristics: [ IMAGE_SCN_CNT_CODE ]
++    VirtualAddress:  4096
++    VirtualSize:     4
++    SectionData:     C3C3C3C3
++  - Name:            .rdata
++    Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA ]
++    VirtualAddress:  8192
++    VirtualSize:     4
++    SectionData:     2A000000
++  - Name:            .buildid
++    Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA ]
++    VirtualAddress:  12288
++    VirtualSize:     4
++    SectionData:     2B000000
++  - Name:            .reloc
++    Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE ]
++    VirtualAddress:  16384
++    VirtualSize:     4
++    SectionData:     2C000000
++  - Name:            .debug_discardable
++    Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE ]
++    VirtualAddress:  20480
++    VirtualSize:     4
++    SectionData:     2D000000
++  - Name:            .debug_undiscardable
++    Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA ]
++    VirtualAddress:  24576
++    VirtualSize:     4
++    SectionData:     2E000000
++  - Name:            .unflagged
++    Characteristics: [  ]
++    VirtualAddress:  28672
++    VirtualSize:     4
++    SectionData:     2F000000
++symbols:         
++  - Name:            main
++    Value:           2
++    SectionNumber:   1
++    SimpleType:      IMAGE_SYM_TYPE_NULL
++    ComplexType:     IMAGE_SYM_DTYPE_FUNCTION
++    StorageClass:    IMAGE_SYM_CLASS_EXTERNAL
++  - Name:            debug_discardable_sym
++    Value:           0
++    SectionNumber:   5
++    SimpleType:      IMAGE_SYM_TYPE_NULL
++    ComplexType:     IMAGE_SYM_DTYPE_FUNCTION
++    StorageClass:    IMAGE_SYM_CLASS_EXTERNAL
++  - Name:            debug_undiscardable_sym
++    Value:           0
++    SectionNumber:   6
++    SimpleType:      IMAGE_SYM_TYPE_NULL
++    ComplexType:     IMAGE_SYM_DTYPE_FUNCTION
++    StorageClass:    IMAGE_SYM_CLASS_EXTERNAL
++...
+diff --git a/llvm/test/tools/llvm-objcopy/COFF/only-keep-debug.test b/llvm/test/tools/llvm-objcopy/COFF/only-keep-debug.test
+new file mode 100644
+index 00000000000..5518d4000fc
+--- /dev/null
++++ b/llvm/test/tools/llvm-objcopy/COFF/only-keep-debug.test
+@@ -0,0 +1,58 @@
++RUN: yaml2obj %p/Inputs/only-keep-sections.yaml > %t.in.exe
++
++RUN: llvm-objcopy --only-keep-debug %t.in.exe %t.out.exe
++RUN: llvm-readobj --sections %t.out.exe | FileCheck %s --check-prefix=SECTIONS
++RUN: llvm-objdump -t %t.out.exe | FileCheck %s --check-prefix=SYMBOLS
++
++Check that all non-debug/buildid sections with IMAGE_SCN_CNT_CODE
++or IMAGE_SCN_CNT_INITIALIZED_DATA are truncated, and no others.
++
++SECTIONS:      Sections [
++SECTIONS-NEXT:  Section {
++SECTIONS-NEXT:   Number: 1
++SECTIONS-NEXT:   Name: .text
++SECTIONS-NEXT:   VirtualSize: 0x4
++SECTIONS-NEXT:   VirtualAddress:
++SECTIONS-NEXT:   RawDataSize: 0
++SECTIONS:       Section {
++SECTIONS-NEXT:   Number: 2
++SECTIONS-NEXT:   Name: .rdata
++SECTIONS-NEXT:   VirtualSize: 0x4
++SECTIONS-NEXT:   VirtualAddress:
++SECTIONS-NEXT:   RawDataSize: 0
++SECTIONS:       Section {
++SECTIONS-NEXT:   Number: 3
++SECTIONS-NEXT:   Name: .buildid
++SECTIONS-NEXT:   VirtualSize: 0x4
++SECTIONS-NEXT:   VirtualAddress:
++SECTIONS-NEXT:   RawDataSize: 512
++SECTIONS:       Section {
++SECTIONS-NEXT:   Number: 4
++SECTIONS-NEXT:   Name: .reloc
++SECTIONS-NEXT:   VirtualSize: 0x4
++SECTIONS-NEXT:   VirtualAddress:
++SECTIONS-NEXT:   RawDataSize: 0
++SECTIONS:       Section {
++SECTIONS-NEXT:   Number: 5
++SECTIONS-NEXT:   Name: .debug_discardable
++SECTIONS-NEXT:   VirtualSize: 0x4
++SECTIONS-NEXT:   VirtualAddress:
++SECTIONS-NEXT:   RawDataSize: 512
++SECTIONS:       Section {
++SECTIONS-NEXT:   Number: 6
++SECTIONS-NEXT:   Name: .debug_undiscardable
++SECTIONS-NEXT:   VirtualSize: 0x4
++SECTIONS-NEXT:   VirtualAddress:
++SECTIONS-NEXT:   RawDataSize: 512
++SECTIONS:       Section {
++SECTIONS-NEXT:   Number: 7
++SECTIONS-NEXT:   Name: .unflagged
++SECTIONS-NEXT:   VirtualSize: 0x4
++SECTIONS-NEXT:   VirtualAddress:
++SECTIONS-NEXT:   RawDataSize: 512
++
++SYMBOLS:      SYMBOL TABLE:
++SYMBOLS-NEXT: main
++SYMBOLS-NEXT: debug_discardable_sym
++SYMBOLS-NEXT: debug_undiscardable_sym
++SYMBOLS-EMPTY:
+diff --git a/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp b/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp
+index 13d8efde37c..60afbf7bb54 100644
+--- a/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp
++++ b/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp
+@@ -46,6 +46,16 @@ static Error handleArgs(const CopyConfig &Config, Object &Obj) {
+     return false;
+   });
+ 
++  if (Config.OnlyKeepDebug) {
++    // For --only-keep-debug, we keep all other sections, but remove their
++    // content. The VirtualSize field in the section header is kept intact.
++    Obj.truncateSections([](const Section &Sec) {
++      return !isDebugSection(Sec) && Sec.Name != ".buildid" &&
++             ((Sec.Header.Characteristics &
++               (IMAGE_SCN_CNT_CODE | IMAGE_SCN_CNT_INITIALIZED_DATA)) != 0);
++    });
++  }
++
+   // StripAll removes all symbols and thus also removes all relocations.
+   if (Config.StripAll || Config.StripAllGNU)
+     for (Section &Sec : Obj.getMutableSections())
+diff --git a/llvm/tools/llvm-objcopy/COFF/Object.cpp b/llvm/tools/llvm-objcopy/COFF/Object.cpp
+index e19cea6aa9d..fc87d9e574d 100644
+--- a/llvm/tools/llvm-objcopy/COFF/Object.cpp
++++ b/llvm/tools/llvm-objcopy/COFF/Object.cpp
+@@ -127,6 +127,16 @@ void Object::removeSections(function_ref<bool(const Section &)> ToRemove) {
+   updateSymbols();
+ }
+ 
++void Object::truncateSections(function_ref<bool(const Section &)> ToTruncate) {
++  for (Section &Sec : Sections) {
++    if (ToTruncate(Sec)) {
++      Sec.Contents = ArrayRef<uint8_t>();
++      Sec.Relocs.clear();
++      Sec.Header.SizeOfRawData = 0;
++    }
++  }
++}
++
+ } // end namespace coff
+ } // end namespace objcopy
+ } // end namespace llvm
+diff --git a/llvm/tools/llvm-objcopy/COFF/Object.h b/llvm/tools/llvm-objcopy/COFF/Object.h
+index a73e93620d3..8e200369f0b 100644
+--- a/llvm/tools/llvm-objcopy/COFF/Object.h
++++ b/llvm/tools/llvm-objcopy/COFF/Object.h
+@@ -93,6 +93,7 @@ struct Object {
+ 
+   void addSections(ArrayRef<Section> NewSections);
+   void removeSections(function_ref<bool(const Section &)> ToRemove);
++  void truncateSections(function_ref<bool(const Section &)> ToTruncate);
+ 
+ private:
+   std::vector<Symbol> Symbols;
+-- 
+2.17.1
+
new file mode 100644
--- /dev/null
+++ b/build/build-clang/mingwclang-llvm-objcopy-COFF-Implement-only-section.patch
@@ -0,0 +1,61 @@
+From 17dcf25b3ade15605ca27150e4440bcc75caed65 Mon Sep 17 00:00:00 2001
+From: Martin Storsjo <martin@martin.st>
+Date: Sat, 19 Jan 2019 19:42:54 +0000
+Subject: [PATCH] [llvm-objcopy] [COFF] Implement --only-section
+
+Differential Revision: https://reviews.llvm.org/D56873
+
+git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@351663 91177308-0d34-0410-b5e6-96231b3b80d8
+---
+ .../tools/llvm-objcopy/COFF/only-section.test | 21 +++++++++++++++++++
+ tools/llvm-objcopy/COFF/COFFObjcopy.cpp       |  6 ++++++
+ 2 files changed, 27 insertions(+)
+ create mode 100644 test/tools/llvm-objcopy/COFF/only-section.test
+
+diff --git a/llvm/test/tools/llvm-objcopy/COFF/only-section.test b/llvm/test/tools/llvm-objcopy/COFF/only-section.test
+new file mode 100644
+index 00000000000..42492ed80ff
+--- /dev/null
++++ b/llvm/test/tools/llvm-objcopy/COFF/only-section.test
+@@ -0,0 +1,21 @@
++RUN: yaml2obj %p/Inputs/only-keep-sections.yaml > %t.in.exe
++
++RUN: llvm-objcopy --only-section .debug_discardable %t.in.exe %t.out.exe
++RUN: llvm-objdump --section-headers -t %t.out.exe | FileCheck %s --check-prefixes=SECTIONS,SECTIONS-DEBUG,SYMBOLS,SYMBOLS-DEBUG
++
++Adding another section stripping option makes it return the intersection of
++kept sections - in this case keeping only .text.
++
++RUN: llvm-objcopy --only-section .debug_discardable --only-section .text --strip-debug %t.in.exe %t.combination.exe
++RUN: llvm-objdump --section-headers -t %t.combination.exe | FileCheck %s --check-prefixes=SECTIONS,SECTIONS-TEXT,SYMBOLS,SYMBOLS-TEXT
++
++SECTIONS:            Sections:
++SECTIONS-NEXT:       Idx Name
++SECTIONS-DEBUG-NEXT: .debug_discardable
++SECTIONS-TEXT-NEXT:  .text
++SECTIONS-EMPTY:
++
++SYMBOLS:            SYMBOL TABLE:
++SYMBOLS-DEBUG-NEXT: debug_discardable_sym
++SYMBOLS-TEXT-NEXT:  main
++SYMBOLS-EMPTY:
+diff --git a/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp b/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp
+index 60afbf7bb54..99929d10a1f 100644
+--- a/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp
++++ b/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp
+@@ -33,6 +33,12 @@ static bool isDebugSection(const Section &Sec) {
+ static Error handleArgs(const CopyConfig &Config, Object &Obj) {
+   // Perform the actual section removals.
+   Obj.removeSections([&Config](const Section &Sec) {
++    // Contrary to --only-keep-debug, --only-section fully removes sections that
++    // aren't mentioned.
++    if (!Config.OnlySection.empty() &&
++        !is_contained(Config.OnlySection, Sec.Name))
++      return true;
++
+     if (Config.StripDebug || Config.StripAll || Config.StripAllGNU ||
+         Config.DiscardAll || Config.StripUnneeded) {
+       if (isDebugSection(Sec) &&
+-- 
+2.17.1
+
new file mode 100644
--- /dev/null
+++ b/build/build-clang/mingwclang-llvm-objcopy-COFF-Implement-strip-debug.patch
@@ -0,0 +1,160 @@
+From 2b6e1b7585d6bd997ea4e4233c904a6d2c11ad33 Mon Sep 17 00:00:00 2001
+From: Martin Storsjo <martin@martin.st>
+Date: Sat, 19 Jan 2019 19:42:41 +0000
+Subject: [PATCH] [llvm-objcopy] [COFF] Implement --strip-debug
+
+Also remove sections similarly for --strip-all, --discard-all,
+--strip-unneeded.
+
+Differential Revision: https://reviews.llvm.org/D56839
+
+git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@351661 91177308-0d34-0410-b5e6-96231b3b80d8
+---
+ test/tools/llvm-objcopy/COFF/strip-debug.test | 109 ++++++++++++++++++
+ tools/llvm-objcopy/COFF/COFFObjcopy.cpp       |  11 ++
+ 2 files changed, 120 insertions(+)
+ create mode 100644 test/tools/llvm-objcopy/COFF/strip-debug.test
+
+diff --git a/llvm/test/tools/llvm-objcopy/COFF/strip-debug.test b/llvm/test/tools/llvm-objcopy/COFF/strip-debug.test
+new file mode 100644
+index 00000000000..97fa96aac70
+--- /dev/null
++++ b/llvm/test/tools/llvm-objcopy/COFF/strip-debug.test
+@@ -0,0 +1,109 @@
++# RUN: yaml2obj %s > %t.in.o
++#
++# RUN: llvm-objdump --section-headers %t.in.o | FileCheck %s --check-prefixes=SECTIONS,SECTIONS-PRE
++# RUN: llvm-objdump -t %t.in.o | FileCheck %s --check-prefixes=SYMBOLS,SYMBOLS-PRE
++#
++# RUN: llvm-objcopy --strip-debug %t.in.o %t.out.o
++# RUN: llvm-objdump --section-headers %t.out.o | FileCheck %s --check-prefixes=SECTIONS
++# RUN: llvm-objdump -t %t.out.o | FileCheck %s --check-prefixes=SYMBOLS
++#
++# Test that --strip-all, --strip-all-gnu, --discard-all and --strip-unneeded,
++# plus llvm-strip without arguments all produce a similiar set of sections
++# (while they remove symbols differently).
++#
++# RUN: llvm-objcopy --strip-all %t.in.o %t.strip-all.o
++# RUN: llvm-objdump --section-headers %t.strip-all.o | FileCheck %s --check-prefixes=SECTIONS
++#
++# RUN: llvm-objcopy --strip-all-gnu %t.in.o %t.strip-all-gnu.o
++# RUN: llvm-objdump --section-headers %t.strip-all-gnu.o | FileCheck %s --check-prefixes=SECTIONS
++#
++# RUN: llvm-objcopy --discard-all %t.in.o %t.discard-all.o
++# RUN: llvm-objdump --section-headers %t.discard-all.o | FileCheck %s --check-prefixes=SECTIONS
++#
++# RUN: llvm-objcopy --discard-all %t.in.o %t.strip-unneeded.o
++# RUN: llvm-objdump --section-headers %t.strip-unneeded.o | FileCheck %s --check-prefixes=SECTIONS
++#
++# SECTIONS:        Sections:
++# SECTIONS-NEXT:   Idx Name
++# SECTIONS-NEXT:     0      .text
++# SECTIONS-NEXT:     1      .data
++# SECTIONS-NEXT:     2      .bss
++# SECTIONS-NEXT:     3      .xdata
++# SECTIONS-NEXT:     4      .reloc
++# SECTIONS-PRE-NEXT: 5      .debug_discardable
++# SECTIONS-NEXT:     {{.*}} .debug_undiscardable
++# SECTIONS-NEXT:     {{.*}} .llvm_addrsig
++# SECTIONS-EMPTY:
++#
++# Test that --strip-debug doesn't remove e.g. unreferenced local symbols.
++#
++# SYMBOLS:          SYMBOL TABLE:
++# SYMBOLS-NEXT:     external
++# SYMBOLS-NEXT:     local_unreferenced
++# SYMBOLS-PRE-NEXT: debug_discardable_sym
++# SYMBOLS-NEXT:     debug_undiscardable_sym
++# SYMBOLS-EMPTY:
++
++--- !COFF
++header:          
++  Machine:         IMAGE_FILE_MACHINE_AMD64
++  Characteristics: [  ]
++sections:        
++  - Name:            .text
++    Characteristics: [  ]
++    Alignment:       4
++    SectionData:     00000000
++  - Name:            .data
++    Characteristics: [  ]
++    Alignment:       4
++    SectionData:     00000000
++  - Name:            .bss
++    Characteristics: [  ]
++    Alignment:       4
++    SectionData:     00000000
++  - Name:            .xdata
++    Characteristics: [  ]
++    Alignment:       4
++    SectionData:     00000000
++  - Name:            .reloc
++    Characteristics: [ IMAGE_SCN_MEM_DISCARDABLE ]
++    Alignment:       4
++    SectionData:     00000000
++  - Name:            .debug_discardable
++    Characteristics: [ IMAGE_SCN_MEM_DISCARDABLE ]
++    Alignment:       4
++    SectionData:     00000000
++  - Name:            .debug_undiscardable
++    Characteristics: [  ]
++    Alignment:       4
++    SectionData:     00000000
++  - Name:            .llvm_addrsig
++    Characteristics: [ IMAGE_SCN_LNK_REMOVE ]
++    Alignment:       4
++    SectionData:     00000000
++symbols:         
++  - Name:            external
++    Value:           0
++    SectionNumber:   1
++    SimpleType:      IMAGE_SYM_TYPE_NULL
++    ComplexType:     IMAGE_SYM_DTYPE_NULL
++    StorageClass:    IMAGE_SYM_CLASS_EXTERNAL
++  - Name:            local_unreferenced
++    Value:           0
++    SectionNumber:   1
++    SimpleType:      IMAGE_SYM_TYPE_NULL
++    ComplexType:     IMAGE_SYM_DTYPE_NULL
++    StorageClass:    IMAGE_SYM_CLASS_STATIC
++  - Name:            debug_discardable_sym
++    Value:           0
++    SectionNumber:   6
++    SimpleType:      IMAGE_SYM_TYPE_NULL
++    ComplexType:     IMAGE_SYM_DTYPE_NULL
++    StorageClass:    IMAGE_SYM_CLASS_EXTERNAL
++  - Name:            debug_undiscardable_sym
++    Value:           0
++    SectionNumber:   7
++    SimpleType:      IMAGE_SYM_TYPE_NULL
++    ComplexType:     IMAGE_SYM_DTYPE_NULL
++    StorageClass:    IMAGE_SYM_CLASS_EXTERNAL
++...
+diff --git a/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp b/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp
+index dd2e4829218..13d8efde37c 100644
+--- a/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp
++++ b/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp
+@@ -26,9 +26,20 @@ namespace coff {
+ using namespace object;
+ using namespace COFF;
+ 
++static bool isDebugSection(const Section &Sec) {
++  return Sec.Name.startswith(".debug");
++}
++
+ static Error handleArgs(const CopyConfig &Config, Object &Obj) {
+   // Perform the actual section removals.
+   Obj.removeSections([&Config](const Section &Sec) {
++    if (Config.StripDebug || Config.StripAll || Config.StripAllGNU ||
++        Config.DiscardAll || Config.StripUnneeded) {
++      if (isDebugSection(Sec) &&
++          (Sec.Header.Characteristics & IMAGE_SCN_MEM_DISCARDABLE) != 0)
++        return true;
++    }
++
+     if (is_contained(Config.ToRemove, Sec.Name))
+       return true;
+ 
+-- 
+2.17.1
+
new file mode 100644
--- /dev/null
+++ b/build/build-clang/mingwclang-llvm-objcopy-COFF-Remove-a-superfluous-namespace-qua.patch
@@ -0,0 +1,27 @@
+From a495c9ae6fb3367e6b59d8d245273ed3669754f0 Mon Sep 17 00:00:00 2001
+From: Martin Storsjo <martin@martin.st>
+Date: Sat, 19 Jan 2019 19:42:23 +0000
+Subject: [PATCH] [llvm-objcopy] [COFF] Remove a superfluous namespace
+ qualification. NFC.
+
+git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@351658 91177308-0d34-0410-b5e6-96231b3b80d8
+---
+ tools/llvm-objcopy/COFF/COFFObjcopy.cpp | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp b/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp
+index ceebf600b3a..437dccbd3d5 100644
+--- a/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp
++++ b/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp
+@@ -78,7 +78,7 @@ static Error handleArgs(const CopyConfig &Config, Object &Obj) {
+ }
+ 
+ void executeObjcopyOnBinary(const CopyConfig &Config,
+-                            object::COFFObjectFile &In, Buffer &Out) {
++                            COFFObjectFile &In, Buffer &Out) {
+   COFFReader Reader(In);
+   Expected<std::unique_ptr<Object>> ObjOrErr = Reader.create();
+   if (!ObjOrErr)
+-- 
+2.17.1
+
new file mode 100644
--- /dev/null
+++ b/build/build-clang/mingwclang-llvm-objcopy-COFF-Update-symbol-indices-in-weak-exte.patch
@@ -0,0 +1,224 @@
+From d37f67c7311cd371d9ff1afd398bc92f309e6baf Mon Sep 17 00:00:00 2001
+From: Martin Storsjo <martin@martin.st>
+Date: Tue, 22 Jan 2019 10:58:09 +0000
+Subject: [PATCH] [llvm-objcopy] [COFF] Update symbol indices in weak externals
+
+Differential Revision: https://reviews.llvm.org/D57006
+
+git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@351800 91177308-0d34-0410-b5e6-96231b3b80d8
+---
+ .../llvm-objcopy/COFF/weak-external.test      | 49 +++++++++++++++++++
+ tools/llvm-objcopy/COFF/Object.h              |  2 +
+ tools/llvm-objcopy/COFF/Reader.cpp            | 24 ++++++++-
+ tools/llvm-objcopy/COFF/Reader.h              |  2 +-
+ tools/llvm-objcopy/COFF/Writer.cpp            | 16 +++++-
+ tools/llvm-objcopy/COFF/Writer.h              |  2 +-
+ 6 files changed, 89 insertions(+), 6 deletions(-)
+ create mode 100644 test/tools/llvm-objcopy/COFF/weak-external.test
+
+diff --git a/llvm/test/tools/llvm-objcopy/COFF/weak-external.test b/llvm/test/tools/llvm-objcopy/COFF/weak-external.test
+new file mode 100644
+index 00000000000..d36a53b4eb1
+--- /dev/null
++++ b/llvm/test/tools/llvm-objcopy/COFF/weak-external.test
+@@ -0,0 +1,49 @@
++# RUN: yaml2obj %s > %t.in.o
++
++# RUN: llvm-objdump -t %t.in.o | FileCheck %s --check-prefixes=SYMBOLS,SYMBOLS-PRE
++
++# RUN: llvm-objcopy -N func %t.in.o %t.out.o
++# RUN: llvm-objdump -t %t.out.o | FileCheck %s --check-prefixes=SYMBOLS,SYMBOLS-POST
++
++# RUN: not llvm-objcopy -N .weak.foobar.file1 %t.in.o %t.err.o 2>&1 | FileCheck %s --check-prefix=ERROR
++
++# SYMBOLS: SYMBOL TABLE:
++# SYMBOLS-PRE-NEXT: func
++# SYMBOLS-NEXT: .weak.foobar.file1
++# SYMBOLS-NEXT: foobar
++# SYMBOLS-PRE-NEXT: AUX indx 1
++# SYMBOLS-POST-NEXT: AUX indx 0
++# SYMBOLS-EMPTY:
++
++# ERROR: Symbol 'foobar' is missing its weak target
++
++--- !COFF
++header:          
++  Machine:         IMAGE_FILE_MACHINE_AMD64
++  Characteristics: [  ]
++sections:        
++  - Name:            .text
++    Characteristics: [  ]
++symbols:         
++  - Name:            func
++    Value:           0
++    SectionNumber:   1
++    SimpleType:      IMAGE_SYM_TYPE_NULL
++    ComplexType:     IMAGE_SYM_DTYPE_NULL
++    StorageClass:    IMAGE_SYM_CLASS_EXTERNAL
++  - Name:            .weak.foobar.file1
++    Value:           1
++    SectionNumber:   1
++    SimpleType:      IMAGE_SYM_TYPE_NULL
++    ComplexType:     IMAGE_SYM_DTYPE_NULL
++    StorageClass:    IMAGE_SYM_CLASS_EXTERNAL
++  - Name:            foobar
++    Value:           0
++    SectionNumber:   0
++    SimpleType:      IMAGE_SYM_TYPE_NULL
++    ComplexType:     IMAGE_SYM_DTYPE_FUNCTION
++    StorageClass:    IMAGE_SYM_CLASS_WEAK_EXTERNAL
++    WeakExternal:    
++      TagIndex:        1
++      Characteristics: IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY
++...
+diff --git a/llvm/tools/llvm-objcopy/COFF/Object.h b/llvm/tools/llvm-objcopy/COFF/Object.h
+index 8e200369f0b..0630f9c5ff8 100644
+--- a/llvm/tools/llvm-objcopy/COFF/Object.h
++++ b/llvm/tools/llvm-objcopy/COFF/Object.h
+@@ -11,6 +11,7 @@
+ 
+ #include "llvm/ADT/ArrayRef.h"
+ #include "llvm/ADT/DenseMap.h"
++#include "llvm/ADT/Optional.h"
+ #include "llvm/ADT/StringRef.h"
+ #include "llvm/ADT/iterator_range.h"
+ #include "llvm/BinaryFormat/COFF.h"
+@@ -47,6 +48,7 @@ struct Symbol {
+   std::vector<uint8_t> AuxData;
+   ssize_t TargetSectionId;
+   ssize_t AssociativeComdatTargetSectionId = 0;
++  Optional<size_t> WeakTargetSymbolId;
+   size_t UniqueId;
+   size_t RawIndex;
+   bool Referenced;
+diff --git a/llvm/tools/llvm-objcopy/COFF/Reader.cpp b/llvm/tools/llvm-objcopy/COFF/Reader.cpp
+index 20ff32a59dc..2446277cc2b 100644
+--- a/llvm/tools/llvm-objcopy/COFF/Reader.cpp
++++ b/llvm/tools/llvm-objcopy/COFF/Reader.cpp
+@@ -121,12 +121,18 @@ Error COFFReader::readSymbols(Object &Obj, bool IsBigObj) const {
+     // For section definitions, check if it is comdat associative, and if
+     // it is, find the target section unique id.
+     const coff_aux_section_definition *SD = SymRef.getSectionDefinition();
++    const coff_aux_weak_external *WE = SymRef.getWeakExternal();
+     if (SD && SD->Selection == IMAGE_COMDAT_SELECT_ASSOCIATIVE) {
+       int32_t Index = SD->getNumber(IsBigObj);
+       if (Index <= 0 || static_cast<uint32_t>(Index - 1) >= Sections.size())
+         return createStringError(object_error::parse_failed,
+                                  "Unexpected associative section index");
+       Sym.AssociativeComdatTargetSectionId = Sections[Index - 1].UniqueId;
++    } else if (WE) {
++      // This is a raw symbol index for now, but store it in the Symbol
++      // until we've added them to the Object, which assigns the final
++      // unique ids.
++      Sym.WeakTargetSymbolId = WE->TagIndex;
+     }
+     I += 1 + SymRef.getNumberOfAuxSymbols();
+   }
+@@ -134,13 +140,27 @@ Error COFFReader::readSymbols(Object &Obj, bool IsBigObj) const {
+   return Error::success();
+ }
+ 
+-Error COFFReader::setRelocTargets(Object &Obj) const {
++Error COFFReader::setSymbolTargets(Object &Obj) const {
+   std::vector<const Symbol *> RawSymbolTable;
+   for (const Symbol &Sym : Obj.getSymbols()) {
+     RawSymbolTable.push_back(&Sym);
+     for (size_t I = 0; I < Sym.Sym.NumberOfAuxSymbols; I++)
+       RawSymbolTable.push_back(nullptr);
+   }
++  for (Symbol &Sym : Obj.getMutableSymbols()) {
++    // Convert WeakTargetSymbolId from the original raw symbol index to
++    // a proper unique id.
++    if (Sym.WeakTargetSymbolId) {
++      if (*Sym.WeakTargetSymbolId >= RawSymbolTable.size())
++        return createStringError(object_error::parse_failed,
++                                 "Weak external reference out of range");
++      const Symbol *Target = RawSymbolTable[*Sym.WeakTargetSymbolId];
++      if (Target == nullptr)
++        return createStringError(object_error::parse_failed,
++                                 "Invalid SymbolTableIndex");
++      Sym.WeakTargetSymbolId = Target->UniqueId;
++    }
++  }
+   for (Section &Sec : Obj.getMutableSections()) {
+     for (Relocation &R : Sec.Relocs) {
+       if (R.Reloc.SymbolTableIndex >= RawSymbolTable.size())
+@@ -184,7 +204,7 @@ Expected<std::unique_ptr<Object>> COFFReader::create() const {
+     return std::move(E);
+   if (Error E = readSymbols(*Obj, IsBigObj))
+     return std::move(E);
+-  if (Error E = setRelocTargets(*Obj))
++  if (Error E = setSymbolTargets(*Obj))
+     return std::move(E);
+ 
+   return std::move(Obj);
+diff --git a/llvm/tools/llvm-objcopy/COFF/Reader.h b/llvm/tools/llvm-objcopy/COFF/Reader.h
+index 4493705e73c..ec15369db0b 100644
+--- a/llvm/tools/llvm-objcopy/COFF/Reader.h
++++ b/llvm/tools/llvm-objcopy/COFF/Reader.h
+@@ -28,7 +28,7 @@ class COFFReader {
+   Error readExecutableHeaders(Object &Obj) const;
+   Error readSections(Object &Obj) const;
+   Error readSymbols(Object &Obj, bool IsBigObj) const;
+-  Error setRelocTargets(Object &Obj) const;
++  Error setSymbolTargets(Object &Obj) const;
+ 
+ public:
+   explicit COFFReader(const COFFObjectFile &O) : COFFObj(O) {}
+diff --git a/llvm/tools/llvm-objcopy/COFF/Writer.cpp b/llvm/tools/llvm-objcopy/COFF/Writer.cpp
+index 0321f94a896..4f57131d5ab 100644
+--- a/llvm/tools/llvm-objcopy/COFF/Writer.cpp
++++ b/llvm/tools/llvm-objcopy/COFF/Writer.cpp
+@@ -38,7 +38,7 @@ Error COFFWriter::finalizeRelocTargets() {
+   return Error::success();
+ }
+ 
+-Error COFFWriter::finalizeSectionNumbers() {
++Error COFFWriter::finalizeSymbolContents() {
+   for (Symbol &Sym : Obj.getMutableSymbols()) {
+     if (Sym.TargetSectionId <= 0) {
+       // Undefined, or a special kind of symbol. These negative values
+@@ -75,6 +75,18 @@ Error COFFWriter::finalizeSectionNumbers() {
+         SD->NumberHighPart = static_cast<uint16_t>(SDSectionNumber >> 16);
+       }
+     }
++    // Check that we actually have got AuxData to match the weak symbol target
++    // we want to set. Only >= 1 would be required, but only == 1 makes sense.
++    if (Sym.WeakTargetSymbolId && Sym.Sym.NumberOfAuxSymbols == 1) {
++      coff_aux_weak_external *WE =
++          reinterpret_cast<coff_aux_weak_external *>(Sym.AuxData.data());
++      const Symbol *Target = Obj.findSymbol(*Sym.WeakTargetSymbolId);
++      if (Target == nullptr)
++        return createStringError(object_error::invalid_symbol_index,
++                                 "Symbol '%s' is missing its weak target",
++                                 Sym.Name.str().c_str());
++      WE->TagIndex = Target->RawIndex;
++    }
+   }
+   return Error::success();
+ }
+@@ -137,7 +149,7 @@ std::pair<size_t, size_t> COFFWriter::finalizeSymbolTable() {
+ Error COFFWriter::finalize(bool IsBigObj) {
+   if (Error E = finalizeRelocTargets())
+     return E;
+-  if (Error E = finalizeSectionNumbers())
++  if (Error E = finalizeSymbolContents())
+     return E;
+ 
+   size_t SizeOfHeaders = 0;
+diff --git a/llvm/tools/llvm-objcopy/COFF/Writer.h b/llvm/tools/llvm-objcopy/COFF/Writer.h
+index a967a103df9..9b1cfa91d00 100644
+--- a/llvm/tools/llvm-objcopy/COFF/Writer.h
++++ b/llvm/tools/llvm-objcopy/COFF/Writer.h
+@@ -31,7 +31,7 @@ class COFFWriter {
+   StringTableBuilder StrTabBuilder;
+ 
+   Error finalizeRelocTargets();
+-  Error finalizeSectionNumbers();
++  Error finalizeSymbolContents();
+   void layoutSections();
+   size_t finalizeStringTable();
+   template <class SymbolTy> std::pair<size_t, size_t> finalizeSymbolTable();
+-- 
+2.17.1
+
new file mode 100644
--- /dev/null
+++ b/build/build-clang/mingwclang-llvm-objcopy-Consistently-use-createStringError-inst.patch
@@ -0,0 +1,242 @@
+From d3b89a1637cddee1c61e59257cfe92227ead29e5 Mon Sep 17 00:00:00 2001
+From: Martin Storsjo <martin@martin.st>
+Date: Tue, 22 Jan 2019 10:57:59 +0000
+Subject: [PATCH] [llvm-objcopy] Consistently use createStringError instead of
+ make_error<StringError>
+
+This was requested in the review of D57006.
+
+Also add missing quotes around symbol names in error messages.
+
+Differential Revision: https://reviews.llvm.org/D57014
+
+git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@351799 91177308-0d34-0410-b5e6-96231b3b80d8
+---
+ .../llvm-objcopy/COFF/remove-section.test     |  2 +-
+ tools/llvm-objcopy/COFF/COFFObjcopy.cpp       |  8 ++---
+ tools/llvm-objcopy/COFF/Object.cpp            |  5 ++-
+ tools/llvm-objcopy/COFF/Reader.cpp            | 24 +++++++-------
+ tools/llvm-objcopy/COFF/Writer.cpp            | 33 +++++++++----------
+ tools/llvm-objcopy/ELF/ELFObjcopy.cpp         | 10 +++---
+ 6 files changed, 40 insertions(+), 42 deletions(-)
+
+diff --git a/llvm/test/tools/llvm-objcopy/COFF/remove-section.test b/llvm/test/tools/llvm-objcopy/COFF/remove-section.test
+index b3dfb0b98cb..6dc8f6a6c2e 100644
+--- a/test/tools/llvm-objcopy/COFF/remove-section.test
++++ b/llvm/test/tools/llvm-objcopy/COFF/remove-section.test
+@@ -96,7 +96,7 @@
+ # Removing the .comdat section fails, since the .text section has relocations
+ # against it.
+ #
+-# ERROR-RELOC: Relocation target foo ({{.*}}) not found
++# ERROR-RELOC: Relocation target 'foo' ({{.*}}) not found
+ #
+ #
+ # Removing the .comdat section and .text (with a relocation against .comdat)
+diff --git a/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp b/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp
+index 99929d10a1f..8d8f53d13d8 100644
+--- a/tools/llvm-objcopy/COFF/COFFObjcopy.cpp
++++ b/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp
+@@ -84,10 +84,10 @@ static Error handleArgs(const CopyConfig &Config, Object &Obj) {
+       // Explicitly removing a referenced symbol is an error.
+       if (Sym.Referenced)
+         reportError(Config.OutputFilename,
+-                    make_error<StringError>(
+-                        "not stripping symbol '" + Sym.Name +
+-                            "' because it is named in a relocation.",
+-                        llvm::errc::invalid_argument));
++                    createStringError(llvm::errc::invalid_argument,
++                                      "not stripping symbol '%s' because it is "
++                                      "named in a relocation.",
++                                      Sym.Name.str().c_str()));
+       return true;
+     }
+ 
+diff --git a/llvm/tools/llvm-objcopy/COFF/Object.cpp b/llvm/tools/llvm-objcopy/COFF/Object.cpp
+index fc87d9e574d..83435dffa98 100644
+--- a/tools/llvm-objcopy/COFF/Object.cpp
++++ b/llvm/tools/llvm-objcopy/COFF/Object.cpp
+@@ -56,9 +56,8 @@ Error Object::markSymbols() {
+     for (const Relocation &R : Sec.Relocs) {
+       auto It = SymbolMap.find(R.Target);
+       if (It == SymbolMap.end())
+-        return make_error<StringError>("Relocation target " + Twine(R.Target) +
+-                                           " not found",
+-                                       object_error::invalid_symbol_index);
++        return createStringError(object_error::invalid_symbol_index,
++                                 "Relocation target %zu not found", R.Target);
+       It->second->Referenced = true;
+     }
+   }
+diff --git a/llvm/tools/llvm-objcopy/COFF/Reader.cpp b/llvm/tools/llvm-objcopy/COFF/Reader.cpp
+index c8abe2913a2..20ff32a59dc 100644
+--- a/tools/llvm-objcopy/COFF/Reader.cpp
++++ b/llvm/tools/llvm-objcopy/COFF/Reader.cpp
+@@ -77,8 +77,8 @@ Error COFFReader::readSections(Object &Obj) const {
+     if (auto EC = COFFObj.getSectionName(Sec, S.Name))
+       return errorCodeToError(EC);
+     if (Sec->hasExtendedRelocations())
+-      return make_error<StringError>("Extended relocations not supported yet",
+-                                     object_error::parse_failed);
++      return createStringError(object_error::parse_failed,
++                               "Extended relocations not supported yet");
+   }
+   Obj.addSections(Sections);
+   return Error::success();
+@@ -116,16 +116,16 @@ Error COFFReader::readSymbols(Object &Obj, bool IsBigObj) const {
+              Sections.size())
+       Sym.TargetSectionId = Sections[SymRef.getSectionNumber() - 1].UniqueId;
+     else
+-      return make_error<StringError>("Section number out of range",
+-                                     object_error::parse_failed);
++      return createStringError(object_error::parse_failed,
++                               "Section number out of range");
+     // For section definitions, check if it is comdat associative, and if
+     // it is, find the target section unique id.
+     const coff_aux_section_definition *SD = SymRef.getSectionDefinition();
+     if (SD && SD->Selection == IMAGE_COMDAT_SELECT_ASSOCIATIVE) {
+       int32_t Index = SD->getNumber(IsBigObj);
+       if (Index <= 0 || static_cast<uint32_t>(Index - 1) >= Sections.size())
+-        return make_error<StringError>("Unexpected associative section index",
+-                                       object_error::parse_failed);
++        return createStringError(object_error::parse_failed,
++                                 "Unexpected associative section index");
+       Sym.AssociativeComdatTargetSectionId = Sections[Index - 1].UniqueId;
+     }
+     I += 1 + SymRef.getNumberOfAuxSymbols();
+@@ -144,12 +144,12 @@ Error COFFReader::setRelocTargets(Object &Obj) const {
+   for (Section &Sec : Obj.getMutableSections()) {
+     for (Relocation &R : Sec.Relocs) {
+       if (R.Reloc.SymbolTableIndex >= RawSymbolTable.size())
+-        return make_error<StringError>("SymbolTableIndex out of range",
+-                                       object_error::parse_failed);
++        return createStringError(object_error::parse_failed,
++                                 "SymbolTableIndex out of range");
+       const Symbol *Sym = RawSymbolTable[R.Reloc.SymbolTableIndex];
+       if (Sym == nullptr)
+-        return make_error<StringError>("Invalid SymbolTableIndex",
+-                                       object_error::parse_failed);
++        return createStringError(object_error::parse_failed,
++                                 "Invalid SymbolTableIndex");
+       R.Target = Sym->UniqueId;
+       R.TargetName = Sym->Name;
+     }
+@@ -169,8 +169,8 @@ Expected<std::unique_ptr<Object>> COFFReader::create() const {
+     Obj->CoffFileHeader = *CFH;
+   } else {
+     if (!CBFH)
+-      return make_error<StringError>("No COFF file header returned",
+-                                     object_error::parse_failed);
++      return createStringError(object_error::parse_failed,
++                               "No COFF file header returned");
+     // Only copying the few fields from the bigobj header that we need
+     // and won't recreate in the end.
+     Obj->CoffFileHeader.Machine = CBFH->Machine;
+diff --git a/llvm/tools/llvm-objcopy/COFF/Writer.cpp b/llvm/tools/llvm-objcopy/COFF/Writer.cpp
+index 9fb7812672b..0321f94a896 100644
+--- a/tools/llvm-objcopy/COFF/Writer.cpp
++++ b/llvm/tools/llvm-objcopy/COFF/Writer.cpp
+@@ -29,10 +29,9 @@ Error COFFWriter::finalizeRelocTargets() {
+     for (Relocation &R : Sec.Relocs) {
+       const Symbol *Sym = Obj.findSymbol(R.Target);
+       if (Sym == nullptr)
+-        return make_error<StringError>("Relocation target " + R.TargetName +
+-                                           " (" + Twine(R.Target) +
+-                                           ") not found",
+-                                       object_error::invalid_symbol_index);
++        return createStringError(object_error::invalid_symbol_index,
++                                 "Relocation target '%s' (%zu) not found",
++                                 R.TargetName.str().c_str(), R.Target);
+       R.Reloc.SymbolTableIndex = Sym->RawIndex;
+     }
+   }
+@@ -48,9 +47,9 @@ Error COFFWriter::finalizeSectionNumbers() {
+     } else {
+       const Section *Sec = Obj.findSection(Sym.TargetSectionId);
+       if (Sec == nullptr)
+-        return make_error<StringError>("Symbol " + Sym.Name +
+-                                           " points to a removed section",
+-                                       object_error::invalid_symbol_index);
++        return createStringError(object_error::invalid_symbol_index,
++                                 "Symbol '%s' points to a removed section",
++                                 Sym.Name.str().c_str());
+       Sym.Sym.SectionNumber = Sec->Index;
+ 
+       if (Sym.Sym.NumberOfAuxSymbols == 1 &&
+@@ -65,9 +64,10 @@ Error COFFWriter::finalizeSectionNumbers() {
+         } else {
+           Sec = Obj.findSection(Sym.AssociativeComdatTargetSectionId);
+           if (Sec == nullptr)
+-            return make_error<StringError>(
+-                "Symbol " + Sym.Name + " is associative to a removed section",
+-                object_error::invalid_symbol_index);
++            return createStringError(
++                object_error::invalid_symbol_index,
++                "Symbol '%s' is associative to a removed section",
++                Sym.Name.str().c_str());
+           SDSectionNumber = Sec->Index;
+         }
+         // Update the section definition with the new section number.
+@@ -343,9 +343,8 @@ Error COFFWriter::patchDebugDirectory() {
+             S.Header.VirtualAddress + S.Header.SizeOfRawData) {
+       if (Dir->RelativeVirtualAddress + Dir->Size >
+           S.Header.VirtualAddress + S.Header.SizeOfRawData)
+-        return make_error<StringError>(
+-            "Debug directory extends past end of section",
+-            object_error::parse_failed);
++        return createStringError(object_error::parse_failed,
++                                 "Debug directory extends past end of section");
+ 
+       size_t Offset = Dir->RelativeVirtualAddress - S.Header.VirtualAddress;
+       uint8_t *Ptr = Buf.getBufferStart() + S.Header.PointerToRawData + Offset;
+@@ -361,15 +360,15 @@ Error COFFWriter::patchDebugDirectory() {
+       return Error::success();
+     }
+   }
+-  return make_error<StringError>("Debug directory not found",
+-                                 object_error::parse_failed);
++  return createStringError(object_error::parse_failed,
++                           "Debug directory not found");
+ }
+ 
+ Error COFFWriter::write() {
+   bool IsBigObj = Obj.getSections().size() > MaxNumberOfSections16;
+   if (IsBigObj && Obj.IsPE)
+-    return make_error<StringError>("Too many sections for executable",
+-                                   object_error::parse_failed);
++    return createStringError(object_error::parse_failed,
++                             "Too many sections for executable");
+   return write(IsBigObj);
+ }
+ 
+diff --git a/llvm/tools/llvm-objcopy/ELF/ELFObjcopy.cpp b/llvm/tools/llvm-objcopy/ELF/ELFObjcopy.cpp
+index db0cd76ced4..a2996395c1f 100644
+--- a/tools/llvm-objcopy/ELF/ELFObjcopy.cpp
++++ b/llvm/tools/llvm-objcopy/ELF/ELFObjcopy.cpp
+@@ -185,9 +185,10 @@ static Error dumpSectionToFile(StringRef SecName, StringRef Filename,
+   for (auto &Sec : Obj.sections()) {
+     if (Sec.Name == SecName) {
+       if (Sec.OriginalData.empty())
+-        return make_error<StringError>("Can't dump section \"" + SecName +
+-                                           "\": it has no contents",
+-                                       object_error::parse_failed);
++        return createStringError(
++            object_error::parse_failed,
++            "Can't dump section \"%s\": it has no contents",
++            SecName.str().c_str());
+       Expected<std::unique_ptr<FileOutputBuffer>> BufferOrErr =
+           FileOutputBuffer::create(Filename, Sec.OriginalData.size());
+       if (!BufferOrErr)
+@@ -200,8 +201,7 @@ static Error dumpSectionToFile(StringRef SecName, StringRef Filename,
+       return Error::success();
+     }
+   }
+-  return make_error<StringError>("Section not found",
+-                                 object_error::parse_failed);
++  return createStringError(object_error::parse_failed, "Section not found");
+ }
+ 
+ static bool isCompressed(const SectionBase &Section) {
+-- 
+2.17.1
+
new file mode 100644
--- /dev/null
+++ b/build/build-clang/mingwclang-llvm-objcopy-Return-Error-from-Buffer-allocate-ELF-W.patch
@@ -0,0 +1,330 @@
+From 8cf7aa39d7c9461e2d765f6d4fa7e0925571695f Mon Sep 17 00:00:00 2001
+From: Jordan Rupprecht <rupprecht@google.com>
+Date: Tue, 22 Jan 2019 23:49:16 +0000
+Subject: [PATCH] [llvm-objcopy] Return Error from Buffer::allocate(),
+ [ELF]Writer::finalize(), and [ELF]Writer::commit()
+
+Summary:
+This patch changes a few methods to return Error instead of manually calling error/reportError to abort. This will make it easier to extract into a library.
+
+Note that error() takes just a string (this patch also adds an overload that takes an Error), while reportError() takes string + [error/code]. To help unify things, use FileError to associate a given filename with an error. Note that this takes some special care (for now), e.g. calling reportError(FileName, <something that could be FileError>) will duplicate the filename. The goal is to eventually remove reportError() and have every error associated with a file to be a FileError, and just one error handling block at the tool level.
+
+This change was suggested in D56806. I took it a little further than suggested, but completely fixing llvm-objcopy will take a couple more patches. If this approach looks good, I'll commit this and apply similar patche(s) for the rest.
+
+This change is NFC in terms of non-error related code, although the error message changes in one context.
+
+Reviewers: alexshap, jhenderson, jakehehrlich, mstorsjo, espindola
+
+Reviewed By: alexshap, jhenderson
+
+Subscribers: llvm-commits, emaste, arichardson
+
+Differential Revision: https://reviews.llvm.org/D56930
+
+git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@351896 91177308-0d34-0410-b5e6-96231b3b80d8
+---
+ .../ELF/fail-no-output-directory.test         |  2 +-
+ tools/llvm-objcopy/Buffer.cpp                 | 20 ++++++++++++-----
+ tools/llvm-objcopy/Buffer.h                   |  6 ++---
+ tools/llvm-objcopy/COFF/Writer.cpp            |  3 ++-
+ tools/llvm-objcopy/ELF/ELFObjcopy.cpp         | 18 ++++++++++-----
+ tools/llvm-objcopy/ELF/Object.cpp             | 22 ++++++++++---------
+ tools/llvm-objcopy/ELF/Object.h               | 12 +++++-----
+ tools/llvm-objcopy/llvm-objcopy.cpp           | 15 +++++++++++--
+ tools/llvm-objcopy/llvm-objcopy.h             |  1 +
+ 9 files changed, 64 insertions(+), 35 deletions(-)
+
+diff --git a/llvm/test/tools/llvm-objcopy/ELF/fail-no-output-directory.test b/llvm/test/tools/llvm-objcopy/ELF/fail-no-output-directory.test
+index f66b2e09fce..732046fa925 100644
+--- a/llvm/test/tools/llvm-objcopy/ELF/fail-no-output-directory.test
++++ b/llvm/test/tools/llvm-objcopy/ELF/fail-no-output-directory.test
+@@ -1,6 +1,6 @@
+ # RUN: yaml2obj %s > %t
+ # RUN: not llvm-objcopy %t no/such/dir 2>&1 | FileCheck %s
+-# CHECK: failed to open no/such/dir:
++# CHECK: error: 'no/such/dir': No such file or directory
+ 
+ !ELF
+ FileHeader:
+diff --git a/llvm/tools/llvm-objcopy/Buffer.cpp b/llvm/tools/llvm-objcopy/Buffer.cpp
+index 2da03dee1af..1789097f276 100644
+--- a/llvm/tools/llvm-objcopy/Buffer.cpp
++++ b/llvm/tools/llvm-objcopy/Buffer.cpp
+@@ -17,23 +17,31 @@ namespace objcopy {
+ 
+ Buffer::~Buffer() {}
+ 
+-void FileBuffer::allocate(size_t Size) {
++Error FileBuffer::allocate(size_t Size) {
+   Expected<std::unique_ptr<FileOutputBuffer>> BufferOrErr =
+       FileOutputBuffer::create(getName(), Size, FileOutputBuffer::F_executable);
+-  handleAllErrors(BufferOrErr.takeError(), [this](const ErrorInfoBase &E) {
+-    error("failed to open " + getName() + ": " + E.message());
+-  });
++  // FileOutputBuffer::create() returns an Error that is just a wrapper around
++  // std::error_code. Wrap it in FileError to include the actual filename.
++  if (!BufferOrErr)
++    return createFileError(getName(), BufferOrErr.takeError());
+   Buf = std::move(*BufferOrErr);
++  return Error::success();
+ }
+ 
+-Error FileBuffer::commit() { return Buf->commit(); }
++Error FileBuffer::commit() {
++  Error Err = Buf->commit();
++  // FileOutputBuffer::commit() returns an Error that is just a wrapper around
++  // std::error_code. Wrap it in FileError to include the actual filename.
++  return Err ? createFileError(getName(), std::move(Err)) : std::move(Err);
++}
+ 
+ uint8_t *FileBuffer::getBufferStart() {
+   return reinterpret_cast<uint8_t *>(Buf->getBufferStart());
+ }
+ 
+-void MemBuffer::allocate(size_t Size) {
++Error MemBuffer::allocate(size_t Size) {
+   Buf = WritableMemoryBuffer::getNewMemBuffer(Size, getName());
++  return Error::success();
+ }
+ 
+ Error MemBuffer::commit() { return Error::success(); }
+diff --git a/llvm/tools/llvm-objcopy/Buffer.h b/llvm/tools/llvm-objcopy/Buffer.h
+index 482777fe05c..40670accac2 100644
+--- a/llvm/tools/llvm-objcopy/Buffer.h
++++ b/llvm/tools/llvm-objcopy/Buffer.h
+@@ -27,7 +27,7 @@ class Buffer {
+ 
+ public:
+   virtual ~Buffer();
+-  virtual void allocate(size_t Size) = 0;
++  virtual Error allocate(size_t Size) = 0;
+   virtual uint8_t *getBufferStart() = 0;
+   virtual Error commit() = 0;
+ 
+@@ -39,7 +39,7 @@ class FileBuffer : public Buffer {
+   std::unique_ptr<FileOutputBuffer> Buf;
+ 
+ public:
+-  void allocate(size_t Size) override;
++  Error allocate(size_t Size) override;
+   uint8_t *getBufferStart() override;
+   Error commit() override;
+ 
+@@ -50,7 +50,7 @@ class MemBuffer : public Buffer {
+   std::unique_ptr<WritableMemoryBuffer> Buf;
+ 
+ public:
+-  void allocate(size_t Size) override;
++  Error allocate(size_t Size) override;
+   uint8_t *getBufferStart() override;
+   Error commit() override;
+ 
+diff --git a/llvm/tools/llvm-objcopy/COFF/Writer.cpp b/llvm/tools/llvm-objcopy/COFF/Writer.cpp
+index 4f57131d5ab..db3589bb119 100644
+--- a/llvm/tools/llvm-objcopy/COFF/Writer.cpp
++++ b/llvm/tools/llvm-objcopy/COFF/Writer.cpp
+@@ -324,7 +324,8 @@ Error COFFWriter::write(bool IsBigObj) {
+   if (Error E = finalize(IsBigObj))
+     return E;
+ 
+-  Buf.allocate(FileSize);
++  if (Error E = Buf.allocate(FileSize))
++    return E;
+ 
+   writeHeaders(IsBigObj);
+   writeSections();
+diff --git a/llvm/tools/llvm-objcopy/ELF/ELFObjcopy.cpp b/llvm/tools/llvm-objcopy/ELF/ELFObjcopy.cpp
+index a2996395c1f..2a52f1f9951 100644
+--- a/llvm/tools/llvm-objcopy/ELF/ELFObjcopy.cpp
++++ b/llvm/tools/llvm-objcopy/ELF/ELFObjcopy.cpp
+@@ -176,8 +176,10 @@ static void splitDWOToFile(const CopyConfig &Config, const Reader &Reader,
+     DWOFile->Machine = Config.OutputArch.getValue().EMachine;
+   FileBuffer FB(File);
+   auto Writer = createWriter(Config, *DWOFile, FB, OutputElfType);
+-  Writer->finalize();
+-  Writer->write();
++  if (Error E = Writer->finalize())
++    error(std::move(E));
++  if (Error E = Writer->write())
++    error(std::move(E));
+ }
+ 
+ static Error dumpSectionToFile(StringRef SecName, StringRef Filename,
+@@ -542,8 +544,10 @@ void executeObjcopyOnRawBinary(const CopyConfig &Config, MemoryBuffer &In,
+   handleArgs(Config, *Obj, Reader, OutputElfType);
+   std::unique_ptr<Writer> Writer =
+       createWriter(Config, *Obj, Out, OutputElfType);
+-  Writer->finalize();
+-  Writer->write();
++  if (Error E = Writer->finalize())
++    error(std::move(E));
++  if (Error E = Writer->write())
++    error(std::move(E));
+ }
+ 
+ void executeObjcopyOnBinary(const CopyConfig &Config,
+@@ -570,8 +574,10 @@ void executeObjcopyOnBinary(const CopyConfig &Config,
+   handleArgs(Config, *Obj, Reader, OutputElfType);
+   std::unique_ptr<Writer> Writer =
+       createWriter(Config, *Obj, Out, OutputElfType);
+-  Writer->finalize();
+-  Writer->write();
++  if (Error E = Writer->finalize())
++    error(std::move(E));
++  if (Error E = Writer->write())
++    error(std::move(E));
+   if (!Config.BuildIdLinkDir.empty() && Config.BuildIdLinkOutput) {
+     linkToBuildIdDir(Config, Config.OutputFilename,
+                      Config.BuildIdLinkOutput.getValue(), BuildIdBytes);
+diff --git a/llvm/tools/llvm-objcopy/ELF/Object.cpp b/llvm/tools/llvm-objcopy/ELF/Object.cpp
+index fecb752a39f..ef5dc5d7951 100644
+--- a/llvm/tools/llvm-objcopy/ELF/Object.cpp
++++ b/llvm/tools/llvm-objcopy/ELF/Object.cpp
+@@ -1488,17 +1488,16 @@ template <class ELFT> size_t ELFWriter<ELFT>::totalSize() const {
+          NullSectionSize;
+ }
+ 
+-template <class ELFT> void ELFWriter<ELFT>::write() {
++template <class ELFT> Error ELFWriter<ELFT>::write() {
+   writeEhdr();
+   writePhdrs();
+   writeSectionData();
+   if (WriteSectionHeaders)
+     writeShdrs();
+-  if (auto E = Buf.commit())
+-    reportError(Buf.getName(), errorToErrorCode(std::move(E)));
++  return Buf.commit();
+ }
+ 
+-template <class ELFT> void ELFWriter<ELFT>::finalize() {
++template <class ELFT> Error ELFWriter<ELFT>::finalize() {
+   // It could happen that SectionNames has been removed and yet the user wants
+   // a section header table output. We need to throw an error if a user tries
+   // to do that.
+@@ -1582,21 +1581,22 @@ template <class ELFT> void ELFWriter<ELFT>::finalize() {
+     Section.finalize();
+   }
+ 
+-  Buf.allocate(totalSize());
++  if (Error E = Buf.allocate(totalSize()))
++    return E;
+   SecWriter = llvm::make_unique<ELFSectionWriter<ELFT>>(Buf);
++  return Error::success();
+ }
+ 
+-void BinaryWriter::write() {
++Error BinaryWriter::write() {
+   for (auto &Section : Obj.sections()) {
+     if ((Section.Flags & SHF_ALLOC) == 0)
+       continue;
+     Section.accept(*SecWriter);
+   }
+-  if (auto E = Buf.commit())
+-    reportError(Buf.getName(), errorToErrorCode(std::move(E)));
++  return Buf.commit();
+ }
+ 
+-void BinaryWriter::finalize() {
++Error BinaryWriter::finalize() {
+   // TODO: Create a filter range to construct OrderedSegments from so that this
+   // code can be deduped with assignOffsets above. This should also solve the
+   // todo below for LayoutSections.
+@@ -1675,8 +1675,10 @@ void BinaryWriter::finalize() {
+       TotalSize = std::max(TotalSize, Section->Offset + Section->Size);
+   }
+ 
+-  Buf.allocate(TotalSize);
++  if (Error E = Buf.allocate(TotalSize))
++    return E;
+   SecWriter = llvm::make_unique<BinarySectionWriter>(Buf);
++  return Error::success();
+ }
+ 
+ template class ELFBuilder<ELF64LE>;
+diff --git a/llvm/tools/llvm-objcopy/ELF/Object.h b/llvm/tools/llvm-objcopy/ELF/Object.h
+index 0dcb0d888bc..9e2b64be9dc 100644
+--- a/llvm/tools/llvm-objcopy/ELF/Object.h
++++ b/llvm/tools/llvm-objcopy/ELF/Object.h
+@@ -193,8 +193,8 @@ protected:
+ 
+ public:
+   virtual ~Writer();
+-  virtual void finalize() = 0;
+-  virtual void write() = 0;
++  virtual Error finalize() = 0;
++  virtual Error write() = 0;
+ 
+   Writer(Object &O, Buffer &B) : Obj(O), Buf(B) {}
+ };
+@@ -226,8 +226,8 @@ public:
+   virtual ~ELFWriter() {}
+   bool WriteSectionHeaders = true;
+ 
+-  void finalize() override;
+-  void write() override;
++  Error finalize() override;
++  Error write() override;
+   ELFWriter(Object &Obj, Buffer &Buf, bool WSH)
+       : Writer(Obj, Buf), WriteSectionHeaders(WSH) {}
+ };
+@@ -240,8 +240,8 @@ private:
+ 
+ public:
+   ~BinaryWriter() {}
+-  void finalize() override;
+-  void write() override;
++  Error finalize() override;
++  Error write() override;
+   BinaryWriter(Object &Obj, Buffer &Buf) : Writer(Obj, Buf) {}
+ };
+ 
+diff --git a/llvm/tools/llvm-objcopy/llvm-objcopy.cpp b/llvm/tools/llvm-objcopy/llvm-objcopy.cpp
+index d27395f2ae0..75d513546b7 100644
+--- a/llvm/tools/llvm-objcopy/llvm-objcopy.cpp
++++ b/llvm/tools/llvm-objcopy/llvm-objcopy.cpp
+@@ -56,6 +56,16 @@ LLVM_ATTRIBUTE_NORETURN void error(Twine Message) {
+   exit(1);
+ }
+ 
++LLVM_ATTRIBUTE_NORETURN void error(Error E) {
++  assert(E);
++  std::string Buf;
++  raw_string_ostream OS(Buf);
++  logAllUnhandledErrors(std::move(E), OS);
++  OS.flush();
++  WithColor::error(errs(), ToolName) << Buf;
++  exit(1);
++}
++
+ LLVM_ATTRIBUTE_NORETURN void reportError(StringRef File, std::error_code EC) {
+   assert(EC);
+   WithColor::error(errs(), ToolName)
+@@ -100,10 +110,11 @@ static Error deepWriteArchive(StringRef ArcName,
+     // NewArchiveMember still requires them even though writeArchive does not
+     // write them on disk.
+     FileBuffer FB(Member.MemberName);
+-    FB.allocate(Member.Buf->getBufferSize());
++    if (Error E = FB.allocate(Member.Buf->getBufferSize()))
++      return E;
+     std::copy(Member.Buf->getBufferStart(), Member.Buf->getBufferEnd(),
+               FB.getBufferStart());
+-    if (auto E = FB.commit())
++    if (Error E = FB.commit())
+       return E;
+   }
+   return Error::success();
+diff --git a/llvm/tools/llvm-objcopy/llvm-objcopy.h b/llvm/tools/llvm-objcopy/llvm-objcopy.h
+index 46d8339576c..18a789ca1f8 100644
+--- a/llvm/tools/llvm-objcopy/llvm-objcopy.h
++++ b/llvm/tools/llvm-objcopy/llvm-objcopy.h
+@@ -19,6 +19,7 @@ namespace llvm {
+ namespace objcopy {
+ 
+ LLVM_ATTRIBUTE_NORETURN extern void error(Twine Message);
++LLVM_ATTRIBUTE_NORETURN extern void error(Error E);
+ LLVM_ATTRIBUTE_NORETURN extern void reportError(StringRef File, Error E);
+ LLVM_ATTRIBUTE_NORETURN extern void reportError(StringRef File,
+                                                 std::error_code EC);
+-- 
+2.17.1
+
--- a/taskcluster/scripts/misc/build-clang-8-mingw.sh
+++ b/taskcluster/scripts/misc/build-clang-8-mingw.sh
@@ -27,19 +27,19 @@ UPLOAD_DIR=$HOME/artifacts
 
 TOOLCHAIN_DIR=$WORKSPACE/moz-toolchain
 INSTALL_DIR=$TOOLCHAIN_DIR/build/stage3/clang
 CROSS_PREFIX_DIR=$INSTALL_DIR/$machine-w64-mingw32
 SRC_DIR=$TOOLCHAIN_DIR/src
 
 make_flags="-j$(nproc)"
 
-mingw_version=d539d36fd573e688ec7ad9dc840e3826a65419b1
-libunwind_version=1f89d78bb488bc71cfdee8281fc0834e9fbe5dce
-llvm_mingw_version=53db1c3a4c9c81972b70556a5ba5cd6ccd8e6e7d
+mingw_version=164990461720e0ed6ea5ea9f359d78595b1a459a
+libunwind_version=6ee92fcc97350ae32db3172a269e9afcc2bab686
+llvm_mingw_version=c3a16814bd26aa6702e1e5b482a3d9044bb0f725
 
 binutils_version=2.27
 binutils_ext=bz2
 binutils_sha=369737ce51587f92466041a97ab7d2358c6d9e1b6490b3940eb09fb0a9a6ac88
 
 # This is default value of _WIN32_WINNT. Gecko configure script explicitly sets this,
 # so this is not used to build Gecko itself. We default to 0x601, which is Windows 7.
 default_win32_winnt=0x601
@@ -188,25 +188,28 @@ build_libcxx() {
       -DCMAKE_INSTALL_PREFIX=$CROSS_PREFIX_DIR \
       -DCMAKE_C_COMPILER=$CC \
       -DCMAKE_CXX_COMPILER=$CXX \
       -DCMAKE_CROSSCOMPILING=TRUE \
       -DCMAKE_SYSROOT=$CROSS_PREFIX_DIR \
       -DCMAKE_SYSTEM_NAME=Windows \
       -DCMAKE_C_COMPILER_WORKS=TRUE \
       -DCMAKE_CXX_COMPILER_WORKS=TRUE \
+      -DLLVM_COMPILER_CHECKED=TRUE \
       -DCMAKE_AR=$INSTALL_DIR/bin/llvm-ar \
       -DCMAKE_RANLIB=$INSTALL_DIR/bin/llvm-ranlib \
       -DLLVM_NO_OLD_LIBSTDCXX=TRUE \
       -DCXX_SUPPORTS_CXX11=TRUE \
+      -DCXX_SUPPORTS_CXX_STD=TRUE \
       -DLIBUNWIND_USE_COMPILER_RT=TRUE \
       -DLIBUNWIND_ENABLE_THREADS=TRUE \
       -DLIBUNWIND_ENABLE_SHARED=FALSE \
       -DLIBUNWIND_ENABLE_CROSS_UNWINDING=FALSE \
-      -DCMAKE_CXX_FLAGS="${DEBUG_FLAGS} -nostdinc++ -I$SRC_DIR/libcxx/include -DPSAPI_VERSION=2" \
+      -DCMAKE_CXX_FLAGS="${DEBUG_FLAGS} -Wno-dll-attribute-on-redeclaration -nostdinc++ -I$SRC_DIR/libcxx/include -DPSAPI_VERSION=2" \
+      -DCMAKE_C_FLAGS="-Wno-dll-attribute-on-redeclaration" \
       $SRC_DIR/libunwind
   make $make_flags
   make $make_flags install
   popd
 
   mkdir libcxxabi
   pushd libcxxabi
   cmake \
@@ -214,42 +217,45 @@ build_libcxx() {
       -DCMAKE_INSTALL_PREFIX=$CROSS_PREFIX_DIR \
       -DCMAKE_C_COMPILER=$CC \
       -DCMAKE_CXX_COMPILER=$CXX \
       -DCMAKE_CROSSCOMPILING=TRUE \
       -DCMAKE_SYSTEM_NAME=Windows \
       -DCMAKE_C_COMPILER_WORKS=TRUE \
       -DCMAKE_CXX_COMPILER_WORKS=TRUE \
       -DCMAKE_SYSROOT=$CROSS_PREFIX_DIR \
+      -DLLVM_COMPILER_CHECKED=TRUE \
       -DCMAKE_AR=$INSTALL_DIR/bin/llvm-ar \
       -DCMAKE_RANLIB=$INSTALL_DIR/bin/llvm-ranlib \
       -DLIBCXXABI_USE_COMPILER_RT=ON \
       -DLIBCXXABI_ENABLE_EXCEPTIONS=ON \
       -DLIBCXXABI_ENABLE_THREADS=ON \
       -DLIBCXXABI_TARGET_TRIPLE=$machine-w64-mingw32 \
       -DLIBCXXABI_ENABLE_SHARED=OFF \
       -DLIBCXXABI_LIBCXX_INCLUDES=$SRC_DIR/libcxx/include \
       -DLLVM_NO_OLD_LIBSTDCXX=TRUE \
       -DCXX_SUPPORTS_CXX11=TRUE \
+      -DCXX_SUPPORTS_CXX_STD=TRUE \
       -DCMAKE_CXX_FLAGS="${DEBUG_FLAGS} -D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS -D_LIBCPP_HAS_THREAD_API_WIN32" \
       $SRC_DIR/libcxxabi
   make $make_flags VERBOSE=1
   popd
 
   mkdir libcxx
   pushd libcxx
   cmake \
       -DCMAKE_BUILD_TYPE=Release \
       -DCMAKE_INSTALL_PREFIX=$CROSS_PREFIX_DIR \
       -DCMAKE_C_COMPILER=$CC \
       -DCMAKE_CXX_COMPILER=$CXX \
       -DCMAKE_CROSSCOMPILING=TRUE \
       -DCMAKE_SYSTEM_NAME=Windows \
       -DCMAKE_C_COMPILER_WORKS=TRUE \
       -DCMAKE_CXX_COMPILER_WORKS=TRUE \
+      -DLLVM_COMPILER_CHECKED=TRUE \
       -DCMAKE_AR=$INSTALL_DIR/bin/llvm-ar \
       -DCMAKE_RANLIB=$INSTALL_DIR/bin/llvm-ranlib \
       -DLIBCXX_USE_COMPILER_RT=ON \
       -DLIBCXX_INSTALL_HEADERS=ON \
       -DLIBCXX_ENABLE_EXCEPTIONS=ON \
       -DLIBCXX_ENABLE_THREADS=ON \
       -DLIBCXX_HAS_WIN32_THREAD_API=ON \
       -DLIBCXX_ENABLE_MONOTONIC_CLOCK=ON \