Index: third_party/binutils/icf-rel.patch |
diff --git a/third_party/binutils/icf-rel.patch b/third_party/binutils/icf-rel.patch |
new file mode 100644 |
index 0000000000000000000000000000000000000000..1747fccfaedb82663c83178111c7ed8a7d50599d |
--- /dev/null |
+++ b/third_party/binutils/icf-rel.patch |
@@ -0,0 +1,181 @@ |
+commit d114b830426300f80302ca03ff4322942f63c615 |
+Author: Roland McGrath <mcgrathr@chromium.org> |
+Date: Thu May 5 13:12:40 2016 -0700 |
+ |
+ 2016-02-05 Sriraman Tallam <tmsriram@google.com> |
+ |
+ PR gold/19047 |
+ * icf.cc (get_rel_addend): New function. |
+ (get_section_contents): Move merge section addend computation to a |
+ new function. Ignore negative values for SHT_REL and SHT_RELA addends. |
+ Fix bug to not read past the length of the section. |
+ |
+ Fix bug related to addend computation for MERGE sections. |
+ |
+ (cherry picked from commit 84d543b7ed93bf6511cdf45791f4f0b717dfb718) |
+ |
+diff --git a/gold/ChangeLog b/gold/ChangeLog |
+index 92b26ba..ec8dacb 100644 |
+--- a/gold/ChangeLog |
++++ b/gold/ChangeLog |
+@@ -1,3 +1,11 @@ |
++2016-02-05 Sriraman Tallam <tmsriram@google.com> |
++ |
++ PR gold/19047 |
++ * icf.cc (get_rel_addend): New function. |
++ (get_section_contents): Move merge section addend computation to a |
++ new function. Ignore negative values for SHT_REL and SHT_RELA addends. |
++ Fix bug to not read past the length of the section. |
++ |
+ 2015-12-17 Peter Collingbourne <pcc@google.com> |
+ |
+ PR gold/18780 |
+diff --git a/gold/icf.cc b/gold/icf.cc |
+index 96b7f2d..663d579 100644 |
+--- a/gold/icf.cc |
++++ b/gold/icf.cc |
+@@ -213,6 +213,45 @@ preprocess_for_unique_sections(const std::vector<Section_id>& id_section, |
+ } |
+ } |
+ |
++// For SHF_MERGE sections that use REL relocations, the addend is stored in |
++// the text section at the relocation offset. Read the addend value given |
++// the pointer to the addend in the text section and the addend size. |
++// Update the addend value if a valid addend is found. |
++// Parameters: |
++// RELOC_ADDEND_PTR : Pointer to the addend in the text section. |
++// ADDEND_SIZE : The size of the addend. |
++// RELOC_ADDEND_VALUE : Pointer to the addend that is updated. |
++ |
++inline void |
++get_rel_addend(const unsigned char* reloc_addend_ptr, |
++ const unsigned int addend_size, |
++ uint64_t* reloc_addend_value) |
++{ |
++ switch (addend_size) |
++ { |
++ case 0: |
++ break; |
++ case 1: |
++ *reloc_addend_value = |
++ read_from_pointer<8>(reloc_addend_ptr); |
++ break; |
++ case 2: |
++ *reloc_addend_value = |
++ read_from_pointer<16>(reloc_addend_ptr); |
++ break; |
++ case 4: |
++ *reloc_addend_value = |
++ read_from_pointer<32>(reloc_addend_ptr); |
++ break; |
++ case 8: |
++ *reloc_addend_value = |
++ read_from_pointer<64>(reloc_addend_ptr); |
++ break; |
++ default: |
++ gold_unreachable(); |
++ } |
++} |
++ |
+ // This returns the buffer containing the section's contents, both |
+ // text and relocs. Relocs are differentiated as those pointing to |
+ // sections that could be folded and those that cannot. Only relocs |
+@@ -397,58 +436,36 @@ get_section_contents(bool first_iteration, |
+ uint64_t entsize = |
+ (it_v->first)->section_entsize(it_v->second); |
+ long long offset = it_a->first; |
+- |
+- unsigned long long addend = it_a->second; |
+- // Ignoring the addend when it is a negative value. See the |
+- // comments in Merged_symbol_value::Value in object.h. |
+- if (addend < 0xffffff00) |
+- offset = offset + addend; |
+- |
+- // For SHT_REL relocation sections, the addend is stored in the |
+- // text section at the relocation offset. |
+- uint64_t reloc_addend_value = 0; |
++ // Handle SHT_RELA and SHT_REL addends, only one of these |
++ // addends exists. |
++ // Get the SHT_RELA addend. For RELA relocations, we have |
++ // the addend from the relocation. |
++ uint64_t reloc_addend_value = it_a->second; |
++ |
++ // Handle SHT_REL addends. |
++ // For REL relocations, we need to fetch the addend from the |
++ // section contents. |
+ const unsigned char* reloc_addend_ptr = |
+ contents + static_cast<unsigned long long>(*it_o); |
+- switch(*it_addend_size) |
+- { |
+- case 0: |
+- { |
+- break; |
+- } |
+- case 1: |
+- { |
+- reloc_addend_value = |
+- read_from_pointer<8>(reloc_addend_ptr); |
+- break; |
+- } |
+- case 2: |
+- { |
+- reloc_addend_value = |
+- read_from_pointer<16>(reloc_addend_ptr); |
+- break; |
+- } |
+- case 4: |
+- { |
+- reloc_addend_value = |
+- read_from_pointer<32>(reloc_addend_ptr); |
+- break; |
+- } |
+- case 8: |
+- { |
+- reloc_addend_value = |
+- read_from_pointer<64>(reloc_addend_ptr); |
+- break; |
+- } |
+- default: |
+- gold_unreachable(); |
+- } |
+- offset = offset + reloc_addend_value; |
++ |
++ // Update the addend value with the SHT_REL addend if |
++ // available. |
++ get_rel_addend(reloc_addend_ptr, *it_addend_size, |
++ &reloc_addend_value); |
++ |
++ // Ignore the addend when it is a negative value. See the |
++ // comments in Merged_symbol_value::value in object.h. |
++ if (reloc_addend_value < 0xffffff00) |
++ offset = offset + reloc_addend_value; |
+ |
+ section_size_type secn_len; |
++ |
+ const unsigned char* str_contents = |
+ (it_v->first)->section_contents(it_v->second, |
+ &secn_len, |
+ false) + offset; |
++ gold_assert (offset < (long long) secn_len); |
++ |
+ if ((secn_flags & elfcpp::SHF_STRINGS) != 0) |
+ { |
+ // String merge section. |
+@@ -489,10 +506,14 @@ get_section_contents(bool first_iteration, |
+ } |
+ else |
+ { |
+- // Use the entsize to determine the length. |
+- buffer.append(reinterpret_cast<const |
++ // Use the entsize to determine the length to copy. |
++ uint64_t bufsize = entsize; |
++ // If entsize is too big, copy all the remaining bytes. |
++ if ((offset + entsize) > secn_len) |
++ bufsize = secn_len - offset; |
++ buffer.append(reinterpret_cast<const |
+ char*>(str_contents), |
+- entsize); |
++ bufsize); |
+ } |
+ buffer.append("@"); |
+ } |