summaryrefslogtreecommitdiffstats
path: root/patchoat
diff options
context:
space:
mode:
authorTong Shen <endlessroad@google.com>2014-09-03 17:24:56 -0700
committerTong Shen <endlessroad@google.com>2014-10-03 11:25:11 -0700
commit62d1ca3182a6cbb921799825f43ad36821233fd7 (patch)
tree54d9663f5ce10f41e95fe774d4e4841c1a78bbc3 /patchoat
parent63462448ca4e377074a10a4720aa22f71154dbe9 (diff)
downloadart-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.cc124
-rw-r--r--patchoat/patchoat.h13
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_);