• 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 <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 "src/profiling/memory/shared_ring_buffer.h"
33 
34 namespace perfetto {
35 
36 namespace base {
37 class UnixSocketRaw;
38 }
39 
40 namespace profiling {
41 
42 struct ClientConfiguration {
43   // On average, sample one allocation every interval bytes,
44   // If interval == 1, sample every allocation.
45   // Must be >= 1.
46   uint64_t interval;
47   bool block_client;
48   uint64_t block_client_timeout_us;
49   bool disable_fork_teardown;
50   bool disable_vfork_detection;
51 };
52 
53 // Types needed for the wire format used for communication between the client
54 // and heapprofd. The basic format of a record is
55 // record size (uint64_t) | record type (RecordType = uint64_t) | record
56 // If record type is malloc, the record format is AllocMetdata | raw stack.
57 // If the record type is free, the record is a sequence of FreeBatchEntry.
58 
59 // Use uint64_t to make sure the following data is aligned as 64bit is the
60 // strongest alignment requirement.
61 
62 // C++11 std::max is not constexpr.
constexpr_max(size_t x,size_t y)63 constexpr size_t constexpr_max(size_t x, size_t y) {
64   return x > y ? x : y;
65 }
66 
67 // clang-format makes this unreadable. Turning it off for this block.
68 // clang-format off
69 constexpr size_t kMaxRegisterDataSize =
70   constexpr_max(
71     constexpr_max(
72       constexpr_max(
73         constexpr_max(
74             constexpr_max(
75               sizeof(uint32_t) * unwindstack::ARM_REG_LAST,
76               sizeof(uint64_t) * unwindstack::ARM64_REG_LAST),
77             sizeof(uint32_t) * unwindstack::X86_REG_LAST),
78           sizeof(uint64_t) * unwindstack::X86_64_REG_LAST),
79         sizeof(uint32_t) * unwindstack::MIPS_REG_LAST),
80       sizeof(uint64_t) * unwindstack::MIPS64_REG_LAST
81   );
82 // clang-format on
83 
84 constexpr size_t kFreeBatchSize = 1024;
85 
86 enum class RecordType : uint64_t {
87   Free = 0,
88   Malloc = 1,
89 };
90 
91 struct AllocMetadata {
92   uint64_t sequence_number;
93   // Size of the allocation that was made.
94   uint64_t alloc_size;
95   // Total number of bytes attributed to this allocation.
96   uint64_t sample_size;
97   // Pointer returned by malloc(2) for this allocation.
98   uint64_t alloc_address;
99   // Current value of the stack pointer.
100   uint64_t stack_pointer;
101   // Offset of the data at stack_pointer from the start of this record.
102   uint64_t stack_pointer_offset;
103   uint64_t clock_monotonic_coarse_timestamp;
104   alignas(uint64_t) char register_data[kMaxRegisterDataSize];
105   // CPU architecture of the client.
106   unwindstack::ArchEnum arch;
107 };
108 
109 struct FreeBatchEntry {
110   uint64_t sequence_number;
111   uint64_t addr;
112 };
113 
114 struct FreeBatch {
115   uint64_t num_entries;
116   uint64_t clock_monotonic_coarse_timestamp;
117   FreeBatchEntry entries[kFreeBatchSize];
118 
FreeBatchFreeBatch119   FreeBatch() { num_entries = 0; }
120 };
121 
122 enum HandshakeFDs : size_t {
123   kHandshakeMaps = 0,
124   kHandshakeMem,
125   kHandshakePageIdle,
126   kHandshakeSize,
127 };
128 
129 struct WireMessage {
130   RecordType record_type;
131 
132   AllocMetadata* alloc_header;
133   FreeBatch* free_header;
134 
135   char* payload;
136   size_t payload_size;
137 };
138 
139 bool SendWireMessage(SharedRingBuffer* buf, const WireMessage& msg);
140 
141 // Parse message received over the wire.
142 // |buf| has to outlive |out|.
143 // If buf is not a valid message, return false.
144 bool ReceiveWireMessage(char* buf, size_t size, WireMessage* out);
145 
146 constexpr const char* kHeapprofdSocketEnvVar = "ANDROID_SOCKET_heapprofd";
147 constexpr const char* kHeapprofdSocketFile = "/dev/socket/heapprofd";
148 
149 }  // namespace profiling
150 }  // namespace perfetto
151 
152 #endif  // SRC_PROFILING_MEMORY_WIRE_PROTOCOL_H_
153