1 //===-- StackFrameList.cpp --------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "lldb/Target/StackFrameList.h"
11 
12 // C Includes
13 // C++ Includes
14 // Other libraries and framework includes
15 // Project includes
16 #include "lldb/Core/StreamFile.h"
17 #include "lldb/Core/SourceManager.h"
18 #include "lldb/Symbol/Block.h"
19 #include "lldb/Symbol/Function.h"
20 #include "lldb/Symbol/Symbol.h"
21 #include "lldb/Target/Process.h"
22 #include "lldb/Target/RegisterContext.h"
23 #include "lldb/Target/StackFrame.h"
24 #include "lldb/Target/Target.h"
25 #include "lldb/Target/Thread.h"
26 #include "lldb/Target/Unwind.h"
27 
28 //#define DEBUG_STACK_FRAMES 1
29 
30 using namespace lldb;
31 using namespace lldb_private;
32 
33 //----------------------------------------------------------------------
34 // StackFrameList constructor
35 //----------------------------------------------------------------------
36 StackFrameList::StackFrameList
37 (
38     Thread &thread,
39     const lldb::StackFrameListSP &prev_frames_sp,
40     bool show_inline_frames
41 ) :
42     m_thread (thread),
43     m_prev_frames_sp (prev_frames_sp),
44     m_mutex (Mutex::eMutexTypeRecursive),
45     m_frames (),
46     m_selected_frame_idx (0),
47     m_show_inlined_frames (show_inline_frames)
48 {
49 }
50 
51 //----------------------------------------------------------------------
52 // Destructor
53 //----------------------------------------------------------------------
54 StackFrameList::~StackFrameList()
55 {
56 }
57 
58 
59 uint32_t
60 StackFrameList::GetNumFrames (bool can_create)
61 {
62     Mutex::Locker locker (m_mutex);
63 
64     if (can_create && m_frames.size() <= 1)
65     {
66         if (m_show_inlined_frames)
67         {
68 #if defined (DEBUG_STACK_FRAMES)
69             StreamFile s(stdout, false);
70 #endif
71             Unwind *unwinder = m_thread.GetUnwinder ();
72             addr_t pc = LLDB_INVALID_ADDRESS;
73             addr_t cfa = LLDB_INVALID_ADDRESS;
74 
75             // If we are going to show inlined stack frames as actual frames,
76             // we need to calculate all concrete frames first, then iterate
77             // through all of them and count up how many inlined functions are
78             // in each frame.
79             const uint32_t unwind_frame_count = unwinder->GetFrameCount();
80 
81             StackFrameSP unwind_frame_sp;
82             for (uint32_t idx=0; idx<unwind_frame_count; ++idx)
83             {
84                 if (idx == 0)
85                 {
86                     // We might have already created frame zero, only create it
87                     // if we need to
88                     if (m_frames.empty())
89                     {
90                         cfa = m_thread.m_reg_context_sp->GetSP();
91                         m_thread.GetRegisterContext();
92                         unwind_frame_sp.reset (new StackFrame (m_frames.size(),
93                                                                idx,
94                                                                m_thread,
95                                                                m_thread.m_reg_context_sp,
96                                                                cfa,
97                                                                m_thread.m_reg_context_sp->GetPC(),
98                                                                NULL));
99                         m_frames.push_back (unwind_frame_sp);
100                     }
101                     else
102                     {
103                         unwind_frame_sp = m_frames.front();
104                         cfa = unwind_frame_sp->m_id.GetCallFrameAddress();
105                     }
106                 }
107                 else
108                 {
109                     const bool success = unwinder->GetFrameInfoAtIndex(idx, cfa, pc);
110                     assert (success);
111                     unwind_frame_sp.reset (new StackFrame (m_frames.size(), idx, m_thread, cfa, pc, NULL));
112                     m_frames.push_back (unwind_frame_sp);
113                 }
114 
115                 Block *unwind_block = unwind_frame_sp->GetSymbolContext (eSymbolContextBlock).block;
116 
117                 if (unwind_block)
118                 {
119                     Block *inlined_block = unwind_block->GetContainingInlinedBlock();
120                     if (inlined_block)
121                     {
122                         for (; inlined_block != NULL; inlined_block = inlined_block->GetInlinedParent ())
123                         {
124                             SymbolContext inline_sc;
125                             Block *parent_block = inlined_block->GetInlinedParent();
126 
127                             const bool is_inlined_frame = parent_block != NULL;
128 
129                             if (parent_block == NULL)
130                                 parent_block = inlined_block->GetParent();
131 
132                             parent_block->CalculateSymbolContext (&inline_sc);
133 
134                             Address previous_frame_lookup_addr (m_frames.back()->GetFrameCodeAddress());
135                             if (unwind_frame_sp->GetFrameIndex() > 0 && m_frames.back().get() == unwind_frame_sp.get())
136                                 previous_frame_lookup_addr.Slide (-1);
137 
138                             AddressRange range;
139                             inlined_block->GetRangeContainingAddress (previous_frame_lookup_addr, range);
140 
141                             const InlineFunctionInfo* inline_info = inlined_block->GetInlinedFunctionInfo();
142                             assert (inline_info);
143                             inline_sc.line_entry.range.GetBaseAddress() = m_frames.back()->GetFrameCodeAddress();
144                             inline_sc.line_entry.file = inline_info->GetCallSite().GetFile();
145                             inline_sc.line_entry.line = inline_info->GetCallSite().GetLine();
146                             inline_sc.line_entry.column = inline_info->GetCallSite().GetColumn();
147 
148                             StackFrameSP frame_sp(new StackFrame (m_frames.size(),
149                                                                   idx,
150                                                                   m_thread,
151                                                                   unwind_frame_sp->GetRegisterContextSP (),
152                                                                   cfa,
153                                                                   range.GetBaseAddress(),
154                                                                   &inline_sc));                                           // The symbol context for this inline frame
155 
156                             if (is_inlined_frame)
157                             {
158                                 // Use the block with the inlined function info
159                                 // as the symbol context since we want this frame
160                                 // to have only the variables for the inlined function
161                                 frame_sp->SetSymbolContextScope (parent_block);
162                             }
163                             else
164                             {
165                                 // This block is not inlined with means it has no
166                                 // inlined parents either, so we want to use the top
167                                 // most function block.
168                                 frame_sp->SetSymbolContextScope (&unwind_frame_sp->GetSymbolContext (eSymbolContextFunction).function->GetBlock(false));
169                             }
170 
171                             m_frames.push_back (frame_sp);
172                         }
173                     }
174                 }
175             }
176 
177             if (m_prev_frames_sp)
178             {
179                 StackFrameList *prev_frames = m_prev_frames_sp.get();
180                 StackFrameList *curr_frames = this;
181 
182 #if defined (DEBUG_STACK_FRAMES)
183                 s.PutCString("\nprev_frames:\n");
184                 prev_frames->Dump (&s);
185                 s.PutCString("\ncurr_frames:\n");
186                 curr_frames->Dump (&s);
187                 s.EOL();
188 #endif
189                 size_t curr_frame_num, prev_frame_num;
190 
191                 for (curr_frame_num = curr_frames->m_frames.size(), prev_frame_num = prev_frames->m_frames.size();
192                      curr_frame_num > 0 && prev_frame_num > 0;
193                      --curr_frame_num, --prev_frame_num)
194                 {
195                     const size_t curr_frame_idx = curr_frame_num-1;
196                     const size_t prev_frame_idx = prev_frame_num-1;
197                     StackFrameSP curr_frame_sp (curr_frames->m_frames[curr_frame_idx]);
198                     StackFrameSP prev_frame_sp (prev_frames->m_frames[prev_frame_idx]);
199 
200 #if defined (DEBUG_STACK_FRAMES)
201                     s.Printf("\n\nCurr frame #%u ", curr_frame_idx);
202                     if (curr_frame_sp)
203                         curr_frame_sp->Dump (&s, true, false);
204                     else
205                         s.PutCString("NULL");
206                     s.Printf("\nPrev frame #%u ", prev_frame_idx);
207                     if (prev_frame_sp)
208                         prev_frame_sp->Dump (&s, true, false);
209                     else
210                         s.PutCString("NULL");
211 #endif
212 
213                     StackFrame *curr_frame = curr_frame_sp.get();
214                     StackFrame *prev_frame = prev_frame_sp.get();
215 
216                     if (curr_frame == NULL || prev_frame == NULL)
217                         break;
218 
219                     // Check the stack ID to make sure they are equal
220                     if (curr_frame->GetStackID() != prev_frame->GetStackID())
221                         break;
222 
223                     prev_frame->UpdatePreviousFrameFromCurrentFrame (*curr_frame);
224                     // Now copy the fixed up previous frame into the current frames
225                     // so the pointer doesn't change
226                     m_frames[curr_frame_idx] = prev_frame_sp;
227                     //curr_frame->UpdateCurrentFrameFromPreviousFrame (*prev_frame);
228 
229 #if defined (DEBUG_STACK_FRAMES)
230                     s.Printf("\n    Copying previous frame to current frame");
231 #endif
232                 }
233                 // We are done with the old stack frame list, we can release it now
234                 m_prev_frames_sp.reset();
235             }
236 
237 #if defined (DEBUG_STACK_FRAMES)
238                 s.PutCString("\n\nNew frames:\n");
239                 Dump (&s);
240                 s.EOL();
241 #endif
242         }
243         else
244         {
245             m_frames.resize(m_thread.GetUnwinder()->GetFrameCount());
246         }
247     }
248     return m_frames.size();
249 }
250 
251 void
252 StackFrameList::Dump (Stream *s)
253 {
254     if (s == NULL)
255         return;
256     Mutex::Locker locker (m_mutex);
257 
258     const_iterator pos, begin = m_frames.begin(), end = m_frames.end();
259     for (pos = begin; pos != end; ++pos)
260     {
261         StackFrame *frame = (*pos).get();
262         s->Printf("%p: ", frame);
263         if (frame)
264         {
265             frame->GetStackID().Dump (s);
266             frame->DumpUsingSettingsFormat (s);
267         }
268         else
269             s->Printf("frame #%u", std::distance (begin, pos));
270         s->EOL();
271     }
272     s->EOL();
273 }
274 
275 StackFrameSP
276 StackFrameList::GetFrameAtIndex (uint32_t idx)
277 {
278     StackFrameSP frame_sp;
279     Mutex::Locker locker (m_mutex);
280     if (idx < m_frames.size())
281         frame_sp = m_frames[idx];
282 
283     if (frame_sp)
284         return frame_sp;
285 
286     // Special case the first frame (idx == 0) so that we don't need to
287     // know how many stack frames there are to get it. If we need any other
288     // frames, then we do need to know if "idx" is a valid index.
289     if (idx == 0)
290     {
291         // If this is the first frame, we want to share the thread register
292         // context with the stack frame at index zero.
293         m_thread.GetRegisterContext();
294         assert (m_thread.m_reg_context_sp.get());
295         frame_sp.reset (new StackFrame (0,
296                                         0,
297                                         m_thread,
298                                         m_thread.m_reg_context_sp,
299                                         m_thread.m_reg_context_sp->GetSP(),
300                                         m_thread.m_reg_context_sp->GetPC(),
301                                         NULL));
302 
303         SetFrameAtIndex(idx, frame_sp);
304     }
305     else if (idx < GetNumFrames())
306     {
307         if (m_show_inlined_frames)
308         {
309             // When inline frames are enabled we cache up all frames in GetNumFrames()
310             frame_sp = m_frames[idx];
311         }
312         else
313         {
314             Unwind *unwinder = m_thread.GetUnwinder ();
315             if (unwinder)
316             {
317                 addr_t pc, cfa;
318                 if (unwinder->GetFrameInfoAtIndex(idx, cfa, pc))
319                 {
320                     frame_sp.reset (new StackFrame (idx, idx, m_thread, cfa, pc, NULL));
321 
322                     Function *function = frame_sp->GetSymbolContext (eSymbolContextFunction).function;
323                     if (function)
324                     {
325                         // When we aren't showing inline functions we always use
326                         // the top most function block as the scope.
327                         frame_sp->SetSymbolContextScope (&function->GetBlock(false));
328                     }
329                     else
330                     {
331                         // Set the symbol scope from the symbol regardless if it is NULL or valid.
332                         frame_sp->SetSymbolContextScope (frame_sp->GetSymbolContext (eSymbolContextSymbol).symbol);
333                     }
334                     SetFrameAtIndex(idx, frame_sp);
335                 }
336             }
337         }
338     }
339     return frame_sp;
340 }
341 
342 StackFrameSP
343 StackFrameList::GetFrameWithConcreteFrameIndex (uint32_t unwind_idx)
344 {
345     // First try assuming the unwind index is the same as the frame index. The
346     // unwind index is always greater than or equal to the frame index, so it
347     // is a good place to start. If we have inlined frames we might have 5
348     // concrete frames (frame unwind indexes go from 0-4), but we might have 15
349     // frames after we make all the inlined frames. Most of the time the unwind
350     // frame index (or the concrete frame index) is the same as the frame index.
351     uint32_t frame_idx = unwind_idx;
352     StackFrameSP frame_sp (GetFrameAtIndex (frame_idx));
353     while (frame_sp)
354     {
355         if (frame_sp->GetFrameIndex() == unwind_idx)
356             break;
357         frame_sp = GetFrameAtIndex (++frame_idx);
358     }
359     return frame_sp;
360 }
361 
362 StackFrameSP
363 StackFrameList::GetFrameWithStackID (StackID &stack_id)
364 {
365     uint32_t frame_idx = 0;
366     StackFrameSP frame_sp;
367     do
368     {
369         frame_sp = GetFrameAtIndex (frame_idx);
370         if (frame_sp && frame_sp->GetStackID() == stack_id)
371             break;
372         frame_idx++;
373     }
374     while (frame_sp);
375     return frame_sp;
376 }
377 
378 bool
379 StackFrameList::SetFrameAtIndex (uint32_t idx, StackFrameSP &frame_sp)
380 {
381     if (idx >= m_frames.size())
382         m_frames.resize(idx + 1);
383     // Make sure allocation succeeded by checking bounds again
384     if (idx < m_frames.size())
385     {
386         m_frames[idx] = frame_sp;
387         return true;
388     }
389     return false;   // resize failed, out of memory?
390 }
391 
392 uint32_t
393 StackFrameList::GetSelectedFrameIndex () const
394 {
395     Mutex::Locker locker (m_mutex);
396     return m_selected_frame_idx;
397 }
398 
399 
400 uint32_t
401 StackFrameList::SetSelectedFrame (lldb_private::StackFrame *frame)
402 {
403     Mutex::Locker locker (m_mutex);
404     const_iterator pos;
405     const_iterator begin = m_frames.begin();
406     const_iterator end = m_frames.end();
407     m_selected_frame_idx = 0;
408     for (pos = begin; pos != end; ++pos)
409     {
410         if (pos->get() == frame)
411         {
412             m_selected_frame_idx = std::distance (begin, pos);
413             break;
414         }
415     }
416     SetDefaultFileAndLineToSelectedFrame();
417     return m_selected_frame_idx;
418 }
419 
420 // Mark a stack frame as the current frame using the frame index
421 void
422 StackFrameList::SetSelectedFrameByIndex (uint32_t idx)
423 {
424     Mutex::Locker locker (m_mutex);
425     m_selected_frame_idx = idx;
426     SetDefaultFileAndLineToSelectedFrame();
427 }
428 
429 void
430 StackFrameList::SetDefaultFileAndLineToSelectedFrame()
431 {
432     if (m_thread.GetID() == m_thread.GetProcess().GetThreadList().GetSelectedThread()->GetID())
433     {
434         StackFrameSP frame_sp = m_frames[m_selected_frame_idx];
435         if (frame_sp)
436         {
437             SymbolContext sc = frame_sp->GetSymbolContext(eSymbolContextEverything);
438             if (sc.line_entry.file)
439             m_thread.GetProcess().GetTarget().GetSourceManager().SetDefaultFileAndLine (sc.line_entry.file, sc.line_entry.line);
440         }
441     }
442 }
443 
444 // The thread has been run, reset the number stack frames to zero so we can
445 // determine how many frames we have lazily.
446 void
447 StackFrameList::Clear ()
448 {
449     Mutex::Locker locker (m_mutex);
450     m_frames.clear();
451 }
452 
453 void
454 StackFrameList::InvalidateFrames (uint32_t start_idx)
455 {
456     Mutex::Locker locker (m_mutex);
457     if (m_show_inlined_frames)
458     {
459         Clear();
460     }
461     else
462     {
463         const size_t num_frames = m_frames.size();
464         while (start_idx < num_frames)
465         {
466             m_frames[start_idx].reset();
467             ++start_idx;
468         }
469     }
470 }
471 
472 void
473 StackFrameList::Merge (std::auto_ptr<StackFrameList>& curr_ap, lldb::StackFrameListSP& prev_sp)
474 {
475     Mutex::Locker curr_locker (curr_ap.get() ? curr_ap->m_mutex.GetMutex() : NULL);
476     Mutex::Locker prev_locker (prev_sp.get() ? prev_sp->m_mutex.GetMutex() : NULL);
477 
478 #if defined (DEBUG_STACK_FRAMES)
479     StreamFile s(stdout, false);
480     s.PutCString("\n\nStackFrameList::Merge():\nPrev:\n");
481     if (prev_sp.get())
482         prev_sp->Dump (&s);
483     else
484         s.PutCString ("NULL");
485     s.PutCString("\nCurr:\n");
486     if (curr_ap.get())
487         curr_ap->Dump (&s);
488     else
489         s.PutCString ("NULL");
490     s.EOL();
491 #endif
492 
493     if (curr_ap.get() == NULL || curr_ap->GetNumFrames (false) == 0)
494     {
495 #if defined (DEBUG_STACK_FRAMES)
496         s.PutCString("No current frames, leave previous frames alone...\n");
497 #endif
498         curr_ap.release();
499         return;
500     }
501 
502     if (prev_sp.get() == NULL || prev_sp->GetNumFrames (false) == 0)
503     {
504 #if defined (DEBUG_STACK_FRAMES)
505         s.PutCString("No previous frames, so use current frames...\n");
506 #endif
507         // We either don't have any previous frames, or since we have more than
508         // one current frames it means we have all the frames and can safely
509         // replace our previous frames.
510         prev_sp.reset (curr_ap.release());
511         return;
512     }
513 
514     const uint32_t num_curr_frames = curr_ap->GetNumFrames (false);
515 
516     if (num_curr_frames > 1)
517     {
518 #if defined (DEBUG_STACK_FRAMES)
519         s.PutCString("We have more than one current frame, so use current frames...\n");
520 #endif
521         // We have more than one current frames it means we have all the frames
522         // and can safely replace our previous frames.
523         prev_sp.reset (curr_ap.release());
524 
525 #if defined (DEBUG_STACK_FRAMES)
526         s.PutCString("\nMerged:\n");
527         prev_sp->Dump (&s);
528 #endif
529         return;
530     }
531 
532     StackFrameSP prev_frame_zero_sp(prev_sp->GetFrameAtIndex (0));
533     StackFrameSP curr_frame_zero_sp(curr_ap->GetFrameAtIndex (0));
534     StackID curr_stack_id (curr_frame_zero_sp->GetStackID());
535     StackID prev_stack_id (prev_frame_zero_sp->GetStackID());
536 
537 #if defined (DEBUG_STACK_FRAMES)
538     const uint32_t num_prev_frames = prev_sp->GetNumFrames (false);
539     s.Printf("\n%u previous frames with one current frame\n", num_prev_frames);
540 #endif
541 
542     // We have only a single current frame
543     // Our previous stack frames only had a single frame as well...
544     if (curr_stack_id == prev_stack_id)
545     {
546 #if defined (DEBUG_STACK_FRAMES)
547         s.Printf("\nPrevious frame #0 is same as current frame #0, merge the cached data\n");
548 #endif
549 
550         curr_frame_zero_sp->UpdateCurrentFrameFromPreviousFrame (*prev_frame_zero_sp);
551 //        prev_frame_zero_sp->UpdatePreviousFrameFromCurrentFrame (*curr_frame_zero_sp);
552 //        prev_sp->SetFrameAtIndex (0, prev_frame_zero_sp);
553     }
554     else if (curr_stack_id < prev_stack_id)
555     {
556 #if defined (DEBUG_STACK_FRAMES)
557         s.Printf("\nCurrent frame #0 has a stack ID that is less than the previous frame #0, insert current frame zero in front of previous\n");
558 #endif
559         prev_sp->m_frames.insert (prev_sp->m_frames.begin(), curr_frame_zero_sp);
560     }
561 
562     curr_ap.release();
563 
564 #if defined (DEBUG_STACK_FRAMES)
565     s.PutCString("\nMerged:\n");
566     prev_sp->Dump (&s);
567 #endif
568 
569 
570 }
571 
572 lldb::StackFrameSP
573 StackFrameList::GetStackFrameSPForStackFramePtr (StackFrame *stack_frame_ptr)
574 {
575     const_iterator pos;
576     const_iterator begin = m_frames.begin();
577     const_iterator end = m_frames.end();
578     lldb::StackFrameSP ret_sp;
579 
580     for (pos = begin; pos != end; ++pos)
581     {
582         if (pos->get() == stack_frame_ptr)
583         {
584             ret_sp = (*pos);
585             break;
586         }
587     }
588     return ret_sp;
589 }
590 
591 size_t
592 StackFrameList::GetStatus (Stream& strm,
593                            uint32_t first_frame,
594                            uint32_t num_frames,
595                            bool show_frame_info,
596                            uint32_t num_frames_with_source,
597                            uint32_t source_lines_before,
598                            uint32_t source_lines_after)
599 {
600     size_t num_frames_displayed = 0;
601 
602     if (num_frames == 0)
603         return 0;
604 
605     StackFrameSP frame_sp;
606     uint32_t frame_idx = 0;
607     uint32_t last_frame;
608 
609     // Don't let the last frame wrap around...
610     if (num_frames == UINT32_MAX)
611         last_frame = UINT32_MAX;
612     else
613         last_frame = first_frame + num_frames;
614 
615     for (frame_idx = first_frame; frame_idx < last_frame; ++frame_idx)
616     {
617         frame_sp = GetFrameAtIndex(frame_idx);
618         if (frame_sp.get() == NULL)
619             break;
620 
621         if (!frame_sp->GetStatus (strm,
622                                   show_frame_info,
623                                   num_frames_with_source > first_frame - frame_idx,
624                                   source_lines_before,
625                                   source_lines_after))
626             break;
627         ++num_frames_displayed;
628     }
629 
630     strm.IndentLess();
631     return num_frames_displayed;
632 }
633 
634