Example #1
0
StackFrameSP StackFrameList::GetFrameAtIndex(uint32_t idx) {
  StackFrameSP frame_sp;
  std::lock_guard<std::recursive_mutex> guard(m_mutex);
  uint32_t original_idx = idx;

  uint32_t inlined_depth = GetCurrentInlinedDepth();
  if (inlined_depth != UINT32_MAX)
    idx += inlined_depth;

  if (idx < m_frames.size())
    frame_sp = m_frames[idx];

  if (frame_sp)
    return frame_sp;

  // GetFramesUpTo will fill m_frames with as many frames as you asked for,
  // if there are that many.  If there weren't then you asked for too many
  // frames.
  GetFramesUpTo(idx);
  if (idx < m_frames.size()) {
    if (m_show_inlined_frames) {
      // When inline frames are enabled we actually create all the frames in
      // GetFramesUpTo.
      frame_sp = m_frames[idx];
    } else {
      Unwind *unwinder = m_thread.GetUnwinder();
      if (unwinder) {
        addr_t pc, cfa;
        if (unwinder->GetFrameInfoAtIndex(idx, cfa, pc)) {
          const bool cfa_is_valid = true;
          const bool stop_id_is_valid = false;
          const bool is_history_frame = false;
          frame_sp.reset(new StackFrame(
              m_thread.shared_from_this(), idx, idx, cfa, cfa_is_valid, pc, 0,
              stop_id_is_valid, is_history_frame, nullptr));

          Function *function =
              frame_sp->GetSymbolContext(eSymbolContextFunction).function;
          if (function) {
            // When we aren't showing inline functions we always use
            // the top most function block as the scope.
            frame_sp->SetSymbolContextScope(&function->GetBlock(false));
          } else {
            // Set the symbol scope from the symbol regardless if it is nullptr
            // or valid.
            frame_sp->SetSymbolContextScope(
                frame_sp->GetSymbolContext(eSymbolContextSymbol).symbol);
          }
          SetFrameAtIndex(idx, frame_sp);
        }
      }
    }
  } else if (original_idx == 0) {
    // There should ALWAYS be a frame at index 0.  If something went wrong with
    // the CurrentInlinedDepth such that
    // there weren't as many frames as we thought taking that into account, then
    // reset the current inlined depth
    // and return the real zeroth frame.
    if (m_frames.empty()) {
      // Why do we have a thread with zero frames, that should not ever
      // happen...
      if (m_thread.IsValid())
        assert("A valid thread has no frames.");
    } else {
      ResetCurrentInlinedDepth();
      frame_sp = m_frames[original_idx];
    }
  }

  return frame_sp;
}