Move .art.rel data to a section in .art, part 1.

Refactor the code so that we can collect all relocation
offsets while writing the image.

Test: Manually verify that the aosp_taimen-userdebug boot
      image is identical before and after this change;
      using WIP follow-up code, check that we record the
      same locations as the patchoat-generated .rel files.
Test: m test-art-host-gtest
Test: testrunner.py --host --optimizing
Bug: 77856493
Change-Id: Id8c78e417e77e859a82a680504253f41e84560d6
diff --git a/runtime/mirror/class-inl.h b/runtime/mirror/class-inl.h
index fffd7f3..bc72517 100644
--- a/runtime/mirror/class-inl.h
+++ b/runtime/mirror/class-inl.h
@@ -331,11 +331,11 @@
 }
 
 inline ImTable* Class::GetImt(PointerSize pointer_size) {
-  return GetFieldPtrWithSize<ImTable*>(MemberOffset(ImtPtrOffset(pointer_size)), pointer_size);
+  return GetFieldPtrWithSize<ImTable*>(ImtPtrOffset(pointer_size), pointer_size);
 }
 
 inline void Class::SetImt(ImTable* imt, PointerSize pointer_size) {
-  return SetFieldPtrWithSize<false>(MemberOffset(ImtPtrOffset(pointer_size)), imt, pointer_size);
+  return SetFieldPtrWithSize<false>(ImtPtrOffset(pointer_size), imt, pointer_size);
 }
 
 inline MemberOffset Class::EmbeddedVTableEntryOffset(uint32_t i, PointerSize pointer_size) {
@@ -1070,20 +1070,26 @@
 inline void Class::FixupNativePointers(Class* dest,
                                        PointerSize pointer_size,
                                        const Visitor& visitor) {
+  auto dest_address_fn = [dest](MemberOffset offset) {
+    return reinterpret_cast<void**>(reinterpret_cast<uintptr_t>(dest) + offset.Uint32Value());
+  };
   // Update the field arrays.
   LengthPrefixedArray<ArtField>* const sfields = GetSFieldsPtr();
-  LengthPrefixedArray<ArtField>* const new_sfields = visitor(sfields);
+  void** sfields_dest_address = dest_address_fn(OFFSET_OF_OBJECT_MEMBER(Class, sfields_));
+  LengthPrefixedArray<ArtField>* const new_sfields = visitor(sfields, sfields_dest_address);
   if (sfields != new_sfields) {
     dest->SetSFieldsPtrUnchecked(new_sfields);
   }
   LengthPrefixedArray<ArtField>* const ifields = GetIFieldsPtr();
-  LengthPrefixedArray<ArtField>* const new_ifields = visitor(ifields);
+  void** ifields_dest_address = dest_address_fn(OFFSET_OF_OBJECT_MEMBER(Class, ifields_));
+  LengthPrefixedArray<ArtField>* const new_ifields = visitor(ifields, ifields_dest_address);
   if (ifields != new_ifields) {
     dest->SetIFieldsPtrUnchecked(new_ifields);
   }
   // Update method array.
   LengthPrefixedArray<ArtMethod>* methods = GetMethodsPtr();
-  LengthPrefixedArray<ArtMethod>* new_methods = visitor(methods);
+  void** methods_dest_address = dest_address_fn(OFFSET_OF_OBJECT_MEMBER(Class, methods_));
+  LengthPrefixedArray<ArtMethod>* new_methods = visitor(methods, methods_dest_address);
   if (methods != new_methods) {
     dest->SetMethodsPtrInternal(new_methods);
   }
@@ -1091,16 +1097,18 @@
   if (!IsTemp() && ShouldHaveEmbeddedVTable<kVerifyNone, kReadBarrierOption>()) {
     for (int32_t i = 0, count = GetEmbeddedVTableLength(); i < count; ++i) {
       ArtMethod* method = GetEmbeddedVTableEntry(i, pointer_size);
-      void** dest_addr = reinterpret_cast<void**>(reinterpret_cast<uintptr_t>(dest) +
-          EmbeddedVTableEntryOffset(i, pointer_size).Uint32Value());
-      ArtMethod* new_method = visitor(method, dest_addr);
+      void** method_dest_addr = dest_address_fn(EmbeddedVTableEntryOffset(i, pointer_size));
+      ArtMethod* new_method = visitor(method, method_dest_addr);
       if (method != new_method) {
         dest->SetEmbeddedVTableEntryUnchecked(i, new_method, pointer_size);
       }
     }
   }
   if (!IsTemp() && ShouldHaveImt<kVerifyNone, kReadBarrierOption>()) {
-    dest->SetImt(visitor(GetImt(pointer_size)), pointer_size);
+    ImTable* imt = GetImt(pointer_size);
+    void** imt_dest_addr = dest_address_fn(ImtPtrOffset(pointer_size));
+    ImTable* new_imt = visitor(imt, imt_dest_addr);
+    dest->SetImt(new_imt, pointer_size);
   }
 }
 
diff --git a/runtime/mirror/dex_cache-inl.h b/runtime/mirror/dex_cache-inl.h
index faec6e6..bbe15ac 100644
--- a/runtime/mirror/dex_cache-inl.h
+++ b/runtime/mirror/dex_cache-inl.h
@@ -257,7 +257,7 @@
   } else {
     auto* array = reinterpret_cast<std::atomic<ConversionPair32>*>(pair_array);
     ConversionPair32 value = array[idx].load(std::memory_order_relaxed);
-    return NativeDexCachePair<T>(reinterpret_cast<T*>(value.first), value.second);
+    return NativeDexCachePair<T>(reinterpret_cast32<T*>(value.first), value.second);
   }
 }
 
