Fix cross-ABI ringbuffer issue.

Test: atest HeapprofdCtsTest -- --abi x86
Test: atest HeapprofdCtsTest -- --abi armeabi-v7a
Bug: 182008256

Change-Id: I1dab81bd94f7cf2a5faf933745d384af423aa137
diff --git a/src/profiling/memory/scoped_spinlock.h b/src/profiling/memory/scoped_spinlock.h
index 7e25e29..aeda611 100644
--- a/src/profiling/memory/scoped_spinlock.h
+++ b/src/profiling/memory/scoped_spinlock.h
@@ -33,6 +33,8 @@
   std::atomic<bool> poisoned;
 };
 
+static_assert(sizeof(Spinlock) == 2, "spinlock size must be ABI independent");
+
 void PoisonSpinlock(Spinlock* lock);
 
 class ScopedSpinlock {
diff --git a/src/profiling/memory/shared_ring_buffer.h b/src/profiling/memory/shared_ring_buffer.h
index a60590b..d4279a9 100644
--- a/src/profiling/memory/shared_ring_buffer.h
+++ b/src/profiling/memory/shared_ring_buffer.h
@@ -21,6 +21,7 @@
 #include "perfetto/ext/base/unix_socket.h"
 #include "perfetto/ext/base/utils.h"
 #include "src/profiling/memory/scoped_spinlock.h"
+#include "src/profiling/memory/util.h"
 
 #include <atomic>
 #include <limits>
@@ -81,19 +82,19 @@
   };
 
   struct Stats {
-    uint64_t bytes_written;
-    uint64_t num_writes_succeeded;
-    uint64_t num_writes_corrupt;
-    uint64_t num_writes_overflow;
+    PERFETTO_CROSS_ABI_ALIGNED(uint64_t) bytes_written;
+    PERFETTO_CROSS_ABI_ALIGNED(uint64_t) num_writes_succeeded;
+    PERFETTO_CROSS_ABI_ALIGNED(uint64_t) num_writes_corrupt;
+    PERFETTO_CROSS_ABI_ALIGNED(uint64_t) num_writes_overflow;
 
-    uint64_t num_reads_succeeded;
-    uint64_t num_reads_corrupt;
-    uint64_t num_reads_nodata;
+    PERFETTO_CROSS_ABI_ALIGNED(uint64_t) num_reads_succeeded;
+    PERFETTO_CROSS_ABI_ALIGNED(uint64_t) num_reads_corrupt;
+    PERFETTO_CROSS_ABI_ALIGNED(uint64_t) num_reads_nodata;
 
     // Fields below get set by GetStats as copies of atomics in MetadataPage.
-    uint64_t failed_spinlocks;
-    uint64_t client_spinlock_blocked_us;
-    ErrorState error_state;
+    PERFETTO_CROSS_ABI_ALIGNED(uint64_t) failed_spinlocks;
+    PERFETTO_CROSS_ABI_ALIGNED(uint64_t) client_spinlock_blocked_us;
+    PERFETTO_CROSS_ABI_ALIGNED(ErrorState) error_state;
   };
 
   static base::Optional<SharedRingBuffer> Create(size_t);
@@ -178,24 +179,28 @@
   struct MetadataPage {
     static_assert(std::is_trivially_constructible<Spinlock>::value,
                   "Spinlock needs to be trivially constructible.");
-    alignas(uint64_t) Spinlock spinlock;
-    std::atomic<uint64_t> read_pos;
-    std::atomic<uint64_t> write_pos;
+    alignas(8) Spinlock spinlock;
+    PERFETTO_CROSS_ABI_ALIGNED(std::atomic<uint64_t>) read_pos;
+    PERFETTO_CROSS_ABI_ALIGNED(std::atomic<uint64_t>) write_pos;
 
-    std::atomic<uint64_t> client_spinlock_blocked_us;
-    std::atomic<uint64_t> failed_spinlocks;
-    std::atomic<ErrorState> error_state;
-    alignas(uint64_t) std::atomic<bool> shutting_down;
-    alignas(uint64_t) std::atomic<bool> reader_paused;
+    PERFETTO_CROSS_ABI_ALIGNED(std::atomic<uint64_t>)
+    client_spinlock_blocked_us;
+    PERFETTO_CROSS_ABI_ALIGNED(std::atomic<uint64_t>) failed_spinlocks;
+    PERFETTO_CROSS_ABI_ALIGNED(std::atomic<ErrorState>) error_state;
+    alignas(sizeof(uint64_t)) std::atomic<bool> shutting_down;
+    alignas(sizeof(uint64_t)) std::atomic<bool> reader_paused;
     // For stats that are only accessed by a single thread or under the
     // spinlock, members of this struct are directly modified. Other stats use
     // the atomics above this struct.
     //
     // When the user requests stats, the atomics above get copied into this
     // struct, which is then returned.
-    Stats stats;
+    alignas(sizeof(uint64_t)) Stats stats;
   };
 
+  static_assert(sizeof(MetadataPage) == 144,
+                "metadata page size needs to be ABI independent");
+
  private:
   struct PointerPositions {
     uint64_t read_pos;
diff --git a/src/profiling/memory/util.h b/src/profiling/memory/util.h
new file mode 100644
index 0000000..1eaf369
--- /dev/null
+++ b/src/profiling/memory/util.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SRC_PROFILING_MEMORY_UTIL_H_
+#define SRC_PROFILING_MEMORY_UTIL_H_
+
+// Make sure the alignment is the same on 32 and 64 bit architectures. This
+// is to ensure the structs below are laid out in exactly the same way for
+// both of those, at the same build.
+// The maximum alignment of every type T is sizeof(T), so we overalign that.
+// E.g., the alignment for uint64_t is 4 bytes on 32, and 8 bytes on 64 bit.
+#define PERFETTO_CROSS_ABI_ALIGNED(type) alignas(sizeof(type)) type
+
+#endif  // SRC_PROFILING_MEMORY_UTIL_H_
diff --git a/src/profiling/memory/wire_protocol.h b/src/profiling/memory/wire_protocol.h
index 2f0a961..f1989b7 100644
--- a/src/profiling/memory/wire_protocol.h
+++ b/src/profiling/memory/wire_protocol.h
@@ -31,13 +31,7 @@
 
 #include "perfetto/heap_profile.h"
 #include "src/profiling/memory/shared_ring_buffer.h"
-
-// Make sure the alignment is the same on 32 and 64 bit architectures. This
-// is to ensure the structs below are laid out in exactly the same way for
-// both of those, at the same build.
-// The maximum alignment of every type T is sizeof(T), so we overalign that.
-// E.g., the alignment for uint64_t is 4 bytes on 32, and 8 bytes on 64 bit.
-#define PERFETTO_CROSS_ABI_ALIGNED(type) alignas(sizeof(type)) type
+#include "src/profiling/memory/util.h"
 
 namespace perfetto {
 
@@ -83,7 +77,7 @@
 
 struct ClientConfigurationHeap {
   char name[HEAPPROFD_HEAP_NAME_SZ];
-  uint64_t interval;
+  PERFETTO_CROSS_ABI_ALIGNED(uint64_t) interval;
 };
 
 struct ClientConfiguration {