• 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 #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