Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1436)

Unified Diff: tools/relocation_packer/src/elf_file.cc

Issue 423393010: Adjust addends rather than targets for RELA configurations. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | tools/relocation_packer/test_data/elf_file_unittest_relocs_arm64_packed.so » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tools/relocation_packer/src/elf_file.cc
diff --git a/tools/relocation_packer/src/elf_file.cc b/tools/relocation_packer/src/elf_file.cc
index 8f9b6b7e9e8ad29e69f972852736c595f18cc3a3..c874713396287af513727d90e641587166088a4a 100644
--- a/tools/relocation_packer/src/elf_file.cc
+++ b/tools/relocation_packer/src/elf_file.cc
@@ -204,10 +204,12 @@ bool ElfFile::Load() {
}
// Note special sections as we encounter them.
- if (name == ".rel.dyn" || name == ".rela.dyn") {
+ if ((name == ".rel.dyn" || name == ".rela.dyn") &&
+ section_header->sh_size > 0) {
found_relocations_section = section;
}
- if (name == ".android.rel.dyn" || name == ".android.rela.dyn") {
+ if ((name == ".android.rel.dyn" || name == ".android.rela.dyn") &&
+ section_header->sh_size > 0) {
found_android_relocations_section = section;
}
if (section_header->sh_offset == dynamic_program_header->p_offset) {
@@ -231,17 +233,17 @@ bool ElfFile::Load() {
// Loading failed if we did not find the required special sections.
if (!found_relocations_section) {
- LOG(ERROR) << "Missing .rel.dyn or .rela.dyn section";
+ LOG(ERROR) << "Missing or empty .rel.dyn or .rela.dyn section";
return false;
}
- if (!found_dynamic_section) {
- LOG(ERROR) << "Missing .dynamic section";
+ if (!found_android_relocations_section) {
+ LOG(ERROR) << "Missing or empty .android.rel.dyn or .android.rela.dyn "
+ << "section (to fix, run with --help and follow the "
+ << "pre-packing instructions)";
return false;
}
- if (!found_android_relocations_section) {
- LOG(ERROR) << "Missing .android.rel.dyn or .android.rela.dyn section "
- << "(to fix, run with --help and follow the pre-packing "
- << "instructions)";
+ if (!found_dynamic_section) {
+ LOG(ERROR) << "Missing .dynamic section";
return false;
}
@@ -686,14 +688,52 @@ void RemoveDynamicEntry(ELF::Sword tag,
CHECK(dynamics->at(dynamics->size() - 1).d_tag == DT_NULL);
}
-// Apply relative relocations to the file data to which they refer.
-// This relocates data into the area it will occupy after the hole in
+// Adjust a relocation. For a relocation without addend, we find its target
+// in the section and adjust that. For a relocation with addend, the target
+// is the relocation addend, and the section data at the target is zero.
+template <typename Rel>
+void AdjustRelocation(ssize_t index,
rmcilroy 2014/08/04 12:12:50 AdjustRelocationTarget?
+ ELF::Addr hole_start,
+ ssize_t hole_size,
+ Rel* relocation,
+ ELF::Off* target);
+
+template <>
+void AdjustRelocation<ELF::Rel>(ssize_t index,
+ ELF::Addr hole_start,
+ ssize_t hole_size,
+ ELF::Rel* relocation,
+ ELF::Off* target) {
+ // Adjust the target if after the hole start.
+ if (*target > hole_start) {
+ *target += hole_size;
+ VLOG(1) << "relocation[" << index << "] target adjusted to " << *target;
+ }
+}
+
+template <>
+void AdjustRelocation<ELF::Rela>(ssize_t index,
+ ELF::Addr hole_start,
+ ssize_t hole_size,
+ ELF::Rela* relocation,
+ ELF::Off* target) {
+ // The relocation's target is the addend. Adjust if after the hole start.
+ if (relocation->r_addend > hole_start) {
+ relocation->r_addend += hole_size;
+ VLOG(1) << "relocation["
+ << index << "] addend adjusted to " << relocation->r_addend;
+ }
+}
+
+// For relative relocations without addends, adjust the file data to which
+// they refer. For relative relocations with addends, adjust the addends.
+// This translates data into the area it will occupy after the hole in
// the dynamic relocations is added or removed.
template <typename Rel>
void AdjustRelocationTargets(Elf* elf,
ELF::Off hole_start,
ssize_t hole_size,
- const std::vector<Rel>& relocations) {
+ std::vector<Rel>* relocations) {
Elf_Scn* section = NULL;
while ((section = elf_nextscn(elf, section)) != NULL) {
const ELF::Shdr* section_header = ELF::getshdr(section);
@@ -712,40 +752,32 @@ void AdjustRelocationTargets(Elf* elf,
const ELF::Addr section_start = section_header->sh_addr;
const ELF::Addr section_end = section_start + section_header->sh_size;
- // Create a copy-on-write pointer to the section's data.
- uint8_t* area = reinterpret_cast<uint8_t*>(data->d_buf);
+ // Create a copy of the section's data.
+ uint8_t* area = new uint8_t[data->d_size];
+ memcpy(area, data->d_buf, data->d_size);
- for (size_t i = 0; i < relocations.size(); ++i) {
- const Rel* relocation = &relocations[i];
+ for (size_t i = 0; i < relocations->size(); ++i) {
+ Rel* relocation = &relocations->at(i);
CHECK(ELF_R_TYPE(relocation->r_info) == ELF::kRelativeRelocationCode);
// See if this relocation points into the current section.
if (relocation->r_offset >= section_start &&
relocation->r_offset < section_end) {
+ // The relocation's target is what it points to in area.
+ // For relocations without addend, this is what we adjust; for
+ // relocations with addend, we leave this (it will be zero)
+ // and instead adjust the addend.
ELF::Addr byte_offset = relocation->r_offset - section_start;
ELF::Off* target = reinterpret_cast<ELF::Off*>(area + byte_offset);
-
- // Is the relocation's target after the hole's start?
- if (*target > hole_start) {
- // Copy on first write. Recompute target to point into the newly
- // allocated buffer.
- if (area == data->d_buf) {
- area = new uint8_t[data->d_size];
- memcpy(area, data->d_buf, data->d_size);
- target = reinterpret_cast<ELF::Off*>(area + byte_offset);
- }
-
- *target += hole_size;
- VLOG(1) << "relocation[" << i << "] target adjusted to " << *target;
- }
+ AdjustRelocation<Rel>(i, hole_start, hole_size, relocation, target);
}
}
- // If we applied any relocation to this section, write it back.
- if (area != data->d_buf) {
+ // If we altered the data for this section, write it back.
+ if (memcmp(area, data->d_buf, data->d_size)) {
RewriteSectionData(data, area, data->d_size);
- delete [] area;
}
+ delete [] area;
}
}
@@ -884,17 +916,31 @@ bool ElfFile::PackTypedRelocations(const std::vector<Rel>& relocations,
return false;
}
- // Add null relocations to other_relocations to preserve alignment.
- const size_t padding_bytes = unaligned_hole_size - hole_size;
+ // Find the padding needed in other_relocations to preserve alignment.
+ // Ensure that we never completely empty the real relocations section.
+ size_t padding_bytes = unaligned_hole_size - hole_size;
+ if (padding_bytes == 0 && other_relocations.size() == 0) {
+ do {
+ padding_bytes += sizeof(relative_relocations[0]);
+ } while (padding_bytes % kPreserveAlignment);
+ }
CHECK(padding_bytes % sizeof(other_relocations[0]) == 0);
- const size_t required = padding_bytes / sizeof(other_relocations[0]);
- PadRelocations(required, &other_relocations);
- LOG(INFO) << "Alignment pad : " << required << " relocations";
+ const size_t padding = padding_bytes / sizeof(other_relocations[0]);
+
+ // Padding may have removed any packing benefit.
+ if (padding >= relative_relocations.size()) {
+ LOG(INFO) << "Too few relative relocations to pack after padding";
+ return false;
+ }
+
+ // Add null relocations to other_relocations to preserve alignment.
+ PadRelocations<Rel>(padding, &other_relocations);
+ LOG(INFO) << "Alignment pad : " << padding << " relocations";
// Apply relocations to all relative data to relocate it into the
// area it will occupy once the hole in the dynamic relocations is removed.
AdjustRelocationTargets<Rel>(
- elf_, hole_start, -hole_size, relative_relocations);
+ elf_, hole_start, -hole_size, &relative_relocations);
// Relocate the relocations.
AdjustRelocations<Rel>(hole_start, -hole_size, &relative_relocations);
AdjustRelocations<Rel>(hole_start, -hole_size, &other_relocations);
@@ -902,8 +948,8 @@ bool ElfFile::PackTypedRelocations(const std::vector<Rel>& relocations,
// If padding, add NONE-type relocations to other_relocations to make it
// the same size as the the original relocations we read in. This makes
// the ResizeSection() below a no-op.
- const size_t required = relocations.size() - other_relocations.size();
- PadRelocations(required, &other_relocations);
+ const size_t padding = relocations.size() - other_relocations.size();
+ PadRelocations<Rel>(padding, &other_relocations);
}
// Pack relative relocations.
@@ -1081,7 +1127,7 @@ bool ElfFile::UnpackTypedRelocations(const std::vector<uint8_t>& packed,
// Apply relocations to all relative data to relocate it into the
// area it will occupy once the hole in dynamic relocations is opened.
AdjustRelocationTargets<Rel>(
- elf_, hole_start, hole_size, relative_relocations);
+ elf_, hole_start, hole_size, &relative_relocations);
// Relocate the relocations.
AdjustRelocations<Rel>(hole_start, hole_size, &relative_relocations);
AdjustRelocations<Rel>(hole_start, hole_size, &other_relocations);
« no previous file with comments | « no previous file | tools/relocation_packer/test_data/elf_file_unittest_relocs_arm64_packed.so » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698