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