1 //===-- SBThread.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/API/SBThread.h" 11 12 #include "lldb/API/SBSymbolContext.h" 13 #include "lldb/API/SBFileSpec.h" 14 #include "lldb/Core/Debugger.h" 15 #include "lldb/Core/Stream.h" 16 #include "lldb/Core/StreamFile.h" 17 #include "lldb/Interpreter/CommandInterpreter.h" 18 #include "lldb/Target/Thread.h" 19 #include "lldb/Target/Process.h" 20 #include "lldb/Symbol/SymbolContext.h" 21 #include "lldb/Symbol/CompileUnit.h" 22 #include "lldb/Target/StopInfo.h" 23 #include "lldb/Target/Target.h" 24 #include "lldb/Target/ThreadPlan.h" 25 #include "lldb/Target/ThreadPlanStepInstruction.h" 26 #include "lldb/Target/ThreadPlanStepOut.h" 27 #include "lldb/Target/ThreadPlanStepRange.h" 28 #include "lldb/Target/ThreadPlanStepInRange.h" 29 30 31 #include "lldb/API/SBAddress.h" 32 #include "lldb/API/SBFrame.h" 33 #include "lldb/API/SBSourceManager.h" 34 #include "lldb/API/SBDebugger.h" 35 #include "lldb/API/SBProcess.h" 36 37 using namespace lldb; 38 using namespace lldb_private; 39 40 SBThread::SBThread () : 41 m_opaque_sp () 42 { 43 } 44 45 //---------------------------------------------------------------------- 46 // Thread constructor 47 //---------------------------------------------------------------------- 48 SBThread::SBThread (const ThreadSP& lldb_object_sp) : 49 m_opaque_sp (lldb_object_sp) 50 { 51 } 52 53 SBThread::SBThread (const SBThread &rhs) 54 { 55 m_opaque_sp = rhs.m_opaque_sp; 56 } 57 58 //---------------------------------------------------------------------- 59 // Destructor 60 //---------------------------------------------------------------------- 61 SBThread::~SBThread() 62 { 63 } 64 65 bool 66 SBThread::IsValid() const 67 { 68 return m_opaque_sp != NULL; 69 } 70 71 void 72 SBThread::Clear () 73 { 74 m_opaque_sp.reset(); 75 } 76 77 78 StopReason 79 SBThread::GetStopReason() 80 { 81 if (m_opaque_sp) 82 { 83 lldb_private::StopInfo *stop_info = m_opaque_sp->GetStopInfo (); 84 if (stop_info) 85 return stop_info->GetStopReason(); 86 } 87 return eStopReasonInvalid; 88 } 89 90 size_t 91 SBThread::GetStopDescription (char *dst, size_t dst_len) 92 { 93 if (m_opaque_sp) 94 { 95 lldb_private::StopInfo *stop_info = m_opaque_sp->GetStopInfo (); 96 if (stop_info) 97 { 98 const char *stop_desc = stop_info->GetDescription(); 99 if (stop_desc) 100 { 101 if (dst) 102 return ::snprintf (dst, dst_len, "%s", stop_desc); 103 else 104 { 105 // NULL dst passed in, return the length needed to contain the description 106 return ::strlen (stop_desc) + 1; // Include the NULL byte for size 107 } 108 } 109 else 110 { 111 size_t stop_desc_len = 0; 112 switch (stop_info->GetStopReason()) 113 { 114 case eStopReasonTrace: 115 case eStopReasonPlanComplete: 116 { 117 static char trace_desc[] = "step"; 118 stop_desc = trace_desc; 119 stop_desc_len = sizeof(trace_desc); // Include the NULL byte for size 120 } 121 break; 122 123 case eStopReasonBreakpoint: 124 { 125 static char bp_desc[] = "breakpoint hit"; 126 stop_desc = bp_desc; 127 stop_desc_len = sizeof(bp_desc); // Include the NULL byte for size 128 } 129 break; 130 131 case eStopReasonWatchpoint: 132 { 133 static char wp_desc[] = "watchpoint hit"; 134 stop_desc = wp_desc; 135 stop_desc_len = sizeof(wp_desc); // Include the NULL byte for size 136 } 137 break; 138 139 case eStopReasonSignal: 140 { 141 stop_desc = m_opaque_sp->GetProcess().GetUnixSignals ().GetSignalAsCString (stop_info->GetValue()); 142 if (stop_desc == NULL || stop_desc[0] == '\0') 143 { 144 static char signal_desc[] = "signal"; 145 stop_desc = signal_desc; 146 stop_desc_len = sizeof(signal_desc); // Include the NULL byte for size 147 } 148 } 149 break; 150 151 case eStopReasonException: 152 { 153 char exc_desc[] = "exception"; 154 stop_desc = exc_desc; 155 stop_desc_len = sizeof(exc_desc); // Include the NULL byte for size 156 } 157 break; 158 159 default: 160 break; 161 } 162 163 if (stop_desc && stop_desc[0]) 164 { 165 if (dst) 166 return ::snprintf (dst, dst_len, "%s", stop_desc) + 1; // Include the NULL byte 167 168 if (stop_desc_len == 0) 169 stop_desc_len = ::strlen (stop_desc) + 1; // Include the NULL byte 170 171 return stop_desc_len; 172 } 173 } 174 } 175 } 176 if (dst) 177 *dst = 0; 178 return 0; 179 } 180 181 void 182 SBThread::SetThread (const ThreadSP& lldb_object_sp) 183 { 184 m_opaque_sp = lldb_object_sp; 185 } 186 187 188 lldb::tid_t 189 SBThread::GetThreadID () const 190 { 191 if (m_opaque_sp) 192 return m_opaque_sp->GetID(); 193 else 194 return LLDB_INVALID_THREAD_ID; 195 } 196 197 uint32_t 198 SBThread::GetIndexID () const 199 { 200 if (m_opaque_sp) 201 return m_opaque_sp->GetIndexID(); 202 return LLDB_INVALID_INDEX32; 203 } 204 const char * 205 SBThread::GetName () const 206 { 207 if (m_opaque_sp) 208 return m_opaque_sp->GetName(); 209 return NULL; 210 } 211 212 const char * 213 SBThread::GetQueueName () const 214 { 215 if (m_opaque_sp) 216 return m_opaque_sp->GetQueueName(); 217 return NULL; 218 } 219 220 221 void 222 SBThread::DisplayFramesForSelectedContext (FILE *out, 223 FILE *err, 224 uint32_t first_frame, 225 uint32_t num_frames, 226 bool show_frame_info, 227 uint32_t num_frames_with_source, 228 uint32_t source_lines_before, 229 uint32_t source_lines_after) 230 { 231 if ((out == NULL) || (err == NULL)) 232 return; 233 234 if (m_opaque_sp) 235 { 236 uint32_t num_stack_frames = m_opaque_sp->GetStackFrameCount (); 237 StackFrameSP frame_sp; 238 uint32_t frame_idx = 0; 239 240 for (frame_idx = first_frame; frame_idx < first_frame + num_frames; ++frame_idx) 241 { 242 if (frame_idx >= num_stack_frames) 243 break; 244 245 frame_sp = m_opaque_sp->GetStackFrameAtIndex (frame_idx); 246 if (!frame_sp) 247 break; 248 249 SBFrame sb_frame (frame_sp); 250 if (DisplaySingleFrameForSelectedContext (out, 251 err, 252 sb_frame, 253 show_frame_info, 254 num_frames_with_source > first_frame - frame_idx, 255 source_lines_before, 256 source_lines_after) == false) 257 break; 258 } 259 } 260 } 261 262 bool 263 SBThread::DisplaySingleFrameForSelectedContext (FILE *out, 264 FILE *err, 265 SBFrame &frame, 266 bool show_frame_info, 267 bool show_source, 268 uint32_t source_lines_after, 269 uint32_t source_lines_before) 270 { 271 bool success = false; 272 273 if ((out == NULL) || (err == NULL)) 274 return false; 275 276 if (m_opaque_sp && frame.IsValid()) 277 { 278 StreamFile str (out); 279 280 SBSymbolContext sc(frame.GetSymbolContext(eSymbolContextEverything)); 281 282 if (show_frame_info && sc.IsValid()) 283 { 284 user_id_t frame_idx = (user_id_t) frame.GetFrameID(); 285 lldb::addr_t pc = frame.GetPC(); 286 ::fprintf (out, 287 " frame #%u: tid = 0x%4.4x, pc = 0x%llx ", 288 frame_idx, 289 GetThreadID(), 290 (long long)pc); 291 sc->DumpStopContext (&str, &m_opaque_sp->GetProcess(), *frame.GetPCAddress(), false, true, false); 292 fprintf (out, "\n"); 293 success = true; 294 } 295 296 SBCompileUnit comp_unit(sc.GetCompileUnit()); 297 if (show_source && comp_unit.IsValid()) 298 { 299 success = false; 300 SBLineEntry line_entry; 301 if (line_entry.IsValid()) 302 { 303 SourceManager& source_manager = m_opaque_sp->GetProcess().GetTarget().GetDebugger().GetSourceManager(); 304 SBFileSpec line_entry_file_spec (line_entry.GetFileSpec()); 305 306 if (line_entry_file_spec.IsValid()) 307 { 308 source_manager.DisplaySourceLinesWithLineNumbers (line_entry_file_spec.ref(), 309 line_entry.GetLine(), 310 source_lines_after, 311 source_lines_before, "->", 312 &str); 313 success = true; 314 } 315 } 316 } 317 } 318 return success; 319 } 320 321 void 322 SBThread::StepOver (lldb::RunMode stop_other_threads) 323 { 324 if (m_opaque_sp) 325 { 326 bool abort_other_plans = true; 327 StackFrameSP frame_sp(m_opaque_sp->GetStackFrameAtIndex (0)); 328 329 if (frame_sp) 330 { 331 if (frame_sp->HasDebugInformation ()) 332 { 333 SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything)); 334 m_opaque_sp->QueueThreadPlanForStepRange (abort_other_plans, 335 eStepTypeOver, 336 sc.line_entry.range, 337 sc, 338 stop_other_threads, 339 false); 340 341 } 342 else 343 { 344 m_opaque_sp->QueueThreadPlanForStepSingleInstruction (true, 345 abort_other_plans, 346 stop_other_threads); 347 } 348 } 349 350 Process &process = m_opaque_sp->GetProcess(); 351 // Why do we need to set the current thread by ID here??? 352 process.GetThreadList().SetSelectedThreadByID (m_opaque_sp->GetID()); 353 process.Resume(); 354 } 355 } 356 357 void 358 SBThread::StepInto (lldb::RunMode stop_other_threads) 359 { 360 if (m_opaque_sp) 361 { 362 bool abort_other_plans = true; 363 364 StackFrameSP frame_sp(m_opaque_sp->GetStackFrameAtIndex (0)); 365 366 if (frame_sp && frame_sp->HasDebugInformation ()) 367 { 368 bool avoid_code_without_debug_info = true; 369 SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything)); 370 m_opaque_sp->QueueThreadPlanForStepRange (abort_other_plans, 371 eStepTypeInto, 372 sc.line_entry.range, 373 sc, 374 stop_other_threads, 375 avoid_code_without_debug_info); 376 } 377 else 378 { 379 m_opaque_sp->QueueThreadPlanForStepSingleInstruction (false, 380 abort_other_plans, 381 stop_other_threads); 382 } 383 384 Process &process = m_opaque_sp->GetProcess(); 385 // Why do we need to set the current thread by ID here??? 386 process.GetThreadList().SetSelectedThreadByID (m_opaque_sp->GetID()); 387 process.Resume(); 388 389 } 390 } 391 392 void 393 SBThread::StepOut () 394 { 395 if (m_opaque_sp) 396 { 397 bool abort_other_plans = true; 398 bool stop_other_threads = true; 399 400 m_opaque_sp->QueueThreadPlanForStepOut (abort_other_plans, NULL, false, stop_other_threads, eVoteYes, eVoteNoOpinion); 401 402 Process &process = m_opaque_sp->GetProcess(); 403 process.GetThreadList().SetSelectedThreadByID (m_opaque_sp->GetID()); 404 process.Resume(); 405 } 406 } 407 408 void 409 SBThread::StepInstruction (bool step_over) 410 { 411 if (m_opaque_sp) 412 { 413 m_opaque_sp->QueueThreadPlanForStepSingleInstruction (step_over, true, true); 414 Process &process = m_opaque_sp->GetProcess(); 415 process.GetThreadList().SetSelectedThreadByID (m_opaque_sp->GetID()); 416 process.Resume(); 417 } 418 } 419 420 void 421 SBThread::RunToAddress (lldb::addr_t addr) 422 { 423 if (m_opaque_sp) 424 { 425 bool abort_other_plans = true; 426 bool stop_other_threads = true; 427 428 Address target_addr (NULL, addr); 429 430 m_opaque_sp->QueueThreadPlanForRunToAddress (abort_other_plans, target_addr, stop_other_threads); 431 Process &process = m_opaque_sp->GetProcess(); 432 process.GetThreadList().SetSelectedThreadByID (m_opaque_sp->GetID()); 433 process.Resume(); 434 } 435 436 } 437 438 SBProcess 439 SBThread::GetProcess () 440 { 441 SBProcess process; 442 if (m_opaque_sp) 443 { 444 // Have to go up to the target so we can get a shared pointer to our process... 445 process.SetProcess(m_opaque_sp->GetProcess().GetTarget().GetProcessSP()); 446 } 447 return process; 448 } 449 450 uint32_t 451 SBThread::GetNumFrames () 452 { 453 if (m_opaque_sp) 454 return m_opaque_sp->GetStackFrameCount(); 455 return 0; 456 } 457 458 SBFrame 459 SBThread::GetFrameAtIndex (uint32_t idx) 460 { 461 SBFrame sb_frame; 462 if (m_opaque_sp) 463 sb_frame.SetFrame (m_opaque_sp->GetStackFrameAtIndex (idx)); 464 return sb_frame; 465 } 466 467 const lldb::SBThread & 468 SBThread::operator = (const lldb::SBThread &rhs) 469 { 470 m_opaque_sp = rhs.m_opaque_sp; 471 return *this; 472 } 473 474 bool 475 SBThread::operator == (const SBThread &rhs) const 476 { 477 return m_opaque_sp.get() == rhs.m_opaque_sp.get(); 478 } 479 480 bool 481 SBThread::operator != (const SBThread &rhs) const 482 { 483 return m_opaque_sp.get() != rhs.m_opaque_sp.get(); 484 } 485 486 lldb_private::Thread * 487 SBThread::GetLLDBObjectPtr () 488 { 489 return m_opaque_sp.get(); 490 } 491 492 const lldb_private::Thread * 493 SBThread::operator->() const 494 { 495 return m_opaque_sp.get(); 496 } 497 498 const lldb_private::Thread & 499 SBThread::operator*() const 500 { 501 return *m_opaque_sp; 502 } 503 504 lldb_private::Thread * 505 SBThread::operator->() 506 { 507 return m_opaque_sp.get(); 508 } 509 510 lldb_private::Thread & 511 SBThread::operator*() 512 { 513 return *m_opaque_sp; 514 } 515