summaryrefslogtreecommitdiffstats
path: root/patchoat/patchoat.cc
diff options
context:
space:
mode:
Diffstat (limited to 'patchoat/patchoat.cc')
-rw-r--r--patchoat/patchoat.cc162
1 files changed, 102 insertions, 60 deletions
diff --git a/patchoat/patchoat.cc b/patchoat/patchoat.cc
index ef84a17..007125c 100644
--- a/patchoat/patchoat.cc
+++ b/patchoat/patchoat.cc
@@ -25,6 +25,7 @@
#include <vector>
#include "art_field-inl.h"
+#include "art_method-inl.h"
#include "base/dumpable.h"
#include "base/scoped_flock.h"
#include "base/stringpiece.h"
@@ -35,8 +36,9 @@
#include "elf_file_impl.h"
#include "gc/space/image_space.h"
#include "image.h"
-#include "mirror/art_method-inl.h"
+#include "mirror/abstract_method.h"
#include "mirror/object-inl.h"
+#include "mirror/method.h"
#include "mirror/reference.h"
#include "noop_compiler_callbacks.h"
#include "offsets.h"
@@ -120,7 +122,7 @@ bool PatchOat::Patch(const std::string& image_location, off_t delta,
}
ImageHeader image_header;
if (sizeof(image_header) != input_image->Read(reinterpret_cast<char*>(&image_header),
- sizeof(image_header), 0)) {
+ sizeof(image_header), 0)) {
LOG(ERROR) << "Unable to read image header from image file " << input_image->GetPath();
return false;
}
@@ -416,12 +418,22 @@ bool PatchOat::ReplaceOatFileWithSymlink(const std::string& input_oat_filename,
}
void PatchOat::PatchArtFields(const ImageHeader* image_header) {
- const size_t art_field_size = image_header->GetArtFieldsSize();
- const size_t art_field_offset = image_header->GetArtFieldsOffset();
- for (size_t pos = 0; pos < art_field_size; pos += sizeof(ArtField)) {
- auto* field = reinterpret_cast<ArtField*>(heap_->Begin() + art_field_offset + pos);
- auto* dest_field = RelocatedCopyOf(field);
- dest_field->SetDeclaringClass(RelocatedAddressOfPointer(field->GetDeclaringClass()));
+ const auto& section = image_header->GetImageSection(ImageHeader::kSectionArtFields);
+ for (size_t pos = 0; pos < section.Size(); pos += sizeof(ArtField)) {
+ auto* src = reinterpret_cast<ArtField*>(heap_->Begin() + section.Offset() + pos);
+ auto* dest = RelocatedCopyOf(src);
+ dest->SetDeclaringClass(RelocatedAddressOfPointer(src->GetDeclaringClass()));
+ }
+}
+
+void PatchOat::PatchArtMethods(const ImageHeader* image_header) {
+ const auto& section = image_header->GetMethodsSection();
+ const size_t pointer_size = InstructionSetPointerSize(isa_);
+ size_t method_size = ArtMethod::ObjectSize(pointer_size);
+ for (size_t pos = 0; pos < section.Size(); pos += method_size) {
+ auto* src = reinterpret_cast<ArtMethod*>(heap_->Begin() + section.Offset() + pos);
+ auto* dest = RelocatedCopyOf(src);
+ FixupMethod(src, dest);
}
}
@@ -431,31 +443,35 @@ void PatchOat::PatchDexFileArrays(mirror::ObjectArray<mirror::Object>* img_roots
for (size_t i = 0, count = dex_caches->GetLength(); i < count; ++i) {
auto* dex_cache = dex_caches->GetWithoutChecks(i);
auto* fields = dex_cache->GetResolvedFields();
- if (fields == nullptr) {
- continue;
+ if (fields != nullptr) {
+ CHECK(!fields->IsObjectArray());
+ CHECK(fields->IsArrayInstance());
+ FixupNativePointerArray(fields);
}
- CHECK(!fields->IsObjectArray());
- CHECK(fields->IsArrayInstance());
- auto* component_type = fields->GetClass()->GetComponentType();
- if (component_type->IsPrimitiveInt()) {
- mirror::IntArray* arr = fields->AsIntArray();
- mirror::IntArray* copy_arr = down_cast<mirror::IntArray*>(RelocatedCopyOf(arr));
- for (size_t j = 0, count2 = arr->GetLength(); j < count2; ++j) {
- auto f = arr->GetWithoutChecks(j);
- if (f != 0) {
- copy_arr->SetWithoutChecks<false>(j, f + delta_);
- }
- }
- } else {
- CHECK(component_type->IsPrimitiveLong());
- mirror::LongArray* arr = fields->AsLongArray();
- mirror::LongArray* copy_arr = down_cast<mirror::LongArray*>(RelocatedCopyOf(arr));
- for (size_t j = 0, count2 = arr->GetLength(); j < count2; ++j) {
- auto f = arr->GetWithoutChecks(j);
- if (f != 0) {
- copy_arr->SetWithoutChecks<false>(j, f + delta_);
- }
- }
+ auto* methods = dex_cache->GetResolvedMethods();
+ if (methods != nullptr) {
+ CHECK(!methods->IsObjectArray());
+ CHECK(methods->IsArrayInstance());
+ FixupNativePointerArray(methods);
+ }
+ }
+}
+
+void PatchOat::FixupNativePointerArray(mirror::PointerArray* object) {
+ if (object->IsIntArray()) {
+ mirror::IntArray* arr = object->AsIntArray();
+ mirror::IntArray* copy_arr = down_cast<mirror::IntArray*>(RelocatedCopyOf(arr));
+ for (size_t j = 0, count2 = arr->GetLength(); j < count2; ++j) {
+ copy_arr->SetWithoutChecks<false>(
+ j, RelocatedAddressOfIntPointer(arr->GetWithoutChecks(j)));
+ }
+ } else {
+ CHECK(object->IsLongArray());
+ mirror::LongArray* arr = object->AsLongArray();
+ mirror::LongArray* copy_arr = down_cast<mirror::LongArray*>(RelocatedCopyOf(arr));
+ for (size_t j = 0, count2 = arr->GetLength(); j < count2; ++j) {
+ copy_arr->SetWithoutChecks<false>(
+ j, RelocatedAddressOfIntPointer(arr->GetWithoutChecks(j)));
}
}
}
@@ -470,6 +486,9 @@ bool PatchOat::PatchImage() {
// Patch and update ArtFields.
PatchArtFields(image_header);
+ // Patch and update ArtMethods.
+ PatchArtMethods(image_header);
+
// Patch dex file int/long arrays which point to ArtFields.
PatchDexFileArrays(img_roots);
@@ -545,40 +564,63 @@ void PatchOat::VisitObject(mirror::Object* object) {
}
PatchOat::PatchVisitor visitor(this, copy);
object->VisitReferences<true, kVerifyNone>(visitor, visitor);
- if (object->IsArtMethod<kVerifyNone>()) {
- FixupMethod(down_cast<mirror::ArtMethod*>(object), down_cast<mirror::ArtMethod*>(copy));
- } else if (object->IsClass<kVerifyNone>()) {
- mirror::Class* klass = down_cast<mirror::Class*>(object);
- down_cast<mirror::Class*>(copy)->SetSFieldsUnchecked(
- RelocatedAddressOfPointer(klass->GetSFields()));
- down_cast<mirror::Class*>(copy)->SetIFieldsUnchecked(
- RelocatedAddressOfPointer(klass->GetIFields()));
+ if (object->IsClass<kVerifyNone>()) {
+ auto* klass = object->AsClass();
+ auto* copy_klass = down_cast<mirror::Class*>(copy);
+ copy_klass->SetSFieldsUnchecked(RelocatedAddressOfPointer(klass->GetSFields()));
+ copy_klass->SetIFieldsUnchecked(RelocatedAddressOfPointer(klass->GetIFields()));
+ copy_klass->SetDirectMethodsPtrUnchecked(
+ RelocatedAddressOfPointer(klass->GetDirectMethodsPtr()));
+ copy_klass->SetVirtualMethodsPtr(RelocatedAddressOfPointer(klass->GetVirtualMethodsPtr()));
+ auto* vtable = klass->GetVTable();
+ if (vtable != nullptr) {
+ FixupNativePointerArray(vtable);
+ }
+ auto* iftable = klass->GetIfTable();
+ if (iftable != nullptr) {
+ for (int32_t i = 0; i < klass->GetIfTableCount(); ++i) {
+ if (iftable->GetMethodArrayCount(i) > 0) {
+ auto* method_array = iftable->GetMethodArray(i);
+ CHECK(method_array != nullptr);
+ FixupNativePointerArray(method_array);
+ }
+ }
+ }
+ if (klass->ShouldHaveEmbeddedImtAndVTable()) {
+ const size_t pointer_size = InstructionSetPointerSize(isa_);
+ for (int32_t i = 0; i < klass->GetEmbeddedVTableLength(); ++i) {
+ copy_klass->SetEmbeddedVTableEntryUnchecked(i, RelocatedAddressOfPointer(
+ klass->GetEmbeddedVTableEntry(i, pointer_size)), pointer_size);
+ }
+ for (size_t i = 0; i < mirror::Class::kImtSize; ++i) {
+ copy_klass->SetEmbeddedImTableEntry(i, RelocatedAddressOfPointer(
+ klass->GetEmbeddedImTableEntry(i, pointer_size)), pointer_size);
+ }
+ }
+ }
+ if (object->GetClass() == mirror::Method::StaticClass() ||
+ object->GetClass() == mirror::Constructor::StaticClass()) {
+ // Need to go update the ArtMethod.
+ auto* dest = down_cast<mirror::AbstractMethod*>(copy);
+ auto* src = down_cast<mirror::AbstractMethod*>(object);
+ dest->SetArtMethod(RelocatedAddressOfPointer(src->GetArtMethod()));
}
}
-void PatchOat::FixupMethod(mirror::ArtMethod* object, mirror::ArtMethod* copy) {
+void PatchOat::FixupMethod(ArtMethod* object, ArtMethod* copy) {
const size_t pointer_size = InstructionSetPointerSize(isa_);
+ copy->CopyFrom(object, pointer_size);
// Just update the entry points if it looks like we should.
// TODO: sanity check all the pointers' values
- uintptr_t quick= reinterpret_cast<uintptr_t>(
- object->GetEntryPointFromQuickCompiledCodePtrSize<kVerifyNone>(pointer_size));
- if (quick != 0) {
- copy->SetEntryPointFromQuickCompiledCodePtrSize(reinterpret_cast<void*>(quick + delta_),
- pointer_size);
- }
- uintptr_t interpreter = reinterpret_cast<uintptr_t>(
- object->GetEntryPointFromInterpreterPtrSize<kVerifyNone>(pointer_size));
- if (interpreter != 0) {
- copy->SetEntryPointFromInterpreterPtrSize(
- reinterpret_cast<mirror::EntryPointFromInterpreter*>(interpreter + delta_), pointer_size);
- }
-
- uintptr_t native_method = reinterpret_cast<uintptr_t>(
- object->GetEntryPointFromJniPtrSize(pointer_size));
- if (native_method != 0) {
- copy->SetEntryPointFromJniPtrSize(reinterpret_cast<void*>(native_method + delta_),
- pointer_size);
- }
+ copy->SetDeclaringClass(RelocatedAddressOfPointer(object->GetDeclaringClass()));
+ copy->SetDexCacheResolvedMethods(RelocatedAddressOfPointer(object->GetDexCacheResolvedMethods()));
+ copy->SetDexCacheResolvedTypes(RelocatedAddressOfPointer(object->GetDexCacheResolvedTypes()));
+ copy->SetEntryPointFromQuickCompiledCodePtrSize(RelocatedAddressOfPointer(
+ object->GetEntryPointFromQuickCompiledCodePtrSize(pointer_size)), pointer_size);
+ copy->SetEntryPointFromInterpreterPtrSize(RelocatedAddressOfPointer(
+ object->GetEntryPointFromInterpreterPtrSize(pointer_size)), pointer_size);
+ copy->SetEntryPointFromJniPtrSize(RelocatedAddressOfPointer(
+ object->GetEntryPointFromJniPtrSize(pointer_size)), pointer_size);
}
bool PatchOat::Patch(File* input_oat, off_t delta, File* output_oat, TimingLogger* timings,