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/Core/SourceManager.h" 18 #include "lldb/Symbol/Block.h" 19 #include "lldb/Symbol/Function.h" 20 #include "lldb/Symbol/Symbol.h" 21 #include "lldb/Target/Process.h" 22 #include "lldb/Target/RegisterContext.h" 23 #include "lldb/Target/StackFrame.h" 24 #include "lldb/Target/Target.h" 25 #include "lldb/Target/Thread.h" 26 #include "lldb/Target/Unwind.h" 27 28 //#define DEBUG_STACK_FRAMES 1 29 30 using namespace lldb; 31 using namespace lldb_private; 32 33 //---------------------------------------------------------------------- 34 // StackFrameList constructor 35 //---------------------------------------------------------------------- 36 StackFrameList::StackFrameList 37 ( 38 Thread &thread, 39 const lldb::StackFrameListSP &prev_frames_sp, 40 bool show_inline_frames 41 ) : 42 m_thread (thread), 43 m_prev_frames_sp (prev_frames_sp), 44 m_mutex (Mutex::eMutexTypeRecursive), 45 m_frames (), 46 m_selected_frame_idx (0), 47 m_show_inlined_frames (show_inline_frames) 48 { 49 } 50 51 //---------------------------------------------------------------------- 52 // Destructor 53 //---------------------------------------------------------------------- 54 StackFrameList::~StackFrameList() 55 { 56 } 57 58 59 uint32_t 60 StackFrameList::GetNumFrames (bool can_create) 61 { 62 Mutex::Locker locker (m_mutex); 63 64 if (can_create && m_frames.size() <= 1) 65 { 66 if (m_show_inlined_frames) 67 { 68 #if defined (DEBUG_STACK_FRAMES) 69 StreamFile s(stdout, false); 70 #endif 71 Unwind *unwinder = m_thread.GetUnwinder (); 72 addr_t pc = LLDB_INVALID_ADDRESS; 73 addr_t cfa = LLDB_INVALID_ADDRESS; 74 75 // If we are going to show inlined stack frames as actual frames, 76 // we need to calculate all concrete frames first, then iterate 77 // through all of them and count up how many inlined functions are 78 // in each frame. 79 const uint32_t unwind_frame_count = unwinder->GetFrameCount(); 80 81 StackFrameSP unwind_frame_sp; 82 for (uint32_t idx=0; idx<unwind_frame_count; ++idx) 83 { 84 if (idx == 0) 85 { 86 // We might have already created frame zero, only create it 87 // if we need to 88 if (m_frames.empty()) 89 { 90 cfa = m_thread.m_reg_context_sp->GetSP(); 91 m_thread.GetRegisterContext(); 92 unwind_frame_sp.reset (new StackFrame (m_frames.size(), 93 idx, 94 m_thread, 95 m_thread.m_reg_context_sp, 96 cfa, 97 m_thread.m_reg_context_sp->GetPC(), 98 NULL)); 99 m_frames.push_back (unwind_frame_sp); 100 } 101 else 102 { 103 unwind_frame_sp = m_frames.front(); 104 cfa = unwind_frame_sp->m_id.GetCallFrameAddress(); 105 } 106 } 107 else 108 { 109 const bool success = unwinder->GetFrameInfoAtIndex(idx, cfa, pc); 110 assert (success); 111 unwind_frame_sp.reset (new StackFrame (m_frames.size(), idx, m_thread, cfa, pc, NULL)); 112 m_frames.push_back (unwind_frame_sp); 113 } 114 115 Block *unwind_block = unwind_frame_sp->GetSymbolContext (eSymbolContextBlock).block; 116 117 if (unwind_block) 118 { 119 Block *inlined_block = unwind_block->GetContainingInlinedBlock(); 120 if (inlined_block) 121 { 122 for (; inlined_block != NULL; inlined_block = inlined_block->GetInlinedParent ()) 123 { 124 SymbolContext inline_sc; 125 Block *parent_block = inlined_block->GetInlinedParent(); 126 127 const bool is_inlined_frame = parent_block != NULL; 128 129 if (parent_block == NULL) 130 parent_block = inlined_block->GetParent(); 131 132 parent_block->CalculateSymbolContext (&inline_sc); 133 134 Address previous_frame_lookup_addr (m_frames.back()->GetFrameCodeAddress()); 135 if (unwind_frame_sp->GetFrameIndex() > 0 && m_frames.back().get() == unwind_frame_sp.get()) 136 previous_frame_lookup_addr.Slide (-1); 137 138 AddressRange range; 139 inlined_block->GetRangeContainingAddress (previous_frame_lookup_addr, range); 140 141 const InlineFunctionInfo* inline_info = inlined_block->GetInlinedFunctionInfo(); 142 assert (inline_info); 143 inline_sc.line_entry.range.GetBaseAddress() = m_frames.back()->GetFrameCodeAddress(); 144 inline_sc.line_entry.file = inline_info->GetCallSite().GetFile(); 145 inline_sc.line_entry.line = inline_info->GetCallSite().GetLine(); 146 inline_sc.line_entry.column = inline_info->GetCallSite().GetColumn(); 147 148 StackFrameSP frame_sp(new StackFrame (m_frames.size(), 149 idx, 150 m_thread, 151 unwind_frame_sp->GetRegisterContextSP (), 152 cfa, 153 range.GetBaseAddress(), 154 &inline_sc)); // The symbol context for this inline frame 155 156 if (is_inlined_frame) 157 { 158 // Use the block with the inlined function info 159 // as the symbol context since we want this frame 160 // to have only the variables for the inlined function 161 frame_sp->SetSymbolContextScope (parent_block); 162 } 163 else 164 { 165 // This block is not inlined with means it has no 166 // inlined parents either, so we want to use the top 167 // most function block. 168 frame_sp->SetSymbolContextScope (&unwind_frame_sp->GetSymbolContext (eSymbolContextFunction).function->GetBlock(false)); 169 } 170 171 m_frames.push_back (frame_sp); 172 } 173 } 174 } 175 } 176 177 if (m_prev_frames_sp) 178 { 179 StackFrameList *prev_frames = m_prev_frames_sp.get(); 180 StackFrameList *curr_frames = this; 181 182 #if defined (DEBUG_STACK_FRAMES) 183 s.PutCString("\nprev_frames:\n"); 184 prev_frames->Dump (&s); 185 s.PutCString("\ncurr_frames:\n"); 186 curr_frames->Dump (&s); 187 s.EOL(); 188 #endif 189 size_t curr_frame_num, prev_frame_num; 190 191 for (curr_frame_num = curr_frames->m_frames.size(), prev_frame_num = prev_frames->m_frames.size(); 192 curr_frame_num > 0 && prev_frame_num > 0; 193 --curr_frame_num, --prev_frame_num) 194 { 195 const size_t curr_frame_idx = curr_frame_num-1; 196 const size_t prev_frame_idx = prev_frame_num-1; 197 StackFrameSP curr_frame_sp (curr_frames->m_frames[curr_frame_idx]); 198 StackFrameSP prev_frame_sp (prev_frames->m_frames[prev_frame_idx]); 199 200 #if defined (DEBUG_STACK_FRAMES) 201 s.Printf("\n\nCurr frame #%u ", curr_frame_idx); 202 if (curr_frame_sp) 203 curr_frame_sp->Dump (&s, true, false); 204 else 205 s.PutCString("NULL"); 206 s.Printf("\nPrev frame #%u ", prev_frame_idx); 207 if (prev_frame_sp) 208 prev_frame_sp->Dump (&s, true, false); 209 else 210 s.PutCString("NULL"); 211 #endif 212 213 StackFrame *curr_frame = curr_frame_sp.get(); 214 StackFrame *prev_frame = prev_frame_sp.get(); 215 216 if (curr_frame == NULL || prev_frame == NULL) 217 break; 218 219 // Check the stack ID to make sure they are equal 220 if (curr_frame->GetStackID() != prev_frame->GetStackID()) 221 break; 222 223 prev_frame->UpdatePreviousFrameFromCurrentFrame (*curr_frame); 224 // Now copy the fixed up previous frame into the current frames 225 // so the pointer doesn't change 226 m_frames[curr_frame_idx] = prev_frame_sp; 227 //curr_frame->UpdateCurrentFrameFromPreviousFrame (*prev_frame); 228 229 #if defined (DEBUG_STACK_FRAMES) 230 s.Printf("\n Copying previous frame to current frame"); 231 #endif 232 } 233 // We are done with the old stack frame list, we can release it now 234 m_prev_frames_sp.reset(); 235 } 236 237 #if defined (DEBUG_STACK_FRAMES) 238 s.PutCString("\n\nNew frames:\n"); 239 Dump (&s); 240 s.EOL(); 241 #endif 242 } 243 else 244 { 245 m_frames.resize(m_thread.GetUnwinder()->GetFrameCount()); 246 } 247 } 248 return m_frames.size(); 249 } 250 251 void 252 StackFrameList::Dump (Stream *s) 253 { 254 if (s == NULL) 255 return; 256 Mutex::Locker locker (m_mutex); 257 258 const_iterator pos, begin = m_frames.begin(), end = m_frames.end(); 259 for (pos = begin; pos != end; ++pos) 260 { 261 StackFrame *frame = (*pos).get(); 262 s->Printf("%p: ", frame); 263 if (frame) 264 { 265 frame->GetStackID().Dump (s); 266 frame->DumpUsingSettingsFormat (s); 267 } 268 else 269 s->Printf("frame #%u", std::distance (begin, pos)); 270 s->EOL(); 271 } 272 s->EOL(); 273 } 274 275 StackFrameSP 276 StackFrameList::GetFrameAtIndex (uint32_t idx) 277 { 278 StackFrameSP frame_sp; 279 Mutex::Locker locker (m_mutex); 280 if (idx < m_frames.size()) 281 frame_sp = m_frames[idx]; 282 283 if (frame_sp) 284 return frame_sp; 285 286 // Special case the first frame (idx == 0) so that we don't need to 287 // know how many stack frames there are to get it. If we need any other 288 // frames, then we do need to know if "idx" is a valid index. 289 if (idx == 0) 290 { 291 // If this is the first frame, we want to share the thread register 292 // context with the stack frame at index zero. 293 m_thread.GetRegisterContext(); 294 assert (m_thread.m_reg_context_sp.get()); 295 frame_sp.reset (new StackFrame (0, 296 0, 297 m_thread, 298 m_thread.m_reg_context_sp, 299 m_thread.m_reg_context_sp->GetSP(), 300 m_thread.m_reg_context_sp->GetPC(), 301 NULL)); 302 303 SetFrameAtIndex(idx, frame_sp); 304 } 305 else if (idx < GetNumFrames()) 306 { 307 if (m_show_inlined_frames) 308 { 309 // When inline frames are enabled we cache up all frames in GetNumFrames() 310 frame_sp = m_frames[idx]; 311 } 312 else 313 { 314 Unwind *unwinder = m_thread.GetUnwinder (); 315 if (unwinder) 316 { 317 addr_t pc, cfa; 318 if (unwinder->GetFrameInfoAtIndex(idx, cfa, pc)) 319 { 320 frame_sp.reset (new StackFrame (idx, idx, m_thread, cfa, pc, NULL)); 321 322 Function *function = frame_sp->GetSymbolContext (eSymbolContextFunction).function; 323 if (function) 324 { 325 // When we aren't showing inline functions we always use 326 // the top most function block as the scope. 327 frame_sp->SetSymbolContextScope (&function->GetBlock(false)); 328 } 329 else 330 { 331 // Set the symbol scope from the symbol regardless if it is NULL or valid. 332 frame_sp->SetSymbolContextScope (frame_sp->GetSymbolContext (eSymbolContextSymbol).symbol); 333 } 334 SetFrameAtIndex(idx, frame_sp); 335 } 336 } 337 } 338 } 339 return frame_sp; 340 } 341 342 StackFrameSP 343 StackFrameList::GetFrameWithConcreteFrameIndex (uint32_t unwind_idx) 344 { 345 // First try assuming the unwind index is the same as the frame index. The 346 // unwind index is always greater than or equal to the frame index, so it 347 // is a good place to start. If we have inlined frames we might have 5 348 // concrete frames (frame unwind indexes go from 0-4), but we might have 15 349 // frames after we make all the inlined frames. Most of the time the unwind 350 // frame index (or the concrete frame index) is the same as the frame index. 351 uint32_t frame_idx = unwind_idx; 352 StackFrameSP frame_sp (GetFrameAtIndex (frame_idx)); 353 while (frame_sp) 354 { 355 if (frame_sp->GetFrameIndex() == unwind_idx) 356 break; 357 frame_sp = GetFrameAtIndex (++frame_idx); 358 } 359 return frame_sp; 360 } 361 362 StackFrameSP 363 StackFrameList::GetFrameWithStackID (StackID &stack_id) 364 { 365 uint32_t frame_idx = 0; 366 StackFrameSP frame_sp; 367 do 368 { 369 frame_sp = GetFrameAtIndex (frame_idx); 370 if (frame_sp && frame_sp->GetStackID() == stack_id) 371 break; 372 frame_idx++; 373 } 374 while (frame_sp); 375 return frame_sp; 376 } 377 378 bool 379 StackFrameList::SetFrameAtIndex (uint32_t idx, StackFrameSP &frame_sp) 380 { 381 if (idx >= m_frames.size()) 382 m_frames.resize(idx + 1); 383 // Make sure allocation succeeded by checking bounds again 384 if (idx < m_frames.size()) 385 { 386 m_frames[idx] = frame_sp; 387 return true; 388 } 389 return false; // resize failed, out of memory? 390 } 391 392 uint32_t 393 StackFrameList::GetSelectedFrameIndex () const 394 { 395 Mutex::Locker locker (m_mutex); 396 return m_selected_frame_idx; 397 } 398 399 400 uint32_t 401 StackFrameList::SetSelectedFrame (lldb_private::StackFrame *frame) 402 { 403 Mutex::Locker locker (m_mutex); 404 const_iterator pos; 405 const_iterator begin = m_frames.begin(); 406 const_iterator end = m_frames.end(); 407 m_selected_frame_idx = 0; 408 for (pos = begin; pos != end; ++pos) 409 { 410 if (pos->get() == frame) 411 { 412 m_selected_frame_idx = std::distance (begin, pos); 413 break; 414 } 415 } 416 SetDefaultFileAndLineToSelectedFrame(); 417 return m_selected_frame_idx; 418 } 419 420 // Mark a stack frame as the current frame using the frame index 421 void 422 StackFrameList::SetSelectedFrameByIndex (uint32_t idx) 423 { 424 Mutex::Locker locker (m_mutex); 425 m_selected_frame_idx = idx; 426 SetDefaultFileAndLineToSelectedFrame(); 427 } 428 429 void 430 StackFrameList::SetDefaultFileAndLineToSelectedFrame() 431 { 432 if (m_thread.GetID() == m_thread.GetProcess().GetThreadList().GetSelectedThread()->GetID()) 433 { 434 StackFrameSP frame_sp = m_frames[m_selected_frame_idx]; 435 if (frame_sp) 436 { 437 SymbolContext sc = frame_sp->GetSymbolContext(eSymbolContextEverything); 438 if (sc.line_entry.file) 439 m_thread.GetProcess().GetTarget().GetSourceManager().SetDefaultFileAndLine (sc.line_entry.file, sc.line_entry.line); 440 } 441 } 442 } 443 444 // The thread has been run, reset the number stack frames to zero so we can 445 // determine how many frames we have lazily. 446 void 447 StackFrameList::Clear () 448 { 449 Mutex::Locker locker (m_mutex); 450 m_frames.clear(); 451 } 452 453 void 454 StackFrameList::InvalidateFrames (uint32_t start_idx) 455 { 456 Mutex::Locker locker (m_mutex); 457 if (m_show_inlined_frames) 458 { 459 Clear(); 460 } 461 else 462 { 463 const size_t num_frames = m_frames.size(); 464 while (start_idx < num_frames) 465 { 466 m_frames[start_idx].reset(); 467 ++start_idx; 468 } 469 } 470 } 471 472 void 473 StackFrameList::Merge (std::auto_ptr<StackFrameList>& curr_ap, lldb::StackFrameListSP& prev_sp) 474 { 475 Mutex::Locker curr_locker (curr_ap.get() ? curr_ap->m_mutex.GetMutex() : NULL); 476 Mutex::Locker prev_locker (prev_sp.get() ? prev_sp->m_mutex.GetMutex() : NULL); 477 478 #if defined (DEBUG_STACK_FRAMES) 479 StreamFile s(stdout, false); 480 s.PutCString("\n\nStackFrameList::Merge():\nPrev:\n"); 481 if (prev_sp.get()) 482 prev_sp->Dump (&s); 483 else 484 s.PutCString ("NULL"); 485 s.PutCString("\nCurr:\n"); 486 if (curr_ap.get()) 487 curr_ap->Dump (&s); 488 else 489 s.PutCString ("NULL"); 490 s.EOL(); 491 #endif 492 493 if (curr_ap.get() == NULL || curr_ap->GetNumFrames (false) == 0) 494 { 495 #if defined (DEBUG_STACK_FRAMES) 496 s.PutCString("No current frames, leave previous frames alone...\n"); 497 #endif 498 curr_ap.release(); 499 return; 500 } 501 502 if (prev_sp.get() == NULL || prev_sp->GetNumFrames (false) == 0) 503 { 504 #if defined (DEBUG_STACK_FRAMES) 505 s.PutCString("No previous frames, so use current frames...\n"); 506 #endif 507 // We either don't have any previous frames, or since we have more than 508 // one current frames it means we have all the frames and can safely 509 // replace our previous frames. 510 prev_sp.reset (curr_ap.release()); 511 return; 512 } 513 514 const uint32_t num_curr_frames = curr_ap->GetNumFrames (false); 515 516 if (num_curr_frames > 1) 517 { 518 #if defined (DEBUG_STACK_FRAMES) 519 s.PutCString("We have more than one current frame, so use current frames...\n"); 520 #endif 521 // We have more than one current frames it means we have all the frames 522 // and can safely replace our previous frames. 523 prev_sp.reset (curr_ap.release()); 524 525 #if defined (DEBUG_STACK_FRAMES) 526 s.PutCString("\nMerged:\n"); 527 prev_sp->Dump (&s); 528 #endif 529 return; 530 } 531 532 StackFrameSP prev_frame_zero_sp(prev_sp->GetFrameAtIndex (0)); 533 StackFrameSP curr_frame_zero_sp(curr_ap->GetFrameAtIndex (0)); 534 StackID curr_stack_id (curr_frame_zero_sp->GetStackID()); 535 StackID prev_stack_id (prev_frame_zero_sp->GetStackID()); 536 537 #if defined (DEBUG_STACK_FRAMES) 538 const uint32_t num_prev_frames = prev_sp->GetNumFrames (false); 539 s.Printf("\n%u previous frames with one current frame\n", num_prev_frames); 540 #endif 541 542 // We have only a single current frame 543 // Our previous stack frames only had a single frame as well... 544 if (curr_stack_id == prev_stack_id) 545 { 546 #if defined (DEBUG_STACK_FRAMES) 547 s.Printf("\nPrevious frame #0 is same as current frame #0, merge the cached data\n"); 548 #endif 549 550 curr_frame_zero_sp->UpdateCurrentFrameFromPreviousFrame (*prev_frame_zero_sp); 551 // prev_frame_zero_sp->UpdatePreviousFrameFromCurrentFrame (*curr_frame_zero_sp); 552 // prev_sp->SetFrameAtIndex (0, prev_frame_zero_sp); 553 } 554 else if (curr_stack_id < prev_stack_id) 555 { 556 #if defined (DEBUG_STACK_FRAMES) 557 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"); 558 #endif 559 prev_sp->m_frames.insert (prev_sp->m_frames.begin(), curr_frame_zero_sp); 560 } 561 562 curr_ap.release(); 563 564 #if defined (DEBUG_STACK_FRAMES) 565 s.PutCString("\nMerged:\n"); 566 prev_sp->Dump (&s); 567 #endif 568 569 570 } 571 572 lldb::StackFrameSP 573 StackFrameList::GetStackFrameSPForStackFramePtr (StackFrame *stack_frame_ptr) 574 { 575 const_iterator pos; 576 const_iterator begin = m_frames.begin(); 577 const_iterator end = m_frames.end(); 578 lldb::StackFrameSP ret_sp; 579 580 for (pos = begin; pos != end; ++pos) 581 { 582 if (pos->get() == stack_frame_ptr) 583 { 584 ret_sp = (*pos); 585 break; 586 } 587 } 588 return ret_sp; 589 } 590 591 size_t 592 StackFrameList::GetStatus (Stream& strm, 593 uint32_t first_frame, 594 uint32_t num_frames, 595 bool show_frame_info, 596 uint32_t num_frames_with_source, 597 uint32_t source_lines_before, 598 uint32_t source_lines_after) 599 { 600 size_t num_frames_displayed = 0; 601 602 if (num_frames == 0) 603 return 0; 604 605 StackFrameSP frame_sp; 606 uint32_t frame_idx = 0; 607 uint32_t last_frame; 608 609 // Don't let the last frame wrap around... 610 if (num_frames == UINT32_MAX) 611 last_frame = UINT32_MAX; 612 else 613 last_frame = first_frame + num_frames; 614 615 for (frame_idx = first_frame; frame_idx < last_frame; ++frame_idx) 616 { 617 frame_sp = GetFrameAtIndex(frame_idx); 618 if (frame_sp.get() == NULL) 619 break; 620 621 if (!frame_sp->GetStatus (strm, 622 show_frame_info, 623 num_frames_with_source > first_frame - frame_idx, 624 source_lines_before, 625 source_lines_after)) 626 break; 627 ++num_frames_displayed; 628 } 629 630 strm.IndentLess(); 631 return num_frames_displayed; 632 } 633 634