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