xref: /aosp_15_r20/external/perfetto/src/profiling/perf/frame_pointer_unwinder.h (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1 /*
2  * Copyright (C) 2024 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 #ifndef SRC_PROFILING_PERF_FRAME_POINTER_UNWINDER_H_
17 #define SRC_PROFILING_PERF_FRAME_POINTER_UNWINDER_H_
18 
19 #include <stdint.h>
20 #include <memory>
21 #include <vector>
22 
23 #include <unwindstack/Error.h>
24 #include <unwindstack/MachineArm64.h>
25 #include <unwindstack/MachineRiscv64.h>
26 #include <unwindstack/MachineX86_64.h>
27 #include <unwindstack/Unwinder.h>
28 
29 namespace perfetto {
30 namespace profiling {
31 
32 class FramePointerUnwinder {
33  public:
FramePointerUnwinder(size_t max_frames,unwindstack::Maps * maps,unwindstack::Regs * regs,std::shared_ptr<unwindstack::Memory> process_memory,size_t stack_size)34   FramePointerUnwinder(size_t max_frames,
35                        unwindstack::Maps* maps,
36                        unwindstack::Regs* regs,
37                        std::shared_ptr<unwindstack::Memory> process_memory,
38                        size_t stack_size)
39       : max_frames_(max_frames),
40         maps_(maps),
41         regs_(regs),
42         process_memory_(process_memory),
43         stack_size_(stack_size),
44         arch_(regs->Arch()) {
45     stack_end_ = regs->sp() + stack_size;
46   }
47 
48   FramePointerUnwinder(const FramePointerUnwinder&) = delete;
49   FramePointerUnwinder& operator=(const FramePointerUnwinder&) = delete;
50 
51   void Unwind();
52 
53   // Disabling the resolving of names results in the function name being
54   // set to an empty string and the function offset being set to zero.
SetResolveNames(bool resolve)55   void SetResolveNames(bool resolve) { resolve_names_ = resolve; }
56 
LastErrorCode()57   unwindstack::ErrorCode LastErrorCode() const { return last_error_.code; }
warnings()58   uint64_t warnings() const { return warnings_; }
59 
ConsumeFrames()60   std::vector<unwindstack::FrameData> ConsumeFrames() {
61     std::vector<unwindstack::FrameData> frames = std::move(frames_);
62     frames_.clear();
63     return frames;
64   }
65 
IsArchSupported()66   bool IsArchSupported() const {
67     return arch_ == unwindstack::ARCH_ARM64 ||
68            arch_ == unwindstack::ARCH_X86_64;
69   }
70 
ClearErrors()71   void ClearErrors() {
72     warnings_ = unwindstack::WARNING_NONE;
73     last_error_.code = unwindstack::ERROR_NONE;
74     last_error_.address = 0;
75   }
76 
77  protected:
78   const size_t max_frames_;
79   unwindstack::Maps* maps_;
80   unwindstack::Regs* regs_;
81   std::vector<unwindstack::FrameData> frames_;
82   std::shared_ptr<unwindstack::Memory> process_memory_;
83   const size_t stack_size_;
84   unwindstack::ArchEnum arch_ = unwindstack::ARCH_UNKNOWN;
85   bool resolve_names_ = false;
86   size_t stack_end_;
87 
88   unwindstack::ErrorData last_error_;
89   uint64_t warnings_ = 0;
90 
91  private:
92   void TryUnwind();
93   // Given a frame pointer, returns the frame pointer of the calling stack
94   // frame, places the return address of the calling stack frame into
95   // `ret_addr` and stack pointer into `sp`.
96   uint64_t DecodeFrame(uint64_t fp, uint64_t* ret_addr, uint64_t* sp);
97   bool IsFrameValid(uint64_t fp, uint64_t sp);
98 };
99 
100 }  // namespace profiling
101 }  // namespace perfetto
102 
103 #endif  // SRC_PROFILING_PERF_FRAME_POINTER_UNWINDER_H_
104