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
2 changed files with 74 additions and 46 deletions
|
@ -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>
|
||||
Andrew Senkevich <andrew.senkevich@intel.com>
|
||||
|
||||
|
|
111
gold/icf.cc
111
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;
|
||||
// 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;
|
||||
// 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_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.
|
||||
// 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("@");
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue