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