summaryrefslogtreecommitdiffstats
path: root/patchoat
diff options
context:
space:
mode:
authorDavid Srbecky <dsrbecky@google.com>2015-04-11 00:17:53 +0100
committerDavid Srbecky <dsrbecky@google.com>2015-04-11 19:14:10 +0100
commit2f6cdb01f74772c1c521a125776ef57ea3c73d43 (patch)
tree163f90841f02b9529997f4e3eea65e512e4795a3 /patchoat
parent58565098b2298041ccc97371a3cc486df88d51b3 (diff)
downloadart-2f6cdb01f74772c1c521a125776ef57ea3c73d43.zip
art-2f6cdb01f74772c1c521a125776ef57ea3c73d43.tar.gz
art-2f6cdb01f74772c1c521a125776ef57ea3c73d43.tar.bz2
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')
-rw-r--r--patchoat/patchoat.cc76
-rw-r--r--patchoat/patchoat.h5
2 files changed, 1 insertions, 80 deletions
diff --git a/patchoat/patchoat.cc b/patchoat/patchoat.cc
index 74c9c38..4dc0967 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;
diff --git a/patchoat/patchoat.h b/patchoat/patchoat.h
index 418650a..86f9118 100644
--- a/patchoat/patchoat.h
+++ b/patchoat/patchoat.h
@@ -109,11 +109,6 @@ class PatchOat {
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 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_);