Add oatdump support for app images

Example usage on host:
oatdumpd --app-oat=art/plus32.odex --app-image=art/plus32.art
--image=art/oats/system@framework@boot.art --instruction-set=arm

TODO: Add to oatdump test.

Bug: 27408512
Bug: 22858531

(cherry picked from commit bcb6a72569a1401b36a3ad3b6aa4d13e29966cf0)

Change-Id: I9d1aa7eaa16795e5fbabc6974d245849e16b1d03
diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc
index bea1dcc..895d3d3 100644
--- a/runtime/gc/space/image_space.cc
+++ b/runtime/gc/space/image_space.cc
@@ -617,7 +617,7 @@
   }
 
   // Returns the delta between the dest from the source.
-  off_t Delta() const {
+  uintptr_t Delta() const {
     return dest_ - source_;
   }
 
@@ -639,6 +639,13 @@
   const uintptr_t length_;
 };
 
+std::ostream& operator<<(std::ostream& os, const RelocationRange& reloc) {
+  return os << "(" << reinterpret_cast<const void*>(reloc.Source()) << "-"
+            << reinterpret_cast<const void*>(reloc.Source() + reloc.Length()) << ")->("
+            << reinterpret_cast<const void*>(reloc.Dest()) << "-"
+            << reinterpret_cast<const void*>(reloc.Dest() + reloc.Length()) << ")";
+}
+
 class FixupVisitor : public ValueObject {
  public:
   FixupVisitor(const RelocationRange& boot_image,
@@ -670,7 +677,7 @@
   ALWAYS_INLINE const void* ForwardCode(const void* src) const {
     const uintptr_t uint_src = reinterpret_cast<uintptr_t>(src);
     if (boot_oat_.InSource(uint_src)) {
-     return reinterpret_cast<const void*>(boot_oat_.ToDest(uint_src));
+      return reinterpret_cast<const void*>(boot_oat_.ToDest(uint_src));
     }
     if (app_oat_.InSource(uint_src)) {
       return reinterpret_cast<const void*>(app_oat_.ToDest(uint_src));
@@ -687,13 +694,6 @@
   const RelocationRange app_oat_;
 };
 
-std::ostream& operator<<(std::ostream& os, const RelocationRange& reloc) {
-  return os << "(" << reinterpret_cast<const void*>(reloc.Source()) << "-"
-            << reinterpret_cast<const void*>(reloc.Source() + reloc.Length()) << ")->("
-            << reinterpret_cast<const void*>(reloc.Dest()) << "-"
-            << reinterpret_cast<const void*>(reloc.Dest() + reloc.Length()) << ")";
-}
-
 // Adapt for mirror::Class::FixupNativePointers.
 class FixupObjectAdapter : public FixupVisitor {
  public:
@@ -756,8 +756,10 @@
  public:
   template<typename... Args>
   explicit FixupObjectVisitor(gc::accounting::ContinuousSpaceBitmap* pointer_array_visited,
+                              const size_t pointer_size,
                               Args... args)
       : FixupVisitor(args...),
+        pointer_size_(pointer_size),
         pointer_array_visited_(pointer_array_visited) {}
 
   // Fix up separately since we also need to fix up method entrypoints.
@@ -791,7 +793,7 @@
     if (array != nullptr &&
         visitor.IsInAppImage(array) &&
         !pointer_array_visited_->Test(array)) {
-      array->Fixup<kVerifyNone, kWithoutReadBarrier>(array, sizeof(void*), visitor);
+      array->Fixup<kVerifyNone, kWithoutReadBarrier>(array, pointer_size_, visitor);
       pointer_array_visited_->Set(array);
     }
   }
@@ -813,7 +815,7 @@
     if (obj->IsClass<kVerifyNone, kWithoutReadBarrier>()) {
       mirror::Class* klass = obj->AsClass<kVerifyNone, kWithoutReadBarrier>();
       FixupObjectAdapter visitor(boot_image_, boot_oat_, app_image_, app_oat_);
-      klass->FixupNativePointers<kVerifyNone, kWithoutReadBarrier>(klass, sizeof(void*), visitor);
+      klass->FixupNativePointers<kVerifyNone, kWithoutReadBarrier>(klass, pointer_size_, visitor);
       // Deal with the pointer arrays. Use the helper function since multiple classes can reference
       // the same arrays.
       VisitPointerArray(klass->GetVTable<kVerifyNone, kWithoutReadBarrier>(), visitor);
@@ -832,6 +834,7 @@
   }
 
  private:
+  const size_t pointer_size_;
   gc::accounting::ContinuousSpaceBitmap* const pointer_array_visited_;
 };
 
@@ -850,7 +853,8 @@
 
 class ForwardCodeAdapter {
  public:
-  ALWAYS_INLINE ForwardCodeAdapter(const FixupVisitor* visitor) : visitor_(visitor) {}
+  ALWAYS_INLINE ForwardCodeAdapter(const FixupVisitor* visitor)
+      : visitor_(visitor) {}
 
   template <typename T>
   ALWAYS_INLINE T* operator()(T* src) const {
@@ -864,19 +868,21 @@
 class FixupArtMethodVisitor : public FixupVisitor, public ArtMethodVisitor {
  public:
   template<typename... Args>
-  explicit FixupArtMethodVisitor(bool fixup_heap_objects, Args... args)
+  explicit FixupArtMethodVisitor(bool fixup_heap_objects, size_t pointer_size, Args... args)
       : FixupVisitor(args...),
-        fixup_heap_objects_(fixup_heap_objects) {}
+        fixup_heap_objects_(fixup_heap_objects),
+        pointer_size_(pointer_size) {}
 
   virtual void Visit(ArtMethod* method) NO_THREAD_SAFETY_ANALYSIS {
     if (fixup_heap_objects_) {
-      method->UpdateObjectsForImageRelocation(ForwardObjectAdapter(this));
+      method->UpdateObjectsForImageRelocation(ForwardObjectAdapter(this), pointer_size_);
     }
-    method->UpdateEntrypoints<kWithoutReadBarrier>(ForwardCodeAdapter(this));
+    method->UpdateEntrypoints<kWithoutReadBarrier>(ForwardCodeAdapter(this), pointer_size_);
   }
 
  private:
   const bool fixup_heap_objects_;
+  const size_t pointer_size_;
 };
 
 class FixupArtFieldVisitor : public FixupVisitor, public ArtFieldVisitor {
@@ -912,6 +918,7 @@
   uint32_t boot_image_end = 0;
   uint32_t boot_oat_begin = 0;
   uint32_t boot_oat_end = 0;
+  const size_t pointer_size = image_header.GetPointerSize();
   gc::Heap* const heap = Runtime::Current()->GetHeap();
   heap->GetBootImagesSize(&boot_image_begin, &boot_image_end, &boot_oat_begin, &boot_oat_end);
   CHECK_NE(boot_image_begin, boot_image_end)
@@ -974,6 +981,7 @@
                                                       target_base,
                                                       image_header.GetImageSize()));
     FixupObjectVisitor fixup_object_visitor(visited_bitmap.get(),
+                                            pointer_size,
                                             boot_image,
                                             boot_oat,
                                             app_image,
@@ -1023,10 +1031,10 @@
           dex_cache->SetResolvedMethods(new_methods);
         }
         for (size_t j = 0, num = dex_cache->NumResolvedMethods(); j != num; ++j) {
-          ArtMethod* orig = mirror::DexCache::GetElementPtrSize(new_methods, j, sizeof(void*));
+          ArtMethod* orig = mirror::DexCache::GetElementPtrSize(new_methods, j, pointer_size);
           ArtMethod* copy = fixup_adapter.ForwardObject(orig);
           if (orig != copy) {
-            mirror::DexCache::SetElementPtrSize(new_methods, j, copy, sizeof(void*));
+            mirror::DexCache::SetElementPtrSize(new_methods, j, copy, pointer_size);
           }
         }
       }
@@ -1037,10 +1045,10 @@
           dex_cache->SetResolvedFields(new_fields);
         }
         for (size_t j = 0, num = dex_cache->NumResolvedFields(); j != num; ++j) {
-          ArtField* orig = mirror::DexCache::GetElementPtrSize(new_fields, j, sizeof(void*));
+          ArtField* orig = mirror::DexCache::GetElementPtrSize(new_fields, j, pointer_size);
           ArtField* copy = fixup_adapter.ForwardObject(orig);
           if (orig != copy) {
-            mirror::DexCache::SetElementPtrSize(new_fields, j, copy, sizeof(void*));
+            mirror::DexCache::SetElementPtrSize(new_fields, j, copy, pointer_size);
           }
         }
       }
@@ -1049,11 +1057,16 @@
   {
     // Only touches objects in the app image, no need for mutator lock.
     TimingLogger::ScopedTiming timing("Fixup methods", &logger);
-    FixupArtMethodVisitor method_visitor(fixup_image, boot_image, boot_oat, app_image, app_oat);
+    FixupArtMethodVisitor method_visitor(fixup_image,
+                                         pointer_size,
+                                         boot_image,
+                                         boot_oat,
+                                         app_image,
+                                         app_oat);
     image_header.GetImageSection(ImageHeader::kSectionArtMethods).VisitPackedArtMethods(
         &method_visitor,
         target_base,
-        sizeof(void*));
+        pointer_size);
   }
   if (fixup_image) {
     {
@@ -1381,6 +1394,7 @@
                                     image_header.GetOatDataBegin(),
                                     image_header.GetOatFileBegin(),
                                     !Runtime::Current()->IsAotCompiler(),
+                                    /*low_4gb*/false,
                                     nullptr,
                                     error_msg);
   if (oat_file == nullptr) {