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 14 #include "lldb/API/SBListener.h" 15 #include "lldb/API/SBBroadcaster.h" 16 #include "lldb/API/SBCommandInterpreter.h" 17 #include "lldb/API/SBCommandReturnObject.h" 18 #include "lldb/API/SBEvent.h" 19 #include "lldb/API/SBFrame.h" 20 #include "lldb/API/SBInputReader.h" 21 #include "lldb/API/SBProcess.h" 22 #include "lldb/API/SBSourceManager.h" 23 #include "lldb/API/SBStream.h" 24 #include "lldb/API/SBStringList.h" 25 #include "lldb/API/SBTarget.h" 26 #include "lldb/API/SBThread.h" 27 #include "lldb/Core/Debugger.h" 28 #include "lldb/Core/State.h" 29 #include "lldb/Interpreter/Args.h" 30 #include "lldb/Interpreter/CommandInterpreter.h" 31 #include "lldb/Target/Process.h" 32 #include "lldb/Target/TargetList.h" 33 34 using namespace lldb; 35 using namespace lldb_private; 36 37 void 38 SBDebugger::Initialize () 39 { 40 Debugger::Initialize(); 41 } 42 43 void 44 SBDebugger::Terminate () 45 { 46 Debugger::Terminate(); 47 } 48 49 void 50 SBDebugger::Clear () 51 { 52 m_opaque_sp.reset(); 53 } 54 55 SBDebugger 56 SBDebugger::Create() 57 { 58 SBDebugger debugger; 59 debugger.reset(Debugger::CreateInstance()); 60 return debugger; 61 } 62 63 SBDebugger::SBDebugger () : 64 m_opaque_sp () 65 { 66 } 67 68 SBDebugger::~SBDebugger () 69 { 70 } 71 72 bool 73 SBDebugger::IsValid() const 74 { 75 return m_opaque_sp.get() != NULL; 76 } 77 78 79 void 80 SBDebugger::SetAsync (bool b) 81 { 82 if (m_opaque_sp) 83 m_opaque_sp->SetAsyncExecution(b); 84 } 85 86 void 87 SBDebugger::SkipLLDBInitFiles (bool b) 88 { 89 if (m_opaque_sp) 90 m_opaque_sp->GetCommandInterpreter().SkipLLDBInitFiles (b); 91 } 92 93 // Shouldn't really be settable after initialization as this could cause lots of problems; don't want users 94 // trying to switch modes in the middle of a debugging session. 95 void 96 SBDebugger::SetInputFileHandle (FILE *fh, bool transfer_ownership) 97 { 98 if (m_opaque_sp) 99 m_opaque_sp->SetInputFileHandle (fh, transfer_ownership); 100 } 101 102 void 103 SBDebugger::SetOutputFileHandle (FILE *fh, bool transfer_ownership) 104 { 105 if (m_opaque_sp) 106 m_opaque_sp->SetOutputFileHandle (fh, transfer_ownership); 107 } 108 109 void 110 SBDebugger::SetErrorFileHandle (FILE *fh, bool transfer_ownership) 111 { 112 if (m_opaque_sp) 113 m_opaque_sp->SetErrorFileHandle (fh, transfer_ownership); 114 } 115 116 FILE * 117 SBDebugger::GetInputFileHandle () 118 { 119 if (m_opaque_sp) 120 return m_opaque_sp->GetInputFileHandle(); 121 return NULL; 122 } 123 124 FILE * 125 SBDebugger::GetOutputFileHandle () 126 { 127 if (m_opaque_sp) 128 return m_opaque_sp->GetOutputFileHandle(); 129 return NULL; 130 } 131 132 FILE * 133 SBDebugger::GetErrorFileHandle () 134 { 135 if (m_opaque_sp) 136 return m_opaque_sp->GetErrorFileHandle(); 137 return NULL; 138 } 139 140 SBCommandInterpreter 141 SBDebugger::GetCommandInterpreter () 142 { 143 SBCommandInterpreter sb_interpreter; 144 if (m_opaque_sp) 145 sb_interpreter.reset (&m_opaque_sp->GetCommandInterpreter()); 146 return sb_interpreter; 147 } 148 149 void 150 SBDebugger::HandleCommand (const char *command) 151 { 152 if (m_opaque_sp) 153 { 154 SBCommandInterpreter sb_interpreter(GetCommandInterpreter ()); 155 SBCommandReturnObject result; 156 157 sb_interpreter.HandleCommand (command, result, false); 158 159 if (GetErrorFileHandle() != NULL) 160 result.PutError (GetErrorFileHandle()); 161 if (GetOutputFileHandle() != NULL) 162 result.PutOutput (GetOutputFileHandle()); 163 164 if (m_opaque_sp->GetAsyncExecution() == false) 165 { 166 SBProcess process(GetCommandInterpreter().GetProcess ()); 167 if (process.IsValid()) 168 { 169 EventSP event_sp; 170 Listener &lldb_listener = m_opaque_sp->GetListener(); 171 while (lldb_listener.GetNextEventForBroadcaster (process.get(), event_sp)) 172 { 173 SBEvent event(event_sp); 174 HandleProcessEvent (process, event, GetOutputFileHandle(), GetErrorFileHandle()); 175 } 176 } 177 } 178 } 179 } 180 181 SBListener 182 SBDebugger::GetListener () 183 { 184 SBListener sb_listener; 185 if (m_opaque_sp) 186 sb_listener.reset(&m_opaque_sp->GetListener(), false); 187 return sb_listener; 188 } 189 190 void 191 SBDebugger::HandleProcessEvent (const SBProcess &process, const SBEvent &event, FILE *out, FILE *err) 192 { 193 const uint32_t event_type = event.GetType(); 194 char stdio_buffer[1024]; 195 size_t len; 196 197 if (event_type & Process::eBroadcastBitSTDOUT) 198 { 199 while ((len = process.GetSTDOUT (stdio_buffer, sizeof (stdio_buffer))) > 0) 200 if (out != NULL) 201 ::fwrite (stdio_buffer, 1, len, out); 202 } 203 else if (event_type & Process::eBroadcastBitSTDERR) 204 { 205 while ((len = process.GetSTDERR (stdio_buffer, sizeof (stdio_buffer))) > 0) 206 if (out != NULL) 207 ::fwrite (stdio_buffer, 1, len, out); 208 } 209 else if (event_type & Process::eBroadcastBitStateChanged) 210 { 211 // Drain any stdout messages. 212 while ((len = process.GetSTDOUT (stdio_buffer, sizeof (stdio_buffer))) > 0) 213 if (out != NULL) 214 ::fwrite (stdio_buffer, 1, len, out); 215 216 // Drain any stderr messages. 217 while ((len = process.GetSTDERR (stdio_buffer, sizeof (stdio_buffer))) > 0) 218 if (out != NULL) 219 ::fwrite (stdio_buffer, 1, len, out); 220 221 StateType event_state = SBProcess::GetStateFromEvent (event); 222 223 if (event_state == eStateInvalid) 224 return; 225 226 bool is_stopped = StateIsStoppedState (event_state); 227 if (!is_stopped) 228 process.ReportEventState (event, out); 229 } 230 } 231 232 void 233 SBDebugger::UpdateSelectedThread (SBProcess &process) 234 { 235 if (process.IsValid()) 236 { 237 SBThread curr_thread = process.GetSelectedThread (); 238 SBThread thread; 239 StopReason curr_thread_stop_reason = eStopReasonInvalid; 240 if (curr_thread.IsValid()) 241 { 242 if (curr_thread.GetStopReason() != eStopReasonInvalid) 243 curr_thread_stop_reason = curr_thread.GetStopReason (); 244 } 245 246 if (! curr_thread.IsValid() 247 || curr_thread_stop_reason == eStopReasonInvalid 248 || curr_thread_stop_reason == eStopReasonNone) 249 { 250 // Prefer a thread that has just completed its plan over another thread as current thread. 251 SBThread plan_thread; 252 SBThread other_thread; 253 const size_t num_threads = process.GetNumThreads (); 254 size_t i; 255 for (i = 0; i < num_threads; ++i) 256 { 257 thread = process.GetThreadAtIndex(i); 258 if (thread.GetStopReason () != eStopReasonInvalid) 259 { 260 switch (thread.GetStopReason ()) 261 { 262 default: 263 case eStopReasonInvalid: 264 case eStopReasonNone: 265 break; 266 267 case eStopReasonTrace: 268 case eStopReasonBreakpoint: 269 case eStopReasonWatchpoint: 270 case eStopReasonSignal: 271 case eStopReasonException: 272 if (! other_thread.IsValid()) 273 other_thread = thread; 274 break; 275 case eStopReasonPlanComplete: 276 if (! plan_thread.IsValid()) 277 plan_thread = thread; 278 break; 279 } 280 } 281 } 282 if (plan_thread.IsValid()) 283 process.SetSelectedThreadByID (plan_thread.GetThreadID()); 284 else if (other_thread.IsValid()) 285 process.SetSelectedThreadByID (other_thread.GetThreadID()); 286 else 287 { 288 if (curr_thread.IsValid()) 289 thread = curr_thread; 290 else 291 thread = process.GetThreadAtIndex(0); 292 293 if (thread.IsValid()) 294 process.SetSelectedThreadByID (thread.GetThreadID()); 295 } 296 } 297 } 298 } 299 300 SBSourceManager & 301 SBDebugger::GetSourceManager () 302 { 303 static SourceManager g_lldb_source_manager; 304 static SBSourceManager g_sb_source_manager (g_lldb_source_manager); 305 return g_sb_source_manager; 306 } 307 308 309 bool 310 SBDebugger::GetDefaultArchitecture (char *arch_name, size_t arch_name_len) 311 { 312 if (arch_name && arch_name_len) 313 { 314 ArchSpec default_arch = lldb_private::Target::GetDefaultArchitecture (); 315 316 if (default_arch.IsValid()) 317 { 318 ::snprintf (arch_name, arch_name_len, "%s", default_arch.AsCString()); 319 return true; 320 } 321 } 322 if (arch_name && arch_name_len) 323 arch_name[0] = '\0'; 324 return false; 325 } 326 327 328 bool 329 SBDebugger::SetDefaultArchitecture (const char *arch_name) 330 { 331 if (arch_name) 332 { 333 ArchSpec arch (arch_name); 334 if (arch.IsValid()) 335 { 336 lldb_private::Target::SetDefaultArchitecture (arch); 337 return true; 338 } 339 } 340 return false; 341 } 342 343 ScriptLanguage 344 SBDebugger::GetScriptingLanguage (const char *script_language_name) 345 { 346 return Args::StringToScriptLanguage (script_language_name, 347 eScriptLanguageDefault, 348 NULL); 349 } 350 351 const char * 352 SBDebugger::GetVersionString () 353 { 354 return lldb_private::GetVersion(); 355 } 356 357 const char * 358 SBDebugger::StateAsCString (lldb::StateType state) 359 { 360 return lldb_private::StateAsCString (state); 361 } 362 363 bool 364 SBDebugger::StateIsRunningState (lldb::StateType state) 365 { 366 return lldb_private::StateIsRunningState (state); 367 } 368 369 bool 370 SBDebugger::StateIsStoppedState (lldb::StateType state) 371 { 372 return lldb_private::StateIsStoppedState (state); 373 } 374 375 376 SBTarget 377 SBDebugger::CreateTargetWithFileAndTargetTriple (const char *filename, 378 const char *target_triple) 379 { 380 SBTarget target; 381 if (m_opaque_sp) 382 { 383 ArchSpec arch; 384 FileSpec file_spec (filename, true); 385 arch.SetArchFromTargetTriple(target_triple); 386 TargetSP target_sp; 387 Error error (m_opaque_sp->GetTargetList().CreateTarget (*m_opaque_sp, file_spec, arch, NULL, true, target_sp)); 388 target.reset (target_sp); 389 } 390 return target; 391 } 392 393 SBTarget 394 SBDebugger::CreateTargetWithFileAndArch (const char *filename, const char *archname) 395 { 396 SBTarget target; 397 if (m_opaque_sp) 398 { 399 FileSpec file (filename, true); 400 ArchSpec arch = lldb_private::Target::GetDefaultArchitecture (); 401 TargetSP target_sp; 402 Error error; 403 404 if (archname != NULL) 405 { 406 ArchSpec arch2 (archname); 407 error = m_opaque_sp->GetTargetList().CreateTarget (*m_opaque_sp, file, arch2, NULL, true, target_sp); 408 } 409 else 410 { 411 if (!arch.IsValid()) 412 arch = LLDB_ARCH_DEFAULT; 413 414 error = m_opaque_sp->GetTargetList().CreateTarget (*m_opaque_sp, file, arch, NULL, true, target_sp); 415 416 if (error.Fail()) 417 { 418 if (arch == LLDB_ARCH_DEFAULT_32BIT) 419 arch = LLDB_ARCH_DEFAULT_64BIT; 420 else 421 arch = LLDB_ARCH_DEFAULT_32BIT; 422 423 error = m_opaque_sp->GetTargetList().CreateTarget (*m_opaque_sp, file, arch, NULL, true, target_sp); 424 } 425 } 426 427 if (error.Success()) 428 { 429 m_opaque_sp->GetTargetList().SetSelectedTarget (target_sp.get()); 430 target.reset(target_sp); 431 } 432 } 433 return target; 434 } 435 436 SBTarget 437 SBDebugger::CreateTarget (const char *filename) 438 { 439 SBTarget target; 440 if (m_opaque_sp) 441 { 442 FileSpec file (filename, true); 443 ArchSpec arch = lldb_private::Target::GetDefaultArchitecture (); 444 TargetSP target_sp; 445 Error error; 446 447 if (!arch.IsValid()) 448 arch = LLDB_ARCH_DEFAULT; 449 450 error = m_opaque_sp->GetTargetList().CreateTarget (*m_opaque_sp, file, arch, NULL, true, target_sp); 451 452 if (error.Fail()) 453 { 454 if (arch == LLDB_ARCH_DEFAULT_32BIT) 455 arch = LLDB_ARCH_DEFAULT_64BIT; 456 else 457 arch = LLDB_ARCH_DEFAULT_32BIT; 458 459 error = m_opaque_sp->GetTargetList().CreateTarget (*m_opaque_sp, file, arch, NULL, true, target_sp); 460 } 461 462 if (error.Success()) 463 { 464 m_opaque_sp->GetTargetList().SetSelectedTarget (target_sp.get()); 465 target.reset (target_sp); 466 } 467 } 468 return target; 469 } 470 471 SBTarget 472 SBDebugger::GetTargetAtIndex (uint32_t idx) 473 { 474 SBTarget sb_target; 475 if (m_opaque_sp) 476 sb_target.reset(m_opaque_sp->GetTargetList().GetTargetAtIndex (idx)); 477 return sb_target; 478 } 479 480 SBTarget 481 SBDebugger::FindTargetWithProcessID (pid_t pid) 482 { 483 SBTarget sb_target; 484 if (m_opaque_sp) 485 sb_target.reset(m_opaque_sp->GetTargetList().FindTargetWithProcessID (pid)); 486 return sb_target; 487 } 488 489 SBTarget 490 SBDebugger::FindTargetWithFileAndArch (const char *filename, const char *arch_name) 491 { 492 SBTarget sb_target; 493 if (m_opaque_sp && filename && filename[0]) 494 { 495 ArchSpec arch; 496 if (arch_name) 497 arch.SetArch(arch_name); 498 TargetSP target_sp (m_opaque_sp->GetTargetList().FindTargetWithExecutableAndArchitecture (FileSpec(filename, false), arch_name ? &arch : NULL)); 499 sb_target.reset(target_sp); 500 } 501 return sb_target; 502 } 503 504 SBTarget 505 SBDebugger::FindTargetWithLLDBProcess (const lldb::ProcessSP &process_sp) 506 { 507 SBTarget sb_target; 508 if (m_opaque_sp) 509 sb_target.reset(m_opaque_sp->GetTargetList().FindTargetWithProcess (process_sp.get())); 510 return sb_target; 511 } 512 513 514 uint32_t 515 SBDebugger::GetNumTargets () 516 { 517 if (m_opaque_sp) 518 return m_opaque_sp->GetTargetList().GetNumTargets (); 519 return 0; 520 } 521 522 SBTarget 523 SBDebugger::GetSelectedTarget () 524 { 525 SBTarget sb_target; 526 if (m_opaque_sp) 527 sb_target.reset(m_opaque_sp->GetTargetList().GetSelectedTarget ()); 528 return sb_target; 529 } 530 531 void 532 SBDebugger::DispatchInput (void *baton, const void *data, size_t data_len) 533 { 534 if (m_opaque_sp) 535 m_opaque_sp->DispatchInput ((const char *) data, data_len); 536 } 537 538 void 539 SBDebugger::PushInputReader (SBInputReader &reader) 540 { 541 if (m_opaque_sp && reader.IsValid()) 542 { 543 InputReaderSP reader_sp(*reader); 544 m_opaque_sp->PushInputReader (reader_sp); 545 } 546 } 547 548 void 549 SBDebugger::reset (const lldb::DebuggerSP &debugger_sp) 550 { 551 m_opaque_sp = debugger_sp; 552 } 553 554 Debugger * 555 SBDebugger::get () const 556 { 557 return m_opaque_sp.get(); 558 } 559 560 Debugger & 561 SBDebugger::ref () const 562 { 563 assert (m_opaque_sp.get()); 564 return *m_opaque_sp; 565 } 566 567 568 SBDebugger 569 SBDebugger::FindDebuggerWithID (int id) 570 { 571 SBDebugger sb_debugger; 572 lldb::DebuggerSP debugger_sp = Debugger::FindDebuggerWithID (id); 573 if (debugger_sp) 574 sb_debugger.reset (debugger_sp); 575 return sb_debugger; 576 } 577 578 const char * 579 SBDebugger::GetInstanceName() 580 { 581 if (m_opaque_sp) 582 return m_opaque_sp->GetInstanceName().AsCString(); 583 else 584 return NULL; 585 } 586 587 SBError 588 SBDebugger::SetInternalVariable (const char *var_name, const char *value, const char *debugger_instance_name) 589 { 590 lldb::UserSettingsControllerSP root_settings_controller = lldb_private::Debugger::GetSettingsController(); 591 592 Error err = root_settings_controller->SetVariable (var_name, value, lldb::eVarSetOperationAssign, true, 593 debugger_instance_name); 594 SBError sb_error; 595 sb_error.SetError (err); 596 597 return sb_error; 598 } 599 600 lldb::SBStringList 601 SBDebugger::GetInternalVariableValue (const char *var_name, const char *debugger_instance_name) 602 { 603 SBStringList ret_value; 604 lldb::SettableVariableType var_type; 605 lldb_private:Error err; 606 607 lldb::UserSettingsControllerSP root_settings_controller = lldb_private::Debugger::GetSettingsController(); 608 609 StringList value = root_settings_controller->GetVariable (var_name, var_type, debugger_instance_name, err); 610 611 if (err.Success()) 612 { 613 for (unsigned i = 0; i != value.GetSize(); ++i) 614 ret_value.AppendString (value.GetStringAtIndex(i)); 615 } 616 else 617 { 618 ret_value.AppendString (err.AsCString()); 619 } 620 621 622 return ret_value; 623 } 624 625 uint32_t 626 SBDebugger::GetTerminalWidth () const 627 { 628 if (m_opaque_sp) 629 return m_opaque_sp->GetTerminalWidth (); 630 return 0; 631 } 632 633 void 634 SBDebugger::SetTerminalWidth (uint32_t term_width) 635 { 636 if (m_opaque_sp) 637 m_opaque_sp->SetTerminalWidth (term_width); 638 } 639 640 const char * 641 SBDebugger::GetPrompt() const 642 { 643 if (m_opaque_sp) 644 return m_opaque_sp->GetPrompt (); 645 return 0; 646 } 647 648 void 649 SBDebugger::SetPrompt (const char *prompt) 650 { 651 if (m_opaque_sp) 652 m_opaque_sp->SetPrompt (prompt); 653 } 654 655 656 lldb::ScriptLanguage 657 SBDebugger::GetScriptLanguage() const 658 { 659 if (m_opaque_sp) 660 return m_opaque_sp->GetScriptLanguage (); 661 return eScriptLanguageNone; 662 } 663 664 void 665 SBDebugger::SetScriptLanguage (lldb::ScriptLanguage script_lang) 666 { 667 if (m_opaque_sp) 668 m_opaque_sp->SetScriptLanguage (script_lang); 669 } 670 671 672 673 674 bool 675 SBDebugger::SetUseExternalEditor (bool value) 676 { 677 if (m_opaque_sp) 678 return m_opaque_sp->SetUseExternalEditor (value); 679 else 680 return false; 681 } 682 683 bool 684 SBDebugger::GetUseExternalEditor () 685 { 686 if (m_opaque_sp) 687 return m_opaque_sp->GetUseExternalEditor (); 688 else 689 return false; 690 } 691 692 bool 693 SBDebugger::GetDescription (SBStream &description) 694 { 695 if (m_opaque_sp) 696 { 697 const char *name = m_opaque_sp->GetInstanceName().AsCString(); 698 lldb::user_id_t id = m_opaque_sp->GetID(); 699 description.Printf ("Debugger (instance: '%s', id: %d)", name, id); 700 } 701 else 702 description.Printf ("No value"); 703 704 return true; 705 } 706