2016-02-05 Sriraman Tallam <tmsriram@google.com>
* 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.
This commit is contained in:
parent
c34c98ed62
commit
84d543b7ed
@ -1,3 +1,10 @@
|
|||||||
|
2016-02-05 Sriraman Tallam <tmsriram@google.com>
|
||||||
|
|
||||||
|
* 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.
|
||||||
|
|
||||||
2016-02-05 Cary Coutant <ccoutant@gmail.com>
|
2016-02-05 Cary Coutant <ccoutant@gmail.com>
|
||||||
Andrew Senkevich <andrew.senkevich@intel.com>
|
Andrew Senkevich <andrew.senkevich@intel.com>
|
||||||
|
|
||||||
|
113
gold/icf.cc
113
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
|
// This returns the buffer containing the section's contents, both
|
||||||
// text and relocs. Relocs are differentiated as those pointing to
|
// text and relocs. Relocs are differentiated as those pointing to
|
||||||
// sections that could be folded and those that cannot. Only relocs
|
// sections that could be folded and those that cannot. Only relocs
|
||||||
@ -397,58 +436,36 @@ get_section_contents(bool first_iteration,
|
|||||||
uint64_t entsize =
|
uint64_t entsize =
|
||||||
(it_v->first)->section_entsize(it_v->second);
|
(it_v->first)->section_entsize(it_v->second);
|
||||||
long long offset = it_a->first;
|
long long offset = it_a->first;
|
||||||
|
// 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;
|
||||||
|
|
||||||
unsigned long long addend = it_a->second;
|
// Handle SHT_REL addends.
|
||||||
// Ignoring the addend when it is a negative value. See the
|
// For REL relocations, we need to fetch the addend from the
|
||||||
// comments in Merged_symbol_value::Value in object.h.
|
// section contents.
|
||||||
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;
|
|
||||||
const unsigned char* reloc_addend_ptr =
|
const unsigned char* reloc_addend_ptr =
|
||||||
contents + static_cast<unsigned long long>(*it_o);
|
contents + static_cast<unsigned long long>(*it_o);
|
||||||
switch(*it_addend_size)
|
|
||||||
{
|
// Update the addend value with the SHT_REL addend if
|
||||||
case 0:
|
// available.
|
||||||
{
|
get_rel_addend(reloc_addend_ptr, *it_addend_size,
|
||||||
break;
|
&reloc_addend_value);
|
||||||
}
|
|
||||||
case 1:
|
// Ignore the addend when it is a negative value. See the
|
||||||
{
|
// comments in Merged_symbol_value::value in object.h.
|
||||||
reloc_addend_value =
|
if (reloc_addend_value < 0xffffff00)
|
||||||
read_from_pointer<8>(reloc_addend_ptr);
|
offset = offset + reloc_addend_value;
|
||||||
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;
|
|
||||||
|
|
||||||
section_size_type secn_len;
|
section_size_type secn_len;
|
||||||
|
|
||||||
const unsigned char* str_contents =
|
const unsigned char* str_contents =
|
||||||
(it_v->first)->section_contents(it_v->second,
|
(it_v->first)->section_contents(it_v->second,
|
||||||
&secn_len,
|
&secn_len,
|
||||||
false) + offset;
|
false) + offset;
|
||||||
|
gold_assert (offset < (long long) secn_len);
|
||||||
|
|
||||||
if ((secn_flags & elfcpp::SHF_STRINGS) != 0)
|
if ((secn_flags & elfcpp::SHF_STRINGS) != 0)
|
||||||
{
|
{
|
||||||
// String merge section.
|
// String merge section.
|
||||||
@ -489,10 +506,14 @@ get_section_contents(bool first_iteration,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Use the entsize to determine the length.
|
// Use the entsize to determine the length to copy.
|
||||||
buffer.append(reinterpret_cast<const
|
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),
|
char*>(str_contents),
|
||||||
entsize);
|
bufsize);
|
||||||
}
|
}
|
||||||
buffer.append("@");
|
buffer.append("@");
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user