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/MachineX86.h>
31 #include <unwindstack/MachineX86_64.h>
32
33 #include "perfetto/heap_profile.h"
34 #include "src/profiling/memory/shared_ring_buffer.h"
35 #include "src/profiling/memory/util.h"
36
37 namespace perfetto {
38
39 namespace base {
40 class UnixSocketRaw;
41 }
42
43 namespace profiling {
44
45 // C++11 std::max is not constexpr.
constexpr_max(size_t x,size_t y)46 constexpr size_t constexpr_max(size_t x, size_t y) {
47 return x > y ? x : y;
48 }
49
50 // clang-format makes this unreadable. Turning it off for this block.
51 // clang-format off
52 constexpr size_t kMaxRegisterDataSize =
53 constexpr_max(
54 constexpr_max(
55 constexpr_max(
56 constexpr_max(
57 constexpr_max(
58 sizeof(uint32_t) * unwindstack::ARM_REG_LAST,
59 sizeof(uint64_t) * unwindstack::ARM64_REG_LAST),
60 sizeof(uint32_t) * unwindstack::X86_REG_LAST),
61 sizeof(uint64_t) * unwindstack::X86_64_REG_LAST),
62 sizeof(uint32_t) * unwindstack::MIPS_REG_LAST),
63 sizeof(uint64_t) * unwindstack::MIPS64_REG_LAST
64 );
65 // clang-format on
66
67 // Types needed for the wire format used for communication between the client
68 // and heapprofd. The basic format of a record sent by the client is
69 // record size (uint64_t) | record type (RecordType = uint64_t) | record
70 // If record type is Malloc, the record format is AllocMetdata | raw stack.
71 // If the record type is Free, the record is a FreeEntry.
72 // If record type is HeapName, the record is a HeapName.
73 // On connect, heapprofd sends one ClientConfiguration struct over the control
74 // socket.
75
76 // Use uint64_t to make sure the following data is aligned as 64bit is the
77 // strongest alignment requirement.
78
79 struct ClientConfigurationHeap {
80 char name[HEAPPROFD_HEAP_NAME_SZ];
81 PERFETTO_CROSS_ABI_ALIGNED(uint64_t) interval;
82 };
83
84 struct ClientConfiguration {
85 // On average, sample one allocation every interval bytes,
86 // If interval == 1, sample every allocation.
87 // Must be >= 1.
88 PERFETTO_CROSS_ABI_ALIGNED(uint64_t) default_interval;
89 PERFETTO_CROSS_ABI_ALIGNED(uint64_t) block_client_timeout_us;
90 PERFETTO_CROSS_ABI_ALIGNED(uint64_t) num_heaps;
91 PERFETTO_CROSS_ABI_ALIGNED(uint64_t) adaptive_sampling_shmem_threshold;
92 PERFETTO_CROSS_ABI_ALIGNED(uint64_t)
93 adaptive_sampling_max_sampling_interval_bytes;
94 alignas(8) ClientConfigurationHeap heaps[64];
95 PERFETTO_CROSS_ABI_ALIGNED(bool) block_client;
96 PERFETTO_CROSS_ABI_ALIGNED(bool) disable_fork_teardown;
97 PERFETTO_CROSS_ABI_ALIGNED(bool) disable_vfork_detection;
98 PERFETTO_CROSS_ABI_ALIGNED(bool) all_heaps;
99 // Just double check that the array sizes are in correct order.
100 };
101
102 enum class RecordType : uint64_t {
103 Free = 0,
104 Malloc = 1,
105 HeapName = 2,
106 };
107
108 // Make the whole struct 8-aligned. This is to make sizeof(AllocMetdata)
109 // the same on 32 and 64-bit.
110 struct alignas(8) AllocMetadata {
111 PERFETTO_CROSS_ABI_ALIGNED(uint64_t) sequence_number;
112 // Size of the allocation that was made.
113 PERFETTO_CROSS_ABI_ALIGNED(uint64_t) alloc_size;
114 // Total number of bytes attributed to this allocation.
115 PERFETTO_CROSS_ABI_ALIGNED(uint64_t) sample_size;
116 // Pointer returned by malloc(2) for this allocation.
117 PERFETTO_CROSS_ABI_ALIGNED(uint64_t) alloc_address;
118 // Current value of the stack pointer.
119 PERFETTO_CROSS_ABI_ALIGNED(uint64_t) stack_pointer;
120 PERFETTO_CROSS_ABI_ALIGNED(uint64_t) clock_monotonic_coarse_timestamp;
121 // unwindstack::AsmGetRegs assumes this is aligned.
122 alignas(8) char register_data[kMaxRegisterDataSize];
123 PERFETTO_CROSS_ABI_ALIGNED(uint32_t) heap_id;
124 // CPU architecture of the client.
125 PERFETTO_CROSS_ABI_ALIGNED(unwindstack::ArchEnum) arch;
126 };
127
128 struct FreeEntry {
129 PERFETTO_CROSS_ABI_ALIGNED(uint64_t) sequence_number;
130 PERFETTO_CROSS_ABI_ALIGNED(uint64_t) addr;
131 PERFETTO_CROSS_ABI_ALIGNED(uint32_t) heap_id;
132 };
133
134 struct HeapName {
135 PERFETTO_CROSS_ABI_ALIGNED(uint64_t) sample_interval;
136 PERFETTO_CROSS_ABI_ALIGNED(uint32_t) heap_id;
137 PERFETTO_CROSS_ABI_ALIGNED(char) heap_name[HEAPPROFD_HEAP_NAME_SZ];
138 };
139
140 // Make sure the sizes do not change on different architectures.
141 static_assert(sizeof(AllocMetadata) == 328,
142 "AllocMetadata needs to be the same size across ABIs.");
143 static_assert(sizeof(FreeEntry) == 24,
144 "FreeEntry needs to be the same size across ABIs.");
145 static_assert(sizeof(HeapName) == 80,
146 "HeapName needs to be the same size across ABIs.");
147 static_assert(sizeof(ClientConfiguration) == 4656,
148 "ClientConfiguration needs to be the same size across ABIs.");
149
150 enum HandshakeFDs : size_t {
151 kHandshakeMaps = 0,
152 kHandshakeMem,
153 kHandshakeSize,
154 };
155
156 struct WireMessage {
157 RecordType record_type;
158
159 AllocMetadata* alloc_header;
160 FreeEntry* free_header;
161 HeapName* heap_name_header;
162
163 char* payload;
164 size_t payload_size;
165 };
166
167 int64_t SendWireMessage(SharedRingBuffer* buf, const WireMessage& msg);
168
169 // Parse message received over the wire.
170 // |buf| has to outlive |out|.
171 // If buf is not a valid message, return false.
172 bool ReceiveWireMessage(char* buf, size_t size, WireMessage* out);
173
174 uint64_t GetHeapSamplingInterval(const ClientConfiguration& cli_config,
175 const char* heap_name);
176
177 constexpr const char* kHeapprofdSocketEnvVar = "ANDROID_SOCKET_heapprofd";
178 constexpr const char* kHeapprofdSocketFile = "/dev/socket/heapprofd";
179
180 } // namespace profiling
181 } // namespace perfetto
182
183 #endif // SRC_PROFILING_MEMORY_WIRE_PROTOCOL_H_
184