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 <shared_mutex> 15 #include <vector> 16 17 #include "lldb/Target/StackFrame.h" 18 19 namespace lldb_private { 20 21 class ScriptedThread; 22 23 class StackFrameList { 24 public: 25 // Constructors and Destructors 26 StackFrameList(Thread &thread, const lldb::StackFrameListSP &prev_frames_sp, 27 bool show_inline_frames); 28 29 ~StackFrameList(); 30 31 /// Get the number of visible frames. Frames may be created if \p can_create 32 /// is true. Synthetic (inline) frames expanded from the concrete frame #0 33 /// (aka invisible frames) are not included in this count. 34 uint32_t GetNumFrames(bool can_create = true); 35 36 /// Get the frame at index \p idx. Invisible frames cannot be indexed. 37 lldb::StackFrameSP GetFrameAtIndex(uint32_t idx); 38 39 /// Get the first concrete frame with index greater than or equal to \p idx. 40 /// Unlike \ref GetFrameAtIndex, this cannot return a synthetic frame. 41 lldb::StackFrameSP GetFrameWithConcreteFrameIndex(uint32_t unwind_idx); 42 43 /// Retrieve the stack frame with the given ID \p stack_id. 44 lldb::StackFrameSP GetFrameWithStackID(const StackID &stack_id); 45 46 /// Mark a stack frame as the currently selected frame and return its index. 47 uint32_t SetSelectedFrame(lldb_private::StackFrame *frame); 48 49 /// Get the currently selected frame index. 50 /// We should only call SelectMostRelevantFrame if (a) the user hasn't already 51 /// selected a frame, and (b) if this really is a user facing 52 /// "GetSelectedFrame". SMRF runs the frame recognizers which can do 53 /// arbitrary work that ends up being dangerous to do internally. Also, 54 /// for most internal uses we don't actually want the frame changed by the 55 /// SMRF logic. So unless this is in a command or SB API, you should 56 /// pass false here. 57 uint32_t 58 GetSelectedFrameIndex(SelectMostRelevant select_most_relevant_frame); 59 60 /// Mark a stack frame as the currently selected frame using the frame index 61 /// \p idx. Like \ref GetFrameAtIndex, invisible frames cannot be selected. 62 bool SetSelectedFrameByIndex(uint32_t idx); 63 64 /// If the current inline depth (i.e the number of invisible frames) is valid, 65 /// subtract it from \p idx. Otherwise simply return \p idx. 66 uint32_t GetVisibleStackFrameIndex(uint32_t idx) { 67 if (m_current_inlined_depth < UINT32_MAX) 68 return idx - m_current_inlined_depth; 69 else 70 return idx; 71 } 72 73 /// Calculate and set the current inline depth. This may be used to update 74 /// the StackFrameList's set of inline frames when execution stops, e.g when 75 /// a breakpoint is hit. 76 void CalculateCurrentInlinedDepth(); 77 78 /// If the currently selected frame comes from the currently selected thread, 79 /// point the default file and line of the thread's target to the location 80 /// specified by the frame. 81 void SetDefaultFileAndLineToSelectedFrame(); 82 83 /// Clear the cache of frames. 84 void Clear(); 85 86 void Dump(Stream *s); 87 88 /// If \p stack_frame_ptr is contained in this StackFrameList, return its 89 /// wrapping shared pointer. 90 lldb::StackFrameSP 91 GetStackFrameSPForStackFramePtr(StackFrame *stack_frame_ptr); 92 93 size_t GetStatus(Stream &strm, uint32_t first_frame, uint32_t num_frames, 94 bool show_frame_info, uint32_t num_frames_with_source, 95 bool show_unique = false, bool show_hidden = false, 96 const char *frame_marker = nullptr); 97 98 /// Returns whether we have currently fetched all the frames of a stack. 99 bool WereAllFramesFetched() const; 100 101 protected: 102 friend class Thread; 103 friend class ScriptedThread; 104 105 /// Use this API to build a stack frame list (used for scripted threads, for 106 /// instance.) This API is not meant for StackFrameLists that have unwinders 107 /// and partake in lazy stack filling (using GetFramesUpTo). Rather if you 108 /// are building StackFrameLists with this API, you should build the entire 109 /// list before making it available for use. 110 bool SetFrameAtIndex(uint32_t idx, lldb::StackFrameSP &frame_sp); 111 112 /// Ensures that frames up to (and including) `end_idx` are realized in the 113 /// StackFrameList. `end_idx` can be larger than the actual number of frames, 114 /// in which case all the frames will be fetched. Acquires the writer end of 115 /// the list mutex. 116 /// Returns true if the function was interrupted, false otherwise. 117 /// Callers should first check (under the shared mutex) whether we need to 118 /// fetch frames or not. 119 bool GetFramesUpTo(uint32_t end_idx, InterruptionControl allow_interrupt); 120 121 // This should be called with either the reader or writer end of the list 122 // mutex held: 123 bool GetAllFramesFetched() const { 124 return m_concrete_frames_fetched == UINT32_MAX; 125 } 126 127 // This should be called with the writer end of the list mutex held. 128 void SetAllFramesFetched() { m_concrete_frames_fetched = UINT32_MAX; } 129 130 bool DecrementCurrentInlinedDepth(); 131 132 void ResetCurrentInlinedDepth(); 133 134 uint32_t GetCurrentInlinedDepth(); 135 136 void SetCurrentInlinedDepth(uint32_t new_depth); 137 138 /// Calls into the stack frame recognizers and stop info to set the most 139 /// relevant frame. This can call out to arbitrary user code so it can't 140 /// hold the StackFrameList mutex. 141 void SelectMostRelevantFrame(); 142 143 typedef std::vector<lldb::StackFrameSP> collection; 144 typedef collection::iterator iterator; 145 typedef collection::const_iterator const_iterator; 146 147 /// The thread this frame list describes. 148 Thread &m_thread; 149 150 /// The old stack frame list. 151 // TODO: The old stack frame list is used to fill in missing frame info 152 // heuristically when it's otherwise unavailable (say, because the unwinder 153 // fails). We should have stronger checks to make sure that this is a valid 154 // source of information. 155 lldb::StackFrameListSP m_prev_frames_sp; 156 157 /// A mutex for this frame list. The only public API that requires the 158 /// unique lock is Clear. All other clients take the shared lock, though 159 /// if we need more frames we may swap shared for unique to fulfill that 160 /// requirement. 161 mutable std::shared_mutex m_list_mutex; 162 163 // Setting the inlined depth should be protected against other attempts to 164 // change it, but since it doesn't mutate the list itself, we can limit the 165 // critical regions it produces by having a separate mutex. 166 mutable std::mutex m_inlined_depth_mutex; 167 168 /// A cache of frames. This may need to be updated when the program counter 169 /// changes. 170 collection m_frames; 171 172 /// The currently selected frame. An optional is used to record whether anyone 173 /// has set the selected frame on this stack yet. We only let recognizers 174 /// change the frame if this is the first time GetSelectedFrame is called. 175 std::optional<uint32_t> m_selected_frame_idx; 176 177 /// The number of concrete frames fetched while filling the frame list. This 178 /// is only used when synthetic frames are enabled. 179 uint32_t m_concrete_frames_fetched; 180 181 /// The number of synthetic function activations (invisible frames) expanded 182 /// from the concrete frame #0 activation. 183 // TODO: Use an optional instead of UINT32_MAX to denote invalid values. 184 uint32_t m_current_inlined_depth; 185 186 /// The program counter value at the currently selected synthetic activation. 187 /// This is only valid if m_current_inlined_depth is valid. 188 // TODO: Use an optional instead of UINT32_MAX to denote invalid values. 189 lldb::addr_t m_current_inlined_pc; 190 191 /// Whether or not to show synthetic (inline) frames. Immutable. 192 const bool m_show_inlined_frames; 193 194 private: 195 uint32_t SetSelectedFrameNoLock(lldb_private::StackFrame *frame); 196 lldb::StackFrameSP 197 GetFrameAtIndexNoLock(uint32_t idx, 198 std::shared_lock<std::shared_mutex> &guard); 199 200 /// These two Fetch frames APIs and SynthesizeTailCallFrames are called in 201 /// GetFramesUpTo, they are the ones that actually add frames. They must be 202 /// called with the writer end of the list mutex held. 203 204 /// Returns true if fetching frames was interrupted, false otherwise. 205 bool FetchFramesUpTo(uint32_t end_idx, InterruptionControl allow_interrupt); 206 /// Not currently interruptible so returns void. 207 void FetchOnlyConcreteFramesUpTo(uint32_t end_idx); 208 void SynthesizeTailCallFrames(StackFrame &next_frame); 209 210 StackFrameList(const StackFrameList &) = delete; 211 const StackFrameList &operator=(const StackFrameList &) = delete; 212 }; 213 214 } // namespace lldb_private 215 216 #endif // LLDB_TARGET_STACKFRAMELIST_H 217