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                 SymbolContext unwind_sc = unwind_frame_sp->GetSymbolContext (eSymbolContextBlock | eSymbolContextFunction);
116                 Block *unwind_block = unwind_sc.block;
117                 if (unwind_block)
118                 {
119                     Address curr_frame_address = unwind_frame_sp->GetFrameCodeAddress();
120                     SymbolContext next_frame_sc;
121                     Address next_frame_address;
122 
123                     while (unwind_sc.GetParentOfInlinedScope(curr_frame_address, next_frame_sc, next_frame_address))
124                     {
125                             StackFrameSP frame_sp(new StackFrame (m_frames.size(),
126                                                                   idx,
127                                                                   m_thread,
128                                                                   unwind_frame_sp->GetRegisterContextSP (),
129                                                                   cfa,
130                                                                   next_frame_address,
131                                                                   &next_frame_sc));
132 
133                             m_frames.push_back (frame_sp);
134                             unwind_sc = next_frame_sc;
135                             curr_frame_address = next_frame_address;
136 
137                     }
138                 }
139             }
140 
141             if (m_prev_frames_sp)
142             {
143                 StackFrameList *prev_frames = m_prev_frames_sp.get();
144                 StackFrameList *curr_frames = this;
145 
146 #if defined (DEBUG_STACK_FRAMES)
147                 s.PutCString("\nprev_frames:\n");
148                 prev_frames->Dump (&s);
149                 s.PutCString("\ncurr_frames:\n");
150                 curr_frames->Dump (&s);
151                 s.EOL();
152 #endif
153                 size_t curr_frame_num, prev_frame_num;
154 
155                 for (curr_frame_num = curr_frames->m_frames.size(), prev_frame_num = prev_frames->m_frames.size();
156                      curr_frame_num > 0 && prev_frame_num > 0;
157                      --curr_frame_num, --prev_frame_num)
158                 {
159                     const size_t curr_frame_idx = curr_frame_num-1;
160                     const size_t prev_frame_idx = prev_frame_num-1;
161                     StackFrameSP curr_frame_sp (curr_frames->m_frames[curr_frame_idx]);
162                     StackFrameSP prev_frame_sp (prev_frames->m_frames[prev_frame_idx]);
163 
164 #if defined (DEBUG_STACK_FRAMES)
165                     s.Printf("\n\nCurr frame #%u ", curr_frame_idx);
166                     if (curr_frame_sp)
167                         curr_frame_sp->Dump (&s, true, false);
168                     else
169                         s.PutCString("NULL");
170                     s.Printf("\nPrev frame #%u ", prev_frame_idx);
171                     if (prev_frame_sp)
172                         prev_frame_sp->Dump (&s, true, false);
173                     else
174                         s.PutCString("NULL");
175 #endif
176 
177                     StackFrame *curr_frame = curr_frame_sp.get();
178                     StackFrame *prev_frame = prev_frame_sp.get();
179 
180                     if (curr_frame == NULL || prev_frame == NULL)
181                         break;
182 
183                     // Check the stack ID to make sure they are equal
184                     if (curr_frame->GetStackID() != prev_frame->GetStackID())
185                         break;
186 
187                     prev_frame->UpdatePreviousFrameFromCurrentFrame (*curr_frame);
188                     // Now copy the fixed up previous frame into the current frames
189                     // so the pointer doesn't change
190                     m_frames[curr_frame_idx] = prev_frame_sp;
191                     //curr_frame->UpdateCurrentFrameFromPreviousFrame (*prev_frame);
192 
193 #if defined (DEBUG_STACK_FRAMES)
194                     s.Printf("\n    Copying previous frame to current frame");
195 #endif
196                 }
197                 // We are done with the old stack frame list, we can release it now
198                 m_prev_frames_sp.reset();
199             }
200 
201 #if defined (DEBUG_STACK_FRAMES)
202                 s.PutCString("\n\nNew frames:\n");
203                 Dump (&s);
204                 s.EOL();
205 #endif
206         }
207         else
208         {
209             m_frames.resize(m_thread.GetUnwinder()->GetFrameCount());
210         }
211     }
212     return m_frames.size();
213 }
214 
215 void
216 StackFrameList::Dump (Stream *s)
217 {
218     if (s == NULL)
219         return;
220     Mutex::Locker locker (m_mutex);
221 
222     const_iterator pos, begin = m_frames.begin(), end = m_frames.end();
223     for (pos = begin; pos != end; ++pos)
224     {
225         StackFrame *frame = (*pos).get();
226         s->Printf("%p: ", frame);
227         if (frame)
228         {
229             frame->GetStackID().Dump (s);
230             frame->DumpUsingSettingsFormat (s);
231         }
232         else
233             s->Printf("frame #%ld", std::distance (begin, pos));
234         s->EOL();
235     }
236     s->EOL();
237 }
238 
239 StackFrameSP
240 StackFrameList::GetFrameAtIndex (uint32_t idx)
241 {
242     StackFrameSP frame_sp;
243     Mutex::Locker locker (m_mutex);
244     if (idx < m_frames.size())
245         frame_sp = m_frames[idx];
246 
247     if (frame_sp)
248         return frame_sp;
249 
250     // Special case the first frame (idx == 0) so that we don't need to
251     // know how many stack frames there are to get it. If we need any other
252     // frames, then we do need to know if "idx" is a valid index.
253     if (idx == 0)
254     {
255         // If this is the first frame, we want to share the thread register
256         // context with the stack frame at index zero.
257         m_thread.GetRegisterContext();
258         assert (m_thread.m_reg_context_sp.get());
259         frame_sp.reset (new StackFrame (0,
260                                         0,
261                                         m_thread,
262                                         m_thread.m_reg_context_sp,
263                                         m_thread.m_reg_context_sp->GetSP(),
264                                         m_thread.m_reg_context_sp->GetPC(),
265                                         NULL));
266 
267         SetFrameAtIndex(idx, frame_sp);
268     }
269     else if (idx < GetNumFrames())
270     {
271         if (m_show_inlined_frames)
272         {
273             // When inline frames are enabled we cache up all frames in GetNumFrames()
274             frame_sp = m_frames[idx];
275         }
276         else
277         {
278             Unwind *unwinder = m_thread.GetUnwinder ();
279             if (unwinder)
280             {
281                 addr_t pc, cfa;
282                 if (unwinder->GetFrameInfoAtIndex(idx, cfa, pc))
283                 {
284                     frame_sp.reset (new StackFrame (idx, idx, m_thread, cfa, pc, NULL));
285 
286                     Function *function = frame_sp->GetSymbolContext (eSymbolContextFunction).function;
287                     if (function)
288                     {
289                         // When we aren't showing inline functions we always use
290                         // the top most function block as the scope.
291                         frame_sp->SetSymbolContextScope (&function->GetBlock(false));
292                     }
293                     else
294                     {
295                         // Set the symbol scope from the symbol regardless if it is NULL or valid.
296                         frame_sp->SetSymbolContextScope (frame_sp->GetSymbolContext (eSymbolContextSymbol).symbol);
297                     }
298                     SetFrameAtIndex(idx, frame_sp);
299                 }
300             }
301         }
302     }
303     return frame_sp;
304 }
305 
306 StackFrameSP
307 StackFrameList::GetFrameWithConcreteFrameIndex (uint32_t unwind_idx)
308 {
309     // First try assuming the unwind index is the same as the frame index. The
310     // unwind index is always greater than or equal to the frame index, so it
311     // is a good place to start. If we have inlined frames we might have 5
312     // concrete frames (frame unwind indexes go from 0-4), but we might have 15
313     // frames after we make all the inlined frames. Most of the time the unwind
314     // frame index (or the concrete frame index) is the same as the frame index.
315     uint32_t frame_idx = unwind_idx;
316     StackFrameSP frame_sp (GetFrameAtIndex (frame_idx));
317     while (frame_sp)
318     {
319         if (frame_sp->GetFrameIndex() == unwind_idx)
320             break;
321         frame_sp = GetFrameAtIndex (++frame_idx);
322     }
323     return frame_sp;
324 }
325 
326 StackFrameSP
327 StackFrameList::GetFrameWithStackID (StackID &stack_id)
328 {
329     uint32_t frame_idx = 0;
330     StackFrameSP frame_sp;
331     do
332     {
333         frame_sp = GetFrameAtIndex (frame_idx);
334         if (frame_sp && frame_sp->GetStackID() == stack_id)
335             break;
336         frame_idx++;
337     }
338     while (frame_sp);
339     return frame_sp;
340 }
341 
342 bool
343 StackFrameList::SetFrameAtIndex (uint32_t idx, StackFrameSP &frame_sp)
344 {
345     if (idx >= m_frames.size())
346         m_frames.resize(idx + 1);
347     // Make sure allocation succeeded by checking bounds again
348     if (idx < m_frames.size())
349     {
350         m_frames[idx] = frame_sp;
351         return true;
352     }
353     return false;   // resize failed, out of memory?
354 }
355 
356 uint32_t
357 StackFrameList::GetSelectedFrameIndex () const
358 {
359     Mutex::Locker locker (m_mutex);
360     return m_selected_frame_idx;
361 }
362 
363 
364 uint32_t
365 StackFrameList::SetSelectedFrame (lldb_private::StackFrame *frame)
366 {
367     Mutex::Locker locker (m_mutex);
368     const_iterator pos;
369     const_iterator begin = m_frames.begin();
370     const_iterator end = m_frames.end();
371     m_selected_frame_idx = 0;
372     for (pos = begin; pos != end; ++pos)
373     {
374         if (pos->get() == frame)
375         {
376             m_selected_frame_idx = std::distance (begin, pos);
377             break;
378         }
379     }
380     SetDefaultFileAndLineToSelectedFrame();
381     return m_selected_frame_idx;
382 }
383 
384 // Mark a stack frame as the current frame using the frame index
385 void
386 StackFrameList::SetSelectedFrameByIndex (uint32_t idx)
387 {
388     Mutex::Locker locker (m_mutex);
389     m_selected_frame_idx = idx;
390     SetDefaultFileAndLineToSelectedFrame();
391 }
392 
393 void
394 StackFrameList::SetDefaultFileAndLineToSelectedFrame()
395 {
396     if (m_thread.GetID() == m_thread.GetProcess().GetThreadList().GetSelectedThread()->GetID())
397     {
398         StackFrameSP frame_sp = m_frames[m_selected_frame_idx];
399         if (frame_sp)
400         {
401             SymbolContext sc = frame_sp->GetSymbolContext(eSymbolContextEverything);
402             if (sc.line_entry.file)
403             m_thread.GetProcess().GetTarget().GetSourceManager().SetDefaultFileAndLine (sc.line_entry.file, sc.line_entry.line);
404         }
405     }
406 }
407 
408 // The thread has been run, reset the number stack frames to zero so we can
409 // determine how many frames we have lazily.
410 void
411 StackFrameList::Clear ()
412 {
413     Mutex::Locker locker (m_mutex);
414     m_frames.clear();
415 }
416 
417 void
418 StackFrameList::InvalidateFrames (uint32_t start_idx)
419 {
420     Mutex::Locker locker (m_mutex);
421     if (m_show_inlined_frames)
422     {
423         Clear();
424     }
425     else
426     {
427         const size_t num_frames = m_frames.size();
428         while (start_idx < num_frames)
429         {
430             m_frames[start_idx].reset();
431             ++start_idx;
432         }
433     }
434 }
435 
436 void
437 StackFrameList::Merge (std::auto_ptr<StackFrameList>& curr_ap, lldb::StackFrameListSP& prev_sp)
438 {
439     Mutex::Locker curr_locker (curr_ap.get() ? curr_ap->m_mutex.GetMutex() : NULL);
440     Mutex::Locker prev_locker (prev_sp.get() ? prev_sp->m_mutex.GetMutex() : NULL);
441 
442 #if defined (DEBUG_STACK_FRAMES)
443     StreamFile s(stdout, false);
444     s.PutCString("\n\nStackFrameList::Merge():\nPrev:\n");
445     if (prev_sp.get())
446         prev_sp->Dump (&s);
447     else
448         s.PutCString ("NULL");
449     s.PutCString("\nCurr:\n");
450     if (curr_ap.get())
451         curr_ap->Dump (&s);
452     else
453         s.PutCString ("NULL");
454     s.EOL();
455 #endif
456 
457     if (curr_ap.get() == NULL || curr_ap->GetNumFrames (false) == 0)
458     {
459 #if defined (DEBUG_STACK_FRAMES)
460         s.PutCString("No current frames, leave previous frames alone...\n");
461 #endif
462         curr_ap.release();
463         return;
464     }
465 
466     if (prev_sp.get() == NULL || prev_sp->GetNumFrames (false) == 0)
467     {
468 #if defined (DEBUG_STACK_FRAMES)
469         s.PutCString("No previous frames, so use current frames...\n");
470 #endif
471         // We either don't have any previous frames, or since we have more than
472         // one current frames it means we have all the frames and can safely
473         // replace our previous frames.
474         prev_sp.reset (curr_ap.release());
475         return;
476     }
477 
478     const uint32_t num_curr_frames = curr_ap->GetNumFrames (false);
479 
480     if (num_curr_frames > 1)
481     {
482 #if defined (DEBUG_STACK_FRAMES)
483         s.PutCString("We have more than one current frame, so use current frames...\n");
484 #endif
485         // We have more than one current frames it means we have all the frames
486         // and can safely replace our previous frames.
487         prev_sp.reset (curr_ap.release());
488 
489 #if defined (DEBUG_STACK_FRAMES)
490         s.PutCString("\nMerged:\n");
491         prev_sp->Dump (&s);
492 #endif
493         return;
494     }
495 
496     StackFrameSP prev_frame_zero_sp(prev_sp->GetFrameAtIndex (0));
497     StackFrameSP curr_frame_zero_sp(curr_ap->GetFrameAtIndex (0));
498     StackID curr_stack_id (curr_frame_zero_sp->GetStackID());
499     StackID prev_stack_id (prev_frame_zero_sp->GetStackID());
500 
501 #if defined (DEBUG_STACK_FRAMES)
502     const uint32_t num_prev_frames = prev_sp->GetNumFrames (false);
503     s.Printf("\n%u previous frames with one current frame\n", num_prev_frames);
504 #endif
505 
506     // We have only a single current frame
507     // Our previous stack frames only had a single frame as well...
508     if (curr_stack_id == prev_stack_id)
509     {
510 #if defined (DEBUG_STACK_FRAMES)
511         s.Printf("\nPrevious frame #0 is same as current frame #0, merge the cached data\n");
512 #endif
513 
514         curr_frame_zero_sp->UpdateCurrentFrameFromPreviousFrame (*prev_frame_zero_sp);
515 //        prev_frame_zero_sp->UpdatePreviousFrameFromCurrentFrame (*curr_frame_zero_sp);
516 //        prev_sp->SetFrameAtIndex (0, prev_frame_zero_sp);
517     }
518     else if (curr_stack_id < prev_stack_id)
519     {
520 #if defined (DEBUG_STACK_FRAMES)
521         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");
522 #endif
523         prev_sp->m_frames.insert (prev_sp->m_frames.begin(), curr_frame_zero_sp);
524     }
525 
526     curr_ap.release();
527 
528 #if defined (DEBUG_STACK_FRAMES)
529     s.PutCString("\nMerged:\n");
530     prev_sp->Dump (&s);
531 #endif
532 
533 
534 }
535 
536 lldb::StackFrameSP
537 StackFrameList::GetStackFrameSPForStackFramePtr (StackFrame *stack_frame_ptr)
538 {
539     const_iterator pos;
540     const_iterator begin = m_frames.begin();
541     const_iterator end = m_frames.end();
542     lldb::StackFrameSP ret_sp;
543 
544     for (pos = begin; pos != end; ++pos)
545     {
546         if (pos->get() == stack_frame_ptr)
547         {
548             ret_sp = (*pos);
549             break;
550         }
551     }
552     return ret_sp;
553 }
554 
555 size_t
556 StackFrameList::GetStatus (Stream& strm,
557                            uint32_t first_frame,
558                            uint32_t num_frames,
559                            bool show_frame_info,
560                            uint32_t num_frames_with_source,
561                            uint32_t source_lines_before,
562                            uint32_t source_lines_after)
563 {
564     size_t num_frames_displayed = 0;
565 
566     if (num_frames == 0)
567         return 0;
568 
569     StackFrameSP frame_sp;
570     uint32_t frame_idx = 0;
571     uint32_t last_frame;
572 
573     // Don't let the last frame wrap around...
574     if (num_frames == UINT32_MAX)
575         last_frame = UINT32_MAX;
576     else
577         last_frame = first_frame + num_frames;
578 
579     for (frame_idx = first_frame; frame_idx < last_frame; ++frame_idx)
580     {
581         frame_sp = GetFrameAtIndex(frame_idx);
582         if (frame_sp.get() == NULL)
583             break;
584 
585         if (!frame_sp->GetStatus (strm,
586                                   show_frame_info,
587                                   num_frames_with_source > first_frame - frame_idx,
588                                   source_lines_before,
589                                   source_lines_after))
590             break;
591         ++num_frames_displayed;
592     }
593 
594     strm.IndentLess();
595     return num_frames_displayed;
596 }
597 
598