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 enum UnwindStackErrorCode : uint8_t {
30   ERROR_NONE,                   // No error.
31   ERROR_MEMORY_INVALID,         // Memory read failed.
32   ERROR_UNWIND_INFO,            // Unable to use unwind information to unwind.
33   ERROR_UNSUPPORTED,            // Encountered unsupported feature.
34   ERROR_INVALID_MAP,            // Unwind in an invalid map.
35   ERROR_MAX_FRAMES_EXCEEDED,    // The number of frames exceed the total allowed.
36   ERROR_REPEATED_FRAME,         // The last frame has the same pc/sp as the next.
37   ERROR_INVALID_ELF,            // Unwind in an invalid elf.
38   ERROR_THREAD_DOES_NOT_EXIST,  // Attempt to unwind a local thread that does
39                                 // not exist.
40   ERROR_THREAD_TIMEOUT,         // Timeout trying to unwind a local thread.
41   ERROR_SYSTEM_CALL,            // System call failed while unwinding.
42   ERROR_BAD_ARCH,               // Arch invalid (none, or mismatched).
43   ERROR_MAPS_PARSE,             // Failed to parse maps data.
44   ERROR_INVALID_PARAMETER,      // Invalid parameter passed to function.
45   ERROR_MAX = ERROR_INVALID_PARAMETER,
46 };
47 
48 struct UnwindingResult {
49   // time used for unwinding, in ns.
50   uint64_t used_time;
51   // unwindstack::LastErrorCode()
52   uint64_t error_code;
53   // unwindstack::LastErrorAddress()
54   uint64_t error_addr;
55   uint64_t stack_start;
56   uint64_t stack_end;
57 };
58 
59 class OfflineUnwinder {
60  public:
61   static constexpr const char* META_KEY_ARM64_PAC_MASK = "arm64_pac_mask";
62 
63   static std::unique_ptr<OfflineUnwinder> Create(bool collect_stat);
~OfflineUnwinder()64   virtual ~OfflineUnwinder() {}
65 
66   virtual bool UnwindCallChain(const ThreadEntry& thread, const RegSet& regs, const char* stack,
67                                size_t stack_size, std::vector<uint64_t>* ips,
68                                std::vector<uint64_t>* sps) = 0;
69 
GetUnwindingResult()70   const UnwindingResult& GetUnwindingResult() const { return unwinding_result_; }
71 
IsCallChainBrokenForIncompleteJITDebugInfo()72   bool IsCallChainBrokenForIncompleteJITDebugInfo() {
73     return is_callchain_broken_for_incomplete_jit_debug_info_;
74   }
75 
76   static void CollectMetaInfo(std::unordered_map<std::string, std::string>* info_map);
LoadMetaInfo(const std::unordered_map<std::string,std::string> &)77   virtual void LoadMetaInfo(const std::unordered_map<std::string, std::string>&) {}
78 
79  protected:
OfflineUnwinder()80   OfflineUnwinder() {}
81 
82   UnwindingResult unwinding_result_;
83   bool is_callchain_broken_for_incomplete_jit_debug_info_ = false;
84 };
85 
86 }  // namespace simpleperf
87 
88 #endif  // SIMPLE_PERF_OFFLINE_UNWINDER_H_
89