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 ensure that code and data loads at the same addresses as before | 8 // want to ensure that code and data loads at the same addresses as before |
9 // packing, so that tools like breakpad can still match up addresses found | 9 // packing, so that tools like breakpad can still match up addresses found |
10 // in any crash dumps with data extracted from the pre-packed version of | 10 // in any crash dumps with data extracted from the pre-packed version of |
(...skipping 515 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
526 // GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0 | 526 // GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0 |
527 // | 527 // |
528 // The hole in the file is in the first of these. In order to preserve all | 528 // The hole in the file is in the first of these. In order to preserve all |
529 // load addresses, what we do is to turn the GNU_STACK into a new LOAD entry | 529 // load addresses, what we do is to turn the GNU_STACK into a new LOAD entry |
530 // that maps segments up to where we created the hole, adjust the first LOAD | 530 // that maps segments up to where we created the hole, adjust the first LOAD |
531 // entry so that it maps segments after that, adjust any other program | 531 // entry so that it maps segments after that, adjust any other program |
532 // headers whose offset is after the hole start, and finally order the LOAD | 532 // headers whose offset is after the hole start, and finally order the LOAD |
533 // segments by offset, to give: | 533 // segments by offset, to give: |
534 // | 534 // |
535 // Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align | 535 // Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align |
536 // LOAD 0x000000 0x00000000 0x00000000 0x14ea4 0x212ea4 R E 0x1000 | 536 // LOAD 0x000000 0x00000000 0x00000000 0x14ea4 0x14ea4 R E 0x1000 |
537 // LOAD 0x014ea4 0x00212ea4 0x00212ea4 0x1cea164 0x1cea164 R E 0x1000 | 537 // LOAD 0x014ea4 0x00212ea4 0x00212ea4 0x1cea164 0x1cea164 R E 0x1000 |
538 // DYNAMIC 0x1e60c50 0x0205fc50 0x0205fc50 0x00108 0x00108 RW 0x4 | 538 // DYNAMIC 0x1e60c50 0x0205fc50 0x0205fc50 0x00108 0x00108 RW 0x4 |
539 // LOAD 0x1cff008 0x01efe008 0x01efe008 0x17ec3c 0x1a0324 RW 0x1000 | 539 // LOAD 0x1cff008 0x01efe008 0x01efe008 0x17ec3c 0x1a0324 RW 0x1000 |
540 // | 540 // |
541 // We work out the split points by finding the .rel.dyn or .rela.dyn section | 541 // We work out the split points by finding the .rel.dyn or .rela.dyn section |
542 // that contains the hole, and by finding the last section in a given segment. | 542 // that contains the hole, and by finding the last section in a given segment. |
543 // | 543 // |
544 // To unpack, we reverse the above to leave the file as it was originally. | 544 // To unpack, we reverse the above to leave the file as it was originally. |
545 void SplitProgramHeadersForHole(Elf* elf, | 545 void SplitProgramHeadersForHole(Elf* elf, |
546 ELF::Off hole_start, | 546 ELF::Off hole_start, |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
586 | 586 |
587 // Split on the section following the holed one, and up to (but not | 587 // Split on the section following the holed one, and up to (but not |
588 // including) the section following the last one in the split segment. | 588 // including) the section following the last one in the split segment. |
589 Elf_Scn* split_section = elf_nextscn(elf, holed_section); | 589 Elf_Scn* split_section = elf_nextscn(elf, holed_section); |
590 LOG_IF(FATAL, !split_section) | 590 LOG_IF(FATAL, !split_section) |
591 << "No section follows the section that contains the hole"; | 591 << "No section follows the section that contains the hole"; |
592 Elf_Scn* end_section = elf_nextscn(elf, last_section); | 592 Elf_Scn* end_section = elf_nextscn(elf, last_section); |
593 LOG_IF(FATAL, !end_section) | 593 LOG_IF(FATAL, !end_section) |
594 << "No section follows the last section in the segment being split"; | 594 << "No section follows the last section in the segment being split"; |
595 | 595 |
596 // Split the first portion of split_header into spliced_header. Done | 596 // Split the first portion of split_header into spliced_header. |
597 // by copying the entire split_header into spliced_header, then changing | |
598 // only the fields that set the segment sizes. | |
599 *spliced_header = *split_header; | |
600 const ELF::Shdr* split_section_header = ELF::getshdr(split_section); | 597 const ELF::Shdr* split_section_header = ELF::getshdr(split_section); |
| 598 spliced_header->p_type = split_header->p_type; |
| 599 spliced_header->p_offset = split_header->p_offset; |
| 600 spliced_header->p_vaddr = split_header->p_vaddr; |
| 601 spliced_header->p_paddr = split_header->p_paddr; |
| 602 CHECK(split_header->p_filesz == split_header->p_memsz); |
601 spliced_header->p_filesz = split_section_header->sh_offset; | 603 spliced_header->p_filesz = split_section_header->sh_offset; |
602 spliced_header->p_memsz = split_section_header->sh_addr; | 604 spliced_header->p_memsz = split_section_header->sh_offset; |
| 605 spliced_header->p_flags = split_header->p_flags; |
| 606 spliced_header->p_align = split_header->p_align; |
603 | 607 |
604 // Now rewrite split_header to remove the part we spliced from it. | 608 // Now rewrite split_header to remove the part we spliced from it. |
605 const ELF::Shdr* end_section_header = ELF::getshdr(end_section); | 609 const ELF::Shdr* end_section_header = ELF::getshdr(end_section); |
606 split_header->p_offset = spliced_header->p_filesz; | 610 split_header->p_offset = spliced_header->p_filesz; |
607 | |
608 CHECK(split_header->p_vaddr == split_header->p_paddr); | 611 CHECK(split_header->p_vaddr == split_header->p_paddr); |
609 split_header->p_vaddr = spliced_header->p_memsz; | 612 split_header->p_vaddr = split_section_header->sh_addr; |
610 split_header->p_paddr = split_header->p_vaddr; | 613 split_header->p_paddr = split_section_header->sh_addr; |
611 | |
612 CHECK(split_header->p_filesz == split_header->p_memsz); | 614 CHECK(split_header->p_filesz == split_header->p_memsz); |
613 split_header->p_filesz = | 615 split_header->p_filesz = |
614 end_section_header->sh_offset - spliced_header->p_filesz; | 616 end_section_header->sh_offset - spliced_header->p_filesz; |
615 split_header->p_memsz = split_header->p_filesz; | 617 split_header->p_memsz = |
| 618 end_section_header->sh_offset - spliced_header->p_filesz; |
616 | 619 |
617 // Adjust the offsets of all program headers that are not one of the pair | 620 // Adjust the offsets of all program headers that are not one of the pair |
618 // we just created by splitting. | 621 // we just created by splitting. |
619 AdjustProgramHeaderOffsets(elf_program_header, | 622 AdjustProgramHeaderOffsets(elf_program_header, |
620 program_header_count, | 623 program_header_count, |
621 spliced_header, | 624 spliced_header, |
622 split_header, | 625 split_header, |
623 hole_start, | 626 hole_start, |
624 hole_size); | 627 hole_size); |
625 | 628 |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
659 size_t string_index; | 662 size_t string_index; |
660 elf_getshdrstrndx(elf, &string_index); | 663 elf_getshdrstrndx(elf, &string_index); |
661 | 664 |
662 const ELF::Shdr* section_header = ELF::getshdr(last_section); | 665 const ELF::Shdr* section_header = ELF::getshdr(last_section); |
663 std::string name = elf_strptr(elf, string_index, section_header->sh_name); | 666 std::string name = elf_strptr(elf, string_index, section_header->sh_name); |
664 VLOG(1) << "section " << name << " coalesced"; | 667 VLOG(1) << "section " << name << " coalesced"; |
665 | 668 |
666 // Rewrite the coalesced segment into split_header. | 669 // Rewrite the coalesced segment into split_header. |
667 const ELF::Shdr* last_section_header = ELF::getshdr(last_section); | 670 const ELF::Shdr* last_section_header = ELF::getshdr(last_section); |
668 split_header->p_offset = spliced_header->p_offset; | 671 split_header->p_offset = spliced_header->p_offset; |
| 672 CHECK(split_header->p_vaddr == split_header->p_paddr); |
669 split_header->p_vaddr = spliced_header->p_vaddr; | 673 split_header->p_vaddr = spliced_header->p_vaddr; |
670 split_header->p_paddr = split_header->p_vaddr; | 674 split_header->p_paddr = spliced_header->p_vaddr; |
| 675 CHECK(split_header->p_filesz == split_header->p_memsz); |
671 split_header->p_filesz = | 676 split_header->p_filesz = |
672 last_section_header->sh_offset + last_section_header->sh_size; | 677 last_section_header->sh_offset + last_section_header->sh_size; |
673 split_header->p_memsz = split_header->p_filesz; | 678 split_header->p_memsz = |
| 679 last_section_header->sh_offset + last_section_header->sh_size; |
674 | 680 |
675 // Reconstruct the original GNU_STACK segment into spliced_header. | 681 // Reconstruct the original GNU_STACK segment into spliced_header. |
676 spliced_header->p_type = PT_GNU_STACK; | 682 spliced_header->p_type = PT_GNU_STACK; |
677 spliced_header->p_offset = 0; | 683 spliced_header->p_offset = 0; |
678 spliced_header->p_vaddr = 0; | 684 spliced_header->p_vaddr = 0; |
679 spliced_header->p_paddr = 0; | 685 spliced_header->p_paddr = 0; |
680 spliced_header->p_filesz = 0; | 686 spliced_header->p_filesz = 0; |
681 spliced_header->p_memsz = 0; | 687 spliced_header->p_memsz = 0; |
682 spliced_header->p_flags = PF_R | PF_W; | 688 spliced_header->p_flags = PF_R | PF_W; |
683 spliced_header->p_align = ELF::kGnuStackSegmentAlignment; | 689 spliced_header->p_align = ELF::kGnuStackSegmentAlignment; |
(...skipping 593 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1277 | 1283 |
1278 // Clean up libelf, and truncate the output file to the number of bytes | 1284 // Clean up libelf, and truncate the output file to the number of bytes |
1279 // written by elf_update(). | 1285 // written by elf_update(). |
1280 elf_end(elf_); | 1286 elf_end(elf_); |
1281 elf_ = NULL; | 1287 elf_ = NULL; |
1282 const int truncate = ftruncate(fd_, file_bytes); | 1288 const int truncate = ftruncate(fd_, file_bytes); |
1283 CHECK(truncate == 0); | 1289 CHECK(truncate == 0); |
1284 } | 1290 } |
1285 | 1291 |
1286 } // namespace relocation_packer | 1292 } // namespace relocation_packer |
OLD | NEW |