diff options
author | Tong Shen <endlessroad@google.com> | 2014-09-03 17:24:56 -0700 |
---|---|---|
committer | Tong Shen <endlessroad@google.com> | 2014-10-03 11:25:11 -0700 |
commit | 62d1ca3182a6cbb921799825f43ad36821233fd7 (patch) | |
tree | 54d9663f5ce10f41e95fe774d4e4841c1a78bbc3 /patchoat | |
parent | 63462448ca4e377074a10a4720aa22f71154dbe9 (diff) | |
download | art-62d1ca3182a6cbb921799825f43ad36821233fd7.zip art-62d1ca3182a6cbb921799825f43ad36821233fd7.tar.gz art-62d1ca3182a6cbb921799825f43ad36821233fd7.tar.bz2 |
ART: Prepare for ELF64.
Only expose necessary interface in ElfFile, and move all details into template class ElfFileImpl.
Change-Id: I9df2bbc55f32ba0ba91f4f3d5d0009e84a2ddf74
Diffstat (limited to 'patchoat')
-rw-r--r-- | patchoat/patchoat.cc | 124 | ||||
-rw-r--r-- | patchoat/patchoat.h | 13 |
2 files changed, 60 insertions, 77 deletions
diff --git a/patchoat/patchoat.cc b/patchoat/patchoat.cc index 50b4ece..c457ecd 100644 --- a/patchoat/patchoat.cc +++ b/patchoat/patchoat.cc @@ -29,6 +29,7 @@ #include "base/stringprintf.h" #include "elf_utils.h" #include "elf_file.h" +#include "elf_file_impl.h" #include "gc/space/image_space.h" #include "image.h" #include "instruction_set.h" @@ -467,15 +468,16 @@ bool PatchOat::Patch(File* input_oat, off_t delta, File* output_oat, TimingLogge return true; } -template <typename ptr_t> -bool PatchOat::CheckOatFile(const Elf32_Shdr& patches_sec) { - if (patches_sec.sh_type != SHT_OAT_PATCH) { +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)); - Elf32_Shdr* oat_data_sec = oat_file_->FindSectionByName(".rodata"); - Elf32_Shdr* oat_text_sec = oat_file_->FindSectionByName(".text"); + 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; } @@ -495,14 +497,15 @@ bool PatchOat::CheckOatFile(const Elf32_Shdr& patches_sec) { return true; } -bool PatchOat::PatchOatHeader() { - Elf32_Shdr *rodata_sec = oat_file_->FindSectionByName(".rodata"); +template <typename ElfFileImpl> +bool PatchOat::PatchOatHeader(ElfFileImpl* oat_file) { + auto rodata_sec = oat_file->FindSectionByName(".rodata"); if (rodata_sec == nullptr) { return false; } - OatHeader* oat_header = reinterpret_cast<OatHeader*>(oat_file_->Begin() + rodata_sec->sh_offset); + OatHeader* oat_header = reinterpret_cast<OatHeader*>(oat_file->Begin() + rodata_sec->sh_offset); if (!oat_header->IsValid()) { - LOG(ERROR) << "Elf file " << oat_file_->GetFile().GetPath() << " has an invalid oat header"; + LOG(ERROR) << "Elf file " << oat_file->GetFile().GetPath() << " has an invalid oat header"; return false; } oat_header->RelocateOat(delta_); @@ -510,28 +513,31 @@ bool PatchOat::PatchOatHeader() { } bool PatchOat::PatchElf() { + if (oat_file_->is_elf64_) + return PatchElf<ElfFileImpl64>(oat_file_->GetImpl64()); + else + return PatchElf<ElfFileImpl32>(oat_file_->GetImpl32()); +} + +template <typename ElfFileImpl> +bool PatchOat::PatchElf(ElfFileImpl* oat_file) { TimingLogger::ScopedTiming t("Fixup Elf Text Section", timings_); - if (!PatchTextSection()) { + if (!PatchTextSection<ElfFileImpl>(oat_file)) { return false; } - if (!PatchOatHeader()) { + if (!PatchOatHeader<ElfFileImpl>(oat_file)) { return false; } bool need_fixup = false; - t.NewTiming("Fixup Elf Headers"); - // Fixup Phdr's - for (unsigned int i = 0; i < oat_file_->GetProgramHeaderNum(); i++) { - Elf32_Phdr* hdr = oat_file_->GetProgramHeader(i); - CHECK(hdr != nullptr); + for (unsigned int i = 0; i < oat_file->GetProgramHeaderNum(); i++) { + auto hdr = oat_file->GetProgramHeader(i); if (hdr->p_vaddr != 0 && hdr->p_vaddr != hdr->p_offset) { need_fixup = true; - hdr->p_vaddr += delta_; } if (hdr->p_paddr != 0 && hdr->p_paddr != hdr->p_offset) { need_fixup = true; - hdr->p_paddr += delta_; } } if (!need_fixup) { @@ -539,67 +545,39 @@ bool PatchOat::PatchElf() { // their addr. Therefore we do not need to update these parts. return true; } + + t.NewTiming("Fixup Elf Headers"); + // Fixup Phdr's + oat_file->FixupProgramHeaders(delta_); + t.NewTiming("Fixup Section Headers"); - for (unsigned int i = 0; i < oat_file_->GetSectionHeaderNum(); i++) { - Elf32_Shdr* hdr = oat_file_->GetSectionHeader(i); - CHECK(hdr != nullptr); - if (hdr->sh_addr != 0) { - hdr->sh_addr += delta_; - } - } + // Fixup Shdr's + oat_file->FixupSectionHeaders(delta_); t.NewTiming("Fixup Dynamics"); - for (Elf32_Word i = 0; i < oat_file_->GetDynamicNum(); i++) { - Elf32_Dyn& dyn = oat_file_->GetDynamic(i); - if (IsDynamicSectionPointer(dyn.d_tag, oat_file_->GetHeader().e_machine)) { - dyn.d_un.d_ptr += delta_; - } - } + oat_file->FixupDynamic(delta_); t.NewTiming("Fixup Elf Symbols"); // Fixup dynsym - Elf32_Shdr* dynsym_sec = oat_file_->FindSectionByName(".dynsym"); - CHECK(dynsym_sec != nullptr); - if (!PatchSymbols(dynsym_sec)) { + if (!oat_file->FixupSymbols(delta_, true)) { return false; } - // Fixup symtab - Elf32_Shdr* symtab_sec = oat_file_->FindSectionByName(".symtab"); - if (symtab_sec != nullptr) { - if (!PatchSymbols(symtab_sec)) { - return false; - } + if (!oat_file->FixupSymbols(delta_, false)) { + return false; } t.NewTiming("Fixup Debug Sections"); - if (!oat_file_->FixupDebugSections(delta_)) { + if (!oat_file->FixupDebugSections(delta_)) { return false; } return true; } -bool PatchOat::PatchSymbols(Elf32_Shdr* section) { - Elf32_Sym* syms = reinterpret_cast<Elf32_Sym*>(oat_file_->Begin() + section->sh_offset); - const Elf32_Sym* last_sym = - reinterpret_cast<Elf32_Sym*>(oat_file_->Begin() + section->sh_offset + section->sh_size); - CHECK_EQ(section->sh_size % sizeof(Elf32_Sym), 0u) - << "Symtab section size is not multiple of symbol size"; - for (; syms < last_sym; syms++) { - uint8_t sttype = ELF32_ST_TYPE(syms->st_info); - Elf32_Word shndx = syms->st_shndx; - if (shndx != SHN_ABS && shndx != SHN_COMMON && shndx != SHN_UNDEF && - (sttype == STT_FUNC || sttype == STT_OBJECT)) { - CHECK_NE(syms->st_value, 0u); - syms->st_value += delta_; - } - } - return true; -} - -bool PatchOat::PatchTextSection() { - Elf32_Shdr* patches_sec = oat_file_->FindSectionByName(".oat_patches"); +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; @@ -611,9 +589,9 @@ bool PatchOat::PatchTextSection() { switch (patches_sec->sh_entsize) { case sizeof(uint32_t): - return PatchTextSection<uint32_t>(*patches_sec); + return PatchTextSection<ElfFileImpl, uint32_t>(oat_file); case sizeof(uint64_t): - return PatchTextSection<uint64_t>(*patches_sec); + return PatchTextSection<ElfFileImpl, uint64_t>(oat_file); default: LOG(ERROR) << ".oat_patches Entsize of " << patches_sec->sh_entsize << "bits " << "is not valid"; @@ -621,14 +599,16 @@ bool PatchOat::PatchTextSection() { } } -template <typename ptr_t> -bool PatchOat::PatchTextSection(const Elf32_Shdr& patches_sec) { - DCHECK(CheckOatFile<ptr_t>(patches_sec)) << "Oat file invalid"; - 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)); - Elf32_Shdr* oat_text_sec = oat_file_->FindSectionByName(".text"); +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); - byte* to_patch = oat_file_->Begin() + oat_text_sec->sh_offset; + byte* 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++) { diff --git a/patchoat/patchoat.h b/patchoat/patchoat.h index 9086d58..7dd95f5 100644 --- a/patchoat/patchoat.h +++ b/patchoat/patchoat.h @@ -76,12 +76,15 @@ class PatchOat { // Patches oat in place, modifying the oat_file given to the constructor. bool PatchElf(); - bool PatchTextSection(); + template <typename ElfFileImpl> + bool PatchElf(ElfFileImpl* oat_file); + template <typename ElfFileImpl> + bool PatchTextSection(ElfFileImpl* oat_file); // Templatized version to actually do the patching with the right sized offsets. - template <typename ptr_t> bool PatchTextSection(const Elf32_Shdr& patches_sec); - template <typename ptr_t> bool CheckOatFile(const Elf32_Shdr& patches_sec); - bool PatchOatHeader(); - bool PatchSymbols(Elf32_Shdr* section); + template <typename ElfFileImpl, typename patch_loc_t> bool PatchTextSection(ElfFileImpl* oat_file); + template <typename ElfFileImpl, typename patch_loc_t> bool CheckOatFile(ElfFileImpl* oat_filec); + template <typename ElfFileImpl> + bool PatchOatHeader(ElfFileImpl* oat_file); bool PatchImage() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); |