1 /*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 // The data types used for communication between heapprofd and the client
18 // embedded in processes that are being profiled.
19
20 #ifndef SRC_PROFILING_MEMORY_WIRE_PROTOCOL_H_
21 #define SRC_PROFILING_MEMORY_WIRE_PROTOCOL_H_
22
23 #include <cinttypes>
24
25 #include <unwindstack/Elf.h>
26 #include <unwindstack/MachineArm.h>
27 #include <unwindstack/MachineArm64.h>
28 #include <unwindstack/MachineMips.h>
29 #include <unwindstack/MachineMips64.h>
30 #include <unwindstack/MachineRiscv64.h>
31 #include <unwindstack/MachineX86.h>
32 #include <unwindstack/MachineX86_64.h>
33
34 #include "perfetto/heap_profile.h"
35 #include "src/profiling/memory/shared_ring_buffer.h"
36 #include "src/profiling/memory/util.h"
37
38 namespace perfetto {
39
40 namespace base {
41 class UnixSocketRaw;
42 }
43
44 namespace profiling {
45
46 // C++11 std::max is not constexpr.
constexpr_max(size_t x,size_t y)47 constexpr size_t constexpr_max(size_t x, size_t y) {
48 return x > y ? x : y;
49 }
50
51 // clang-format makes this unreadable. Turning it off for this block.
52 // clang-format off
53 constexpr size_t kMaxRegisterDataSize =
54 constexpr_max(
55 constexpr_max(
56 constexpr_max(
57 constexpr_max(
58 constexpr_max(
59 constexpr_max(
60 sizeof(uint32_t) * unwindstack::ARM_REG_LAST,
61 sizeof(uint64_t) * unwindstack::ARM64_REG_LAST),
62 sizeof(uint32_t) * unwindstack::X86_REG_LAST),
63 sizeof(uint64_t) * unwindstack::X86_64_REG_LAST),
64 sizeof(uint32_t) * unwindstack::MIPS_REG_LAST),
65 sizeof(uint64_t) * unwindstack::MIPS64_REG_LAST),
66 sizeof(uint64_t) * unwindstack::RISCV64_REG_MAX
67 );
68 // clang-format on
69
70 // Types needed for the wire format used for communication between the client
71 // and heapprofd. The basic format of a record sent by the client is
72 // record size (uint64_t) | record type (RecordType = uint64_t) | record
73 // If record type is Malloc, the record format is AllocMetdata | raw stack.
74 // If the record type is Free, the record is a FreeEntry.
75 // If record type is HeapName, the record is a HeapName.
76 // On connect, heapprofd sends one ClientConfiguration struct over the control
77 // socket.
78
79 // Use uint64_t to make sure the following data is aligned as 64bit is the
80 // strongest alignment requirement.
81
82 struct ClientConfigurationHeap {
83 char name[HEAPPROFD_HEAP_NAME_SZ];
84 PERFETTO_CROSS_ABI_ALIGNED(uint64_t) interval;
85 };
86
87 struct ClientConfiguration {
88 // On average, sample one allocation every interval bytes,
89 // If interval == 1, sample every allocation.
90 // Must be >= 1.
91 PERFETTO_CROSS_ABI_ALIGNED(uint64_t) default_interval;
92 PERFETTO_CROSS_ABI_ALIGNED(uint64_t) block_client_timeout_us;
93 PERFETTO_CROSS_ABI_ALIGNED(uint64_t) num_heaps;
94 PERFETTO_CROSS_ABI_ALIGNED(uint64_t) adaptive_sampling_shmem_threshold;
95 PERFETTO_CROSS_ABI_ALIGNED(uint64_t)
96 adaptive_sampling_max_sampling_interval_bytes;
97 alignas(8) ClientConfigurationHeap heaps[64];
98 PERFETTO_CROSS_ABI_ALIGNED(bool) block_client;
99 PERFETTO_CROSS_ABI_ALIGNED(bool) disable_fork_teardown;
100 PERFETTO_CROSS_ABI_ALIGNED(bool) disable_vfork_detection;
101 PERFETTO_CROSS_ABI_ALIGNED(bool) all_heaps;
102 // Just double check that the array sizes are in correct order.
103 };
104
105 enum class RecordType : uint64_t {
106 Free = 0,
107 Malloc = 1,
108 HeapName = 2,
109 };
110
111 // Make the whole struct 8-aligned. This is to make sizeof(AllocMetdata)
112 // the same on 32 and 64-bit.
113 struct alignas(8) AllocMetadata {
114 PERFETTO_CROSS_ABI_ALIGNED(uint64_t) sequence_number;
115 // Size of the allocation that was made.
116 PERFETTO_CROSS_ABI_ALIGNED(uint64_t) alloc_size;
117 // Total number of bytes attributed to this allocation.
118 PERFETTO_CROSS_ABI_ALIGNED(uint64_t) sample_size;
119 // Pointer returned by malloc(2) for this allocation.
120 PERFETTO_CROSS_ABI_ALIGNED(uint64_t) alloc_address;
121 // Current value of the stack pointer.
122 PERFETTO_CROSS_ABI_ALIGNED(uint64_t) stack_pointer;
123 PERFETTO_CROSS_ABI_ALIGNED(uint64_t) clock_monotonic_coarse_timestamp;
124 // unwindstack::AsmGetRegs assumes this is aligned.
125 alignas(8) char register_data[kMaxRegisterDataSize];
126 PERFETTO_CROSS_ABI_ALIGNED(uint32_t) heap_id;
127 // CPU architecture of the client.
128 PERFETTO_CROSS_ABI_ALIGNED(unwindstack::ArchEnum) arch;
129 };
130
131 struct FreeEntry {
132 PERFETTO_CROSS_ABI_ALIGNED(uint64_t) sequence_number;
133 PERFETTO_CROSS_ABI_ALIGNED(uint64_t) addr;
134 PERFETTO_CROSS_ABI_ALIGNED(uint32_t) heap_id;
135 };
136
137 struct HeapName {
138 PERFETTO_CROSS_ABI_ALIGNED(uint64_t) sample_interval;
139 PERFETTO_CROSS_ABI_ALIGNED(uint32_t) heap_id;
140 PERFETTO_CROSS_ABI_ALIGNED(char) heap_name[HEAPPROFD_HEAP_NAME_SZ];
141 };
142
143 // Make sure the sizes do not change on different architectures.
144 static_assert(sizeof(AllocMetadata) == 328,
145 "AllocMetadata needs to be the same size across ABIs.");
146 static_assert(sizeof(FreeEntry) == 24,
147 "FreeEntry needs to be the same size across ABIs.");
148 static_assert(sizeof(HeapName) == 80,
149 "HeapName needs to be the same size across ABIs.");
150 static_assert(sizeof(ClientConfiguration) == 4656,
151 "ClientConfiguration needs to be the same size across ABIs.");
152
153 enum HandshakeFDs : size_t {
154 kHandshakeMaps = 0,
155 kHandshakeMem,
156 kHandshakeSize,
157 };
158
159 struct WireMessage {
160 RecordType record_type;
161
162 AllocMetadata* alloc_header;
163 FreeEntry* free_header;
164 HeapName* heap_name_header;
165
166 char* payload;
167 size_t payload_size;
168 };
169
170 int64_t SendWireMessage(SharedRingBuffer* buf, const WireMessage& msg);
171
172 // Parse message received over the wire.
173 // |buf| has to outlive |out|.
174 // If buf is not a valid message, return false.
175 bool ReceiveWireMessage(char* buf, size_t size, WireMessage* out);
176
177 uint64_t GetHeapSamplingInterval(const ClientConfiguration& cli_config,
178 const char* heap_name);
179
180 constexpr const char* kHeapprofdSocketEnvVar = "ANDROID_SOCKET_heapprofd";
181 constexpr const char* kHeapprofdSocketFile = "/dev/socket/heapprofd";
182
183 } // namespace profiling
184 } // namespace perfetto
185
186 #endif // SRC_PROFILING_MEMORY_WIRE_PROTOCOL_H_
187