1 //===-- StackFrameList.cpp ------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "lldb/Target/StackFrameList.h"
10 #include "lldb/Breakpoint/Breakpoint.h"
11 #include "lldb/Breakpoint/BreakpointLocation.h"
12 #include "lldb/Core/Debugger.h"
13 #include "lldb/Core/SourceManager.h"
14 #include "lldb/Host/StreamFile.h"
15 #include "lldb/Symbol/Block.h"
16 #include "lldb/Symbol/Function.h"
17 #include "lldb/Symbol/Symbol.h"
18 #include "lldb/Target/Process.h"
19 #include "lldb/Target/RegisterContext.h"
20 #include "lldb/Target/StackFrame.h"
21 #include "lldb/Target/StackFrameRecognizer.h"
22 #include "lldb/Target/StopInfo.h"
23 #include "lldb/Target/Target.h"
24 #include "lldb/Target/Thread.h"
25 #include "lldb/Target/Unwind.h"
26 #include "lldb/Utility/LLDBLog.h"
27 #include "lldb/Utility/Log.h"
28 #include "llvm/ADT/SmallPtrSet.h"
32 //#define DEBUG_STACK_FRAMES 1
35 using namespace lldb_private
;
37 // StackFrameList constructor
38 StackFrameList::StackFrameList(Thread
&thread
,
39 const lldb::StackFrameListSP
&prev_frames_sp
,
40 bool show_inline_frames
)
41 : m_thread(thread
), m_prev_frames_sp(prev_frames_sp
), m_mutex(), m_frames(),
42 m_selected_frame_idx(), m_concrete_frames_fetched(0),
43 m_current_inlined_depth(UINT32_MAX
),
44 m_current_inlined_pc(LLDB_INVALID_ADDRESS
),
45 m_show_inlined_frames(show_inline_frames
) {
47 m_current_inlined_depth
= prev_frames_sp
->m_current_inlined_depth
;
48 m_current_inlined_pc
= prev_frames_sp
->m_current_inlined_pc
;
52 StackFrameList::~StackFrameList() {
53 // Call clear since this takes a lock and clears the stack frame list in case
54 // another thread is currently using this stack frame list
58 void StackFrameList::CalculateCurrentInlinedDepth() {
59 uint32_t cur_inlined_depth
= GetCurrentInlinedDepth();
60 if (cur_inlined_depth
== UINT32_MAX
) {
61 ResetCurrentInlinedDepth();
65 uint32_t StackFrameList::GetCurrentInlinedDepth() {
66 if (m_show_inlined_frames
&& m_current_inlined_pc
!= LLDB_INVALID_ADDRESS
) {
67 lldb::addr_t cur_pc
= m_thread
.GetRegisterContext()->GetPC();
68 if (cur_pc
!= m_current_inlined_pc
) {
69 m_current_inlined_pc
= LLDB_INVALID_ADDRESS
;
70 m_current_inlined_depth
= UINT32_MAX
;
71 Log
*log
= GetLog(LLDBLog::Step
);
72 if (log
&& log
->GetVerbose())
75 "GetCurrentInlinedDepth: invalidating current inlined depth.\n");
77 return m_current_inlined_depth
;
83 void StackFrameList::ResetCurrentInlinedDepth() {
84 if (!m_show_inlined_frames
)
87 std::lock_guard
<std::recursive_mutex
> guard(m_mutex
);
89 GetFramesUpTo(0, DoNotAllowInterruption
);
92 if (!m_frames
[0]->IsInlined()) {
93 m_current_inlined_depth
= UINT32_MAX
;
94 m_current_inlined_pc
= LLDB_INVALID_ADDRESS
;
95 Log
*log
= GetLog(LLDBLog::Step
);
96 if (log
&& log
->GetVerbose())
99 "ResetCurrentInlinedDepth: Invalidating current inlined depth.\n");
103 // We only need to do something special about inlined blocks when we are
104 // at the beginning of an inlined function:
105 // FIXME: We probably also have to do something special if the PC is at
106 // the END of an inlined function, which coincides with the end of either
107 // its containing function or another inlined function.
109 Block
*block_ptr
= m_frames
[0]->GetFrameBlock();
113 Address pc_as_address
;
114 lldb::addr_t curr_pc
= m_thread
.GetRegisterContext()->GetPC();
115 pc_as_address
.SetLoadAddress(curr_pc
, &(m_thread
.GetProcess()->GetTarget()));
116 AddressRange containing_range
;
117 if (!block_ptr
->GetRangeContainingAddress(pc_as_address
, containing_range
) ||
118 pc_as_address
!= containing_range
.GetBaseAddress())
121 // If we got here because of a breakpoint hit, then set the inlined depth
122 // depending on where the breakpoint was set. If we got here because of a
123 // crash, then set the inlined depth to the deepest most block. Otherwise,
124 // we stopped here naturally as the result of a step, so set ourselves in the
125 // containing frame of the whole set of nested inlines, so the user can then
126 // "virtually" step into the frames one by one, or next over the whole mess.
127 // Note: We don't have to handle being somewhere in the middle of the stack
128 // here, since ResetCurrentInlinedDepth doesn't get called if there is a
129 // valid inlined depth set.
130 StopInfoSP stop_info_sp
= m_thread
.GetStopInfo();
133 switch (stop_info_sp
->GetStopReason()) {
134 case eStopReasonWatchpoint
:
135 case eStopReasonException
:
136 case eStopReasonExec
:
137 case eStopReasonFork
:
138 case eStopReasonVFork
:
139 case eStopReasonVForkDone
:
140 case eStopReasonSignal
:
141 // In all these cases we want to stop in the deepest frame.
142 m_current_inlined_pc
= curr_pc
;
143 m_current_inlined_depth
= 0;
145 case eStopReasonBreakpoint
: {
146 // FIXME: Figure out what this break point is doing, and set the inline
147 // depth appropriately. Be careful to take into account breakpoints that
148 // implement step over prologue, since that should do the default
149 // calculation. For now, if the breakpoints corresponding to this hit are
150 // all internal, I set the stop location to the top of the inlined stack,
151 // since that will make things like stepping over prologues work right.
152 // But if there are any non-internal breakpoints I do to the bottom of the
153 // stack, since that was the old behavior.
154 uint32_t bp_site_id
= stop_info_sp
->GetValue();
155 BreakpointSiteSP
bp_site_sp(
156 m_thread
.GetProcess()->GetBreakpointSiteList().FindByID(bp_site_id
));
157 bool all_internal
= true;
159 uint32_t num_owners
= bp_site_sp
->GetNumberOfOwners();
160 for (uint32_t i
= 0; i
< num_owners
; i
++) {
161 Breakpoint
&bp_ref
= bp_site_sp
->GetOwnerAtIndex(i
)->GetBreakpoint();
162 if (!bp_ref
.IsInternal()) {
163 all_internal
= false;
168 m_current_inlined_pc
= curr_pc
;
169 m_current_inlined_depth
= 0;
175 // Otherwise, we should set ourselves at the container of the inlining, so
176 // that the user can descend into them. So first we check whether we have
177 // more than one inlined block sharing this PC:
178 int num_inlined_functions
= 0;
180 for (Block
*container_ptr
= block_ptr
->GetInlinedParent();
181 container_ptr
!= nullptr;
182 container_ptr
= container_ptr
->GetInlinedParent()) {
183 if (!container_ptr
->GetRangeContainingAddress(pc_as_address
,
186 if (pc_as_address
!= containing_range
.GetBaseAddress())
189 num_inlined_functions
++;
191 m_current_inlined_pc
= curr_pc
;
192 m_current_inlined_depth
= num_inlined_functions
+ 1;
193 Log
*log
= GetLog(LLDBLog::Step
);
194 if (log
&& log
->GetVerbose())
196 "ResetCurrentInlinedDepth: setting inlined "
197 "depth: %d 0x%" PRIx64
".\n",
198 m_current_inlined_depth
, curr_pc
);
205 bool StackFrameList::DecrementCurrentInlinedDepth() {
206 if (m_show_inlined_frames
) {
207 uint32_t current_inlined_depth
= GetCurrentInlinedDepth();
208 if (current_inlined_depth
!= UINT32_MAX
) {
209 if (current_inlined_depth
> 0) {
210 m_current_inlined_depth
--;
218 void StackFrameList::SetCurrentInlinedDepth(uint32_t new_depth
) {
219 m_current_inlined_depth
= new_depth
;
220 if (new_depth
== UINT32_MAX
)
221 m_current_inlined_pc
= LLDB_INVALID_ADDRESS
;
223 m_current_inlined_pc
= m_thread
.GetRegisterContext()->GetPC();
226 void StackFrameList::GetOnlyConcreteFramesUpTo(uint32_t end_idx
,
228 assert(m_thread
.IsValid() && "Expected valid thread");
229 assert(m_frames
.size() <= end_idx
&& "Expected there to be frames to fill");
231 if (end_idx
< m_concrete_frames_fetched
)
234 uint32_t num_frames
= unwinder
.GetFramesUpTo(end_idx
);
235 if (num_frames
<= end_idx
+ 1) {
237 m_concrete_frames_fetched
= UINT32_MAX
;
240 // Don't create the frames eagerly. Defer this work to GetFrameAtIndex,
241 // which can lazily query the unwinder to create frames.
242 m_frames
.resize(num_frames
);
245 /// A sequence of calls that comprise some portion of a backtrace. Each frame
246 /// is represented as a pair of a callee (Function *) and an address within the
248 struct CallDescriptor
{
250 CallEdge::AddrType address_type
= CallEdge::AddrType::Call
;
251 addr_t address
= LLDB_INVALID_ADDRESS
;
253 using CallSequence
= std::vector
<CallDescriptor
>;
255 /// Find the unique path through the call graph from \p begin (with return PC
256 /// \p return_pc) to \p end. On success this path is stored into \p path, and
257 /// on failure \p path is unchanged.
258 static void FindInterveningFrames(Function
&begin
, Function
&end
,
259 ExecutionContext
&exe_ctx
, Target
&target
,
260 addr_t return_pc
, CallSequence
&path
,
261 ModuleList
&images
, Log
*log
) {
262 LLDB_LOG(log
, "Finding frames between {0} and {1}, retn-pc={2:x}",
263 begin
.GetDisplayName(), end
.GetDisplayName(), return_pc
);
265 // Find a non-tail calling edge with the correct return PC.
267 for (const auto &edge
: begin
.GetCallEdges())
268 LLDB_LOG(log
, "FindInterveningFrames: found call with retn-PC = {0:x}",
269 edge
->GetReturnPCAddress(begin
, target
));
270 CallEdge
*first_edge
= begin
.GetCallEdgeForReturnAddress(return_pc
, target
);
272 LLDB_LOG(log
, "No call edge outgoing from {0} with retn-PC == {1:x}",
273 begin
.GetDisplayName(), return_pc
);
277 // The first callee may not be resolved, or there may be nothing to fill in.
278 Function
*first_callee
= first_edge
->GetCallee(images
, exe_ctx
);
280 LLDB_LOG(log
, "Could not resolve callee");
283 if (first_callee
== &end
) {
284 LLDB_LOG(log
, "Not searching further, first callee is {0} (retn-PC: {1:x})",
285 end
.GetDisplayName(), return_pc
);
289 // Run DFS on the tail-calling edges out of the first callee to find \p end.
290 // Fully explore the set of functions reachable from the first edge via tail
291 // calls in order to detect ambiguous executions.
293 CallSequence active_path
= {};
294 CallSequence solution_path
= {};
295 llvm::SmallPtrSet
<Function
*, 2> visited_nodes
= {};
296 bool ambiguous
= false;
300 ExecutionContext
&context
;
302 DFS(Function
*end
, ModuleList
&images
, Target
&target
,
303 ExecutionContext
&context
)
304 : end(end
), images(images
), target(target
), context(context
) {}
306 void search(CallEdge
&first_edge
, Function
&first_callee
,
307 CallSequence
&path
) {
308 dfs(first_edge
, first_callee
);
310 path
= std::move(solution_path
);
313 void dfs(CallEdge
¤t_edge
, Function
&callee
) {
314 // Found a path to the target function.
315 if (&callee
== end
) {
316 if (solution_path
.empty())
317 solution_path
= active_path
;
323 // Terminate the search if tail recursion is found, or more generally if
324 // there's more than one way to reach a target. This errs on the side of
325 // caution: it conservatively stops searching when some solutions are
326 // still possible to save time in the average case.
327 if (!visited_nodes
.insert(&callee
).second
) {
332 // Search the calls made from this callee.
333 active_path
.push_back(CallDescriptor
{&callee
});
334 for (const auto &edge
: callee
.GetTailCallingEdges()) {
335 Function
*next_callee
= edge
->GetCallee(images
, context
);
339 std::tie(active_path
.back().address_type
, active_path
.back().address
) =
340 edge
->GetCallerAddress(callee
, target
);
342 dfs(*edge
, *next_callee
);
346 active_path
.pop_back();
350 DFS(&end
, images
, target
, exe_ctx
).search(*first_edge
, *first_callee
, path
);
353 /// Given that \p next_frame will be appended to the frame list, synthesize
354 /// tail call frames between the current end of the list and \p next_frame.
355 /// If any frames are added, adjust the frame index of \p next_frame.
358 /// | ... | <- Completed frames.
362 /// | ... | <- Artificial frames inserted here.
366 /// | ... | <- Not-yet-visited frames.
368 void StackFrameList::SynthesizeTailCallFrames(StackFrame
&next_frame
) {
369 // Cannot synthesize tail call frames when the stack is empty (there is no
370 // "previous" frame).
371 if (m_frames
.empty())
374 TargetSP target_sp
= next_frame
.CalculateTarget();
378 lldb::RegisterContextSP next_reg_ctx_sp
= next_frame
.GetRegisterContext();
379 if (!next_reg_ctx_sp
)
382 Log
*log
= GetLog(LLDBLog::Step
);
384 StackFrame
&prev_frame
= *m_frames
.back().get();
386 // Find the functions prev_frame and next_frame are stopped in. The function
387 // objects are needed to search the lazy call graph for intervening frames.
388 Function
*prev_func
=
389 prev_frame
.GetSymbolContext(eSymbolContextFunction
).function
;
391 LLDB_LOG(log
, "SynthesizeTailCallFrames: can't find previous function");
394 Function
*next_func
=
395 next_frame
.GetSymbolContext(eSymbolContextFunction
).function
;
397 LLDB_LOG(log
, "SynthesizeTailCallFrames: can't find next function");
401 // Try to find the unique sequence of (tail) calls which led from next_frame
404 addr_t return_pc
= next_reg_ctx_sp
->GetPC();
405 Target
&target
= *target_sp
.get();
406 ModuleList
&images
= next_frame
.CalculateTarget()->GetImages();
407 ExecutionContext
exe_ctx(target_sp
, /*get_process=*/true);
408 exe_ctx
.SetFramePtr(&next_frame
);
409 FindInterveningFrames(*next_func
, *prev_func
, exe_ctx
, target
, return_pc
,
412 // Push synthetic tail call frames.
413 for (auto calleeInfo
: llvm::reverse(path
)) {
414 Function
*callee
= calleeInfo
.func
;
415 uint32_t frame_idx
= m_frames
.size();
416 uint32_t concrete_frame_idx
= next_frame
.GetConcreteFrameIndex();
417 addr_t cfa
= LLDB_INVALID_ADDRESS
;
418 bool cfa_is_valid
= false;
419 addr_t pc
= calleeInfo
.address
;
420 // If the callee address refers to the call instruction, we do not want to
421 // subtract 1 from this value.
422 const bool behaves_like_zeroth_frame
=
423 calleeInfo
.address_type
== CallEdge::AddrType::Call
;
425 callee
->CalculateSymbolContext(&sc
);
426 auto synth_frame
= std::make_shared
<StackFrame
>(
427 m_thread
.shared_from_this(), frame_idx
, concrete_frame_idx
, cfa
,
428 cfa_is_valid
, pc
, StackFrame::Kind::Artificial
,
429 behaves_like_zeroth_frame
, &sc
);
430 m_frames
.push_back(synth_frame
);
431 LLDB_LOG(log
, "Pushed frame {0} at {1:x}", callee
->GetDisplayName(), pc
);
434 // If any frames were created, adjust next_frame's index.
436 next_frame
.SetFrameIndex(m_frames
.size());
439 bool StackFrameList::GetFramesUpTo(uint32_t end_idx
,
440 InterruptionControl allow_interrupt
) {
441 // Do not fetch frames for an invalid thread.
442 bool was_interrupted
= false;
443 if (!m_thread
.IsValid())
446 // We've already gotten more frames than asked for, or we've already finished
447 // unwinding, return.
448 if (m_frames
.size() > end_idx
|| GetAllFramesFetched())
451 Unwind
&unwinder
= m_thread
.GetUnwinder();
453 if (!m_show_inlined_frames
) {
454 GetOnlyConcreteFramesUpTo(end_idx
, unwinder
);
458 #if defined(DEBUG_STACK_FRAMES)
459 StreamFile
s(stdout
, false);
461 // If we are hiding some frames from the outside world, we need to add
462 // those onto the total count of frames to fetch. However, we don't need
463 // to do that if end_idx is 0 since in that case we always get the first
464 // concrete frame and all the inlined frames below it... And of course, if
465 // end_idx is UINT32_MAX that means get all, so just do that...
467 uint32_t inlined_depth
= 0;
468 if (end_idx
> 0 && end_idx
!= UINT32_MAX
) {
469 inlined_depth
= GetCurrentInlinedDepth();
470 if (inlined_depth
!= UINT32_MAX
) {
472 end_idx
+= inlined_depth
;
476 StackFrameSP unwind_frame_sp
;
477 Debugger
&dbg
= m_thread
.GetProcess()->GetTarget().GetDebugger();
479 uint32_t idx
= m_concrete_frames_fetched
++;
480 lldb::addr_t pc
= LLDB_INVALID_ADDRESS
;
481 lldb::addr_t cfa
= LLDB_INVALID_ADDRESS
;
482 bool behaves_like_zeroth_frame
= (idx
== 0);
484 // We might have already created frame zero, only create it if we need
486 if (m_frames
.empty()) {
487 RegisterContextSP
reg_ctx_sp(m_thread
.GetRegisterContext());
490 const bool success
= unwinder
.GetFrameInfoAtIndex(
491 idx
, cfa
, pc
, behaves_like_zeroth_frame
);
492 // There shouldn't be any way not to get the frame info for frame
493 // 0. But if the unwinder can't make one, lets make one by hand
494 // with the SP as the CFA and see if that gets any further.
496 cfa
= reg_ctx_sp
->GetSP();
497 pc
= reg_ctx_sp
->GetPC();
500 unwind_frame_sp
= std::make_shared
<StackFrame
>(
501 m_thread
.shared_from_this(), m_frames
.size(), idx
, reg_ctx_sp
,
502 cfa
, pc
, behaves_like_zeroth_frame
, nullptr);
503 m_frames
.push_back(unwind_frame_sp
);
506 unwind_frame_sp
= m_frames
.front();
507 cfa
= unwind_frame_sp
->m_id
.GetCallFrameAddress();
510 // Check for interruption when building the frames.
511 // Do the check in idx > 0 so that we'll always create a 0th frame.
513 && INTERRUPT_REQUESTED(dbg
, "Interrupted having fetched {0} frames",
515 was_interrupted
= true;
520 unwinder
.GetFrameInfoAtIndex(idx
, cfa
, pc
, behaves_like_zeroth_frame
);
522 // We've gotten to the end of the stack.
523 SetAllFramesFetched();
526 const bool cfa_is_valid
= true;
527 unwind_frame_sp
= std::make_shared
<StackFrame
>(
528 m_thread
.shared_from_this(), m_frames
.size(), idx
, cfa
, cfa_is_valid
,
529 pc
, StackFrame::Kind::Regular
, behaves_like_zeroth_frame
, nullptr);
531 // Create synthetic tail call frames between the previous frame and the
532 // newly-found frame. The new frame's index may change after this call,
533 // although its concrete index will stay the same.
534 SynthesizeTailCallFrames(*unwind_frame_sp
.get());
536 m_frames
.push_back(unwind_frame_sp
);
539 assert(unwind_frame_sp
);
540 SymbolContext unwind_sc
= unwind_frame_sp
->GetSymbolContext(
541 eSymbolContextBlock
| eSymbolContextFunction
);
542 Block
*unwind_block
= unwind_sc
.block
;
543 TargetSP target_sp
= m_thread
.CalculateTarget();
545 Address
curr_frame_address(
546 unwind_frame_sp
->GetFrameCodeAddressForSymbolication());
548 SymbolContext next_frame_sc
;
549 Address next_frame_address
;
551 while (unwind_sc
.GetParentOfInlinedScope(
552 curr_frame_address
, next_frame_sc
, next_frame_address
)) {
553 next_frame_sc
.line_entry
.ApplyFileMappings(target_sp
);
554 behaves_like_zeroth_frame
= false;
555 StackFrameSP
frame_sp(new StackFrame(
556 m_thread
.shared_from_this(), m_frames
.size(), idx
,
557 unwind_frame_sp
->GetRegisterContextSP(), cfa
, next_frame_address
,
558 behaves_like_zeroth_frame
, &next_frame_sc
));
560 m_frames
.push_back(frame_sp
);
561 unwind_sc
= next_frame_sc
;
562 curr_frame_address
= next_frame_address
;
565 } while (m_frames
.size() - 1 < end_idx
);
567 // Don't try to merge till you've calculated all the frames in this stack.
568 if (GetAllFramesFetched() && m_prev_frames_sp
) {
569 StackFrameList
*prev_frames
= m_prev_frames_sp
.get();
570 StackFrameList
*curr_frames
= this;
572 #if defined(DEBUG_STACK_FRAMES)
573 s
.PutCString("\nprev_frames:\n");
574 prev_frames
->Dump(&s
);
575 s
.PutCString("\ncurr_frames:\n");
576 curr_frames
->Dump(&s
);
579 size_t curr_frame_num
, prev_frame_num
;
581 for (curr_frame_num
= curr_frames
->m_frames
.size(),
582 prev_frame_num
= prev_frames
->m_frames
.size();
583 curr_frame_num
> 0 && prev_frame_num
> 0;
584 --curr_frame_num
, --prev_frame_num
) {
585 const size_t curr_frame_idx
= curr_frame_num
- 1;
586 const size_t prev_frame_idx
= prev_frame_num
- 1;
587 StackFrameSP
curr_frame_sp(curr_frames
->m_frames
[curr_frame_idx
]);
588 StackFrameSP
prev_frame_sp(prev_frames
->m_frames
[prev_frame_idx
]);
590 #if defined(DEBUG_STACK_FRAMES)
591 s
.Printf("\n\nCurr frame #%u ", curr_frame_idx
);
593 curr_frame_sp
->Dump(&s
, true, false);
595 s
.PutCString("NULL");
596 s
.Printf("\nPrev frame #%u ", prev_frame_idx
);
598 prev_frame_sp
->Dump(&s
, true, false);
600 s
.PutCString("NULL");
603 StackFrame
*curr_frame
= curr_frame_sp
.get();
604 StackFrame
*prev_frame
= prev_frame_sp
.get();
606 if (curr_frame
== nullptr || prev_frame
== nullptr)
609 // Check the stack ID to make sure they are equal.
610 if (curr_frame
->GetStackID() != prev_frame
->GetStackID())
613 prev_frame
->UpdatePreviousFrameFromCurrentFrame(*curr_frame
);
614 // Now copy the fixed up previous frame into the current frames so the
615 // pointer doesn't change.
616 m_frames
[curr_frame_idx
] = prev_frame_sp
;
618 #if defined(DEBUG_STACK_FRAMES)
619 s
.Printf("\n Copying previous frame to current frame");
622 // We are done with the old stack frame list, we can release it now.
623 m_prev_frames_sp
.reset();
626 #if defined(DEBUG_STACK_FRAMES)
627 s
.PutCString("\n\nNew frames:\n");
631 // Don't report interrupted if we happen to have gotten all the frames:
632 if (!GetAllFramesFetched())
633 return was_interrupted
;
637 uint32_t StackFrameList::GetNumFrames(bool can_create
) {
638 std::lock_guard
<std::recursive_mutex
> guard(m_mutex
);
641 // Don't allow interrupt or we might not return the correct count
642 GetFramesUpTo(UINT32_MAX
, DoNotAllowInterruption
);
644 return GetVisibleStackFrameIndex(m_frames
.size());
647 void StackFrameList::Dump(Stream
*s
) {
651 std::lock_guard
<std::recursive_mutex
> guard(m_mutex
);
653 const_iterator pos
, begin
= m_frames
.begin(), end
= m_frames
.end();
654 for (pos
= begin
; pos
!= end
; ++pos
) {
655 StackFrame
*frame
= (*pos
).get();
656 s
->Printf("%p: ", static_cast<void *>(frame
));
658 frame
->GetStackID().Dump(s
);
659 frame
->DumpUsingSettingsFormat(s
);
661 s
->Printf("frame #%u", (uint32_t)std::distance(begin
, pos
));
667 StackFrameSP
StackFrameList::GetFrameAtIndex(uint32_t idx
) {
668 StackFrameSP frame_sp
;
669 std::lock_guard
<std::recursive_mutex
> guard(m_mutex
);
670 uint32_t original_idx
= idx
;
672 uint32_t inlined_depth
= GetCurrentInlinedDepth();
673 if (inlined_depth
!= UINT32_MAX
)
674 idx
+= inlined_depth
;
676 if (idx
< m_frames
.size())
677 frame_sp
= m_frames
[idx
];
682 // GetFramesUpTo will fill m_frames with as many frames as you asked for, if
683 // there are that many. If there weren't then you asked for too many frames.
684 // GetFramesUpTo returns true if interrupted:
685 if (GetFramesUpTo(idx
)) {
686 Log
*log
= GetLog(LLDBLog::Thread
);
687 LLDB_LOG(log
, "GetFrameAtIndex was interrupted");
691 if (idx
< m_frames
.size()) {
692 if (m_show_inlined_frames
) {
693 // When inline frames are enabled we actually create all the frames in
695 frame_sp
= m_frames
[idx
];
698 bool behaves_like_zeroth_frame
= (idx
== 0);
699 if (m_thread
.GetUnwinder().GetFrameInfoAtIndex(
700 idx
, cfa
, pc
, behaves_like_zeroth_frame
)) {
701 const bool cfa_is_valid
= true;
702 frame_sp
= std::make_shared
<StackFrame
>(
703 m_thread
.shared_from_this(), idx
, idx
, cfa
, cfa_is_valid
, pc
,
704 StackFrame::Kind::Regular
, behaves_like_zeroth_frame
, nullptr);
707 frame_sp
->GetSymbolContext(eSymbolContextFunction
).function
;
709 // When we aren't showing inline functions we always use the top
710 // most function block as the scope.
711 frame_sp
->SetSymbolContextScope(&function
->GetBlock(false));
713 // Set the symbol scope from the symbol regardless if it is nullptr
715 frame_sp
->SetSymbolContextScope(
716 frame_sp
->GetSymbolContext(eSymbolContextSymbol
).symbol
);
718 SetFrameAtIndex(idx
, frame_sp
);
721 } else if (original_idx
== 0) {
722 // There should ALWAYS be a frame at index 0. If something went wrong with
723 // the CurrentInlinedDepth such that there weren't as many frames as we
724 // thought taking that into account, then reset the current inlined depth
725 // and return the real zeroth frame.
726 if (m_frames
.empty()) {
727 // Why do we have a thread with zero frames, that should not ever
729 assert(!m_thread
.IsValid() && "A valid thread has no frames.");
731 ResetCurrentInlinedDepth();
732 frame_sp
= m_frames
[original_idx
];
740 StackFrameList::GetFrameWithConcreteFrameIndex(uint32_t unwind_idx
) {
741 // First try assuming the unwind index is the same as the frame index. The
742 // unwind index is always greater than or equal to the frame index, so it is
743 // a good place to start. If we have inlined frames we might have 5 concrete
744 // frames (frame unwind indexes go from 0-4), but we might have 15 frames
745 // after we make all the inlined frames. Most of the time the unwind frame
746 // index (or the concrete frame index) is the same as the frame index.
747 uint32_t frame_idx
= unwind_idx
;
748 StackFrameSP
frame_sp(GetFrameAtIndex(frame_idx
));
750 if (frame_sp
->GetFrameIndex() == unwind_idx
)
752 frame_sp
= GetFrameAtIndex(++frame_idx
);
757 static bool CompareStackID(const StackFrameSP
&stack_sp
,
758 const StackID
&stack_id
) {
759 return stack_sp
->GetStackID() < stack_id
;
762 StackFrameSP
StackFrameList::GetFrameWithStackID(const StackID
&stack_id
) {
763 StackFrameSP frame_sp
;
765 if (stack_id
.IsValid()) {
766 std::lock_guard
<std::recursive_mutex
> guard(m_mutex
);
767 uint32_t frame_idx
= 0;
768 // Do a binary search in case the stack frame is already in our cache
769 collection::const_iterator begin
= m_frames
.begin();
770 collection::const_iterator end
= m_frames
.end();
772 collection::const_iterator pos
=
773 std::lower_bound(begin
, end
, stack_id
, CompareStackID
);
775 if ((*pos
)->GetStackID() == stack_id
)
780 frame_sp
= GetFrameAtIndex(frame_idx
);
781 if (frame_sp
&& frame_sp
->GetStackID() == stack_id
)
789 bool StackFrameList::SetFrameAtIndex(uint32_t idx
, StackFrameSP
&frame_sp
) {
790 if (idx
>= m_frames
.size())
791 m_frames
.resize(idx
+ 1);
792 // Make sure allocation succeeded by checking bounds again
793 if (idx
< m_frames
.size()) {
794 m_frames
[idx
] = frame_sp
;
797 return false; // resize failed, out of memory?
800 void StackFrameList::SelectMostRelevantFrame() {
801 // Don't call into the frame recognizers on the private state thread as
802 // they can cause code to run in the target, and that can cause deadlocks
803 // when fetching stop events for the expression.
804 if (m_thread
.GetProcess()->CurrentThreadIsPrivateStateThread())
807 Log
*log
= GetLog(LLDBLog::Thread
);
809 // Only the top frame should be recognized.
810 StackFrameSP frame_sp
= GetFrameAtIndex(0);
812 LLDB_LOG(log
, "Failed to construct Frame #0");
816 RecognizedStackFrameSP recognized_frame_sp
= frame_sp
->GetRecognizedFrame();
818 if (!recognized_frame_sp
) {
819 LLDB_LOG(log
, "Frame #0 not recognized");
823 if (StackFrameSP most_relevant_frame_sp
=
824 recognized_frame_sp
->GetMostRelevantFrame()) {
825 LLDB_LOG(log
, "Found most relevant frame at index {0}",
826 most_relevant_frame_sp
->GetFrameIndex());
827 SetSelectedFrame(most_relevant_frame_sp
.get());
829 LLDB_LOG(log
, "No relevant frame!");
833 uint32_t StackFrameList::GetSelectedFrameIndex(
834 SelectMostRelevant select_most_relevant
) {
835 std::lock_guard
<std::recursive_mutex
> guard(m_mutex
);
836 if (!m_selected_frame_idx
&& select_most_relevant
)
837 SelectMostRelevantFrame();
838 if (!m_selected_frame_idx
) {
839 // If we aren't selecting the most relevant frame, and the selected frame
840 // isn't set, then don't force a selection here, just return 0.
841 if (!select_most_relevant
)
843 m_selected_frame_idx
= 0;
845 return *m_selected_frame_idx
;
848 uint32_t StackFrameList::SetSelectedFrame(lldb_private::StackFrame
*frame
) {
849 std::lock_guard
<std::recursive_mutex
> guard(m_mutex
);
851 const_iterator begin
= m_frames
.begin();
852 const_iterator end
= m_frames
.end();
853 m_selected_frame_idx
= 0;
855 for (pos
= begin
; pos
!= end
; ++pos
) {
856 if (pos
->get() == frame
) {
857 m_selected_frame_idx
= std::distance(begin
, pos
);
858 uint32_t inlined_depth
= GetCurrentInlinedDepth();
859 if (inlined_depth
!= UINT32_MAX
)
860 m_selected_frame_idx
= *m_selected_frame_idx
- inlined_depth
;
865 SetDefaultFileAndLineToSelectedFrame();
866 return *m_selected_frame_idx
;
869 bool StackFrameList::SetSelectedFrameByIndex(uint32_t idx
) {
870 std::lock_guard
<std::recursive_mutex
> guard(m_mutex
);
871 StackFrameSP
frame_sp(GetFrameAtIndex(idx
));
873 SetSelectedFrame(frame_sp
.get());
879 void StackFrameList::SetDefaultFileAndLineToSelectedFrame() {
880 if (m_thread
.GetID() ==
881 m_thread
.GetProcess()->GetThreadList().GetSelectedThread()->GetID()) {
882 StackFrameSP
frame_sp(
883 GetFrameAtIndex(GetSelectedFrameIndex(DoNoSelectMostRelevantFrame
)));
885 SymbolContext sc
= frame_sp
->GetSymbolContext(eSymbolContextLineEntry
);
886 if (sc
.line_entry
.file
)
887 m_thread
.CalculateTarget()->GetSourceManager().SetDefaultFileAndLine(
888 sc
.line_entry
.file
, sc
.line_entry
.line
);
893 // The thread has been run, reset the number stack frames to zero so we can
894 // determine how many frames we have lazily.
895 // Note, we don't actually re-use StackFrameLists, we always make a new
896 // StackFrameList every time we stop, and then copy frame information frame
897 // by frame from the old to the new StackFrameList. So the comment above,
898 // does not describe how StackFrameLists are currently used.
899 // Clear is currently only used to clear the list in the destructor.
900 void StackFrameList::Clear() {
901 std::lock_guard
<std::recursive_mutex
> guard(m_mutex
);
903 m_concrete_frames_fetched
= 0;
904 m_selected_frame_idx
.reset();
908 StackFrameList::GetStackFrameSPForStackFramePtr(StackFrame
*stack_frame_ptr
) {
910 const_iterator begin
= m_frames
.begin();
911 const_iterator end
= m_frames
.end();
912 lldb::StackFrameSP ret_sp
;
914 for (pos
= begin
; pos
!= end
; ++pos
) {
915 if (pos
->get() == stack_frame_ptr
) {
923 size_t StackFrameList::GetStatus(Stream
&strm
, uint32_t first_frame
,
924 uint32_t num_frames
, bool show_frame_info
,
925 uint32_t num_frames_with_source
,
927 const char *selected_frame_marker
) {
928 size_t num_frames_displayed
= 0;
933 StackFrameSP frame_sp
;
934 uint32_t frame_idx
= 0;
937 // Don't let the last frame wrap around...
938 if (num_frames
== UINT32_MAX
)
939 last_frame
= UINT32_MAX
;
941 last_frame
= first_frame
+ num_frames
;
943 StackFrameSP selected_frame_sp
=
944 m_thread
.GetSelectedFrame(DoNoSelectMostRelevantFrame
);
945 const char *unselected_marker
= nullptr;
947 if (selected_frame_marker
) {
948 size_t len
= strlen(selected_frame_marker
);
949 buffer
.insert(buffer
.begin(), len
, ' ');
950 unselected_marker
= buffer
.c_str();
952 const char *marker
= nullptr;
954 for (frame_idx
= first_frame
; frame_idx
< last_frame
; ++frame_idx
) {
955 frame_sp
= GetFrameAtIndex(frame_idx
);
959 if (selected_frame_marker
!= nullptr) {
960 if (frame_sp
== selected_frame_sp
)
961 marker
= selected_frame_marker
;
963 marker
= unselected_marker
;
965 // Check for interruption here. If we're fetching arguments, this loop
967 Debugger
&dbg
= m_thread
.GetProcess()->GetTarget().GetDebugger();
968 if (INTERRUPT_REQUESTED(dbg
,
969 "Interrupted dumping stack for thread {0:hex} with {1} shown.",
970 m_thread
.GetID(), num_frames_displayed
))
974 if (!frame_sp
->GetStatus(strm
, show_frame_info
,
975 num_frames_with_source
> (first_frame
- frame_idx
),
976 show_unique
, marker
))
978 ++num_frames_displayed
;
982 return num_frames_displayed
;