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 // C Includes 11 // C++ Includes 12 // Other libraries and framework includes 13 // Project includes 14 15 #include "SystemInitializerFull.h" 16 17 #include "lldb/API/SBDebugger.h" 18 19 #include "lldb/lldb-private.h" 20 21 #include "lldb/API/SBBroadcaster.h" 22 #include "lldb/API/SBCommandInterpreter.h" 23 #include "lldb/API/SBCommandReturnObject.h" 24 #include "lldb/API/SBError.h" 25 #include "lldb/API/SBEvent.h" 26 #include "lldb/API/SBFrame.h" 27 #include "lldb/API/SBListener.h" 28 #include "lldb/API/SBProcess.h" 29 #include "lldb/API/SBSourceManager.h" 30 #include "lldb/API/SBStream.h" 31 #include "lldb/API/SBStringList.h" 32 #include "lldb/API/SBStructuredData.h" 33 #include "lldb/API/SBTarget.h" 34 #include "lldb/API/SBThread.h" 35 #include "lldb/API/SBTypeCategory.h" 36 #include "lldb/API/SBTypeFilter.h" 37 #include "lldb/API/SBTypeFormat.h" 38 #include "lldb/API/SBTypeNameSpecifier.h" 39 #include "lldb/API/SBTypeSummary.h" 40 #include "lldb/API/SBTypeSynthetic.h" 41 42 #include "lldb/Core/Debugger.h" 43 #include "lldb/Core/PluginManager.h" 44 #include "lldb/Core/StreamFile.h" 45 #include "lldb/Core/StructuredDataImpl.h" 46 #include "lldb/DataFormatters/DataVisualization.h" 47 #include "lldb/Host/XML.h" 48 #include "lldb/Initialization/SystemLifetimeManager.h" 49 #include "lldb/Interpreter/CommandInterpreter.h" 50 #include "lldb/Interpreter/OptionArgParser.h" 51 #include "lldb/Interpreter/OptionGroupPlatform.h" 52 #include "lldb/Target/Process.h" 53 #include "lldb/Target/TargetList.h" 54 #include "lldb/Utility/Args.h" 55 #include "lldb/Utility/State.h" 56 57 #include "llvm/ADT/STLExtras.h" 58 #include "llvm/ADT/StringRef.h" 59 #include "llvm/Support/DynamicLibrary.h" 60 #include "llvm/Support/ManagedStatic.h" 61 62 using namespace lldb; 63 using namespace lldb_private; 64 65 static llvm::sys::DynamicLibrary LoadPlugin(const lldb::DebuggerSP &debugger_sp, 66 const FileSpec &spec, 67 Status &error) { 68 llvm::sys::DynamicLibrary dynlib = 69 llvm::sys::DynamicLibrary::getPermanentLibrary(spec.GetPath().c_str()); 70 if (dynlib.isValid()) { 71 typedef bool (*LLDBCommandPluginInit)(lldb::SBDebugger & debugger); 72 73 lldb::SBDebugger debugger_sb(debugger_sp); 74 // This calls the bool lldb::PluginInitialize(lldb::SBDebugger debugger) 75 // function. 76 // TODO: mangle this differently for your system - on OSX, the first 77 // underscore needs to be removed and the second one stays 78 LLDBCommandPluginInit init_func = 79 (LLDBCommandPluginInit)(uintptr_t)dynlib.getAddressOfSymbol( 80 "_ZN4lldb16PluginInitializeENS_10SBDebuggerE"); 81 if (init_func) { 82 if (init_func(debugger_sb)) 83 return dynlib; 84 else 85 error.SetErrorString("plug-in refused to load " 86 "(lldb::PluginInitialize(lldb::SBDebugger) " 87 "returned false)"); 88 } else { 89 error.SetErrorString("plug-in is missing the required initialization: " 90 "lldb::PluginInitialize(lldb::SBDebugger)"); 91 } 92 } else { 93 if (spec.Exists()) 94 error.SetErrorString("this file does not represent a loadable dylib"); 95 else 96 error.SetErrorString("no such file"); 97 } 98 return llvm::sys::DynamicLibrary(); 99 } 100 101 static llvm::ManagedStatic<SystemLifetimeManager> g_debugger_lifetime; 102 103 SBError SBInputReader::Initialize( 104 lldb::SBDebugger &sb_debugger, 105 unsigned long (*)(void *, lldb::SBInputReader *, lldb::InputReaderAction, 106 char const *, unsigned long), 107 void *, lldb::InputReaderGranularity, char const *, char const *, bool) { 108 return SBError(); 109 } 110 111 void SBInputReader::SetIsDone(bool) {} 112 113 bool SBInputReader::IsActive() const { return false; } 114 115 SBDebugger::SBDebugger() = default; 116 117 SBDebugger::SBDebugger(const lldb::DebuggerSP &debugger_sp) 118 : m_opaque_sp(debugger_sp) {} 119 120 SBDebugger::SBDebugger(const SBDebugger &rhs) : m_opaque_sp(rhs.m_opaque_sp) {} 121 122 SBDebugger::~SBDebugger() = default; 123 124 SBDebugger &SBDebugger::operator=(const SBDebugger &rhs) { 125 if (this != &rhs) { 126 m_opaque_sp = rhs.m_opaque_sp; 127 } 128 return *this; 129 } 130 131 void SBDebugger::Initialize() { 132 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 133 134 if (log) 135 log->Printf("SBDebugger::Initialize ()"); 136 137 g_debugger_lifetime->Initialize(llvm::make_unique<SystemInitializerFull>(), 138 LoadPlugin); 139 } 140 141 void SBDebugger::Terminate() { g_debugger_lifetime->Terminate(); } 142 143 void SBDebugger::Clear() { 144 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 145 146 if (log) 147 log->Printf("SBDebugger(%p)::Clear ()", 148 static_cast<void *>(m_opaque_sp.get())); 149 150 if (m_opaque_sp) 151 m_opaque_sp->ClearIOHandlers(); 152 153 m_opaque_sp.reset(); 154 } 155 156 SBDebugger SBDebugger::Create() { 157 return SBDebugger::Create(false, nullptr, nullptr); 158 } 159 160 SBDebugger SBDebugger::Create(bool source_init_files) { 161 return SBDebugger::Create(source_init_files, nullptr, nullptr); 162 } 163 164 SBDebugger SBDebugger::Create(bool source_init_files, 165 lldb::LogOutputCallback callback, void *baton) 166 167 { 168 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 169 170 SBDebugger debugger; 171 172 // Currently we have issues if this function is called simultaneously on two 173 // different threads. The issues mainly revolve around the fact that the 174 // lldb_private::FormatManager uses global collections and having two threads 175 // parsing the .lldbinit files can cause mayhem. So to get around this for 176 // now we need to use a mutex to prevent bad things from happening. 177 static std::recursive_mutex g_mutex; 178 std::lock_guard<std::recursive_mutex> guard(g_mutex); 179 180 debugger.reset(Debugger::CreateInstance(callback, baton)); 181 182 if (log) { 183 SBStream sstr; 184 debugger.GetDescription(sstr); 185 log->Printf("SBDebugger::Create () => SBDebugger(%p): %s", 186 static_cast<void *>(debugger.m_opaque_sp.get()), 187 sstr.GetData()); 188 } 189 190 SBCommandInterpreter interp = debugger.GetCommandInterpreter(); 191 if (source_init_files) { 192 interp.get()->SkipLLDBInitFiles(false); 193 interp.get()->SkipAppInitFiles(false); 194 SBCommandReturnObject result; 195 interp.SourceInitFileInHomeDirectory(result); 196 } else { 197 interp.get()->SkipLLDBInitFiles(true); 198 interp.get()->SkipAppInitFiles(true); 199 } 200 return debugger; 201 } 202 203 void SBDebugger::Destroy(SBDebugger &debugger) { 204 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 205 206 if (log) { 207 SBStream sstr; 208 debugger.GetDescription(sstr); 209 log->Printf("SBDebugger::Destroy () => SBDebugger(%p): %s", 210 static_cast<void *>(debugger.m_opaque_sp.get()), 211 sstr.GetData()); 212 } 213 214 Debugger::Destroy(debugger.m_opaque_sp); 215 216 if (debugger.m_opaque_sp.get() != nullptr) 217 debugger.m_opaque_sp.reset(); 218 } 219 220 void SBDebugger::MemoryPressureDetected() { 221 // Since this function can be call asynchronously, we allow it to be non- 222 // mandatory. We have seen deadlocks with this function when called so we 223 // need to safeguard against this until we can determine what is causing the 224 // deadlocks. 225 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 226 227 const bool mandatory = false; 228 if (log) { 229 log->Printf("SBDebugger::MemoryPressureDetected (), mandatory = %d", 230 mandatory); 231 } 232 233 ModuleList::RemoveOrphanSharedModules(mandatory); 234 } 235 236 bool SBDebugger::IsValid() const { return m_opaque_sp.get() != nullptr; } 237 238 void SBDebugger::SetAsync(bool b) { 239 if (m_opaque_sp) 240 m_opaque_sp->SetAsyncExecution(b); 241 } 242 243 bool SBDebugger::GetAsync() { 244 return (m_opaque_sp ? m_opaque_sp->GetAsyncExecution() : false); 245 } 246 247 void SBDebugger::SkipLLDBInitFiles(bool b) { 248 if (m_opaque_sp) 249 m_opaque_sp->GetCommandInterpreter().SkipLLDBInitFiles(b); 250 } 251 252 void SBDebugger::SkipAppInitFiles(bool b) { 253 if (m_opaque_sp) 254 m_opaque_sp->GetCommandInterpreter().SkipAppInitFiles(b); 255 } 256 257 // Shouldn't really be settable after initialization as this could cause lots 258 // of problems; don't want users trying to switch modes in the middle of a 259 // debugging session. 260 void SBDebugger::SetInputFileHandle(FILE *fh, bool transfer_ownership) { 261 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 262 263 if (log) 264 log->Printf( 265 "SBDebugger(%p)::SetInputFileHandle (fh=%p, transfer_ownership=%i)", 266 static_cast<void *>(m_opaque_sp.get()), static_cast<void *>(fh), 267 transfer_ownership); 268 269 if (m_opaque_sp) 270 m_opaque_sp->SetInputFileHandle(fh, transfer_ownership); 271 } 272 273 void SBDebugger::SetOutputFileHandle(FILE *fh, bool transfer_ownership) { 274 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 275 276 if (log) 277 log->Printf( 278 "SBDebugger(%p)::SetOutputFileHandle (fh=%p, transfer_ownership=%i)", 279 static_cast<void *>(m_opaque_sp.get()), static_cast<void *>(fh), 280 transfer_ownership); 281 282 if (m_opaque_sp) 283 m_opaque_sp->SetOutputFileHandle(fh, transfer_ownership); 284 } 285 286 void SBDebugger::SetErrorFileHandle(FILE *fh, bool transfer_ownership) { 287 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 288 289 if (log) 290 log->Printf( 291 "SBDebugger(%p)::SetErrorFileHandle (fh=%p, transfer_ownership=%i)", 292 static_cast<void *>(m_opaque_sp.get()), static_cast<void *>(fh), 293 transfer_ownership); 294 295 if (m_opaque_sp) 296 m_opaque_sp->SetErrorFileHandle(fh, transfer_ownership); 297 } 298 299 FILE *SBDebugger::GetInputFileHandle() { 300 if (m_opaque_sp) { 301 StreamFileSP stream_file_sp(m_opaque_sp->GetInputFile()); 302 if (stream_file_sp) 303 return stream_file_sp->GetFile().GetStream(); 304 } 305 return nullptr; 306 } 307 308 FILE *SBDebugger::GetOutputFileHandle() { 309 if (m_opaque_sp) { 310 StreamFileSP stream_file_sp(m_opaque_sp->GetOutputFile()); 311 if (stream_file_sp) 312 return stream_file_sp->GetFile().GetStream(); 313 } 314 return nullptr; 315 } 316 317 FILE *SBDebugger::GetErrorFileHandle() { 318 if (m_opaque_sp) { 319 StreamFileSP stream_file_sp(m_opaque_sp->GetErrorFile()); 320 if (stream_file_sp) 321 return stream_file_sp->GetFile().GetStream(); 322 } 323 return nullptr; 324 } 325 326 void SBDebugger::SaveInputTerminalState() { 327 if (m_opaque_sp) 328 m_opaque_sp->SaveInputTerminalState(); 329 } 330 331 void SBDebugger::RestoreInputTerminalState() { 332 if (m_opaque_sp) 333 m_opaque_sp->RestoreInputTerminalState(); 334 } 335 SBCommandInterpreter SBDebugger::GetCommandInterpreter() { 336 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 337 338 SBCommandInterpreter sb_interpreter; 339 if (m_opaque_sp) 340 sb_interpreter.reset(&m_opaque_sp->GetCommandInterpreter()); 341 342 if (log) 343 log->Printf( 344 "SBDebugger(%p)::GetCommandInterpreter () => SBCommandInterpreter(%p)", 345 static_cast<void *>(m_opaque_sp.get()), 346 static_cast<void *>(sb_interpreter.get())); 347 348 return sb_interpreter; 349 } 350 351 void SBDebugger::HandleCommand(const char *command) { 352 if (m_opaque_sp) { 353 TargetSP target_sp(m_opaque_sp->GetSelectedTarget()); 354 std::unique_lock<std::recursive_mutex> lock; 355 if (target_sp) 356 lock = std::unique_lock<std::recursive_mutex>(target_sp->GetAPIMutex()); 357 358 SBCommandInterpreter sb_interpreter(GetCommandInterpreter()); 359 SBCommandReturnObject result; 360 361 sb_interpreter.HandleCommand(command, result, false); 362 363 if (GetErrorFileHandle() != nullptr) 364 result.PutError(GetErrorFileHandle()); 365 if (GetOutputFileHandle() != nullptr) 366 result.PutOutput(GetOutputFileHandle()); 367 368 if (!m_opaque_sp->GetAsyncExecution()) { 369 SBProcess process(GetCommandInterpreter().GetProcess()); 370 ProcessSP process_sp(process.GetSP()); 371 if (process_sp) { 372 EventSP event_sp; 373 ListenerSP lldb_listener_sp = m_opaque_sp->GetListener(); 374 while (lldb_listener_sp->GetEventForBroadcaster( 375 process_sp.get(), event_sp, std::chrono::seconds(0))) { 376 SBEvent event(event_sp); 377 HandleProcessEvent(process, event, GetOutputFileHandle(), 378 GetErrorFileHandle()); 379 } 380 } 381 } 382 } 383 } 384 385 SBListener SBDebugger::GetListener() { 386 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 387 388 SBListener sb_listener; 389 if (m_opaque_sp) 390 sb_listener.reset(m_opaque_sp->GetListener()); 391 392 if (log) 393 log->Printf("SBDebugger(%p)::GetListener () => SBListener(%p)", 394 static_cast<void *>(m_opaque_sp.get()), 395 static_cast<void *>(sb_listener.get())); 396 397 return sb_listener; 398 } 399 400 void SBDebugger::HandleProcessEvent(const SBProcess &process, 401 const SBEvent &event, FILE *out, 402 FILE *err) { 403 if (!process.IsValid()) 404 return; 405 406 TargetSP target_sp(process.GetTarget().GetSP()); 407 if (!target_sp) 408 return; 409 410 const uint32_t event_type = event.GetType(); 411 char stdio_buffer[1024]; 412 size_t len; 413 414 std::lock_guard<std::recursive_mutex> guard(target_sp->GetAPIMutex()); 415 416 if (event_type & 417 (Process::eBroadcastBitSTDOUT | Process::eBroadcastBitStateChanged)) { 418 // Drain stdout when we stop just in case we have any bytes 419 while ((len = process.GetSTDOUT(stdio_buffer, sizeof(stdio_buffer))) > 0) 420 if (out != nullptr) 421 ::fwrite(stdio_buffer, 1, len, out); 422 } 423 424 if (event_type & 425 (Process::eBroadcastBitSTDERR | Process::eBroadcastBitStateChanged)) { 426 // Drain stderr when we stop just in case we have any bytes 427 while ((len = process.GetSTDERR(stdio_buffer, sizeof(stdio_buffer))) > 0) 428 if (err != nullptr) 429 ::fwrite(stdio_buffer, 1, len, err); 430 } 431 432 if (event_type & Process::eBroadcastBitStateChanged) { 433 StateType event_state = SBProcess::GetStateFromEvent(event); 434 435 if (event_state == eStateInvalid) 436 return; 437 438 bool is_stopped = StateIsStoppedState(event_state); 439 if (!is_stopped) 440 process.ReportEventState(event, out); 441 } 442 } 443 444 SBSourceManager SBDebugger::GetSourceManager() { 445 SBSourceManager sb_source_manager(*this); 446 return sb_source_manager; 447 } 448 449 bool SBDebugger::GetDefaultArchitecture(char *arch_name, size_t arch_name_len) { 450 if (arch_name && arch_name_len) { 451 ArchSpec default_arch = Target::GetDefaultArchitecture(); 452 453 if (default_arch.IsValid()) { 454 const std::string &triple_str = default_arch.GetTriple().str(); 455 if (!triple_str.empty()) 456 ::snprintf(arch_name, arch_name_len, "%s", triple_str.c_str()); 457 else 458 ::snprintf(arch_name, arch_name_len, "%s", 459 default_arch.GetArchitectureName()); 460 return true; 461 } 462 } 463 if (arch_name && arch_name_len) 464 arch_name[0] = '\0'; 465 return false; 466 } 467 468 bool SBDebugger::SetDefaultArchitecture(const char *arch_name) { 469 if (arch_name) { 470 ArchSpec arch(arch_name); 471 if (arch.IsValid()) { 472 Target::SetDefaultArchitecture(arch); 473 return true; 474 } 475 } 476 return false; 477 } 478 479 ScriptLanguage 480 SBDebugger::GetScriptingLanguage(const char *script_language_name) { 481 if (!script_language_name) return eScriptLanguageDefault; 482 return OptionArgParser::ToScriptLanguage( 483 llvm::StringRef(script_language_name), eScriptLanguageDefault, nullptr); 484 } 485 486 const char *SBDebugger::GetVersionString() { 487 return lldb_private::GetVersion(); 488 } 489 490 const char *SBDebugger::StateAsCString(StateType state) { 491 return lldb_private::StateAsCString(state); 492 } 493 494 static void AddBoolConfigEntry(StructuredData::Dictionary &dict, 495 llvm::StringRef name, bool value, 496 llvm::StringRef description) { 497 auto entry_up = llvm::make_unique<StructuredData::Dictionary>(); 498 entry_up->AddBooleanItem("value", value); 499 entry_up->AddStringItem("description", description); 500 dict.AddItem(name, std::move(entry_up)); 501 } 502 503 static void AddLLVMTargets(StructuredData::Dictionary &dict) { 504 auto array_up = llvm::make_unique<StructuredData::Array>(); 505 #define LLVM_TARGET(target) \ 506 array_up->AddItem(llvm::make_unique<StructuredData::String>(#target)); 507 #include "llvm/Config/Targets.def" 508 auto entry_up = llvm::make_unique<StructuredData::Dictionary>(); 509 entry_up->AddItem("value", std::move(array_up)); 510 entry_up->AddStringItem("description", "A list of configured LLVM targets."); 511 dict.AddItem("targets", std::move(entry_up)); 512 } 513 514 SBStructuredData SBDebugger::GetBuildConfiguration() { 515 auto config_up = llvm::make_unique<StructuredData::Dictionary>(); 516 AddBoolConfigEntry( 517 *config_up, "xml", XMLDocument::XMLEnabled(), 518 "A boolean value that indicates if XML support is enabled in LLDB"); 519 AddLLVMTargets(*config_up); 520 521 SBStructuredData data; 522 data.m_impl_up->SetObjectSP(std::move(config_up)); 523 return data; 524 } 525 526 bool SBDebugger::StateIsRunningState(StateType state) { 527 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 528 529 const bool result = lldb_private::StateIsRunningState(state); 530 if (log) 531 log->Printf("SBDebugger::StateIsRunningState (state=%s) => %i", 532 StateAsCString(state), result); 533 534 return result; 535 } 536 537 bool SBDebugger::StateIsStoppedState(StateType state) { 538 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 539 540 const bool result = lldb_private::StateIsStoppedState(state, false); 541 if (log) 542 log->Printf("SBDebugger::StateIsStoppedState (state=%s) => %i", 543 StateAsCString(state), result); 544 545 return result; 546 } 547 548 lldb::SBTarget SBDebugger::CreateTarget(const char *filename, 549 const char *target_triple, 550 const char *platform_name, 551 bool add_dependent_modules, 552 lldb::SBError &sb_error) { 553 SBTarget sb_target; 554 TargetSP target_sp; 555 if (m_opaque_sp) { 556 sb_error.Clear(); 557 OptionGroupPlatform platform_options(false); 558 platform_options.SetPlatformName(platform_name); 559 560 sb_error.ref() = m_opaque_sp->GetTargetList().CreateTarget( 561 *m_opaque_sp, filename, target_triple, 562 add_dependent_modules ? eLoadDependentsYes : eLoadDependentsNo, 563 &platform_options, target_sp); 564 565 if (sb_error.Success()) 566 sb_target.SetSP(target_sp); 567 } else { 568 sb_error.SetErrorString("invalid debugger"); 569 } 570 571 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 572 if (log) 573 log->Printf("SBDebugger(%p)::CreateTarget (filename=\"%s\", triple=%s, " 574 "platform_name=%s, add_dependent_modules=%u, error=%s) => " 575 "SBTarget(%p)", 576 static_cast<void *>(m_opaque_sp.get()), filename, target_triple, 577 platform_name, add_dependent_modules, sb_error.GetCString(), 578 static_cast<void *>(target_sp.get())); 579 580 return sb_target; 581 } 582 583 SBTarget 584 SBDebugger::CreateTargetWithFileAndTargetTriple(const char *filename, 585 const char *target_triple) { 586 SBTarget sb_target; 587 TargetSP target_sp; 588 if (m_opaque_sp) { 589 const bool add_dependent_modules = true; 590 Status error(m_opaque_sp->GetTargetList().CreateTarget( 591 *m_opaque_sp, filename, target_triple, 592 add_dependent_modules ? eLoadDependentsYes : eLoadDependentsNo, nullptr, 593 target_sp)); 594 sb_target.SetSP(target_sp); 595 } 596 597 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 598 if (log) 599 log->Printf("SBDebugger(%p)::CreateTargetWithFileAndTargetTriple " 600 "(filename=\"%s\", triple=%s) => SBTarget(%p)", 601 static_cast<void *>(m_opaque_sp.get()), filename, target_triple, 602 static_cast<void *>(target_sp.get())); 603 604 return sb_target; 605 } 606 607 SBTarget SBDebugger::CreateTargetWithFileAndArch(const char *filename, 608 const char *arch_cstr) { 609 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 610 611 SBTarget sb_target; 612 TargetSP target_sp; 613 if (m_opaque_sp) { 614 Status error; 615 const bool add_dependent_modules = true; 616 617 error = m_opaque_sp->GetTargetList().CreateTarget( 618 *m_opaque_sp, filename, arch_cstr, 619 add_dependent_modules ? eLoadDependentsYes : eLoadDependentsNo, nullptr, 620 target_sp); 621 622 if (error.Success()) { 623 m_opaque_sp->GetTargetList().SetSelectedTarget(target_sp.get()); 624 sb_target.SetSP(target_sp); 625 } 626 } 627 628 if (log) 629 log->Printf("SBDebugger(%p)::CreateTargetWithFileAndArch (filename=\"%s\", " 630 "arch=%s) => SBTarget(%p)", 631 static_cast<void *>(m_opaque_sp.get()), filename, arch_cstr, 632 static_cast<void *>(target_sp.get())); 633 634 return sb_target; 635 } 636 637 SBTarget SBDebugger::CreateTarget(const char *filename) { 638 SBTarget sb_target; 639 TargetSP target_sp; 640 if (m_opaque_sp) { 641 Status error; 642 const bool add_dependent_modules = true; 643 error = m_opaque_sp->GetTargetList().CreateTarget( 644 *m_opaque_sp, filename, "", 645 add_dependent_modules ? eLoadDependentsYes : eLoadDependentsNo, nullptr, 646 target_sp); 647 648 if (error.Success()) { 649 m_opaque_sp->GetTargetList().SetSelectedTarget(target_sp.get()); 650 sb_target.SetSP(target_sp); 651 } 652 } 653 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 654 if (log) 655 log->Printf( 656 "SBDebugger(%p)::CreateTarget (filename=\"%s\") => SBTarget(%p)", 657 static_cast<void *>(m_opaque_sp.get()), filename, 658 static_cast<void *>(target_sp.get())); 659 return sb_target; 660 } 661 662 SBTarget SBDebugger::GetDummyTarget() { 663 SBTarget sb_target; 664 if (m_opaque_sp) { 665 sb_target.SetSP(m_opaque_sp->GetDummyTarget()->shared_from_this()); 666 } 667 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 668 if (log) 669 log->Printf( 670 "SBDebugger(%p)::GetDummyTarget() => SBTarget(%p)", 671 static_cast<void *>(m_opaque_sp.get()), 672 static_cast<void *>(sb_target.GetSP().get())); 673 return sb_target; 674 } 675 676 bool SBDebugger::DeleteTarget(lldb::SBTarget &target) { 677 bool result = false; 678 if (m_opaque_sp) { 679 TargetSP target_sp(target.GetSP()); 680 if (target_sp) { 681 // No need to lock, the target list is thread safe 682 result = m_opaque_sp->GetTargetList().DeleteTarget(target_sp); 683 target_sp->Destroy(); 684 target.Clear(); 685 const bool mandatory = true; 686 ModuleList::RemoveOrphanSharedModules(mandatory); 687 } 688 } 689 690 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 691 if (log) 692 log->Printf("SBDebugger(%p)::DeleteTarget (SBTarget(%p)) => %i", 693 static_cast<void *>(m_opaque_sp.get()), 694 static_cast<void *>(target.m_opaque_sp.get()), result); 695 696 return result; 697 } 698 699 SBTarget SBDebugger::GetTargetAtIndex(uint32_t idx) { 700 SBTarget sb_target; 701 if (m_opaque_sp) { 702 // No need to lock, the target list is thread safe 703 sb_target.SetSP(m_opaque_sp->GetTargetList().GetTargetAtIndex(idx)); 704 } 705 return sb_target; 706 } 707 708 uint32_t SBDebugger::GetIndexOfTarget(lldb::SBTarget target) { 709 710 lldb::TargetSP target_sp = target.GetSP(); 711 if (!target_sp) 712 return UINT32_MAX; 713 714 if (!m_opaque_sp) 715 return UINT32_MAX; 716 717 return m_opaque_sp->GetTargetList().GetIndexOfTarget(target.GetSP()); 718 } 719 720 SBTarget SBDebugger::FindTargetWithProcessID(lldb::pid_t pid) { 721 SBTarget sb_target; 722 if (m_opaque_sp) { 723 // No need to lock, the target list is thread safe 724 sb_target.SetSP(m_opaque_sp->GetTargetList().FindTargetWithProcessID(pid)); 725 } 726 return sb_target; 727 } 728 729 SBTarget SBDebugger::FindTargetWithFileAndArch(const char *filename, 730 const char *arch_name) { 731 SBTarget sb_target; 732 if (m_opaque_sp && filename && filename[0]) { 733 // No need to lock, the target list is thread safe 734 ArchSpec arch = Platform::GetAugmentedArchSpec( 735 m_opaque_sp->GetPlatformList().GetSelectedPlatform().get(), arch_name); 736 TargetSP target_sp( 737 m_opaque_sp->GetTargetList().FindTargetWithExecutableAndArchitecture( 738 FileSpec(filename, false), arch_name ? &arch : nullptr)); 739 sb_target.SetSP(target_sp); 740 } 741 return sb_target; 742 } 743 744 SBTarget SBDebugger::FindTargetWithLLDBProcess(const ProcessSP &process_sp) { 745 SBTarget sb_target; 746 if (m_opaque_sp) { 747 // No need to lock, the target list is thread safe 748 sb_target.SetSP( 749 m_opaque_sp->GetTargetList().FindTargetWithProcess(process_sp.get())); 750 } 751 return sb_target; 752 } 753 754 uint32_t SBDebugger::GetNumTargets() { 755 if (m_opaque_sp) { 756 // No need to lock, the target list is thread safe 757 return m_opaque_sp->GetTargetList().GetNumTargets(); 758 } 759 return 0; 760 } 761 762 SBTarget SBDebugger::GetSelectedTarget() { 763 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 764 765 SBTarget sb_target; 766 TargetSP target_sp; 767 if (m_opaque_sp) { 768 // No need to lock, the target list is thread safe 769 target_sp = m_opaque_sp->GetTargetList().GetSelectedTarget(); 770 sb_target.SetSP(target_sp); 771 } 772 773 if (log) { 774 SBStream sstr; 775 sb_target.GetDescription(sstr, eDescriptionLevelBrief); 776 log->Printf("SBDebugger(%p)::GetSelectedTarget () => SBTarget(%p): %s", 777 static_cast<void *>(m_opaque_sp.get()), 778 static_cast<void *>(target_sp.get()), sstr.GetData()); 779 } 780 781 return sb_target; 782 } 783 784 void SBDebugger::SetSelectedTarget(SBTarget &sb_target) { 785 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 786 787 TargetSP target_sp(sb_target.GetSP()); 788 if (m_opaque_sp) { 789 m_opaque_sp->GetTargetList().SetSelectedTarget(target_sp.get()); 790 } 791 if (log) { 792 SBStream sstr; 793 sb_target.GetDescription(sstr, eDescriptionLevelBrief); 794 log->Printf("SBDebugger(%p)::SetSelectedTarget () => SBTarget(%p): %s", 795 static_cast<void *>(m_opaque_sp.get()), 796 static_cast<void *>(target_sp.get()), sstr.GetData()); 797 } 798 } 799 800 SBPlatform SBDebugger::GetSelectedPlatform() { 801 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 802 803 SBPlatform sb_platform; 804 DebuggerSP debugger_sp(m_opaque_sp); 805 if (debugger_sp) { 806 sb_platform.SetSP(debugger_sp->GetPlatformList().GetSelectedPlatform()); 807 } 808 if (log) 809 log->Printf("SBDebugger(%p)::GetSelectedPlatform () => SBPlatform(%p): %s", 810 static_cast<void *>(m_opaque_sp.get()), 811 static_cast<void *>(sb_platform.GetSP().get()), 812 sb_platform.GetName()); 813 return sb_platform; 814 } 815 816 void SBDebugger::SetSelectedPlatform(SBPlatform &sb_platform) { 817 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 818 819 DebuggerSP debugger_sp(m_opaque_sp); 820 if (debugger_sp) { 821 debugger_sp->GetPlatformList().SetSelectedPlatform(sb_platform.GetSP()); 822 } 823 824 if (log) 825 log->Printf("SBDebugger(%p)::SetSelectedPlatform (SBPlatform(%p) %s)", 826 static_cast<void *>(m_opaque_sp.get()), 827 static_cast<void *>(sb_platform.GetSP().get()), 828 sb_platform.GetName()); 829 } 830 831 uint32_t SBDebugger::GetNumPlatforms() { 832 if (m_opaque_sp) { 833 // No need to lock, the platform list is thread safe 834 return m_opaque_sp->GetPlatformList().GetSize(); 835 } 836 return 0; 837 } 838 839 SBPlatform SBDebugger::GetPlatformAtIndex(uint32_t idx) { 840 SBPlatform sb_platform; 841 if (m_opaque_sp) { 842 // No need to lock, the platform list is thread safe 843 sb_platform.SetSP(m_opaque_sp->GetPlatformList().GetAtIndex(idx)); 844 } 845 return sb_platform; 846 } 847 848 uint32_t SBDebugger::GetNumAvailablePlatforms() { 849 uint32_t idx = 0; 850 while (true) { 851 if (!PluginManager::GetPlatformPluginNameAtIndex(idx)) { 852 break; 853 } 854 ++idx; 855 } 856 // +1 for the host platform, which should always appear first in the list. 857 return idx + 1; 858 } 859 860 SBStructuredData SBDebugger::GetAvailablePlatformInfoAtIndex(uint32_t idx) { 861 SBStructuredData data; 862 auto platform_dict = llvm::make_unique<StructuredData::Dictionary>(); 863 llvm::StringRef name_str("name"), desc_str("description"); 864 865 if (idx == 0) { 866 PlatformSP host_platform_sp(Platform::GetHostPlatform()); 867 platform_dict->AddStringItem( 868 name_str, host_platform_sp->GetPluginName().GetStringRef()); 869 platform_dict->AddStringItem( 870 desc_str, llvm::StringRef(host_platform_sp->GetDescription())); 871 } else if (idx > 0) { 872 const char *plugin_name = 873 PluginManager::GetPlatformPluginNameAtIndex(idx - 1); 874 if (!plugin_name) { 875 return data; 876 } 877 platform_dict->AddStringItem(name_str, llvm::StringRef(plugin_name)); 878 879 const char *plugin_desc = 880 PluginManager::GetPlatformPluginDescriptionAtIndex(idx - 1); 881 if (!plugin_desc) { 882 return data; 883 } 884 platform_dict->AddStringItem(desc_str, llvm::StringRef(plugin_desc)); 885 } 886 887 data.m_impl_up->SetObjectSP( 888 StructuredData::ObjectSP(platform_dict.release())); 889 return data; 890 } 891 892 void SBDebugger::DispatchInput(void *baton, const void *data, size_t data_len) { 893 DispatchInput(data, data_len); 894 } 895 896 void SBDebugger::DispatchInput(const void *data, size_t data_len) { 897 // Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 898 // 899 // if (log) 900 // log->Printf ("SBDebugger(%p)::DispatchInput (data=\"%.*s\", 901 // size_t=%" PRIu64 ")", 902 // m_opaque_sp.get(), 903 // (int) data_len, 904 // (const char *) data, 905 // (uint64_t)data_len); 906 // 907 // if (m_opaque_sp) 908 // m_opaque_sp->DispatchInput ((const char *) data, data_len); 909 } 910 911 void SBDebugger::DispatchInputInterrupt() { 912 if (m_opaque_sp) 913 m_opaque_sp->DispatchInputInterrupt(); 914 } 915 916 void SBDebugger::DispatchInputEndOfFile() { 917 if (m_opaque_sp) 918 m_opaque_sp->DispatchInputEndOfFile(); 919 } 920 921 void SBDebugger::PushInputReader(SBInputReader &reader) {} 922 923 void SBDebugger::RunCommandInterpreter(bool auto_handle_events, 924 bool spawn_thread) { 925 if (m_opaque_sp) { 926 CommandInterpreterRunOptions options; 927 928 m_opaque_sp->GetCommandInterpreter().RunCommandInterpreter( 929 auto_handle_events, spawn_thread, options); 930 } 931 } 932 933 void SBDebugger::RunCommandInterpreter(bool auto_handle_events, 934 bool spawn_thread, 935 SBCommandInterpreterRunOptions &options, 936 int &num_errors, bool &quit_requested, 937 bool &stopped_for_crash) 938 939 { 940 if (m_opaque_sp) { 941 CommandInterpreter &interp = m_opaque_sp->GetCommandInterpreter(); 942 interp.RunCommandInterpreter(auto_handle_events, spawn_thread, 943 options.ref()); 944 num_errors = interp.GetNumErrors(); 945 quit_requested = interp.GetQuitRequested(); 946 stopped_for_crash = interp.GetStoppedForCrash(); 947 } 948 } 949 950 SBError SBDebugger::RunREPL(lldb::LanguageType language, 951 const char *repl_options) { 952 SBError error; 953 if (m_opaque_sp) 954 error.ref() = m_opaque_sp->RunREPL(language, repl_options); 955 else 956 error.SetErrorString("invalid debugger"); 957 return error; 958 } 959 960 void SBDebugger::reset(const DebuggerSP &debugger_sp) { 961 m_opaque_sp = debugger_sp; 962 } 963 964 Debugger *SBDebugger::get() const { return m_opaque_sp.get(); } 965 966 Debugger &SBDebugger::ref() const { 967 assert(m_opaque_sp.get()); 968 return *m_opaque_sp; 969 } 970 971 const lldb::DebuggerSP &SBDebugger::get_sp() const { return m_opaque_sp; } 972 973 SBDebugger SBDebugger::FindDebuggerWithID(int id) { 974 // No need to lock, the debugger list is thread safe 975 SBDebugger sb_debugger; 976 DebuggerSP debugger_sp = Debugger::FindDebuggerWithID(id); 977 if (debugger_sp) 978 sb_debugger.reset(debugger_sp); 979 return sb_debugger; 980 } 981 982 const char *SBDebugger::GetInstanceName() { 983 return (m_opaque_sp ? m_opaque_sp->GetInstanceName().AsCString() : nullptr); 984 } 985 986 SBError SBDebugger::SetInternalVariable(const char *var_name, const char *value, 987 const char *debugger_instance_name) { 988 SBError sb_error; 989 DebuggerSP debugger_sp(Debugger::FindDebuggerWithInstanceName( 990 ConstString(debugger_instance_name))); 991 Status error; 992 if (debugger_sp) { 993 ExecutionContext exe_ctx( 994 debugger_sp->GetCommandInterpreter().GetExecutionContext()); 995 error = debugger_sp->SetPropertyValue(&exe_ctx, eVarSetOperationAssign, 996 var_name, value); 997 } else { 998 error.SetErrorStringWithFormat("invalid debugger instance name '%s'", 999 debugger_instance_name); 1000 } 1001 if (error.Fail()) 1002 sb_error.SetError(error); 1003 return sb_error; 1004 } 1005 1006 SBStringList 1007 SBDebugger::GetInternalVariableValue(const char *var_name, 1008 const char *debugger_instance_name) { 1009 SBStringList ret_value; 1010 DebuggerSP debugger_sp(Debugger::FindDebuggerWithInstanceName( 1011 ConstString(debugger_instance_name))); 1012 Status error; 1013 if (debugger_sp) { 1014 ExecutionContext exe_ctx( 1015 debugger_sp->GetCommandInterpreter().GetExecutionContext()); 1016 lldb::OptionValueSP value_sp( 1017 debugger_sp->GetPropertyValue(&exe_ctx, var_name, false, error)); 1018 if (value_sp) { 1019 StreamString value_strm; 1020 value_sp->DumpValue(&exe_ctx, value_strm, OptionValue::eDumpOptionValue); 1021 const std::string &value_str = value_strm.GetString(); 1022 if (!value_str.empty()) { 1023 StringList string_list; 1024 string_list.SplitIntoLines(value_str); 1025 return SBStringList(&string_list); 1026 } 1027 } 1028 } 1029 return SBStringList(); 1030 } 1031 1032 uint32_t SBDebugger::GetTerminalWidth() const { 1033 return (m_opaque_sp ? m_opaque_sp->GetTerminalWidth() : 0); 1034 } 1035 1036 void SBDebugger::SetTerminalWidth(uint32_t term_width) { 1037 if (m_opaque_sp) 1038 m_opaque_sp->SetTerminalWidth(term_width); 1039 } 1040 1041 const char *SBDebugger::GetPrompt() const { 1042 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 1043 1044 if (log) 1045 log->Printf("SBDebugger(%p)::GetPrompt () => \"%s\"", 1046 static_cast<void *>(m_opaque_sp.get()), 1047 (m_opaque_sp ? m_opaque_sp->GetPrompt().str().c_str() : "")); 1048 1049 return (m_opaque_sp ? ConstString(m_opaque_sp->GetPrompt()).GetCString() 1050 : nullptr); 1051 } 1052 1053 void SBDebugger::SetPrompt(const char *prompt) { 1054 if (m_opaque_sp) 1055 m_opaque_sp->SetPrompt(llvm::StringRef::withNullAsEmpty(prompt)); 1056 } 1057 1058 ScriptLanguage SBDebugger::GetScriptLanguage() const { 1059 return (m_opaque_sp ? m_opaque_sp->GetScriptLanguage() : eScriptLanguageNone); 1060 } 1061 1062 void SBDebugger::SetScriptLanguage(ScriptLanguage script_lang) { 1063 if (m_opaque_sp) { 1064 m_opaque_sp->SetScriptLanguage(script_lang); 1065 } 1066 } 1067 1068 bool SBDebugger::SetUseExternalEditor(bool value) { 1069 return (m_opaque_sp ? m_opaque_sp->SetUseExternalEditor(value) : false); 1070 } 1071 1072 bool SBDebugger::GetUseExternalEditor() { 1073 return (m_opaque_sp ? m_opaque_sp->GetUseExternalEditor() : false); 1074 } 1075 1076 bool SBDebugger::SetUseColor(bool value) { 1077 return (m_opaque_sp ? m_opaque_sp->SetUseColor(value) : false); 1078 } 1079 1080 bool SBDebugger::GetUseColor() const { 1081 return (m_opaque_sp ? m_opaque_sp->GetUseColor() : false); 1082 } 1083 1084 bool SBDebugger::GetDescription(SBStream &description) { 1085 Stream &strm = description.ref(); 1086 1087 if (m_opaque_sp) { 1088 const char *name = m_opaque_sp->GetInstanceName().AsCString(); 1089 user_id_t id = m_opaque_sp->GetID(); 1090 strm.Printf("Debugger (instance: \"%s\", id: %" PRIu64 ")", name, id); 1091 } else 1092 strm.PutCString("No value"); 1093 1094 return true; 1095 } 1096 1097 user_id_t SBDebugger::GetID() { 1098 return (m_opaque_sp ? m_opaque_sp->GetID() : LLDB_INVALID_UID); 1099 } 1100 1101 SBError SBDebugger::SetCurrentPlatform(const char *platform_name_cstr) { 1102 SBError sb_error; 1103 if (m_opaque_sp) { 1104 if (platform_name_cstr && platform_name_cstr[0]) { 1105 ConstString platform_name(platform_name_cstr); 1106 PlatformSP platform_sp(Platform::Find(platform_name)); 1107 1108 if (platform_sp) { 1109 // Already have a platform with this name, just select it 1110 m_opaque_sp->GetPlatformList().SetSelectedPlatform(platform_sp); 1111 } else { 1112 // We don't have a platform by this name yet, create one 1113 platform_sp = Platform::Create(platform_name, sb_error.ref()); 1114 if (platform_sp) { 1115 // We created the platform, now append and select it 1116 bool make_selected = true; 1117 m_opaque_sp->GetPlatformList().Append(platform_sp, make_selected); 1118 } 1119 } 1120 } else { 1121 sb_error.ref().SetErrorString("invalid platform name"); 1122 } 1123 } else { 1124 sb_error.ref().SetErrorString("invalid debugger"); 1125 } 1126 return sb_error; 1127 } 1128 1129 bool SBDebugger::SetCurrentPlatformSDKRoot(const char *sysroot) { 1130 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 1131 if (m_opaque_sp) { 1132 PlatformSP platform_sp( 1133 m_opaque_sp->GetPlatformList().GetSelectedPlatform()); 1134 1135 if (platform_sp) { 1136 if (log && sysroot) 1137 log->Printf("SBDebugger::SetCurrentPlatformSDKRoot (\"%s\")", sysroot); 1138 platform_sp->SetSDKRootDirectory(ConstString(sysroot)); 1139 return true; 1140 } 1141 } 1142 return false; 1143 } 1144 1145 bool SBDebugger::GetCloseInputOnEOF() const { 1146 return (m_opaque_sp ? m_opaque_sp->GetCloseInputOnEOF() : false); 1147 } 1148 1149 void SBDebugger::SetCloseInputOnEOF(bool b) { 1150 if (m_opaque_sp) 1151 m_opaque_sp->SetCloseInputOnEOF(b); 1152 } 1153 1154 SBTypeCategory SBDebugger::GetCategory(const char *category_name) { 1155 if (!category_name || *category_name == 0) 1156 return SBTypeCategory(); 1157 1158 TypeCategoryImplSP category_sp; 1159 1160 if (DataVisualization::Categories::GetCategory(ConstString(category_name), 1161 category_sp, false)) 1162 return SBTypeCategory(category_sp); 1163 else 1164 return SBTypeCategory(); 1165 } 1166 1167 SBTypeCategory SBDebugger::GetCategory(lldb::LanguageType lang_type) { 1168 TypeCategoryImplSP category_sp; 1169 if (DataVisualization::Categories::GetCategory(lang_type, category_sp)) 1170 return SBTypeCategory(category_sp); 1171 else 1172 return SBTypeCategory(); 1173 } 1174 1175 SBTypeCategory SBDebugger::CreateCategory(const char *category_name) { 1176 if (!category_name || *category_name == 0) 1177 return SBTypeCategory(); 1178 1179 TypeCategoryImplSP category_sp; 1180 1181 if (DataVisualization::Categories::GetCategory(ConstString(category_name), 1182 category_sp, true)) 1183 return SBTypeCategory(category_sp); 1184 else 1185 return SBTypeCategory(); 1186 } 1187 1188 bool SBDebugger::DeleteCategory(const char *category_name) { 1189 if (!category_name || *category_name == 0) 1190 return false; 1191 1192 return DataVisualization::Categories::Delete(ConstString(category_name)); 1193 } 1194 1195 uint32_t SBDebugger::GetNumCategories() { 1196 return DataVisualization::Categories::GetCount(); 1197 } 1198 1199 SBTypeCategory SBDebugger::GetCategoryAtIndex(uint32_t index) { 1200 return SBTypeCategory( 1201 DataVisualization::Categories::GetCategoryAtIndex(index)); 1202 } 1203 1204 SBTypeCategory SBDebugger::GetDefaultCategory() { 1205 return GetCategory("default"); 1206 } 1207 1208 SBTypeFormat SBDebugger::GetFormatForType(SBTypeNameSpecifier type_name) { 1209 SBTypeCategory default_category_sb = GetDefaultCategory(); 1210 if (default_category_sb.GetEnabled()) 1211 return default_category_sb.GetFormatForType(type_name); 1212 return SBTypeFormat(); 1213 } 1214 1215 #ifndef LLDB_DISABLE_PYTHON 1216 SBTypeSummary SBDebugger::GetSummaryForType(SBTypeNameSpecifier type_name) { 1217 if (!type_name.IsValid()) 1218 return SBTypeSummary(); 1219 return SBTypeSummary(DataVisualization::GetSummaryForType(type_name.GetSP())); 1220 } 1221 #endif // LLDB_DISABLE_PYTHON 1222 1223 SBTypeFilter SBDebugger::GetFilterForType(SBTypeNameSpecifier type_name) { 1224 if (!type_name.IsValid()) 1225 return SBTypeFilter(); 1226 return SBTypeFilter(DataVisualization::GetFilterForType(type_name.GetSP())); 1227 } 1228 1229 #ifndef LLDB_DISABLE_PYTHON 1230 SBTypeSynthetic SBDebugger::GetSyntheticForType(SBTypeNameSpecifier type_name) { 1231 if (!type_name.IsValid()) 1232 return SBTypeSynthetic(); 1233 return SBTypeSynthetic( 1234 DataVisualization::GetSyntheticForType(type_name.GetSP())); 1235 } 1236 #endif // LLDB_DISABLE_PYTHON 1237 1238 static llvm::ArrayRef<const char *> GetCategoryArray(const char **categories) { 1239 if (categories == nullptr) 1240 return {}; 1241 size_t len = 0; 1242 while (categories[len] != nullptr) 1243 ++len; 1244 return llvm::makeArrayRef(categories, len); 1245 } 1246 1247 bool SBDebugger::EnableLog(const char *channel, const char **categories) { 1248 if (m_opaque_sp) { 1249 uint32_t log_options = 1250 LLDB_LOG_OPTION_PREPEND_TIMESTAMP | LLDB_LOG_OPTION_PREPEND_THREAD_NAME; 1251 std::string error; 1252 llvm::raw_string_ostream error_stream(error); 1253 return m_opaque_sp->EnableLog(channel, GetCategoryArray(categories), "", 1254 log_options, error_stream); 1255 } else 1256 return false; 1257 } 1258 1259 void SBDebugger::SetLoggingCallback(lldb::LogOutputCallback log_callback, 1260 void *baton) { 1261 if (m_opaque_sp) { 1262 return m_opaque_sp->SetLoggingCallback(log_callback, baton); 1263 } 1264 } 1265