| 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 |