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::StepOver (lldb::RunMode stop_other_threads) 223 { 224 if (m_opaque_sp) 225 { 226 bool abort_other_plans = true; 227 StackFrameSP frame_sp(m_opaque_sp->GetStackFrameAtIndex (0)); 228 229 if (frame_sp) 230 { 231 if (frame_sp->HasDebugInformation ()) 232 { 233 SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything)); 234 m_opaque_sp->QueueThreadPlanForStepRange (abort_other_plans, 235 eStepTypeOver, 236 sc.line_entry.range, 237 sc, 238 stop_other_threads, 239 false); 240 241 } 242 else 243 { 244 m_opaque_sp->QueueThreadPlanForStepSingleInstruction (true, 245 abort_other_plans, 246 stop_other_threads); 247 } 248 } 249 250 Process &process = m_opaque_sp->GetProcess(); 251 // Why do we need to set the current thread by ID here??? 252 process.GetThreadList().SetSelectedThreadByID (m_opaque_sp->GetID()); 253 process.Resume(); 254 } 255 } 256 257 void 258 SBThread::StepInto (lldb::RunMode stop_other_threads) 259 { 260 if (m_opaque_sp) 261 { 262 bool abort_other_plans = true; 263 264 StackFrameSP frame_sp(m_opaque_sp->GetStackFrameAtIndex (0)); 265 266 if (frame_sp && frame_sp->HasDebugInformation ()) 267 { 268 bool avoid_code_without_debug_info = true; 269 SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything)); 270 m_opaque_sp->QueueThreadPlanForStepRange (abort_other_plans, 271 eStepTypeInto, 272 sc.line_entry.range, 273 sc, 274 stop_other_threads, 275 avoid_code_without_debug_info); 276 } 277 else 278 { 279 m_opaque_sp->QueueThreadPlanForStepSingleInstruction (false, 280 abort_other_plans, 281 stop_other_threads); 282 } 283 284 Process &process = m_opaque_sp->GetProcess(); 285 // Why do we need to set the current thread by ID here??? 286 process.GetThreadList().SetSelectedThreadByID (m_opaque_sp->GetID()); 287 process.Resume(); 288 289 } 290 } 291 292 void 293 SBThread::StepOut () 294 { 295 if (m_opaque_sp) 296 { 297 bool abort_other_plans = true; 298 bool stop_other_threads = true; 299 300 m_opaque_sp->QueueThreadPlanForStepOut (abort_other_plans, NULL, false, stop_other_threads, eVoteYes, eVoteNoOpinion); 301 302 Process &process = m_opaque_sp->GetProcess(); 303 process.GetThreadList().SetSelectedThreadByID (m_opaque_sp->GetID()); 304 process.Resume(); 305 } 306 } 307 308 void 309 SBThread::StepInstruction (bool step_over) 310 { 311 if (m_opaque_sp) 312 { 313 m_opaque_sp->QueueThreadPlanForStepSingleInstruction (step_over, true, true); 314 Process &process = m_opaque_sp->GetProcess(); 315 process.GetThreadList().SetSelectedThreadByID (m_opaque_sp->GetID()); 316 process.Resume(); 317 } 318 } 319 320 void 321 SBThread::RunToAddress (lldb::addr_t addr) 322 { 323 if (m_opaque_sp) 324 { 325 bool abort_other_plans = true; 326 bool stop_other_threads = true; 327 328 Address target_addr (NULL, addr); 329 330 m_opaque_sp->QueueThreadPlanForRunToAddress (abort_other_plans, target_addr, stop_other_threads); 331 Process &process = m_opaque_sp->GetProcess(); 332 process.GetThreadList().SetSelectedThreadByID (m_opaque_sp->GetID()); 333 process.Resume(); 334 } 335 336 } 337 338 SBProcess 339 SBThread::GetProcess () 340 { 341 SBProcess process; 342 if (m_opaque_sp) 343 { 344 // Have to go up to the target so we can get a shared pointer to our process... 345 process.SetProcess(m_opaque_sp->GetProcess().GetTarget().GetProcessSP()); 346 } 347 return process; 348 } 349 350 uint32_t 351 SBThread::GetNumFrames () 352 { 353 if (m_opaque_sp) 354 return m_opaque_sp->GetStackFrameCount(); 355 return 0; 356 } 357 358 SBFrame 359 SBThread::GetFrameAtIndex (uint32_t idx) 360 { 361 SBFrame sb_frame; 362 if (m_opaque_sp) 363 sb_frame.SetFrame (m_opaque_sp->GetStackFrameAtIndex (idx)); 364 return sb_frame; 365 } 366 367 const lldb::SBThread & 368 SBThread::operator = (const lldb::SBThread &rhs) 369 { 370 m_opaque_sp = rhs.m_opaque_sp; 371 return *this; 372 } 373 374 bool 375 SBThread::operator == (const SBThread &rhs) const 376 { 377 return m_opaque_sp.get() == rhs.m_opaque_sp.get(); 378 } 379 380 bool 381 SBThread::operator != (const SBThread &rhs) const 382 { 383 return m_opaque_sp.get() != rhs.m_opaque_sp.get(); 384 } 385 386 lldb_private::Thread * 387 SBThread::GetLLDBObjectPtr () 388 { 389 return m_opaque_sp.get(); 390 } 391 392 const lldb_private::Thread * 393 SBThread::operator->() const 394 { 395 return m_opaque_sp.get(); 396 } 397 398 const lldb_private::Thread & 399 SBThread::operator*() const 400 { 401 return *m_opaque_sp; 402 } 403 404 lldb_private::Thread * 405 SBThread::operator->() 406 { 407 return m_opaque_sp.get(); 408 } 409 410 lldb_private::Thread & 411 SBThread::operator*() 412 { 413 return *m_opaque_sp; 414 } 415