• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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