StackFrameList.cpp revision 360784
1//===-- StackFrameList.cpp --------------------------------------*- 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#include "lldb/Target/StackFrameList.h"
10#include "lldb/Breakpoint/Breakpoint.h"
11#include "lldb/Breakpoint/BreakpointLocation.h"
12#include "lldb/Core/SourceManager.h"
13#include "lldb/Core/StreamFile.h"
14#include "lldb/Symbol/Block.h"
15#include "lldb/Symbol/Function.h"
16#include "lldb/Symbol/Symbol.h"
17#include "lldb/Target/Process.h"
18#include "lldb/Target/RegisterContext.h"
19#include "lldb/Target/StackFrame.h"
20#include "lldb/Target/StopInfo.h"
21#include "lldb/Target/Target.h"
22#include "lldb/Target/Thread.h"
23#include "lldb/Target/Unwind.h"
24#include "lldb/Utility/Log.h"
25#include "llvm/ADT/SmallPtrSet.h"
26
27#include <memory>
28
29//#define DEBUG_STACK_FRAMES 1
30
31using namespace lldb;
32using namespace lldb_private;
33
34// StackFrameList constructor
35StackFrameList::StackFrameList(Thread &thread,
36                               const lldb::StackFrameListSP &prev_frames_sp,
37                               bool show_inline_frames)
38    : m_thread(thread), m_prev_frames_sp(prev_frames_sp), m_mutex(), m_frames(),
39      m_selected_frame_idx(0), m_concrete_frames_fetched(0),
40      m_current_inlined_depth(UINT32_MAX),
41      m_current_inlined_pc(LLDB_INVALID_ADDRESS),
42      m_show_inlined_frames(show_inline_frames) {
43  if (prev_frames_sp) {
44    m_current_inlined_depth = prev_frames_sp->m_current_inlined_depth;
45    m_current_inlined_pc = prev_frames_sp->m_current_inlined_pc;
46  }
47}
48
49StackFrameList::~StackFrameList() {
50  // Call clear since this takes a lock and clears the stack frame list in case
51  // another thread is currently using this stack frame list
52  Clear();
53}
54
55void StackFrameList::CalculateCurrentInlinedDepth() {
56  uint32_t cur_inlined_depth = GetCurrentInlinedDepth();
57  if (cur_inlined_depth == UINT32_MAX) {
58    ResetCurrentInlinedDepth();
59  }
60}
61
62uint32_t StackFrameList::GetCurrentInlinedDepth() {
63  if (m_show_inlined_frames && m_current_inlined_pc != LLDB_INVALID_ADDRESS) {
64    lldb::addr_t cur_pc = m_thread.GetRegisterContext()->GetPC();
65    if (cur_pc != m_current_inlined_pc) {
66      m_current_inlined_pc = LLDB_INVALID_ADDRESS;
67      m_current_inlined_depth = UINT32_MAX;
68      Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
69      if (log && log->GetVerbose())
70        LLDB_LOGF(
71            log,
72            "GetCurrentInlinedDepth: invalidating current inlined depth.\n");
73    }
74    return m_current_inlined_depth;
75  } else {
76    return UINT32_MAX;
77  }
78}
79
80void StackFrameList::ResetCurrentInlinedDepth() {
81  if (!m_show_inlined_frames)
82    return;
83
84  std::lock_guard<std::recursive_mutex> guard(m_mutex);
85
86  GetFramesUpTo(0);
87  if (m_frames.empty())
88    return;
89  if (!m_frames[0]->IsInlined()) {
90    m_current_inlined_depth = UINT32_MAX;
91    m_current_inlined_pc = LLDB_INVALID_ADDRESS;
92    Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
93    if (log && log->GetVerbose())
94      LLDB_LOGF(
95          log,
96          "ResetCurrentInlinedDepth: Invalidating current inlined depth.\n");
97    return;
98  }
99
100  // We only need to do something special about inlined blocks when we are
101  // at the beginning of an inlined function:
102  // FIXME: We probably also have to do something special if the PC is at
103  // the END of an inlined function, which coincides with the end of either
104  // its containing function or another inlined function.
105
106  Block *block_ptr = m_frames[0]->GetFrameBlock();
107  if (!block_ptr)
108    return;
109
110  Address pc_as_address;
111  lldb::addr_t curr_pc = m_thread.GetRegisterContext()->GetPC();
112  pc_as_address.SetLoadAddress(curr_pc, &(m_thread.GetProcess()->GetTarget()));
113  AddressRange containing_range;
114  if (!block_ptr->GetRangeContainingAddress(pc_as_address, containing_range) ||
115      pc_as_address != containing_range.GetBaseAddress())
116    return;
117
118  // If we got here because of a breakpoint hit, then set the inlined depth
119  // depending on where the breakpoint was set. If we got here because of a
120  // crash, then set the inlined depth to the deepest most block.  Otherwise,
121  // we stopped here naturally as the result of a step, so set ourselves in the
122  // containing frame of the whole set of nested inlines, so the user can then
123  // "virtually" step into the frames one by one, or next over the whole mess.
124  // Note: We don't have to handle being somewhere in the middle of the stack
125  // here, since ResetCurrentInlinedDepth doesn't get called if there is a
126  // valid inlined depth set.
127  StopInfoSP stop_info_sp = m_thread.GetStopInfo();
128  if (!stop_info_sp)
129    return;
130  switch (stop_info_sp->GetStopReason()) {
131  case eStopReasonWatchpoint:
132  case eStopReasonException:
133  case eStopReasonExec:
134  case eStopReasonSignal:
135    // In all these cases we want to stop in the deepest frame.
136    m_current_inlined_pc = curr_pc;
137    m_current_inlined_depth = 0;
138    break;
139  case eStopReasonBreakpoint: {
140    // FIXME: Figure out what this break point is doing, and set the inline
141    // depth appropriately.  Be careful to take into account breakpoints that
142    // implement step over prologue, since that should do the default
143    // calculation. For now, if the breakpoints corresponding to this hit are
144    // all internal, I set the stop location to the top of the inlined stack,
145    // since that will make things like stepping over prologues work right.
146    // But if there are any non-internal breakpoints I do to the bottom of the
147    // stack, since that was the old behavior.
148    uint32_t bp_site_id = stop_info_sp->GetValue();
149    BreakpointSiteSP bp_site_sp(
150        m_thread.GetProcess()->GetBreakpointSiteList().FindByID(bp_site_id));
151    bool all_internal = true;
152    if (bp_site_sp) {
153      uint32_t num_owners = bp_site_sp->GetNumberOfOwners();
154      for (uint32_t i = 0; i < num_owners; i++) {
155        Breakpoint &bp_ref = bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint();
156        if (!bp_ref.IsInternal()) {
157          all_internal = false;
158        }
159      }
160    }
161    if (!all_internal) {
162      m_current_inlined_pc = curr_pc;
163      m_current_inlined_depth = 0;
164      break;
165    }
166  }
167    LLVM_FALLTHROUGH;
168  default: {
169    // Otherwise, we should set ourselves at the container of the inlining, so
170    // that the user can descend into them. So first we check whether we have
171    // more than one inlined block sharing this PC:
172    int num_inlined_functions = 0;
173
174    for (Block *container_ptr = block_ptr->GetInlinedParent();
175         container_ptr != nullptr;
176         container_ptr = container_ptr->GetInlinedParent()) {
177      if (!container_ptr->GetRangeContainingAddress(pc_as_address,
178                                                    containing_range))
179        break;
180      if (pc_as_address != containing_range.GetBaseAddress())
181        break;
182
183      num_inlined_functions++;
184    }
185    m_current_inlined_pc = curr_pc;
186    m_current_inlined_depth = num_inlined_functions + 1;
187    Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
188    if (log && log->GetVerbose())
189      LLDB_LOGF(log,
190                "ResetCurrentInlinedDepth: setting inlined "
191                "depth: %d 0x%" PRIx64 ".\n",
192                m_current_inlined_depth, curr_pc);
193
194    break;
195  }
196  }
197}
198
199bool StackFrameList::DecrementCurrentInlinedDepth() {
200  if (m_show_inlined_frames) {
201    uint32_t current_inlined_depth = GetCurrentInlinedDepth();
202    if (current_inlined_depth != UINT32_MAX) {
203      if (current_inlined_depth > 0) {
204        m_current_inlined_depth--;
205        return true;
206      }
207    }
208  }
209  return false;
210}
211
212void StackFrameList::SetCurrentInlinedDepth(uint32_t new_depth) {
213  m_current_inlined_depth = new_depth;
214  if (new_depth == UINT32_MAX)
215    m_current_inlined_pc = LLDB_INVALID_ADDRESS;
216  else
217    m_current_inlined_pc = m_thread.GetRegisterContext()->GetPC();
218}
219
220void StackFrameList::GetOnlyConcreteFramesUpTo(uint32_t end_idx,
221                                               Unwind *unwinder) {
222  assert(m_thread.IsValid() && "Expected valid thread");
223  assert(m_frames.size() <= end_idx && "Expected there to be frames to fill");
224
225  if (end_idx < m_concrete_frames_fetched)
226    return;
227
228  if (!unwinder)
229    return;
230
231  uint32_t num_frames = unwinder->GetFramesUpTo(end_idx);
232  if (num_frames <= end_idx + 1) {
233    // Done unwinding.
234    m_concrete_frames_fetched = UINT32_MAX;
235  }
236
237  // Don't create the frames eagerly. Defer this work to GetFrameAtIndex,
238  // which can lazily query the unwinder to create frames.
239  m_frames.resize(num_frames);
240}
241
242/// Find the unique path through the call graph from \p begin (with return PC
243/// \p return_pc) to \p end. On success this path is stored into \p path, and
244/// on failure \p path is unchanged.
245static void FindInterveningFrames(Function &begin, Function &end,
246                                  ExecutionContext &exe_ctx, Target &target,
247                                  addr_t return_pc,
248                                  std::vector<Function *> &path,
249                                  ModuleList &images, Log *log) {
250  LLDB_LOG(log, "Finding frames between {0} and {1}, retn-pc={2:x}",
251           begin.GetDisplayName(), end.GetDisplayName(), return_pc);
252
253  // Find a non-tail calling edge with the correct return PC.
254  if (log)
255    for (const auto &edge : begin.GetCallEdges())
256      LLDB_LOG(log, "FindInterveningFrames: found call with retn-PC = {0:x}",
257               edge->GetReturnPCAddress(begin, target));
258  CallEdge *first_edge = begin.GetCallEdgeForReturnAddress(return_pc, target);
259  if (!first_edge) {
260    LLDB_LOG(log, "No call edge outgoing from {0} with retn-PC == {1:x}",
261             begin.GetDisplayName(), return_pc);
262    return;
263  }
264
265  // The first callee may not be resolved, or there may be nothing to fill in.
266  Function *first_callee = first_edge->GetCallee(images, exe_ctx);
267  if (!first_callee) {
268    LLDB_LOG(log, "Could not resolve callee");
269    return;
270  }
271  if (first_callee == &end) {
272    LLDB_LOG(log, "Not searching further, first callee is {0} (retn-PC: {1:x})",
273             end.GetDisplayName(), return_pc);
274    return;
275  }
276
277  // Run DFS on the tail-calling edges out of the first callee to find \p end.
278  // Fully explore the set of functions reachable from the first edge via tail
279  // calls in order to detect ambiguous executions.
280  struct DFS {
281    std::vector<Function *> active_path = {};
282    std::vector<Function *> solution_path = {};
283    llvm::SmallPtrSet<Function *, 2> visited_nodes = {};
284    bool ambiguous = false;
285    Function *end;
286    ModuleList &images;
287    ExecutionContext &context;
288
289    DFS(Function *end, ModuleList &images, ExecutionContext &context)
290        : end(end), images(images), context(context) {}
291
292    void search(Function &first_callee, std::vector<Function *> &path) {
293      dfs(first_callee);
294      if (!ambiguous)
295        path = std::move(solution_path);
296    }
297
298    void dfs(Function &callee) {
299      // Found a path to the target function.
300      if (&callee == end) {
301        if (solution_path.empty())
302          solution_path = active_path;
303        else
304          ambiguous = true;
305        return;
306      }
307
308      // Terminate the search if tail recursion is found, or more generally if
309      // there's more than one way to reach a target. This errs on the side of
310      // caution: it conservatively stops searching when some solutions are
311      // still possible to save time in the average case.
312      if (!visited_nodes.insert(&callee).second) {
313        ambiguous = true;
314        return;
315      }
316
317      // Search the calls made from this callee.
318      active_path.push_back(&callee);
319      for (const auto &edge : callee.GetTailCallingEdges()) {
320        Function *next_callee = edge->GetCallee(images, context);
321        if (!next_callee)
322          continue;
323
324        dfs(*next_callee);
325        if (ambiguous)
326          return;
327      }
328      active_path.pop_back();
329    }
330  };
331
332  DFS(&end, images, exe_ctx).search(*first_callee, path);
333}
334
335/// Given that \p next_frame will be appended to the frame list, synthesize
336/// tail call frames between the current end of the list and \p next_frame.
337/// If any frames are added, adjust the frame index of \p next_frame.
338///
339///   --------------
340///   |    ...     | <- Completed frames.
341///   --------------
342///   | prev_frame |
343///   --------------
344///   |    ...     | <- Artificial frames inserted here.
345///   --------------
346///   | next_frame |
347///   --------------
348///   |    ...     | <- Not-yet-visited frames.
349///   --------------
350void StackFrameList::SynthesizeTailCallFrames(StackFrame &next_frame) {
351  TargetSP target_sp = next_frame.CalculateTarget();
352  if (!target_sp)
353    return;
354
355  lldb::RegisterContextSP next_reg_ctx_sp = next_frame.GetRegisterContext();
356  if (!next_reg_ctx_sp)
357    return;
358
359  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
360
361  assert(!m_frames.empty() && "Cannot synthesize frames in an empty stack");
362  StackFrame &prev_frame = *m_frames.back().get();
363
364  // Find the functions prev_frame and next_frame are stopped in. The function
365  // objects are needed to search the lazy call graph for intervening frames.
366  Function *prev_func =
367      prev_frame.GetSymbolContext(eSymbolContextFunction).function;
368  if (!prev_func) {
369    LLDB_LOG(log, "SynthesizeTailCallFrames: can't find previous function");
370    return;
371  }
372  Function *next_func =
373      next_frame.GetSymbolContext(eSymbolContextFunction).function;
374  if (!next_func) {
375    LLDB_LOG(log, "SynthesizeTailCallFrames: can't find next function");
376    return;
377  }
378
379  // Try to find the unique sequence of (tail) calls which led from next_frame
380  // to prev_frame.
381  std::vector<Function *> path;
382  addr_t return_pc = next_reg_ctx_sp->GetPC();
383  Target &target = *target_sp.get();
384  ModuleList &images = next_frame.CalculateTarget()->GetImages();
385  ExecutionContext exe_ctx(target_sp, /*get_process=*/true);
386  exe_ctx.SetFramePtr(&next_frame);
387  FindInterveningFrames(*next_func, *prev_func, exe_ctx, target, return_pc,
388                        path, images, log);
389
390  // Push synthetic tail call frames.
391  for (Function *callee : llvm::reverse(path)) {
392    uint32_t frame_idx = m_frames.size();
393    uint32_t concrete_frame_idx = next_frame.GetConcreteFrameIndex();
394    addr_t cfa = LLDB_INVALID_ADDRESS;
395    bool cfa_is_valid = false;
396    addr_t pc =
397        callee->GetAddressRange().GetBaseAddress().GetLoadAddress(&target);
398    constexpr bool behaves_like_zeroth_frame = false;
399    SymbolContext sc;
400    callee->CalculateSymbolContext(&sc);
401    auto synth_frame = std::make_shared<StackFrame>(
402        m_thread.shared_from_this(), frame_idx, concrete_frame_idx, cfa,
403        cfa_is_valid, pc, StackFrame::Kind::Artificial,
404        behaves_like_zeroth_frame, &sc);
405    m_frames.push_back(synth_frame);
406    LLDB_LOG(log, "Pushed frame {0}", callee->GetDisplayName());
407  }
408
409  // If any frames were created, adjust next_frame's index.
410  if (!path.empty())
411    next_frame.SetFrameIndex(m_frames.size());
412}
413
414void StackFrameList::GetFramesUpTo(uint32_t end_idx) {
415  // Do not fetch frames for an invalid thread.
416  if (!m_thread.IsValid())
417    return;
418
419  // We've already gotten more frames than asked for, or we've already finished
420  // unwinding, return.
421  if (m_frames.size() > end_idx || GetAllFramesFetched())
422    return;
423
424  Unwind *unwinder = m_thread.GetUnwinder();
425
426  if (!m_show_inlined_frames) {
427    GetOnlyConcreteFramesUpTo(end_idx, unwinder);
428    return;
429  }
430
431#if defined(DEBUG_STACK_FRAMES)
432  StreamFile s(stdout, false);
433#endif
434  // If we are hiding some frames from the outside world, we need to add
435  // those onto the total count of frames to fetch.  However, we don't need
436  // to do that if end_idx is 0 since in that case we always get the first
437  // concrete frame and all the inlined frames below it...  And of course, if
438  // end_idx is UINT32_MAX that means get all, so just do that...
439
440  uint32_t inlined_depth = 0;
441  if (end_idx > 0 && end_idx != UINT32_MAX) {
442    inlined_depth = GetCurrentInlinedDepth();
443    if (inlined_depth != UINT32_MAX) {
444      if (end_idx > 0)
445        end_idx += inlined_depth;
446    }
447  }
448
449  StackFrameSP unwind_frame_sp;
450  do {
451    uint32_t idx = m_concrete_frames_fetched++;
452    lldb::addr_t pc = LLDB_INVALID_ADDRESS;
453    lldb::addr_t cfa = LLDB_INVALID_ADDRESS;
454    bool behaves_like_zeroth_frame = (idx == 0);
455    if (idx == 0) {
456      // We might have already created frame zero, only create it if we need
457      // to.
458      if (m_frames.empty()) {
459        RegisterContextSP reg_ctx_sp(m_thread.GetRegisterContext());
460
461        if (reg_ctx_sp) {
462          const bool success = unwinder &&
463                               unwinder->GetFrameInfoAtIndex(
464                                   idx, cfa, pc, behaves_like_zeroth_frame);
465          // There shouldn't be any way not to get the frame info for frame
466          // 0. But if the unwinder can't make one, lets make one by hand
467          // with the SP as the CFA and see if that gets any further.
468          if (!success) {
469            cfa = reg_ctx_sp->GetSP();
470            pc = reg_ctx_sp->GetPC();
471          }
472
473          unwind_frame_sp = std::make_shared<StackFrame>(
474              m_thread.shared_from_this(), m_frames.size(), idx, reg_ctx_sp,
475              cfa, pc, behaves_like_zeroth_frame, nullptr);
476          m_frames.push_back(unwind_frame_sp);
477        }
478      } else {
479        unwind_frame_sp = m_frames.front();
480        cfa = unwind_frame_sp->m_id.GetCallFrameAddress();
481      }
482    } else {
483      const bool success = unwinder &&
484                           unwinder->GetFrameInfoAtIndex(
485                               idx, cfa, pc, behaves_like_zeroth_frame);
486      if (!success) {
487        // We've gotten to the end of the stack.
488        SetAllFramesFetched();
489        break;
490      }
491      const bool cfa_is_valid = true;
492      unwind_frame_sp = std::make_shared<StackFrame>(
493          m_thread.shared_from_this(), m_frames.size(), idx, cfa, cfa_is_valid,
494          pc, StackFrame::Kind::Regular, behaves_like_zeroth_frame, nullptr);
495
496      // Create synthetic tail call frames between the previous frame and the
497      // newly-found frame. The new frame's index may change after this call,
498      // although its concrete index will stay the same.
499      SynthesizeTailCallFrames(*unwind_frame_sp.get());
500
501      m_frames.push_back(unwind_frame_sp);
502    }
503
504    assert(unwind_frame_sp);
505    SymbolContext unwind_sc = unwind_frame_sp->GetSymbolContext(
506        eSymbolContextBlock | eSymbolContextFunction);
507    Block *unwind_block = unwind_sc.block;
508    if (unwind_block) {
509      Address curr_frame_address(unwind_frame_sp->GetFrameCodeAddress());
510      TargetSP target_sp = m_thread.CalculateTarget();
511      // Be sure to adjust the frame address to match the address that was
512      // used to lookup the symbol context above. If we are in the first
513      // concrete frame, then we lookup using the current address, else we
514      // decrement the address by one to get the correct location.
515      if (idx > 0) {
516        if (curr_frame_address.GetOffset() == 0) {
517          // If curr_frame_address points to the first address in a section
518          // then after adjustment it will point to an other section. In that
519          // case resolve the address again to the correct section plus
520          // offset form.
521          addr_t load_addr = curr_frame_address.GetOpcodeLoadAddress(
522              target_sp.get(), AddressClass::eCode);
523          curr_frame_address.SetOpcodeLoadAddress(
524              load_addr - 1, target_sp.get(), AddressClass::eCode);
525        } else {
526          curr_frame_address.Slide(-1);
527        }
528      }
529
530      SymbolContext next_frame_sc;
531      Address next_frame_address;
532
533      while (unwind_sc.GetParentOfInlinedScope(
534          curr_frame_address, next_frame_sc, next_frame_address)) {
535        next_frame_sc.line_entry.ApplyFileMappings(target_sp);
536        behaves_like_zeroth_frame = false;
537        StackFrameSP frame_sp(new StackFrame(
538            m_thread.shared_from_this(), m_frames.size(), idx,
539            unwind_frame_sp->GetRegisterContextSP(), cfa, next_frame_address,
540            behaves_like_zeroth_frame, &next_frame_sc));
541
542        m_frames.push_back(frame_sp);
543        unwind_sc = next_frame_sc;
544        curr_frame_address = next_frame_address;
545      }
546    }
547  } while (m_frames.size() - 1 < end_idx);
548
549  // Don't try to merge till you've calculated all the frames in this stack.
550  if (GetAllFramesFetched() && m_prev_frames_sp) {
551    StackFrameList *prev_frames = m_prev_frames_sp.get();
552    StackFrameList *curr_frames = this;
553
554#if defined(DEBUG_STACK_FRAMES)
555    s.PutCString("\nprev_frames:\n");
556    prev_frames->Dump(&s);
557    s.PutCString("\ncurr_frames:\n");
558    curr_frames->Dump(&s);
559    s.EOL();
560#endif
561    size_t curr_frame_num, prev_frame_num;
562
563    for (curr_frame_num = curr_frames->m_frames.size(),
564        prev_frame_num = prev_frames->m_frames.size();
565         curr_frame_num > 0 && prev_frame_num > 0;
566         --curr_frame_num, --prev_frame_num) {
567      const size_t curr_frame_idx = curr_frame_num - 1;
568      const size_t prev_frame_idx = prev_frame_num - 1;
569      StackFrameSP curr_frame_sp(curr_frames->m_frames[curr_frame_idx]);
570      StackFrameSP prev_frame_sp(prev_frames->m_frames[prev_frame_idx]);
571
572#if defined(DEBUG_STACK_FRAMES)
573      s.Printf("\n\nCurr frame #%u ", curr_frame_idx);
574      if (curr_frame_sp)
575        curr_frame_sp->Dump(&s, true, false);
576      else
577        s.PutCString("NULL");
578      s.Printf("\nPrev frame #%u ", prev_frame_idx);
579      if (prev_frame_sp)
580        prev_frame_sp->Dump(&s, true, false);
581      else
582        s.PutCString("NULL");
583#endif
584
585      StackFrame *curr_frame = curr_frame_sp.get();
586      StackFrame *prev_frame = prev_frame_sp.get();
587
588      if (curr_frame == nullptr || prev_frame == nullptr)
589        break;
590
591      // Check the stack ID to make sure they are equal.
592      if (curr_frame->GetStackID() != prev_frame->GetStackID())
593        break;
594
595      prev_frame->UpdatePreviousFrameFromCurrentFrame(*curr_frame);
596      // Now copy the fixed up previous frame into the current frames so the
597      // pointer doesn't change.
598      m_frames[curr_frame_idx] = prev_frame_sp;
599
600#if defined(DEBUG_STACK_FRAMES)
601      s.Printf("\n    Copying previous frame to current frame");
602#endif
603    }
604    // We are done with the old stack frame list, we can release it now.
605    m_prev_frames_sp.reset();
606  }
607
608#if defined(DEBUG_STACK_FRAMES)
609  s.PutCString("\n\nNew frames:\n");
610  Dump(&s);
611  s.EOL();
612#endif
613}
614
615uint32_t StackFrameList::GetNumFrames(bool can_create) {
616  std::lock_guard<std::recursive_mutex> guard(m_mutex);
617
618  if (can_create)
619    GetFramesUpTo(UINT32_MAX);
620
621  return GetVisibleStackFrameIndex(m_frames.size());
622}
623
624void StackFrameList::Dump(Stream *s) {
625  if (s == nullptr)
626    return;
627
628  std::lock_guard<std::recursive_mutex> guard(m_mutex);
629
630  const_iterator pos, begin = m_frames.begin(), end = m_frames.end();
631  for (pos = begin; pos != end; ++pos) {
632    StackFrame *frame = (*pos).get();
633    s->Printf("%p: ", static_cast<void *>(frame));
634    if (frame) {
635      frame->GetStackID().Dump(s);
636      frame->DumpUsingSettingsFormat(s);
637    } else
638      s->Printf("frame #%u", (uint32_t)std::distance(begin, pos));
639    s->EOL();
640  }
641  s->EOL();
642}
643
644StackFrameSP StackFrameList::GetFrameAtIndex(uint32_t idx) {
645  StackFrameSP frame_sp;
646  std::lock_guard<std::recursive_mutex> guard(m_mutex);
647  uint32_t original_idx = idx;
648
649  uint32_t inlined_depth = GetCurrentInlinedDepth();
650  if (inlined_depth != UINT32_MAX)
651    idx += inlined_depth;
652
653  if (idx < m_frames.size())
654    frame_sp = m_frames[idx];
655
656  if (frame_sp)
657    return frame_sp;
658
659  // GetFramesUpTo will fill m_frames with as many frames as you asked for, if
660  // there are that many.  If there weren't then you asked for too many frames.
661  GetFramesUpTo(idx);
662  if (idx < m_frames.size()) {
663    if (m_show_inlined_frames) {
664      // When inline frames are enabled we actually create all the frames in
665      // GetFramesUpTo.
666      frame_sp = m_frames[idx];
667    } else {
668      Unwind *unwinder = m_thread.GetUnwinder();
669      if (unwinder) {
670        addr_t pc, cfa;
671        bool behaves_like_zeroth_frame = (idx == 0);
672        if (unwinder->GetFrameInfoAtIndex(idx, cfa, pc,
673                                          behaves_like_zeroth_frame)) {
674          const bool cfa_is_valid = true;
675          frame_sp = std::make_shared<StackFrame>(
676              m_thread.shared_from_this(), idx, idx, cfa, cfa_is_valid, pc,
677              StackFrame::Kind::Regular, behaves_like_zeroth_frame, nullptr);
678
679          Function *function =
680              frame_sp->GetSymbolContext(eSymbolContextFunction).function;
681          if (function) {
682            // When we aren't showing inline functions we always use the top
683            // most function block as the scope.
684            frame_sp->SetSymbolContextScope(&function->GetBlock(false));
685          } else {
686            // Set the symbol scope from the symbol regardless if it is nullptr
687            // or valid.
688            frame_sp->SetSymbolContextScope(
689                frame_sp->GetSymbolContext(eSymbolContextSymbol).symbol);
690          }
691          SetFrameAtIndex(idx, frame_sp);
692        }
693      }
694    }
695  } else if (original_idx == 0) {
696    // There should ALWAYS be a frame at index 0.  If something went wrong with
697    // the CurrentInlinedDepth such that there weren't as many frames as we
698    // thought taking that into account, then reset the current inlined depth
699    // and return the real zeroth frame.
700    if (m_frames.empty()) {
701      // Why do we have a thread with zero frames, that should not ever
702      // happen...
703      assert(!m_thread.IsValid() && "A valid thread has no frames.");
704    } else {
705      ResetCurrentInlinedDepth();
706      frame_sp = m_frames[original_idx];
707    }
708  }
709
710  return frame_sp;
711}
712
713StackFrameSP
714StackFrameList::GetFrameWithConcreteFrameIndex(uint32_t unwind_idx) {
715  // First try assuming the unwind index is the same as the frame index. The
716  // unwind index is always greater than or equal to the frame index, so it is
717  // a good place to start. If we have inlined frames we might have 5 concrete
718  // frames (frame unwind indexes go from 0-4), but we might have 15 frames
719  // after we make all the inlined frames. Most of the time the unwind frame
720  // index (or the concrete frame index) is the same as the frame index.
721  uint32_t frame_idx = unwind_idx;
722  StackFrameSP frame_sp(GetFrameAtIndex(frame_idx));
723  while (frame_sp) {
724    if (frame_sp->GetFrameIndex() == unwind_idx)
725      break;
726    frame_sp = GetFrameAtIndex(++frame_idx);
727  }
728  return frame_sp;
729}
730
731static bool CompareStackID(const StackFrameSP &stack_sp,
732                           const StackID &stack_id) {
733  return stack_sp->GetStackID() < stack_id;
734}
735
736StackFrameSP StackFrameList::GetFrameWithStackID(const StackID &stack_id) {
737  StackFrameSP frame_sp;
738
739  if (stack_id.IsValid()) {
740    std::lock_guard<std::recursive_mutex> guard(m_mutex);
741    uint32_t frame_idx = 0;
742    // Do a binary search in case the stack frame is already in our cache
743    collection::const_iterator begin = m_frames.begin();
744    collection::const_iterator end = m_frames.end();
745    if (begin != end) {
746      collection::const_iterator pos =
747          std::lower_bound(begin, end, stack_id, CompareStackID);
748      if (pos != end) {
749        if ((*pos)->GetStackID() == stack_id)
750          return *pos;
751      }
752    }
753    do {
754      frame_sp = GetFrameAtIndex(frame_idx);
755      if (frame_sp && frame_sp->GetStackID() == stack_id)
756        break;
757      frame_idx++;
758    } while (frame_sp);
759  }
760  return frame_sp;
761}
762
763bool StackFrameList::SetFrameAtIndex(uint32_t idx, StackFrameSP &frame_sp) {
764  if (idx >= m_frames.size())
765    m_frames.resize(idx + 1);
766  // Make sure allocation succeeded by checking bounds again
767  if (idx < m_frames.size()) {
768    m_frames[idx] = frame_sp;
769    return true;
770  }
771  return false; // resize failed, out of memory?
772}
773
774uint32_t StackFrameList::GetSelectedFrameIndex() const {
775  std::lock_guard<std::recursive_mutex> guard(m_mutex);
776  return m_selected_frame_idx;
777}
778
779uint32_t StackFrameList::SetSelectedFrame(lldb_private::StackFrame *frame) {
780  std::lock_guard<std::recursive_mutex> guard(m_mutex);
781  const_iterator pos;
782  const_iterator begin = m_frames.begin();
783  const_iterator end = m_frames.end();
784  m_selected_frame_idx = 0;
785  for (pos = begin; pos != end; ++pos) {
786    if (pos->get() == frame) {
787      m_selected_frame_idx = std::distance(begin, pos);
788      uint32_t inlined_depth = GetCurrentInlinedDepth();
789      if (inlined_depth != UINT32_MAX)
790        m_selected_frame_idx -= inlined_depth;
791      break;
792    }
793  }
794  SetDefaultFileAndLineToSelectedFrame();
795  return m_selected_frame_idx;
796}
797
798bool StackFrameList::SetSelectedFrameByIndex(uint32_t idx) {
799  std::lock_guard<std::recursive_mutex> guard(m_mutex);
800  StackFrameSP frame_sp(GetFrameAtIndex(idx));
801  if (frame_sp) {
802    SetSelectedFrame(frame_sp.get());
803    return true;
804  } else
805    return false;
806}
807
808void StackFrameList::SetDefaultFileAndLineToSelectedFrame() {
809  if (m_thread.GetID() ==
810      m_thread.GetProcess()->GetThreadList().GetSelectedThread()->GetID()) {
811    StackFrameSP frame_sp(GetFrameAtIndex(GetSelectedFrameIndex()));
812    if (frame_sp) {
813      SymbolContext sc = frame_sp->GetSymbolContext(eSymbolContextLineEntry);
814      if (sc.line_entry.file)
815        m_thread.CalculateTarget()->GetSourceManager().SetDefaultFileAndLine(
816            sc.line_entry.file, sc.line_entry.line);
817    }
818  }
819}
820
821// The thread has been run, reset the number stack frames to zero so we can
822// determine how many frames we have lazily.
823void StackFrameList::Clear() {
824  std::lock_guard<std::recursive_mutex> guard(m_mutex);
825  m_frames.clear();
826  m_concrete_frames_fetched = 0;
827}
828
829void StackFrameList::Merge(std::unique_ptr<StackFrameList> &curr_up,
830                           lldb::StackFrameListSP &prev_sp) {
831  std::unique_lock<std::recursive_mutex> current_lock, previous_lock;
832  if (curr_up)
833    current_lock = std::unique_lock<std::recursive_mutex>(curr_up->m_mutex);
834  if (prev_sp)
835    previous_lock = std::unique_lock<std::recursive_mutex>(prev_sp->m_mutex);
836
837#if defined(DEBUG_STACK_FRAMES)
838  StreamFile s(stdout, false);
839  s.PutCString("\n\nStackFrameList::Merge():\nPrev:\n");
840  if (prev_sp)
841    prev_sp->Dump(&s);
842  else
843    s.PutCString("NULL");
844  s.PutCString("\nCurr:\n");
845  if (curr_up)
846    curr_up->Dump(&s);
847  else
848    s.PutCString("NULL");
849  s.EOL();
850#endif
851
852  if (!curr_up || curr_up->GetNumFrames(false) == 0) {
853#if defined(DEBUG_STACK_FRAMES)
854    s.PutCString("No current frames, leave previous frames alone...\n");
855#endif
856    curr_up.release();
857    return;
858  }
859
860  if (!prev_sp || prev_sp->GetNumFrames(false) == 0) {
861#if defined(DEBUG_STACK_FRAMES)
862    s.PutCString("No previous frames, so use current frames...\n");
863#endif
864    // We either don't have any previous frames, or since we have more than one
865    // current frames it means we have all the frames and can safely replace
866    // our previous frames.
867    prev_sp.reset(curr_up.release());
868    return;
869  }
870
871  const uint32_t num_curr_frames = curr_up->GetNumFrames(false);
872
873  if (num_curr_frames > 1) {
874#if defined(DEBUG_STACK_FRAMES)
875    s.PutCString(
876        "We have more than one current frame, so use current frames...\n");
877#endif
878    // We have more than one current frames it means we have all the frames and
879    // can safely replace our previous frames.
880    prev_sp.reset(curr_up.release());
881
882#if defined(DEBUG_STACK_FRAMES)
883    s.PutCString("\nMerged:\n");
884    prev_sp->Dump(&s);
885#endif
886    return;
887  }
888
889  StackFrameSP prev_frame_zero_sp(prev_sp->GetFrameAtIndex(0));
890  StackFrameSP curr_frame_zero_sp(curr_up->GetFrameAtIndex(0));
891  StackID curr_stack_id(curr_frame_zero_sp->GetStackID());
892  StackID prev_stack_id(prev_frame_zero_sp->GetStackID());
893
894#if defined(DEBUG_STACK_FRAMES)
895  const uint32_t num_prev_frames = prev_sp->GetNumFrames(false);
896  s.Printf("\n%u previous frames with one current frame\n", num_prev_frames);
897#endif
898
899  // We have only a single current frame
900  // Our previous stack frames only had a single frame as well...
901  if (curr_stack_id == prev_stack_id) {
902#if defined(DEBUG_STACK_FRAMES)
903    s.Printf("\nPrevious frame #0 is same as current frame #0, merge the "
904             "cached data\n");
905#endif
906
907    curr_frame_zero_sp->UpdateCurrentFrameFromPreviousFrame(
908        *prev_frame_zero_sp);
909    //        prev_frame_zero_sp->UpdatePreviousFrameFromCurrentFrame
910    //        (*curr_frame_zero_sp);
911    //        prev_sp->SetFrameAtIndex (0, prev_frame_zero_sp);
912  } else if (curr_stack_id < prev_stack_id) {
913#if defined(DEBUG_STACK_FRAMES)
914    s.Printf("\nCurrent frame #0 has a stack ID that is less than the previous "
915             "frame #0, insert current frame zero in front of previous\n");
916#endif
917    prev_sp->m_frames.insert(prev_sp->m_frames.begin(), curr_frame_zero_sp);
918  }
919
920  curr_up.release();
921
922#if defined(DEBUG_STACK_FRAMES)
923  s.PutCString("\nMerged:\n");
924  prev_sp->Dump(&s);
925#endif
926}
927
928lldb::StackFrameSP
929StackFrameList::GetStackFrameSPForStackFramePtr(StackFrame *stack_frame_ptr) {
930  const_iterator pos;
931  const_iterator begin = m_frames.begin();
932  const_iterator end = m_frames.end();
933  lldb::StackFrameSP ret_sp;
934
935  for (pos = begin; pos != end; ++pos) {
936    if (pos->get() == stack_frame_ptr) {
937      ret_sp = (*pos);
938      break;
939    }
940  }
941  return ret_sp;
942}
943
944size_t StackFrameList::GetStatus(Stream &strm, uint32_t first_frame,
945                                 uint32_t num_frames, bool show_frame_info,
946                                 uint32_t num_frames_with_source,
947                                 bool show_unique,
948                                 const char *selected_frame_marker) {
949  size_t num_frames_displayed = 0;
950
951  if (num_frames == 0)
952    return 0;
953
954  StackFrameSP frame_sp;
955  uint32_t frame_idx = 0;
956  uint32_t last_frame;
957
958  // Don't let the last frame wrap around...
959  if (num_frames == UINT32_MAX)
960    last_frame = UINT32_MAX;
961  else
962    last_frame = first_frame + num_frames;
963
964  StackFrameSP selected_frame_sp = m_thread.GetSelectedFrame();
965  const char *unselected_marker = nullptr;
966  std::string buffer;
967  if (selected_frame_marker) {
968    size_t len = strlen(selected_frame_marker);
969    buffer.insert(buffer.begin(), len, ' ');
970    unselected_marker = buffer.c_str();
971  }
972  const char *marker = nullptr;
973
974  for (frame_idx = first_frame; frame_idx < last_frame; ++frame_idx) {
975    frame_sp = GetFrameAtIndex(frame_idx);
976    if (!frame_sp)
977      break;
978
979    if (selected_frame_marker != nullptr) {
980      if (frame_sp == selected_frame_sp)
981        marker = selected_frame_marker;
982      else
983        marker = unselected_marker;
984    }
985
986    if (!frame_sp->GetStatus(strm, show_frame_info,
987                             num_frames_with_source > (first_frame - frame_idx),
988                             show_unique, marker))
989      break;
990    ++num_frames_displayed;
991  }
992
993  strm.IndentLess();
994  return num_frames_displayed;
995}
996