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