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