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 lldb_private::StopInfo *stop_info = m_opaque_sp->GetStopInfo (); 85 if (stop_info) 86 return stop_info->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 lldb_private::StopInfo *stop_info = m_opaque_sp->GetStopInfo (); 97 if (stop_info) 98 { 99 const char *stop_desc = stop_info->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->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->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 process.Resume(); 255 } 256 } 257 258 void 259 SBThread::StepInto (lldb::RunMode stop_other_threads) 260 { 261 if (m_opaque_sp) 262 { 263 bool abort_other_plans = true; 264 265 StackFrameSP frame_sp(m_opaque_sp->GetStackFrameAtIndex (0)); 266 267 if (frame_sp && frame_sp->HasDebugInformation ()) 268 { 269 bool avoid_code_without_debug_info = true; 270 SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything)); 271 m_opaque_sp->QueueThreadPlanForStepRange (abort_other_plans, 272 eStepTypeInto, 273 sc.line_entry.range, 274 sc, 275 stop_other_threads, 276 avoid_code_without_debug_info); 277 } 278 else 279 { 280 m_opaque_sp->QueueThreadPlanForStepSingleInstruction (false, 281 abort_other_plans, 282 stop_other_threads); 283 } 284 285 Process &process = m_opaque_sp->GetProcess(); 286 // Why do we need to set the current thread by ID here??? 287 process.GetThreadList().SetSelectedThreadByID (m_opaque_sp->GetID()); 288 process.Resume(); 289 290 } 291 } 292 293 void 294 SBThread::StepOut () 295 { 296 if (m_opaque_sp) 297 { 298 bool abort_other_plans = true; 299 bool stop_other_threads = true; 300 301 m_opaque_sp->QueueThreadPlanForStepOut (abort_other_plans, NULL, false, stop_other_threads, eVoteYes, eVoteNoOpinion); 302 303 Process &process = m_opaque_sp->GetProcess(); 304 process.GetThreadList().SetSelectedThreadByID (m_opaque_sp->GetID()); 305 process.Resume(); 306 } 307 } 308 309 void 310 SBThread::StepInstruction (bool step_over) 311 { 312 if (m_opaque_sp) 313 { 314 m_opaque_sp->QueueThreadPlanForStepSingleInstruction (step_over, true, true); 315 Process &process = m_opaque_sp->GetProcess(); 316 process.GetThreadList().SetSelectedThreadByID (m_opaque_sp->GetID()); 317 process.Resume(); 318 } 319 } 320 321 void 322 SBThread::RunToAddress (lldb::addr_t addr) 323 { 324 if (m_opaque_sp) 325 { 326 bool abort_other_plans = true; 327 bool stop_other_threads = true; 328 329 Address target_addr (NULL, addr); 330 331 m_opaque_sp->QueueThreadPlanForRunToAddress (abort_other_plans, target_addr, stop_other_threads); 332 Process &process = m_opaque_sp->GetProcess(); 333 process.GetThreadList().SetSelectedThreadByID (m_opaque_sp->GetID()); 334 process.Resume(); 335 } 336 337 } 338 339 SBProcess 340 SBThread::GetProcess () 341 { 342 SBProcess process; 343 if (m_opaque_sp) 344 { 345 // Have to go up to the target so we can get a shared pointer to our process... 346 process.SetProcess(m_opaque_sp->GetProcess().GetTarget().GetProcessSP()); 347 } 348 return process; 349 } 350 351 uint32_t 352 SBThread::GetNumFrames () 353 { 354 if (m_opaque_sp) 355 return m_opaque_sp->GetStackFrameCount(); 356 return 0; 357 } 358 359 SBFrame 360 SBThread::GetFrameAtIndex (uint32_t idx) 361 { 362 SBFrame sb_frame; 363 if (m_opaque_sp) 364 sb_frame.SetFrame (m_opaque_sp->GetStackFrameAtIndex (idx)); 365 return sb_frame; 366 } 367 368 const lldb::SBThread & 369 SBThread::operator = (const lldb::SBThread &rhs) 370 { 371 m_opaque_sp = rhs.m_opaque_sp; 372 return *this; 373 } 374 375 bool 376 SBThread::operator == (const SBThread &rhs) const 377 { 378 return m_opaque_sp.get() == rhs.m_opaque_sp.get(); 379 } 380 381 bool 382 SBThread::operator != (const SBThread &rhs) const 383 { 384 return m_opaque_sp.get() != rhs.m_opaque_sp.get(); 385 } 386 387 lldb_private::Thread * 388 SBThread::GetLLDBObjectPtr () 389 { 390 return m_opaque_sp.get(); 391 } 392 393 const lldb_private::Thread * 394 SBThread::operator->() const 395 { 396 return m_opaque_sp.get(); 397 } 398 399 const lldb_private::Thread & 400 SBThread::operator*() const 401 { 402 return *m_opaque_sp; 403 } 404 405 lldb_private::Thread * 406 SBThread::operator->() 407 { 408 return m_opaque_sp.get(); 409 } 410 411 lldb_private::Thread & 412 SBThread::operator*() 413 { 414 return *m_opaque_sp; 415 } 416 417 bool 418 SBThread::GetDescription (SBStream &description) 419 { 420 if (m_opaque_sp) 421 { 422 m_opaque_sp->DumpInfo (description.ref(), true, true, true, LLDB_INVALID_INDEX32); 423 description.Printf (" %d frames, (instance name: %s)", GetNumFrames(), 424 m_opaque_sp->GetInstanceName().AsCString()); 425 } 426 else 427 description.Printf ("No value"); 428 429 return true; 430 } 431 432 PyObject * 433 SBThread::__repr__ () 434 { 435 SBStream description; 436 GetDescription (description); 437 return PyString_FromString (description.GetData()); 438 } 439