|
|
|||
File indexing completed on 2026-05-10 08:42:55
0001 //===-- StackFrameList.h ----------------------------------------*- C++ -*-===// 0002 // 0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 0004 // See https://llvm.org/LICENSE.txt for license information. 0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 0006 // 0007 //===----------------------------------------------------------------------===// 0008 0009 #ifndef LLDB_TARGET_STACKFRAMELIST_H 0010 #define LLDB_TARGET_STACKFRAMELIST_H 0011 0012 #include <memory> 0013 #include <mutex> 0014 #include <shared_mutex> 0015 #include <vector> 0016 0017 #include "lldb/Target/StackFrame.h" 0018 0019 namespace lldb_private { 0020 0021 class ScriptedThread; 0022 0023 class StackFrameList { 0024 public: 0025 // Constructors and Destructors 0026 StackFrameList(Thread &thread, const lldb::StackFrameListSP &prev_frames_sp, 0027 bool show_inline_frames); 0028 0029 ~StackFrameList(); 0030 0031 /// Get the number of visible frames. Frames may be created if \p can_create 0032 /// is true. Synthetic (inline) frames expanded from the concrete frame #0 0033 /// (aka invisible frames) are not included in this count. 0034 uint32_t GetNumFrames(bool can_create = true); 0035 0036 /// Get the frame at index \p idx. Invisible frames cannot be indexed. 0037 lldb::StackFrameSP GetFrameAtIndex(uint32_t idx); 0038 0039 /// Get the first concrete frame with index greater than or equal to \p idx. 0040 /// Unlike \ref GetFrameAtIndex, this cannot return a synthetic frame. 0041 lldb::StackFrameSP GetFrameWithConcreteFrameIndex(uint32_t unwind_idx); 0042 0043 /// Retrieve the stack frame with the given ID \p stack_id. 0044 lldb::StackFrameSP GetFrameWithStackID(const StackID &stack_id); 0045 0046 /// Mark a stack frame as the currently selected frame and return its index. 0047 uint32_t SetSelectedFrame(lldb_private::StackFrame *frame); 0048 0049 /// Get the currently selected frame index. 0050 /// We should only call SelectMostRelevantFrame if (a) the user hasn't already 0051 /// selected a frame, and (b) if this really is a user facing 0052 /// "GetSelectedFrame". SMRF runs the frame recognizers which can do 0053 /// arbitrary work that ends up being dangerous to do internally. Also, 0054 /// for most internal uses we don't actually want the frame changed by the 0055 /// SMRF logic. So unless this is in a command or SB API, you should 0056 /// pass false here. 0057 uint32_t 0058 GetSelectedFrameIndex(SelectMostRelevant select_most_relevant_frame); 0059 0060 /// Mark a stack frame as the currently selected frame using the frame index 0061 /// \p idx. Like \ref GetFrameAtIndex, invisible frames cannot be selected. 0062 bool SetSelectedFrameByIndex(uint32_t idx); 0063 0064 /// If the current inline depth (i.e the number of invisible frames) is valid, 0065 /// subtract it from \p idx. Otherwise simply return \p idx. 0066 uint32_t GetVisibleStackFrameIndex(uint32_t idx) { 0067 if (m_current_inlined_depth < UINT32_MAX) 0068 return idx - m_current_inlined_depth; 0069 else 0070 return idx; 0071 } 0072 0073 /// Calculate and set the current inline depth. This may be used to update 0074 /// the StackFrameList's set of inline frames when execution stops, e.g when 0075 /// a breakpoint is hit. 0076 void CalculateCurrentInlinedDepth(); 0077 0078 /// If the currently selected frame comes from the currently selected thread, 0079 /// point the default file and line of the thread's target to the location 0080 /// specified by the frame. 0081 void SetDefaultFileAndLineToSelectedFrame(); 0082 0083 /// Clear the cache of frames. 0084 void Clear(); 0085 0086 void Dump(Stream *s); 0087 0088 /// If \p stack_frame_ptr is contained in this StackFrameList, return its 0089 /// wrapping shared pointer. 0090 lldb::StackFrameSP 0091 GetStackFrameSPForStackFramePtr(StackFrame *stack_frame_ptr); 0092 0093 size_t GetStatus(Stream &strm, uint32_t first_frame, uint32_t num_frames, 0094 bool show_frame_info, uint32_t num_frames_with_source, 0095 bool show_unique = false, bool show_hidden = false, 0096 const char *frame_marker = nullptr); 0097 0098 /// Returns whether we have currently fetched all the frames of a stack. 0099 bool WereAllFramesFetched() const; 0100 0101 protected: 0102 friend class Thread; 0103 friend class ScriptedThread; 0104 0105 /// Use this API to build a stack frame list (used for scripted threads, for 0106 /// instance.) This API is not meant for StackFrameLists that have unwinders 0107 /// and partake in lazy stack filling (using GetFramesUpTo). Rather if you 0108 /// are building StackFrameLists with this API, you should build the entire 0109 /// list before making it available for use. 0110 bool SetFrameAtIndex(uint32_t idx, lldb::StackFrameSP &frame_sp); 0111 0112 /// Ensures that frames up to (and including) `end_idx` are realized in the 0113 /// StackFrameList. `end_idx` can be larger than the actual number of frames, 0114 /// in which case all the frames will be fetched. Acquires the writer end of 0115 /// the list mutex. 0116 /// Returns true if the function was interrupted, false otherwise. 0117 /// Callers should first check (under the shared mutex) whether we need to 0118 /// fetch frames or not. 0119 bool GetFramesUpTo(uint32_t end_idx, InterruptionControl allow_interrupt); 0120 0121 // This should be called with either the reader or writer end of the list 0122 // mutex held: 0123 bool GetAllFramesFetched() const { 0124 return m_concrete_frames_fetched == UINT32_MAX; 0125 } 0126 0127 // This should be called with the writer end of the list mutex held. 0128 void SetAllFramesFetched() { m_concrete_frames_fetched = UINT32_MAX; } 0129 0130 bool DecrementCurrentInlinedDepth(); 0131 0132 void ResetCurrentInlinedDepth(); 0133 0134 uint32_t GetCurrentInlinedDepth(); 0135 0136 void SetCurrentInlinedDepth(uint32_t new_depth); 0137 0138 /// Calls into the stack frame recognizers and stop info to set the most 0139 /// relevant frame. This can call out to arbitrary user code so it can't 0140 /// hold the StackFrameList mutex. 0141 void SelectMostRelevantFrame(); 0142 0143 typedef std::vector<lldb::StackFrameSP> collection; 0144 typedef collection::iterator iterator; 0145 typedef collection::const_iterator const_iterator; 0146 0147 /// The thread this frame list describes. 0148 Thread &m_thread; 0149 0150 /// The old stack frame list. 0151 // TODO: The old stack frame list is used to fill in missing frame info 0152 // heuristically when it's otherwise unavailable (say, because the unwinder 0153 // fails). We should have stronger checks to make sure that this is a valid 0154 // source of information. 0155 lldb::StackFrameListSP m_prev_frames_sp; 0156 0157 /// A mutex for this frame list. The only public API that requires the 0158 /// unique lock is Clear. All other clients take the shared lock, though 0159 /// if we need more frames we may swap shared for unique to fulfill that 0160 /// requirement. 0161 mutable std::shared_mutex m_list_mutex; 0162 0163 // Setting the inlined depth should be protected against other attempts to 0164 // change it, but since it doesn't mutate the list itself, we can limit the 0165 // critical regions it produces by having a separate mutex. 0166 mutable std::mutex m_inlined_depth_mutex; 0167 0168 /// A cache of frames. This may need to be updated when the program counter 0169 /// changes. 0170 collection m_frames; 0171 0172 /// The currently selected frame. An optional is used to record whether anyone 0173 /// has set the selected frame on this stack yet. We only let recognizers 0174 /// change the frame if this is the first time GetSelectedFrame is called. 0175 std::optional<uint32_t> m_selected_frame_idx; 0176 0177 /// The number of concrete frames fetched while filling the frame list. This 0178 /// is only used when synthetic frames are enabled. 0179 uint32_t m_concrete_frames_fetched; 0180 0181 /// The number of synthetic function activations (invisible frames) expanded 0182 /// from the concrete frame #0 activation. 0183 // TODO: Use an optional instead of UINT32_MAX to denote invalid values. 0184 uint32_t m_current_inlined_depth; 0185 0186 /// The program counter value at the currently selected synthetic activation. 0187 /// This is only valid if m_current_inlined_depth is valid. 0188 // TODO: Use an optional instead of UINT32_MAX to denote invalid values. 0189 lldb::addr_t m_current_inlined_pc; 0190 0191 /// Whether or not to show synthetic (inline) frames. Immutable. 0192 const bool m_show_inlined_frames; 0193 0194 private: 0195 uint32_t SetSelectedFrameNoLock(lldb_private::StackFrame *frame); 0196 lldb::StackFrameSP 0197 GetFrameAtIndexNoLock(uint32_t idx, 0198 std::shared_lock<std::shared_mutex> &guard); 0199 0200 /// These two Fetch frames APIs and SynthesizeTailCallFrames are called in 0201 /// GetFramesUpTo, they are the ones that actually add frames. They must be 0202 /// called with the writer end of the list mutex held. 0203 0204 /// Returns true if fetching frames was interrupted, false otherwise. 0205 bool FetchFramesUpTo(uint32_t end_idx, InterruptionControl allow_interrupt); 0206 /// Not currently interruptible so returns void. 0207 void FetchOnlyConcreteFramesUpTo(uint32_t end_idx); 0208 void SynthesizeTailCallFrames(StackFrame &next_frame); 0209 0210 StackFrameList(const StackFrameList &) = delete; 0211 const StackFrameList &operator=(const StackFrameList &) = delete; 0212 }; 0213 0214 } // namespace lldb_private 0215 0216 #endif // LLDB_TARGET_STACKFRAMELIST_H
| [ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
|
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
|