1 //===-- SBDebugger.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/SBDebugger.h" 11 12 #include "lldb/lldb-include.h" 13 #include "lldb/Interpreter/Args.h" 14 #include "lldb/Core/Debugger.h" 15 #include "lldb/Core/State.h" 16 #include "lldb/Target/Process.h" 17 #include "lldb/Target/TargetList.h" 18 19 #include "lldb/API/SBListener.h" 20 #include "lldb/API/SBBroadcaster.h" 21 #include "lldb/API/SBCommandInterpreter.h" 22 #include "lldb/API/SBCommandReturnObject.h" 23 #include "lldb/API/SBEvent.h" 24 #include "lldb/API/SBFrame.h" 25 #include "lldb/API/SBTarget.h" 26 #include "lldb/API/SBProcess.h" 27 #include "lldb/API/SBThread.h" 28 #include "lldb/API/SBSourceManager.h" 29 #include "lldb/API/SBInputReader.h" 30 31 using namespace lldb; 32 using namespace lldb_private; 33 34 void 35 SBDebugger::Initialize () 36 { 37 Debugger::Initialize(); 38 } 39 40 void 41 SBDebugger::Terminate () 42 { 43 Debugger::Terminate(); 44 } 45 46 SBDebugger 47 SBDebugger::Create() 48 { 49 SBDebugger debugger; 50 debugger.reset(Debugger::CreateInstance()); 51 return debugger; 52 } 53 54 SBDebugger::SBDebugger () : 55 m_opaque_sp () 56 { 57 } 58 59 SBDebugger::~SBDebugger () 60 { 61 } 62 63 bool 64 SBDebugger::IsValid() const 65 { 66 return m_opaque_sp.get() != NULL; 67 } 68 69 70 void 71 SBDebugger::SetAsync (bool b) 72 { 73 if (m_opaque_sp) 74 m_opaque_sp->SetAsyncExecution(b); 75 } 76 77 // Shouldn't really be settable after initialization as this could cause lots of problems; don't want users 78 // trying to switch modes in the middle of a debugging session. 79 void 80 SBDebugger::SetInputFileHandle (FILE *fh, bool transfer_ownership) 81 { 82 if (m_opaque_sp) 83 m_opaque_sp->SetInputFileHandle (fh, transfer_ownership); 84 } 85 86 void 87 SBDebugger::SetOutputFileHandle (FILE *fh, bool transfer_ownership) 88 { 89 if (m_opaque_sp) 90 m_opaque_sp->SetOutputFileHandle (fh, transfer_ownership); 91 } 92 93 void 94 SBDebugger::SetErrorFileHandle (FILE *fh, bool transfer_ownership) 95 { 96 if (m_opaque_sp) 97 m_opaque_sp->SetErrorFileHandle (fh, transfer_ownership); 98 } 99 100 FILE * 101 SBDebugger::GetInputFileHandle () 102 { 103 if (m_opaque_sp) 104 return m_opaque_sp->GetInputFileHandle(); 105 return NULL; 106 } 107 108 FILE * 109 SBDebugger::GetOutputFileHandle () 110 { 111 if (m_opaque_sp) 112 return m_opaque_sp->GetOutputFileHandle(); 113 return NULL; 114 } 115 116 FILE * 117 SBDebugger::GetErrorFileHandle () 118 { 119 if (m_opaque_sp) 120 return m_opaque_sp->GetErrorFileHandle(); 121 return NULL; 122 } 123 124 SBCommandInterpreter 125 SBDebugger::GetCommandInterpreter () 126 { 127 SBCommandInterpreter sb_interpreter; 128 if (m_opaque_sp) 129 sb_interpreter.reset (&m_opaque_sp->GetCommandInterpreter()); 130 return sb_interpreter; 131 } 132 133 void 134 SBDebugger::HandleCommand (const char *command) 135 { 136 if (m_opaque_sp) 137 { 138 SBCommandInterpreter sb_interpreter(GetCommandInterpreter ()); 139 SBCommandReturnObject result; 140 141 sb_interpreter.HandleCommand (command, result, false); 142 143 if (GetErrorFileHandle() != NULL) 144 result.PutError (GetErrorFileHandle()); 145 if (GetOutputFileHandle() != NULL) 146 result.PutOutput (GetOutputFileHandle()); 147 148 if (m_opaque_sp->GetAsyncExecution() == false) 149 { 150 SBProcess process(GetCommandInterpreter().GetProcess ()); 151 if (process.IsValid()) 152 { 153 EventSP event_sp; 154 Listener &lldb_listener = m_opaque_sp->GetListener(); 155 while (lldb_listener.GetNextEventForBroadcaster (process.get(), event_sp)) 156 { 157 SBEvent event(event_sp); 158 HandleProcessEvent (process, event, GetOutputFileHandle(), GetErrorFileHandle()); 159 } 160 } 161 } 162 } 163 } 164 165 SBListener 166 SBDebugger::GetListener () 167 { 168 SBListener sb_listener; 169 if (m_opaque_sp) 170 sb_listener.reset(&m_opaque_sp->GetListener(), false); 171 return sb_listener; 172 } 173 174 void 175 SBDebugger::HandleProcessEvent (const SBProcess &process, const SBEvent &event, FILE *out, FILE *err) 176 { 177 const uint32_t event_type = event.GetType(); 178 char stdio_buffer[1024]; 179 size_t len; 180 181 if (event_type & Process::eBroadcastBitSTDOUT) 182 { 183 while ((len = process.GetSTDOUT (stdio_buffer, sizeof (stdio_buffer))) > 0) 184 if (out != NULL) 185 ::fwrite (stdio_buffer, 1, len, out); 186 } 187 else if (event_type & Process::eBroadcastBitSTDERR) 188 { 189 while ((len = process.GetSTDERR (stdio_buffer, sizeof (stdio_buffer))) > 0) 190 if (out != NULL) 191 ::fwrite (stdio_buffer, 1, len, out); 192 } 193 else if (event_type & Process::eBroadcastBitStateChanged) 194 { 195 // Drain any stdout messages. 196 while ((len = process.GetSTDOUT (stdio_buffer, sizeof (stdio_buffer))) > 0) 197 if (out != NULL) 198 ::fwrite (stdio_buffer, 1, len, out); 199 200 // Drain any stderr messages. 201 while ((len = process.GetSTDERR (stdio_buffer, sizeof (stdio_buffer))) > 0) 202 if (out != NULL) 203 ::fwrite (stdio_buffer, 1, len, out); 204 205 StateType event_state = SBProcess::GetStateFromEvent (event); 206 207 if (event_state == eStateInvalid) 208 return; 209 210 bool is_stopped = StateIsStoppedState (event_state); 211 if (!is_stopped) 212 process.ReportCurrentState (event, out); 213 } 214 } 215 216 void 217 SBDebugger::UpdateCurrentThread (SBProcess &process) 218 { 219 if (process.IsValid()) 220 { 221 SBThread curr_thread = process.GetCurrentThread (); 222 SBThread thread; 223 StopReason curr_thread_stop_reason = eStopReasonInvalid; 224 if (curr_thread.IsValid()) 225 { 226 if (curr_thread.GetStopReason() != eStopReasonInvalid) 227 curr_thread_stop_reason = curr_thread.GetStopReason (); 228 } 229 230 if (! curr_thread.IsValid() 231 || curr_thread_stop_reason == eStopReasonInvalid 232 || curr_thread_stop_reason == eStopReasonNone) 233 { 234 // Prefer a thread that has just completed its plan over another thread as current thread. 235 SBThread plan_thread; 236 SBThread other_thread; 237 const size_t num_threads = process.GetNumThreads (); 238 size_t i; 239 for (i = 0; i < num_threads; ++i) 240 { 241 thread = process.GetThreadAtIndex(i); 242 if (thread.GetStopReason () != eStopReasonInvalid) 243 { 244 switch (thread.GetStopReason ()) 245 { 246 default: 247 case eStopReasonInvalid: 248 case eStopReasonNone: 249 break; 250 251 case eStopReasonTrace: 252 case eStopReasonBreakpoint: 253 case eStopReasonWatchpoint: 254 case eStopReasonSignal: 255 case eStopReasonException: 256 if (! other_thread.IsValid()) 257 other_thread = thread; 258 break; 259 case eStopReasonPlanComplete: 260 if (! plan_thread.IsValid()) 261 plan_thread = thread; 262 break; 263 } 264 } 265 } 266 if (plan_thread.IsValid()) 267 process.SetCurrentThreadByID (plan_thread.GetThreadID()); 268 else if (other_thread.IsValid()) 269 process.SetCurrentThreadByID (other_thread.GetThreadID()); 270 else 271 { 272 if (curr_thread.IsValid()) 273 thread = curr_thread; 274 else 275 thread = process.GetThreadAtIndex(0); 276 277 if (thread.IsValid()) 278 process.SetCurrentThreadByID (thread.GetThreadID()); 279 } 280 } 281 } 282 } 283 284 SBSourceManager & 285 SBDebugger::GetSourceManager () 286 { 287 static SourceManager g_lldb_source_manager; 288 static SBSourceManager g_sb_source_manager (g_lldb_source_manager); 289 return g_sb_source_manager; 290 } 291 292 293 bool 294 SBDebugger::GetDefaultArchitecture (char *arch_name, size_t arch_name_len) 295 { 296 if (arch_name && arch_name_len) 297 { 298 ArchSpec &default_arch = lldb_private::GetDefaultArchitecture (); 299 if (default_arch.IsValid()) 300 { 301 ::snprintf (arch_name, arch_name_len, "%s", default_arch.AsCString()); 302 return true; 303 } 304 } 305 if (arch_name && arch_name_len) 306 arch_name[0] = '\0'; 307 return false; 308 } 309 310 311 bool 312 SBDebugger::SetDefaultArchitecture (const char *arch_name) 313 { 314 if (arch_name) 315 { 316 ArchSpec arch (arch_name); 317 if (arch.IsValid()) 318 { 319 lldb_private::GetDefaultArchitecture () = arch; 320 return true; 321 } 322 } 323 return false; 324 } 325 326 ScriptLanguage 327 SBDebugger::GetScriptingLanguage (const char *script_language_name) 328 { 329 return Args::StringToScriptLanguage (script_language_name, 330 eScriptLanguageDefault, 331 NULL); 332 } 333 334 const char * 335 SBDebugger::GetVersionString () 336 { 337 return lldb_private::GetVersion(); 338 } 339 340 const char * 341 SBDebugger::StateAsCString (lldb::StateType state) 342 { 343 return lldb_private::StateAsCString (state); 344 } 345 346 bool 347 SBDebugger::StateIsRunningState (lldb::StateType state) 348 { 349 return lldb_private::StateIsRunningState (state); 350 } 351 352 bool 353 SBDebugger::StateIsStoppedState (lldb::StateType state) 354 { 355 return lldb_private::StateIsStoppedState (state); 356 } 357 358 359 SBTarget 360 SBDebugger::CreateTargetWithFileAndTargetTriple (const char *filename, 361 const char *target_triple) 362 { 363 SBTarget target; 364 if (m_opaque_sp) 365 { 366 ArchSpec arch; 367 FileSpec file_spec (filename); 368 arch.SetArchFromTargetTriple(target_triple); 369 TargetSP target_sp; 370 Error error (m_opaque_sp->GetTargetList().CreateTarget (*m_opaque_sp, file_spec, arch, NULL, true, target_sp)); 371 target.reset (target_sp); 372 } 373 return target; 374 } 375 376 SBTarget 377 SBDebugger::CreateTargetWithFileAndArch (const char *filename, const char *archname) 378 { 379 SBTarget target; 380 if (m_opaque_sp) 381 { 382 FileSpec file (filename); 383 ArchSpec arch = lldb_private::GetDefaultArchitecture(); 384 TargetSP target_sp; 385 Error error; 386 387 if (archname != NULL) 388 { 389 ArchSpec arch2 (archname); 390 error = m_opaque_sp->GetTargetList().CreateTarget (*m_opaque_sp, file, arch2, NULL, true, target_sp); 391 } 392 else 393 { 394 if (!arch.IsValid()) 395 arch = LLDB_ARCH_DEFAULT; 396 397 error = m_opaque_sp->GetTargetList().CreateTarget (*m_opaque_sp, file, arch, NULL, true, target_sp); 398 399 if (error.Fail()) 400 { 401 if (arch == LLDB_ARCH_DEFAULT_32BIT) 402 arch = LLDB_ARCH_DEFAULT_64BIT; 403 else 404 arch = LLDB_ARCH_DEFAULT_32BIT; 405 406 error = m_opaque_sp->GetTargetList().CreateTarget (*m_opaque_sp, file, arch, NULL, true, target_sp); 407 } 408 } 409 410 if (error.Success()) 411 { 412 m_opaque_sp->GetTargetList().SetCurrentTarget (target_sp.get()); 413 target.reset(target_sp); 414 } 415 } 416 return target; 417 } 418 419 SBTarget 420 SBDebugger::CreateTarget (const char *filename) 421 { 422 SBTarget target; 423 if (m_opaque_sp) 424 { 425 FileSpec file (filename); 426 ArchSpec arch = lldb_private::GetDefaultArchitecture(); 427 TargetSP target_sp; 428 Error error; 429 430 if (!arch.IsValid()) 431 arch = LLDB_ARCH_DEFAULT; 432 433 error = m_opaque_sp->GetTargetList().CreateTarget (*m_opaque_sp, file, arch, NULL, true, target_sp); 434 435 if (error.Fail()) 436 { 437 if (arch == LLDB_ARCH_DEFAULT_32BIT) 438 arch = LLDB_ARCH_DEFAULT_64BIT; 439 else 440 arch = LLDB_ARCH_DEFAULT_32BIT; 441 442 error = m_opaque_sp->GetTargetList().CreateTarget (*m_opaque_sp, file, arch, NULL, true, target_sp); 443 } 444 445 if (error.Success()) 446 { 447 m_opaque_sp->GetTargetList().SetCurrentTarget (target_sp.get()); 448 target.reset (target_sp); 449 } 450 } 451 return target; 452 } 453 454 SBTarget 455 SBDebugger::GetTargetAtIndex (uint32_t idx) 456 { 457 SBTarget sb_target; 458 if (m_opaque_sp) 459 sb_target.reset(m_opaque_sp->GetTargetList().GetTargetAtIndex (idx)); 460 return sb_target; 461 } 462 463 SBTarget 464 SBDebugger::FindTargetWithProcessID (pid_t pid) 465 { 466 SBTarget sb_target; 467 if (m_opaque_sp) 468 sb_target.reset(m_opaque_sp->GetTargetList().FindTargetWithProcessID (pid)); 469 return sb_target; 470 } 471 472 SBTarget 473 SBDebugger::FindTargetWithFileAndArch (const char *filename, const char *arch_name) 474 { 475 SBTarget sb_target; 476 if (m_opaque_sp && filename && filename[0]) 477 { 478 ArchSpec arch; 479 if (arch_name) 480 arch.SetArch(arch_name); 481 TargetSP target_sp (m_opaque_sp->GetTargetList().FindTargetWithExecutableAndArchitecture (FileSpec(filename), arch_name ? &arch : NULL)); 482 sb_target.reset(target_sp); 483 } 484 return sb_target; 485 } 486 487 SBTarget 488 SBDebugger::FindTargetWithLLDBProcess (const lldb::ProcessSP &process_sp) 489 { 490 SBTarget sb_target; 491 if (m_opaque_sp) 492 sb_target.reset(m_opaque_sp->GetTargetList().FindTargetWithProcess (process_sp.get())); 493 return sb_target; 494 } 495 496 497 uint32_t 498 SBDebugger::GetNumTargets () 499 { 500 if (m_opaque_sp) 501 return m_opaque_sp->GetTargetList().GetNumTargets (); 502 return 0; 503 } 504 505 SBTarget 506 SBDebugger::GetCurrentTarget () 507 { 508 SBTarget sb_target; 509 if (m_opaque_sp) 510 sb_target.reset(m_opaque_sp->GetTargetList().GetCurrentTarget ()); 511 return sb_target; 512 } 513 514 void 515 SBDebugger::DispatchInput (void *baton, const void *data, size_t data_len) 516 { 517 if (m_opaque_sp) 518 m_opaque_sp->DispatchInput ((const char *) data, data_len); 519 } 520 521 void 522 SBDebugger::PushInputReader (SBInputReader &reader) 523 { 524 if (m_opaque_sp && reader.IsValid()) 525 { 526 InputReaderSP reader_sp(*reader); 527 m_opaque_sp->PushInputReader (reader_sp); 528 } 529 } 530 531 void 532 SBDebugger::reset (const lldb::DebuggerSP &debugger_sp) 533 { 534 m_opaque_sp = debugger_sp; 535 } 536 537 Debugger * 538 SBDebugger::get () const 539 { 540 return m_opaque_sp.get(); 541 } 542 543 Debugger & 544 SBDebugger::ref () const 545 { 546 assert (m_opaque_sp.get()); 547 return *m_opaque_sp; 548 } 549 550 551 SBDebugger 552 SBDebugger::FindDebuggerWithID (int id) 553 { 554 SBDebugger sb_debugger; 555 lldb::DebuggerSP debugger_sp = Debugger::FindDebuggerWithID (id); 556 if (debugger_sp) 557 sb_debugger.reset (debugger_sp); 558 return sb_debugger; 559 } 560