@@ -272,9 +272,8 @@
     AtomicStoreRelease16B(&array[idx], v);
   } else {
     auto* array = reinterpret_cast<std::atomic<ConversionPair32>*>(pair_array);
-    ConversionPair32 v(
-        dchecked_integral_cast<uint32_t>(reinterpret_cast<uintptr_t>(pair.object)),
-        dchecked_integral_cast<uint32_t>(pair.index));
+    ConversionPair32 v(reinterpret_cast32<uint32_t>(pair.object),
+                       dchecked_integral_cast<uint32_t>(pair.index));
     array[idx].store(v, std::memory_order_release);
   }
 }
diff --git a/runtime/mirror/dex_cache.h b/runtime/mirror/dex_cache.h
index 941248e..ab5fb85 100644
--- a/runtime/mirror/dex_cache.h
+++ b/runtime/mirror/dex_cache.h
@@ -27,11 +27,14 @@
 
 namespace art {
 
+namespace linker {
+class ImageWriter;
+}  // namespace linker
+
 class ArtField;
 class ArtMethod;
 struct DexCacheOffsets;
 class DexFile;
-class ImageWriter;
 union JValue;
 class LinearAlloc;
 class Thread;
@@ -539,6 +542,7 @@
   uint32_t num_strings_;                // Number of elements in the strings_ array.
 
   friend struct art::DexCacheOffsets;  // for verifying offset information
+  friend class linker::ImageWriter;
   friend class Object;  // For VisitReferences
   DISALLOW_IMPLICIT_CONSTRUCTORS(DexCache);
 };
diff --git a/runtime/mirror/executable.h b/runtime/mirror/executable.h
index 23dd787..bf66d79 100644
--- a/runtime/mirror/executable.h
+++ b/runtime/mirror/executable.h
@@ -42,6 +42,10 @@
   void SetArtMethod(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_);
   mirror::Class* GetDeclaringClass() REQUIRES_SHARED(Locks::mutator_lock_);
 
+  static MemberOffset ArtMethodOffset() {
+    return MemberOffset(OFFSETOF_MEMBER(Executable, art_method_));
+  }
+
  private:
   uint16_t has_real_parameter_data_;
   HeapReference<mirror::Class> declaring_class_;
@@ -51,9 +55,6 @@
   uint32_t access_flags_;
   uint32_t dex_method_index_;
 
-  static MemberOffset ArtMethodOffset() {
-    return MemberOffset(OFFSETOF_MEMBER(Executable, art_method_));
-  }
   static MemberOffset DeclaringClassOffset() {
     return MemberOffset(OFFSETOF_MEMBER(Executable, declaring_class_));
   }
diff --git a/runtime/mirror/object.h b/runtime/mirror/object.h
index c7cffed..2801928 100644
--- a/runtime/mirror/object.h
+++ b/runtime/mirror/object.h
@@ -542,7 +542,7 @@
   void SetFieldPtr64(MemberOffset field_offset, T new_value)
       REQUIRES_SHARED(Locks::mutator_lock_) {
     SetFieldPtrWithSize<kTransactionActive, kCheckTransaction, kVerifyFlags>(
-        field_offset, new_value, 8u);
+        field_offset, new_value, PointerSize::k64);
   }
 
   template<bool kTransactionActive,
@@ -554,10 +554,8 @@
                                          PointerSize pointer_size)
       REQUIRES_SHARED(Locks::mutator_lock_) {
     if (pointer_size == PointerSize::k32) {
-      uintptr_t ptr  = reinterpret_cast<uintptr_t>(new_value);
-      DCHECK_EQ(static_cast<uint32_t>(ptr), ptr);  // Check that we dont lose any non 0 bits.
       SetField32<kTransactionActive, kCheckTransaction, kVerifyFlags>(
-          field_offset, static_cast<int32_t>(static_cast<uint32_t>(ptr)));
+          field_offset, reinterpret_cast32<int32_t>(new_value));
     } else {
       SetField64<kTransactionActive, kCheckTransaction, kVerifyFlags>(
           field_offset, reinterpret_cast64<int64_t>(new_value));
@@ -658,8 +656,8 @@
   ALWAYS_INLINE T GetFieldPtrWithSize(MemberOffset field_offset, PointerSize pointer_size)
       REQUIRES_SHARED(Locks::mutator_lock_) {
     if (pointer_size == PointerSize::k32) {
-      uint64_t address = static_cast<uint32_t>(GetField32<kVerifyFlags, kIsVolatile>(field_offset));
-      return reinterpret_cast<T>(static_cast<uintptr_t>(address));
+      int32_t v = GetField32<kVerifyFlags, kIsVolatile>(field_offset);
+      return reinterpret_cast32<T>(v);
     } else {
       int64_t v = GetField64<kVerifyFlags, kIsVolatile>(field_offset);
       return reinterpret_cast64<T>(v);