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(Thread &thread, StackFrameList *prev_frames, bool show_inline_frames) : 34 m_thread (thread), 35 m_prev_frames_ap (prev_frames), 36 m_show_inlined_frames (show_inline_frames), 37 m_mutex (Mutex::eMutexTypeRecursive), 38 m_frames (), 39 m_selected_frame_idx (0) 40 { 41 } 42 43 //---------------------------------------------------------------------- 44 // Destructor 45 //---------------------------------------------------------------------- 46 StackFrameList::~StackFrameList() 47 { 48 } 49 50 51 uint32_t 52 StackFrameList::GetNumFrames() 53 { 54 Mutex::Locker locker (m_mutex); 55 56 if (m_frames.size() <= 1) 57 { 58 if (m_show_inlined_frames) 59 { 60 #if defined (DEBUG_STACK_FRAMES) 61 StreamFile s(stdout); 62 #endif 63 Unwind *unwinder = m_thread.GetUnwinder (); 64 addr_t pc = LLDB_INVALID_ADDRESS; 65 addr_t cfa = LLDB_INVALID_ADDRESS; 66 67 // 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 70 // in each frame. 71 const uint32_t unwind_frame_count = unwinder->GetFrameCount(); 72 73 StackFrameSP unwind_frame_sp; 74 for (uint32_t idx=0; idx<unwind_frame_count; ++idx) 75 { 76 if (idx == 0) 77 { 78 // We might have already created frame zero, only create it 79 // if we need to 80 if (m_frames.empty()) 81 { 82 cfa = m_thread.m_reg_context_sp->GetSP(); 83 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, 88 cfa, 89 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(); 96 cfa = unwind_frame_sp->m_id.GetCallFrameAddress(); 97 } 98 } 99 else 100 { 101 const bool success = unwinder->GetFrameInfoAtIndex(idx, cfa, pc); 102 assert (success); 103 unwind_frame_sp.reset (new StackFrame (m_frames.size(), idx, m_thread, cfa, pc, NULL)); 104 m_frames.push_back (unwind_frame_sp); 105 } 106 107 Block *unwind_block = unwind_frame_sp->GetSymbolContext (eSymbolContextBlock).block; 108 109 if (unwind_block) 110 { 111 Block *inlined_block = unwind_block->GetContainingInlinedBlock(); 112 if (inlined_block) 113 { 114 for (; inlined_block != NULL; inlined_block = inlined_block->GetInlinedParent ()) 115 { 116 SymbolContext inline_sc; 117 Block *parent_block = inlined_block->GetInlinedParent(); 118 119 const bool is_inlined_frame = parent_block != NULL; 120 121 if (parent_block == NULL) 122 parent_block = inlined_block->GetParent(); 123 124 parent_block->CalculateSymbolContext (&inline_sc); 125 126 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); 129 130 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 } 165 } 166 } 167 } 168 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) 174 s.PutCString("\nprev_frames:\n"); 175 prev_frames->Dump (&s); 176 s.PutCString("\ncurr_frames:\n"); 177 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 211 // Check the stack ID to make sure they are equal 212 if (curr_frame->GetStackID() != prev_frame->GetStackID()) 213 break; 214 215 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); 220 221 #if defined (DEBUG_STACK_FRAMES) 222 s.Printf("\n Copying previous frame to current frame"); 223 #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 } 229 230 #if defined (DEBUG_STACK_FRAMES) 231 s.PutCString("\n\nNew frames:\n"); 232 Dump (&s); 233 s.EOL(); 234 #endif 235 } 236 else 237 { 238 m_frames.resize(m_thread.GetUnwinder()->GetFrameCount()); 239 } 240 } 241 return m_frames.size(); 242 } 243 244 void 245 StackFrameList::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) 253 { 254 StackFrame *frame = (*pos).get(); 255 s->Printf("%p: ", frame); 256 if (frame) 257 { 258 frame->GetStackID().Dump (s); 259 frame->Dump(s, true, false); 260 } 261 else 262 s->Printf("frame #%u", std::distance (begin, pos)); 263 s->EOL(); 264 } 265 s->EOL(); 266 } 267 268 StackFrameSP 269 StackFrameList::GetFrameAtIndex (uint32_t idx) 270 { 271 StackFrameSP frame_sp; 272 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) 283 { 284 // 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)); 295 296 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]; 304 } 305 else 306 { 307 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)); 314 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 } 327 SetFrameAtIndex(idx, frame_sp); 328 } 329 } 330 } 331 } 332 return frame_sp; 333 } 334 335 336 bool 337 StackFrameList::SetFrameAtIndex (uint32_t idx, StackFrameSP &frame_sp) 338 { 339 if (idx >= m_frames.size()) 340 m_frames.resize(idx + 1); 341 // Make sure allocation succeeded by checking bounds again 342 if (idx < m_frames.size()) 343 { 344 m_frames[idx] = frame_sp; 345 return true; 346 } 347 return false; // resize failed, out of memory? 348 } 349 350 uint32_t 351 StackFrameList::GetSelectedFrameIndex () const 352 { 353 Mutex::Locker locker (m_mutex); 354 return m_selected_frame_idx; 355 } 356 357 358 uint32_t 359 StackFrameList::SetSelectedFrame (lldb_private::StackFrame *frame) 360 { 361 Mutex::Locker locker (m_mutex); 362 const_iterator pos; 363 const_iterator begin = m_frames.begin(); 364 const_iterator end = m_frames.end(); 365 for (pos = begin; pos != end; ++pos) 366 { 367 if (pos->get() == frame) 368 { 369 m_selected_frame_idx = std::distance (begin, pos); 370 return m_selected_frame_idx; 371 } 372 } 373 m_selected_frame_idx = 0; 374 return m_selected_frame_idx; 375 } 376 377 // Mark a stack frame as the current frame using the frame index 378 void 379 StackFrameList::SetSelectedFrameByIndex (uint32_t idx) 380 { 381 Mutex::Locker locker (m_mutex); 382 m_selected_frame_idx = idx; 383 } 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. 387 void 388 StackFrameList::Clear () 389 { 390 Mutex::Locker locker (m_mutex); 391 m_frames.clear(); 392 } 393 394 void 395 StackFrameList::InvalidateFrames (uint32_t start_idx) 396 { 397 Mutex::Locker locker (m_mutex); 398 if (m_show_inlined_frames) 399 { 400 Clear(); 401 } 402 else 403 { 404 const size_t num_frames = m_frames.size(); 405 while (start_idx < num_frames) 406 { 407 m_frames[start_idx].reset(); 408 ++start_idx; 409 } 410 } 411 } 412