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