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