OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |