1 /* 2 * Copyright (C) 2015 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 SIMPLE_PERF_OFFLINE_UNWINDER_H_ 18 #define SIMPLE_PERF_OFFLINE_UNWINDER_H_ 19 20 #include <memory> 21 #include <vector> 22 #include <unordered_map> 23 24 #include "perf_regs.h" 25 #include "thread_tree.h" 26 27 #if defined(__linux__) 28 #include <unwindstack/Maps.h> 29 #endif 30 31 namespace simpleperf { 32 struct ThreadEntry; 33 34 struct UnwindingResult { 35 // time used for unwinding, in ns. 36 uint64_t used_time; 37 enum { 38 UNKNOWN_REASON, 39 EXCEED_MAX_FRAMES_LIMIT, 40 ACCESS_REG_FAILED, 41 ACCESS_STACK_FAILED, 42 ACCESS_MEM_FAILED, 43 FIND_PROC_INFO_FAILED, 44 EXECUTE_DWARF_INSTRUCTION_FAILED, 45 DIFFERENT_ARCH, 46 MAP_MISSING, 47 } stop_reason; 48 union { 49 // for ACCESS_REG_FAILED 50 uint64_t regno; 51 // for ACCESS_MEM_FAILED and ACCESS_STACK_FAILED 52 uint64_t addr; 53 } stop_info; 54 uint64_t stack_start; 55 uint64_t stack_end; 56 }; 57 58 #if defined(__linux__) 59 class UnwindMaps : public unwindstack::Maps { 60 public: 61 void UpdateMaps(const MapSet& map_set); 62 63 private: 64 uint64_t version_ = 0u; 65 std::vector<const MapEntry*> entries_; 66 }; 67 68 class OfflineUnwinder { 69 public: 70 OfflineUnwinder(bool collect_stat); 71 72 bool UnwindCallChain(const ThreadEntry& thread, const RegSet& regs, const char* stack, 73 size_t stack_size, std::vector<uint64_t>* ips, std::vector<uint64_t>* sps); 74 HasStat()75 bool HasStat() const { 76 return collect_stat_; 77 } 78 GetUnwindingResult()79 const UnwindingResult& GetUnwindingResult() const { 80 return unwinding_result_; 81 } 82 IsCallChainBrokenForIncompleteJITDebugInfo()83 bool IsCallChainBrokenForIncompleteJITDebugInfo() { 84 return is_callchain_broken_for_incomplete_jit_debug_info_; 85 } 86 87 private: 88 bool collect_stat_; 89 UnwindingResult unwinding_result_; 90 bool is_callchain_broken_for_incomplete_jit_debug_info_; 91 92 std::unordered_map<pid_t, UnwindMaps> cached_maps_; 93 }; 94 95 #else // defined(__linux__) 96 97 class OfflineUnwinder { 98 public: OfflineUnwinder(bool)99 OfflineUnwinder(bool) {} UnwindCallChain(const ThreadEntry &,const RegSet &,const char *,size_t,std::vector<uint64_t> *,std::vector<uint64_t> *)100 bool UnwindCallChain(const ThreadEntry&, const RegSet&, const char*, size_t, 101 std::vector<uint64_t>*, std::vector<uint64_t>*) { 102 return false; 103 } 104 }; 105 106 #endif // !defined(__linux__) 107 108 } // namespace simpleperf 109 110 #endif // SIMPLE_PERF_OFFLINE_UNWINDER_H_ 111