summaryrefslogtreecommitdiffstats
path: root/lldb/include/lldb/Target/StackFrameList.h
blob: 732a325d410722ae32aa0f9456b42242a8c9a083 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
//===-- StackFrameList.h ----------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef liblldb_StackFrameList_h_
#define liblldb_StackFrameList_h_

#include <memory>
#include <mutex>
#include <vector>

#include "lldb/Target/StackFrame.h"

namespace lldb_private {

class StackFrameList {
public:
  //------------------------------------------------------------------
  // Constructors and Destructors
  //------------------------------------------------------------------
  StackFrameList(Thread &thread, const lldb::StackFrameListSP &prev_frames_sp,
                 bool show_inline_frames);

  ~StackFrameList();

  /// Get the number of visible frames. Frames may be created if \p can_create
  /// is true. Synthetic (inline) frames expanded from the concrete frame #0
  /// (aka invisible frames) are not included in this count.
  uint32_t GetNumFrames(bool can_create = true);

  /// Get the frame at index \p idx. Invisible frames cannot be indexed.
  lldb::StackFrameSP GetFrameAtIndex(uint32_t idx);

  /// Get the first concrete frame with index greater than or equal to \p idx.
  /// Unlike \ref GetFrameAtIndex, this cannot return a synthetic frame.
  lldb::StackFrameSP GetFrameWithConcreteFrameIndex(uint32_t unwind_idx);

  /// Retrieve the stack frame with the given ID \p stack_id.
  lldb::StackFrameSP GetFrameWithStackID(const StackID &stack_id);

  /// Mark a stack frame as the currently selected frame and return its index.
  uint32_t SetSelectedFrame(lldb_private::StackFrame *frame);

  /// Get the currently selected frame index.
  uint32_t GetSelectedFrameIndex() const;

  /// Mark a stack frame as the currently selected frame using the frame index
  /// \p idx. Like \ref GetFrameAtIndex, invisible frames cannot be selected.
  bool SetSelectedFrameByIndex(uint32_t idx);

  /// If the current inline depth (i.e the number of invisible frames) is valid,
  /// subtract it from \p idx. Otherwise simply return \p idx.
  uint32_t GetVisibleStackFrameIndex(uint32_t idx) {
    if (m_current_inlined_depth < UINT32_MAX)
      return idx - m_current_inlined_depth;
    else
      return idx;
  }

  /// Calculate and set the current inline depth. This may be used to update
  /// the StackFrameList's set of inline frames when execution stops, e.g when
  /// a breakpoint is hit.
  void CalculateCurrentInlinedDepth();

  /// If the currently selected frame comes from the currently selected thread,
  /// point the default file and line of the thread's target to the location
  /// specified by the frame.
  void SetDefaultFileAndLineToSelectedFrame();

  /// Clear the cache of frames.
  void Clear();

  void Dump(Stream *s);

  /// If \p stack_frame_ptr is contained in this StackFrameList, return its
  /// wrapping shared pointer.
  lldb::StackFrameSP
  GetStackFrameSPForStackFramePtr(StackFrame *stack_frame_ptr);

  size_t GetStatus(Stream &strm, uint32_t first_frame, uint32_t num_frames,
                   bool show_frame_info, uint32_t num_frames_with_source,
                   bool show_unique = false,
                   const char *frame_marker = nullptr);

protected:
  friend class Thread;

  bool SetFrameAtIndex(uint32_t idx, lldb::StackFrameSP &frame_sp);

  static void Merge(std::unique_ptr<StackFrameList> &curr_ap,
                    lldb::StackFrameListSP &prev_sp);

  void GetFramesUpTo(uint32_t end_idx);

  void GetOnlyConcreteFramesUpTo(uint32_t end_idx, Unwind *unwinder);

  void SynthesizeTailCallFrames(StackFrame &next_frame);

  bool GetAllFramesFetched() { return m_concrete_frames_fetched == UINT32_MAX; }

  void SetAllFramesFetched() { m_concrete_frames_fetched = UINT32_MAX; }

  bool DecrementCurrentInlinedDepth();

  void ResetCurrentInlinedDepth();

  uint32_t GetCurrentInlinedDepth();

  void SetCurrentInlinedDepth(uint32_t new_depth);

  typedef std::vector<lldb::StackFrameSP> collection;
  typedef collection::iterator iterator;
  typedef collection::const_iterator const_iterator;

  /// The thread this frame list describes.
  Thread &m_thread;

  /// The old stack frame list.
  // TODO: The old stack frame list is used to fill in missing frame info
  // heuristically when it's otherwise unavailable (say, because the unwinder
  // fails). We should have stronger checks to make sure that this is a valid
  // source of information.
  lldb::StackFrameListSP m_prev_frames_sp;

  /// A mutex for this frame list.
  // TODO: This mutex may not always be held when required. In particular, uses
  // of the StackFrameList APIs in lldb_private::Thread look suspect. Consider
  // passing around a lock_guard reference to enforce proper locking.
  mutable std::recursive_mutex m_mutex;

  /// A cache of frames. This may need to be updated when the program counter
  /// changes.
  collection m_frames;

  /// The currently selected frame.
  uint32_t m_selected_frame_idx;

  /// The number of concrete frames fetched while filling the frame list. This
  /// is only used when synthetic frames are enabled.
  uint32_t m_concrete_frames_fetched;

  /// The number of synthetic function activations (invisible frames) expanded
  /// from the concrete frame #0 activation.
  // TODO: Use an optional instead of UINT32_MAX to denote invalid values.
  uint32_t m_current_inlined_depth;

  /// The program counter value at the currently selected synthetic activation.
  /// This is only valid if m_current_inlined_depth is valid.
  // TODO: Use an optional instead of UINT32_MAX to denote invalid values.
  lldb::addr_t m_current_inlined_pc;

  /// Whether or not to show synthetic (inline) frames. Immutable.
  const bool m_show_inlined_frames;

private:
  DISALLOW_COPY_AND_ASSIGN(StackFrameList);
};

} // namespace lldb_private

#endif // liblldb_StackFrameList_h_
OpenPOWER on IntegriCloud