[tbb-commits] [tor-browser-build/master] Bug 30585: Provide clang 8 for Tor Browser 9

gk at torproject.org gk at torproject.org
Wed Jul 31 09:28:17 UTC 2019


commit 4c2b3a98e04605ce7fcbd1c2c7c4864c6a5125a2
Author: Georg Koppen <gk at torproject.org>
Date:   Thu May 23 12:02:51 2019 +0000

    Bug 30585: Provide clang 8 for Tor Browser 9
    
    Adding a clang project is mainly motivated by getting our
    mingw-w64/clang toolchain for Windows set up (#28716). Clang is a
    separate project and will replace the llvm one (which we use in parallel
    for now) as we don't want to build the clang part every time, say, the
    ming-w64 commit gets updated. Moreover, we need a recent enough clang on
    the host system for building at least the Stylo part in Firefox anyway.
    
    The patches for Windows and general set up is more or less following
    build/build-clang/clang-8-mingw.json on the mozilla-esr68 branch.
---
 keyring/clang.gpg                                | Bin 0 -> 7186 bytes
 projects/clang/build                             |  45 ++
 projects/clang/config                            |  45 ++
 projects/clang/win-patches/llvm-objcopy-1.patch  |  27 +
 projects/clang/win-patches/llvm-objcopy-10.patch |  28 +
 projects/clang/win-patches/llvm-objcopy-11.patch | 377 +++++++++++++
 projects/clang/win-patches/llvm-objcopy-12.patch |  43 ++
 projects/clang/win-patches/llvm-objcopy-2.patch  | 665 +++++++++++++++++++++++
 projects/clang/win-patches/llvm-objcopy-3.patch  | 160 ++++++
 projects/clang/win-patches/llvm-objcopy-4.patch  | 222 ++++++++
 projects/clang/win-patches/llvm-objcopy-5.patch  |  61 +++
 projects/clang/win-patches/llvm-objcopy-6.patch  | 242 +++++++++
 projects/clang/win-patches/llvm-objcopy-7.patch  | 224 ++++++++
 projects/clang/win-patches/llvm-objcopy-8.patch  | 330 +++++++++++
 projects/clang/win-patches/llvm-objcopy-9.patch  | 260 +++++++++
 15 files changed, 2729 insertions(+)

diff --git a/keyring/clang.gpg b/keyring/clang.gpg
new file mode 100644
index 0000000..15f0d8a
Binary files /dev/null and b/keyring/clang.gpg differ
diff --git a/projects/clang/build b/projects/clang/build
new file mode 100644
index 0000000..50576b4
--- /dev/null
+++ b/projects/clang/build
@@ -0,0 +1,45 @@
+#!/bin/bash
+[% c("var/set_default_env") -%]
+distdir=/var/tmp/dist/[% project %]
+mkdir -p /var/tmp/dist
+tar -C /var/tmp/dist -xf [% c('input_files_by_name/cmake') %]
+export PATH="/var/tmp/dist/cmake/bin:$PATH"
+[% IF c("var/linux") %]
+  # We need a link to our GCC, otherwise the system cc gets used which points to
+  # /usr/bin/gcc.
+  [% pc('gcc', 'var/setup', { compiler_tarfile => c('input_files_by_name/gcc'),
+                              hardened_gcc => 0 }) %]
+  ln -s gcc /var/tmp/dist/gcc/bin/cc
+[% END -%]
+mkdir -p /var/tmp/build
+cd /var/tmp/build
+tar -xf $rootdir/[% c('input_files_by_name/llvm') %]
+tar -xf $rootdir/[% c('input_files_by_name/cfe') %]
+tar -xf $rootdir/[% c('input_files_by_name/libcxx') %]
+tar -xf $rootdir/[% c('input_files_by_name/libcxxabi') %]
+tar -xf $rootdir/[% c('input_files_by_name/lld') %]
+tar -xf $rootdir/[% c('input_files_by_name/compiler-rt') %]
+mv llvm-* llvm
+mv cfe-* llvm/tools/clang
+mv libcxx-* llvm/projects/libcxx
+mv libcxxabi-* llvm/projects/libcxxabi
+mv lld-* llvm/tools/lld
+mv compiler-rt-* llvm/projects/compiler-rt
+[% IF c("var/windows") -%]
+  # Patch order is important here
+  for i in {1..12}
+    do git apply $rootdir/win-patches/llvm-objcopy-$i.patch
+  done
+[% END %]
+cd llvm
+export LLVM_HOME=$(pwd)
+mkdir build
+cd build
+cmake .. -G "Unix Makefiles" -DCMAKE_INSTALL_PREFIX=$distdir -DCMAKE_BUILD_TYPE:STRING=Release $LLVM_HOME
+make -j[% c("buildconf/num_procs") %]
+make install
+cd /var/tmp/dist
+[% c('tar', {
+        tar_src => [ project ],
+        tar_args => '-czf ' _ dest_dir _ '/' _ c('filename'),
+    }) %]
diff --git a/projects/clang/config b/projects/clang/config
new file mode 100644
index 0000000..f439cf7
--- /dev/null
+++ b/projects/clang/config
@@ -0,0 +1,45 @@
+# vim: filetype=yaml sw=2
+version: 8.0.0
+filename: '[% project %]-[% c("version") %]-[% c("var/build_id") %].tar.gz'
+gpg_keyring: clang.gpg
+sig_ext: sig
+
+var:
+  container:
+    use_container: 1
+
+targets:
+  windows:
+    var:
+      arch_deps:
+        # We use git to apply patches
+        - git
+
+
+input_files:
+  - project: container-image
+  - name: '[% c("var/compiler") %]'
+    project: '[% c("var/compiler") %]'
+    enable: '[% c("var/linux") %]'
+  - project: cmake
+    name: cmake
+  - URL: 'https://releases.llvm.org/[% c("version") %]/llvm-[% c("version") %].src.tar.xz'
+    name: llvm
+    file_gpg_id: 1
+  - URL: 'https://releases.llvm.org/[% c("version") %]/cfe-[% c("version") %].src.tar.xz'
+    name: cfe
+    file_gpg_id: 1
+  - URL: 'https://releases.llvm.org/[% c("version") %]/libcxx-[% c("version") %].src.tar.xz'
+    name: libcxx
+    file_gpg_id: 1
+  - URL: 'https://releases.llvm.org/[% c("version") %]/libcxxabi-[% c("version") %].src.tar.xz'
+    name: libcxxabi
+    file_gpg_id: 1
+  - URL: 'https://releases.llvm.org/[% c("version") %]/lld-[% c("version") %].src.tar.xz'
+    name: lld
+    file_gpg_id: 1
+  - URL: 'https://releases.llvm.org/[% c("version") %]/compiler-rt-[% c("version") %].src.tar.xz'
+    name: compiler-rt
+    file_gpg_id: 1
+  - filename: win-patches
+    enable: '[% c("var/windows") %]'
diff --git a/projects/clang/win-patches/llvm-objcopy-1.patch b/projects/clang/win-patches/llvm-objcopy-1.patch
new file mode 100644
index 0000000..9c9f250
--- /dev/null
+++ b/projects/clang/win-patches/llvm-objcopy-1.patch
@@ -0,0 +1,27 @@
+From a495c9ae6fb3367e6b59d8d245273ed3669754f0 Mon Sep 17 00:00:00 2001
+From: Martin Storsjo <martin at 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
+
diff --git a/projects/clang/win-patches/llvm-objcopy-10.patch b/projects/clang/win-patches/llvm-objcopy-10.patch
new file mode 100644
index 0000000..4aca911
--- /dev/null
+++ b/projects/clang/win-patches/llvm-objcopy-10.patch
@@ -0,0 +1,28 @@
+From 1284ee3c47bab17ec081b5169633aea4f8abfd30 Mon Sep 17 00:00:00 2001
+From: Martin Storsjo <martin at 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
+
diff --git a/projects/clang/win-patches/llvm-objcopy-11.patch b/projects/clang/win-patches/llvm-objcopy-11.patch
new file mode 100644
index 0000000..9149b80
--- /dev/null
+++ b/projects/clang/win-patches/llvm-objcopy-11.patch
@@ -0,0 +1,377 @@
+From 74c7d422cba163635394ec32f2b243b1de502a18 Mon Sep 17 00:00:00 2001
+From: Martin Storsjo <martin at 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 at 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 at 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 llvm/test/tools/llvm-objcopy/ELF/Inputs/ungzip.py
+rename to llvm/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
+
diff --git a/projects/clang/win-patches/llvm-objcopy-12.patch b/projects/clang/win-patches/llvm-objcopy-12.patch
new file mode 100644
index 0000000..35dec30
--- /dev/null
+++ b/projects/clang/win-patches/llvm-objcopy-12.patch
@@ -0,0 +1,43 @@
+From abacd83232acf69d7cbacd53fc2f9aae66c1a32e Mon Sep 17 00:00:00 2001
+From: Martin Storsjo <martin at 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
+
diff --git a/projects/clang/win-patches/llvm-objcopy-2.patch b/projects/clang/win-patches/llvm-objcopy-2.patch
new file mode 100644
index 0000000..41e7a94
--- /dev/null
+++ b/projects/clang/win-patches/llvm-objcopy-2.patch
@@ -0,0 +1,665 @@
+From 2ccafacb7ddd740054dbee06655749ebc55a4d86 Mon Sep 17 00:00:00 2001
+From: Martin Storsjo <martin at 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
+
diff --git a/projects/clang/win-patches/llvm-objcopy-3.patch b/projects/clang/win-patches/llvm-objcopy-3.patch
new file mode 100644
index 0000000..6e303c0
--- /dev/null
+++ b/projects/clang/win-patches/llvm-objcopy-3.patch
@@ -0,0 +1,160 @@
+From 2b6e1b7585d6bd997ea4e4233c904a6d2c11ad33 Mon Sep 17 00:00:00 2001
+From: Martin Storsjo <martin at 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
+
diff --git a/projects/clang/win-patches/llvm-objcopy-4.patch b/projects/clang/win-patches/llvm-objcopy-4.patch
new file mode 100644
index 0000000..e922384
--- /dev/null
+++ b/projects/clang/win-patches/llvm-objcopy-4.patch
@@ -0,0 +1,222 @@
+From 526aa2e94355b7feb3bf7774a6e1899f68e94ad8 Mon Sep 17 00:00:00 2001
+From: Martin Storsjo <martin at 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
+
diff --git a/projects/clang/win-patches/llvm-objcopy-5.patch b/projects/clang/win-patches/llvm-objcopy-5.patch
new file mode 100644
index 0000000..657c72a
--- /dev/null
+++ b/projects/clang/win-patches/llvm-objcopy-5.patch
@@ -0,0 +1,61 @@
+From 17dcf25b3ade15605ca27150e4440bcc75caed65 Mon Sep 17 00:00:00 2001
+From: Martin Storsjo <martin at 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
+
diff --git a/projects/clang/win-patches/llvm-objcopy-6.patch b/projects/clang/win-patches/llvm-objcopy-6.patch
new file mode 100644
index 0000000..e70f1b9
--- /dev/null
+++ b/projects/clang/win-patches/llvm-objcopy-6.patch
@@ -0,0 +1,242 @@
+From d3b89a1637cddee1c61e59257cfe92227ead29e5 Mon Sep 17 00:00:00 2001
+From: Martin Storsjo <martin at 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/llvm/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/llvm/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/llvm/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/llvm/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/llvm/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/llvm/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
+
diff --git a/projects/clang/win-patches/llvm-objcopy-7.patch b/projects/clang/win-patches/llvm-objcopy-7.patch
new file mode 100644
index 0000000..80e9785
--- /dev/null
+++ b/projects/clang/win-patches/llvm-objcopy-7.patch
@@ -0,0 +1,224 @@
+From d37f67c7311cd371d9ff1afd398bc92f309e6baf Mon Sep 17 00:00:00 2001
+From: Martin Storsjo <martin at 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
+
diff --git a/projects/clang/win-patches/llvm-objcopy-8.patch b/projects/clang/win-patches/llvm-objcopy-8.patch
new file mode 100644
index 0000000..6fd9776
--- /dev/null
+++ b/projects/clang/win-patches/llvm-objcopy-8.patch
@@ -0,0 +1,330 @@
+From 8cf7aa39d7c9461e2d765f6d4fa7e0925571695f Mon Sep 17 00:00:00 2001
+From: Jordan Rupprecht <rupprecht at 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
+
diff --git a/projects/clang/win-patches/llvm-objcopy-9.patch b/projects/clang/win-patches/llvm-objcopy-9.patch
new file mode 100644
index 0000000..6cb4656
--- /dev/null
+++ b/projects/clang/win-patches/llvm-objcopy-9.patch
@@ -0,0 +1,260 @@
+From 840d70f854a1d550924ced1d00160efcc7b8549a Mon Sep 17 00:00:00 2001
+From: Martin Storsjo <martin at 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
+





More information about the tbb-commits mailing list