forked from OSchip/llvm-project
				
			[StackFrame] Factor GetOnlyConcreteFramesUpTo out of GetFramesUpTo (NFC)
Splitting GetOnlyConcreteFramesUpTo will make it easier to implement support for synthetic tail call frames in backtraces. This is just a prep change, no functionality is affected. llvm-svn: 338588
This commit is contained in:
		
							parent
							
								
									6d302c93cc
								
							
						
					
					
						commit
						eb8fa58e97
					
				| 
						 | 
					@ -83,6 +83,8 @@ protected:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void GetFramesUpTo(uint32_t end_idx);
 | 
					  void GetFramesUpTo(uint32_t end_idx);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  void GetOnlyConcreteFramesUpTo(uint32_t end_idx, Unwind *unwinder);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  bool GetAllFramesFetched() { return m_concrete_frames_fetched == UINT32_MAX; }
 | 
					  bool GetAllFramesFetched() { return m_concrete_frames_fetched == UINT32_MAX; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void SetAllFramesFetched() { m_concrete_frames_fetched = UINT32_MAX; }
 | 
					  void SetAllFramesFetched() { m_concrete_frames_fetched = UINT32_MAX; }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -226,8 +226,27 @@ void StackFrameList::SetCurrentInlinedDepth(uint32_t new_depth) {
 | 
				
			||||||
    m_current_inlined_pc = m_thread.GetRegisterContext()->GetPC();
 | 
					    m_current_inlined_pc = m_thread.GetRegisterContext()->GetPC();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void StackFrameList::GetOnlyConcreteFramesUpTo(uint32_t end_idx,
 | 
				
			||||||
 | 
					                                               Unwind *unwinder) {
 | 
				
			||||||
 | 
					  assert(m_thread.IsValid() && "Expected valid thread");
 | 
				
			||||||
 | 
					  assert(m_frames.size() <= end_idx && "Expected there to be frames to fill");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (end_idx < m_concrete_frames_fetched)
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (!unwinder)
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  uint32_t num_frames = unwinder->GetFramesUpTo(end_idx);
 | 
				
			||||||
 | 
					  if (num_frames <= end_idx + 1) {
 | 
				
			||||||
 | 
					    // Done unwinding.
 | 
				
			||||||
 | 
					    m_concrete_frames_fetched = UINT32_MAX;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  m_frames.resize(num_frames);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void StackFrameList::GetFramesUpTo(uint32_t end_idx) {
 | 
					void StackFrameList::GetFramesUpTo(uint32_t end_idx) {
 | 
				
			||||||
  // this makes sure we do not fetch frames for an invalid thread
 | 
					  // Do not fetch frames for an invalid thread.
 | 
				
			||||||
  if (!m_thread.IsValid())
 | 
					  if (!m_thread.IsValid())
 | 
				
			||||||
    return;
 | 
					    return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -238,201 +257,185 @@ void StackFrameList::GetFramesUpTo(uint32_t end_idx) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  Unwind *unwinder = m_thread.GetUnwinder();
 | 
					  Unwind *unwinder = m_thread.GetUnwinder();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (m_show_inlined_frames) {
 | 
					  if (!m_show_inlined_frames) {
 | 
				
			||||||
#if defined(DEBUG_STACK_FRAMES)
 | 
					    GetOnlyConcreteFramesUpTo(end_idx, unwinder);
 | 
				
			||||||
    StreamFile s(stdout, false);
 | 
					    return;
 | 
				
			||||||
#endif
 | 
					  }
 | 
				
			||||||
    // If we are hiding some frames from the outside world, we need to add
 | 
					 | 
				
			||||||
    // those onto the total count of frames to fetch.  However, we don't need
 | 
					 | 
				
			||||||
    // to do that if end_idx is 0 since in that case we always get the first
 | 
					 | 
				
			||||||
    // concrete frame and all the inlined frames below it...  And of course, if
 | 
					 | 
				
			||||||
    // end_idx is UINT32_MAX that means get all, so just do that...
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    uint32_t inlined_depth = 0;
 | 
					 | 
				
			||||||
    if (end_idx > 0 && end_idx != UINT32_MAX) {
 | 
					 | 
				
			||||||
      inlined_depth = GetCurrentInlinedDepth();
 | 
					 | 
				
			||||||
      if (inlined_depth != UINT32_MAX) {
 | 
					 | 
				
			||||||
        if (end_idx > 0)
 | 
					 | 
				
			||||||
          end_idx += inlined_depth;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    StackFrameSP unwind_frame_sp;
 | 
					 | 
				
			||||||
    do {
 | 
					 | 
				
			||||||
      uint32_t idx = m_concrete_frames_fetched++;
 | 
					 | 
				
			||||||
      lldb::addr_t pc = LLDB_INVALID_ADDRESS;
 | 
					 | 
				
			||||||
      lldb::addr_t cfa = LLDB_INVALID_ADDRESS;
 | 
					 | 
				
			||||||
      if (idx == 0) {
 | 
					 | 
				
			||||||
        // We might have already created frame zero, only create it if we need
 | 
					 | 
				
			||||||
        // to
 | 
					 | 
				
			||||||
        if (m_frames.empty()) {
 | 
					 | 
				
			||||||
          RegisterContextSP reg_ctx_sp(m_thread.GetRegisterContext());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
          if (reg_ctx_sp) {
 | 
					 | 
				
			||||||
            const bool success =
 | 
					 | 
				
			||||||
                unwinder && unwinder->GetFrameInfoAtIndex(idx, cfa, pc);
 | 
					 | 
				
			||||||
            // There shouldn't be any way not to get the frame info for frame
 | 
					 | 
				
			||||||
            // 0. But if the unwinder can't make one, lets make one by hand
 | 
					 | 
				
			||||||
            // with the
 | 
					 | 
				
			||||||
            // SP as the CFA and see if that gets any further.
 | 
					 | 
				
			||||||
            if (!success) {
 | 
					 | 
				
			||||||
              cfa = reg_ctx_sp->GetSP();
 | 
					 | 
				
			||||||
              pc = reg_ctx_sp->GetPC();
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            unwind_frame_sp.reset(new StackFrame(m_thread.shared_from_this(),
 | 
					 | 
				
			||||||
                                                 m_frames.size(), idx,
 | 
					 | 
				
			||||||
                                                 reg_ctx_sp, cfa, pc, nullptr));
 | 
					 | 
				
			||||||
            m_frames.push_back(unwind_frame_sp);
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
          unwind_frame_sp = m_frames.front();
 | 
					 | 
				
			||||||
          cfa = unwind_frame_sp->m_id.GetCallFrameAddress();
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      } else {
 | 
					 | 
				
			||||||
        const bool success =
 | 
					 | 
				
			||||||
            unwinder && unwinder->GetFrameInfoAtIndex(idx, cfa, pc);
 | 
					 | 
				
			||||||
        if (!success) {
 | 
					 | 
				
			||||||
          // We've gotten to the end of the stack.
 | 
					 | 
				
			||||||
          SetAllFramesFetched();
 | 
					 | 
				
			||||||
          break;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        const bool cfa_is_valid = true;
 | 
					 | 
				
			||||||
        const bool stop_id_is_valid = false;
 | 
					 | 
				
			||||||
        const bool is_history_frame = false;
 | 
					 | 
				
			||||||
        unwind_frame_sp.reset(new StackFrame(
 | 
					 | 
				
			||||||
            m_thread.shared_from_this(), m_frames.size(), idx, cfa,
 | 
					 | 
				
			||||||
            cfa_is_valid, pc, 0, stop_id_is_valid, is_history_frame, nullptr));
 | 
					 | 
				
			||||||
        m_frames.push_back(unwind_frame_sp);
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      assert(unwind_frame_sp);
 | 
					 | 
				
			||||||
      SymbolContext unwind_sc = unwind_frame_sp->GetSymbolContext(
 | 
					 | 
				
			||||||
          eSymbolContextBlock | eSymbolContextFunction);
 | 
					 | 
				
			||||||
      Block *unwind_block = unwind_sc.block;
 | 
					 | 
				
			||||||
      if (unwind_block) {
 | 
					 | 
				
			||||||
        Address curr_frame_address(unwind_frame_sp->GetFrameCodeAddress());
 | 
					 | 
				
			||||||
        TargetSP target_sp = m_thread.CalculateTarget();
 | 
					 | 
				
			||||||
        // Be sure to adjust the frame address to match the address that was
 | 
					 | 
				
			||||||
        // used to lookup the symbol context above. If we are in the first
 | 
					 | 
				
			||||||
        // concrete frame, then we lookup using the current address, else we
 | 
					 | 
				
			||||||
        // decrement the address by one to get the correct location.
 | 
					 | 
				
			||||||
        if (idx > 0) {
 | 
					 | 
				
			||||||
          if (curr_frame_address.GetOffset() == 0) {
 | 
					 | 
				
			||||||
            // If curr_frame_address points to the first address in a section
 | 
					 | 
				
			||||||
            // then after adjustment it will point to an other section. In that
 | 
					 | 
				
			||||||
            // case resolve the address again to the correct section plus
 | 
					 | 
				
			||||||
            // offset form.
 | 
					 | 
				
			||||||
            addr_t load_addr = curr_frame_address.GetOpcodeLoadAddress(
 | 
					 | 
				
			||||||
                target_sp.get(), AddressClass::eCode);
 | 
					 | 
				
			||||||
            curr_frame_address.SetOpcodeLoadAddress(
 | 
					 | 
				
			||||||
                load_addr - 1, target_sp.get(), AddressClass::eCode);
 | 
					 | 
				
			||||||
          } else {
 | 
					 | 
				
			||||||
            curr_frame_address.Slide(-1);
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        SymbolContext next_frame_sc;
 | 
					 | 
				
			||||||
        Address next_frame_address;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        while (unwind_sc.GetParentOfInlinedScope(
 | 
					 | 
				
			||||||
            curr_frame_address, next_frame_sc, next_frame_address)) {
 | 
					 | 
				
			||||||
          next_frame_sc.line_entry.ApplyFileMappings(target_sp);
 | 
					 | 
				
			||||||
          StackFrameSP frame_sp(
 | 
					 | 
				
			||||||
              new StackFrame(m_thread.shared_from_this(), m_frames.size(), idx,
 | 
					 | 
				
			||||||
                             unwind_frame_sp->GetRegisterContextSP(), cfa,
 | 
					 | 
				
			||||||
                             next_frame_address, &next_frame_sc));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
          m_frames.push_back(frame_sp);
 | 
					 | 
				
			||||||
          unwind_sc = next_frame_sc;
 | 
					 | 
				
			||||||
          curr_frame_address = next_frame_address;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    } while (m_frames.size() - 1 < end_idx);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // Don't try to merge till you've calculated all the frames in this stack.
 | 
					 | 
				
			||||||
    if (GetAllFramesFetched() && m_prev_frames_sp) {
 | 
					 | 
				
			||||||
      StackFrameList *prev_frames = m_prev_frames_sp.get();
 | 
					 | 
				
			||||||
      StackFrameList *curr_frames = this;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// curr_frames->m_current_inlined_depth = prev_frames->m_current_inlined_depth;
 | 
					 | 
				
			||||||
// curr_frames->m_current_inlined_pc = prev_frames->m_current_inlined_pc;
 | 
					 | 
				
			||||||
// printf ("GetFramesUpTo: Copying current inlined depth: %d 0x%" PRIx64 ".\n",
 | 
					 | 
				
			||||||
// curr_frames->m_current_inlined_depth, curr_frames->m_current_inlined_pc);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if defined(DEBUG_STACK_FRAMES)
 | 
					#if defined(DEBUG_STACK_FRAMES)
 | 
				
			||||||
      s.PutCString("\nprev_frames:\n");
 | 
					  StreamFile s(stdout, false);
 | 
				
			||||||
      prev_frames->Dump(&s);
 | 
					 | 
				
			||||||
      s.PutCString("\ncurr_frames:\n");
 | 
					 | 
				
			||||||
      curr_frames->Dump(&s);
 | 
					 | 
				
			||||||
      s.EOL();
 | 
					 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
      size_t curr_frame_num, prev_frame_num;
 | 
					  // If we are hiding some frames from the outside world, we need to add
 | 
				
			||||||
 | 
					  // those onto the total count of frames to fetch.  However, we don't need
 | 
				
			||||||
 | 
					  // to do that if end_idx is 0 since in that case we always get the first
 | 
				
			||||||
 | 
					  // concrete frame and all the inlined frames below it...  And of course, if
 | 
				
			||||||
 | 
					  // end_idx is UINT32_MAX that means get all, so just do that...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      for (curr_frame_num = curr_frames->m_frames.size(),
 | 
					  uint32_t inlined_depth = 0;
 | 
				
			||||||
          prev_frame_num = prev_frames->m_frames.size();
 | 
					  if (end_idx > 0 && end_idx != UINT32_MAX) {
 | 
				
			||||||
           curr_frame_num > 0 && prev_frame_num > 0;
 | 
					    inlined_depth = GetCurrentInlinedDepth();
 | 
				
			||||||
           --curr_frame_num, --prev_frame_num) {
 | 
					    if (inlined_depth != UINT32_MAX) {
 | 
				
			||||||
        const size_t curr_frame_idx = curr_frame_num - 1;
 | 
					      if (end_idx > 0)
 | 
				
			||||||
        const size_t prev_frame_idx = prev_frame_num - 1;
 | 
					        end_idx += inlined_depth;
 | 
				
			||||||
        StackFrameSP curr_frame_sp(curr_frames->m_frames[curr_frame_idx]);
 | 
					 | 
				
			||||||
        StackFrameSP prev_frame_sp(prev_frames->m_frames[prev_frame_idx]);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#if defined(DEBUG_STACK_FRAMES)
 | 
					 | 
				
			||||||
        s.Printf("\n\nCurr frame #%u ", curr_frame_idx);
 | 
					 | 
				
			||||||
        if (curr_frame_sp)
 | 
					 | 
				
			||||||
          curr_frame_sp->Dump(&s, true, false);
 | 
					 | 
				
			||||||
        else
 | 
					 | 
				
			||||||
          s.PutCString("NULL");
 | 
					 | 
				
			||||||
        s.Printf("\nPrev frame #%u ", prev_frame_idx);
 | 
					 | 
				
			||||||
        if (prev_frame_sp)
 | 
					 | 
				
			||||||
          prev_frame_sp->Dump(&s, true, false);
 | 
					 | 
				
			||||||
        else
 | 
					 | 
				
			||||||
          s.PutCString("NULL");
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        StackFrame *curr_frame = curr_frame_sp.get();
 | 
					 | 
				
			||||||
        StackFrame *prev_frame = prev_frame_sp.get();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (curr_frame == nullptr || prev_frame == nullptr)
 | 
					 | 
				
			||||||
          break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Check the stack ID to make sure they are equal
 | 
					 | 
				
			||||||
        if (curr_frame->GetStackID() != prev_frame->GetStackID())
 | 
					 | 
				
			||||||
          break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        prev_frame->UpdatePreviousFrameFromCurrentFrame(*curr_frame);
 | 
					 | 
				
			||||||
        // Now copy the fixed up previous frame into the current frames so the
 | 
					 | 
				
			||||||
        // pointer doesn't change
 | 
					 | 
				
			||||||
        m_frames[curr_frame_idx] = prev_frame_sp;
 | 
					 | 
				
			||||||
// curr_frame->UpdateCurrentFrameFromPreviousFrame (*prev_frame);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#if defined(DEBUG_STACK_FRAMES)
 | 
					 | 
				
			||||||
        s.Printf("\n    Copying previous frame to current frame");
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      // We are done with the old stack frame list, we can release it now
 | 
					 | 
				
			||||||
      m_prev_frames_sp.reset();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#if defined(DEBUG_STACK_FRAMES)
 | 
					 | 
				
			||||||
    s.PutCString("\n\nNew frames:\n");
 | 
					 | 
				
			||||||
    Dump(&s);
 | 
					 | 
				
			||||||
    s.EOL();
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
  } else {
 | 
					 | 
				
			||||||
    if (end_idx < m_concrete_frames_fetched)
 | 
					 | 
				
			||||||
      return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (unwinder) {
 | 
					 | 
				
			||||||
      uint32_t num_frames = unwinder->GetFramesUpTo(end_idx);
 | 
					 | 
				
			||||||
      if (num_frames <= end_idx + 1) {
 | 
					 | 
				
			||||||
        // Done unwinding.
 | 
					 | 
				
			||||||
        m_concrete_frames_fetched = UINT32_MAX;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      m_frames.resize(num_frames);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  StackFrameSP unwind_frame_sp;
 | 
				
			||||||
 | 
					  do {
 | 
				
			||||||
 | 
					    uint32_t idx = m_concrete_frames_fetched++;
 | 
				
			||||||
 | 
					    lldb::addr_t pc = LLDB_INVALID_ADDRESS;
 | 
				
			||||||
 | 
					    lldb::addr_t cfa = LLDB_INVALID_ADDRESS;
 | 
				
			||||||
 | 
					    if (idx == 0) {
 | 
				
			||||||
 | 
					      // We might have already created frame zero, only create it if we need
 | 
				
			||||||
 | 
					      // to.
 | 
				
			||||||
 | 
					      if (m_frames.empty()) {
 | 
				
			||||||
 | 
					        RegisterContextSP reg_ctx_sp(m_thread.GetRegisterContext());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (reg_ctx_sp) {
 | 
				
			||||||
 | 
					          const bool success =
 | 
				
			||||||
 | 
					              unwinder && unwinder->GetFrameInfoAtIndex(idx, cfa, pc);
 | 
				
			||||||
 | 
					          // There shouldn't be any way not to get the frame info for frame
 | 
				
			||||||
 | 
					          // 0. But if the unwinder can't make one, lets make one by hand
 | 
				
			||||||
 | 
					          // with the SP as the CFA and see if that gets any further.
 | 
				
			||||||
 | 
					          if (!success) {
 | 
				
			||||||
 | 
					            cfa = reg_ctx_sp->GetSP();
 | 
				
			||||||
 | 
					            pc = reg_ctx_sp->GetPC();
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          unwind_frame_sp.reset(new StackFrame(m_thread.shared_from_this(),
 | 
				
			||||||
 | 
					                                               m_frames.size(), idx, reg_ctx_sp,
 | 
				
			||||||
 | 
					                                               cfa, pc, nullptr));
 | 
				
			||||||
 | 
					          m_frames.push_back(unwind_frame_sp);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        unwind_frame_sp = m_frames.front();
 | 
				
			||||||
 | 
					        cfa = unwind_frame_sp->m_id.GetCallFrameAddress();
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      const bool success =
 | 
				
			||||||
 | 
					          unwinder && unwinder->GetFrameInfoAtIndex(idx, cfa, pc);
 | 
				
			||||||
 | 
					      if (!success) {
 | 
				
			||||||
 | 
					        // We've gotten to the end of the stack.
 | 
				
			||||||
 | 
					        SetAllFramesFetched();
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      const bool cfa_is_valid = true;
 | 
				
			||||||
 | 
					      const bool stop_id_is_valid = false;
 | 
				
			||||||
 | 
					      const bool is_history_frame = false;
 | 
				
			||||||
 | 
					      unwind_frame_sp.reset(new StackFrame(
 | 
				
			||||||
 | 
					          m_thread.shared_from_this(), m_frames.size(), idx, cfa, cfa_is_valid,
 | 
				
			||||||
 | 
					          pc, 0, stop_id_is_valid, is_history_frame, nullptr));
 | 
				
			||||||
 | 
					      m_frames.push_back(unwind_frame_sp);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    assert(unwind_frame_sp);
 | 
				
			||||||
 | 
					    SymbolContext unwind_sc = unwind_frame_sp->GetSymbolContext(
 | 
				
			||||||
 | 
					        eSymbolContextBlock | eSymbolContextFunction);
 | 
				
			||||||
 | 
					    Block *unwind_block = unwind_sc.block;
 | 
				
			||||||
 | 
					    if (unwind_block) {
 | 
				
			||||||
 | 
					      Address curr_frame_address(unwind_frame_sp->GetFrameCodeAddress());
 | 
				
			||||||
 | 
					      TargetSP target_sp = m_thread.CalculateTarget();
 | 
				
			||||||
 | 
					      // Be sure to adjust the frame address to match the address that was
 | 
				
			||||||
 | 
					      // used to lookup the symbol context above. If we are in the first
 | 
				
			||||||
 | 
					      // concrete frame, then we lookup using the current address, else we
 | 
				
			||||||
 | 
					      // decrement the address by one to get the correct location.
 | 
				
			||||||
 | 
					      if (idx > 0) {
 | 
				
			||||||
 | 
					        if (curr_frame_address.GetOffset() == 0) {
 | 
				
			||||||
 | 
					          // If curr_frame_address points to the first address in a section
 | 
				
			||||||
 | 
					          // then after adjustment it will point to an other section. In that
 | 
				
			||||||
 | 
					          // case resolve the address again to the correct section plus
 | 
				
			||||||
 | 
					          // offset form.
 | 
				
			||||||
 | 
					          addr_t load_addr = curr_frame_address.GetOpcodeLoadAddress(
 | 
				
			||||||
 | 
					              target_sp.get(), AddressClass::eCode);
 | 
				
			||||||
 | 
					          curr_frame_address.SetOpcodeLoadAddress(
 | 
				
			||||||
 | 
					              load_addr - 1, target_sp.get(), AddressClass::eCode);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					          curr_frame_address.Slide(-1);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      SymbolContext next_frame_sc;
 | 
				
			||||||
 | 
					      Address next_frame_address;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      while (unwind_sc.GetParentOfInlinedScope(
 | 
				
			||||||
 | 
					          curr_frame_address, next_frame_sc, next_frame_address)) {
 | 
				
			||||||
 | 
					        next_frame_sc.line_entry.ApplyFileMappings(target_sp);
 | 
				
			||||||
 | 
					        StackFrameSP frame_sp(
 | 
				
			||||||
 | 
					            new StackFrame(m_thread.shared_from_this(), m_frames.size(), idx,
 | 
				
			||||||
 | 
					                           unwind_frame_sp->GetRegisterContextSP(), cfa,
 | 
				
			||||||
 | 
					                           next_frame_address, &next_frame_sc));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        m_frames.push_back(frame_sp);
 | 
				
			||||||
 | 
					        unwind_sc = next_frame_sc;
 | 
				
			||||||
 | 
					        curr_frame_address = next_frame_address;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  } while (m_frames.size() - 1 < end_idx);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Don't try to merge till you've calculated all the frames in this stack.
 | 
				
			||||||
 | 
					  if (GetAllFramesFetched() && m_prev_frames_sp) {
 | 
				
			||||||
 | 
					    StackFrameList *prev_frames = m_prev_frames_sp.get();
 | 
				
			||||||
 | 
					    StackFrameList *curr_frames = this;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(DEBUG_STACK_FRAMES)
 | 
				
			||||||
 | 
					    s.PutCString("\nprev_frames:\n");
 | 
				
			||||||
 | 
					    prev_frames->Dump(&s);
 | 
				
			||||||
 | 
					    s.PutCString("\ncurr_frames:\n");
 | 
				
			||||||
 | 
					    curr_frames->Dump(&s);
 | 
				
			||||||
 | 
					    s.EOL();
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					    size_t curr_frame_num, prev_frame_num;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (curr_frame_num = curr_frames->m_frames.size(),
 | 
				
			||||||
 | 
					        prev_frame_num = prev_frames->m_frames.size();
 | 
				
			||||||
 | 
					         curr_frame_num > 0 && prev_frame_num > 0;
 | 
				
			||||||
 | 
					         --curr_frame_num, --prev_frame_num) {
 | 
				
			||||||
 | 
					      const size_t curr_frame_idx = curr_frame_num - 1;
 | 
				
			||||||
 | 
					      const size_t prev_frame_idx = prev_frame_num - 1;
 | 
				
			||||||
 | 
					      StackFrameSP curr_frame_sp(curr_frames->m_frames[curr_frame_idx]);
 | 
				
			||||||
 | 
					      StackFrameSP prev_frame_sp(prev_frames->m_frames[prev_frame_idx]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(DEBUG_STACK_FRAMES)
 | 
				
			||||||
 | 
					      s.Printf("\n\nCurr frame #%u ", curr_frame_idx);
 | 
				
			||||||
 | 
					      if (curr_frame_sp)
 | 
				
			||||||
 | 
					        curr_frame_sp->Dump(&s, true, false);
 | 
				
			||||||
 | 
					      else
 | 
				
			||||||
 | 
					        s.PutCString("NULL");
 | 
				
			||||||
 | 
					      s.Printf("\nPrev frame #%u ", prev_frame_idx);
 | 
				
			||||||
 | 
					      if (prev_frame_sp)
 | 
				
			||||||
 | 
					        prev_frame_sp->Dump(&s, true, false);
 | 
				
			||||||
 | 
					      else
 | 
				
			||||||
 | 
					        s.PutCString("NULL");
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      StackFrame *curr_frame = curr_frame_sp.get();
 | 
				
			||||||
 | 
					      StackFrame *prev_frame = prev_frame_sp.get();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (curr_frame == nullptr || prev_frame == nullptr)
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      // Check the stack ID to make sure they are equal.
 | 
				
			||||||
 | 
					      if (curr_frame->GetStackID() != prev_frame->GetStackID())
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      prev_frame->UpdatePreviousFrameFromCurrentFrame(*curr_frame);
 | 
				
			||||||
 | 
					      // Now copy the fixed up previous frame into the current frames so the
 | 
				
			||||||
 | 
					      // pointer doesn't change.
 | 
				
			||||||
 | 
					      m_frames[curr_frame_idx] = prev_frame_sp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(DEBUG_STACK_FRAMES)
 | 
				
			||||||
 | 
					      s.Printf("\n    Copying previous frame to current frame");
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    // We are done with the old stack frame list, we can release it now.
 | 
				
			||||||
 | 
					    m_prev_frames_sp.reset();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(DEBUG_STACK_FRAMES)
 | 
				
			||||||
 | 
					  s.PutCString("\n\nNew frames:\n");
 | 
				
			||||||
 | 
					  Dump(&s);
 | 
				
			||||||
 | 
					  s.EOL();
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
uint32_t StackFrameList::GetNumFrames(bool can_create) {
 | 
					uint32_t StackFrameList::GetNumFrames(bool can_create) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue