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