1ac7ddfbfSEd Maste //===-- StackFrameList.cpp --------------------------------------*- C++ -*-===//
2ac7ddfbfSEd Maste //
3ac7ddfbfSEd Maste //                     The LLVM Compiler Infrastructure
4ac7ddfbfSEd Maste //
5ac7ddfbfSEd Maste // This file is distributed under the University of Illinois Open Source
6ac7ddfbfSEd Maste // License. See LICENSE.TXT for details.
7ac7ddfbfSEd Maste //
8ac7ddfbfSEd Maste //===----------------------------------------------------------------------===//
9ac7ddfbfSEd Maste 
104bb0738eSEd Maste #include "lldb/Target/StackFrameList.h"
11ac7ddfbfSEd Maste #include "lldb/Breakpoint/Breakpoint.h"
12435933ddSDimitry Andric #include "lldb/Breakpoint/BreakpointLocation.h"
13ac7ddfbfSEd Maste #include "lldb/Core/SourceManager.h"
14435933ddSDimitry Andric #include "lldb/Core/StreamFile.h"
15ac7ddfbfSEd Maste #include "lldb/Symbol/Block.h"
16ac7ddfbfSEd Maste #include "lldb/Symbol/Function.h"
17ac7ddfbfSEd Maste #include "lldb/Symbol/Symbol.h"
18ac7ddfbfSEd Maste #include "lldb/Target/Process.h"
19ac7ddfbfSEd Maste #include "lldb/Target/RegisterContext.h"
20ac7ddfbfSEd Maste #include "lldb/Target/StackFrame.h"
21ac7ddfbfSEd Maste #include "lldb/Target/StopInfo.h"
22ac7ddfbfSEd Maste #include "lldb/Target/Target.h"
23ac7ddfbfSEd Maste #include "lldb/Target/Thread.h"
24ac7ddfbfSEd Maste #include "lldb/Target/Unwind.h"
25f678e45dSDimitry Andric #include "lldb/Utility/Log.h"
26*b5893f02SDimitry Andric #include "llvm/ADT/SmallPtrSet.h"
27ac7ddfbfSEd Maste 
28ac7ddfbfSEd Maste //#define DEBUG_STACK_FRAMES 1
29ac7ddfbfSEd Maste 
30ac7ddfbfSEd Maste using namespace lldb;
31ac7ddfbfSEd Maste using namespace lldb_private;
32ac7ddfbfSEd Maste 
33ac7ddfbfSEd Maste //----------------------------------------------------------------------
34ac7ddfbfSEd Maste // StackFrameList constructor
35ac7ddfbfSEd Maste //----------------------------------------------------------------------
StackFrameList(Thread & thread,const lldb::StackFrameListSP & prev_frames_sp,bool show_inline_frames)36435933ddSDimitry Andric StackFrameList::StackFrameList(Thread &thread,
37435933ddSDimitry Andric                                const lldb::StackFrameListSP &prev_frames_sp,
38435933ddSDimitry Andric                                bool show_inline_frames)
39435933ddSDimitry Andric     : m_thread(thread), m_prev_frames_sp(prev_frames_sp), m_mutex(), m_frames(),
40435933ddSDimitry Andric       m_selected_frame_idx(0), m_concrete_frames_fetched(0),
41ac7ddfbfSEd Maste       m_current_inlined_depth(UINT32_MAX),
42ac7ddfbfSEd Maste       m_current_inlined_pc(LLDB_INVALID_ADDRESS),
43435933ddSDimitry Andric       m_show_inlined_frames(show_inline_frames) {
44435933ddSDimitry Andric   if (prev_frames_sp) {
45ac7ddfbfSEd Maste     m_current_inlined_depth = prev_frames_sp->m_current_inlined_depth;
46ac7ddfbfSEd Maste     m_current_inlined_pc = prev_frames_sp->m_current_inlined_pc;
47ac7ddfbfSEd Maste   }
48ac7ddfbfSEd Maste }
49ac7ddfbfSEd Maste 
~StackFrameList()50435933ddSDimitry Andric StackFrameList::~StackFrameList() {
514ba319b5SDimitry Andric   // Call clear since this takes a lock and clears the stack frame list in case
524ba319b5SDimitry Andric   // another thread is currently using this stack frame list
53ac7ddfbfSEd Maste   Clear();
54ac7ddfbfSEd Maste }
55ac7ddfbfSEd Maste 
CalculateCurrentInlinedDepth()56435933ddSDimitry Andric void StackFrameList::CalculateCurrentInlinedDepth() {
57ac7ddfbfSEd Maste   uint32_t cur_inlined_depth = GetCurrentInlinedDepth();
58435933ddSDimitry Andric   if (cur_inlined_depth == UINT32_MAX) {
59ac7ddfbfSEd Maste     ResetCurrentInlinedDepth();
60ac7ddfbfSEd Maste   }
61ac7ddfbfSEd Maste }
62ac7ddfbfSEd Maste 
GetCurrentInlinedDepth()63435933ddSDimitry Andric uint32_t StackFrameList::GetCurrentInlinedDepth() {
64435933ddSDimitry Andric   if (m_show_inlined_frames && m_current_inlined_pc != LLDB_INVALID_ADDRESS) {
65ac7ddfbfSEd Maste     lldb::addr_t cur_pc = m_thread.GetRegisterContext()->GetPC();
66435933ddSDimitry Andric     if (cur_pc != m_current_inlined_pc) {
67ac7ddfbfSEd Maste       m_current_inlined_pc = LLDB_INVALID_ADDRESS;
68ac7ddfbfSEd Maste       m_current_inlined_depth = UINT32_MAX;
69ac7ddfbfSEd Maste       Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
70ac7ddfbfSEd Maste       if (log && log->GetVerbose())
71435933ddSDimitry Andric         log->Printf(
72435933ddSDimitry Andric             "GetCurrentInlinedDepth: invalidating current inlined depth.\n");
73ac7ddfbfSEd Maste     }
74ac7ddfbfSEd Maste     return m_current_inlined_depth;
75435933ddSDimitry Andric   } else {
76ac7ddfbfSEd Maste     return UINT32_MAX;
77ac7ddfbfSEd Maste   }
78ac7ddfbfSEd Maste }
79ac7ddfbfSEd Maste 
ResetCurrentInlinedDepth()80435933ddSDimitry Andric void StackFrameList::ResetCurrentInlinedDepth() {
81*b5893f02SDimitry Andric   if (!m_show_inlined_frames)
82*b5893f02SDimitry Andric     return;
83*b5893f02SDimitry Andric 
844bb0738eSEd Maste   std::lock_guard<std::recursive_mutex> guard(m_mutex);
859f2f44ceSEd Maste 
86ac7ddfbfSEd Maste   GetFramesUpTo(0);
874bb0738eSEd Maste   if (m_frames.empty())
889f2f44ceSEd Maste     return;
89435933ddSDimitry Andric   if (!m_frames[0]->IsInlined()) {
90ac7ddfbfSEd Maste     m_current_inlined_depth = UINT32_MAX;
91ac7ddfbfSEd Maste     m_current_inlined_pc = LLDB_INVALID_ADDRESS;
92ac7ddfbfSEd Maste     Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
93ac7ddfbfSEd Maste     if (log && log->GetVerbose())
94435933ddSDimitry Andric       log->Printf(
95435933ddSDimitry Andric           "ResetCurrentInlinedDepth: Invalidating current inlined depth.\n");
96*b5893f02SDimitry Andric     return;
97*b5893f02SDimitry Andric   }
98*b5893f02SDimitry Andric 
994ba319b5SDimitry Andric   // We only need to do something special about inlined blocks when we are
1004ba319b5SDimitry Andric   // at the beginning of an inlined function:
101435933ddSDimitry Andric   // FIXME: We probably also have to do something special if the PC is at
102*b5893f02SDimitry Andric   // the END of an inlined function, which coincides with the end of either
103*b5893f02SDimitry Andric   // its containing function or another inlined function.
104ac7ddfbfSEd Maste 
105ac7ddfbfSEd Maste   Block *block_ptr = m_frames[0]->GetFrameBlock();
106*b5893f02SDimitry Andric   if (!block_ptr)
107*b5893f02SDimitry Andric     return;
108*b5893f02SDimitry Andric 
109ac7ddfbfSEd Maste   Address pc_as_address;
110*b5893f02SDimitry Andric   lldb::addr_t curr_pc = m_thread.GetRegisterContext()->GetPC();
111*b5893f02SDimitry Andric   pc_as_address.SetLoadAddress(curr_pc, &(m_thread.GetProcess()->GetTarget()));
112ac7ddfbfSEd Maste   AddressRange containing_range;
113*b5893f02SDimitry Andric   if (!block_ptr->GetRangeContainingAddress(pc_as_address, containing_range) ||
114*b5893f02SDimitry Andric       pc_as_address != containing_range.GetBaseAddress())
115*b5893f02SDimitry Andric     return;
116*b5893f02SDimitry Andric 
117*b5893f02SDimitry Andric   // If we got here because of a breakpoint hit, then set the inlined depth
118*b5893f02SDimitry Andric   // depending on where the breakpoint was set. If we got here because of a
119*b5893f02SDimitry Andric   // crash, then set the inlined depth to the deepest most block.  Otherwise,
120*b5893f02SDimitry Andric   // we stopped here naturally as the result of a step, so set ourselves in the
121*b5893f02SDimitry Andric   // containing frame of the whole set of nested inlines, so the user can then
122*b5893f02SDimitry Andric   // "virtually" step into the frames one by one, or next over the whole mess.
123*b5893f02SDimitry Andric   // Note: We don't have to handle being somewhere in the middle of the stack
124*b5893f02SDimitry Andric   // here, since ResetCurrentInlinedDepth doesn't get called if there is a
125*b5893f02SDimitry Andric   // valid inlined depth set.
126ac7ddfbfSEd Maste   StopInfoSP stop_info_sp = m_thread.GetStopInfo();
127*b5893f02SDimitry Andric   if (!stop_info_sp)
128*b5893f02SDimitry Andric     return;
129435933ddSDimitry Andric   switch (stop_info_sp->GetStopReason()) {
130ac7ddfbfSEd Maste   case eStopReasonWatchpoint:
131ac7ddfbfSEd Maste   case eStopReasonException:
132ac7ddfbfSEd Maste   case eStopReasonExec:
133ac7ddfbfSEd Maste   case eStopReasonSignal:
134*b5893f02SDimitry Andric     // In all these cases we want to stop in the deepest frame.
135ac7ddfbfSEd Maste     m_current_inlined_pc = curr_pc;
136ac7ddfbfSEd Maste     m_current_inlined_depth = 0;
137ac7ddfbfSEd Maste     break;
138435933ddSDimitry Andric   case eStopReasonBreakpoint: {
139*b5893f02SDimitry Andric     // FIXME: Figure out what this break point is doing, and set the inline
140*b5893f02SDimitry Andric     // depth appropriately.  Be careful to take into account breakpoints that
141*b5893f02SDimitry Andric     // implement step over prologue, since that should do the default
142*b5893f02SDimitry Andric     // calculation. For now, if the breakpoints corresponding to this hit are
143*b5893f02SDimitry Andric     // all internal, I set the stop location to the top of the inlined stack,
144*b5893f02SDimitry Andric     // since that will make things like stepping over prologues work right.
145*b5893f02SDimitry Andric     // But if there are any non-internal breakpoints I do to the bottom of the
146*b5893f02SDimitry Andric     // stack, since that was the old behavior.
147ac7ddfbfSEd Maste     uint32_t bp_site_id = stop_info_sp->GetValue();
148435933ddSDimitry Andric     BreakpointSiteSP bp_site_sp(
149*b5893f02SDimitry Andric         m_thread.GetProcess()->GetBreakpointSiteList().FindByID(bp_site_id));
150ac7ddfbfSEd Maste     bool all_internal = true;
151435933ddSDimitry Andric     if (bp_site_sp) {
152ac7ddfbfSEd Maste       uint32_t num_owners = bp_site_sp->GetNumberOfOwners();
153435933ddSDimitry Andric       for (uint32_t i = 0; i < num_owners; i++) {
154*b5893f02SDimitry Andric         Breakpoint &bp_ref = bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint();
155435933ddSDimitry Andric         if (!bp_ref.IsInternal()) {
156ac7ddfbfSEd Maste           all_internal = false;
157ac7ddfbfSEd Maste         }
158ac7ddfbfSEd Maste       }
159ac7ddfbfSEd Maste     }
160435933ddSDimitry Andric     if (!all_internal) {
161ac7ddfbfSEd Maste       m_current_inlined_pc = curr_pc;
162ac7ddfbfSEd Maste       m_current_inlined_depth = 0;
163ac7ddfbfSEd Maste       break;
164ac7ddfbfSEd Maste     }
165ac7ddfbfSEd Maste   }
1664bb0738eSEd Maste     LLVM_FALLTHROUGH;
167435933ddSDimitry Andric   default: {
168*b5893f02SDimitry Andric     // Otherwise, we should set ourselves at the container of the inlining, so
169*b5893f02SDimitry Andric     // that the user can descend into them. So first we check whether we have
170*b5893f02SDimitry Andric     // more than one inlined block sharing this PC:
171ac7ddfbfSEd Maste     int num_inlined_functions = 0;
172ac7ddfbfSEd Maste 
173ac7ddfbfSEd Maste     for (Block *container_ptr = block_ptr->GetInlinedParent();
1744bb0738eSEd Maste          container_ptr != nullptr;
175435933ddSDimitry Andric          container_ptr = container_ptr->GetInlinedParent()) {
176*b5893f02SDimitry Andric       if (!container_ptr->GetRangeContainingAddress(pc_as_address,
177*b5893f02SDimitry Andric                                                     containing_range))
178ac7ddfbfSEd Maste         break;
179ac7ddfbfSEd Maste       if (pc_as_address != containing_range.GetBaseAddress())
180ac7ddfbfSEd Maste         break;
181ac7ddfbfSEd Maste 
182ac7ddfbfSEd Maste       num_inlined_functions++;
183ac7ddfbfSEd Maste     }
184ac7ddfbfSEd Maste     m_current_inlined_pc = curr_pc;
185ac7ddfbfSEd Maste     m_current_inlined_depth = num_inlined_functions + 1;
186*b5893f02SDimitry Andric     Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
187ac7ddfbfSEd Maste     if (log && log->GetVerbose())
188435933ddSDimitry Andric       log->Printf("ResetCurrentInlinedDepth: setting inlined "
189435933ddSDimitry Andric                   "depth: %d 0x%" PRIx64 ".\n",
190435933ddSDimitry Andric                   m_current_inlined_depth, curr_pc);
191ac7ddfbfSEd Maste 
192*b5893f02SDimitry Andric     break;
193ac7ddfbfSEd Maste   }
194ac7ddfbfSEd Maste   }
195ac7ddfbfSEd Maste }
196ac7ddfbfSEd Maste 
DecrementCurrentInlinedDepth()197435933ddSDimitry Andric bool StackFrameList::DecrementCurrentInlinedDepth() {
198435933ddSDimitry Andric   if (m_show_inlined_frames) {
199ac7ddfbfSEd Maste     uint32_t current_inlined_depth = GetCurrentInlinedDepth();
200435933ddSDimitry Andric     if (current_inlined_depth != UINT32_MAX) {
201435933ddSDimitry Andric       if (current_inlined_depth > 0) {
202ac7ddfbfSEd Maste         m_current_inlined_depth--;
203ac7ddfbfSEd Maste         return true;
204ac7ddfbfSEd Maste       }
205ac7ddfbfSEd Maste     }
206ac7ddfbfSEd Maste   }
207ac7ddfbfSEd Maste   return false;
208ac7ddfbfSEd Maste }
209ac7ddfbfSEd Maste 
SetCurrentInlinedDepth(uint32_t new_depth)210435933ddSDimitry Andric void StackFrameList::SetCurrentInlinedDepth(uint32_t new_depth) {
211ac7ddfbfSEd Maste   m_current_inlined_depth = new_depth;
212ac7ddfbfSEd Maste   if (new_depth == UINT32_MAX)
213ac7ddfbfSEd Maste     m_current_inlined_pc = LLDB_INVALID_ADDRESS;
214ac7ddfbfSEd Maste   else
215ac7ddfbfSEd Maste     m_current_inlined_pc = m_thread.GetRegisterContext()->GetPC();
216ac7ddfbfSEd Maste }
217ac7ddfbfSEd Maste 
GetOnlyConcreteFramesUpTo(uint32_t end_idx,Unwind * unwinder)218*b5893f02SDimitry Andric void StackFrameList::GetOnlyConcreteFramesUpTo(uint32_t end_idx,
219*b5893f02SDimitry Andric                                                Unwind *unwinder) {
220*b5893f02SDimitry Andric   assert(m_thread.IsValid() && "Expected valid thread");
221*b5893f02SDimitry Andric   assert(m_frames.size() <= end_idx && "Expected there to be frames to fill");
222*b5893f02SDimitry Andric 
223*b5893f02SDimitry Andric   if (end_idx < m_concrete_frames_fetched)
224*b5893f02SDimitry Andric     return;
225*b5893f02SDimitry Andric 
226*b5893f02SDimitry Andric   if (!unwinder)
227*b5893f02SDimitry Andric     return;
228*b5893f02SDimitry Andric 
229*b5893f02SDimitry Andric   uint32_t num_frames = unwinder->GetFramesUpTo(end_idx);
230*b5893f02SDimitry Andric   if (num_frames <= end_idx + 1) {
231*b5893f02SDimitry Andric     // Done unwinding.
232*b5893f02SDimitry Andric     m_concrete_frames_fetched = UINT32_MAX;
233*b5893f02SDimitry Andric   }
234*b5893f02SDimitry Andric 
235*b5893f02SDimitry Andric   // Don't create the frames eagerly. Defer this work to GetFrameAtIndex,
236*b5893f02SDimitry Andric   // which can lazily query the unwinder to create frames.
237*b5893f02SDimitry Andric   m_frames.resize(num_frames);
238*b5893f02SDimitry Andric }
239*b5893f02SDimitry Andric 
240*b5893f02SDimitry Andric /// Find the unique path through the call graph from \p begin (with return PC
241*b5893f02SDimitry Andric /// \p return_pc) to \p end. On success this path is stored into \p path, and
242*b5893f02SDimitry Andric /// on failure \p path is unchanged.
FindInterveningFrames(Function & begin,Function & end,Target & target,addr_t return_pc,std::vector<Function * > & path,ModuleList & images,Log * log)243*b5893f02SDimitry Andric static void FindInterveningFrames(Function &begin, Function &end,
244*b5893f02SDimitry Andric                                   Target &target, addr_t return_pc,
245*b5893f02SDimitry Andric                                   std::vector<Function *> &path,
246*b5893f02SDimitry Andric                                   ModuleList &images, Log *log) {
247*b5893f02SDimitry Andric   LLDB_LOG(log, "Finding frames between {0} and {1}, retn-pc={2:x}",
248*b5893f02SDimitry Andric            begin.GetDisplayName(), end.GetDisplayName(), return_pc);
249*b5893f02SDimitry Andric 
250*b5893f02SDimitry Andric   // Find a non-tail calling edge with the correct return PC.
251*b5893f02SDimitry Andric   auto first_level_edges = begin.GetCallEdges();
252*b5893f02SDimitry Andric   if (log)
253*b5893f02SDimitry Andric     for (const CallEdge &edge : first_level_edges)
254*b5893f02SDimitry Andric       LLDB_LOG(log, "FindInterveningFrames: found call with retn-PC = {0:x}",
255*b5893f02SDimitry Andric                edge.GetReturnPCAddress(begin, target));
256*b5893f02SDimitry Andric   auto first_edge_it = std::lower_bound(
257*b5893f02SDimitry Andric       first_level_edges.begin(), first_level_edges.end(), return_pc,
258*b5893f02SDimitry Andric       [&](const CallEdge &edge, addr_t target_pc) {
259*b5893f02SDimitry Andric         return edge.GetReturnPCAddress(begin, target) < target_pc;
260*b5893f02SDimitry Andric       });
261*b5893f02SDimitry Andric   if (first_edge_it == first_level_edges.end() ||
262*b5893f02SDimitry Andric       first_edge_it->GetReturnPCAddress(begin, target) != return_pc) {
263*b5893f02SDimitry Andric     LLDB_LOG(log, "No call edge outgoing from {0} with retn-PC == {1:x}",
264*b5893f02SDimitry Andric              begin.GetDisplayName(), return_pc);
265*b5893f02SDimitry Andric     return;
266*b5893f02SDimitry Andric   }
267*b5893f02SDimitry Andric   CallEdge &first_edge = const_cast<CallEdge &>(*first_edge_it);
268*b5893f02SDimitry Andric 
269*b5893f02SDimitry Andric   // The first callee may not be resolved, or there may be nothing to fill in.
270*b5893f02SDimitry Andric   Function *first_callee = first_edge.GetCallee(images);
271*b5893f02SDimitry Andric   if (!first_callee) {
272*b5893f02SDimitry Andric     LLDB_LOG(log, "Could not resolve callee");
273*b5893f02SDimitry Andric     return;
274*b5893f02SDimitry Andric   }
275*b5893f02SDimitry Andric   if (first_callee == &end) {
276*b5893f02SDimitry Andric     LLDB_LOG(log, "Not searching further, first callee is {0} (retn-PC: {1:x})",
277*b5893f02SDimitry Andric              end.GetDisplayName(), return_pc);
278*b5893f02SDimitry Andric     return;
279*b5893f02SDimitry Andric   }
280*b5893f02SDimitry Andric 
281*b5893f02SDimitry Andric   // Run DFS on the tail-calling edges out of the first callee to find \p end.
282*b5893f02SDimitry Andric   // Fully explore the set of functions reachable from the first edge via tail
283*b5893f02SDimitry Andric   // calls in order to detect ambiguous executions.
284*b5893f02SDimitry Andric   struct DFS {
285*b5893f02SDimitry Andric     std::vector<Function *> active_path = {};
286*b5893f02SDimitry Andric     std::vector<Function *> solution_path = {};
287*b5893f02SDimitry Andric     llvm::SmallPtrSet<Function *, 2> visited_nodes = {};
288*b5893f02SDimitry Andric     bool ambiguous = false;
289*b5893f02SDimitry Andric     Function *end;
290*b5893f02SDimitry Andric     ModuleList &images;
291*b5893f02SDimitry Andric 
292*b5893f02SDimitry Andric     DFS(Function *end, ModuleList &images) : end(end), images(images) {}
293*b5893f02SDimitry Andric 
294*b5893f02SDimitry Andric     void search(Function *first_callee, std::vector<Function *> &path) {
295*b5893f02SDimitry Andric       dfs(first_callee);
296*b5893f02SDimitry Andric       if (!ambiguous)
297*b5893f02SDimitry Andric         path = std::move(solution_path);
298*b5893f02SDimitry Andric     }
299*b5893f02SDimitry Andric 
300*b5893f02SDimitry Andric     void dfs(Function *callee) {
301*b5893f02SDimitry Andric       // Found a path to the target function.
302*b5893f02SDimitry Andric       if (callee == end) {
303*b5893f02SDimitry Andric         if (solution_path.empty())
304*b5893f02SDimitry Andric           solution_path = active_path;
305*b5893f02SDimitry Andric         else
306*b5893f02SDimitry Andric           ambiguous = true;
307*b5893f02SDimitry Andric         return;
308*b5893f02SDimitry Andric       }
309*b5893f02SDimitry Andric 
310*b5893f02SDimitry Andric       // Terminate the search if tail recursion is found, or more generally if
311*b5893f02SDimitry Andric       // there's more than one way to reach a target. This errs on the side of
312*b5893f02SDimitry Andric       // caution: it conservatively stops searching when some solutions are
313*b5893f02SDimitry Andric       // still possible to save time in the average case.
314*b5893f02SDimitry Andric       if (!visited_nodes.insert(callee).second) {
315*b5893f02SDimitry Andric         ambiguous = true;
316*b5893f02SDimitry Andric         return;
317*b5893f02SDimitry Andric       }
318*b5893f02SDimitry Andric 
319*b5893f02SDimitry Andric       // Search the calls made from this callee.
320*b5893f02SDimitry Andric       active_path.push_back(callee);
321*b5893f02SDimitry Andric       for (CallEdge &edge : callee->GetTailCallingEdges()) {
322*b5893f02SDimitry Andric         Function *next_callee = edge.GetCallee(images);
323*b5893f02SDimitry Andric         if (!next_callee)
324*b5893f02SDimitry Andric           continue;
325*b5893f02SDimitry Andric 
326*b5893f02SDimitry Andric         dfs(next_callee);
327*b5893f02SDimitry Andric         if (ambiguous)
328*b5893f02SDimitry Andric           return;
329*b5893f02SDimitry Andric       }
330*b5893f02SDimitry Andric       active_path.pop_back();
331*b5893f02SDimitry Andric     }
332*b5893f02SDimitry Andric   };
333*b5893f02SDimitry Andric 
334*b5893f02SDimitry Andric   DFS(&end, images).search(first_callee, path);
335*b5893f02SDimitry Andric }
336*b5893f02SDimitry Andric 
337*b5893f02SDimitry Andric /// Given that \p next_frame will be appended to the frame list, synthesize
338*b5893f02SDimitry Andric /// tail call frames between the current end of the list and \p next_frame.
339*b5893f02SDimitry Andric /// If any frames are added, adjust the frame index of \p next_frame.
340*b5893f02SDimitry Andric ///
341*b5893f02SDimitry Andric ///   --------------
342*b5893f02SDimitry Andric ///   |    ...     | <- Completed frames.
343*b5893f02SDimitry Andric ///   --------------
344*b5893f02SDimitry Andric ///   | prev_frame |
345*b5893f02SDimitry Andric ///   --------------
346*b5893f02SDimitry Andric ///   |    ...     | <- Artificial frames inserted here.
347*b5893f02SDimitry Andric ///   --------------
348*b5893f02SDimitry Andric ///   | next_frame |
349*b5893f02SDimitry Andric ///   --------------
350*b5893f02SDimitry Andric ///   |    ...     | <- Not-yet-visited frames.
351*b5893f02SDimitry Andric ///   --------------
SynthesizeTailCallFrames(StackFrame & next_frame)352*b5893f02SDimitry Andric void StackFrameList::SynthesizeTailCallFrames(StackFrame &next_frame) {
353*b5893f02SDimitry Andric   TargetSP target_sp = next_frame.CalculateTarget();
354*b5893f02SDimitry Andric   if (!target_sp)
355*b5893f02SDimitry Andric     return;
356*b5893f02SDimitry Andric 
357*b5893f02SDimitry Andric   lldb::RegisterContextSP next_reg_ctx_sp = next_frame.GetRegisterContext();
358*b5893f02SDimitry Andric   if (!next_reg_ctx_sp)
359*b5893f02SDimitry Andric     return;
360*b5893f02SDimitry Andric 
361*b5893f02SDimitry Andric   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
362*b5893f02SDimitry Andric 
363*b5893f02SDimitry Andric   assert(!m_frames.empty() && "Cannot synthesize frames in an empty stack");
364*b5893f02SDimitry Andric   StackFrame &prev_frame = *m_frames.back().get();
365*b5893f02SDimitry Andric 
366*b5893f02SDimitry Andric   // Find the functions prev_frame and next_frame are stopped in. The function
367*b5893f02SDimitry Andric   // objects are needed to search the lazy call graph for intervening frames.
368*b5893f02SDimitry Andric   Function *prev_func =
369*b5893f02SDimitry Andric       prev_frame.GetSymbolContext(eSymbolContextFunction).function;
370*b5893f02SDimitry Andric   if (!prev_func) {
371*b5893f02SDimitry Andric     LLDB_LOG(log, "SynthesizeTailCallFrames: can't find previous function");
372*b5893f02SDimitry Andric     return;
373*b5893f02SDimitry Andric   }
374*b5893f02SDimitry Andric   Function *next_func =
375*b5893f02SDimitry Andric       next_frame.GetSymbolContext(eSymbolContextFunction).function;
376*b5893f02SDimitry Andric   if (!next_func) {
377*b5893f02SDimitry Andric     LLDB_LOG(log, "SynthesizeTailCallFrames: can't find next function");
378*b5893f02SDimitry Andric     return;
379*b5893f02SDimitry Andric   }
380*b5893f02SDimitry Andric 
381*b5893f02SDimitry Andric   // Try to find the unique sequence of (tail) calls which led from next_frame
382*b5893f02SDimitry Andric   // to prev_frame.
383*b5893f02SDimitry Andric   std::vector<Function *> path;
384*b5893f02SDimitry Andric   addr_t return_pc = next_reg_ctx_sp->GetPC();
385*b5893f02SDimitry Andric   Target &target = *target_sp.get();
386*b5893f02SDimitry Andric   ModuleList &images = next_frame.CalculateTarget()->GetImages();
387*b5893f02SDimitry Andric   FindInterveningFrames(*next_func, *prev_func, target, return_pc, path, images,
388*b5893f02SDimitry Andric                         log);
389*b5893f02SDimitry Andric 
390*b5893f02SDimitry Andric   // Push synthetic tail call frames.
391*b5893f02SDimitry Andric   for (Function *callee : llvm::reverse(path)) {
392*b5893f02SDimitry Andric     uint32_t frame_idx = m_frames.size();
393*b5893f02SDimitry Andric     uint32_t concrete_frame_idx = next_frame.GetConcreteFrameIndex();
394*b5893f02SDimitry Andric     addr_t cfa = LLDB_INVALID_ADDRESS;
395*b5893f02SDimitry Andric     bool cfa_is_valid = false;
396*b5893f02SDimitry Andric     addr_t pc =
397*b5893f02SDimitry Andric         callee->GetAddressRange().GetBaseAddress().GetLoadAddress(&target);
398*b5893f02SDimitry Andric     SymbolContext sc;
399*b5893f02SDimitry Andric     callee->CalculateSymbolContext(&sc);
400*b5893f02SDimitry Andric     auto synth_frame = std::make_shared<StackFrame>(
401*b5893f02SDimitry Andric         m_thread.shared_from_this(), frame_idx, concrete_frame_idx, cfa,
402*b5893f02SDimitry Andric         cfa_is_valid, pc, StackFrame::Kind::Artificial, &sc);
403*b5893f02SDimitry Andric     m_frames.push_back(synth_frame);
404*b5893f02SDimitry Andric     LLDB_LOG(log, "Pushed frame {0}", callee->GetDisplayName());
405*b5893f02SDimitry Andric   }
406*b5893f02SDimitry Andric 
407*b5893f02SDimitry Andric   // If any frames were created, adjust next_frame's index.
408*b5893f02SDimitry Andric   if (!path.empty())
409*b5893f02SDimitry Andric     next_frame.SetFrameIndex(m_frames.size());
410*b5893f02SDimitry Andric }
411*b5893f02SDimitry Andric 
GetFramesUpTo(uint32_t end_idx)412435933ddSDimitry Andric void StackFrameList::GetFramesUpTo(uint32_t end_idx) {
413*b5893f02SDimitry Andric   // Do not fetch frames for an invalid thread.
4144bb0738eSEd Maste   if (!m_thread.IsValid())
415ac7ddfbfSEd Maste     return;
416ac7ddfbfSEd Maste 
417435933ddSDimitry Andric   // We've already gotten more frames than asked for, or we've already finished
418435933ddSDimitry Andric   // unwinding, return.
419ac7ddfbfSEd Maste   if (m_frames.size() > end_idx || GetAllFramesFetched())
420ac7ddfbfSEd Maste     return;
421ac7ddfbfSEd Maste 
422ac7ddfbfSEd Maste   Unwind *unwinder = m_thread.GetUnwinder();
423ac7ddfbfSEd Maste 
424*b5893f02SDimitry Andric   if (!m_show_inlined_frames) {
425*b5893f02SDimitry Andric     GetOnlyConcreteFramesUpTo(end_idx, unwinder);
426*b5893f02SDimitry Andric     return;
427*b5893f02SDimitry Andric   }
428*b5893f02SDimitry Andric 
429ac7ddfbfSEd Maste #if defined(DEBUG_STACK_FRAMES)
430ac7ddfbfSEd Maste   StreamFile s(stdout, false);
431ac7ddfbfSEd Maste #endif
4324ba319b5SDimitry Andric   // If we are hiding some frames from the outside world, we need to add
4334ba319b5SDimitry Andric   // those onto the total count of frames to fetch.  However, we don't need
4344ba319b5SDimitry Andric   // to do that if end_idx is 0 since in that case we always get the first
4354ba319b5SDimitry Andric   // concrete frame and all the inlined frames below it...  And of course, if
4364ba319b5SDimitry Andric   // end_idx is UINT32_MAX that means get all, so just do that...
437ac7ddfbfSEd Maste 
438ac7ddfbfSEd Maste   uint32_t inlined_depth = 0;
439435933ddSDimitry Andric   if (end_idx > 0 && end_idx != UINT32_MAX) {
440ac7ddfbfSEd Maste     inlined_depth = GetCurrentInlinedDepth();
441435933ddSDimitry Andric     if (inlined_depth != UINT32_MAX) {
442ac7ddfbfSEd Maste       if (end_idx > 0)
443ac7ddfbfSEd Maste         end_idx += inlined_depth;
444ac7ddfbfSEd Maste     }
445ac7ddfbfSEd Maste   }
446ac7ddfbfSEd Maste 
447ac7ddfbfSEd Maste   StackFrameSP unwind_frame_sp;
448435933ddSDimitry Andric   do {
449ac7ddfbfSEd Maste     uint32_t idx = m_concrete_frames_fetched++;
4507aa51b79SEd Maste     lldb::addr_t pc = LLDB_INVALID_ADDRESS;
4517aa51b79SEd Maste     lldb::addr_t cfa = LLDB_INVALID_ADDRESS;
452435933ddSDimitry Andric     if (idx == 0) {
4534ba319b5SDimitry Andric       // We might have already created frame zero, only create it if we need
454*b5893f02SDimitry Andric       // to.
455435933ddSDimitry Andric       if (m_frames.empty()) {
456ac7ddfbfSEd Maste         RegisterContextSP reg_ctx_sp(m_thread.GetRegisterContext());
457ac7ddfbfSEd Maste 
458435933ddSDimitry Andric         if (reg_ctx_sp) {
459435933ddSDimitry Andric           const bool success =
460435933ddSDimitry Andric               unwinder && unwinder->GetFrameInfoAtIndex(idx, cfa, pc);
4614ba319b5SDimitry Andric           // There shouldn't be any way not to get the frame info for frame
4624ba319b5SDimitry Andric           // 0. But if the unwinder can't make one, lets make one by hand
463*b5893f02SDimitry Andric           // with the SP as the CFA and see if that gets any further.
464435933ddSDimitry Andric           if (!success) {
465ac7ddfbfSEd Maste             cfa = reg_ctx_sp->GetSP();
466ac7ddfbfSEd Maste             pc = reg_ctx_sp->GetPC();
467ac7ddfbfSEd Maste           }
468ac7ddfbfSEd Maste 
469ac7ddfbfSEd Maste           unwind_frame_sp.reset(new StackFrame(m_thread.shared_from_this(),
470*b5893f02SDimitry Andric                                                m_frames.size(), idx, reg_ctx_sp,
471*b5893f02SDimitry Andric                                                cfa, pc, nullptr));
472ac7ddfbfSEd Maste           m_frames.push_back(unwind_frame_sp);
473ac7ddfbfSEd Maste         }
474435933ddSDimitry Andric       } else {
475ac7ddfbfSEd Maste         unwind_frame_sp = m_frames.front();
476ac7ddfbfSEd Maste         cfa = unwind_frame_sp->m_id.GetCallFrameAddress();
477ac7ddfbfSEd Maste       }
478435933ddSDimitry Andric     } else {
479435933ddSDimitry Andric       const bool success =
480435933ddSDimitry Andric           unwinder && unwinder->GetFrameInfoAtIndex(idx, cfa, pc);
481435933ddSDimitry Andric       if (!success) {
482ac7ddfbfSEd Maste         // We've gotten to the end of the stack.
483ac7ddfbfSEd Maste         SetAllFramesFetched();
484ac7ddfbfSEd Maste         break;
485ac7ddfbfSEd Maste       }
48635617911SEd Maste       const bool cfa_is_valid = true;
487*b5893f02SDimitry Andric       unwind_frame_sp.reset(
488*b5893f02SDimitry Andric           new StackFrame(m_thread.shared_from_this(), m_frames.size(), idx, cfa,
489*b5893f02SDimitry Andric                          cfa_is_valid, pc, StackFrame::Kind::Regular, nullptr));
490*b5893f02SDimitry Andric 
491*b5893f02SDimitry Andric       // Create synthetic tail call frames between the previous frame and the
492*b5893f02SDimitry Andric       // newly-found frame. The new frame's index may change after this call,
493*b5893f02SDimitry Andric       // although its concrete index will stay the same.
494*b5893f02SDimitry Andric       SynthesizeTailCallFrames(*unwind_frame_sp.get());
495*b5893f02SDimitry Andric 
496ac7ddfbfSEd Maste       m_frames.push_back(unwind_frame_sp);
497ac7ddfbfSEd Maste     }
498ac7ddfbfSEd Maste 
4991c3bbb01SEd Maste     assert(unwind_frame_sp);
500435933ddSDimitry Andric     SymbolContext unwind_sc = unwind_frame_sp->GetSymbolContext(
501435933ddSDimitry Andric         eSymbolContextBlock | eSymbolContextFunction);
502ac7ddfbfSEd Maste     Block *unwind_block = unwind_sc.block;
503435933ddSDimitry Andric     if (unwind_block) {
504ac7ddfbfSEd Maste       Address curr_frame_address(unwind_frame_sp->GetFrameCodeAddress());
5054bb0738eSEd Maste       TargetSP target_sp = m_thread.CalculateTarget();
5064ba319b5SDimitry Andric       // Be sure to adjust the frame address to match the address that was
5074ba319b5SDimitry Andric       // used to lookup the symbol context above. If we are in the first
5084ba319b5SDimitry Andric       // concrete frame, then we lookup using the current address, else we
5094ba319b5SDimitry Andric       // decrement the address by one to get the correct location.
510435933ddSDimitry Andric       if (idx > 0) {
511435933ddSDimitry Andric         if (curr_frame_address.GetOffset() == 0) {
512435933ddSDimitry Andric           // If curr_frame_address points to the first address in a section
5134ba319b5SDimitry Andric           // then after adjustment it will point to an other section. In that
5144ba319b5SDimitry Andric           // case resolve the address again to the correct section plus
5154ba319b5SDimitry Andric           // offset form.
516435933ddSDimitry Andric           addr_t load_addr = curr_frame_address.GetOpcodeLoadAddress(
5174ba319b5SDimitry Andric               target_sp.get(), AddressClass::eCode);
518435933ddSDimitry Andric           curr_frame_address.SetOpcodeLoadAddress(
5194ba319b5SDimitry Andric               load_addr - 1, target_sp.get(), AddressClass::eCode);
520435933ddSDimitry Andric         } else {
521ac7ddfbfSEd Maste           curr_frame_address.Slide(-1);
5221c3bbb01SEd Maste         }
5231c3bbb01SEd Maste       }
524ac7ddfbfSEd Maste 
525ac7ddfbfSEd Maste       SymbolContext next_frame_sc;
526ac7ddfbfSEd Maste       Address next_frame_address;
527ac7ddfbfSEd Maste 
528435933ddSDimitry Andric       while (unwind_sc.GetParentOfInlinedScope(
529435933ddSDimitry Andric           curr_frame_address, next_frame_sc, next_frame_address)) {
5304bb0738eSEd Maste         next_frame_sc.line_entry.ApplyFileMappings(target_sp);
531435933ddSDimitry Andric         StackFrameSP frame_sp(
532435933ddSDimitry Andric             new StackFrame(m_thread.shared_from_this(), m_frames.size(), idx,
533435933ddSDimitry Andric                            unwind_frame_sp->GetRegisterContextSP(), cfa,
534435933ddSDimitry Andric                            next_frame_address, &next_frame_sc));
535ac7ddfbfSEd Maste 
536ac7ddfbfSEd Maste         m_frames.push_back(frame_sp);
537ac7ddfbfSEd Maste         unwind_sc = next_frame_sc;
538ac7ddfbfSEd Maste         curr_frame_address = next_frame_address;
539ac7ddfbfSEd Maste       }
540ac7ddfbfSEd Maste     }
541ac7ddfbfSEd Maste   } while (m_frames.size() - 1 < end_idx);
542ac7ddfbfSEd Maste 
543ac7ddfbfSEd Maste   // Don't try to merge till you've calculated all the frames in this stack.
544435933ddSDimitry Andric   if (GetAllFramesFetched() && m_prev_frames_sp) {
545ac7ddfbfSEd Maste     StackFrameList *prev_frames = m_prev_frames_sp.get();
546ac7ddfbfSEd Maste     StackFrameList *curr_frames = this;
547ac7ddfbfSEd Maste 
548ac7ddfbfSEd Maste #if defined(DEBUG_STACK_FRAMES)
549ac7ddfbfSEd Maste     s.PutCString("\nprev_frames:\n");
550ac7ddfbfSEd Maste     prev_frames->Dump(&s);
551ac7ddfbfSEd Maste     s.PutCString("\ncurr_frames:\n");
552ac7ddfbfSEd Maste     curr_frames->Dump(&s);
553ac7ddfbfSEd Maste     s.EOL();
554ac7ddfbfSEd Maste #endif
555ac7ddfbfSEd Maste     size_t curr_frame_num, prev_frame_num;
556ac7ddfbfSEd Maste 
557435933ddSDimitry Andric     for (curr_frame_num = curr_frames->m_frames.size(),
558435933ddSDimitry Andric         prev_frame_num = prev_frames->m_frames.size();
559ac7ddfbfSEd Maste          curr_frame_num > 0 && prev_frame_num > 0;
560435933ddSDimitry Andric          --curr_frame_num, --prev_frame_num) {
561ac7ddfbfSEd Maste       const size_t curr_frame_idx = curr_frame_num - 1;
562ac7ddfbfSEd Maste       const size_t prev_frame_idx = prev_frame_num - 1;
563ac7ddfbfSEd Maste       StackFrameSP curr_frame_sp(curr_frames->m_frames[curr_frame_idx]);
564ac7ddfbfSEd Maste       StackFrameSP prev_frame_sp(prev_frames->m_frames[prev_frame_idx]);
565ac7ddfbfSEd Maste 
566ac7ddfbfSEd Maste #if defined(DEBUG_STACK_FRAMES)
567ac7ddfbfSEd Maste       s.Printf("\n\nCurr frame #%u ", curr_frame_idx);
568ac7ddfbfSEd Maste       if (curr_frame_sp)
569ac7ddfbfSEd Maste         curr_frame_sp->Dump(&s, true, false);
570ac7ddfbfSEd Maste       else
571ac7ddfbfSEd Maste         s.PutCString("NULL");
572ac7ddfbfSEd Maste       s.Printf("\nPrev frame #%u ", prev_frame_idx);
573ac7ddfbfSEd Maste       if (prev_frame_sp)
574ac7ddfbfSEd Maste         prev_frame_sp->Dump(&s, true, false);
575ac7ddfbfSEd Maste       else
576ac7ddfbfSEd Maste         s.PutCString("NULL");
577ac7ddfbfSEd Maste #endif
578ac7ddfbfSEd Maste 
579ac7ddfbfSEd Maste       StackFrame *curr_frame = curr_frame_sp.get();
580ac7ddfbfSEd Maste       StackFrame *prev_frame = prev_frame_sp.get();
581ac7ddfbfSEd Maste 
5824bb0738eSEd Maste       if (curr_frame == nullptr || prev_frame == nullptr)
583ac7ddfbfSEd Maste         break;
584ac7ddfbfSEd Maste 
585*b5893f02SDimitry Andric       // Check the stack ID to make sure they are equal.
586ac7ddfbfSEd Maste       if (curr_frame->GetStackID() != prev_frame->GetStackID())
587ac7ddfbfSEd Maste         break;
588ac7ddfbfSEd Maste 
589ac7ddfbfSEd Maste       prev_frame->UpdatePreviousFrameFromCurrentFrame(*curr_frame);
5904ba319b5SDimitry Andric       // Now copy the fixed up previous frame into the current frames so the
591*b5893f02SDimitry Andric       // pointer doesn't change.
592ac7ddfbfSEd Maste       m_frames[curr_frame_idx] = prev_frame_sp;
593ac7ddfbfSEd Maste 
594ac7ddfbfSEd Maste #if defined(DEBUG_STACK_FRAMES)
595ac7ddfbfSEd Maste       s.Printf("\n    Copying previous frame to current frame");
596ac7ddfbfSEd Maste #endif
597ac7ddfbfSEd Maste     }
598*b5893f02SDimitry Andric     // We are done with the old stack frame list, we can release it now.
599ac7ddfbfSEd Maste     m_prev_frames_sp.reset();
600ac7ddfbfSEd Maste   }
601ac7ddfbfSEd Maste 
602ac7ddfbfSEd Maste #if defined(DEBUG_STACK_FRAMES)
603ac7ddfbfSEd Maste   s.PutCString("\n\nNew frames:\n");
604ac7ddfbfSEd Maste   Dump(&s);
605ac7ddfbfSEd Maste   s.EOL();
606ac7ddfbfSEd Maste #endif
607b952cd58SEd Maste }
608ac7ddfbfSEd Maste 
GetNumFrames(bool can_create)609435933ddSDimitry Andric uint32_t StackFrameList::GetNumFrames(bool can_create) {
6104bb0738eSEd Maste   std::lock_guard<std::recursive_mutex> guard(m_mutex);
611ac7ddfbfSEd Maste 
612ac7ddfbfSEd Maste   if (can_create)
613ac7ddfbfSEd Maste     GetFramesUpTo(UINT32_MAX);
614ac7ddfbfSEd Maste 
615*b5893f02SDimitry Andric   return GetVisibleStackFrameIndex(m_frames.size());
616ac7ddfbfSEd Maste }
617ac7ddfbfSEd Maste 
Dump(Stream * s)618435933ddSDimitry Andric void StackFrameList::Dump(Stream *s) {
6194bb0738eSEd Maste   if (s == nullptr)
620ac7ddfbfSEd Maste     return;
6214bb0738eSEd Maste 
6224bb0738eSEd Maste   std::lock_guard<std::recursive_mutex> guard(m_mutex);
623ac7ddfbfSEd Maste 
624ac7ddfbfSEd Maste   const_iterator pos, begin = m_frames.begin(), end = m_frames.end();
625435933ddSDimitry Andric   for (pos = begin; pos != end; ++pos) {
626ac7ddfbfSEd Maste     StackFrame *frame = (*pos).get();
6270127ef0fSEd Maste     s->Printf("%p: ", static_cast<void *>(frame));
628435933ddSDimitry Andric     if (frame) {
629ac7ddfbfSEd Maste       frame->GetStackID().Dump(s);
630ac7ddfbfSEd Maste       frame->DumpUsingSettingsFormat(s);
631435933ddSDimitry Andric     } else
632ac7ddfbfSEd Maste       s->Printf("frame #%u", (uint32_t)std::distance(begin, pos));
633ac7ddfbfSEd Maste     s->EOL();
634ac7ddfbfSEd Maste   }
635ac7ddfbfSEd Maste   s->EOL();
636ac7ddfbfSEd Maste }
637ac7ddfbfSEd Maste 
GetFrameAtIndex(uint32_t idx)638435933ddSDimitry Andric StackFrameSP StackFrameList::GetFrameAtIndex(uint32_t idx) {
639ac7ddfbfSEd Maste   StackFrameSP frame_sp;
6404bb0738eSEd Maste   std::lock_guard<std::recursive_mutex> guard(m_mutex);
641ac7ddfbfSEd Maste   uint32_t original_idx = idx;
642ac7ddfbfSEd Maste 
643ac7ddfbfSEd Maste   uint32_t inlined_depth = GetCurrentInlinedDepth();
644ac7ddfbfSEd Maste   if (inlined_depth != UINT32_MAX)
645ac7ddfbfSEd Maste     idx += inlined_depth;
646ac7ddfbfSEd Maste 
647ac7ddfbfSEd Maste   if (idx < m_frames.size())
648ac7ddfbfSEd Maste     frame_sp = m_frames[idx];
649ac7ddfbfSEd Maste 
650ac7ddfbfSEd Maste   if (frame_sp)
651ac7ddfbfSEd Maste     return frame_sp;
652ac7ddfbfSEd Maste 
6534ba319b5SDimitry Andric   // GetFramesUpTo will fill m_frames with as many frames as you asked for, if
6544ba319b5SDimitry Andric   // there are that many.  If there weren't then you asked for too many frames.
655ac7ddfbfSEd Maste   GetFramesUpTo(idx);
656435933ddSDimitry Andric   if (idx < m_frames.size()) {
657435933ddSDimitry Andric     if (m_show_inlined_frames) {
658435933ddSDimitry Andric       // When inline frames are enabled we actually create all the frames in
659435933ddSDimitry Andric       // GetFramesUpTo.
660ac7ddfbfSEd Maste       frame_sp = m_frames[idx];
661435933ddSDimitry Andric     } else {
662ac7ddfbfSEd Maste       Unwind *unwinder = m_thread.GetUnwinder();
663435933ddSDimitry Andric       if (unwinder) {
664ac7ddfbfSEd Maste         addr_t pc, cfa;
665435933ddSDimitry Andric         if (unwinder->GetFrameInfoAtIndex(idx, cfa, pc)) {
66635617911SEd Maste           const bool cfa_is_valid = true;
667*b5893f02SDimitry Andric           frame_sp.reset(new StackFrame(m_thread.shared_from_this(), idx, idx,
668*b5893f02SDimitry Andric                                         cfa, cfa_is_valid, pc,
669*b5893f02SDimitry Andric                                         StackFrame::Kind::Regular, nullptr));
670ac7ddfbfSEd Maste 
671435933ddSDimitry Andric           Function *function =
672435933ddSDimitry Andric               frame_sp->GetSymbolContext(eSymbolContextFunction).function;
673435933ddSDimitry Andric           if (function) {
6744ba319b5SDimitry Andric             // When we aren't showing inline functions we always use the top
6754ba319b5SDimitry Andric             // most function block as the scope.
676ac7ddfbfSEd Maste             frame_sp->SetSymbolContextScope(&function->GetBlock(false));
677435933ddSDimitry Andric           } else {
678435933ddSDimitry Andric             // Set the symbol scope from the symbol regardless if it is nullptr
679435933ddSDimitry Andric             // or valid.
680435933ddSDimitry Andric             frame_sp->SetSymbolContextScope(
681435933ddSDimitry Andric                 frame_sp->GetSymbolContext(eSymbolContextSymbol).symbol);
682ac7ddfbfSEd Maste           }
683ac7ddfbfSEd Maste           SetFrameAtIndex(idx, frame_sp);
684ac7ddfbfSEd Maste         }
685ac7ddfbfSEd Maste       }
686ac7ddfbfSEd Maste     }
687435933ddSDimitry Andric   } else if (original_idx == 0) {
688435933ddSDimitry Andric     // There should ALWAYS be a frame at index 0.  If something went wrong with
6894ba319b5SDimitry Andric     // the CurrentInlinedDepth such that there weren't as many frames as we
6904ba319b5SDimitry Andric     // thought taking that into account, then reset the current inlined depth
691ac7ddfbfSEd Maste     // and return the real zeroth frame.
692435933ddSDimitry Andric     if (m_frames.empty()) {
693435933ddSDimitry Andric       // Why do we have a thread with zero frames, that should not ever
694435933ddSDimitry Andric       // happen...
69595ec533aSDimitry Andric       assert(!m_thread.IsValid() && "A valid thread has no frames.");
696435933ddSDimitry Andric     } else {
6974bb0738eSEd Maste       ResetCurrentInlinedDepth();
6984bb0738eSEd Maste       frame_sp = m_frames[original_idx];
699ac7ddfbfSEd Maste     }
700ac7ddfbfSEd Maste   }
701ac7ddfbfSEd Maste 
702ac7ddfbfSEd Maste   return frame_sp;
703ac7ddfbfSEd Maste }
704ac7ddfbfSEd Maste 
705ac7ddfbfSEd Maste StackFrameSP
GetFrameWithConcreteFrameIndex(uint32_t unwind_idx)706435933ddSDimitry Andric StackFrameList::GetFrameWithConcreteFrameIndex(uint32_t unwind_idx) {
707ac7ddfbfSEd Maste   // First try assuming the unwind index is the same as the frame index. The
7084ba319b5SDimitry Andric   // unwind index is always greater than or equal to the frame index, so it is
7094ba319b5SDimitry Andric   // a good place to start. If we have inlined frames we might have 5 concrete
7104ba319b5SDimitry Andric   // frames (frame unwind indexes go from 0-4), but we might have 15 frames
7114ba319b5SDimitry Andric   // after we make all the inlined frames. Most of the time the unwind frame
7124ba319b5SDimitry Andric   // index (or the concrete frame index) is the same as the frame index.
713ac7ddfbfSEd Maste   uint32_t frame_idx = unwind_idx;
714ac7ddfbfSEd Maste   StackFrameSP frame_sp(GetFrameAtIndex(frame_idx));
715435933ddSDimitry Andric   while (frame_sp) {
716ac7ddfbfSEd Maste     if (frame_sp->GetFrameIndex() == unwind_idx)
717ac7ddfbfSEd Maste       break;
718ac7ddfbfSEd Maste     frame_sp = GetFrameAtIndex(++frame_idx);
719ac7ddfbfSEd Maste   }
720ac7ddfbfSEd Maste   return frame_sp;
721ac7ddfbfSEd Maste }
722ac7ddfbfSEd Maste 
CompareStackID(const StackFrameSP & stack_sp,const StackID & stack_id)723435933ddSDimitry Andric static bool CompareStackID(const StackFrameSP &stack_sp,
724435933ddSDimitry Andric                            const StackID &stack_id) {
725ac7ddfbfSEd Maste   return stack_sp->GetStackID() < stack_id;
726ac7ddfbfSEd Maste }
727ac7ddfbfSEd Maste 
GetFrameWithStackID(const StackID & stack_id)728435933ddSDimitry Andric StackFrameSP StackFrameList::GetFrameWithStackID(const StackID &stack_id) {
729ac7ddfbfSEd Maste   StackFrameSP frame_sp;
730ac7ddfbfSEd Maste 
731435933ddSDimitry Andric   if (stack_id.IsValid()) {
7324bb0738eSEd Maste     std::lock_guard<std::recursive_mutex> guard(m_mutex);
733ac7ddfbfSEd Maste     uint32_t frame_idx = 0;
734ac7ddfbfSEd Maste     // Do a binary search in case the stack frame is already in our cache
735ac7ddfbfSEd Maste     collection::const_iterator begin = m_frames.begin();
736ac7ddfbfSEd Maste     collection::const_iterator end = m_frames.end();
737435933ddSDimitry Andric     if (begin != end) {
738435933ddSDimitry Andric       collection::const_iterator pos =
739435933ddSDimitry Andric           std::lower_bound(begin, end, stack_id, CompareStackID);
740435933ddSDimitry Andric       if (pos != end) {
7417aa51b79SEd Maste         if ((*pos)->GetStackID() == stack_id)
742ac7ddfbfSEd Maste           return *pos;
7437aa51b79SEd Maste       }
744ac7ddfbfSEd Maste     }
745435933ddSDimitry Andric     do {
746ac7ddfbfSEd Maste       frame_sp = GetFrameAtIndex(frame_idx);
747ac7ddfbfSEd Maste       if (frame_sp && frame_sp->GetStackID() == stack_id)
748ac7ddfbfSEd Maste         break;
749ac7ddfbfSEd Maste       frame_idx++;
750435933ddSDimitry Andric     } while (frame_sp);
751ac7ddfbfSEd Maste   }
752ac7ddfbfSEd Maste   return frame_sp;
753ac7ddfbfSEd Maste }
754ac7ddfbfSEd Maste 
SetFrameAtIndex(uint32_t idx,StackFrameSP & frame_sp)755435933ddSDimitry Andric bool StackFrameList::SetFrameAtIndex(uint32_t idx, StackFrameSP &frame_sp) {
756ac7ddfbfSEd Maste   if (idx >= m_frames.size())
757ac7ddfbfSEd Maste     m_frames.resize(idx + 1);
758ac7ddfbfSEd Maste   // Make sure allocation succeeded by checking bounds again
759435933ddSDimitry Andric   if (idx < m_frames.size()) {
760ac7ddfbfSEd Maste     m_frames[idx] = frame_sp;
761ac7ddfbfSEd Maste     return true;
762ac7ddfbfSEd Maste   }
763ac7ddfbfSEd Maste   return false; // resize failed, out of memory?
764ac7ddfbfSEd Maste }
765ac7ddfbfSEd Maste 
GetSelectedFrameIndex() const766435933ddSDimitry Andric uint32_t StackFrameList::GetSelectedFrameIndex() const {
7674bb0738eSEd Maste   std::lock_guard<std::recursive_mutex> guard(m_mutex);
768ac7ddfbfSEd Maste   return m_selected_frame_idx;
769ac7ddfbfSEd Maste }
770ac7ddfbfSEd Maste 
SetSelectedFrame(lldb_private::StackFrame * frame)771435933ddSDimitry Andric uint32_t StackFrameList::SetSelectedFrame(lldb_private::StackFrame *frame) {
7724bb0738eSEd Maste   std::lock_guard<std::recursive_mutex> guard(m_mutex);
773ac7ddfbfSEd Maste   const_iterator pos;
774ac7ddfbfSEd Maste   const_iterator begin = m_frames.begin();
775ac7ddfbfSEd Maste   const_iterator end = m_frames.end();
776ac7ddfbfSEd Maste   m_selected_frame_idx = 0;
777435933ddSDimitry Andric   for (pos = begin; pos != end; ++pos) {
778435933ddSDimitry Andric     if (pos->get() == frame) {
779ac7ddfbfSEd Maste       m_selected_frame_idx = std::distance(begin, pos);
780ac7ddfbfSEd Maste       uint32_t inlined_depth = GetCurrentInlinedDepth();
781ac7ddfbfSEd Maste       if (inlined_depth != UINT32_MAX)
782ac7ddfbfSEd Maste         m_selected_frame_idx -= inlined_depth;
783ac7ddfbfSEd Maste       break;
784ac7ddfbfSEd Maste     }
785ac7ddfbfSEd Maste   }
786ac7ddfbfSEd Maste   SetDefaultFileAndLineToSelectedFrame();
787ac7ddfbfSEd Maste   return m_selected_frame_idx;
788ac7ddfbfSEd Maste }
789ac7ddfbfSEd Maste 
SetSelectedFrameByIndex(uint32_t idx)790435933ddSDimitry Andric bool StackFrameList::SetSelectedFrameByIndex(uint32_t idx) {
7914bb0738eSEd Maste   std::lock_guard<std::recursive_mutex> guard(m_mutex);
792ac7ddfbfSEd Maste   StackFrameSP frame_sp(GetFrameAtIndex(idx));
793435933ddSDimitry Andric   if (frame_sp) {
794ac7ddfbfSEd Maste     SetSelectedFrame(frame_sp.get());
795ac7ddfbfSEd Maste     return true;
796435933ddSDimitry Andric   } else
797ac7ddfbfSEd Maste     return false;
798ac7ddfbfSEd Maste }
799ac7ddfbfSEd Maste 
SetDefaultFileAndLineToSelectedFrame()800435933ddSDimitry Andric void StackFrameList::SetDefaultFileAndLineToSelectedFrame() {
801435933ddSDimitry Andric   if (m_thread.GetID() ==
802435933ddSDimitry Andric       m_thread.GetProcess()->GetThreadList().GetSelectedThread()->GetID()) {
803ac7ddfbfSEd Maste     StackFrameSP frame_sp(GetFrameAtIndex(GetSelectedFrameIndex()));
804435933ddSDimitry Andric     if (frame_sp) {
805ac7ddfbfSEd Maste       SymbolContext sc = frame_sp->GetSymbolContext(eSymbolContextLineEntry);
806ac7ddfbfSEd Maste       if (sc.line_entry.file)
807435933ddSDimitry Andric         m_thread.CalculateTarget()->GetSourceManager().SetDefaultFileAndLine(
808435933ddSDimitry Andric             sc.line_entry.file, sc.line_entry.line);
809ac7ddfbfSEd Maste     }
810ac7ddfbfSEd Maste   }
811ac7ddfbfSEd Maste }
812ac7ddfbfSEd Maste 
813ac7ddfbfSEd Maste // The thread has been run, reset the number stack frames to zero so we can
814ac7ddfbfSEd Maste // determine how many frames we have lazily.
Clear()815435933ddSDimitry Andric void StackFrameList::Clear() {
8164bb0738eSEd Maste   std::lock_guard<std::recursive_mutex> guard(m_mutex);
817ac7ddfbfSEd Maste   m_frames.clear();
818ac7ddfbfSEd Maste   m_concrete_frames_fetched = 0;
819ac7ddfbfSEd Maste }
820ac7ddfbfSEd Maste 
Merge(std::unique_ptr<StackFrameList> & curr_ap,lldb::StackFrameListSP & prev_sp)821435933ddSDimitry Andric void StackFrameList::Merge(std::unique_ptr<StackFrameList> &curr_ap,
822435933ddSDimitry Andric                            lldb::StackFrameListSP &prev_sp) {
8234bb0738eSEd Maste   std::unique_lock<std::recursive_mutex> current_lock, previous_lock;
8244bb0738eSEd Maste   if (curr_ap)
8254bb0738eSEd Maste     current_lock = std::unique_lock<std::recursive_mutex>(curr_ap->m_mutex);
8264bb0738eSEd Maste   if (prev_sp)
8274bb0738eSEd Maste     previous_lock = std::unique_lock<std::recursive_mutex>(prev_sp->m_mutex);
828ac7ddfbfSEd Maste 
829ac7ddfbfSEd Maste #if defined(DEBUG_STACK_FRAMES)
830ac7ddfbfSEd Maste   StreamFile s(stdout, false);
831ac7ddfbfSEd Maste   s.PutCString("\n\nStackFrameList::Merge():\nPrev:\n");
8324bb0738eSEd Maste   if (prev_sp)
833ac7ddfbfSEd Maste     prev_sp->Dump(&s);
834ac7ddfbfSEd Maste   else
835ac7ddfbfSEd Maste     s.PutCString("NULL");
836ac7ddfbfSEd Maste   s.PutCString("\nCurr:\n");
8374bb0738eSEd Maste   if (curr_ap)
838ac7ddfbfSEd Maste     curr_ap->Dump(&s);
839ac7ddfbfSEd Maste   else
840ac7ddfbfSEd Maste     s.PutCString("NULL");
841ac7ddfbfSEd Maste   s.EOL();
842ac7ddfbfSEd Maste #endif
843ac7ddfbfSEd Maste 
844435933ddSDimitry Andric   if (!curr_ap || curr_ap->GetNumFrames(false) == 0) {
845ac7ddfbfSEd Maste #if defined(DEBUG_STACK_FRAMES)
846ac7ddfbfSEd Maste     s.PutCString("No current frames, leave previous frames alone...\n");
847ac7ddfbfSEd Maste #endif
848ac7ddfbfSEd Maste     curr_ap.release();
849ac7ddfbfSEd Maste     return;
850ac7ddfbfSEd Maste   }
851ac7ddfbfSEd Maste 
852435933ddSDimitry Andric   if (!prev_sp || prev_sp->GetNumFrames(false) == 0) {
853ac7ddfbfSEd Maste #if defined(DEBUG_STACK_FRAMES)
854ac7ddfbfSEd Maste     s.PutCString("No previous frames, so use current frames...\n");
855ac7ddfbfSEd Maste #endif
8564ba319b5SDimitry Andric     // We either don't have any previous frames, or since we have more than one
8574ba319b5SDimitry Andric     // current frames it means we have all the frames and can safely replace
8584ba319b5SDimitry Andric     // our previous frames.
859ac7ddfbfSEd Maste     prev_sp.reset(curr_ap.release());
860ac7ddfbfSEd Maste     return;
861ac7ddfbfSEd Maste   }
862ac7ddfbfSEd Maste 
863ac7ddfbfSEd Maste   const uint32_t num_curr_frames = curr_ap->GetNumFrames(false);
864ac7ddfbfSEd Maste 
865435933ddSDimitry Andric   if (num_curr_frames > 1) {
866ac7ddfbfSEd Maste #if defined(DEBUG_STACK_FRAMES)
867435933ddSDimitry Andric     s.PutCString(
868435933ddSDimitry Andric         "We have more than one current frame, so use current frames...\n");
869ac7ddfbfSEd Maste #endif
8704ba319b5SDimitry Andric     // We have more than one current frames it means we have all the frames and
8714ba319b5SDimitry Andric     // can safely replace our previous frames.
872ac7ddfbfSEd Maste     prev_sp.reset(curr_ap.release());
873ac7ddfbfSEd Maste 
874ac7ddfbfSEd Maste #if defined(DEBUG_STACK_FRAMES)
875ac7ddfbfSEd Maste     s.PutCString("\nMerged:\n");
876ac7ddfbfSEd Maste     prev_sp->Dump(&s);
877ac7ddfbfSEd Maste #endif
878ac7ddfbfSEd Maste     return;
879ac7ddfbfSEd Maste   }
880ac7ddfbfSEd Maste 
881ac7ddfbfSEd Maste   StackFrameSP prev_frame_zero_sp(prev_sp->GetFrameAtIndex(0));
882ac7ddfbfSEd Maste   StackFrameSP curr_frame_zero_sp(curr_ap->GetFrameAtIndex(0));
883ac7ddfbfSEd Maste   StackID curr_stack_id(curr_frame_zero_sp->GetStackID());
884ac7ddfbfSEd Maste   StackID prev_stack_id(prev_frame_zero_sp->GetStackID());
885ac7ddfbfSEd Maste 
886ac7ddfbfSEd Maste #if defined(DEBUG_STACK_FRAMES)
887ac7ddfbfSEd Maste   const uint32_t num_prev_frames = prev_sp->GetNumFrames(false);
888ac7ddfbfSEd Maste   s.Printf("\n%u previous frames with one current frame\n", num_prev_frames);
889ac7ddfbfSEd Maste #endif
890ac7ddfbfSEd Maste 
891ac7ddfbfSEd Maste   // We have only a single current frame
892ac7ddfbfSEd Maste   // Our previous stack frames only had a single frame as well...
893435933ddSDimitry Andric   if (curr_stack_id == prev_stack_id) {
894ac7ddfbfSEd Maste #if defined(DEBUG_STACK_FRAMES)
895435933ddSDimitry Andric     s.Printf("\nPrevious frame #0 is same as current frame #0, merge the "
896435933ddSDimitry Andric              "cached data\n");
897ac7ddfbfSEd Maste #endif
898ac7ddfbfSEd Maste 
899435933ddSDimitry Andric     curr_frame_zero_sp->UpdateCurrentFrameFromPreviousFrame(
900435933ddSDimitry Andric         *prev_frame_zero_sp);
901435933ddSDimitry Andric     //        prev_frame_zero_sp->UpdatePreviousFrameFromCurrentFrame
902435933ddSDimitry Andric     //        (*curr_frame_zero_sp);
903ac7ddfbfSEd Maste     //        prev_sp->SetFrameAtIndex (0, prev_frame_zero_sp);
904435933ddSDimitry Andric   } else if (curr_stack_id < prev_stack_id) {
905ac7ddfbfSEd Maste #if defined(DEBUG_STACK_FRAMES)
906435933ddSDimitry Andric     s.Printf("\nCurrent frame #0 has a stack ID that is less than the previous "
907435933ddSDimitry Andric              "frame #0, insert current frame zero in front of previous\n");
908ac7ddfbfSEd Maste #endif
909ac7ddfbfSEd Maste     prev_sp->m_frames.insert(prev_sp->m_frames.begin(), curr_frame_zero_sp);
910ac7ddfbfSEd Maste   }
911ac7ddfbfSEd Maste 
912ac7ddfbfSEd Maste   curr_ap.release();
913ac7ddfbfSEd Maste 
914ac7ddfbfSEd Maste #if defined(DEBUG_STACK_FRAMES)
915ac7ddfbfSEd Maste   s.PutCString("\nMerged:\n");
916ac7ddfbfSEd Maste   prev_sp->Dump(&s);
917ac7ddfbfSEd Maste #endif
918ac7ddfbfSEd Maste }
919ac7ddfbfSEd Maste 
920ac7ddfbfSEd Maste lldb::StackFrameSP
GetStackFrameSPForStackFramePtr(StackFrame * stack_frame_ptr)921435933ddSDimitry Andric StackFrameList::GetStackFrameSPForStackFramePtr(StackFrame *stack_frame_ptr) {
922ac7ddfbfSEd Maste   const_iterator pos;
923ac7ddfbfSEd Maste   const_iterator begin = m_frames.begin();
924ac7ddfbfSEd Maste   const_iterator end = m_frames.end();
925ac7ddfbfSEd Maste   lldb::StackFrameSP ret_sp;
926ac7ddfbfSEd Maste 
927435933ddSDimitry Andric   for (pos = begin; pos != end; ++pos) {
928435933ddSDimitry Andric     if (pos->get() == stack_frame_ptr) {
929ac7ddfbfSEd Maste       ret_sp = (*pos);
930ac7ddfbfSEd Maste       break;
931ac7ddfbfSEd Maste     }
932ac7ddfbfSEd Maste   }
933ac7ddfbfSEd Maste   return ret_sp;
934ac7ddfbfSEd Maste }
935ac7ddfbfSEd Maste 
GetStatus(Stream & strm,uint32_t first_frame,uint32_t num_frames,bool show_frame_info,uint32_t num_frames_with_source,bool show_unique,const char * selected_frame_marker)936435933ddSDimitry Andric size_t StackFrameList::GetStatus(Stream &strm, uint32_t first_frame,
937435933ddSDimitry Andric                                  uint32_t num_frames, bool show_frame_info,
93835617911SEd Maste                                  uint32_t num_frames_with_source,
93924d58133SDimitry Andric                                  bool show_unique,
940435933ddSDimitry Andric                                  const char *selected_frame_marker) {
941ac7ddfbfSEd Maste   size_t num_frames_displayed = 0;
942ac7ddfbfSEd Maste 
943ac7ddfbfSEd Maste   if (num_frames == 0)
944ac7ddfbfSEd Maste     return 0;
945ac7ddfbfSEd Maste 
946ac7ddfbfSEd Maste   StackFrameSP frame_sp;
947ac7ddfbfSEd Maste   uint32_t frame_idx = 0;
948ac7ddfbfSEd Maste   uint32_t last_frame;
949ac7ddfbfSEd Maste 
950ac7ddfbfSEd Maste   // Don't let the last frame wrap around...
951ac7ddfbfSEd Maste   if (num_frames == UINT32_MAX)
952ac7ddfbfSEd Maste     last_frame = UINT32_MAX;
953ac7ddfbfSEd Maste   else
954ac7ddfbfSEd Maste     last_frame = first_frame + num_frames;
955ac7ddfbfSEd Maste 
95635617911SEd Maste   StackFrameSP selected_frame_sp = m_thread.GetSelectedFrame();
9574bb0738eSEd Maste   const char *unselected_marker = nullptr;
95835617911SEd Maste   std::string buffer;
959435933ddSDimitry Andric   if (selected_frame_marker) {
96035617911SEd Maste     size_t len = strlen(selected_frame_marker);
96135617911SEd Maste     buffer.insert(buffer.begin(), len, ' ');
96235617911SEd Maste     unselected_marker = buffer.c_str();
96335617911SEd Maste   }
9644bb0738eSEd Maste   const char *marker = nullptr;
96535617911SEd Maste 
966435933ddSDimitry Andric   for (frame_idx = first_frame; frame_idx < last_frame; ++frame_idx) {
967ac7ddfbfSEd Maste     frame_sp = GetFrameAtIndex(frame_idx);
9684bb0738eSEd Maste     if (!frame_sp)
969ac7ddfbfSEd Maste       break;
970ac7ddfbfSEd Maste 
971435933ddSDimitry Andric     if (selected_frame_marker != nullptr) {
97235617911SEd Maste       if (frame_sp == selected_frame_sp)
97335617911SEd Maste         marker = selected_frame_marker;
97435617911SEd Maste       else
97535617911SEd Maste         marker = unselected_marker;
97635617911SEd Maste     }
97735617911SEd Maste 
978435933ddSDimitry Andric     if (!frame_sp->GetStatus(strm, show_frame_info,
979435933ddSDimitry Andric                              num_frames_with_source > (first_frame - frame_idx),
98024d58133SDimitry Andric                              show_unique, marker))
981ac7ddfbfSEd Maste       break;
982ac7ddfbfSEd Maste     ++num_frames_displayed;
983ac7ddfbfSEd Maste   }
984ac7ddfbfSEd Maste 
985ac7ddfbfSEd Maste   strm.IndentLess();
986ac7ddfbfSEd Maste   return num_frames_displayed;
987ac7ddfbfSEd Maste }
988