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