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

Side by Side Diff: tools/relocation_packer/src/elf_file.cc

Issue 935333002: Update from https://crrev.com/316786 (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 5 years, 10 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 | « tools/relocation_packer/src/debug.h ('k') | tools/relocation_packer/src/elf_traits.h » ('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 // 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 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
49 // android packed relocations section. 49 // android packed relocations section.
50 static const ELF::Sword DT_ANDROID_REL_OFFSET = DT_LOOS; 50 static const ELF::Sword DT_ANDROID_REL_OFFSET = DT_LOOS;
51 static const ELF::Sword DT_ANDROID_REL_SIZE = DT_LOOS + 1; 51 static const ELF::Sword DT_ANDROID_REL_SIZE = DT_LOOS + 1;
52 52
53 // Alignment to preserve, in bytes. This must be at least as large as the 53 // Alignment to preserve, in bytes. This must be at least as large as the
54 // largest d_align and sh_addralign values found in the loaded file. 54 // largest d_align and sh_addralign values found in the loaded file.
55 // Out of caution for RELRO page alignment, we preserve to a complete target 55 // Out of caution for RELRO page alignment, we preserve to a complete target
56 // page. See http://www.airs.com/blog/archives/189. 56 // page. See http://www.airs.com/blog/archives/189.
57 static const size_t kPreserveAlignment = 4096; 57 static const size_t kPreserveAlignment = 4096;
58 58
59 // Alignment values used by ld and gold for the GNU_STACK segment. Different
60 // linkers write different values; the actual value is immaterial on Android
61 // because it ignores GNU_STACK segments. However, it is useful for binary
62 // comparison and unit test purposes if packing and unpacking can preserve
63 // them through a round-trip.
64 static const size_t kLdGnuStackSegmentAlignment = 16;
65 static const size_t kGoldGnuStackSegmentAlignment = 0;
66
59 namespace { 67 namespace {
60 68
61 // Get section data. Checks that the section has exactly one data entry, 69 // Get section data. Checks that the section has exactly one data entry,
62 // so that the section size and the data size are the same. True in 70 // so that the section size and the data size are the same. True in
63 // practice for all sections we resize when packing or unpacking. Done 71 // practice for all sections we resize when packing or unpacking. Done
64 // by ensuring that a call to elf_getdata(section, data) returns NULL as 72 // by ensuring that a call to elf_getdata(section, data) returns NULL as
65 // the next data entry. 73 // the next data entry.
66 Elf_Data* GetSectionData(Elf_Scn* section) { 74 Elf_Data* GetSectionData(Elf_Scn* section) {
67 Elf_Data* data = elf_getdata(section, NULL); 75 Elf_Data* data = elf_getdata(section, NULL);
68 CHECK(data && elf_getdata(section, data) == NULL); 76 CHECK(data && elf_getdata(section, data) == NULL);
(...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after
356 program_header->p_paddr == 0) { 364 program_header->p_paddr == 0) {
357 first_loadable_segment = program_header; 365 first_loadable_segment = program_header;
358 } 366 }
359 } 367 }
360 LOG_IF(FATAL, !first_loadable_segment) 368 LOG_IF(FATAL, !first_loadable_segment)
361 << "Cannot locate a LOAD segment with address and offset zero"; 369 << "Cannot locate a LOAD segment with address and offset zero";
362 370
363 return first_loadable_segment; 371 return first_loadable_segment;
364 } 372 }
365 373
374 // Helper for ResizeSection(). Deduce the alignment that the PT_GNU_STACK
375 // segment will use. Determined by sensing the linker that was used to
376 // create the shared library.
377 size_t DeduceGnuStackSegmentAlignment(Elf* elf) {
378 size_t string_index;
379 elf_getshdrstrndx(elf, &string_index);
380
381 Elf_Scn* section = NULL;
382 size_t gnu_stack_segment_alignment = kLdGnuStackSegmentAlignment;
383
384 while ((section = elf_nextscn(elf, section)) != NULL) {
385 const ELF::Shdr* section_header = ELF::getshdr(section);
386 std::string name = elf_strptr(elf, string_index, section_header->sh_name);
387
388 if (name == ".note.gnu.gold-version") {
389 gnu_stack_segment_alignment = kGoldGnuStackSegmentAlignment;
390 break;
391 }
392 }
393
394 return gnu_stack_segment_alignment;
395 }
396
366 // Helper for ResizeSection(). Find the PT_GNU_STACK segment, and check 397 // Helper for ResizeSection(). Find the PT_GNU_STACK segment, and check
367 // that it contains what we expect so we can restore it on unpack if needed. 398 // that it contains what we expect so we can restore it on unpack if needed.
368 ELF::Phdr* FindUnusedGnuStackSegment(ELF::Phdr* program_headers, 399 ELF::Phdr* FindUnusedGnuStackSegment(Elf* elf,
400 ELF::Phdr* program_headers,
369 size_t count) { 401 size_t count) {
370 ELF::Phdr* unused_segment = NULL; 402 ELF::Phdr* unused_segment = NULL;
403 const size_t stack_alignment = DeduceGnuStackSegmentAlignment(elf);
371 404
372 for (size_t i = 0; i < count; ++i) { 405 for (size_t i = 0; i < count; ++i) {
373 ELF::Phdr* program_header = &program_headers[i]; 406 ELF::Phdr* program_header = &program_headers[i];
374 407
375 if (program_header->p_type == PT_GNU_STACK && 408 if (program_header->p_type == PT_GNU_STACK &&
376 program_header->p_offset == 0 && 409 program_header->p_offset == 0 &&
377 program_header->p_vaddr == 0 && 410 program_header->p_vaddr == 0 &&
378 program_header->p_paddr == 0 && 411 program_header->p_paddr == 0 &&
379 program_header->p_filesz == 0 && 412 program_header->p_filesz == 0 &&
380 program_header->p_memsz == 0 && 413 program_header->p_memsz == 0 &&
381 program_header->p_flags == (PF_R | PF_W) && 414 program_header->p_flags == (PF_R | PF_W) &&
382 program_header->p_align == ELF::kGnuStackSegmentAlignment) { 415 program_header->p_align == stack_alignment) {
383 unused_segment = program_header; 416 unused_segment = program_header;
384 } 417 }
385 } 418 }
386 LOG_IF(FATAL, !unused_segment) 419 LOG_IF(FATAL, !unused_segment)
387 << "Cannot locate the expected GNU_STACK segment"; 420 << "Cannot locate the expected GNU_STACK segment";
388 421
389 return unused_segment; 422 return unused_segment;
390 } 423 }
391 424
392 // Helper for ResizeSection(). Find the segment that was the first loadable 425 // Helper for ResizeSection(). Find the segment that was the first loadable
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
551 CHECK(elf_header); 584 CHECK(elf_header);
552 585
553 ELF::Phdr* elf_program_header = ELF::getphdr(elf); 586 ELF::Phdr* elf_program_header = ELF::getphdr(elf);
554 CHECK(elf_program_header); 587 CHECK(elf_program_header);
555 588
556 const size_t program_header_count = elf_header->e_phnum; 589 const size_t program_header_count = elf_header->e_phnum;
557 590
558 // Locate the segment that we can overwrite to form the new LOAD entry, 591 // Locate the segment that we can overwrite to form the new LOAD entry,
559 // and the segment that we are going to split into two parts. 592 // and the segment that we are going to split into two parts.
560 ELF::Phdr* spliced_header = 593 ELF::Phdr* spliced_header =
561 FindUnusedGnuStackSegment(elf_program_header, program_header_count); 594 FindUnusedGnuStackSegment(elf, elf_program_header, program_header_count);
562 ELF::Phdr* split_header = 595 ELF::Phdr* split_header =
563 FindFirstLoadSegment(elf_program_header, program_header_count); 596 FindFirstLoadSegment(elf_program_header, program_header_count);
564 597
565 VLOG(1) << "phdr[" << split_header - elf_program_header << "] split"; 598 VLOG(1) << "phdr[" << split_header - elf_program_header << "] split";
566 VLOG(1) << "phdr[" << spliced_header - elf_program_header << "] new LOAD"; 599 VLOG(1) << "phdr[" << spliced_header - elf_program_header << "] new LOAD";
567 600
568 // Find the section that contains the hole. We split on the section that 601 // Find the section that contains the hole. We split on the section that
569 // follows it. 602 // follows it.
570 Elf_Scn* holed_section = 603 Elf_Scn* holed_section =
571 FindSectionContainingHole(elf, hole_start, hole_size); 604 FindSectionContainingHole(elf, hole_start, hole_size);
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
673 CHECK(split_header->p_vaddr == split_header->p_paddr); 706 CHECK(split_header->p_vaddr == split_header->p_paddr);
674 split_header->p_vaddr = spliced_header->p_vaddr; 707 split_header->p_vaddr = spliced_header->p_vaddr;
675 split_header->p_paddr = spliced_header->p_vaddr; 708 split_header->p_paddr = spliced_header->p_vaddr;
676 CHECK(split_header->p_filesz == split_header->p_memsz); 709 CHECK(split_header->p_filesz == split_header->p_memsz);
677 split_header->p_filesz = 710 split_header->p_filesz =
678 last_section_header->sh_offset + last_section_header->sh_size; 711 last_section_header->sh_offset + last_section_header->sh_size;
679 split_header->p_memsz = 712 split_header->p_memsz =
680 last_section_header->sh_offset + last_section_header->sh_size; 713 last_section_header->sh_offset + last_section_header->sh_size;
681 714
682 // Reconstruct the original GNU_STACK segment into spliced_header. 715 // Reconstruct the original GNU_STACK segment into spliced_header.
716 const size_t stack_alignment = DeduceGnuStackSegmentAlignment(elf);
683 spliced_header->p_type = PT_GNU_STACK; 717 spliced_header->p_type = PT_GNU_STACK;
684 spliced_header->p_offset = 0; 718 spliced_header->p_offset = 0;
685 spliced_header->p_vaddr = 0; 719 spliced_header->p_vaddr = 0;
686 spliced_header->p_paddr = 0; 720 spliced_header->p_paddr = 0;
687 spliced_header->p_filesz = 0; 721 spliced_header->p_filesz = 0;
688 spliced_header->p_memsz = 0; 722 spliced_header->p_memsz = 0;
689 spliced_header->p_flags = PF_R | PF_W; 723 spliced_header->p_flags = PF_R | PF_W;
690 spliced_header->p_align = ELF::kGnuStackSegmentAlignment; 724 spliced_header->p_align = stack_alignment;
691 725
692 // Adjust the offsets of all program headers that are not one of the pair 726 // Adjust the offsets of all program headers that are not one of the pair
693 // we just coalesced. 727 // we just coalesced.
694 AdjustProgramHeaderOffsets(elf_program_header, 728 AdjustProgramHeaderOffsets(elf_program_header,
695 program_header_count, 729 program_header_count,
696 spliced_header, 730 spliced_header,
697 split_header, 731 split_header,
698 hole_start, 732 hole_start,
699 hole_size); 733 hole_size);
700 734
(...skipping 573 matching lines...) Expand 10 before | Expand all | Expand 10 after
1274 1308
1275 // Clean up libelf, and truncate the output file to the number of bytes 1309 // Clean up libelf, and truncate the output file to the number of bytes
1276 // written by elf_update(). 1310 // written by elf_update().
1277 elf_end(elf_); 1311 elf_end(elf_);
1278 elf_ = NULL; 1312 elf_ = NULL;
1279 const int truncate = ftruncate(fd_, file_bytes); 1313 const int truncate = ftruncate(fd_, file_bytes);
1280 CHECK(truncate == 0); 1314 CHECK(truncate == 0);
1281 } 1315 }
1282 1316
1283 } // namespace relocation_packer 1317 } // namespace relocation_packer
OLDNEW
« no previous file with comments | « tools/relocation_packer/src/debug.h ('k') | tools/relocation_packer/src/elf_traits.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698