| 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("@"); |
| } |