blob: 0b8b8bf3775fc2b9f42cdb8c0f2044b48838688e [file] [log] [blame]
Chris Lattner24943d22010-06-08 16:52:24 +00001//===-- 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
Greg Clayton782b9cc2010-08-25 00:35:26 +000010#include "lldb/Target/StackFrameList.h"
11
Chris Lattner24943d22010-06-08 16:52:24 +000012// C Includes
13// C++ Includes
14// Other libraries and framework includes
15// Project includes
Greg Clayton1d66ef52010-08-27 18:24:16 +000016#include "lldb/Core/StreamFile.h"
Greg Clayton782b9cc2010-08-25 00:35:26 +000017#include "lldb/Symbol/Block.h"
18#include "lldb/Symbol/Function.h"
Greg Clayton4fb08152010-08-30 18:11:35 +000019#include "lldb/Symbol/Symbol.h"
Greg Clayton782b9cc2010-08-25 00:35:26 +000020#include "lldb/Target/RegisterContext.h"
Chris Lattner24943d22010-06-08 16:52:24 +000021#include "lldb/Target/StackFrame.h"
Greg Clayton782b9cc2010-08-25 00:35:26 +000022#include "lldb/Target/Thread.h"
23#include "lldb/Target/Unwind.h"
Chris Lattner24943d22010-06-08 16:52:24 +000024
Greg Clayton1d66ef52010-08-27 18:24:16 +000025//#define DEBUG_STACK_FRAMES 1
26
Chris Lattner24943d22010-06-08 16:52:24 +000027using namespace lldb;
28using namespace lldb_private;
29
30//----------------------------------------------------------------------
31// StackFrameList constructor
32//----------------------------------------------------------------------
Greg Claytonf40e3082010-08-26 02:28:22 +000033StackFrameList::StackFrameList(Thread &thread, StackFrameList *prev_frames, bool show_inline_frames) :
Greg Clayton782b9cc2010-08-25 00:35:26 +000034 m_thread (thread),
Greg Claytonf40e3082010-08-26 02:28:22 +000035 m_prev_frames_ap (prev_frames),
Greg Clayton782b9cc2010-08-25 00:35:26 +000036 m_show_inlined_frames (show_inline_frames),
Chris Lattner24943d22010-06-08 16:52:24 +000037 m_mutex (Mutex::eMutexTypeRecursive),
Greg Clayton1d66ef52010-08-27 18:24:16 +000038 m_frames (),
Jim Inghamc8332952010-08-26 21:32:51 +000039 m_selected_frame_idx (0)
Chris Lattner24943d22010-06-08 16:52:24 +000040{
41}
42
43//----------------------------------------------------------------------
44// Destructor
45//----------------------------------------------------------------------
46StackFrameList::~StackFrameList()
47{
48}
49
50
51uint32_t
Greg Clayton782b9cc2010-08-25 00:35:26 +000052StackFrameList::GetNumFrames()
Chris Lattner24943d22010-06-08 16:52:24 +000053{
54 Mutex::Locker locker (m_mutex);
Greg Clayton782b9cc2010-08-25 00:35:26 +000055
Greg Clayton1d66ef52010-08-27 18:24:16 +000056 if (m_frames.size() <= 1)
Greg Clayton782b9cc2010-08-25 00:35:26 +000057 {
Greg Clayton1d66ef52010-08-27 18:24:16 +000058 if (m_show_inlined_frames)
Greg Clayton782b9cc2010-08-25 00:35:26 +000059 {
Greg Clayton1d66ef52010-08-27 18:24:16 +000060#if defined (DEBUG_STACK_FRAMES)
61 StreamFile s(stdout);
62#endif
Greg Clayton782b9cc2010-08-25 00:35:26 +000063 Unwind *unwinder = m_thread.GetUnwinder ();
Greg Clayton4fb08152010-08-30 18:11:35 +000064 addr_t pc = LLDB_INVALID_ADDRESS;
65 addr_t cfa = LLDB_INVALID_ADDRESS;
Greg Clayton1d66ef52010-08-27 18:24:16 +000066
Greg Clayton782b9cc2010-08-25 00:35:26 +000067 // If we are going to show inlined stack frames as actual frames,
68 // we need to calculate all concrete frames first, then iterate
69 // through all of them and count up how many inlined functions are
Greg Clayton1d66ef52010-08-27 18:24:16 +000070 // in each frame.
71 const uint32_t unwind_frame_count = unwinder->GetFrameCount();
Greg Clayton782b9cc2010-08-25 00:35:26 +000072
Greg Clayton1d66ef52010-08-27 18:24:16 +000073 StackFrameSP unwind_frame_sp;
74 for (uint32_t idx=0; idx<unwind_frame_count; ++idx)
Greg Clayton782b9cc2010-08-25 00:35:26 +000075 {
76 if (idx == 0)
77 {
Greg Clayton1d66ef52010-08-27 18:24:16 +000078 // We might have already created frame zero, only create it
79 // if we need to
80 if (m_frames.empty())
81 {
Greg Clayton4fb08152010-08-30 18:11:35 +000082 cfa = m_thread.m_reg_context_sp->GetSP();
Greg Clayton1d66ef52010-08-27 18:24:16 +000083 m_thread.GetRegisterContext();
84 unwind_frame_sp.reset (new StackFrame (m_frames.size(),
85 idx,
86 m_thread,
87 m_thread.m_reg_context_sp,
Greg Clayton4fb08152010-08-30 18:11:35 +000088 cfa,
Greg Clayton1d66ef52010-08-27 18:24:16 +000089 m_thread.m_reg_context_sp->GetPC(),
90 NULL));
91 m_frames.push_back (unwind_frame_sp);
92 }
93 else
94 {
95 unwind_frame_sp = m_frames.front();
Greg Clayton4fb08152010-08-30 18:11:35 +000096 cfa = unwind_frame_sp->m_id.GetCallFrameAddress();
Greg Clayton1d66ef52010-08-27 18:24:16 +000097 }
Greg Clayton782b9cc2010-08-25 00:35:26 +000098 }
99 else
100 {
101 const bool success = unwinder->GetFrameInfoAtIndex(idx, cfa, pc);
102 assert (success);
Greg Clayton1d66ef52010-08-27 18:24:16 +0000103 unwind_frame_sp.reset (new StackFrame (m_frames.size(), idx, m_thread, cfa, pc, NULL));
104 m_frames.push_back (unwind_frame_sp);
Greg Clayton782b9cc2010-08-25 00:35:26 +0000105 }
Greg Clayton782b9cc2010-08-25 00:35:26 +0000106
Greg Clayton4fb08152010-08-30 18:11:35 +0000107 Block *unwind_block = unwind_frame_sp->GetSymbolContext (eSymbolContextBlock).block;
Greg Clayton1d66ef52010-08-27 18:24:16 +0000108
Greg Clayton4fb08152010-08-30 18:11:35 +0000109 if (unwind_block)
Greg Clayton782b9cc2010-08-25 00:35:26 +0000110 {
Greg Clayton4fb08152010-08-30 18:11:35 +0000111 Block *inlined_block = unwind_block->GetContainingInlinedBlock();
112 if (inlined_block)
Greg Clayton782b9cc2010-08-25 00:35:26 +0000113 {
Greg Clayton4fb08152010-08-30 18:11:35 +0000114 for (; inlined_block != NULL; inlined_block = inlined_block->GetInlinedParent ())
115 {
116 SymbolContext inline_sc;
117 Block *parent_block = inlined_block->GetInlinedParent();
Greg Claytonf40e3082010-08-26 02:28:22 +0000118
Greg Clayton4fb08152010-08-30 18:11:35 +0000119 const bool is_inlined_frame = parent_block != NULL;
Greg Clayton1d66ef52010-08-27 18:24:16 +0000120
Greg Clayton4fb08152010-08-30 18:11:35 +0000121 if (parent_block == NULL)
122 parent_block = inlined_block->GetParent();
123
124 parent_block->CalculateSymbolContext (&inline_sc);
Greg Clayton1d66ef52010-08-27 18:24:16 +0000125
Greg Clayton4fb08152010-08-30 18:11:35 +0000126 Address previous_frame_lookup_addr (m_frames.back()->GetFrameCodeAddress());
127 if (unwind_frame_sp->GetFrameIndex() > 0 && m_frames.back().get() == unwind_frame_sp.get())
128 previous_frame_lookup_addr.Slide (-1);
Greg Clayton1d66ef52010-08-27 18:24:16 +0000129
Greg Clayton4fb08152010-08-30 18:11:35 +0000130 AddressRange range;
131 inlined_block->GetRangeContainingAddress (previous_frame_lookup_addr, range);
132
133 const InlineFunctionInfo* inline_info = inlined_block->InlinedFunctionInfo();
134 assert (inline_info);
135 inline_sc.line_entry.range.GetBaseAddress() = m_frames.back()->GetFrameCodeAddress();
136 inline_sc.line_entry.file = inline_info->GetCallSite().GetFile();
137 inline_sc.line_entry.line = inline_info->GetCallSite().GetLine();
138 inline_sc.line_entry.column = inline_info->GetCallSite().GetColumn();
139
140 StackFrameSP frame_sp(new StackFrame (m_frames.size(),
141 idx,
142 m_thread,
143 unwind_frame_sp->GetRegisterContextSP (),
144 cfa,
145 range.GetBaseAddress(),
146 &inline_sc)); // The symbol context for this inline frame
147
148 if (is_inlined_frame)
149 {
150 // Use the block with the inlined function info
151 // as the symbol context since we want this frame
152 // to have only the variables for the inlined function
153 frame_sp->SetSymbolContextScope (parent_block);
154 }
155 else
156 {
157 // This block is not inlined with means it has no
158 // inlined parents either, so we want to use the top
159 // most function block.
160 frame_sp->SetSymbolContextScope (&unwind_frame_sp->GetSymbolContext (eSymbolContextFunction).function->GetBlock(false));
161 }
162
163 m_frames.push_back (frame_sp);
164 }
Greg Clayton782b9cc2010-08-25 00:35:26 +0000165 }
166 }
167 }
Greg Clayton1d66ef52010-08-27 18:24:16 +0000168 StackFrameList *prev_frames = m_prev_frames_ap.get();
169 if (prev_frames)
170 {
171 StackFrameList *curr_frames = this;
172
173#if defined (DEBUG_STACK_FRAMES)
Greg Clayton870a1cd2010-08-27 21:47:54 +0000174 s.PutCString("\nprev_frames:\n");
Greg Clayton1d66ef52010-08-27 18:24:16 +0000175 prev_frames->Dump (&s);
Greg Clayton870a1cd2010-08-27 21:47:54 +0000176 s.PutCString("\ncurr_frames:\n");
Greg Clayton1d66ef52010-08-27 18:24:16 +0000177 curr_frames->Dump (&s);
178 s.EOL();
179#endif
180 size_t curr_frame_num, prev_frame_num;
181
182 for (curr_frame_num = curr_frames->m_frames.size(), prev_frame_num = prev_frames->m_frames.size();
183 curr_frame_num > 0 && prev_frame_num > 0;
184 --curr_frame_num, --prev_frame_num)
185 {
186 const size_t curr_frame_idx = curr_frame_num-1;
187 const size_t prev_frame_idx = prev_frame_num-1;
188 StackFrameSP curr_frame_sp (curr_frames->m_frames[curr_frame_idx]);
189 StackFrameSP prev_frame_sp (prev_frames->m_frames[prev_frame_idx]);
190
191#if defined (DEBUG_STACK_FRAMES)
192 s.Printf("\nCurrent frame #%u ", curr_frame_idx);
193 if (curr_frame_sp)
194 curr_frame_sp->Dump (&s, true);
195 else
196 s.PutCString("NULL");
197 s.Printf("\nPrevious frame #%u ", prev_frame_idx);
198 if (prev_frame_sp)
199 prev_frame_sp->Dump (&s, true);
200 else
201 s.PutCString("NULL");
202 s.EOL();
203#endif
204
205 StackFrame *curr_frame = curr_frame_sp.get();
206 StackFrame *prev_frame = prev_frame_sp.get();
207
208 if (curr_frame == NULL || prev_frame == NULL)
209 break;
210
Greg Clayton4fb08152010-08-30 18:11:35 +0000211 // Check the stack ID to make sure they are equal
212 if (curr_frame->GetStackID() != prev_frame->GetStackID())
Greg Clayton1d66ef52010-08-27 18:24:16 +0000213 break;
214
Greg Clayton4fb08152010-08-30 18:11:35 +0000215 prev_frame->UpdatePreviousFrameFromCurrentFrame (*curr_frame);
216 // Now copy the fixed up previous frame into the current frames
217 // so the pointer doesn't change
218 m_frames[curr_frame_idx] = prev_frame_sp;
219 //curr_frame->UpdateCurrentFrameFromPreviousFrame (*prev_frame);
Greg Clayton1d66ef52010-08-27 18:24:16 +0000220
221#if defined (DEBUG_STACK_FRAMES)
Greg Clayton870a1cd2010-08-27 21:47:54 +0000222 s.Printf("\n Copying previous frame to current frame");
Greg Clayton1d66ef52010-08-27 18:24:16 +0000223#endif
224 }
225 // We are done with the old stack frame list, we can release it now
226 m_prev_frames_ap.release();
227 prev_frames = NULL;
228 }
Greg Clayton870a1cd2010-08-27 21:47:54 +0000229
230#if defined (DEBUG_STACK_FRAMES)
231 s.PutCString("\n\nNew frames:\n");
232 Dump (&s);
233 s.EOL();
234#endif
Greg Clayton782b9cc2010-08-25 00:35:26 +0000235 }
Greg Clayton1d66ef52010-08-27 18:24:16 +0000236 else
237 {
238 m_frames.resize(m_thread.GetUnwinder()->GetFrameCount());
239 }
Greg Clayton782b9cc2010-08-25 00:35:26 +0000240 }
Greg Clayton1d66ef52010-08-27 18:24:16 +0000241 return m_frames.size();
242}
243
244void
245StackFrameList::Dump (Stream *s)
246{
247 if (s == NULL)
248 return;
249 Mutex::Locker locker (m_mutex);
250
251 const_iterator pos, begin = m_frames.begin(), end = m_frames.end();
252 for (pos = begin; pos != end; ++pos)
Greg Clayton782b9cc2010-08-25 00:35:26 +0000253 {
Greg Clayton1d66ef52010-08-27 18:24:16 +0000254 StackFrame *frame = (*pos).get();
255 s->Printf("%p: ", frame);
256 if (frame)
Greg Clayton4fb08152010-08-30 18:11:35 +0000257 {
258 frame->GetStackID().Dump (s);
Greg Clayton72b71582010-09-02 21:44:10 +0000259 frame->Dump(s, true, false);
Greg Clayton4fb08152010-08-30 18:11:35 +0000260 }
Greg Clayton1d66ef52010-08-27 18:24:16 +0000261 else
262 s->Printf("frame #%u", std::distance (begin, pos));
263 s->EOL();
Greg Clayton782b9cc2010-08-25 00:35:26 +0000264 }
Greg Clayton1d66ef52010-08-27 18:24:16 +0000265 s->EOL();
Chris Lattner24943d22010-06-08 16:52:24 +0000266}
267
Chris Lattner24943d22010-06-08 16:52:24 +0000268StackFrameSP
Greg Clayton782b9cc2010-08-25 00:35:26 +0000269StackFrameList::GetFrameAtIndex (uint32_t idx)
Chris Lattner24943d22010-06-08 16:52:24 +0000270{
271 StackFrameSP frame_sp;
Greg Clayton1d66ef52010-08-27 18:24:16 +0000272 Mutex::Locker locker (m_mutex);
273 if (idx < m_frames.size())
274 frame_sp = m_frames[idx];
275
276 if (frame_sp)
277 return frame_sp;
278
279 // Special case the first frame (idx == 0) so that we don't need to
280 // know how many stack frames there are to get it. If we need any other
281 // frames, then we do need to know if "idx" is a valid index.
282 if (idx == 0)
Chris Lattner24943d22010-06-08 16:52:24 +0000283 {
Greg Clayton1d66ef52010-08-27 18:24:16 +0000284 // If this is the first frame, we want to share the thread register
285 // context with the stack frame at index zero.
286 m_thread.GetRegisterContext();
287 assert (m_thread.m_reg_context_sp.get());
288 frame_sp.reset (new StackFrame (0,
289 0,
290 m_thread,
291 m_thread.m_reg_context_sp,
292 m_thread.m_reg_context_sp->GetSP(),
293 m_thread.m_reg_context_sp->GetPC(),
294 NULL));
Greg Claytonf40e3082010-08-26 02:28:22 +0000295
Greg Clayton1d66ef52010-08-27 18:24:16 +0000296 SetFrameAtIndex(idx, frame_sp);
297 }
298 else if (idx < GetNumFrames())
299 {
300 if (m_show_inlined_frames)
301 {
302 // When inline frames are enabled we cache up all frames in GetNumFrames()
303 frame_sp = m_frames[idx];
Greg Clayton782b9cc2010-08-25 00:35:26 +0000304 }
305 else
306 {
Greg Clayton1d66ef52010-08-27 18:24:16 +0000307 Unwind *unwinder = m_thread.GetUnwinder ();
308 if (unwinder)
309 {
310 addr_t pc, cfa;
311 if (unwinder->GetFrameInfoAtIndex(idx, cfa, pc))
312 {
313 frame_sp.reset (new StackFrame (idx, idx, m_thread, cfa, pc, NULL));
Greg Clayton4fb08152010-08-30 18:11:35 +0000314
315 Function *function = frame_sp->GetSymbolContext (eSymbolContextFunction).function;
316 if (function)
317 {
318 // When we aren't showing inline functions we always use
319 // the top most function block as the scope.
320 frame_sp->SetSymbolContextScope (&function->GetBlock(false));
321 }
322 else
323 {
324 // Set the symbol scope from the symbol regardless if it is NULL or valid.
325 frame_sp->SetSymbolContextScope (frame_sp->GetSymbolContext (eSymbolContextSymbol).symbol);
326 }
Greg Clayton1d66ef52010-08-27 18:24:16 +0000327 SetFrameAtIndex(idx, frame_sp);
328 }
329 }
Greg Clayton782b9cc2010-08-25 00:35:26 +0000330 }
Chris Lattner24943d22010-06-08 16:52:24 +0000331 }
332 return frame_sp;
333}
334
Greg Clayton782b9cc2010-08-25 00:35:26 +0000335
336bool
Greg Clayton1d66ef52010-08-27 18:24:16 +0000337StackFrameList::SetFrameAtIndex (uint32_t idx, StackFrameSP &frame_sp)
Greg Clayton782b9cc2010-08-25 00:35:26 +0000338{
Greg Clayton1d66ef52010-08-27 18:24:16 +0000339 if (idx >= m_frames.size())
340 m_frames.resize(idx + 1);
Greg Clayton782b9cc2010-08-25 00:35:26 +0000341 // Make sure allocation succeeded by checking bounds again
Greg Clayton1d66ef52010-08-27 18:24:16 +0000342 if (idx < m_frames.size())
Greg Clayton782b9cc2010-08-25 00:35:26 +0000343 {
Greg Clayton1d66ef52010-08-27 18:24:16 +0000344 m_frames[idx] = frame_sp;
Chris Lattner24943d22010-06-08 16:52:24 +0000345 return true;
346 }
347 return false; // resize failed, out of memory?
348}
349
350uint32_t
Jim Inghamc8332952010-08-26 21:32:51 +0000351StackFrameList::GetSelectedFrameIndex () const
Chris Lattner24943d22010-06-08 16:52:24 +0000352{
353 Mutex::Locker locker (m_mutex);
Jim Inghamc8332952010-08-26 21:32:51 +0000354 return m_selected_frame_idx;
Chris Lattner24943d22010-06-08 16:52:24 +0000355}
356
357
358uint32_t
Jim Inghamc8332952010-08-26 21:32:51 +0000359StackFrameList::SetSelectedFrame (lldb_private::StackFrame *frame)
Chris Lattner24943d22010-06-08 16:52:24 +0000360{
361 Mutex::Locker locker (m_mutex);
Greg Clayton782b9cc2010-08-25 00:35:26 +0000362 const_iterator pos;
Greg Clayton1d66ef52010-08-27 18:24:16 +0000363 const_iterator begin = m_frames.begin();
364 const_iterator end = m_frames.end();
Chris Lattner24943d22010-06-08 16:52:24 +0000365 for (pos = begin; pos != end; ++pos)
366 {
367 if (pos->get() == frame)
368 {
Jim Inghamc8332952010-08-26 21:32:51 +0000369 m_selected_frame_idx = std::distance (begin, pos);
370 return m_selected_frame_idx;
Chris Lattner24943d22010-06-08 16:52:24 +0000371 }
372 }
Jim Inghamc8332952010-08-26 21:32:51 +0000373 m_selected_frame_idx = 0;
374 return m_selected_frame_idx;
Chris Lattner24943d22010-06-08 16:52:24 +0000375}
376
377// Mark a stack frame as the current frame using the frame index
378void
Jim Inghamc8332952010-08-26 21:32:51 +0000379StackFrameList::SetSelectedFrameByIndex (uint32_t idx)
Chris Lattner24943d22010-06-08 16:52:24 +0000380{
381 Mutex::Locker locker (m_mutex);
Jim Inghamc8332952010-08-26 21:32:51 +0000382 m_selected_frame_idx = idx;
Chris Lattner24943d22010-06-08 16:52:24 +0000383}
384
385// The thread has been run, reset the number stack frames to zero so we can
386// determine how many frames we have lazily.
387void
388StackFrameList::Clear ()
389{
390 Mutex::Locker locker (m_mutex);
Greg Clayton1d66ef52010-08-27 18:24:16 +0000391 m_frames.clear();
Chris Lattner24943d22010-06-08 16:52:24 +0000392}
393
394void
395StackFrameList::InvalidateFrames (uint32_t start_idx)
396{
397 Mutex::Locker locker (m_mutex);
Greg Clayton782b9cc2010-08-25 00:35:26 +0000398 if (m_show_inlined_frames)
Chris Lattner24943d22010-06-08 16:52:24 +0000399 {
Greg Clayton782b9cc2010-08-25 00:35:26 +0000400 Clear();
401 }
402 else
403 {
Greg Clayton1d66ef52010-08-27 18:24:16 +0000404 const size_t num_frames = m_frames.size();
Greg Clayton782b9cc2010-08-25 00:35:26 +0000405 while (start_idx < num_frames)
406 {
Greg Clayton1d66ef52010-08-27 18:24:16 +0000407 m_frames[start_idx].reset();
Greg Clayton782b9cc2010-08-25 00:35:26 +0000408 ++start_idx;
409 }
Chris Lattner24943d22010-06-08 16:52:24 +0000410 }
411}