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