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 #ifndef SRC_PROFILING_MEMORY_UNWINDING_H_ 18 #define SRC_PROFILING_MEMORY_UNWINDING_H_ 19 20 #include "perfetto/base/build_config.h" 21 22 #include <unwindstack/Maps.h> 23 #include <unwindstack/Unwinder.h> 24 25 #if PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD) 26 #include <unwindstack/DexFiles.h> 27 #include <unwindstack/JitDebug.h> 28 #endif 29 30 #include "perfetto/base/scoped_file.h" 31 #include "perfetto/base/thread_task_runner.h" 32 #include "perfetto/tracing/core/basic_types.h" 33 #include "src/profiling/memory/bookkeeping.h" 34 #include "src/profiling/memory/unwound_messages.h" 35 #include "src/profiling/memory/wire_protocol.h" 36 37 namespace perfetto { 38 namespace profiling { 39 40 // Read /proc/[pid]/maps from an open file descriptor. 41 // TODO(fmayer): Figure out deduplication to other maps. 42 class FileDescriptorMaps : public unwindstack::Maps { 43 public: 44 FileDescriptorMaps(base::ScopedFile fd); 45 46 FileDescriptorMaps(const FileDescriptorMaps&) = delete; 47 FileDescriptorMaps& operator=(const FileDescriptorMaps&) = delete; 48 FileDescriptorMaps(FileDescriptorMaps && m)49 FileDescriptorMaps(FileDescriptorMaps&& m) : Maps(std::move(m)) { 50 fd_ = std::move(m.fd_); 51 } 52 53 FileDescriptorMaps& operator=(FileDescriptorMaps&& m) { 54 if (&m != this) 55 fd_ = std::move(m.fd_); 56 Maps::operator=(std::move(m)); 57 return *this; 58 } 59 60 virtual ~FileDescriptorMaps() override = default; 61 62 bool Parse() override; 63 void Reset(); 64 65 private: 66 base::ScopedFile fd_; 67 }; 68 69 class FDMemory : public unwindstack::Memory { 70 public: 71 FDMemory(base::ScopedFile mem_fd); 72 size_t Read(uint64_t addr, void* dst, size_t size) override; 73 74 private: 75 base::ScopedFile mem_fd_; 76 }; 77 78 // Overlays size bytes pointed to by stack for addresses in [sp, sp + size). 79 // Addresses outside of that range are read from mem_fd, which should be an fd 80 // that opened /proc/[pid]/mem. 81 class StackOverlayMemory : public unwindstack::Memory { 82 public: 83 StackOverlayMemory(std::shared_ptr<unwindstack::Memory> mem, 84 uint64_t sp, 85 uint8_t* stack, 86 size_t size); 87 size_t Read(uint64_t addr, void* dst, size_t size) override; 88 89 private: 90 std::shared_ptr<unwindstack::Memory> mem_; 91 uint64_t sp_; 92 uint64_t stack_end_; 93 uint8_t* stack_; 94 }; 95 96 struct UnwindingMetadata { UnwindingMetadataUnwindingMetadata97 UnwindingMetadata(pid_t p, base::ScopedFile maps_fd, base::ScopedFile mem) 98 : pid(p), 99 maps(std::move(maps_fd)), 100 fd_mem(std::make_shared<FDMemory>(std::move(mem))) 101 #if PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD) 102 , 103 jit_debug(std::unique_ptr<unwindstack::JitDebug>( 104 new unwindstack::JitDebug(fd_mem))), 105 dex_files(std::unique_ptr<unwindstack::DexFiles>( 106 new unwindstack::DexFiles(fd_mem))) 107 #endif 108 { 109 PERFETTO_CHECK(maps.Parse()); 110 } ReparseMapsUnwindingMetadata111 void ReparseMaps() { 112 reparses++; 113 maps.Reset(); 114 maps.Parse(); 115 #if PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD) 116 jit_debug = std::unique_ptr<unwindstack::JitDebug>( 117 new unwindstack::JitDebug(fd_mem)); 118 dex_files = std::unique_ptr<unwindstack::DexFiles>( 119 new unwindstack::DexFiles(fd_mem)); 120 #endif 121 } 122 pid_t pid; 123 FileDescriptorMaps maps; 124 // The API of libunwindstack expects shared_ptr for Memory. 125 std::shared_ptr<unwindstack::Memory> fd_mem; 126 uint64_t reparses = 0; 127 #if PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD) 128 std::unique_ptr<unwindstack::JitDebug> jit_debug; 129 std::unique_ptr<unwindstack::DexFiles> dex_files; 130 #endif 131 }; 132 133 bool DoUnwind(WireMessage*, UnwindingMetadata* metadata, AllocRecord* out); 134 135 class UnwindingWorker : public base::UnixSocket::EventListener { 136 public: 137 class Delegate { 138 public: 139 virtual void PostAllocRecord(AllocRecord) = 0; 140 virtual void PostFreeRecord(FreeRecord) = 0; 141 virtual void PostSocketDisconnected(DataSourceInstanceID, 142 pid_t pid, 143 SharedRingBuffer::Stats stats) = 0; 144 virtual ~Delegate(); 145 }; 146 147 struct HandoffData { 148 DataSourceInstanceID data_source_instance_id; 149 base::UnixSocketRaw sock; 150 base::ScopedFile fds[kHandshakeSize]; 151 SharedRingBuffer shmem; 152 ClientConfiguration client_config; 153 }; 154 UnwindingWorker(Delegate * delegate,base::ThreadTaskRunner thread_task_runner)155 UnwindingWorker(Delegate* delegate, base::ThreadTaskRunner thread_task_runner) 156 : thread_task_runner_(std::move(thread_task_runner)), 157 delegate_(delegate) {} 158 159 // Public API safe to call from other threads. 160 void PostDisconnectSocket(pid_t pid); 161 void PostHandoffSocket(HandoffData); 162 163 // Implementation of UnixSocket::EventListener. 164 // Do not call explicitly. 165 void OnDisconnect(base::UnixSocket* self) override; OnNewIncomingConnection(base::UnixSocket *,std::unique_ptr<base::UnixSocket>)166 void OnNewIncomingConnection(base::UnixSocket*, 167 std::unique_ptr<base::UnixSocket>) override { 168 PERFETTO_DFATAL("This should not happen."); 169 } 170 void OnDataAvailable(base::UnixSocket* self) override; 171 172 public: 173 // static and public for testing/fuzzing 174 static void HandleBuffer(const SharedRingBuffer::Buffer& buf, 175 UnwindingMetadata* unwinding_metadata, 176 DataSourceInstanceID data_source_instance_id, 177 pid_t peer_pid, 178 Delegate* delegate); 179 180 private: 181 void HandleHandoffSocket(HandoffData data); 182 void HandleDisconnectSocket(pid_t pid); 183 184 void HandleUnwindBatch(pid_t); 185 186 struct ClientData { 187 DataSourceInstanceID data_source_instance_id; 188 std::unique_ptr<base::UnixSocket> sock; 189 UnwindingMetadata metadata; 190 SharedRingBuffer shmem; 191 ClientConfiguration client_config; 192 }; 193 194 // Task runner with a dedicated thread. Keep at the start of the data member 195 // declarations, such that it is valid during construction & destruction of 196 // the other members. 197 base::ThreadTaskRunner thread_task_runner_; 198 199 std::map<pid_t, ClientData> client_data_; 200 Delegate* delegate_; 201 }; 202 203 } // namespace profiling 204 } // namespace perfetto 205 206 #endif // SRC_PROFILING_MEMORY_UNWINDING_H_ 207