| /* | 
 |  * 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_ |