From 57d27334bcb9ea95c969be70d8d93eb1a9c72b41 Mon Sep 17 00:00:00 2001 From: Mathieu Chartier Date: Thu, 29 May 2014 10:19:19 -0700 Subject: Add support for relative patching to quick offsets. We now have support for patching relative patches to quick offsets (interpreter bridge, generic trampoline). This fixes an issue where the compiler was generating relative branches to methods but then later deciding to not compile them, we now properly patch these in the image writer. Credits: agampe for help. Bug: 15283931 Change-Id: I3ea5278b39def6c442432fb14103a91c6eae6d0f --- compiler/image_writer.cc | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) (limited to 'compiler') diff --git a/compiler/image_writer.cc b/compiler/image_writer.cc index be53926ac8..e909c97f64 100644 --- a/compiler/image_writer.cc +++ b/compiler/image_writer.cc @@ -742,30 +742,42 @@ void ImageWriter::PatchOatCodeAndMethods() { const CompilerDriver::CallPatchInformation* patch = code_to_patch[i]; ArtMethod* target = GetTargetMethod(patch); uintptr_t quick_code = reinterpret_cast(class_linker->GetQuickOatCodeFor(target)); + DCHECK_NE(quick_code, 0U) << PrettyMethod(target); uintptr_t code_base = reinterpret_cast(&oat_file_->GetOatHeader()); uintptr_t code_offset = quick_code - code_base; + bool is_quick_offset = false; + if (quick_code == reinterpret_cast(GetQuickToInterpreterBridge())) { + is_quick_offset = true; + code_offset = PointerToLowMemUInt32(GetOatAddress(quick_to_interpreter_bridge_offset_)); + } else if (quick_code == + reinterpret_cast(class_linker->GetQuickGenericJniTrampoline())) { + CHECK(target->IsNative()); + is_quick_offset = true; + code_offset = PointerToLowMemUInt32(GetOatAddress(quick_generic_jni_trampoline_offset_)); + } + uintptr_t value; if (patch->IsRelative()) { // value to patch is relative to the location being patched const void* quick_oat_code = class_linker->GetQuickOatCodeFor(patch->GetDexFile(), patch->GetReferrerClassDefIdx(), patch->GetReferrerMethodIdx()); + if (is_quick_offset) { + quick_code = code_offset; + // If its a quick offset it means that we are doing a relative patch from the class linker + // oat_file to the image writer oat_file so we need to adjust the quick oat code to be the + // one in the image writer oat_file. + quick_oat_code = + reinterpret_cast(reinterpret_cast(quick_oat_code) + + reinterpret_cast(oat_data_begin_) - code_base); + } uintptr_t base = reinterpret_cast(quick_oat_code); uintptr_t patch_location = base + patch->GetLiteralOffset(); - uintptr_t value = quick_code - patch_location + patch->RelativeOffset(); - SetPatchLocation(patch, value); + value = quick_code - patch_location + patch->RelativeOffset(); } else { - if (quick_code == reinterpret_cast(GetQuickToInterpreterBridge()) || - quick_code == reinterpret_cast(class_linker->GetQuickGenericJniTrampoline())) { - if (target->IsNative()) { - // generic JNI, not interpreter bridge from GetQuickOatCodeFor(). - code_offset = quick_generic_jni_trampoline_offset_; - } else { - code_offset = quick_to_interpreter_bridge_offset_; - } - } - SetPatchLocation(patch, PointerToLowMemUInt32(GetOatAddress(code_offset))); + value = code_offset; } + SetPatchLocation(patch, value); } const CallPatches& methods_to_patch = compiler_driver_.GetMethodsToPatch(); -- cgit v1.2.3-59-g8ed1b