/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/include/lldb/Target/StackFrameList.h
Line | Count | Source |
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. |
65 | 8.42k | uint32_t GetVisibleStackFrameIndex(uint32_t idx) { |
66 | 8.42k | if (m_current_inlined_depth < UINT32_MAX) |
67 | 56 | return idx - m_current_inlined_depth; |
68 | 8.37k | else |
69 | 8.37k | return idx; |
70 | 8.42k | } |
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 | | |
113 | 76.6k | bool GetAllFramesFetched() { return m_concrete_frames_fetched == UINT32_MAX; } |
114 | | |
115 | 885 | 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 |