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