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 
23 #include "perf_regs.h"
24 #include "thread_tree.h"
25 
26 namespace simpleperf {
27 struct ThreadEntry;
28 
29 struct UnwindingResult {
30   // time used for unwinding, in ns.
31   uint64_t used_time;
32   enum {
33     UNKNOWN_REASON,
34     EXCEED_MAX_FRAMES_LIMIT,
35     ACCESS_REG_FAILED,
36     ACCESS_STACK_FAILED,
37     ACCESS_MEM_FAILED,
38     FIND_PROC_INFO_FAILED,
39     EXECUTE_DWARF_INSTRUCTION_FAILED,
40     DIFFERENT_ARCH,
41     MAP_MISSING,
42   } stop_reason;
43   union {
44     // for ACCESS_REG_FAILED
45     uint64_t regno;
46     // for ACCESS_MEM_FAILED and ACCESS_STACK_FAILED
47     uint64_t addr;
48   } stop_info;
49   uint64_t stack_start;
50   uint64_t stack_end;
51 };
52 
53 class OfflineUnwinder {
54  public:
55   static constexpr const char* META_KEY_ARM64_PAC_MASK = "arm64_pac_mask";
56 
57   static std::unique_ptr<OfflineUnwinder> Create(bool collect_stat);
~OfflineUnwinder()58   virtual ~OfflineUnwinder() {}
59 
60   virtual bool UnwindCallChain(const ThreadEntry& thread, const RegSet& regs, const char* stack,
61                                size_t stack_size, std::vector<uint64_t>* ips,
62                                std::vector<uint64_t>* sps) = 0;
63 
GetUnwindingResult()64   const UnwindingResult& GetUnwindingResult() const {
65     return unwinding_result_;
66   }
67 
IsCallChainBrokenForIncompleteJITDebugInfo()68   bool IsCallChainBrokenForIncompleteJITDebugInfo() {
69     return is_callchain_broken_for_incomplete_jit_debug_info_;
70   }
71 
72   static void CollectMetaInfo(std::unordered_map<std::string, std::string>* info_map);
LoadMetaInfo(const std::unordered_map<std::string,std::string> &)73   virtual void LoadMetaInfo(const std::unordered_map<std::string, std::string>&) {}
74 
75  protected:
OfflineUnwinder()76   OfflineUnwinder() {}
77 
78   UnwindingResult unwinding_result_;
79   bool is_callchain_broken_for_incomplete_jit_debug_info_ = false;
80 };
81 
82 } // namespace simpleperf
83 
84 #endif  // SIMPLE_PERF_OFFLINE_UNWINDER_H_
85