tbb-commits
Threads by month
- ----- 2025 -----
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- 1 participants
- 18612 discussions

[tor-launcher/master] Bug 31300: Modify Tor Launcher so it is compatible with ESR68
by gk@torproject.org 07 Aug '19
by gk@torproject.org 07 Aug '19
07 Aug '19
commit 1af54380f289426fea9dfa24c4fd6cf171046723
Author: Kathy Brade <brade(a)pearlcrescent.com>
Date: Fri Aug 2 10:23:31 2019 -0400
Bug 31300: Modify Tor Launcher so it is compatible with ESR68
Replace some wizard and dialog "on" attributes with event handlers.
Replace the XUL listbox element (which was removed by Mozilla) with
richlistbox.
Replace the XUL progressmeter element (which was removed by Mozilla) with
an HTML progress element.
Define our own CSS rules for groupbox elements (Mozilla removed the
built-in styles).
Fix some minor CSS incompatibilities.
---
src/chrome/content/localePicker.xul | 6 +-
src/chrome/content/network-settings-shared.js | 8 +--
src/chrome/content/network-settings-wizard.xul | 24 +++-----
src/chrome/content/network-settings.js | 76 +++++++++++++++++++++++---
src/chrome/content/network-settings.xul | 3 -
src/chrome/skin/network-settings.css | 14 +++--
6 files changed, 92 insertions(+), 39 deletions(-)
diff --git a/src/chrome/content/localePicker.xul b/src/chrome/content/localePicker.xul
index 1d0987c..152b54c 100644
--- a/src/chrome/content/localePicker.xul
+++ b/src/chrome/content/localePicker.xul
@@ -1,6 +1,6 @@
<?xml version="1.0"?>
<!--
- - Copyright (c) 2017, The Tor Project, Inc.
+ - Copyright (c) 2019, The Tor Project, Inc.
- See LICENSE for licensing information.
- vim: set sw=2 sts=2 ts=8 et syntax=xml:
-->
@@ -16,8 +16,6 @@
title="&torlauncher.localePicker.title;"
windowtype="TorLauncher:LocalePicker"
persist="screenX screenY"
- onwizardfinish="return setLocale();"
- onwizardcancel="return onCancel();"
onload="initLocaleDialog();">
<script type="application/x-javascript"
@@ -31,7 +29,7 @@
<vbox>
<label class="question">&torlauncher.localePicker.prompt;</label>
<separator/>
- <listbox id="localeList" ondblclick="onLocaleListDoubleClick()"/>
+ <richlistbox id="localeList" ondblclick="onLocaleListDoubleClick()"/>
</vbox>
</wizardpage>
diff --git a/src/chrome/content/network-settings-shared.js b/src/chrome/content/network-settings-shared.js
index 206872b..f1bdb91 100644
--- a/src/chrome/content/network-settings-shared.js
+++ b/src/chrome/content/network-settings-shared.js
@@ -20,7 +20,7 @@ var proxySettings = `
<rows>
<row align="center">
<label value="&torsettings.useProxy.type;" control="proxyType"
- style="text-align:right"/>
+ class="rightAlign"/>
<hbox align="center">
<menulist id="proxyType" sizetopopup="always"
placeholder="&torsettings.useProxy.type.placeholder;"
@@ -38,7 +38,7 @@ var proxySettings = `
</row>
<row align="center">
<label value="&torsettings.useProxy.address;" control="proxyAddr"
- style="text-align:right"/>
+ class="rightAlign"/>
<hbox align="center">
<textbox id="proxyAddr" size="20" flex="1"
placeholder="&torsettings.useProxy.address.placeholder;"/>
@@ -50,7 +50,7 @@ var proxySettings = `
<row align="center">
<label id="proxyUsernameLabel"
value="&torsettings.useProxy.username;"
- control="proxyUsername" style="text-align:right"/>
+ control="proxyUsername" class="rightAlign"/>
<hbox align="center">
<textbox id="proxyUsername" size="14" flex="1"
placeholder="&torsettings.optional;"/>
@@ -146,7 +146,7 @@ var progressContent = `
<vbox flex="1">
<description id="progressPleaseWait"
hidden="true">&torprogress.pleaseWait;</description>
- <progressmeter id="progressMeter" mode="determined" value="0"/>
+ <html:progress id="progressMeter" value="0" max="100"/>
<description id="progressDesc" errorElemId="message"/>
<label id="progressReconfigureLabel" hidden="true"
value="&torsettings.reconfigTor;"/>
diff --git a/src/chrome/content/network-settings-wizard.xul b/src/chrome/content/network-settings-wizard.xul
index 2eb6d6d..ec48bd0 100644
--- a/src/chrome/content/network-settings-wizard.xul
+++ b/src/chrome/content/network-settings-wizard.xul
@@ -1,4 +1,3 @@
-<?xml version="1.0"?>
<!--
- Copyright (c) 2019, The Tor Project, Inc.
- See LICENSE for licensing information.
@@ -17,15 +16,13 @@
windowtype="TorLauncher:NetworkSettings"
persist="screenX screenY"
buttonlabelextra2="&torsettings.copyLog;"
- onwizardfinish="return onWizardFinish();"
- onwizardcancel="return onCancel();"
onload="initDialog();"
onunload="deinitDialog();">
<script type="application/x-javascript"
src="chrome://torlauncher/content/network-settings.js"/>
- <wizardpage pageid="first" next="configureSettings" onextra2="onCopyLog();"
+ <wizardpage pageid="first" next="configureSettings"
torShowNavButtons="false">
<hbox class="tbb-header" pack="center">
<image class="tbb-logo"/>
@@ -44,7 +41,7 @@
</vbox>
</wizardpage>
- <wizardpage pageid="configureSettings" onextra2="onCopyLog();"
+ <wizardpage pageid="configureSettings"
windowtitle="&torsettings.wizard.title.configure;"
torShowNavButtons="true">
<stack flex="1">
@@ -63,11 +60,9 @@
</stack>
</wizardpage>
- <wizardpage pageid="progress" onextra2="onCopyLog();"
+ <wizardpage pageid="progress"
windowtitle="&torsettings.wizard.title.connecting;"
- torShowNavButtons="false"
- onpageshow="onShowProgressPanel();"
- onpagehide="return resetProgressNavButtons();">
+ torShowNavButtons="false">
<vbox id="progressContent"/>
</wizardpage>
@@ -86,12 +81,12 @@
</wizardpage>
<wizardpage pageid="restartPanel" class="messagePanel" next="notUsed"
- pack="center" torShowNavButtons="false" onextra2="onCopyLog();">
+ pack="center" torShowNavButtons="false">
<vbox id="restartContent"/>
</wizardpage>
<wizardpage pageid="errorPanel" class="messagePanel" next="notUsed"
- torShowNavButtons="false" onextra2="onCopyLog();">
+ torShowNavButtons="false">
<spring flex="1"/>
<hbox pack="center">
<description errorElemId="message" flex="1"/>
@@ -104,8 +99,8 @@
<spring flex="1"/>
</wizardpage>
- <wizardpage pageid="discardSettings" next="notUsed" torShowNavButtons="false"
- onextra2="onCopyLog();">
+ <wizardpage pageid="discardSettings" next="notUsed"
+ torShowNavButtons="false">
<hbox class="tbb-header" pack="center">
<image class="tbb-logo"/>
</hbox>
@@ -123,8 +118,7 @@
<spring flex="1"/>
</wizardpage>
- <wizardpage class="help" pageid="helpPanel" next="notUsed"
- onpageadvanced="closeHelp(); return false;">
+ <wizardpage class="help" pageid="helpPanel" next="notUsed">
<vbox id="bridgeHelpContent"/>
<vbox id="proxyHelpContent"/>
</wizardpage>
diff --git a/src/chrome/content/network-settings.js b/src/chrome/content/network-settings.js
index 85dade2..a4f2866 100644
--- a/src/chrome/content/network-settings.js
+++ b/src/chrome/content/network-settings.js
@@ -157,6 +157,51 @@ function initDialogCommon()
.getService(Ci.nsIEnvironment);
if (env.exists("TOR_HIDE_BROWSER_LOGO"))
wizardElem.setAttribute("tor_hide_browser_logo", true);
+
+ // Add wizard event listeners.
+ document.addEventListener("wizardcancel", (aEvent) => {
+ if (!onCancel())
+ aEvent.preventDefault();
+ });
+
+ document.addEventListener("pageadvanced", (aEvent) => {
+ if ("helpPanel" == wizardElem.currentPage.pageid)
+ {
+ closeHelp();
+ aEvent.preventDefault();
+ }
+ });
+
+ document.addEventListener("pageshow", (aEvent) => {
+ if (kWizardProgressPageID == wizardElem.currentPage.pageid)
+ onShowProgressPanel();
+ });
+
+ document.addEventListener("pagehide", (aEvent) => {
+ if (kWizardProgressPageID == wizardElem.currentPage.pageid)
+ resetProgressNavButtons();
+ });
+
+ document.addEventListener("extra2", (aEvent) => {
+ onCopyLog();
+ });
+ }
+ else
+ {
+ // Add network settings dialog event listeners.
+ document.addEventListener("dialogaccept", (aEvent) => {
+ if (!onNetworkSettingsFinish())
+ aEvent.preventDefault();
+ });
+
+ document.addEventListener("dialogcancel", (aEvent) => {
+ if (!onCancel())
+ aEvent.preventDefault();
+ });
+
+ document.addEventListener("dialogextra2", (aEvent) => {
+ onCopyLog();
+ });
}
}
@@ -239,6 +284,12 @@ function initDialog()
let haveWizard = (wizardElem != null);
if (haveWizard)
{
+ // Add wizardfinish event handler.
+ document.addEventListener("wizardfinish", (aEvent) => {
+ if (!onWizardFinish())
+ aEvent.preventDefault();
+ });
+
// Relabel the accept button to be "Connect"
let okBtn = document.documentElement.getButton("accept");
if (okBtn)
@@ -316,6 +367,11 @@ function initLocaleDialog()
{
initDialogCommon();
+ // Add wizardfinish event handler.
+ document.addEventListener("wizardfinish", (aEvent) => {
+ setLocale();
+ });
+
// Replace the finish button's label ("Done") with the next button's
// label ("Next" or "Continue").
let nextBtn = document.documentElement.getButton("next");
@@ -324,7 +380,8 @@ function initLocaleDialog()
doneBtn.label = nextBtn.label;
let { AddonManager } = Cu.import("resource://gre/modules/AddonManager.jsm");
- AddonManager.getAddonsByTypes(["locale"], function(aLangPackAddons)
+ let addonsPromise = AddonManager.getAddonsByTypes(["locale"]);
+ addonsPromise.then(aLangPackAddons =>
{
populateLocaleList(aLangPackAddons);
resizeDialogToFitContent();
@@ -421,13 +478,15 @@ function populateLocaleList(aLangPackAddons)
langInfo.splice(0, 0,
{ langCode: code, langName: name, isSelected: isSelected });
- // Populate the XUL listbox.
+ // Populate the XUL richlistbox.
let localeList = document.getElementById(kLocaleList);
for (let infoObj of langInfo)
{
- let listItem = document.createElement("listitem");
+ let listItem = document.createElement("richlistitem");
listItem.setAttribute("value", infoObj.langCode);
- listItem.setAttribute("label", infoObj.langName);
+ let label = document.createElement("label");
+ label.value = infoObj.langName;
+ listItem.appendChild(label);
localeList.appendChild(listItem);
if (infoObj.isSelected)
localeList.selectedItem = listItem;
@@ -807,7 +866,6 @@ function resetProgressNavButtons()
restoreButtonLabel("finish");
showOrHideButton("cancel", true, false);
- return true;
}
@@ -905,7 +963,7 @@ function updateBootstrapProgress(aStatusObj)
let meter = document.getElementById("progressMeter");
if (meter)
{
- meter.value = percentComplete;
+ meter.setAttribute("value", percentComplete);
showProgressMeterIfNoError();
}
@@ -1968,7 +2026,7 @@ function showProgressPanel()
let meter = document.getElementById("progressMeter");
if (meter)
{
- meter.value = 0;
+ meter.setAttribute("value", 0);
meter.style.visibility = "hidden";
}
@@ -2428,7 +2486,7 @@ function setElemValue(aID, aValue)
}
// fallthru
case "menulist":
- case "listbox":
+ case "richlistbox":
case "label":
elem.value = (val) ? val : "";
break;
@@ -2482,7 +2540,7 @@ function getElemValue(aID, aDefaultValue)
break;
case "textbox":
case "menulist":
- case "listbox":
+ case "richlistbox":
rv = elem.value;
break;
}
diff --git a/src/chrome/content/network-settings.xul b/src/chrome/content/network-settings.xul
index 2ba0741..6a8fac4 100644
--- a/src/chrome/content/network-settings.xul
+++ b/src/chrome/content/network-settings.xul
@@ -18,9 +18,6 @@
persist="screenX screenY"
buttons="accept,cancel,extra2"
buttonlabelextra2="&torsettings.copyLog;"
- ondialogaccept="return onNetworkSettingsFinish();"
- ondialogcancel="return onCancel();"
- ondialogextra2="onCopyLog();"
onload="initDialog();"
onunload="deinitDialog();">
diff --git a/src/chrome/skin/network-settings.css b/src/chrome/skin/network-settings.css
index 40ca0f0..9fed4f2 100644
--- a/src/chrome/skin/network-settings.css
+++ b/src/chrome/skin/network-settings.css
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, The Tor Project, Inc.
+ * Copyright (c) 2019, The Tor Project, Inc.
* See LICENSE for licensing information.
*
* vim: set sw=2 sts=2 ts=8 et syntax=css:
@@ -47,8 +47,14 @@ wizard label {
margin: 0px;
}
-wizard radiogroup {
- margin: 5px 0px 8px 25px;
+.rightAlign {
+ text-align: right;
+}
+
+groupbox {
+ margin-left: 16px;
+ padding: 8px;
+ border: 1px solid GrayText;
}
.tbb-header groupbox {
@@ -57,7 +63,7 @@ wizard radiogroup {
margin-bottom: 0px;
}
-.firstResponses label {
+.firstResponses > label {
text-align: center;
margin-top: 1.2em;
}
1
0

[tor-browser/tor-browser-60.8.0esr-9.0-1] Bug 31344: Actually register SecurityLevelPreference's 'unload' callback in privacy.js
by gk@torproject.org 07 Aug '19
by gk@torproject.org 07 Aug '19
07 Aug '19
commit d48c3fa6ace654296c78210e370838bcaaf4078c
Author: Richard Pospesel <richard(a)torproject.org>
Date: Mon Aug 5 15:44:15 2019 -0700
Bug 31344: Actually register SecurityLevelPreference's 'unload' callback in privacy.js
---
browser/components/preferences/in-content/privacy.js | 1 +
1 file changed, 1 insertion(+)
diff --git a/browser/components/preferences/in-content/privacy.js b/browser/components/preferences/in-content/privacy.js
index d2229d136261..3997f22d63ad 100644
--- a/browser/components/preferences/in-content/privacy.js
+++ b/browser/components/preferences/in-content/privacy.js
@@ -161,6 +161,7 @@ var gPrivacyPane = {
window.removeEventListener("unload", unload);
SecurityLevelPreferences.uninit();
};
+ window.addEventListener("unload", unload);
},
/**
1
0

[tor-browser-build/master] Bug 30736: Install yasm from wheezy-backports
by gk@torproject.org 07 Aug '19
by gk@torproject.org 07 Aug '19
07 Aug '19
commit 0a8ab5b289753683cf9a5bfae3bd6e24b463eeb1
Author: Nicolas Vigier <boklm(a)torproject.org>
Date: Fri Aug 2 06:01:54 2019 +0200
Bug 30736: Install yasm from wheezy-backports
---
projects/firefox/config | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/projects/firefox/config b/projects/firefox/config
index 0b340f5..14be6ef 100644
--- a/projects/firefox/config
+++ b/projects/firefox/config
@@ -58,6 +58,15 @@ targets:
arch_deps:
- openjdk-8-jdk
+ linux:
+ var:
+ post_pkginst: |
+ # Firefox ESR68 needs Yasm >= 1.2.0 which Debian Wheezy ships in backports.
+ echo 'deb http://archive.debian.org/debian/ wheezy-backports main' >> /etc/apt/sources.list
+ export DEBIAN_FRONTEND=noninteractive
+ apt-get update
+ apt-get install -t wheezy-backports -y yasm
+
linux-x86_64:
var:
martools_filename: mar-tools-linux64.zip
1
0

02 Aug '19
commit 2a34a082c587eb21e5880406a5fd6ac8c8425234
Author: Georg Koppen <gk(a)torproject.org>
Date: Fri May 31 16:50:24 2019 +0000
Bug 30701: Adding node project
---
projects/node/build | 24 ++++++++++++++++++++++++
projects/node/config | 17 +++++++++++++++++
2 files changed, 41 insertions(+)
diff --git a/projects/node/build b/projects/node/build
new file mode 100644
index 0000000..0e6ca04
--- /dev/null
+++ b/projects/node/build
@@ -0,0 +1,24 @@
+#!/bin/bash
+[% c("var/set_default_env") -%]
+[% 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
+ tar -C /var/tmp/dist -xf $rootdir/[% c('input_files_by_name/binutils') %]
+ export PATH="/var/tmp/dist/binutils/bin:$PATH"
+[% END -%]
+distdir=/var/tmp/dist/[% project %]
+tar -xf [% project %]-[% c('version') %].tar.xz
+cd [% project %]-[% c('version') %]
+
+./configure --prefix=$distdir
+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/node/config b/projects/node/config
new file mode 100644
index 0000000..e023380
--- /dev/null
+++ b/projects/node/config
@@ -0,0 +1,17 @@
+# vim: filetype=yaml sw=2
+version: v10.16.0
+filename: '[% project %]-[% c("version") %]-[% c("var/build_id") %].tar.gz'
+var:
+ container:
+ use_container: 1
+
+input_files:
+ - project: container-image
+ - project: binutils
+ name: binutils
+ enable: '[% c("var/linux") %]'
+ - project: '[% c("var/compiler") %]'
+ name: '[% c("var/compiler") %]'
+ enable: '[% c("var/linux") %]'
+ - URL: 'https://nodejs.org/download/release/[% c("version") %]/node-[% c("version") %].tar.xz'
+ sha256sum: 18e37f891d10ea7fbc8f6410c444c2b1d9cc3cbbb1d35aa9c41f761816956608
1
0

02 Aug '19
commit 460d5ef80d2bb7ebf808574d21ec7fe43dd9dd01
Author: Georg Koppen <gk(a)torproject.org>
Date: Sun Jun 2 20:33:22 2019 +0000
Bug 30734: Add nasm project
---
projects/nasm/build | 24 ++++++++++++++++++++++++
projects/nasm/config | 17 +++++++++++++++++
2 files changed, 41 insertions(+)
diff --git a/projects/nasm/build b/projects/nasm/build
new file mode 100644
index 0000000..0e6ca04
--- /dev/null
+++ b/projects/nasm/build
@@ -0,0 +1,24 @@
+#!/bin/bash
+[% c("var/set_default_env") -%]
+[% 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
+ tar -C /var/tmp/dist -xf $rootdir/[% c('input_files_by_name/binutils') %]
+ export PATH="/var/tmp/dist/binutils/bin:$PATH"
+[% END -%]
+distdir=/var/tmp/dist/[% project %]
+tar -xf [% project %]-[% c('version') %].tar.xz
+cd [% project %]-[% c('version') %]
+
+./configure --prefix=$distdir
+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/nasm/config b/projects/nasm/config
new file mode 100644
index 0000000..ff82004
--- /dev/null
+++ b/projects/nasm/config
@@ -0,0 +1,17 @@
+# vim: filetype=yaml sw=2
+version: 2.14.02
+filename: '[% project %]-[% c("version") %]-[% c("var/build_id") %].tar.gz'
+var:
+ container:
+ use_container: 1
+
+input_files:
+ - project: container-image
+ - project: binutils
+ name: binutils
+ enable: '[% c("var/linux") %]'
+ - project: '[% c("var/compiler") %]'
+ name: '[% c("var/compiler") %]'
+ enable: '[% c("var/linux") %]'
+ - URL: 'https://www.nasm.us/pub/nasm/releasebuilds/[% c("version") %]/nasm-[% c("version") %].tar.xz'
+ sha256sum: e24ade3e928f7253aa8c14aa44726d1edf3f98643f87c9d72ec1df44b26be8f5
1
0

[tor-browser/tor-browser-60.8.0esr-9.0-1] Bug 31251: Security Level button UI polish
by gk@torproject.org 01 Aug '19
by gk@torproject.org 01 Aug '19
01 Aug '19
commit 0bed1d181d0839f058e311c01dbdb263a96270fd
Author: Richard Pospesel <richard(a)torproject.org>
Date: Tue Jul 30 11:32:31 2019 -0700
Bug 31251: Security Level button UI polish
Changed the anchor to toolbarbutton's anonymous child toolbarbutton-icon
xul:image element so that the security level panel has the same vertical
alignment as other built-in toolbar buttons. Also needed to add the
badged-button class to our toolbar button for this to align properly.
Now setting and deleting the "open" attribute from the toolbarbutton
element so that it maintains the "pushed" style while the security level
panel is open.
Changed the toolbarbutton's oncommand callback to onmousedown to match
the behaviour of firefox's other toolbarbuttons. Security level panel
now opens on mouse press rather than on mouse press and release.
Slightly re-arranged the ordering of the SecurityLevelPanel object's
method definitions so that callbacks appear in a contiguous block to
better match the other objects defined in securityLevel.js
Removed unnecessary async modifier from
SecurityLevelPanel.openAdvancedSecuritySettings().
Fixed a few typos, improved comments, and removed trailing whitespace.
---
.../securitylevel/content/securityLevel.js | 92 ++++++++++++++++------
.../content/securityLevelButton.inc.xul | 4 +-
.../content/securityLevelPanel.inc.xul | 5 +-
3 files changed, 73 insertions(+), 28 deletions(-)
diff --git a/browser/components/securitylevel/content/securityLevel.js b/browser/components/securitylevel/content/securityLevel.js
index e37f2d49175b..25f6423bc6d3 100644
--- a/browser/components/securitylevel/content/securityLevel.js
+++ b/browser/components/securitylevel/content/securityLevel.js
@@ -124,7 +124,7 @@ const SecurityLevelPrefs = {
set securityCustom(val) {
Services.prefs.setBoolPref(this.security_custom_pref, val);
},
-};
+}; /* Security Level Prefs */
/*
Security Level Button Code
@@ -134,6 +134,8 @@ const SecurityLevelPrefs = {
const SecurityLevelButton = {
_securityPrefsBranch : null,
+ _button : null,
+ _anchor : null,
_populateXUL : function(securityLevelButton) {
if (securityLevelButton != null) {
@@ -164,11 +166,38 @@ const SecurityLevelButton = {
}
},
+ get button() {
+ if (this._button) {
+ return this._button;
+ }
+
+ let button = document.getElementById("security-level-button");
+ if (!button) {
+ return null;
+ }
+
+ return this._button = button;
+ },
+
+ get anchor() {
+ if (this._anchor) {
+ return this._anchor;
+ }
+
+ let anchor = document.getAnonymousElementByAttribute(this.button, "class",
+ "toolbarbutton-icon");
+ if (!anchor) {
+ return null;
+ }
+
+ anchor.setAttribute("consumeanchor", SecurityLevelButton.button.id);
+ return this._anchor = anchor;
+ },
+
init : function() {
// set the initial class based off of the current pref
- let button = document.getElementById("security-level-button");
- this._populateXUL(button);
- this._configUIFromPrefs(button);
+ this._populateXUL(this.button);
+ this._configUIFromPrefs(this.button);
this._securityPrefsBranch = Services.prefs.getBranch("extensions.torbutton.");
this._securityPrefsBranch.addObserver("", this, false);
@@ -191,13 +220,13 @@ const SecurityLevelButton = {
switch(topic) {
case "nsPref:changed":
if (data == "security_slider") {
- this._configUIFromPrefs(document.getElementById("security-level-button"));
+ this._configUIFromPrefs(this.button);
}
break;
}
},
- // callbacks for entering the 'Customize Firefox' screen to set icon
+ // callback for entering the 'Customize Firefox' screen to set icon
onCustomizeStart : function(window) {
let navigatorToolbox = document.getElementById("navigator-toolbox");
let button = navigatorToolbox.palette.querySelector("#security-level-button");
@@ -210,14 +239,20 @@ const SecurityLevelButton = {
if (aNode.id == "security-level-button" && !aWasRemoval) {
this._populateXUL(aNode);
this._configUIFromPrefs(aNode);
+ // clear out our cached elements as they seem to be recreated when the UI is customized
+ delete this._button;
+ delete this._anchor;
}
},
// when toolbar button is pressed
- onCommand : function(anchor, event) {
- SecurityLevelPanel.show(anchor);
+ onCommand : function(event) {
+ // we need to set this attribute for the button to be shaded correctly to look like it is pressed
+ // while the security level panel is open
+ this.button.setAttribute("open", "true");
+ SecurityLevelPanel.show(event);
},
-};
+}; /* Security Level Button */
/*
Security Level Panel Code
@@ -305,19 +340,16 @@ const SecurityLevelPanel = {
this._securityPrefsBranch = null;
},
- show : function(anchor) {
+ show : function() {
// we have to defer this until after the browser has finished init'ing before
// we can populate the panel
if (!this._populated) {
this._populateXUL();
}
- // save off anchor in case we want to show from our own code
- this._anchor = anchor;
-
let panel = document.getElementById("securityLevel-panel");
panel.hidden = false;
- PanelMultiView.openPopup(panel, anchor, "bottomcenter topright",
+ PanelMultiView.openPopup(panel, SecurityLevelButton.anchor, "bottomcenter topright",
0, 0, false, null).catch(Cu.reportError);
},
@@ -326,7 +358,19 @@ const SecurityLevelPanel = {
PanelMultiView.hidePopup(panel);
},
- // when prefs change
+ restoreDefaults : function() {
+ SecurityLevelPrefs.securityCustom = false;
+ // hide and reshow so that layout re-renders properly
+ this.hide();
+ this.show(this._anchor);
+ },
+
+ openAdvancedSecuritySettings : function() {
+ openPreferences("privacy-securitylevel");
+ this.hide();
+ },
+
+ // callback when prefs change
observe : function(subject, topic, data) {
switch(topic) {
case "nsPref:changed":
@@ -337,18 +381,16 @@ const SecurityLevelPanel = {
}
},
- restoreDefaults : function() {
- SecurityLevelPrefs.securityCustom = false;
- // hide and reshow so that layout re-renders properly
- this.hide();
- this.show(this._anchor);
+ // callback when the panel is displayed
+ onPopupShown : function(event) {
+ SecurityLevelButton.button.setAttribute("open", "true");
},
- openAdvancedSecuritySettings : async function() {
- openPreferences("privacy-securitylevel");
- this.hide();
+ // callback when the panel is hidden
+ onPopupHidden : function(event) {
+ SecurityLevelButton.button.removeAttribute("open");
}
-};
+}; /* Security Level Panel */
/*
Security Level Preferences Code
@@ -507,7 +549,7 @@ const SecurityLevelPreferences =
restoreDefaults : function() {
SecurityLevelPrefs.securityCustom = false;
},
-};
+}; /* Security Level Prefereces */
Object.defineProperty(this, "SecurityLevelButton", {
value: SecurityLevelButton,
diff --git a/browser/components/securitylevel/content/securityLevelButton.inc.xul b/browser/components/securitylevel/content/securityLevelButton.inc.xul
index 4ad26f4142bd..579a55f46d4a 100644
--- a/browser/components/securitylevel/content/securityLevelButton.inc.xul
+++ b/browser/components/securitylevel/content/securityLevelButton.inc.xul
@@ -1,5 +1,5 @@
-<toolbarbutton id="security-level-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
+<toolbarbutton id="security-level-button" class="toolbarbutton-1 chromeclass-toolbar-additional badged-button"
removable="true"
- oncommand="SecurityLevelButton.onCommand(this, event);"
+ onmousedown="SecurityLevelButton.onCommand();"
closemenu="none"
cui-areatype="toolbar"/>
diff --git a/browser/components/securitylevel/content/securityLevelPanel.inc.xul b/browser/components/securitylevel/content/securityLevelPanel.inc.xul
index 532e8dd98b32..6a00e811a6ac 100644
--- a/browser/components/securitylevel/content/securityLevelPanel.inc.xul
+++ b/browser/components/securitylevel/content/securityLevelPanel.inc.xul
@@ -3,7 +3,10 @@
type="arrow"
orient="vertical"
level="top"
- hidden="true">
+ hidden="true"
+ onpopupshown="SecurityLevelPanel.onPopupShown(event);"
+ onpopuphidden="SecurityLevelPanel.onPopupHidden(event);"
+ >
<panelmultiview mainViewId="securityLevel-panelview">
<panelview id="securityLevel-panelview" descriptionheightworkaround="true">
<vbox class="panel-subview-body">
1
0

[tor-browser-build/master] Merge remote-tracking branch 'boklm/bug_30585_v2'
by gk@torproject.org 31 Jul '19
by gk@torproject.org 31 Jul '19
31 Jul '19
commit 7b6444dd34d7a9e32d619c194e078464529fd5c1
Merge: 525e93a 4c2b3a9
Author: Georg Koppen <gk(a)torproject.org>
Date: Wed Jul 31 09:27:04 2019 +0000
Merge remote-tracking branch 'boklm/bug_30585_v2'
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(+)
1
0

[tor-browser-build/master] Bug 30585: Provide clang 8 for Tor Browser 9
by gk@torproject.org 31 Jul '19
by gk@torproject.org 31 Jul '19
31 Jul '19
commit 4c2b3a98e04605ce7fcbd1c2c7c4864c6a5125a2
Author: Georg Koppen <gk(a)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(a)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(a)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(a)martin.st>
+Date: Wed, 23 Jan 2019 11:54:51 +0000
+Subject: [PATCH] [llvm-objcopy] [COFF] Fix handling of aux symbols for big
+ objects
+
+The aux symbols were stored in an opaque std::vector<uint8_t>,
+with contents interpreted according to the rest of the symbol.
+
+All aux symbol types but one fit in 18 bytes (sizeof(coff_symbol16)),
+and if written to a bigobj, two extra padding bytes are written (as
+sizeof(coff_symbol32) is 20). In the storage agnostic intermediate
+representation, store the aux symbols as a series of coff_symbol16
+sized opaque blobs. (In practice, all such aux symbols only consist
+of one aux symbol, so this is more flexible than what reality needs.)
+
+The special case is the file aux symbols, which are written in
+potentially more than one aux symbol slot, without any padding,
+as one single long string. This can't be stored in the same opaque
+vector of fixed sized aux symbol entries. The file aux symbols will
+occupy a different number of aux symbol slots depending on the type
+of output object file. As nothing in the intermediate process needs
+to have accurate raw symbol indices, updating that is moved into the
+writer class.
+
+Differential Revision: https://reviews.llvm.org/D57009
+
+git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@351947 91177308-0d34-0410-b5e6-96231b3b80d8
+---
+ .../llvm-objcopy/COFF/Inputs/bigobj.o.gz | Bin 0 -> 7841 bytes
+ test/tools/llvm-objcopy/COFF/bigobj.test | 35 +++++++++++++
+ .../llvm-objcopy/ELF/auto-remove-shndx.test | 2 +-
+ .../tools/llvm-objcopy/ELF/many-sections.test | 2 +-
+ test/tools/llvm-objcopy/ELF/remove-shndx.test | 2 +-
+ .../tools/llvm-objcopy/ELF/strict-no-add.test | 2 +-
+ .../llvm-objcopy/{ELF => }/Inputs/ungzip.py | 0
+ tools/llvm-objcopy/COFF/COFFObjcopy.cpp | 6 +--
+ tools/llvm-objcopy/COFF/Object.cpp | 6 +--
+ tools/llvm-objcopy/COFF/Object.h | 18 ++++++-
+ tools/llvm-objcopy/COFF/Reader.cpp | 21 ++++++--
+ tools/llvm-objcopy/COFF/Writer.cpp | 49 +++++++++++++-----
+ tools/llvm-objcopy/COFF/Writer.h | 2 +-
+ 13 files changed, 115 insertions(+), 30 deletions(-)
+ create mode 100644 test/tools/llvm-objcopy/COFF/Inputs/bigobj.o.gz
+ create mode 100644 test/tools/llvm-objcopy/COFF/bigobj.test
+ rename test/tools/llvm-objcopy/{ELF => }/Inputs/ungzip.py (100%)
+
+diff --git a/llvm/test/tools/llvm-objcopy/COFF/Inputs/bigobj.o.gz b/llvm/test/tools/llvm-objcopy/COFF/Inputs/bigobj.o.gz
+new file mode 100644
+index 0000000000000000000000000000000000000000..6435f4785ff76e0c6bca12f3e57bc6ad8888bece
+GIT binary patch
+literal 7841
+zcmb2|=3r3v^@w3&etUMmo^zoH`-kGKM_vfJsF<z%6+Sz#g6qq)pf0Hj#_r`4B7DML
+zW(h1l`+!x)t@&W-R@I~lyKmU3Ti&1Z=iKur;uBMy1MR!_ywlsouYY&-*4H1mU!Qw=
+z`RpIDkw;!V4(WOF_)B3`(Vt|~S>?L-b)Wx@^wig`HIMAw|N8V<v65oeyETs611{)_
+zm27RwTe)ENN|7SLgM~83N6}~qjE2By2#kinXb6mkz-S1JhQMeDjE2By2#kinXb6mk
+zz-S1JhQMeDjE2By2#kinXb6mkz-S1JhQMeDjE2By2#kgRokHNw|D97mKRo|%+Z6Ym
+z*X{Ku$4#4*Vqm}gyYR^b^Sc?_E*<<cFE#Q=*rt6OBmJeLZ=aoe_u9R>-w!^l5biDe
+p{d@nvw*mU6<NG83=jxn4_wt_G?yUy#YeOF~KhH^=cj<;Y0{~9Br>p<~
+
+literal 0
+HcmV?d00001
+
+diff --git a/llvm/test/tools/llvm-objcopy/COFF/bigobj.test b/llvm/test/tools/llvm-objcopy/COFF/bigobj.test
+new file mode 100644
+index 00000000000..17968f12b8a
+--- /dev/null
++++ b/llvm/test/tools/llvm-objcopy/COFF/bigobj.test
+@@ -0,0 +1,35 @@
++RUN: %python %p/../Inputs/ungzip.py %p/Inputs/bigobj.o.gz > %t.in.o
++
++RUN: llvm-objdump -t %t.in.o | FileCheck %s --check-prefixes=SYMBOLS,SYMBOLS-BIG,SYMBOLS-ORIG
++
++# Do a plain copy, to check that section numbers in symbols referring
++# to sections outside of the small object format are handled correctly.
++RUN: llvm-objcopy -R '.text$4' %t.in.o %t.small.o
++RUN: llvm-objdump -t %t.in.o | FileCheck %s --check-prefixes=SYMBOLS,SYMBOLS-BIG,SYMBOLS-ORIG
++
++# Remove a section, making the section count fit into a small object.
++RUN: llvm-objcopy -R '.text$4' %t.in.o %t.small.o
++RUN: llvm-objdump -t %t.small.o | FileCheck %s --check-prefixes=SYMBOLS,SYMBOLS-SMALL,SYMBOLS-REMOVED-SMALL
++
++# Add a .gnu_debuglink section, forcing the object back to big format.
++RUN: llvm-objcopy --add-gnu-debuglink=%t.in.o %t.small.o %t.big.o
++ llvm-objdump -t %t.big.o | FileCheck %s --check-prefixes=SYMBOLS,SYMBOLS-BIG,SYMBOLS-REMOVED-BIG
++
++# In big object format, the .file symbol occupies one symbol table entry for
++# the auxillary data, but needs two entries in the small format, forcing the
++# raw symbol indices of later symbols to change.
++SYMBOLS: SYMBOL TABLE:
++SYMBOLS-NEXT: [ 0]{{.*}} (nx 1) {{.*}} .text
++SYMBOLS-NEXT: AUX scnlen
++SYMBOLS-SMALL-NEXT: [ 2]{{.*}} (nx 2) {{.*}} .file
++SYMBOLS-BIG-NEXT: [ 2]{{.*}} (nx 1) {{.*}} .file
++SYMBOLS-NEXT: AUX abcdefghijklmnopqrs
++SYMBOLS-SMALL-NEXT: [ 5]{{.*}} (nx 0) {{.*}} foo
++SYMBOLS-BIG-NEXT: [ 4]{{.*}} (nx 0) {{.*}} foo
++
++# Check that the section numbers outside of signed 16 bit int range
++# are represented properly. After removing one section, the section
++# numbers decrease.
++SYMBOLS-ORIG: [ 5](sec 65280){{.*}} symbol65280
++SYMBOLS-REMOVED-SMALL: [ 6](sec 65279){{.*}} symbol65280
++SYMBOLS-REMOVED-BIG: [ 5](sec 65279){{.*}} symbol65280
+diff --git a/llvm/test/tools/llvm-objcopy/ELF/auto-remove-shndx.test b/llvm/test/tools/llvm-objcopy/ELF/auto-remove-shndx.test
+index 5a23493fa94..8e6c788bf48 100644
+--- a/llvm/test/tools/llvm-objcopy/ELF/auto-remove-shndx.test
++++ b/llvm/test/tools/llvm-objcopy/ELF/auto-remove-shndx.test
+@@ -1,4 +1,4 @@
+-# RUN: %python %p/Inputs/ungzip.py %p/Inputs/many-sections.o.gz > %t
++# RUN: %python %p/../Inputs/ungzip.py %p/Inputs/many-sections.o.gz > %t
+ # RUN: llvm-objcopy -R .text -R s0 -R s1 -R s2 -R s3 -R s4 -R s5 -R s6 %t %t2
+ # RUN: llvm-readobj --sections %t2 | FileCheck --check-prefix=SECS %s
+
+diff --git a/llvm/test/tools/llvm-objcopy/ELF/many-sections.test b/llvm/test/tools/llvm-objcopy/ELF/many-sections.test
+index 57239f32e4a..1dd41cfb10c 100644
+--- a/llvm/test/tools/llvm-objcopy/ELF/many-sections.test
++++ b/llvm/test/tools/llvm-objcopy/ELF/many-sections.test
+@@ -1,4 +1,4 @@
+-RUN: %python %p/Inputs/ungzip.py %p/Inputs/many-sections.o.gz > %t
++RUN: %python %p/../Inputs/ungzip.py %p/Inputs/many-sections.o.gz > %t
+ RUN: llvm-objcopy %t %t2
+ RUN: llvm-readobj --file-headers %t2 | FileCheck --check-prefix=EHDR %s
+ RUN: llvm-readobj --sections %t2 | FileCheck --check-prefix=SECS %s
+diff --git a/llvm/test/tools/llvm-objcopy/ELF/remove-shndx.test b/llvm/test/tools/llvm-objcopy/ELF/remove-shndx.test
+index 6cc3a1a291f..53ca8e7f220 100644
+--- a/llvm/test/tools/llvm-objcopy/ELF/remove-shndx.test
++++ b/llvm/test/tools/llvm-objcopy/ELF/remove-shndx.test
+@@ -1,6 +1,6 @@
+ # This test checks to see that a .symtab_shndx section is added to any binary
+ # that needs it, even if the original was removed.
+-RUN: %python %p/Inputs/ungzip.py %p/Inputs/many-sections.o.gz > %t
++RUN: %python %p/../Inputs/ungzip.py %p/Inputs/many-sections.o.gz > %t
+ RUN: llvm-objcopy -R .symtab_shndx %t %t2
+ RUN: llvm-readobj --sections %t2 | FileCheck %s
+
+diff --git a/llvm/test/tools/llvm-objcopy/ELF/strict-no-add.test b/llvm/test/tools/llvm-objcopy/ELF/strict-no-add.test
+index 4f24df31bf9..348ab7c4fbd 100644
+--- a/llvm/test/tools/llvm-objcopy/ELF/strict-no-add.test
++++ b/llvm/test/tools/llvm-objcopy/ELF/strict-no-add.test
+@@ -1,7 +1,7 @@
+ # This test makes sure that sections added at the end that don't have symbols
+ # defined in them don't trigger the creation of a large index table.
+
+-RUN: %python %p/Inputs/ungzip.py %p/Inputs/many-sections.o.gz > %t.0
++RUN: %python %p/../Inputs/ungzip.py %p/Inputs/many-sections.o.gz > %t.0
+ RUN: cat %p/Inputs/alloc-symtab.o > %t
+ RUN: llvm-objcopy -R .text -R s0 -R s1 -R s2 -R s3 -R s4 -R s5 -R s6 %t.0 %t2
+ RUN: llvm-objcopy --add-section=.s0=%t --add-section=.s1=%t --add-section=.s2=%t %t2 %t2
+diff --git a/llvm/test/tools/llvm-objcopy/ELF/Inputs/ungzip.py b/llvm/test/tools/llvm-objcopy/Inputs/ungzip.py
+similarity index 100%
+rename from 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(a)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(a)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(a)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(a)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(a)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(a)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(a)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(a)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(a)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
+
1
0
commit 525e93a130757ab4df445888ecc211bace1122eb
Author: Georg Koppen <gk(a)torproject.org>
Date: Tue Jul 30 20:38:50 2019 +0000
Release prep for 9.0a5
We want to better test aarch64 support on Google Play before the 64bit
requirement on Aug 1 is getting enforced.
---
projects/firefox/config | 2 +-
projects/tor-browser/Bundle-Data/Docs/ChangeLog.txt | 4 ++++
rbm.conf | 4 ++--
3 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/projects/firefox/config b/projects/firefox/config
index 9565b8e..0b340f5 100644
--- a/projects/firefox/config
+++ b/projects/firefox/config
@@ -1,7 +1,7 @@
# vim: filetype=yaml sw=2
version: '[% c("abbrev") %]'
filename: 'firefox-[% c("version") %]-[% c("var/osname") %]-[% c("var/build_id") %]'
-git_hash: 'tor-browser-[% c("var/firefox_version") %]-[% c("var/torbrowser_branch") %]-1-build1'
+git_hash: 'tor-browser-[% c("var/firefox_version") %]-[% c("var/torbrowser_branch") %]-1-build2'
tag_gpg_id: 1
git_url: https://git.torproject.org/tor-browser.git
git_submodule: 1
diff --git a/projects/tor-browser/Bundle-Data/Docs/ChangeLog.txt b/projects/tor-browser/Bundle-Data/Docs/ChangeLog.txt
index ffab828..594225a 100644
--- a/projects/tor-browser/Bundle-Data/Docs/ChangeLog.txt
+++ b/projects/tor-browser/Bundle-Data/Docs/ChangeLog.txt
@@ -1,3 +1,7 @@
+Tor Browser 9.0a5 -- July 31 2019
+ * Android
+ * Bug 31260: Backport bug 1477259 for aarch64 support on Google Play
+
Tor Browser 9.0a4 -- July 9 2019
* All platforms
* Update Firefox to 60.8.0esr
diff --git a/rbm.conf b/rbm.conf
index 4f6e943..76695f3 100644
--- a/rbm.conf
+++ b/rbm.conf
@@ -24,8 +24,8 @@ buildconf:
git_signtag_opt: '-s'
var:
- torbrowser_version: '9.0a4'
- torbrowser_build: 'build2'
+ torbrowser_version: '9.0a5'
+ torbrowser_build: 'build1'
torbrowser_incremental_from:
- 9.0a3
project_name: tor-browser
1
0

[tor-browser/tor-browser-60.8.0esr-8.5-1] Bug 1477259 - Use separate version codes for 64-bit builds; r=nalexander
by gk@torproject.org 30 Jul '19
by gk@torproject.org 30 Jul '19
30 Jul '19
commit 3111f2ee9a389db8d4c4f025b34314f8fe42d865
Author: Jim Chen <nchen(a)mozilla.com>
Date: Thu Aug 30 21:51:18 2018 +0000
Bug 1477259 - Use separate version codes for 64-bit builds; r=nalexander
Use the unused 'p' bit in the version code to denote 64-bit builds, so
we have different version codes for 64-bit builds on aarch64 and x86-64.
Differential Revision: https://phabricator.services.mozilla.com/D4260
--HG--
extra : moz-landing-system : lando
---
python/mozbuild/mozbuild/android_version_code.py | 53 ++++++++++++------------
1 file changed, 27 insertions(+), 26 deletions(-)
diff --git a/python/mozbuild/mozbuild/android_version_code.py b/python/mozbuild/mozbuild/android_version_code.py
index 5e786b2358c0..92392d563c42 100644
--- a/python/mozbuild/mozbuild/android_version_code.py
+++ b/python/mozbuild/mozbuild/android_version_code.py
@@ -49,26 +49,24 @@ def android_version_code_v1(buildid, cpu_arch=None, min_sdk=0, max_sdk=0):
The bits labelled 'x', 'p', and 'g' are feature flags.
- The bit labelled 'x' is 1 if the build is for an x86 or ARM64 architecture,
- and 0 otherwise, which means the build is for a (32-bit) ARM architecture.
+ The bit labelled 'x' is 1 if the build is for an x86 or x86-64 architecture,
+ and 0 otherwise, which means the build is for an ARM or ARM64 architecture.
(Fennec no longer supports ARMv6, so ARM is equivalent to ARMv7.
ARM64 is also known as AArch64; it is logically ARMv8.)
- For the same release, x86 and ARM64 builds have higher version codes and
+ For the same release, x86 and x86_64 builds have higher version codes and
take precedence over ARM builds, so that they are preferred over ARM on
devices that have ARM emulation.
- The bit labelled 'p' is a placeholder that is always 0 (for now).
+ The bit labelled 'p' is 1 if the build is for a 64-bit architecture (x86-64
+ or ARM64), and 0 otherwise, which means the build is for a 32-bit
+ architecture (x86 or ARM). 64-bit builds have higher version codes so
+ they take precedence over 32-bit builds on devices that support 64-bit.
- Firefox no longer supports API 14 or earlier.
-
- This version code computation allows for a split on API levels that allowed
- us to ship builds specifically for Gingerbread (API 9-10); we preserve
- that functionality for sanity's sake, and to allow us to reintroduce a
- split in the future.
-
- At present, the bit labelled 'g' is 1 if the build is an ARM build
- targeting API 16+, which will always be the case.
+ The bit labelled 'g' is 1 if the build targets a recent API level, which
+ is currently always the case, because Firefox no longer ships releases that
+ are split by API levels. However, we may reintroduce a split in the future,
+ in which case the release that targets an older API level will
We throw an explanatory exception when we are within one calendar year of
running out of build events. This gives lots of time to update the version
@@ -113,24 +111,27 @@ def android_version_code_v1(buildid, cpu_arch=None, min_sdk=0, max_sdk=0):
# for architecture and APK splits.
version |= base << 3
- # None is interpreted as arm.
- if not cpu_arch or cpu_arch == 'armeabi-v7a':
- # 0 is interpreted as SDK 9.
- if not min_sdk or min_sdk == 9:
- pass
- # This used to compare to 11. The 16+ APK directly supersedes 11+, so
- # we reuse this check.
- elif min_sdk == 16:
- version |= 1 << 0
- else:
- raise ValueError("Don't know how to compute android:versionCode "
- "for CPU arch %s and min SDK %s" % (cpu_arch, min_sdk))
- elif cpu_arch in ['x86', 'arm64-v8a']:
+ # 'x' bit is 1 for x86/x86-64 architectures (`None` is interpreted as ARM).
+ if cpu_arch in ['x86', 'x86_64']:
version |= 1 << 2
+ elif not cpu_arch or cpu_arch in ['armeabi-v7a', 'arm64-v8a']:
+ pass
else:
raise ValueError("Don't know how to compute android:versionCode "
"for CPU arch %s" % cpu_arch)
+ # 'p' bit is 1 for 64-bit architectures.
+ if cpu_arch in ['arm64-v8a', 'x86_64']:
+ version |= 1 << 1
+ elif cpu_arch in ['armeabi-v7a', 'x86']:
+ pass
+ else:
+ raise ValueError("Don't know how to compute android:versionCode "
+ "for CPU arch %s" % cpu_arch)
+
+ # 'g' bit is currently always 1, but may depend on `min_sdk` in the future.
+ version |= 1 << 0
+
return version
def android_version_code(buildid, *args, **kwargs):
1
0