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