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