blob: e8a436fb3144883e560ba921cfed1aec1e84d88f [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 Claytonf40e3082010-08-26 02:28:22 +000029StackFrameList::StackFrameList(Thread &thread, StackFrameList *prev_frames, bool show_inline_frames) :
Greg Clayton782b9cc2010-08-25 00:35:26 +000030 m_thread (thread),
Greg Claytonf40e3082010-08-26 02:28:22 +000031 m_prev_frames_ap (prev_frames),
Greg Clayton782b9cc2010-08-25 00:35:26 +000032 m_show_inlined_frames (show_inline_frames),
Chris Lattner24943d22010-06-08 16:52:24 +000033 m_mutex (Mutex::eMutexTypeRecursive),
Greg Claytonf40e3082010-08-26 02:28:22 +000034 m_unwind_frames (),
Greg Clayton782b9cc2010-08-25 00:35:26 +000035 m_inline_frames (),
Chris Lattner24943d22010-06-08 16:52:24 +000036 m_current_frame_idx (0)
37{
38}
39
40//----------------------------------------------------------------------
41// Destructor
42//----------------------------------------------------------------------
43StackFrameList::~StackFrameList()
44{
45}
46
47
48uint32_t
Greg Clayton782b9cc2010-08-25 00:35:26 +000049StackFrameList::GetNumFrames()
Chris Lattner24943d22010-06-08 16:52:24 +000050{
51 Mutex::Locker locker (m_mutex);
Greg Clayton782b9cc2010-08-25 00:35:26 +000052
53 if (m_show_inlined_frames)
54 {
Greg Claytonf40e3082010-08-26 02:28:22 +000055 if (m_inlined_info.empty())
Greg Clayton782b9cc2010-08-25 00:35:26 +000056 {
57 Unwind *unwinder = m_thread.GetUnwinder ();
58 // If we are going to show inlined stack frames as actual frames,
59 // we need to calculate all concrete frames first, then iterate
60 // through all of them and count up how many inlined functions are
Greg Claytonf40e3082010-08-26 02:28:22 +000061 // in each frame. We can then fill in m_inlined_info with
Greg Clayton782b9cc2010-08-25 00:35:26 +000062 // the concrete frame index and inlined depth
63 const uint32_t concrete_frame_count = unwinder->GetFrameCount();
64
65 addr_t pc, cfa;
66 InlinedFrameInfo inlined_frame_info;
67
68 StackFrameSP frame_sp;
69 for (uint32_t idx=0; idx<concrete_frame_count; ++idx)
70 {
71 if (idx == 0)
72 {
73 m_thread.GetRegisterContext();
74 frame_sp.reset (new StackFrame (0,
75 0,
76 m_thread,
77 m_thread.m_reg_context_sp,
78 m_thread.m_reg_context_sp->GetSP(),
Greg Clayton782b9cc2010-08-25 00:35:26 +000079 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);
Greg Claytonf40e3082010-08-26 02:28:22 +000086 frame_sp.reset (new StackFrame (m_inlined_info.size(), idx, m_thread, cfa, pc, NULL));
Greg Clayton782b9cc2010-08-25 00:35:26 +000087 }
Greg Claytonf40e3082010-08-26 02:28:22 +000088 SetUnwindFrameAtIndex (idx, frame_sp);
Greg Clayton782b9cc2010-08-25 00:35:26 +000089 Block *block = frame_sp->GetSymbolContext (eSymbolContextBlock).block;
90
Greg Claytonf40e3082010-08-26 02:28:22 +000091 inlined_frame_info.unwind_frame_index = idx;
92 inlined_frame_info.block = NULL;
93 m_inlined_info.push_back (inlined_frame_info);
Greg Clayton782b9cc2010-08-25 00:35:26 +000094
95 if (block)
96 {
Greg Claytonf40e3082010-08-26 02:28:22 +000097 Block *inlined_block = block->GetContainingInlinedBlock();
98
99 if (inlined_block)
Greg Clayton782b9cc2010-08-25 00:35:26 +0000100 {
Greg Claytonf40e3082010-08-26 02:28:22 +0000101 frame_sp->SetInlineBlockID (inlined_block->GetID());
102
103 while (inlined_block)
104 {
105 inlined_frame_info.block = inlined_block;
106 m_inlined_info.push_back (inlined_frame_info);
107 inlined_block = inlined_block->GetInlinedParent ();
108 }
Greg Clayton782b9cc2010-08-25 00:35:26 +0000109 }
110 }
111 }
112 }
Greg Claytonf40e3082010-08-26 02:28:22 +0000113 return m_inlined_info.size();
Greg Clayton782b9cc2010-08-25 00:35:26 +0000114 }
115 else
116 {
Greg Claytonf40e3082010-08-26 02:28:22 +0000117 if (m_unwind_frames.empty())
118 m_unwind_frames.resize(m_thread.GetUnwinder()->GetFrameCount());
Greg Clayton782b9cc2010-08-25 00:35:26 +0000119
Greg Claytonf40e3082010-08-26 02:28:22 +0000120 return m_unwind_frames.size();
Greg Clayton782b9cc2010-08-25 00:35:26 +0000121 }
122 return 0;
Chris Lattner24943d22010-06-08 16:52:24 +0000123}
124
Greg Clayton782b9cc2010-08-25 00:35:26 +0000125lldb::StackFrameSP
Greg Claytonf40e3082010-08-26 02:28:22 +0000126StackFrameList::GetUnwindFrameAtIndex (uint32_t idx) const
Chris Lattner24943d22010-06-08 16:52:24 +0000127{
Greg Clayton782b9cc2010-08-25 00:35:26 +0000128 StackFrameSP frame_sp;
Greg Claytonf40e3082010-08-26 02:28:22 +0000129 if (idx < m_unwind_frames.size())
130 frame_sp = m_unwind_frames[idx];
Greg Clayton782b9cc2010-08-25 00:35:26 +0000131 return frame_sp;
Chris Lattner24943d22010-06-08 16:52:24 +0000132}
133
Greg Clayton782b9cc2010-08-25 00:35:26 +0000134lldb::StackFrameSP
135StackFrameList::GetInlineFrameAtIndex (uint32_t idx) const
136{
137 StackFrameSP frame_sp;
138 if (idx < m_inline_frames.size())
139 frame_sp = m_inline_frames[idx];
140 return frame_sp;
141}
142
143
Chris Lattner24943d22010-06-08 16:52:24 +0000144StackFrameSP
Greg Clayton782b9cc2010-08-25 00:35:26 +0000145StackFrameList::GetFrameAtIndex (uint32_t idx)
Chris Lattner24943d22010-06-08 16:52:24 +0000146{
147 StackFrameSP frame_sp;
148 {
149 Mutex::Locker locker (m_mutex);
Greg Clayton782b9cc2010-08-25 00:35:26 +0000150
151 if (m_show_inlined_frames)
152 {
153 frame_sp = GetInlineFrameAtIndex (idx);
154 }
155 else
156 {
Greg Claytonf40e3082010-08-26 02:28:22 +0000157 frame_sp = GetUnwindFrameAtIndex (idx);
Greg Clayton782b9cc2010-08-25 00:35:26 +0000158 }
159
160 if (frame_sp.get())
Greg Claytonf40e3082010-08-26 02:28:22 +0000161 return frame_sp;
Greg Clayton782b9cc2010-08-25 00:35:26 +0000162
Greg Claytonf40e3082010-08-26 02:28:22 +0000163 // Special case the first frame (idx == 0) so that we don't need to
164 // know how many stack frames there are to get it. If we need any other
165 // frames, then we do need to know if "idx" is a valid index.
166 if (idx == 0)
167 {
168 // If this is the first frame, we want to share the thread register
169 // context with the stack frame at index zero.
170 m_thread.GetRegisterContext();
171 assert (m_thread.m_reg_context_sp.get());
172 frame_sp.reset (new StackFrame (0,
173 0,
174 m_thread,
175 m_thread.m_reg_context_sp,
176 m_thread.m_reg_context_sp->GetSP(),
177 m_thread.m_reg_context_sp->GetPC(),
178 NULL));
179
180 if (m_show_inlined_frames && idx + 1 < m_inlined_info.size())
181 {
182 if (m_inlined_info[idx].unwind_frame_index == m_inlined_info[idx+1].unwind_frame_index)
183 frame_sp->SetInlineBlockID (frame_sp->GetSymbolContext (eSymbolContextBlock).block->GetID());
184 }
185
186 }
187 else if (idx < GetNumFrames())
188 {
189 if (m_show_inlined_frames)
190 {
191 if (m_inlined_info[idx].block == NULL)
192 {
193 // Same as the concrete stack frame if block is NULL
194 assert (m_inlined_info[idx].unwind_frame_index < m_unwind_frames.size());
195 frame_sp = GetUnwindFrameAtIndex (m_inlined_info[idx].unwind_frame_index);
196 if (idx + 1 < m_inlined_info.size())
197 {
198 if (m_inlined_info[idx].unwind_frame_index == m_inlined_info[idx+1].unwind_frame_index)
199 frame_sp->SetInlineBlockID (frame_sp->GetSymbolContext (eSymbolContextBlock).block->GetID());
200 }
201 }
202 else
203 {
204 // We have blocks that were above an inlined function. Inlined
205 // functions are represented as blocks with non-NULL inline
206 // function info. Here we must reconstruct a frame by looking
207 // at the block
208 StackFrameSP previous_frame_sp (m_thread.GetStackFrameAtIndex (idx-1));
209
210 SymbolContext inline_sc;
211
212 Block *inlined_parent_block = m_inlined_info[idx].block->GetInlinedParent();
213
214 if (inlined_parent_block)
215 inlined_parent_block->CalculateSymbolContext (&inline_sc);
216 else
217 {
218 Block *parent_block = m_inlined_info[idx].block->GetParent();
219 parent_block->CalculateSymbolContext(&inline_sc);
220 }
221
222 Address previous_frame_lookup_addr (previous_frame_sp->GetFrameCodeAddress());
223 if (previous_frame_sp->GetFrameIndex() > 0 && m_inlined_info[idx-1].block == NULL)
224 previous_frame_lookup_addr.Slide (-1);
225
226 AddressRange range;
227 m_inlined_info[idx].block->GetRangeContainingAddress (previous_frame_lookup_addr, range);
228
229 const InlineFunctionInfo* inline_info = m_inlined_info[idx].block->InlinedFunctionInfo();
230 assert (inline_info);
231 inline_sc.line_entry.range.GetBaseAddress() = previous_frame_sp->GetFrameCodeAddress();
232 inline_sc.line_entry.file = inline_info->GetCallSite().GetFile();
233 inline_sc.line_entry.line = inline_info->GetCallSite().GetLine();
234 inline_sc.line_entry.column = inline_info->GetCallSite().GetColumn();
235
236 StackFrameSP concrete_frame_sp (GetUnwindFrameAtIndex (m_inlined_info[idx].unwind_frame_index));
237 assert (previous_frame_sp.get());
238
239 frame_sp.reset (new StackFrame (idx,
240 m_inlined_info[idx].unwind_frame_index,
241 m_thread,
242 concrete_frame_sp->GetRegisterContextSP (),
243 concrete_frame_sp->GetStackID().GetCallFrameAddress(), // CFA
244 range.GetBaseAddress(),
245 &inline_sc)); // The symbol context for this inline frame
246
247 if (idx + 1 < m_inlined_info.size())
248 {
249 if (m_inlined_info[idx].unwind_frame_index == m_inlined_info[idx+1].unwind_frame_index)
250 frame_sp->SetInlineBlockID (m_inlined_info[idx].block->GetID());
251 }
252 }
253 }
254 else
255 {
256 Unwind *unwinder = m_thread.GetUnwinder ();
257 if (unwinder)
258 {
259 addr_t pc, cfa;
260 if (unwinder->GetFrameInfoAtIndex(idx, cfa, pc))
261 frame_sp.reset (new StackFrame (idx, idx, m_thread, cfa, pc, NULL));
262 }
263 }
264 }
265
Greg Clayton782b9cc2010-08-25 00:35:26 +0000266 if (m_show_inlined_frames)
267 {
Greg Claytonf40e3082010-08-26 02:28:22 +0000268 SetInlineFrameAtIndex(idx, frame_sp);
Greg Clayton782b9cc2010-08-25 00:35:26 +0000269 }
270 else
271 {
Greg Claytonf40e3082010-08-26 02:28:22 +0000272 SetUnwindFrameAtIndex(idx, frame_sp);
Greg Clayton782b9cc2010-08-25 00:35:26 +0000273 }
Greg Claytonf40e3082010-08-26 02:28:22 +0000274 return frame_sp;
275
Chris Lattner24943d22010-06-08 16:52:24 +0000276 }
277 return frame_sp;
278}
279
280bool
Greg Claytonf40e3082010-08-26 02:28:22 +0000281StackFrameList::SetUnwindFrameAtIndex (uint32_t idx, StackFrameSP &frame_sp)
Chris Lattner24943d22010-06-08 16:52:24 +0000282{
Greg Claytonf40e3082010-08-26 02:28:22 +0000283 if (idx >= m_unwind_frames.size())
284 m_unwind_frames.resize(idx + 1);
Chris Lattner24943d22010-06-08 16:52:24 +0000285 // Make sure allocation succeeded by checking bounds again
Greg Claytonf40e3082010-08-26 02:28:22 +0000286 if (idx < m_unwind_frames.size())
Chris Lattner24943d22010-06-08 16:52:24 +0000287 {
Greg Claytonf40e3082010-08-26 02:28:22 +0000288 m_unwind_frames[idx] = frame_sp;
Greg Clayton782b9cc2010-08-25 00:35:26 +0000289 return true;
290 }
291 return false; // resize failed, out of memory?
292}
293
294bool
295StackFrameList::SetInlineFrameAtIndex (uint32_t idx, StackFrameSP &frame_sp)
296{
297 if (idx >= m_inline_frames.size())
298 m_inline_frames.resize(idx + 1);
299 // Make sure allocation succeeded by checking bounds again
300 if (idx < m_inline_frames.size())
301 {
302 m_inline_frames[idx] = frame_sp;
Chris Lattner24943d22010-06-08 16:52:24 +0000303 return true;
304 }
305 return false; // resize failed, out of memory?
306}
307
308uint32_t
309StackFrameList::GetCurrentFrameIndex () const
310{
311 Mutex::Locker locker (m_mutex);
312 return m_current_frame_idx;
313}
314
315
316uint32_t
317StackFrameList::SetCurrentFrame (lldb_private::StackFrame *frame)
318{
319 Mutex::Locker locker (m_mutex);
Greg Clayton782b9cc2010-08-25 00:35:26 +0000320 const_iterator pos;
Greg Claytonf40e3082010-08-26 02:28:22 +0000321 const_iterator begin = m_show_inlined_frames ? m_inline_frames.begin() : m_unwind_frames.begin();
322 const_iterator end = m_show_inlined_frames ? m_inline_frames.end() : m_unwind_frames.end();
Chris Lattner24943d22010-06-08 16:52:24 +0000323 for (pos = begin; pos != end; ++pos)
324 {
325 if (pos->get() == frame)
326 {
327 m_current_frame_idx = std::distance (begin, pos);
328 return m_current_frame_idx;
329 }
330 }
331 m_current_frame_idx = 0;
332 return m_current_frame_idx;
333}
334
335// Mark a stack frame as the current frame using the frame index
336void
337StackFrameList::SetCurrentFrameByIndex (uint32_t idx)
338{
339 Mutex::Locker locker (m_mutex);
340 m_current_frame_idx = idx;
341}
342
343// The thread has been run, reset the number stack frames to zero so we can
344// determine how many frames we have lazily.
345void
346StackFrameList::Clear ()
347{
348 Mutex::Locker locker (m_mutex);
Greg Claytonf40e3082010-08-26 02:28:22 +0000349 m_unwind_frames.clear();
Greg Clayton782b9cc2010-08-25 00:35:26 +0000350 m_inline_frames.clear();
Greg Claytonf40e3082010-08-26 02:28:22 +0000351 m_inlined_info.clear();
Chris Lattner24943d22010-06-08 16:52:24 +0000352}
353
354void
355StackFrameList::InvalidateFrames (uint32_t start_idx)
356{
357 Mutex::Locker locker (m_mutex);
Greg Clayton782b9cc2010-08-25 00:35:26 +0000358 if (m_show_inlined_frames)
Chris Lattner24943d22010-06-08 16:52:24 +0000359 {
Greg Clayton782b9cc2010-08-25 00:35:26 +0000360 Clear();
361 }
362 else
363 {
Greg Claytonf40e3082010-08-26 02:28:22 +0000364 const size_t num_frames = m_unwind_frames.size();
Greg Clayton782b9cc2010-08-25 00:35:26 +0000365 while (start_idx < num_frames)
366 {
Greg Claytonf40e3082010-08-26 02:28:22 +0000367 m_unwind_frames[start_idx].reset();
Greg Clayton782b9cc2010-08-25 00:35:26 +0000368 ++start_idx;
369 }
Chris Lattner24943d22010-06-08 16:52:24 +0000370 }
371}