blob: 1ebe8a4ae78a69d5244c30c2edc83205ba72fb63 [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 Clayton782b9cc2010-08-25 00:35:26 +000016#include "lldb/Symbol/Block.h"
17#include "lldb/Symbol/Function.h"
18#include "lldb/Target/RegisterContext.h"
Chris Lattner24943d22010-06-08 16:52:24 +000019#include "lldb/Target/StackFrame.h"
Greg Clayton782b9cc2010-08-25 00:35:26 +000020#include "lldb/Target/Thread.h"
21#include "lldb/Target/Unwind.h"
Chris Lattner24943d22010-06-08 16:52:24 +000022
23using namespace lldb;
24using namespace lldb_private;
25
26//----------------------------------------------------------------------
27// StackFrameList constructor
28//----------------------------------------------------------------------
Greg Clayton782b9cc2010-08-25 00:35:26 +000029StackFrameList::StackFrameList(Thread &thread, bool show_inline_frames) :
30 m_thread (thread),
31 m_show_inlined_frames (show_inline_frames),
Chris Lattner24943d22010-06-08 16:52:24 +000032 m_mutex (Mutex::eMutexTypeRecursive),
Greg Clayton782b9cc2010-08-25 00:35:26 +000033 m_actual_frames (),
34 m_inline_frames (),
Chris Lattner24943d22010-06-08 16:52:24 +000035 m_current_frame_idx (0)
36{
37}
38
39//----------------------------------------------------------------------
40// Destructor
41//----------------------------------------------------------------------
42StackFrameList::~StackFrameList()
43{
44}
45
46
47uint32_t
Greg Clayton782b9cc2010-08-25 00:35:26 +000048StackFrameList::GetNumFrames()
Chris Lattner24943d22010-06-08 16:52:24 +000049{
50 Mutex::Locker locker (m_mutex);
Greg Clayton782b9cc2010-08-25 00:35:26 +000051
52 if (m_show_inlined_frames)
53 {
54 if (m_inlined_frame_info.empty())
55 {
56 Unwind *unwinder = m_thread.GetUnwinder ();
57 // If we are going to show inlined stack frames as actual frames,
58 // we need to calculate all concrete frames first, then iterate
59 // through all of them and count up how many inlined functions are
60 // in each frame. We can then fill in m_inlined_frame_info with
61 // the concrete frame index and inlined depth
62 const uint32_t concrete_frame_count = unwinder->GetFrameCount();
63
64 addr_t pc, cfa;
65 InlinedFrameInfo inlined_frame_info;
66
67 StackFrameSP frame_sp;
68 for (uint32_t idx=0; idx<concrete_frame_count; ++idx)
69 {
70 if (idx == 0)
71 {
72 m_thread.GetRegisterContext();
73 frame_sp.reset (new StackFrame (0,
74 0,
75 m_thread,
76 m_thread.m_reg_context_sp,
77 m_thread.m_reg_context_sp->GetSP(),
78 0,
79 m_thread.m_reg_context_sp->GetPC(),
80 NULL));
81 }
82 else
83 {
84 const bool success = unwinder->GetFrameInfoAtIndex(idx, cfa, pc);
85 assert (success);
86 frame_sp.reset (new StackFrame (m_inlined_frame_info.size(), idx, m_thread, cfa, 0, pc, NULL));
87 }
88 SetActualFrameAtIndex (idx, frame_sp);
89 Block *block = frame_sp->GetSymbolContext (eSymbolContextBlock).block;
90
91 inlined_frame_info.concrete_frame_index = idx;
92 inlined_frame_info.inline_height = 0;
93 inlined_frame_info.block = block;
94 m_inlined_frame_info.push_back (inlined_frame_info);
95
96 if (block)
97 {
98 Block *inlined_block;
99 if (block->InlinedFunctionInfo())
100 inlined_block = block;
101 else
102 inlined_block = block->GetInlinedParent ();
103
104 while (inlined_block)
105 {
106 inlined_frame_info.block = inlined_block;
107 inlined_frame_info.inline_height++;
108 m_inlined_frame_info.push_back (inlined_frame_info);
109 inlined_block = inlined_block->GetInlinedParent ();
110 }
111 }
112 }
113 }
114 return m_inlined_frame_info.size();
115 }
116 else
117 {
118 if (m_actual_frames.empty())
119 m_actual_frames.resize(m_thread.GetUnwinder()->GetFrameCount());
120
121 return m_actual_frames.size();
122 }
123 return 0;
Chris Lattner24943d22010-06-08 16:52:24 +0000124}
125
Greg Clayton782b9cc2010-08-25 00:35:26 +0000126lldb::StackFrameSP
127StackFrameList::GetActualFrameAtIndex (uint32_t idx) const
Chris Lattner24943d22010-06-08 16:52:24 +0000128{
Greg Clayton782b9cc2010-08-25 00:35:26 +0000129 StackFrameSP frame_sp;
130 if (idx < m_actual_frames.size())
131 frame_sp = m_actual_frames[idx];
132 return frame_sp;
Chris Lattner24943d22010-06-08 16:52:24 +0000133}
134
Greg Clayton782b9cc2010-08-25 00:35:26 +0000135lldb::StackFrameSP
136StackFrameList::GetInlineFrameAtIndex (uint32_t idx) const
137{
138 StackFrameSP frame_sp;
139 if (idx < m_inline_frames.size())
140 frame_sp = m_inline_frames[idx];
141 return frame_sp;
142}
143
144
Chris Lattner24943d22010-06-08 16:52:24 +0000145StackFrameSP
Greg Clayton782b9cc2010-08-25 00:35:26 +0000146StackFrameList::GetFrameAtIndex (uint32_t idx)
Chris Lattner24943d22010-06-08 16:52:24 +0000147{
148 StackFrameSP frame_sp;
149 {
150 Mutex::Locker locker (m_mutex);
Greg Clayton782b9cc2010-08-25 00:35:26 +0000151
152 if (m_show_inlined_frames)
153 {
154 frame_sp = GetInlineFrameAtIndex (idx);
155 }
156 else
157 {
158 frame_sp = GetActualFrameAtIndex (idx);
159 }
160
161 if (frame_sp.get())
162 return frame_sp;
163
164 // Special case the first frame (idx == 0) so that we don't need to
165 // know how many stack frames there are to get it. If we need any other
166 // frames, then we do need to know if "idx" is a valid index.
167 if (idx == 0)
168 {
169 // If this is the first frame, we want to share the thread register
170 // context with the stack frame at index zero.
171 m_thread.GetRegisterContext();
172 assert (m_thread.m_reg_context_sp.get());
173 frame_sp.reset (new StackFrame (0,
174 0,
175 m_thread,
176 m_thread.m_reg_context_sp,
177 m_thread.m_reg_context_sp->GetSP(),
178 0,
179 m_thread.m_reg_context_sp->GetPC(),
180 NULL));
181 }
182 else if (idx < GetNumFrames())
183 {
184 if (m_show_inlined_frames)
185 {
186 if (m_inlined_frame_info[idx].inline_height == 0)
187 {
188 // Same as the concrete stack frame if block is NULL
189 assert (m_inlined_frame_info[idx].concrete_frame_index < m_actual_frames.size());
190 frame_sp = GetActualFrameAtIndex (m_inlined_frame_info[idx].concrete_frame_index);
191 }
192 else
193 {
194 // We have blocks that were above an inlined function. Inlined
195 // functions are represented as blocks with non-NULL inline
196 // function info. Here we must reconstruct a frame by looking
197 // at the block
198 StackFrameSP previous_frame_sp (m_thread.GetStackFrameAtIndex (idx-1));
199
200 SymbolContext inline_sc;
201
202 Block *inlined_parent_block = m_inlined_frame_info[idx].block->GetInlinedParent();
203
204 if (inlined_parent_block)
205 inlined_parent_block->CalculateSymbolContext (&inline_sc);
206 else
207 {
208 Block *parent_block = m_inlined_frame_info[idx].block->GetParent();
209 parent_block->CalculateSymbolContext(&inline_sc);
210 }
211
212 Address previous_frame_lookup_addr (previous_frame_sp->GetFrameCodeAddress());
213 if (previous_frame_sp->IsConcrete () && previous_frame_sp->GetFrameIndex() > 0)
214 previous_frame_lookup_addr.Slide (-1);
215
216 AddressRange range;
217 m_inlined_frame_info[idx].block->GetRangeContainingAddress (previous_frame_lookup_addr, range);
218
219 const InlineFunctionInfo* inline_info = m_inlined_frame_info[idx].block->InlinedFunctionInfo();
220 assert (inline_info);
221 inline_sc.line_entry.range.GetBaseAddress() = previous_frame_sp->GetFrameCodeAddress();
222 inline_sc.line_entry.file = inline_info->GetCallSite().GetFile();
223 inline_sc.line_entry.line = inline_info->GetCallSite().GetLine();
224 inline_sc.line_entry.column = inline_info->GetCallSite().GetColumn();
225
226 StackFrameSP concrete_frame_sp (GetActualFrameAtIndex (m_inlined_frame_info[idx].concrete_frame_index));
227 assert (previous_frame_sp.get());
228
229 frame_sp.reset (new StackFrame (idx,
230 m_inlined_frame_info[idx].concrete_frame_index,
231 m_thread,
232 concrete_frame_sp->GetRegisterContextSP (),
233 concrete_frame_sp->GetStackID().GetCallFrameAddress(), // CFA
234 m_inlined_frame_info[idx].inline_height, // Inline height
235 range.GetBaseAddress(),
236 &inline_sc)); // The symbol context for this inline frame
237
238 }
239 }
240 else
241 {
242 Unwind *unwinder = m_thread.GetUnwinder ();
243 if (unwinder)
244 {
245 addr_t pc, cfa;
246 if (unwinder->GetFrameInfoAtIndex(idx, cfa, pc))
247 frame_sp.reset (new StackFrame (idx, idx, m_thread, cfa, 0, pc, NULL));
248 }
249 }
250 }
251 if (m_show_inlined_frames)
252 SetInlineFrameAtIndex(idx, frame_sp);
253 else
254 SetActualFrameAtIndex(idx, frame_sp);
255 return frame_sp;
256
Chris Lattner24943d22010-06-08 16:52:24 +0000257 }
258 return frame_sp;
259}
260
261bool
Greg Clayton782b9cc2010-08-25 00:35:26 +0000262StackFrameList::SetActualFrameAtIndex (uint32_t idx, StackFrameSP &frame_sp)
Chris Lattner24943d22010-06-08 16:52:24 +0000263{
Greg Clayton782b9cc2010-08-25 00:35:26 +0000264 if (idx >= m_actual_frames.size())
265 m_actual_frames.resize(idx + 1);
Chris Lattner24943d22010-06-08 16:52:24 +0000266 // Make sure allocation succeeded by checking bounds again
Greg Clayton782b9cc2010-08-25 00:35:26 +0000267 if (idx < m_actual_frames.size())
Chris Lattner24943d22010-06-08 16:52:24 +0000268 {
Greg Clayton782b9cc2010-08-25 00:35:26 +0000269 m_actual_frames[idx] = frame_sp;
270 return true;
271 }
272 return false; // resize failed, out of memory?
273}
274
275bool
276StackFrameList::SetInlineFrameAtIndex (uint32_t idx, StackFrameSP &frame_sp)
277{
278 if (idx >= m_inline_frames.size())
279 m_inline_frames.resize(idx + 1);
280 // Make sure allocation succeeded by checking bounds again
281 if (idx < m_inline_frames.size())
282 {
283 m_inline_frames[idx] = frame_sp;
Chris Lattner24943d22010-06-08 16:52:24 +0000284 return true;
285 }
286 return false; // resize failed, out of memory?
287}
288
289uint32_t
290StackFrameList::GetCurrentFrameIndex () const
291{
292 Mutex::Locker locker (m_mutex);
293 return m_current_frame_idx;
294}
295
296
297uint32_t
298StackFrameList::SetCurrentFrame (lldb_private::StackFrame *frame)
299{
300 Mutex::Locker locker (m_mutex);
Greg Clayton782b9cc2010-08-25 00:35:26 +0000301 const_iterator pos;
302 const_iterator begin = m_show_inlined_frames ? m_inline_frames.begin() : m_actual_frames.begin();
303 const_iterator end = m_show_inlined_frames ? m_inline_frames.end() : m_actual_frames.end();
Chris Lattner24943d22010-06-08 16:52:24 +0000304 for (pos = begin; pos != end; ++pos)
305 {
306 if (pos->get() == frame)
307 {
308 m_current_frame_idx = std::distance (begin, pos);
309 return m_current_frame_idx;
310 }
311 }
312 m_current_frame_idx = 0;
313 return m_current_frame_idx;
314}
315
316// Mark a stack frame as the current frame using the frame index
317void
318StackFrameList::SetCurrentFrameByIndex (uint32_t idx)
319{
320 Mutex::Locker locker (m_mutex);
321 m_current_frame_idx = idx;
322}
323
324// The thread has been run, reset the number stack frames to zero so we can
325// determine how many frames we have lazily.
326void
327StackFrameList::Clear ()
328{
329 Mutex::Locker locker (m_mutex);
Greg Clayton782b9cc2010-08-25 00:35:26 +0000330 m_actual_frames.clear();
331 m_inline_frames.clear();
332 m_inlined_frame_info.clear();
Chris Lattner24943d22010-06-08 16:52:24 +0000333}
334
335void
336StackFrameList::InvalidateFrames (uint32_t start_idx)
337{
338 Mutex::Locker locker (m_mutex);
Greg Clayton782b9cc2010-08-25 00:35:26 +0000339 if (m_show_inlined_frames)
Chris Lattner24943d22010-06-08 16:52:24 +0000340 {
Greg Clayton782b9cc2010-08-25 00:35:26 +0000341 Clear();
342 }
343 else
344 {
345 const size_t num_frames = m_actual_frames.size();
346 while (start_idx < num_frames)
347 {
348 m_actual_frames[start_idx].reset();
349 ++start_idx;
350 }
Chris Lattner24943d22010-06-08 16:52:24 +0000351 }
352}