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

Side by Side 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 unified diff | 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 »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "elf_file.h" 5 #include "elf_file.h"
6 6
7 #include <stdlib.h> 7 #include <stdlib.h>
8 #include <sys/types.h> 8 #include <sys/types.h>
9 #include <unistd.h> 9 #include <unistd.h>
10 #include <string> 10 #include <string>
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after
197 197
198 // Note relocation section types. 198 // Note relocation section types.
199 if (section_header->sh_type == SHT_REL) { 199 if (section_header->sh_type == SHT_REL) {
200 has_rel_relocations = true; 200 has_rel_relocations = true;
201 } 201 }
202 if (section_header->sh_type == SHT_RELA) { 202 if (section_header->sh_type == SHT_RELA) {
203 has_rela_relocations = true; 203 has_rela_relocations = true;
204 } 204 }
205 205
206 // Note special sections as we encounter them. 206 // Note special sections as we encounter them.
207 if (name == ".rel.dyn" || name == ".rela.dyn") { 207 if ((name == ".rel.dyn" || name == ".rela.dyn") &&
208 section_header->sh_size > 0) {
208 found_relocations_section = section; 209 found_relocations_section = section;
209 } 210 }
210 if (name == ".android.rel.dyn" || name == ".android.rela.dyn") { 211 if ((name == ".android.rel.dyn" || name == ".android.rela.dyn") &&
212 section_header->sh_size > 0) {
211 found_android_relocations_section = section; 213 found_android_relocations_section = section;
212 } 214 }
213 if (section_header->sh_offset == dynamic_program_header->p_offset) { 215 if (section_header->sh_offset == dynamic_program_header->p_offset) {
214 found_dynamic_section = section; 216 found_dynamic_section = section;
215 } 217 }
216 218
217 // If we find a section named .debug*, set the debug warning flag. 219 // If we find a section named .debug*, set the debug warning flag.
218 if (std::string(name).find(".debug") == 0) { 220 if (std::string(name).find(".debug") == 0) {
219 has_debug_section = true; 221 has_debug_section = true;
220 } 222 }
221 223
222 // Ensure we preserve alignment, repeated later for the data block(s). 224 // Ensure we preserve alignment, repeated later for the data block(s).
223 CHECK(section_header->sh_addralign <= kPreserveAlignment); 225 CHECK(section_header->sh_addralign <= kPreserveAlignment);
224 226
225 Elf_Data* data = NULL; 227 Elf_Data* data = NULL;
226 while ((data = elf_getdata(section, data)) != NULL) { 228 while ((data = elf_getdata(section, data)) != NULL) {
227 CHECK(data->d_align <= kPreserveAlignment); 229 CHECK(data->d_align <= kPreserveAlignment);
228 VerboseLogSectionData(data); 230 VerboseLogSectionData(data);
229 } 231 }
230 } 232 }
231 233
232 // Loading failed if we did not find the required special sections. 234 // Loading failed if we did not find the required special sections.
233 if (!found_relocations_section) { 235 if (!found_relocations_section) {
234 LOG(ERROR) << "Missing .rel.dyn or .rela.dyn section"; 236 LOG(ERROR) << "Missing or empty .rel.dyn or .rela.dyn section";
237 return false;
238 }
239 if (!found_android_relocations_section) {
240 LOG(ERROR) << "Missing or empty .android.rel.dyn or .android.rela.dyn "
241 << "section (to fix, run with --help and follow the "
242 << "pre-packing instructions)";
235 return false; 243 return false;
236 } 244 }
237 if (!found_dynamic_section) { 245 if (!found_dynamic_section) {
238 LOG(ERROR) << "Missing .dynamic section"; 246 LOG(ERROR) << "Missing .dynamic section";
239 return false; 247 return false;
240 } 248 }
241 if (!found_android_relocations_section) {
242 LOG(ERROR) << "Missing .android.rel.dyn or .android.rela.dyn section "
243 << "(to fix, run with --help and follow the pre-packing "
244 << "instructions)";
245 return false;
246 }
247 249
248 // Loading failed if we could not identify the relocations type. 250 // Loading failed if we could not identify the relocations type.
249 if (!has_rel_relocations && !has_rela_relocations) { 251 if (!has_rel_relocations && !has_rela_relocations) {
250 LOG(ERROR) << "No relocations sections found"; 252 LOG(ERROR) << "No relocations sections found";
251 return false; 253 return false;
252 } 254 }
253 if (has_rel_relocations && has_rela_relocations) { 255 if (has_rel_relocations && has_rela_relocations) {
254 LOG(ERROR) << "Multiple relocations sections with different types found, " 256 LOG(ERROR) << "Multiple relocations sections with different types found, "
255 << "not currently supported"; 257 << "not currently supported";
256 return false; 258 return false;
(...skipping 422 matching lines...) Expand 10 before | Expand all | Expand 10 after
679 for (size_t i = slot; i < dynamics->size() - 1; ++i) { 681 for (size_t i = slot; i < dynamics->size() - 1; ++i) {
680 dynamics->at(i) = dynamics->at(i + 1); 682 dynamics->at(i) = dynamics->at(i + 1);
681 VLOG(1) << "dynamic[" << i 683 VLOG(1) << "dynamic[" << i
682 << "] overwritten with dynamic[" << i + 1 << "]"; 684 << "] overwritten with dynamic[" << i + 1 << "]";
683 } 685 }
684 686
685 // Ensure that the end sentinel is still present. 687 // Ensure that the end sentinel is still present.
686 CHECK(dynamics->at(dynamics->size() - 1).d_tag == DT_NULL); 688 CHECK(dynamics->at(dynamics->size() - 1).d_tag == DT_NULL);
687 } 689 }
688 690
689 // Apply relative relocations to the file data to which they refer. 691 // Adjust a relocation. For a relocation without addend, we find its target
690 // This relocates data into the area it will occupy after the hole in 692 // in the section and adjust that. For a relocation with addend, the target
693 // is the relocation addend, and the section data at the target is zero.
694 template <typename Rel>
695 void AdjustRelocation(ssize_t index,
rmcilroy 2014/08/04 12:12:50 AdjustRelocationTarget?
696 ELF::Addr hole_start,
697 ssize_t hole_size,
698 Rel* relocation,
699 ELF::Off* target);
700
701 template <>
702 void AdjustRelocation<ELF::Rel>(ssize_t index,
703 ELF::Addr hole_start,
704 ssize_t hole_size,
705 ELF::Rel* relocation,
706 ELF::Off* target) {
707 // Adjust the target if after the hole start.
708 if (*target > hole_start) {
709 *target += hole_size;
710 VLOG(1) << "relocation[" << index << "] target adjusted to " << *target;
711 }
712 }
713
714 template <>
715 void AdjustRelocation<ELF::Rela>(ssize_t index,
716 ELF::Addr hole_start,
717 ssize_t hole_size,
718 ELF::Rela* relocation,
719 ELF::Off* target) {
720 // The relocation's target is the addend. Adjust if after the hole start.
721 if (relocation->r_addend > hole_start) {
722 relocation->r_addend += hole_size;
723 VLOG(1) << "relocation["
724 << index << "] addend adjusted to " << relocation->r_addend;
725 }
726 }
727
728 // For relative relocations without addends, adjust the file data to which
729 // they refer. For relative relocations with addends, adjust the addends.
730 // This translates data into the area it will occupy after the hole in
691 // the dynamic relocations is added or removed. 731 // the dynamic relocations is added or removed.
692 template <typename Rel> 732 template <typename Rel>
693 void AdjustRelocationTargets(Elf* elf, 733 void AdjustRelocationTargets(Elf* elf,
694 ELF::Off hole_start, 734 ELF::Off hole_start,
695 ssize_t hole_size, 735 ssize_t hole_size,
696 const std::vector<Rel>& relocations) { 736 std::vector<Rel>* relocations) {
697 Elf_Scn* section = NULL; 737 Elf_Scn* section = NULL;
698 while ((section = elf_nextscn(elf, section)) != NULL) { 738 while ((section = elf_nextscn(elf, section)) != NULL) {
699 const ELF::Shdr* section_header = ELF::getshdr(section); 739 const ELF::Shdr* section_header = ELF::getshdr(section);
700 740
701 // Ignore sections that do not appear in a process memory image. 741 // Ignore sections that do not appear in a process memory image.
702 if (section_header->sh_addr == 0) 742 if (section_header->sh_addr == 0)
703 continue; 743 continue;
704 744
705 Elf_Data* data = GetSectionData(section); 745 Elf_Data* data = GetSectionData(section);
706 746
707 // Ignore sections with no effective data. 747 // Ignore sections with no effective data.
708 if (data->d_buf == NULL) 748 if (data->d_buf == NULL)
709 continue; 749 continue;
710 750
711 // Identify this section's start and end addresses. 751 // Identify this section's start and end addresses.
712 const ELF::Addr section_start = section_header->sh_addr; 752 const ELF::Addr section_start = section_header->sh_addr;
713 const ELF::Addr section_end = section_start + section_header->sh_size; 753 const ELF::Addr section_end = section_start + section_header->sh_size;
714 754
715 // Create a copy-on-write pointer to the section's data. 755 // Create a copy of the section's data.
716 uint8_t* area = reinterpret_cast<uint8_t*>(data->d_buf); 756 uint8_t* area = new uint8_t[data->d_size];
757 memcpy(area, data->d_buf, data->d_size);
717 758
718 for (size_t i = 0; i < relocations.size(); ++i) { 759 for (size_t i = 0; i < relocations->size(); ++i) {
719 const Rel* relocation = &relocations[i]; 760 Rel* relocation = &relocations->at(i);
720 CHECK(ELF_R_TYPE(relocation->r_info) == ELF::kRelativeRelocationCode); 761 CHECK(ELF_R_TYPE(relocation->r_info) == ELF::kRelativeRelocationCode);
721 762
722 // See if this relocation points into the current section. 763 // See if this relocation points into the current section.
723 if (relocation->r_offset >= section_start && 764 if (relocation->r_offset >= section_start &&
724 relocation->r_offset < section_end) { 765 relocation->r_offset < section_end) {
766 // The relocation's target is what it points to in area.
767 // For relocations without addend, this is what we adjust; for
768 // relocations with addend, we leave this (it will be zero)
769 // and instead adjust the addend.
725 ELF::Addr byte_offset = relocation->r_offset - section_start; 770 ELF::Addr byte_offset = relocation->r_offset - section_start;
726 ELF::Off* target = reinterpret_cast<ELF::Off*>(area + byte_offset); 771 ELF::Off* target = reinterpret_cast<ELF::Off*>(area + byte_offset);
727 772 AdjustRelocation<Rel>(i, hole_start, hole_size, relocation, target);
728 // Is the relocation's target after the hole's start?
729 if (*target > hole_start) {
730 // Copy on first write. Recompute target to point into the newly
731 // allocated buffer.
732 if (area == data->d_buf) {
733 area = new uint8_t[data->d_size];
734 memcpy(area, data->d_buf, data->d_size);
735 target = reinterpret_cast<ELF::Off*>(area + byte_offset);
736 }
737
738 *target += hole_size;
739 VLOG(1) << "relocation[" << i << "] target adjusted to " << *target;
740 }
741 } 773 }
742 } 774 }
743 775
744 // If we applied any relocation to this section, write it back. 776 // If we altered the data for this section, write it back.
745 if (area != data->d_buf) { 777 if (memcmp(area, data->d_buf, data->d_size)) {
746 RewriteSectionData(data, area, data->d_size); 778 RewriteSectionData(data, area, data->d_size);
747 delete [] area;
748 } 779 }
780 delete [] area;
749 } 781 }
750 } 782 }
751 783
752 // Pad relocations with a given number of null relocations. 784 // Pad relocations with a given number of null relocations.
753 template <typename Rel> 785 template <typename Rel>
754 void PadRelocations(size_t count, std::vector<Rel>* relocations); 786 void PadRelocations(size_t count, std::vector<Rel>* relocations);
755 787
756 template <> 788 template <>
757 void PadRelocations<ELF::Rel>(size_t count, 789 void PadRelocations<ELF::Rel>(size_t count,
758 std::vector<ELF::Rel>* relocations) { 790 std::vector<ELF::Rel>* relocations) {
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
877 while (hole_size % kPreserveAlignment) 909 while (hole_size % kPreserveAlignment)
878 hole_size -= sizeof(relative_relocations[0]); 910 hole_size -= sizeof(relative_relocations[0]);
879 LOG(INFO) << "Compaction : " << hole_size << " bytes"; 911 LOG(INFO) << "Compaction : " << hole_size << " bytes";
880 912
881 // Adjusting for alignment may have removed any packing benefit. 913 // Adjusting for alignment may have removed any packing benefit.
882 if (hole_size == 0) { 914 if (hole_size == 0) {
883 LOG(INFO) << "Too few relative relocations to pack after alignment"; 915 LOG(INFO) << "Too few relative relocations to pack after alignment";
884 return false; 916 return false;
885 } 917 }
886 918
919 // Find the padding needed in other_relocations to preserve alignment.
920 // Ensure that we never completely empty the real relocations section.
921 size_t padding_bytes = unaligned_hole_size - hole_size;
922 if (padding_bytes == 0 && other_relocations.size() == 0) {
923 do {
924 padding_bytes += sizeof(relative_relocations[0]);
925 } while (padding_bytes % kPreserveAlignment);
926 }
927 CHECK(padding_bytes % sizeof(other_relocations[0]) == 0);
928 const size_t padding = padding_bytes / sizeof(other_relocations[0]);
929
930 // Padding may have removed any packing benefit.
931 if (padding >= relative_relocations.size()) {
932 LOG(INFO) << "Too few relative relocations to pack after padding";
933 return false;
934 }
935
887 // Add null relocations to other_relocations to preserve alignment. 936 // Add null relocations to other_relocations to preserve alignment.
888 const size_t padding_bytes = unaligned_hole_size - hole_size; 937 PadRelocations<Rel>(padding, &other_relocations);
889 CHECK(padding_bytes % sizeof(other_relocations[0]) == 0); 938 LOG(INFO) << "Alignment pad : " << padding << " relocations";
890 const size_t required = padding_bytes / sizeof(other_relocations[0]);
891 PadRelocations(required, &other_relocations);
892 LOG(INFO) << "Alignment pad : " << required << " relocations";
893 939
894 // Apply relocations to all relative data to relocate it into the 940 // Apply relocations to all relative data to relocate it into the
895 // area it will occupy once the hole in the dynamic relocations is removed. 941 // area it will occupy once the hole in the dynamic relocations is removed.
896 AdjustRelocationTargets<Rel>( 942 AdjustRelocationTargets<Rel>(
897 elf_, hole_start, -hole_size, relative_relocations); 943 elf_, hole_start, -hole_size, &relative_relocations);
898 // Relocate the relocations. 944 // Relocate the relocations.
899 AdjustRelocations<Rel>(hole_start, -hole_size, &relative_relocations); 945 AdjustRelocations<Rel>(hole_start, -hole_size, &relative_relocations);
900 AdjustRelocations<Rel>(hole_start, -hole_size, &other_relocations); 946 AdjustRelocations<Rel>(hole_start, -hole_size, &other_relocations);
901 } else { 947 } else {
902 // If padding, add NONE-type relocations to other_relocations to make it 948 // If padding, add NONE-type relocations to other_relocations to make it
903 // the same size as the the original relocations we read in. This makes 949 // the same size as the the original relocations we read in. This makes
904 // the ResizeSection() below a no-op. 950 // the ResizeSection() below a no-op.
905 const size_t required = relocations.size() - other_relocations.size(); 951 const size_t padding = relocations.size() - other_relocations.size();
906 PadRelocations(required, &other_relocations); 952 PadRelocations<Rel>(padding, &other_relocations);
907 } 953 }
908 954
909 // Pack relative relocations. 955 // Pack relative relocations.
910 const size_t initial_bytes = 956 const size_t initial_bytes =
911 relative_relocations.size() * sizeof(relative_relocations[0]); 957 relative_relocations.size() * sizeof(relative_relocations[0]);
912 LOG(INFO) << "Unpacked relative: " << initial_bytes << " bytes"; 958 LOG(INFO) << "Unpacked relative: " << initial_bytes << " bytes";
913 std::vector<uint8_t> packed; 959 std::vector<uint8_t> packed;
914 RelocationPacker packer; 960 RelocationPacker packer;
915 packer.PackRelativeRelocations(relative_relocations, &packed); 961 packer.PackRelativeRelocations(relative_relocations, &packed);
916 const void* packed_data = &packed[0]; 962 const void* packed_data = &packed[0];
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after
1074 ssize_t hole_size = 1120 ssize_t hole_size =
1075 relative_relocations.size() * sizeof(relative_relocations[0]); 1121 relative_relocations.size() * sizeof(relative_relocations[0]);
1076 1122
1077 // Adjust the hole size for the padding added to preserve alignment. 1123 // Adjust the hole size for the padding added to preserve alignment.
1078 hole_size -= padding * sizeof(other_relocations[0]); 1124 hole_size -= padding * sizeof(other_relocations[0]);
1079 LOG(INFO) << "Expansion : " << hole_size << " bytes"; 1125 LOG(INFO) << "Expansion : " << hole_size << " bytes";
1080 1126
1081 // Apply relocations to all relative data to relocate it into the 1127 // Apply relocations to all relative data to relocate it into the
1082 // area it will occupy once the hole in dynamic relocations is opened. 1128 // area it will occupy once the hole in dynamic relocations is opened.
1083 AdjustRelocationTargets<Rel>( 1129 AdjustRelocationTargets<Rel>(
1084 elf_, hole_start, hole_size, relative_relocations); 1130 elf_, hole_start, hole_size, &relative_relocations);
1085 // Relocate the relocations. 1131 // Relocate the relocations.
1086 AdjustRelocations<Rel>(hole_start, hole_size, &relative_relocations); 1132 AdjustRelocations<Rel>(hole_start, hole_size, &relative_relocations);
1087 AdjustRelocations<Rel>(hole_start, hole_size, &other_relocations); 1133 AdjustRelocations<Rel>(hole_start, hole_size, &other_relocations);
1088 } 1134 }
1089 1135
1090 // Rewrite the current dynamic relocations section to be the relative 1136 // Rewrite the current dynamic relocations section to be the relative
1091 // relocations followed by other relocations. This is the usual order in 1137 // relocations followed by other relocations. This is the usual order in
1092 // which we find them after linking, so this action will normally put the 1138 // which we find them after linking, so this action will normally put the
1093 // entire dynamic relocations section back to its pre-split-and-packed state. 1139 // entire dynamic relocations section back to its pre-split-and-packed state.
1094 relocations.assign(relative_relocations.begin(), relative_relocations.end()); 1140 relocations.assign(relative_relocations.begin(), relative_relocations.end());
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
1140 1186
1141 // Clean up libelf, and truncate the output file to the number of bytes 1187 // Clean up libelf, and truncate the output file to the number of bytes
1142 // written by elf_update(). 1188 // written by elf_update().
1143 elf_end(elf_); 1189 elf_end(elf_);
1144 elf_ = NULL; 1190 elf_ = NULL;
1145 const int truncate = ftruncate(fd_, file_bytes); 1191 const int truncate = ftruncate(fd_, file_bytes);
1146 CHECK(truncate == 0); 1192 CHECK(truncate == 0);
1147 } 1193 }
1148 1194
1149 } // namespace relocation_packer 1195 } // namespace relocation_packer
OLDNEW
« 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