| Index: tools/relocation_packer/src/elf_file.cc
|
| diff --git a/tools/relocation_packer/src/elf_file.cc b/tools/relocation_packer/src/elf_file.cc
|
| index 3ffccecd7c4bc4d87a34194f7416b04b141524ee..5853c9d7d5547de5108bb3b99ce79f533d00446c 100644
|
| --- a/tools/relocation_packer/src/elf_file.cc
|
| +++ b/tools/relocation_packer/src/elf_file.cc
|
| @@ -56,6 +56,14 @@ static const ELF::Sword DT_ANDROID_REL_SIZE = DT_LOOS + 1;
|
| // page. See http://www.airs.com/blog/archives/189.
|
| static const size_t kPreserveAlignment = 4096;
|
|
|
| +// Alignment values used by ld and gold for the GNU_STACK segment. Different
|
| +// linkers write different values; the actual value is immaterial on Android
|
| +// because it ignores GNU_STACK segments. However, it is useful for binary
|
| +// comparison and unit test purposes if packing and unpacking can preserve
|
| +// them through a round-trip.
|
| +static const size_t kLdGnuStackSegmentAlignment = 16;
|
| +static const size_t kGoldGnuStackSegmentAlignment = 0;
|
| +
|
| namespace {
|
|
|
| // Get section data. Checks that the section has exactly one data entry,
|
| @@ -363,11 +371,36 @@ ELF::Phdr* FindFirstLoadSegment(ELF::Phdr* program_headers,
|
| return first_loadable_segment;
|
| }
|
|
|
| +// Helper for ResizeSection(). Deduce the alignment that the PT_GNU_STACK
|
| +// segment will use. Determined by sensing the linker that was used to
|
| +// create the shared library.
|
| +size_t DeduceGnuStackSegmentAlignment(Elf* elf) {
|
| + size_t string_index;
|
| + elf_getshdrstrndx(elf, &string_index);
|
| +
|
| + Elf_Scn* section = NULL;
|
| + size_t gnu_stack_segment_alignment = kLdGnuStackSegmentAlignment;
|
| +
|
| + while ((section = elf_nextscn(elf, section)) != NULL) {
|
| + const ELF::Shdr* section_header = ELF::getshdr(section);
|
| + std::string name = elf_strptr(elf, string_index, section_header->sh_name);
|
| +
|
| + if (name == ".note.gnu.gold-version") {
|
| + gnu_stack_segment_alignment = kGoldGnuStackSegmentAlignment;
|
| + break;
|
| + }
|
| + }
|
| +
|
| + return gnu_stack_segment_alignment;
|
| +}
|
| +
|
| // Helper for ResizeSection(). Find the PT_GNU_STACK segment, and check
|
| // that it contains what we expect so we can restore it on unpack if needed.
|
| -ELF::Phdr* FindUnusedGnuStackSegment(ELF::Phdr* program_headers,
|
| +ELF::Phdr* FindUnusedGnuStackSegment(Elf* elf,
|
| + ELF::Phdr* program_headers,
|
| size_t count) {
|
| ELF::Phdr* unused_segment = NULL;
|
| + const size_t stack_alignment = DeduceGnuStackSegmentAlignment(elf);
|
|
|
| for (size_t i = 0; i < count; ++i) {
|
| ELF::Phdr* program_header = &program_headers[i];
|
| @@ -379,7 +412,7 @@ ELF::Phdr* FindUnusedGnuStackSegment(ELF::Phdr* program_headers,
|
| program_header->p_filesz == 0 &&
|
| program_header->p_memsz == 0 &&
|
| program_header->p_flags == (PF_R | PF_W) &&
|
| - program_header->p_align == ELF::kGnuStackSegmentAlignment) {
|
| + program_header->p_align == stack_alignment) {
|
| unused_segment = program_header;
|
| }
|
| }
|
| @@ -558,7 +591,7 @@ void SplitProgramHeadersForHole(Elf* elf,
|
| // Locate the segment that we can overwrite to form the new LOAD entry,
|
| // and the segment that we are going to split into two parts.
|
| ELF::Phdr* spliced_header =
|
| - FindUnusedGnuStackSegment(elf_program_header, program_header_count);
|
| + FindUnusedGnuStackSegment(elf, elf_program_header, program_header_count);
|
| ELF::Phdr* split_header =
|
| FindFirstLoadSegment(elf_program_header, program_header_count);
|
|
|
| @@ -680,6 +713,7 @@ void CoalesceProgramHeadersForHole(Elf* elf,
|
| last_section_header->sh_offset + last_section_header->sh_size;
|
|
|
| // Reconstruct the original GNU_STACK segment into spliced_header.
|
| + const size_t stack_alignment = DeduceGnuStackSegmentAlignment(elf);
|
| spliced_header->p_type = PT_GNU_STACK;
|
| spliced_header->p_offset = 0;
|
| spliced_header->p_vaddr = 0;
|
| @@ -687,7 +721,7 @@ void CoalesceProgramHeadersForHole(Elf* elf,
|
| spliced_header->p_filesz = 0;
|
| spliced_header->p_memsz = 0;
|
| spliced_header->p_flags = PF_R | PF_W;
|
| - spliced_header->p_align = ELF::kGnuStackSegmentAlignment;
|
| + spliced_header->p_align = stack_alignment;
|
|
|
| // Adjust the offsets of all program headers that are not one of the pair
|
| // we just coalesced.
|
|
|