Index: third_party/binutils/icf-align.patch |
diff --git a/third_party/binutils/icf-align.patch b/third_party/binutils/icf-align.patch |
new file mode 100644 |
index 0000000000000000000000000000000000000000..719f019024cff55bde17be2a8c2742e6d6859c73 |
--- /dev/null |
+++ b/third_party/binutils/icf-align.patch |
@@ -0,0 +1,126 @@ |
+commit ac423761af22f7858a1413cda5df3e1d5e88d4e4 |
+Author: Gergely Nagy <ngg@tresorit.com> |
+Date: Fri Oct 21 11:08:20 2016 -0700 |
+ |
+ Fix PR 17704. |
+ |
+ This fix keeps the section with the highest alignment when folding sections with ICF. |
+ |
+ PR gold/17704 |
+ * icf.cc (match_sections): Add new parameter section_addraligns. |
+ Check section alignment and keep the section with the strictest |
+ alignment. |
+ (find_identical_sections): New local variable section_addraligns. |
+ Store each section's alignment. |
+ * testsuite/pr17704a_test.s: New file. |
+ * testsuite/Makefile.am (pr17704a_test): New test. |
+ * testsuite/Makefile.in: Regenerate. |
+ |
+diff --git a/gold/icf.cc b/gold/icf.cc |
+index dce0b8b3e2..c09c746ae1 100644 |
+--- a/gold/icf.cc |
++++ b/gold/icf.cc |
+@@ -590,6 +590,7 @@ match_sections(unsigned int iteration_num, |
+ std::vector<unsigned int>* num_tracked_relocs, |
+ std::vector<unsigned int>* kept_section_id, |
+ const std::vector<Section_id>& id_section, |
++ const std::vector<uint64_t>& section_addraligns, |
+ std::vector<bool>* is_secn_or_group_unique, |
+ std::vector<std::string>* section_contents) |
+ { |
+@@ -630,13 +631,7 @@ match_sections(unsigned int iteration_num, |
+ { |
+ if ((*kept_section_id)[i] != i) |
+ { |
+- // This section is already folded into something. See |
+- // if it should point to a different kept section. |
+- unsigned int kept_section = (*kept_section_id)[i]; |
+- if (kept_section != (*kept_section_id)[kept_section]) |
+- { |
+- (*kept_section_id)[i] = (*kept_section_id)[kept_section]; |
+- } |
++ // This section is already folded into something. |
+ continue; |
+ } |
+ this_secn_contents = get_section_contents(false, secn, i, NULL, |
+@@ -671,7 +666,25 @@ match_sections(unsigned int iteration_num, |
+ this_secn_contents.c_str(), |
+ this_secn_contents.length()) != 0) |
+ continue; |
+- (*kept_section_id)[i] = kept_section; |
++ |
++ // Check section alignment here. |
++ // The section with the larger alignment requirement |
++ // should be kept. We assume alignment can only be |
++ // zero or postive integral powers of two. |
++ uint64_t align_i = section_addraligns[i]; |
++ uint64_t align_kept = section_addraligns[kept_section]; |
++ if (align_i <= align_kept) |
++ { |
++ (*kept_section_id)[i] = kept_section; |
++ } |
++ else |
++ { |
++ (*kept_section_id)[kept_section] = i; |
++ it->second = i; |
++ full_section_contents[kept_section].swap( |
++ full_section_contents[i]); |
++ } |
++ |
+ converged = false; |
+ break; |
+ } |
+@@ -688,6 +701,26 @@ match_sections(unsigned int iteration_num, |
+ (*is_secn_or_group_unique)[i] = true; |
+ } |
+ |
++ // If a section was folded into another section that was later folded |
++ // again then the former has to be updated. |
++ for (unsigned int i = 0; i < id_section.size(); i++) |
++ { |
++ // Find the end of the folding chain |
++ unsigned int kept = i; |
++ while ((*kept_section_id)[kept] != kept) |
++ { |
++ kept = (*kept_section_id)[kept]; |
++ } |
++ // Update every element of the chain |
++ unsigned int current = i; |
++ while ((*kept_section_id)[current] != kept) |
++ { |
++ unsigned int next = (*kept_section_id)[current]; |
++ (*kept_section_id)[current] = kept; |
++ current = next; |
++ } |
++ } |
++ |
+ return converged; |
+ } |
+ |
+@@ -719,6 +752,7 @@ Icf::find_identical_sections(const Input_objects* input_objects, |
+ { |
+ unsigned int section_num = 0; |
+ std::vector<unsigned int> num_tracked_relocs; |
++ std::vector<uint64_t> section_addraligns; |
+ std::vector<bool> is_secn_or_group_unique; |
+ std::vector<std::string> section_contents; |
+ const Target& target = parameters->target(); |
+@@ -759,6 +793,7 @@ Icf::find_identical_sections(const Input_objects* input_objects, |
+ this->section_id_[Section_id(*p, i)] = section_num; |
+ this->kept_section_id_.push_back(section_num); |
+ num_tracked_relocs.push_back(0); |
++ section_addraligns.push_back((*p)->section_addralign(i)); |
+ is_secn_or_group_unique.push_back(false); |
+ section_contents.push_back(""); |
+ section_num++; |
+@@ -779,8 +814,8 @@ Icf::find_identical_sections(const Input_objects* input_objects, |
+ num_iterations++; |
+ converged = match_sections(num_iterations, symtab, |
+ &num_tracked_relocs, &this->kept_section_id_, |
+- this->id_section_, &is_secn_or_group_unique, |
+- §ion_contents); |
++ this->id_section_, section_addraligns, |
++ &is_secn_or_group_unique, §ion_contents); |
+ } |
+ |
+ if (parameters->options().print_icf_sections()) |