1 //===-- StackFrameList.h ----------------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef LLDB_TARGET_STACKFRAMELIST_H 10 #define LLDB_TARGET_STACKFRAMELIST_H 11 12 #include <memory> 13 #include <mutex> 14 #include <vector> 15 16 #include "lldb/Target/StackFrame.h" 17 18 namespace lldb_private { 19 20 class ScriptedThread; 21 22 class StackFrameList { 23 public: 24 // Constructors and Destructors 25 StackFrameList(Thread &thread, const lldb::StackFrameListSP &prev_frames_sp, 26 bool show_inline_frames); 27 28 ~StackFrameList(); 29 30 /// Get the number of visible frames. Frames may be created if \p can_create 31 /// is true. Synthetic (inline) frames expanded from the concrete frame #0 32 /// (aka invisible frames) are not included in this count. 33 uint32_t GetNumFrames(bool can_create = true); 34 35 /// Get the frame at index \p idx. Invisible frames cannot be indexed. 36 lldb::StackFrameSP GetFrameAtIndex(uint32_t idx); 37 38 /// Get the first concrete frame with index greater than or equal to \p idx. 39 /// Unlike \ref GetFrameAtIndex, this cannot return a synthetic frame. 40 lldb::StackFrameSP GetFrameWithConcreteFrameIndex(uint32_t unwind_idx); 41 42 /// Retrieve the stack frame with the given ID \p stack_id. 43 lldb::StackFrameSP GetFrameWithStackID(const StackID &stack_id); 44 45 /// Mark a stack frame as the currently selected frame and return its index. 46 uint32_t SetSelectedFrame(lldb_private::StackFrame *frame); 47 48 /// Get the currently selected frame index. 49 /// We should only call SelectMostRelevantFrame if (a) the user hasn't already 50 /// selected a frame, and (b) if this really is a user facing 51 /// "GetSelectedFrame". SMRF runs the frame recognizers which can do 52 /// arbitrary work that ends up being dangerous to do internally. Also, 53 /// for most internal uses we don't actually want the frame changed by the 54 /// SMRF logic. So unless this is in a command or SB API, you should 55 /// pass false here. 56 uint32_t 57 GetSelectedFrameIndex(SelectMostRelevant select_most_relevant_frame); 58 59 /// Mark a stack frame as the currently selected frame using the frame index 60 /// \p idx. Like \ref GetFrameAtIndex, invisible frames cannot be selected. 61 bool SetSelectedFrameByIndex(uint32_t idx); 62 63 /// If the current inline depth (i.e the number of invisible frames) is valid, 64 /// subtract it from \p idx. Otherwise simply return \p idx. GetVisibleStackFrameIndex(uint32_t idx)65 uint32_t GetVisibleStackFrameIndex(uint32_t idx) { 66 if (m_current_inlined_depth < UINT32_MAX) 67 return idx - m_current_inlined_depth; 68 else 69 return idx; 70 } 71 72 /// Calculate and set the current inline depth. This may be used to update 73 /// the StackFrameList's set of inline frames when execution stops, e.g when 74 /// a breakpoint is hit. 75 void CalculateCurrentInlinedDepth(); 76 77 /// If the currently selected frame comes from the currently selected thread, 78 /// point the default file and line of the thread's target to the location 79 /// specified by the frame. 80 void SetDefaultFileAndLineToSelectedFrame(); 81 82 /// Clear the cache of frames. 83 void Clear(); 84 85 void Dump(Stream *s); 86 87 /// If \p stack_frame_ptr is contained in this StackFrameList, return its 88 /// wrapping shared pointer. 89 lldb::StackFrameSP 90 GetStackFrameSPForStackFramePtr(StackFrame *stack_frame_ptr); 91 92 size_t GetStatus(Stream &strm, uint32_t first_frame, uint32_t num_frames, 93 bool show_frame_info, uint32_t num_frames_with_source, 94 bool show_unique = false, 95 const char *frame_marker = nullptr); 96 97 protected: 98 friend class Thread; 99 friend class ScriptedThread; 100 101 bool SetFrameAtIndex(uint32_t idx, lldb::StackFrameSP &frame_sp); 102 103 /// Realizes frames up to (and including) end_idx (which can be greater than 104 /// the actual number of frames.) 105 /// Returns true if the function was interrupted, false otherwise. 106 bool GetFramesUpTo(uint32_t end_idx, 107 InterruptionControl allow_interrupt = AllowInterruption); 108 109 void GetOnlyConcreteFramesUpTo(uint32_t end_idx, Unwind &unwinder); 110 111 void SynthesizeTailCallFrames(StackFrame &next_frame); 112 GetAllFramesFetched()113 bool GetAllFramesFetched() { return m_concrete_frames_fetched == UINT32_MAX; } 114 SetAllFramesFetched()115 void SetAllFramesFetched() { m_concrete_frames_fetched = UINT32_MAX; } 116 117 bool DecrementCurrentInlinedDepth(); 118 119 void ResetCurrentInlinedDepth(); 120 121 uint32_t GetCurrentInlinedDepth(); 122 123 void SetCurrentInlinedDepth(uint32_t new_depth); 124 125 void SelectMostRelevantFrame(); 126 127 typedef std::vector<lldb::StackFrameSP> collection; 128 typedef collection::iterator iterator; 129 typedef collection::const_iterator const_iterator; 130 131 /// The thread this frame list describes. 132 Thread &m_thread; 133 134 /// The old stack frame list. 135 // TODO: The old stack frame list is used to fill in missing frame info 136 // heuristically when it's otherwise unavailable (say, because the unwinder 137 // fails). We should have stronger checks to make sure that this is a valid 138 // source of information. 139 lldb::StackFrameListSP m_prev_frames_sp; 140 141 /// A mutex for this frame list. 142 // TODO: This mutex may not always be held when required. In particular, uses 143 // of the StackFrameList APIs in lldb_private::Thread look suspect. Consider 144 // passing around a lock_guard reference to enforce proper locking. 145 mutable std::recursive_mutex m_mutex; 146 147 /// A cache of frames. This may need to be updated when the program counter 148 /// changes. 149 collection m_frames; 150 151 /// The currently selected frame. An optional is used to record whether anyone 152 /// has set the selected frame on this stack yet. We only let recognizers 153 /// change the frame if this is the first time GetSelectedFrame is called. 154 std::optional<uint32_t> m_selected_frame_idx; 155 156 /// The number of concrete frames fetched while filling the frame list. This 157 /// is only used when synthetic frames are enabled. 158 uint32_t m_concrete_frames_fetched; 159 160 /// The number of synthetic function activations (invisible frames) expanded 161 /// from the concrete frame #0 activation. 162 // TODO: Use an optional instead of UINT32_MAX to denote invalid values. 163 uint32_t m_current_inlined_depth; 164 165 /// The program counter value at the currently selected synthetic activation. 166 /// This is only valid if m_current_inlined_depth is valid. 167 // TODO: Use an optional instead of UINT32_MAX to denote invalid values. 168 lldb::addr_t m_current_inlined_pc; 169 170 /// Whether or not to show synthetic (inline) frames. Immutable. 171 const bool m_show_inlined_frames; 172 173 private: 174 StackFrameList(const StackFrameList &) = delete; 175 const StackFrameList &operator=(const StackFrameList &) = delete; 176 }; 177 178 } // namespace lldb_private 179 180 #endif // LLDB_TARGET_STACKFRAMELIST_H 181