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

Side by Side Diff: third_party/android_platform/bionic/tools/relocation_packer/src/elf_file.cc

Issue 1099343004: Synchronize Android relocation packer source with AOSP. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 8 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
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 // Implementation notes: 5 // Implementation notes:
6 // 6 //
7 // We need to remove a piece from the ELF shared library. However, we also 7 // We need to remove a piece from the ELF shared library. However, we also
8 // want to avoid fixing DWARF cfi data and relative relocation addresses. 8 // want to avoid fixing DWARF cfi data and relative relocation addresses.
9 // So after packing we shift offets and starting address of the RX segment 9 // So after packing we shift offets and starting address of the RX segment
10 // while preserving code/data vaddrs location. 10 // while preserving code/data vaddrs location.
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after
183 // Notes of the dynamic relocations, packed relocations, and .dynamic 183 // Notes of the dynamic relocations, packed relocations, and .dynamic
184 // sections. Found while iterating sections, and later stored in class 184 // sections. Found while iterating sections, and later stored in class
185 // attributes. 185 // attributes.
186 Elf_Scn* found_relocations_section = nullptr; 186 Elf_Scn* found_relocations_section = nullptr;
187 Elf_Scn* found_dynamic_section = nullptr; 187 Elf_Scn* found_dynamic_section = nullptr;
188 188
189 // Notes of relocation section types seen. We require one or the other of 189 // Notes of relocation section types seen. We require one or the other of
190 // these; both is unsupported. 190 // these; both is unsupported.
191 bool has_rel_relocations = false; 191 bool has_rel_relocations = false;
192 bool has_rela_relocations = false; 192 bool has_rela_relocations = false;
193 bool has_android_relocations = false;
193 194
194 Elf_Scn* section = NULL; 195 Elf_Scn* section = NULL;
195 while ((section = elf_nextscn(elf, section)) != nullptr) { 196 while ((section = elf_nextscn(elf, section)) != nullptr) {
196 auto section_header = ELF::getshdr(section); 197 auto section_header = ELF::getshdr(section);
197 std::string name = elf_strptr(elf, string_index, section_header->sh_name); 198 std::string name = elf_strptr(elf, string_index, section_header->sh_name);
198 VerboseLogSectionHeader(name, section_header); 199 VerboseLogSectionHeader(name, section_header);
199 200
200 // Note relocation section types. 201 // Note relocation section types.
201 if (section_header->sh_type == SHT_REL || section_header->sh_type == SHT_AND ROID_REL) { 202 if (section_header->sh_type == SHT_REL || section_header->sh_type == SHT_AND ROID_REL) {
202 has_rel_relocations = true; 203 has_rel_relocations = true;
203 } 204 }
204 if (section_header->sh_type == SHT_RELA || section_header->sh_type == SHT_AN DROID_RELA) { 205 if (section_header->sh_type == SHT_RELA || section_header->sh_type == SHT_AN DROID_RELA) {
205 has_rela_relocations = true; 206 has_rela_relocations = true;
206 } 207 }
207 208
208 // Note special sections as we encounter them. 209 // Note special sections as we encounter them.
209 if ((name == ".rel.dyn" || name == ".rela.dyn") && 210 if ((name == ".rel.dyn" || name == ".rela.dyn") &&
210 section_header->sh_size > 0) { 211 section_header->sh_size > 0) {
211 found_relocations_section = section; 212 found_relocations_section = section;
213
214 // Note if relocation section is already packed
215 has_android_relocations =
216 section_header->sh_type == SHT_ANDROID_REL ||
217 section_header->sh_type == SHT_ANDROID_RELA;
212 } 218 }
213 219
214 if (section_header->sh_offset == dynamic_program_header->p_offset) { 220 if (section_header->sh_offset == dynamic_program_header->p_offset) {
215 found_dynamic_section = section; 221 found_dynamic_section = section;
216 } 222 }
217 223
218 // Ensure we preserve alignment, repeated later for the data block(s). 224 // Ensure we preserve alignment, repeated later for the data block(s).
219 CHECK(section_header->sh_addralign <= kPreserveAlignment); 225 CHECK(section_header->sh_addralign <= kPreserveAlignment);
220 226
221 Elf_Data* data = NULL; 227 Elf_Data* data = NULL;
(...skipping 21 matching lines...) Expand all
243 if (has_rel_relocations && has_rela_relocations) { 249 if (has_rel_relocations && has_rela_relocations) {
244 LOG(ERROR) << "Multiple relocations sections with different types found, " 250 LOG(ERROR) << "Multiple relocations sections with different types found, "
245 << "not currently supported"; 251 << "not currently supported";
246 return false; 252 return false;
247 } 253 }
248 254
249 elf_ = elf; 255 elf_ = elf;
250 relocations_section_ = found_relocations_section; 256 relocations_section_ = found_relocations_section;
251 dynamic_section_ = found_dynamic_section; 257 dynamic_section_ = found_dynamic_section;
252 relocations_type_ = has_rel_relocations ? REL : RELA; 258 relocations_type_ = has_rel_relocations ? REL : RELA;
259 has_android_relocations_ = has_android_relocations;
253 return true; 260 return true;
254 } 261 }
255 262
256 // Helper for ResizeSection(). Adjust the main ELF header for the hole. 263 // Helper for ResizeSection(). Adjust the main ELF header for the hole.
257 template <typename ELF> 264 template <typename ELF>
258 static void AdjustElfHeaderForHole(typename ELF::Ehdr* elf_header, 265 static void AdjustElfHeaderForHole(typename ELF::Ehdr* elf_header,
259 typename ELF::Off hole_start, 266 typename ELF::Off hole_start,
260 ssize_t hole_size) { 267 ssize_t hole_size) {
261 if (elf_header->e_phoff > hole_start) { 268 if (elf_header->e_phoff > hole_start) {
262 elf_header->e_phoff += hole_size; 269 elf_header->e_phoff += hole_size;
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after
432 tag == DT_GNU_HASH || 439 tag == DT_GNU_HASH ||
433 tag == DT_STRTAB || 440 tag == DT_STRTAB ||
434 tag == DT_SYMTAB || 441 tag == DT_SYMTAB ||
435 tag == DT_RELA || 442 tag == DT_RELA ||
436 tag == DT_INIT || 443 tag == DT_INIT ||
437 tag == DT_FINI || 444 tag == DT_FINI ||
438 tag == DT_REL || 445 tag == DT_REL ||
439 tag == DT_JMPREL || 446 tag == DT_JMPREL ||
440 tag == DT_INIT_ARRAY || 447 tag == DT_INIT_ARRAY ||
441 tag == DT_FINI_ARRAY || 448 tag == DT_FINI_ARRAY ||
449 tag == DT_VERSYM ||
450 tag == DT_VERNEED ||
451 tag == DT_VERDEF ||
442 tag == DT_ANDROID_REL|| 452 tag == DT_ANDROID_REL||
443 tag == DT_ANDROID_RELA); 453 tag == DT_ANDROID_RELA);
444 454
445 if (is_adjustable && dynamic->d_un.d_ptr <= hole_start) { 455 if (is_adjustable && dynamic->d_un.d_ptr <= hole_start) {
446 dynamic->d_un.d_ptr -= hole_size; 456 dynamic->d_un.d_ptr -= hole_size;
447 VLOG(1) << "dynamic[" << i << "] " << dynamic->d_tag 457 VLOG(1) << "dynamic[" << i << "] " << dynamic->d_tag
448 << " d_ptr adjusted to " << dynamic->d_un.d_ptr; 458 << " d_ptr adjusted to " << dynamic->d_un.d_ptr;
449 } 459 }
450 460
451 // DT_RELSZ or DT_RELASZ indicate the overall size of relocations. 461 // DT_RELSZ or DT_RELASZ indicate the overall size of relocations.
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
579 // Retrieve the current dynamic relocations section data. 589 // Retrieve the current dynamic relocations section data.
580 Elf_Data* data = GetSectionData(relocations_section_); 590 Elf_Data* data = GetSectionData(relocations_section_);
581 // we always pack rela, because packed format is pretty much the same 591 // we always pack rela, because packed format is pretty much the same
582 std::vector<typename ELF::Rela> relocations; 592 std::vector<typename ELF::Rela> relocations;
583 593
584 if (relocations_type_ == REL) { 594 if (relocations_type_ == REL) {
585 // Convert data to a vector of relocations. 595 // Convert data to a vector of relocations.
586 const typename ELF::Rel* relocations_base = reinterpret_cast<typename ELF::R el*>(data->d_buf); 596 const typename ELF::Rel* relocations_base = reinterpret_cast<typename ELF::R el*>(data->d_buf);
587 ConvertRelArrayToRelaVector(relocations_base, 597 ConvertRelArrayToRelaVector(relocations_base,
588 data->d_size / sizeof(typename ELF::Rel), &relocations); 598 data->d_size / sizeof(typename ELF::Rel), &relocations);
589 LOG(INFO) << "Relocations : REL"; 599 VLOG(1) << "Relocations : REL";
590 } else if (relocations_type_ == RELA) { 600 } else if (relocations_type_ == RELA) {
591 // Convert data to a vector of relocations with addends. 601 // Convert data to a vector of relocations with addends.
592 const typename ELF::Rela* relocations_base = reinterpret_cast<typename ELF:: Rela*>(data->d_buf); 602 const typename ELF::Rela* relocations_base = reinterpret_cast<typename ELF:: Rela*>(data->d_buf);
593 relocations = std::vector<typename ELF::Rela>( 603 relocations = std::vector<typename ELF::Rela>(
594 relocations_base, 604 relocations_base,
595 relocations_base + data->d_size / sizeof(relocations[0])); 605 relocations_base + data->d_size / sizeof(relocations[0]));
596 606
597 LOG(INFO) << "Relocations : RELA"; 607 VLOG(1) << "Relocations : RELA";
598 } else { 608 } else {
599 NOTREACHED(); 609 NOTREACHED();
600 } 610 }
601 611
602 return PackTypedRelocations(&relocations); 612 return PackTypedRelocations(&relocations);
603 } 613 }
604 614
605 // Helper for PackRelocations(). Rel type is one of ELF::Rel or ELF::Rela. 615 // Helper for PackRelocations(). Rel type is one of ELF::Rel or ELF::Rela.
606 template <typename ELF> 616 template <typename ELF>
607 bool ElfFile<ELF>::PackTypedRelocations(std::vector<typename ELF::Rela>* relocat ions) { 617 bool ElfFile<ELF>::PackTypedRelocations(std::vector<typename ELF::Rela>* relocat ions) {
608 typedef typename ELF::Rela Rela; 618 typedef typename ELF::Rela Rela;
609 619
620 if (has_android_relocations_) {
621 LOG(ERROR) << "Relocation table is already packed";
622 return false;
623 }
624
610 // If no relocations then we have nothing packable. Perhaps 625 // If no relocations then we have nothing packable. Perhaps
611 // the shared object has already been packed? 626 // the shared object has already been packed?
612 if (relocations->empty()) { 627 if (relocations->empty()) {
613 LOG(ERROR) << "No relocations found (already packed?)"; 628 LOG(ERROR) << "No relocations found";
614 return false; 629 return false;
615 } 630 }
616 631
617 const size_t rel_size = 632 const size_t rel_size =
618 relocations_type_ == RELA ? sizeof(typename ELF::Rela) : sizeof(typename E LF::Rel); 633 relocations_type_ == RELA ? sizeof(typename ELF::Rela) : sizeof(typename E LF::Rel);
619 const size_t initial_bytes = relocations->size() * rel_size; 634 const size_t initial_bytes = relocations->size() * rel_size;
620 635
621 LOG(INFO) << "Unpacked : " << initial_bytes << " bytes"; 636 VLOG(1) << "Unpacked : " << initial_bytes << " bytes";
622 std::vector<uint8_t> packed; 637 std::vector<uint8_t> packed;
623 RelocationPacker<ELF> packer; 638 RelocationPacker<ELF> packer;
624 639
625 // Pack relocations: dry run to estimate memory savings. 640 // Pack relocations: dry run to estimate memory savings.
626 packer.PackRelocations(*relocations, &packed); 641 packer.PackRelocations(*relocations, &packed);
627 const size_t packed_bytes_estimate = packed.size() * sizeof(packed[0]); 642 const size_t packed_bytes_estimate = packed.size() * sizeof(packed[0]);
628 LOG(INFO) << "Packed (no padding): " << packed_bytes_estimate << " byt es"; 643 VLOG(1) << "Packed (no padding): " << packed_bytes_estimate << " bytes ";
629 644
630 if (packed.empty()) { 645 if (packed.empty()) {
631 LOG(INFO) << "Too few relocations to pack"; 646 LOG(INFO) << "Too few relocations to pack";
632 return false; 647 return true;
633 } 648 }
634 649
635 // Pre-calculate the size of the hole we will close up when we rewrite 650 // Pre-calculate the size of the hole we will close up when we rewrite
636 // dynamic relocations. We have to adjust relocation addresses to 651 // dynamic relocations. We have to adjust relocation addresses to
637 // account for this. 652 // account for this.
638 typename ELF::Shdr* section_header = ELF::getshdr(relocations_section_); 653 typename ELF::Shdr* section_header = ELF::getshdr(relocations_section_);
639 ssize_t hole_size = initial_bytes - packed_bytes_estimate; 654 ssize_t hole_size = initial_bytes - packed_bytes_estimate;
640 655
641 // hole_size needs to be page_aligned. 656 // hole_size needs to be page_aligned.
642 hole_size -= hole_size % kPreserveAlignment; 657 hole_size -= hole_size % kPreserveAlignment;
643 658
644 LOG(INFO) << "Compaction : " << hole_size << " bytes"; 659 LOG(INFO) << "Compaction : " << hole_size << " bytes";
645 660
646 // Adjusting for alignment may have removed any packing benefit. 661 // Adjusting for alignment may have removed any packing benefit.
647 if (hole_size == 0) { 662 if (hole_size == 0) {
648 LOG(INFO) << "Too few relocations to pack after alignment"; 663 LOG(INFO) << "Too few relocations to pack after alignment";
649 return false; 664 return true;
650 } 665 }
651 666
652 if (hole_size <= 0) { 667 if (hole_size <= 0) {
653 LOG(INFO) << "Packing relocations saves no space"; 668 LOG(INFO) << "Packing relocations saves no space";
654 return false; 669 return true;
655 } 670 }
656 671
657 size_t data_padding_bytes = is_padding_relocations_ ? 672 size_t data_padding_bytes = is_padding_relocations_ ?
658 initial_bytes - packed_bytes_estimate : 673 initial_bytes - packed_bytes_estimate :
659 initial_bytes - hole_size - packed_bytes_estimate; 674 initial_bytes - hole_size - packed_bytes_estimate;
660 675
661 // pad data 676 // pad data
662 std::vector<uint8_t> padding(data_padding_bytes, 0); 677 std::vector<uint8_t> padding(data_padding_bytes, 0);
663 packed.insert(packed.end(), padding.begin(), padding.end()); 678 packed.insert(packed.end(), padding.begin(), padding.end());
664 679
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
727 // Convert data to a vector of bytes. 742 // Convert data to a vector of bytes.
728 const uint8_t* packed_base = reinterpret_cast<uint8_t*>(data->d_buf); 743 const uint8_t* packed_base = reinterpret_cast<uint8_t*>(data->d_buf);
729 std::vector<uint8_t> packed( 744 std::vector<uint8_t> packed(
730 packed_base, 745 packed_base,
731 packed_base + data->d_size / sizeof(packed[0])); 746 packed_base + data->d_size / sizeof(packed[0]));
732 747
733 if ((section_header->sh_type == SHT_ANDROID_RELA || section_header->sh_type == SHT_ANDROID_REL) && 748 if ((section_header->sh_type == SHT_ANDROID_RELA || section_header->sh_type == SHT_ANDROID_REL) &&
734 packed.size() > 3 && 749 packed.size() > 3 &&
735 packed[0] == 'A' && 750 packed[0] == 'A' &&
736 packed[1] == 'P' && 751 packed[1] == 'P' &&
737 (packed[2] == 'U' || packed[2] == 'S') && 752 packed[2] == 'S' &&
738 packed[3] == '2') { 753 packed[3] == '2') {
739 LOG(INFO) << "Relocations : " << (relocations_type_ == REL ? "REL" : "RELA "); 754 LOG(INFO) << "Relocations : " << (relocations_type_ == REL ? "REL" : "RELA ");
740 } else { 755 } else {
741 LOG(ERROR) << "Packed relocations not found (not packed?)"; 756 LOG(ERROR) << "Packed relocations not found (not packed?)";
742 return false; 757 return false;
743 } 758 }
744 759
745 return UnpackTypedRelocations(packed); 760 return UnpackTypedRelocations(packed);
746 } 761 }
747 762
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
873 rel.r_info = rela.r_info; 888 rel.r_info = rela.r_info;
874 CHECK(rela.r_addend == 0); 889 CHECK(rela.r_addend == 0);
875 rel_vector->push_back(rel); 890 rel_vector->push_back(rel);
876 } 891 }
877 } 892 }
878 893
879 template class ElfFile<ELF32_traits>; 894 template class ElfFile<ELF32_traits>;
880 template class ElfFile<ELF64_traits>; 895 template class ElfFile<ELF64_traits>;
881 896
882 } // namespace relocation_packer 897 } // namespace relocation_packer
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698