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_COMMON_UNWIND_SUPPORT_H_
18 #define SRC_PROFILING_COMMON_UNWIND_SUPPORT_H_
19 
20 // defines PERFETTO_BUILDFLAG
21 #include "perfetto/base/build_config.h"
22 
23 #include <memory>
24 #include <string>
25 
26 #include <unwindstack/Maps.h>
27 #include <unwindstack/Unwinder.h>
28 #if PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
29 #include <unwindstack/DexFiles.h>
30 #include <unwindstack/JitDebug.h>
31 #endif
32 
33 #include "perfetto/base/logging.h"
34 #include "perfetto/base/time.h"
35 #include "perfetto/ext/base/scoped_file.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 FDMaps : public unwindstack::Maps {
43  public:
44   explicit FDMaps(base::ScopedFile fd);
45 
46   FDMaps(const FDMaps&) = delete;
47   FDMaps& operator=(const FDMaps&) = delete;
48 
FDMaps(FDMaps && m)49   FDMaps(FDMaps&& m) : Maps(std::move(m)) { fd_ = std::move(m.fd_); }
50 
51   FDMaps& operator=(FDMaps&& m) {
52     if (&m != this)
53       fd_ = std::move(m.fd_);
54     Maps::operator=(std::move(m));
55     return *this;
56   }
57 
58   virtual ~FDMaps() override = default;
59 
60   bool Parse() override;
61   void Reset();
62 
63  private:
64   base::ScopedFile fd_;
65 };
66 
67 class FDMemory : public unwindstack::Memory {
68  public:
69   explicit FDMemory(base::ScopedFile mem_fd);
70   size_t Read(uint64_t addr, void* dst, size_t size) override;
71 
72  private:
73   base::ScopedFile mem_fd_;
74 };
75 
76 // Overlays size bytes pointed to by stack for addresses in [sp, sp + size).
77 // Addresses outside of that range are read from mem_fd, which should be an fd
78 // that opened /proc/[pid]/mem.
79 class StackOverlayMemory : public unwindstack::Memory {
80  public:
81   StackOverlayMemory(std::shared_ptr<unwindstack::Memory> mem,
82                      uint64_t sp,
83                      const uint8_t* stack,
84                      size_t size);
85   size_t Read(uint64_t addr, void* dst, size_t size) override;
86 
87  private:
88   std::shared_ptr<unwindstack::Memory> mem_;
89   const uint64_t sp_;
90   const uint64_t stack_end_;
91   const uint8_t* const stack_;
92 };
93 
94 struct UnwindingMetadata {
95   UnwindingMetadata(base::ScopedFile maps_fd, base::ScopedFile mem_fd);
96 
97   // move-only
98   UnwindingMetadata(const UnwindingMetadata&) = delete;
99   UnwindingMetadata& operator=(const UnwindingMetadata&) = delete;
100 
101   UnwindingMetadata(UnwindingMetadata&&) = default;
102   UnwindingMetadata& operator=(UnwindingMetadata&&) = default;
103 
104   void ReparseMaps();
105 
106 #if PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
107   unwindstack::JitDebug* GetJitDebug(unwindstack::ArchEnum arch);
108   unwindstack::DexFiles* GetDexFiles(unwindstack::ArchEnum arch);
109 #endif
110 
111   const std::string& GetBuildId(const unwindstack::FrameData& frame);
112 
113   std::string empty_string_;
114   FDMaps fd_maps;
115   // The API of libunwindstack expects shared_ptr for Memory.
116   std::shared_ptr<unwindstack::Memory> fd_mem;
117   uint64_t reparses = 0;
118   base::TimeMillis last_maps_reparse_time{0};
119 #if PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
120   std::unique_ptr<unwindstack::JitDebug> jit_debug;
121   std::unique_ptr<unwindstack::DexFiles> dex_files;
122 #endif
123 };
124 
125 std::string StringifyLibUnwindstackError(unwindstack::ErrorCode);
126 
127 }  // namespace profiling
128 }  // namespace perfetto
129 
130 #endif  // SRC_PROFILING_COMMON_UNWIND_SUPPORT_H_
131