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