Back to home page

EIC code displayed by LXR

 
 

    


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