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