diff options
author | simonb <simonb@chromium.org> | 2015-05-28 10:35:27 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-05-28 17:35:55 +0000 |
commit | 9cb10e88d01e71c5786a463f7c39409e7a41ddcd (patch) | |
tree | 42f3fd48377efff161d8abc8f64513f172a62192 /third_party/android_platform | |
parent | 9bacad65abe3631048c1e5d0467e1cea414e5700 (diff) | |
download | chromium_src-9cb10e88d01e71c5786a463f7c39409e7a41ddcd.zip chromium_src-9cb10e88d01e71c5786a463f7c39409e7a41ddcd.tar.gz chromium_src-9cb10e88d01e71c5786a463f7c39409e7a41ddcd.tar.bz2 |
Refresh android relocation packer from AOSP bionic.
Imports:
Fix unit tests, and extend for other architectures
https://android-review.googlesource.com/#/c/151901/
Do not adjust PT_GNU_STACK segment
https://android-review.googlesource.com/#/c/149300/
Adjust DT_MIPS_RLD_MAP2 value
https://android-review.googlesource.com/#/c/148822/
Reduce p_align for program header to page size.
https://android-review.googlesource.com/#/c/148492/
Exit normally when relocations are already packed.
https://android-review.googlesource.com/#/c/148175/
NOPRESUBMIT=true
BUG=385553
Review URL: https://codereview.chromium.org/1164453002
Cr-Commit-Position: refs/heads/master@{#331808}
Diffstat (limited to 'third_party/android_platform')
16 files changed, 163 insertions, 20 deletions
diff --git a/third_party/android_platform/README.chromium b/third_party/android_platform/README.chromium index 1dea3b60..192b9d6 100644 --- a/third_party/android_platform/README.chromium +++ b/third_party/android_platform/README.chromium @@ -40,7 +40,13 @@ Android relocation packing tool details: Create a nativehelper/ScopedFd.h to satisfy inclusion from main.cc Create gyp build Create gn build (currently packer only; no unit tests) - Apply https://android-review.googlesource.com/#/c/143878/ - Apply https://android-review.googlesource.com/#/c/147620/ - https://android-review.googlesource.com/#/c/147745/ - https://android-review.googlesource.com/#/c/148073/ + List of bionic changes currently included: + Refresh: https://android-review.googlesource.com/#/c/143878/ + Refresh: https://android-review.googlesource.com/#/c/147620/ + https://android-review.googlesource.com/#/c/147745/ + https://android-review.googlesource.com/#/c/148073/ + Refresh: https://android-review.googlesource.com/#/c/151901/ + https://android-review.googlesource.com/#/c/149300/ + https://android-review.googlesource.com/#/c/148822/ + https://android-review.googlesource.com/#/c/148492/ + https://android-review.googlesource.com/#/c/148175/ diff --git a/third_party/android_platform/bionic/tools/relocation_packer/Android.mk b/third_party/android_platform/bionic/tools/relocation_packer/Android.mk index 99a39c0..94c946c 100644 --- a/third_party/android_platform/bionic/tools/relocation_packer/Android.mk +++ b/third_party/android_platform/bionic/tools/relocation_packer/Android.mk @@ -26,7 +26,6 @@ LOCAL_SRC_FILES := \ src/debug.cc \ src/delta_encoder.cc \ src/elf_file.cc \ - src/leb128.cc \ src/packer.cc \ src/sleb128.cc \ @@ -46,6 +45,9 @@ LOCAL_CPP_EXTENSION := .cc LOCAL_SRC_FILES := src/main.cc LOCAL_STATIC_LIBRARIES := lib_relocation_packer libelf + +# Statically linking libc++ to make it work from prebuilts +LOCAL_CXX_STL := libc++_static LOCAL_C_INCLUDES := external/elfutils/src/libelf libnativehelper/include LOCAL_MODULE := relocation_packer @@ -64,7 +66,6 @@ LOCAL_SRC_FILES := \ src/debug_unittest.cc \ src/delta_encoder_unittest.cc \ src/elf_file_unittest.cc \ - src/leb128_unittest.cc \ src/sleb128_unittest.cc \ src/packer_unittest.cc \ @@ -94,3 +95,9 @@ $(eval $(call copy-test-library,elf_file_unittest_relocs_arm32.so)) $(eval $(call copy-test-library,elf_file_unittest_relocs_arm32_packed.so)) $(eval $(call copy-test-library,elf_file_unittest_relocs_arm64.so)) $(eval $(call copy-test-library,elf_file_unittest_relocs_arm64_packed.so)) +$(eval $(call copy-test-library,elf_file_unittest_relocs_ia32.so)) +$(eval $(call copy-test-library,elf_file_unittest_relocs_ia32_packed.so)) +$(eval $(call copy-test-library,elf_file_unittest_relocs_x64.so)) +$(eval $(call copy-test-library,elf_file_unittest_relocs_x64_packed.so)) +$(eval $(call copy-test-library,elf_file_unittest_relocs_mips32.so)) +$(eval $(call copy-test-library,elf_file_unittest_relocs_mips32_packed.so)) diff --git a/third_party/android_platform/bionic/tools/relocation_packer/src/elf_file.cc b/third_party/android_platform/bionic/tools/relocation_packer/src/elf_file.cc index fb74233..4004239 100644 --- a/third_party/android_platform/bionic/tools/relocation_packer/src/elf_file.cc +++ b/third_party/android_platform/bionic/tools/relocation_packer/src/elf_file.cc @@ -37,11 +37,13 @@ static constexpr int32_t DT_ANDROID_RELASZ = DT_LOOS + 5; static constexpr uint32_t SHT_ANDROID_REL = SHT_LOOS + 1; static constexpr uint32_t SHT_ANDROID_RELA = SHT_LOOS + 2; +static const size_t kPageSize = 4096; + // Alignment to preserve, in bytes. This must be at least as large as the // largest d_align and sh_addralign values found in the loaded file. // Out of caution for RELRO page alignment, we preserve to a complete target // page. See http://www.airs.com/blog/archives/189. -static constexpr size_t kPreserveAlignment = 4096; +static const size_t kPreserveAlignment = kPageSize; // Get section data. Checks that the section has exactly one data entry, // so that the section size and the data size are the same. True in @@ -300,16 +302,85 @@ static void AdjustSectionHeadersForHole(Elf* elf, } } -// Helper for ResizeSection(). Adjust the offsets of any program headers -// that have offsets currently beyond the hole start. +// Helpers for ResizeSection(). On packing, reduce p_align for LOAD segments +// to 4kb if larger. On unpacking, restore p_align for LOAD segments if +// packing reduced it to 4kb. Return true if p_align was changed. +template <typename ELF> +static bool ClampLoadSegmentAlignment(typename ELF::Phdr* program_header) { + CHECK(program_header->p_type == PT_LOAD); + + // If large, reduce p_align for a LOAD segment to page size on packing. + if (program_header->p_align > kPageSize) { + program_header->p_align = kPageSize; + return true; + } + return false; +} + template <typename ELF> -static void AdjustProgramHeaderOffsets(typename ELF::Phdr* program_headers, +static bool RestoreLoadSegmentAlignment(typename ELF::Phdr* program_headers, + size_t count, + typename ELF::Phdr* program_header) { + CHECK(program_header->p_type == PT_LOAD); + + // If p_align was reduced on packing, restore it to its previous value + // on unpacking. We do this by searching for a different LOAD segment + // and setting p_align to that of the other LOAD segment found. + // + // Relies on the following observations: + // - a packable ELF executable has more than one LOAD segment; + // - before packing all LOAD segments have the same p_align; + // - on packing we reduce only one LOAD segment's p_align. + if (program_header->p_align == kPageSize) { + for (size_t i = 0; i < count; ++i) { + typename ELF::Phdr* other_header = &program_headers[i]; + if (other_header->p_type == PT_LOAD && other_header != program_header) { + program_header->p_align = other_header->p_align; + return true; + } + } + LOG(WARNING) << "Cannot find a LOAD segment from which to restore p_align"; + } + return false; +} + +template <typename ELF> +static bool AdjustLoadSegmentAlignment(typename ELF::Phdr* program_headers, size_t count, - typename ELF::Off hole_start, + typename ELF::Phdr* program_header, ssize_t hole_size) { + CHECK(program_header->p_type == PT_LOAD); + + bool status = false; + if (hole_size < 0) { + status = ClampLoadSegmentAlignment<ELF>(program_header); + } else if (hole_size > 0) { + status = RestoreLoadSegmentAlignment<ELF>(program_headers, + count, + program_header); + } + return status; +} + +// Helper for ResizeSection(). Adjust the offsets of any program headers +// that have offsets currently beyond the hole start, and adjust the +// virtual and physical addrs (and perhaps alignment) of the others. +template <typename ELF> +static void AdjustProgramHeaderFields(typename ELF::Phdr* program_headers, + size_t count, + typename ELF::Off hole_start, + ssize_t hole_size) { + int alignment_changes = 0; for (size_t i = 0; i < count; ++i) { typename ELF::Phdr* program_header = &program_headers[i]; + // Do not adjust PT_GNU_STACK - it confuses gdb and results + // in incorrect unwinding if the executable is stripped after + // packing. + if (program_header->p_type == PT_GNU_STACK) { + continue; + } + if (program_header->p_offset > hole_start) { // The hole start is past this segment, so adjust offset. program_header->p_offset += hole_size; @@ -318,9 +389,24 @@ static void AdjustProgramHeaderOffsets(typename ELF::Phdr* program_headers, } else { program_header->p_vaddr -= hole_size; program_header->p_paddr -= hole_size; + + // If packing, clamp LOAD segment alignment to 4kb to prevent strip + // from adjusting it unnecessarily if run on a packed file. If + // unpacking, attempt to restore a reduced alignment to its previous + // value. Ensure that we do this on at most one LOAD segment. + if (program_header->p_type == PT_LOAD) { + alignment_changes += AdjustLoadSegmentAlignment<ELF>(program_headers, + count, + program_header, + hole_size); + LOG_IF(FATAL, alignment_changes > 1) + << "Changed p_align on more than one LOAD segment"; + } + VLOG(1) << "phdr[" << i << "] p_vaddr adjusted to "<< program_header->p_vaddr - << "; p_paddr adjusted to "<< program_header->p_paddr; + << "; p_paddr adjusted to "<< program_header->p_paddr + << "; p_align adjusted to "<< program_header->p_align; } } } @@ -370,10 +456,10 @@ static void RewriteProgramHeadersForHole(Elf* elf, target_load_header->p_memsz += hole_size; // Adjust the offsets and p_vaddrs - AdjustProgramHeaderOffsets<ELF>(elf_program_header, - program_header_count, - hole_start, - hole_size); + AdjustProgramHeaderFields<ELF>(elf_program_header, + program_header_count, + hole_start, + hole_size); } // Helper for ResizeSection(). Locate and return the dynamic section. @@ -466,6 +552,16 @@ void ElfFile<ELF>::AdjustDynamicSectionForHole(Elf_Scn* dynamic_section, << " d_val adjusted to " << dynamic->d_un.d_val; } + // Special case: DT_MIPS_RLD_MAP2 stores the difference between dynamic + // entry address and the address of the _r_debug (used by GDB) + // since the dynamic section and target address are on the + // different sides of the hole it needs to be adjusted accordingly + if (tag == DT_MIPS_RLD_MAP2) { + dynamic->d_un.d_val += hole_size; + VLOG(1) << "dynamic[" << i << "] " << dynamic->d_tag + << " d_val adjusted to " << dynamic->d_un.d_val; + } + // Ignore DT_RELCOUNT and DT_RELACOUNT: (1) nobody uses them and // technically (2) the relative relocation count is not changed. @@ -618,8 +714,8 @@ bool ElfFile<ELF>::PackTypedRelocations(std::vector<typename ELF::Rela>* relocat typedef typename ELF::Rela Rela; if (has_android_relocations_) { - LOG(ERROR) << "Relocation table is already packed"; - return false; + LOG(INFO) << "Relocation table is already packed"; + return true; } // If no relocations then we have nothing packable. Perhaps diff --git a/third_party/android_platform/bionic/tools/relocation_packer/src/elf_file_unittest.cc b/third_party/android_platform/bionic/tools/relocation_packer/src/elf_file_unittest.cc index 5271eef..d5c8918 100644 --- a/third_party/android_platform/bionic/tools/relocation_packer/src/elf_file_unittest.cc +++ b/third_party/android_platform/bionic/tools/relocation_packer/src/elf_file_unittest.cc @@ -103,8 +103,8 @@ template <typename ELF> static void ProcessUnpack(FILE* relocs_so, FILE* packed_relocs_so) { relocation_packer::ElfFile<ELF> elf_file(fileno(packed_relocs_so)); - // Ensure packing fails (already packed). - EXPECT_FALSE(elf_file.PackRelocations()); + // Ensure packing already packed elf-file does not fail the build. + EXPECT_TRUE(elf_file.PackRelocations()); // Unpack golden relocations, and check files are now identical. EXPECT_TRUE(elf_file.UnpackRelocations()); @@ -183,6 +183,18 @@ TEST(ElfFile, PackRelocationsArm64) { RunPackRelocationsTestFor("arm64"); } +TEST(ElfFile, PackRelocationsMips32) { + RunPackRelocationsTestFor("mips32"); +} + +TEST(ElfFile, PackRelocationsIa32) { + RunPackRelocationsTestFor("ia32"); +} + +TEST(ElfFile, PackRelocationsX64) { + RunPackRelocationsTestFor("x64"); +} + TEST(ElfFile, UnpackRelocationsArm32) { RunUnpackRelocationsTestFor("arm32"); } @@ -191,4 +203,16 @@ TEST(ElfFile, UnpackRelocationsArm64) { RunUnpackRelocationsTestFor("arm64"); } +TEST(ElfFile, UnpackRelocationsMips32) { + RunUnpackRelocationsTestFor("mips32"); +} + +TEST(ElfFile, UnpackRelocationsIa32) { + RunUnpackRelocationsTestFor("ia32"); +} + +TEST(ElfFile, UnpackRelocationsX64) { + RunUnpackRelocationsTestFor("x64"); +} + } // namespace relocation_packer diff --git a/third_party/android_platform/bionic/tools/relocation_packer/src/elf_traits.h b/third_party/android_platform/bionic/tools/relocation_packer/src/elf_traits.h index 41b06c8..1c938fa 100644 --- a/third_party/android_platform/bionic/tools/relocation_packer/src/elf_traits.h +++ b/third_party/android_platform/bionic/tools/relocation_packer/src/elf_traits.h @@ -10,6 +10,10 @@ #include "elf.h" #include "libelf.h" +#if !defined(DT_MIPS_RLD_MAP2) +#define DT_MIPS_RLD_MAP2 0x70000035 +#endif + // ELF is a traits structure used to provide convenient aliases for // 32/64 bit Elf types and functions, depending on the target file. diff --git a/third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_arm32.so b/third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_arm32.so Binary files differindex 6ce6d0c..5e339ae 100755 --- a/third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_arm32.so +++ b/third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_arm32.so diff --git a/third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_arm32_packed.so b/third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_arm32_packed.so Binary files differindex 6ac2eef..253dd97 100755 --- a/third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_arm32_packed.so +++ b/third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_arm32_packed.so diff --git a/third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_arm64.so b/third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_arm64.so Binary files differindex 945b450..d3d0194 100755 --- a/third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_arm64.so +++ b/third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_arm64.so diff --git a/third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_arm64_packed.so b/third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_arm64_packed.so Binary files differindex a2b0039..269b975 100755 --- a/third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_arm64_packed.so +++ b/third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_arm64_packed.so diff --git a/third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_ia32.so b/third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_ia32.so Binary files differnew file mode 100644 index 0000000..42db62c --- /dev/null +++ b/third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_ia32.so diff --git a/third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_ia32_packed.so b/third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_ia32_packed.so Binary files differnew file mode 100644 index 0000000..27817cc --- /dev/null +++ b/third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_ia32_packed.so diff --git a/third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_mips32.so b/third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_mips32.so Binary files differnew file mode 100644 index 0000000..6da324b --- /dev/null +++ b/third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_mips32.so diff --git a/third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_mips32_packed.so b/third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_mips32_packed.so Binary files differnew file mode 100644 index 0000000..b11ca48 --- /dev/null +++ b/third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_mips32_packed.so diff --git a/third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_x64.so b/third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_x64.so Binary files differnew file mode 100644 index 0000000..6cb689e --- /dev/null +++ b/third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_x64.so diff --git a/third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_x64_packed.so b/third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_x64_packed.so Binary files differnew file mode 100644 index 0000000..60b9ad1 --- /dev/null +++ b/third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_x64_packed.so diff --git a/third_party/android_platform/relocation_packer.gyp b/third_party/android_platform/relocation_packer.gyp index a41253f..cb09841 100644 --- a/third_party/android_platform/relocation_packer.gyp +++ b/third_party/android_platform/relocation_packer.gyp @@ -73,6 +73,12 @@ 'bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_arm32_packed.so', 'bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_arm64.so', 'bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_arm64_packed.so', + 'bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_ia32.so', + 'bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_ia32_packed.so', + 'bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_x64.so', + 'bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_x64_packed.so', + 'bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_mips32.so', + 'bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_mips32_packed.so', ], }, ], |