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