1*6dbdd20aSAndroid Build Coastguard Worker /* 2*6dbdd20aSAndroid Build Coastguard Worker * Copyright (C) 2018 The Android Open Source Project 3*6dbdd20aSAndroid Build Coastguard Worker * 4*6dbdd20aSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*6dbdd20aSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*6dbdd20aSAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*6dbdd20aSAndroid Build Coastguard Worker * 8*6dbdd20aSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*6dbdd20aSAndroid Build Coastguard Worker * 10*6dbdd20aSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*6dbdd20aSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*6dbdd20aSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*6dbdd20aSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*6dbdd20aSAndroid Build Coastguard Worker * limitations under the License. 15*6dbdd20aSAndroid Build Coastguard Worker */ 16*6dbdd20aSAndroid Build Coastguard Worker 17*6dbdd20aSAndroid Build Coastguard Worker #ifndef SRC_PROFILING_MEMORY_CLIENT_H_ 18*6dbdd20aSAndroid Build Coastguard Worker #define SRC_PROFILING_MEMORY_CLIENT_H_ 19*6dbdd20aSAndroid Build Coastguard Worker 20*6dbdd20aSAndroid Build Coastguard Worker #include <stddef.h> 21*6dbdd20aSAndroid Build Coastguard Worker #include <sys/types.h> 22*6dbdd20aSAndroid Build Coastguard Worker 23*6dbdd20aSAndroid Build Coastguard Worker #include <atomic> 24*6dbdd20aSAndroid Build Coastguard Worker #include <condition_variable> 25*6dbdd20aSAndroid Build Coastguard Worker #include <mutex> 26*6dbdd20aSAndroid Build Coastguard Worker #include <vector> 27*6dbdd20aSAndroid Build Coastguard Worker 28*6dbdd20aSAndroid Build Coastguard Worker #include <unwindstack/Arch.h> 29*6dbdd20aSAndroid Build Coastguard Worker 30*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/base/build_config.h" 31*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/base/compiler.h" 32*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/base/unix_socket.h" 33*6dbdd20aSAndroid Build Coastguard Worker #include "src/profiling/memory/sampler.h" 34*6dbdd20aSAndroid Build Coastguard Worker #include "src/profiling/memory/shared_ring_buffer.h" 35*6dbdd20aSAndroid Build Coastguard Worker #include "src/profiling/memory/unhooked_allocator.h" 36*6dbdd20aSAndroid Build Coastguard Worker #include "src/profiling/memory/wire_protocol.h" 37*6dbdd20aSAndroid Build Coastguard Worker 38*6dbdd20aSAndroid Build Coastguard Worker namespace perfetto { 39*6dbdd20aSAndroid Build Coastguard Worker namespace profiling { 40*6dbdd20aSAndroid Build Coastguard Worker 41*6dbdd20aSAndroid Build Coastguard Worker struct StackRange { 42*6dbdd20aSAndroid Build Coastguard Worker const char* begin; 43*6dbdd20aSAndroid Build Coastguard Worker // One past the highest address part of the stack. 44*6dbdd20aSAndroid Build Coastguard Worker const char* end; 45*6dbdd20aSAndroid Build Coastguard Worker }; 46*6dbdd20aSAndroid Build Coastguard Worker 47*6dbdd20aSAndroid Build Coastguard Worker StackRange GetThreadStackRange(); 48*6dbdd20aSAndroid Build Coastguard Worker StackRange GetSigAltStackRange(); 49*6dbdd20aSAndroid Build Coastguard Worker StackRange GetMainThreadStackRange(); 50*6dbdd20aSAndroid Build Coastguard Worker 51*6dbdd20aSAndroid Build Coastguard Worker constexpr uint64_t kInfiniteTries = 0; 52*6dbdd20aSAndroid Build Coastguard Worker constexpr uint32_t kClientSockTimeoutMs = 1000; 53*6dbdd20aSAndroid Build Coastguard Worker 54*6dbdd20aSAndroid Build Coastguard Worker uint64_t GetMaxTries(const ClientConfiguration& client_config); 55*6dbdd20aSAndroid Build Coastguard Worker 56*6dbdd20aSAndroid Build Coastguard Worker // Profiling client, used to sample and record the malloc/free family of calls, 57*6dbdd20aSAndroid Build Coastguard Worker // and communicate the necessary state to a separate profiling daemon process. 58*6dbdd20aSAndroid Build Coastguard Worker // 59*6dbdd20aSAndroid Build Coastguard Worker // Created and owned by the malloc hooks. 60*6dbdd20aSAndroid Build Coastguard Worker // 61*6dbdd20aSAndroid Build Coastguard Worker // Methods of this class are thread-safe unless otherwise stated, in which case 62*6dbdd20aSAndroid Build Coastguard Worker // the caller needs to synchronize calls behind a mutex or similar. 63*6dbdd20aSAndroid Build Coastguard Worker // 64*6dbdd20aSAndroid Build Coastguard Worker // Implementation warning: this class should not use any heap, as otherwise its 65*6dbdd20aSAndroid Build Coastguard Worker // destruction would enter the possibly-hooked |free|, which can reference the 66*6dbdd20aSAndroid Build Coastguard Worker // Client itself. If avoiding the heap is not possible, then look at using 67*6dbdd20aSAndroid Build Coastguard Worker // UnhookedAllocator. 68*6dbdd20aSAndroid Build Coastguard Worker class Client { 69*6dbdd20aSAndroid Build Coastguard Worker public: 70*6dbdd20aSAndroid Build Coastguard Worker // Returns a client that is ready for sampling allocations, using the given 71*6dbdd20aSAndroid Build Coastguard Worker // socket (which should already be connected to heapprofd). 72*6dbdd20aSAndroid Build Coastguard Worker // 73*6dbdd20aSAndroid Build Coastguard Worker // Returns a shared_ptr since that is how the client will ultimately be used, 74*6dbdd20aSAndroid Build Coastguard Worker // and to take advantage of std::allocate_shared putting the object & the 75*6dbdd20aSAndroid Build Coastguard Worker // control block in one block of memory. 76*6dbdd20aSAndroid Build Coastguard Worker static std::shared_ptr<Client> CreateAndHandshake( 77*6dbdd20aSAndroid Build Coastguard Worker base::UnixSocketRaw sock, 78*6dbdd20aSAndroid Build Coastguard Worker UnhookedAllocator<Client> unhooked_allocator); 79*6dbdd20aSAndroid Build Coastguard Worker 80*6dbdd20aSAndroid Build Coastguard Worker static std::optional<base::UnixSocketRaw> ConnectToHeapprofd( 81*6dbdd20aSAndroid Build Coastguard Worker const std::string& sock_name); 82*6dbdd20aSAndroid Build Coastguard Worker 83*6dbdd20aSAndroid Build Coastguard Worker bool RecordMalloc(uint32_t heap_id, 84*6dbdd20aSAndroid Build Coastguard Worker uint64_t sample_size, 85*6dbdd20aSAndroid Build Coastguard Worker uint64_t alloc_size, 86*6dbdd20aSAndroid Build Coastguard Worker uint64_t alloc_address) PERFETTO_WARN_UNUSED_RESULT; 87*6dbdd20aSAndroid Build Coastguard Worker 88*6dbdd20aSAndroid Build Coastguard Worker // Add address to buffer of deallocations. Flushes the buffer if necessary. 89*6dbdd20aSAndroid Build Coastguard Worker bool RecordFree(uint32_t heap_id, 90*6dbdd20aSAndroid Build Coastguard Worker uint64_t alloc_address) PERFETTO_WARN_UNUSED_RESULT; 91*6dbdd20aSAndroid Build Coastguard Worker bool RecordHeapInfo(uint32_t heap_id, 92*6dbdd20aSAndroid Build Coastguard Worker const char* heap_name, 93*6dbdd20aSAndroid Build Coastguard Worker uint64_t interval); 94*6dbdd20aSAndroid Build Coastguard Worker AddClientSpinlockBlockedUs(size_t n)95*6dbdd20aSAndroid Build Coastguard Worker void AddClientSpinlockBlockedUs(size_t n) { 96*6dbdd20aSAndroid Build Coastguard Worker shmem_.AddClientSpinlockBlockedUs(n); 97*6dbdd20aSAndroid Build Coastguard Worker } 98*6dbdd20aSAndroid Build Coastguard Worker 99*6dbdd20aSAndroid Build Coastguard Worker // Public for std::allocate_shared. Use CreateAndHandshake() to create 100*6dbdd20aSAndroid Build Coastguard Worker // instances instead. 101*6dbdd20aSAndroid Build Coastguard Worker Client(base::UnixSocketRaw sock, 102*6dbdd20aSAndroid Build Coastguard Worker ClientConfiguration client_config, 103*6dbdd20aSAndroid Build Coastguard Worker SharedRingBuffer shmem, 104*6dbdd20aSAndroid Build Coastguard Worker pid_t pid_at_creation, 105*6dbdd20aSAndroid Build Coastguard Worker StackRange main_thread_stack_range); 106*6dbdd20aSAndroid Build Coastguard Worker 107*6dbdd20aSAndroid Build Coastguard Worker ~Client(); 108*6dbdd20aSAndroid Build Coastguard Worker client_config()109*6dbdd20aSAndroid Build Coastguard Worker const ClientConfiguration& client_config() { return client_config_; } adaptive_sampling_shmem_threshold()110*6dbdd20aSAndroid Build Coastguard Worker uint64_t adaptive_sampling_shmem_threshold() { 111*6dbdd20aSAndroid Build Coastguard Worker return client_config_.adaptive_sampling_shmem_threshold; 112*6dbdd20aSAndroid Build Coastguard Worker } adaptive_sampling_max_sampling_interval_bytes()113*6dbdd20aSAndroid Build Coastguard Worker uint64_t adaptive_sampling_max_sampling_interval_bytes() { 114*6dbdd20aSAndroid Build Coastguard Worker return client_config_.adaptive_sampling_max_sampling_interval_bytes; 115*6dbdd20aSAndroid Build Coastguard Worker } write_avail()116*6dbdd20aSAndroid Build Coastguard Worker uint64_t write_avail() { return shmem_.write_avail(); } 117*6dbdd20aSAndroid Build Coastguard Worker 118*6dbdd20aSAndroid Build Coastguard Worker bool IsConnected(); 119*6dbdd20aSAndroid Build Coastguard Worker 120*6dbdd20aSAndroid Build Coastguard Worker private: 121*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_BUILDFLAG(PERFETTO_ARCH_CPU_RISCV) && \ 122*6dbdd20aSAndroid Build Coastguard Worker !PERFETTO_HAS_BUILTIN_STACK_ADDRESS() 123*6dbdd20aSAndroid Build Coastguard Worker // For specific architectures, such as riscv, different calling conventions 124*6dbdd20aSAndroid Build Coastguard Worker // make a difference in the meaning of the frame pointer. (see comments in 125*6dbdd20aSAndroid Build Coastguard Worker // client.cc) So, we want to use other method to get the stack address for 126*6dbdd20aSAndroid Build Coastguard Worker // specific architectures such as riscv. 127*6dbdd20aSAndroid Build Coastguard Worker ssize_t GetStackRegister(unwindstack::ArchEnum arch); 128*6dbdd20aSAndroid Build Coastguard Worker uintptr_t GetStackAddress(char* reg_data, unwindstack::ArchEnum arch); 129*6dbdd20aSAndroid Build Coastguard Worker #endif 130*6dbdd20aSAndroid Build Coastguard Worker const char* GetStackEnd(const char* stacktop); 131*6dbdd20aSAndroid Build Coastguard Worker bool SendControlSocketByte() PERFETTO_WARN_UNUSED_RESULT; 132*6dbdd20aSAndroid Build Coastguard Worker int64_t SendWireMessageWithRetriesIfBlocking(const WireMessage&) 133*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_WARN_UNUSED_RESULT; 134*6dbdd20aSAndroid Build Coastguard Worker 135*6dbdd20aSAndroid Build Coastguard Worker bool IsPostFork(); 136*6dbdd20aSAndroid Build Coastguard Worker 137*6dbdd20aSAndroid Build Coastguard Worker ClientConfiguration client_config_; 138*6dbdd20aSAndroid Build Coastguard Worker uint64_t max_shmem_tries_; 139*6dbdd20aSAndroid Build Coastguard Worker base::UnixSocketRaw sock_; 140*6dbdd20aSAndroid Build Coastguard Worker 141*6dbdd20aSAndroid Build Coastguard Worker StackRange main_thread_stack_range_{nullptr, nullptr}; 142*6dbdd20aSAndroid Build Coastguard Worker std::atomic<uint64_t> 143*6dbdd20aSAndroid Build Coastguard Worker sequence_number_[base::ArraySize(ClientConfiguration{}.heaps)] = {}; 144*6dbdd20aSAndroid Build Coastguard Worker SharedRingBuffer shmem_; 145*6dbdd20aSAndroid Build Coastguard Worker 146*6dbdd20aSAndroid Build Coastguard Worker // Used to detect (during the slow path) the situation where the process has 147*6dbdd20aSAndroid Build Coastguard Worker // forked during profiling, and is performing malloc operations in the child. 148*6dbdd20aSAndroid Build Coastguard Worker // In this scenario, we want to stop profiling in the child, as otherwise 149*6dbdd20aSAndroid Build Coastguard Worker // it'll proceed to write to the same shared buffer & control socket (with 150*6dbdd20aSAndroid Build Coastguard Worker // duplicate sequence ids). 151*6dbdd20aSAndroid Build Coastguard Worker const pid_t pid_at_creation_; 152*6dbdd20aSAndroid Build Coastguard Worker bool detected_fork_ = false; 153*6dbdd20aSAndroid Build Coastguard Worker bool postfork_return_value_ = false; 154*6dbdd20aSAndroid Build Coastguard Worker }; 155*6dbdd20aSAndroid Build Coastguard Worker 156*6dbdd20aSAndroid Build Coastguard Worker } // namespace profiling 157*6dbdd20aSAndroid Build Coastguard Worker } // namespace perfetto 158*6dbdd20aSAndroid Build Coastguard Worker 159*6dbdd20aSAndroid Build Coastguard Worker #endif // SRC_PROFILING_MEMORY_CLIENT_H_ 160