| /* |
| * Copyright (C) 2018 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| // The data types used for communication between heapprofd and the client |
| // embedded in processes that are being profiled. |
| |
| #ifndef SRC_PROFILING_MEMORY_WIRE_PROTOCOL_H_ |
| #define SRC_PROFILING_MEMORY_WIRE_PROTOCOL_H_ |
| |
| #include <inttypes.h> |
| #include <unwindstack/Elf.h> |
| #include <unwindstack/UserArm.h> |
| #include <unwindstack/UserArm64.h> |
| #include <unwindstack/UserMips.h> |
| #include <unwindstack/UserMips64.h> |
| #include <unwindstack/UserX86.h> |
| #include <unwindstack/UserX86_64.h> |
| |
| namespace perfetto { |
| namespace profiling { |
| |
| // Types needed for the wire format used for communication between the client |
| // and heapprofd. The basic format of a record is |
| // record size (uint64_t) | record type (RecordType = uint64_t) | record |
| // If record type is malloc, the record format is AllocMetdata | raw stack. |
| // If the record type is free, the record is a sequence of FreePageEntry. |
| |
| // Use uint64_t to make sure the following data is aligned as 64bit is the |
| // strongest alignment requirement. |
| |
| // C++11 std::max is not constexpr. |
| constexpr size_t constexpr_max(size_t x, size_t y) { |
| return x > y ? x : y; |
| } |
| |
| // clang-format makes this unreadable. Turning it off for this block. |
| // clang-format off |
| constexpr size_t kMaxRegisterDataSize = |
| constexpr_max( |
| constexpr_max( |
| constexpr_max( |
| constexpr_max( |
| constexpr_max( |
| sizeof(unwindstack::arm_user_regs), |
| sizeof(unwindstack::arm64_user_regs)), |
| sizeof(unwindstack::x86_user_regs)), |
| sizeof(unwindstack::x86_64_user_regs)), |
| sizeof(unwindstack::mips_user_regs)), |
| sizeof(unwindstack::mips64_user_regs) |
| ); |
| // clang-format on |
| |
| constexpr size_t kFreePageSize = 1024; |
| |
| enum class RecordType : uint64_t { |
| Free = 0, |
| Malloc = 1, |
| }; |
| |
| struct AllocMetadata { |
| uint64_t sequence_number; |
| // Size of the allocation that was made. |
| uint64_t alloc_size; |
| // Total number of bytes attributed to this allocation. |
| uint64_t total_size; |
| // Pointer returned by malloc(2) for this allocation. |
| uint64_t alloc_address; |
| // Current value of the stack pointer. |
| uint64_t stack_pointer; |
| // Offset of the data at stack_pointer from the start of this record. |
| uint64_t stack_pointer_offset; |
| alignas(uint64_t) char register_data[kMaxRegisterDataSize]; |
| // CPU architecture of the client. This determines the size of the |
| // register data that follows this struct. |
| unwindstack::ArchEnum arch; |
| }; |
| |
| struct FreePageEntry { |
| uint64_t sequence_number; |
| uint64_t addr; |
| }; |
| |
| struct ClientConfiguration { |
| // On average, sample one allocation every interval bytes, |
| // If interval == 1, sample every allocation. |
| // Must be >= 1. |
| uint64_t interval; |
| }; |
| |
| struct FreeMetadata { |
| uint64_t num_entries; |
| FreePageEntry entries[kFreePageSize]; |
| }; |
| |
| struct WireMessage { |
| RecordType record_type; |
| |
| AllocMetadata* alloc_header; |
| FreeMetadata* free_header; |
| |
| char* payload; |
| size_t payload_size; |
| }; |
| |
| bool SendWireMessage(int sock, const WireMessage& msg); |
| |
| // Parse message received over the wire. |
| // |buf| has to outlive |out|. |
| // If buf is not a valid message, return false. |
| bool ReceiveWireMessage(char* buf, size_t size, WireMessage* out); |
| |
| constexpr const char* kHeapprofdSocketEnvVar = "ANDROID_SOCKET_heapprofd"; |
| constexpr const char* kHeapprofdSocketFile = "/dev/socket/heapprofd"; |
| |
| } // namespace profiling |
| } // namespace perfetto |
| |
| #endif // SRC_PROFILING_MEMORY_WIRE_PROTOCOL_H_ |