diff options
author | 2015-04-11 00:17:53 +0100 | |
---|---|---|
committer | 2015-04-11 19:14:10 +0100 | |
commit | 2f6cdb01f74772c1c521a125776ef57ea3c73d43 (patch) | |
tree | 163f90841f02b9529997f4e3eea65e512e4795a3 /patchoat/patchoat.cc | |
parent | 58565098b2298041ccc97371a3cc486df88d51b3 (diff) |
Relocate DWARF using .oat_patches.
The current solution is to hard-code knowledge of DWARF in the linker.
This works for simple use of DWARF, but breaks as soon as I try to do
anything more complex. Making the linker fully support DWARF would be
non-trivial task and would be essentially rewrite. Using .oat_patches
is much easier solution.
Relocating .debug_* sections required extending .oat_patches to support
more sections than just .text. I have encoded each section as
null-terminated section name followed by ULEB128 deltas.
The ULEB128 encoding shrinks .oat_patches for .text by factor of
about 6 with 64-bit compiler, and factor of 3 with 32-bit compiler.
On the other hand, it grows by the extra .oat_patches for DWARF which
were not present before (if debug symbols are included).
Overall, it is still a clear improvement even with the DWARF patches.
Change-Id: I78ffeda0f8a3da03341995a3b5ef15c954e16e9f
Diffstat (limited to 'patchoat/patchoat.cc')
-rw-r--r-- | patchoat/patchoat.cc | 76 |
1 files changed, 1 insertions, 75 deletions
diff --git a/patchoat/patchoat.cc b/patchoat/patchoat.cc index 74c9c38255..4dc0967bc0 100644 --- a/patchoat/patchoat.cc +++ b/patchoat/patchoat.cc @@ -625,35 +625,6 @@ bool PatchOat::Patch(File* input_oat, off_t delta, File* output_oat, TimingLogge return true; } -template <typename ElfFileImpl, typename ptr_t> -bool PatchOat::CheckOatFile(ElfFileImpl* oat_file) { - auto patches_sec = oat_file->FindSectionByName(".oat_patches"); - if (patches_sec->sh_type != SHT_OAT_PATCH) { - return false; - } - ptr_t* patches = reinterpret_cast<ptr_t*>(oat_file->Begin() + patches_sec->sh_offset); - ptr_t* patches_end = patches + (patches_sec->sh_size / sizeof(ptr_t)); - auto oat_data_sec = oat_file->FindSectionByName(".rodata"); - auto oat_text_sec = oat_file->FindSectionByName(".text"); - if (oat_data_sec == nullptr) { - return false; - } - if (oat_text_sec == nullptr) { - return false; - } - if (oat_text_sec->sh_offset <= oat_data_sec->sh_offset) { - return false; - } - - for (; patches < patches_end; patches++) { - if (oat_text_sec->sh_size <= *patches) { - return false; - } - } - - return true; -} - template <typename ElfFileImpl> bool PatchOat::PatchOatHeader(ElfFileImpl* oat_file) { auto rodata_sec = oat_file->FindSectionByName(".rodata"); @@ -679,7 +650,7 @@ bool PatchOat::PatchElf() { template <typename ElfFileImpl> bool PatchOat::PatchElf(ElfFileImpl* oat_file) { TimingLogger::ScopedTiming t("Fixup Elf Text Section", timings_); - if (!PatchTextSection<ElfFileImpl>(oat_file)) { + if (!oat_file->ApplyOatPatchesTo(".text", delta_)) { return false; } @@ -731,51 +702,6 @@ bool PatchOat::PatchElf(ElfFileImpl* oat_file) { return true; } -template <typename ElfFileImpl> -bool PatchOat::PatchTextSection(ElfFileImpl* oat_file) { - auto patches_sec = oat_file->FindSectionByName(".oat_patches"); - if (patches_sec == nullptr) { - LOG(ERROR) << ".oat_patches section not found. Aborting patch"; - return false; - } - if (patches_sec->sh_type != SHT_OAT_PATCH) { - LOG(ERROR) << "Unexpected type of .oat_patches"; - return false; - } - - switch (patches_sec->sh_entsize) { - case sizeof(uint32_t): - return PatchTextSection<ElfFileImpl, uint32_t>(oat_file); - case sizeof(uint64_t): - return PatchTextSection<ElfFileImpl, uint64_t>(oat_file); - default: - LOG(ERROR) << ".oat_patches Entsize of " << patches_sec->sh_entsize << "bits " - << "is not valid"; - return false; - } -} - -template <typename ElfFileImpl, typename patch_loc_t> -bool PatchOat::PatchTextSection(ElfFileImpl* oat_file) { - bool oat_file_valid = CheckOatFile<ElfFileImpl, patch_loc_t>(oat_file); - CHECK(oat_file_valid) << "Oat file invalid"; - auto patches_sec = oat_file->FindSectionByName(".oat_patches"); - patch_loc_t* patches = reinterpret_cast<patch_loc_t*>(oat_file->Begin() + patches_sec->sh_offset); - patch_loc_t* patches_end = patches + (patches_sec->sh_size / sizeof(patch_loc_t)); - auto oat_text_sec = oat_file->FindSectionByName(".text"); - CHECK(oat_text_sec != nullptr); - uint8_t* to_patch = oat_file->Begin() + oat_text_sec->sh_offset; - uintptr_t to_patch_end = reinterpret_cast<uintptr_t>(to_patch) + oat_text_sec->sh_size; - - for (; patches < patches_end; patches++) { - CHECK_LT(*patches, oat_text_sec->sh_size) << "Bad Patch"; - uint32_t* patch_loc = reinterpret_cast<uint32_t*>(to_patch + *patches); - CHECK_LT(reinterpret_cast<uintptr_t>(patch_loc), to_patch_end); - *patch_loc += delta_; - } - return true; -} - static int orig_argc; static char** orig_argv; |