]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/API/SBDebugger.cpp
Merge ^/head r338731 through r338987.
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / source / API / SBDebugger.cpp
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/State.h"
45 #include "lldb/Core/StreamFile.h"
46 #include "lldb/Core/StructuredDataImpl.h"
47 #include "lldb/DataFormatters/DataVisualization.h"
48 #include "lldb/Host/XML.h"
49 #include "lldb/Initialization/SystemLifetimeManager.h"
50 #include "lldb/Interpreter/CommandInterpreter.h"
51 #include "lldb/Interpreter/OptionArgParser.h"
52 #include "lldb/Interpreter/OptionGroupPlatform.h"
53 #include "lldb/Target/Process.h"
54 #include "lldb/Target/TargetList.h"
55 #include "lldb/Utility/Args.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, add_dependent_modules,
562         &platform_options, target_sp);
563
564     if (sb_error.Success())
565       sb_target.SetSP(target_sp);
566   } else {
567     sb_error.SetErrorString("invalid debugger");
568   }
569
570   Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
571   if (log)
572     log->Printf("SBDebugger(%p)::CreateTarget (filename=\"%s\", triple=%s, "
573                 "platform_name=%s, add_dependent_modules=%u, error=%s) => "
574                 "SBTarget(%p)",
575                 static_cast<void *>(m_opaque_sp.get()), filename, target_triple,
576                 platform_name, add_dependent_modules, sb_error.GetCString(),
577                 static_cast<void *>(target_sp.get()));
578
579   return sb_target;
580 }
581
582 SBTarget
583 SBDebugger::CreateTargetWithFileAndTargetTriple(const char *filename,
584                                                 const char *target_triple) {
585   SBTarget sb_target;
586   TargetSP target_sp;
587   if (m_opaque_sp) {
588     const bool add_dependent_modules = true;
589     Status error(m_opaque_sp->GetTargetList().CreateTarget(
590         *m_opaque_sp, filename, target_triple, add_dependent_modules, nullptr,
591         target_sp));
592     sb_target.SetSP(target_sp);
593   }
594
595   Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
596   if (log)
597     log->Printf("SBDebugger(%p)::CreateTargetWithFileAndTargetTriple "
598                 "(filename=\"%s\", triple=%s) => SBTarget(%p)",
599                 static_cast<void *>(m_opaque_sp.get()), filename, target_triple,
600                 static_cast<void *>(target_sp.get()));
601
602   return sb_target;
603 }
604
605 SBTarget SBDebugger::CreateTargetWithFileAndArch(const char *filename,
606                                                  const char *arch_cstr) {
607   Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
608
609   SBTarget sb_target;
610   TargetSP target_sp;
611   if (m_opaque_sp) {
612     Status error;
613     const bool add_dependent_modules = true;
614
615     error = m_opaque_sp->GetTargetList().CreateTarget(
616         *m_opaque_sp, filename, arch_cstr, add_dependent_modules, nullptr,
617         target_sp);
618
619     if (error.Success()) {
620       m_opaque_sp->GetTargetList().SetSelectedTarget(target_sp.get());
621       sb_target.SetSP(target_sp);
622     }
623   }
624
625   if (log)
626     log->Printf("SBDebugger(%p)::CreateTargetWithFileAndArch (filename=\"%s\", "
627                 "arch=%s) => SBTarget(%p)",
628                 static_cast<void *>(m_opaque_sp.get()), filename, arch_cstr,
629                 static_cast<void *>(target_sp.get()));
630
631   return sb_target;
632 }
633
634 SBTarget SBDebugger::CreateTarget(const char *filename) {
635   SBTarget sb_target;
636   TargetSP target_sp;
637   if (m_opaque_sp) {
638     Status error;
639     const bool add_dependent_modules = true;
640     error = m_opaque_sp->GetTargetList().CreateTarget(
641         *m_opaque_sp, filename, "", add_dependent_modules, nullptr, target_sp);
642
643     if (error.Success()) {
644       m_opaque_sp->GetTargetList().SetSelectedTarget(target_sp.get());
645       sb_target.SetSP(target_sp);
646     }
647   }
648   Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
649   if (log)
650     log->Printf(
651         "SBDebugger(%p)::CreateTarget (filename=\"%s\") => SBTarget(%p)",
652         static_cast<void *>(m_opaque_sp.get()), filename,
653         static_cast<void *>(target_sp.get()));
654   return sb_target;
655 }
656
657 SBTarget SBDebugger::GetDummyTarget() {
658   SBTarget sb_target;
659   if (m_opaque_sp) {
660       sb_target.SetSP(m_opaque_sp->GetDummyTarget()->shared_from_this());
661   }
662   Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
663   if (log)
664     log->Printf(
665         "SBDebugger(%p)::GetDummyTarget() => SBTarget(%p)",
666         static_cast<void *>(m_opaque_sp.get()),
667         static_cast<void *>(sb_target.GetSP().get()));
668   return sb_target;
669 }
670
671 bool SBDebugger::DeleteTarget(lldb::SBTarget &target) {
672   bool result = false;
673   if (m_opaque_sp) {
674     TargetSP target_sp(target.GetSP());
675     if (target_sp) {
676       // No need to lock, the target list is thread safe
677       result = m_opaque_sp->GetTargetList().DeleteTarget(target_sp);
678       target_sp->Destroy();
679       target.Clear();
680       const bool mandatory = true;
681       ModuleList::RemoveOrphanSharedModules(mandatory);
682     }
683   }
684
685   Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
686   if (log)
687     log->Printf("SBDebugger(%p)::DeleteTarget (SBTarget(%p)) => %i",
688                 static_cast<void *>(m_opaque_sp.get()),
689                 static_cast<void *>(target.m_opaque_sp.get()), result);
690
691   return result;
692 }
693
694 SBTarget SBDebugger::GetTargetAtIndex(uint32_t idx) {
695   SBTarget sb_target;
696   if (m_opaque_sp) {
697     // No need to lock, the target list is thread safe
698     sb_target.SetSP(m_opaque_sp->GetTargetList().GetTargetAtIndex(idx));
699   }
700   return sb_target;
701 }
702
703 uint32_t SBDebugger::GetIndexOfTarget(lldb::SBTarget target) {
704
705   lldb::TargetSP target_sp = target.GetSP();
706   if (!target_sp)
707     return UINT32_MAX;
708
709   if (!m_opaque_sp)
710     return UINT32_MAX;
711
712   return m_opaque_sp->GetTargetList().GetIndexOfTarget(target.GetSP());
713 }
714
715 SBTarget SBDebugger::FindTargetWithProcessID(lldb::pid_t pid) {
716   SBTarget sb_target;
717   if (m_opaque_sp) {
718     // No need to lock, the target list is thread safe
719     sb_target.SetSP(m_opaque_sp->GetTargetList().FindTargetWithProcessID(pid));
720   }
721   return sb_target;
722 }
723
724 SBTarget SBDebugger::FindTargetWithFileAndArch(const char *filename,
725                                                const char *arch_name) {
726   SBTarget sb_target;
727   if (m_opaque_sp && filename && filename[0]) {
728     // No need to lock, the target list is thread safe
729     ArchSpec arch = Platform::GetAugmentedArchSpec(
730         m_opaque_sp->GetPlatformList().GetSelectedPlatform().get(), arch_name);
731     TargetSP target_sp(
732         m_opaque_sp->GetTargetList().FindTargetWithExecutableAndArchitecture(
733             FileSpec(filename, false), arch_name ? &arch : nullptr));
734     sb_target.SetSP(target_sp);
735   }
736   return sb_target;
737 }
738
739 SBTarget SBDebugger::FindTargetWithLLDBProcess(const ProcessSP &process_sp) {
740   SBTarget sb_target;
741   if (m_opaque_sp) {
742     // No need to lock, the target list is thread safe
743     sb_target.SetSP(
744         m_opaque_sp->GetTargetList().FindTargetWithProcess(process_sp.get()));
745   }
746   return sb_target;
747 }
748
749 uint32_t SBDebugger::GetNumTargets() {
750   if (m_opaque_sp) {
751     // No need to lock, the target list is thread safe
752     return m_opaque_sp->GetTargetList().GetNumTargets();
753   }
754   return 0;
755 }
756
757 SBTarget SBDebugger::GetSelectedTarget() {
758   Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
759
760   SBTarget sb_target;
761   TargetSP target_sp;
762   if (m_opaque_sp) {
763     // No need to lock, the target list is thread safe
764     target_sp = m_opaque_sp->GetTargetList().GetSelectedTarget();
765     sb_target.SetSP(target_sp);
766   }
767
768   if (log) {
769     SBStream sstr;
770     sb_target.GetDescription(sstr, eDescriptionLevelBrief);
771     log->Printf("SBDebugger(%p)::GetSelectedTarget () => SBTarget(%p): %s",
772                 static_cast<void *>(m_opaque_sp.get()),
773                 static_cast<void *>(target_sp.get()), sstr.GetData());
774   }
775
776   return sb_target;
777 }
778
779 void SBDebugger::SetSelectedTarget(SBTarget &sb_target) {
780   Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
781
782   TargetSP target_sp(sb_target.GetSP());
783   if (m_opaque_sp) {
784     m_opaque_sp->GetTargetList().SetSelectedTarget(target_sp.get());
785   }
786   if (log) {
787     SBStream sstr;
788     sb_target.GetDescription(sstr, eDescriptionLevelBrief);
789     log->Printf("SBDebugger(%p)::SetSelectedTarget () => SBTarget(%p): %s",
790                 static_cast<void *>(m_opaque_sp.get()),
791                 static_cast<void *>(target_sp.get()), sstr.GetData());
792   }
793 }
794
795 SBPlatform SBDebugger::GetSelectedPlatform() {
796   Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
797
798   SBPlatform sb_platform;
799   DebuggerSP debugger_sp(m_opaque_sp);
800   if (debugger_sp) {
801     sb_platform.SetSP(debugger_sp->GetPlatformList().GetSelectedPlatform());
802   }
803   if (log)
804     log->Printf("SBDebugger(%p)::GetSelectedPlatform () => SBPlatform(%p): %s",
805                 static_cast<void *>(m_opaque_sp.get()),
806                 static_cast<void *>(sb_platform.GetSP().get()),
807                 sb_platform.GetName());
808   return sb_platform;
809 }
810
811 void SBDebugger::SetSelectedPlatform(SBPlatform &sb_platform) {
812   Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
813
814   DebuggerSP debugger_sp(m_opaque_sp);
815   if (debugger_sp) {
816     debugger_sp->GetPlatformList().SetSelectedPlatform(sb_platform.GetSP());
817   }
818
819   if (log)
820     log->Printf("SBDebugger(%p)::SetSelectedPlatform (SBPlatform(%p) %s)",
821                 static_cast<void *>(m_opaque_sp.get()),
822                 static_cast<void *>(sb_platform.GetSP().get()),
823                 sb_platform.GetName());
824 }
825
826 uint32_t SBDebugger::GetNumPlatforms() {
827   if (m_opaque_sp) {
828     // No need to lock, the platform list is thread safe
829     return m_opaque_sp->GetPlatformList().GetSize();
830   }
831   return 0;
832 }
833
834 SBPlatform SBDebugger::GetPlatformAtIndex(uint32_t idx) {
835   SBPlatform sb_platform;
836   if (m_opaque_sp) {
837     // No need to lock, the platform list is thread safe
838     sb_platform.SetSP(m_opaque_sp->GetPlatformList().GetAtIndex(idx));
839   }
840   return sb_platform;
841 }
842
843 uint32_t SBDebugger::GetNumAvailablePlatforms() {
844   uint32_t idx = 0;
845   while (true) {
846     if (!PluginManager::GetPlatformPluginNameAtIndex(idx)) {
847       break;
848     }
849     ++idx;
850   }
851   // +1 for the host platform, which should always appear first in the list.
852   return idx + 1;
853 }
854
855 SBStructuredData SBDebugger::GetAvailablePlatformInfoAtIndex(uint32_t idx) {
856   SBStructuredData data;
857   auto platform_dict = llvm::make_unique<StructuredData::Dictionary>();
858   llvm::StringRef name_str("name"), desc_str("description");
859
860   if (idx == 0) {
861     PlatformSP host_platform_sp(Platform::GetHostPlatform());
862     platform_dict->AddStringItem(
863         name_str, host_platform_sp->GetPluginName().GetStringRef());
864     platform_dict->AddStringItem(
865         desc_str, llvm::StringRef(host_platform_sp->GetDescription()));
866   } else if (idx > 0) {
867     const char *plugin_name =
868         PluginManager::GetPlatformPluginNameAtIndex(idx - 1);
869     if (!plugin_name) {
870       return data;
871     }
872     platform_dict->AddStringItem(name_str, llvm::StringRef(plugin_name));
873
874     const char *plugin_desc =
875         PluginManager::GetPlatformPluginDescriptionAtIndex(idx - 1);
876     if (!plugin_desc) {
877       return data;
878     }
879     platform_dict->AddStringItem(desc_str, llvm::StringRef(plugin_desc));
880   }
881
882   data.m_impl_up->SetObjectSP(
883       StructuredData::ObjectSP(platform_dict.release()));
884   return data;
885 }
886
887 void SBDebugger::DispatchInput(void *baton, const void *data, size_t data_len) {
888   DispatchInput(data, data_len);
889 }
890
891 void SBDebugger::DispatchInput(const void *data, size_t data_len) {
892   //    Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
893   //
894   //    if (log)
895   //        log->Printf ("SBDebugger(%p)::DispatchInput (data=\"%.*s\",
896   //        size_t=%" PRIu64 ")",
897   //                     m_opaque_sp.get(),
898   //                     (int) data_len,
899   //                     (const char *) data,
900   //                     (uint64_t)data_len);
901   //
902   //    if (m_opaque_sp)
903   //        m_opaque_sp->DispatchInput ((const char *) data, data_len);
904 }
905
906 void SBDebugger::DispatchInputInterrupt() {
907   if (m_opaque_sp)
908     m_opaque_sp->DispatchInputInterrupt();
909 }
910
911 void SBDebugger::DispatchInputEndOfFile() {
912   if (m_opaque_sp)
913     m_opaque_sp->DispatchInputEndOfFile();
914 }
915
916 void SBDebugger::PushInputReader(SBInputReader &reader) {}
917
918 void SBDebugger::RunCommandInterpreter(bool auto_handle_events,
919                                        bool spawn_thread) {
920   if (m_opaque_sp) {
921     CommandInterpreterRunOptions options;
922
923     m_opaque_sp->GetCommandInterpreter().RunCommandInterpreter(
924         auto_handle_events, spawn_thread, options);
925   }
926 }
927
928 void SBDebugger::RunCommandInterpreter(bool auto_handle_events,
929                                        bool spawn_thread,
930                                        SBCommandInterpreterRunOptions &options,
931                                        int &num_errors, bool &quit_requested,
932                                        bool &stopped_for_crash)
933
934 {
935   if (m_opaque_sp) {
936     CommandInterpreter &interp = m_opaque_sp->GetCommandInterpreter();
937     interp.RunCommandInterpreter(auto_handle_events, spawn_thread,
938                                  options.ref());
939     num_errors = interp.GetNumErrors();
940     quit_requested = interp.GetQuitRequested();
941     stopped_for_crash = interp.GetStoppedForCrash();
942   }
943 }
944
945 SBError SBDebugger::RunREPL(lldb::LanguageType language,
946                             const char *repl_options) {
947   SBError error;
948   if (m_opaque_sp)
949     error.ref() = m_opaque_sp->RunREPL(language, repl_options);
950   else
951     error.SetErrorString("invalid debugger");
952   return error;
953 }
954
955 void SBDebugger::reset(const DebuggerSP &debugger_sp) {
956   m_opaque_sp = debugger_sp;
957 }
958
959 Debugger *SBDebugger::get() const { return m_opaque_sp.get(); }
960
961 Debugger &SBDebugger::ref() const {
962   assert(m_opaque_sp.get());
963   return *m_opaque_sp;
964 }
965
966 const lldb::DebuggerSP &SBDebugger::get_sp() const { return m_opaque_sp; }
967
968 SBDebugger SBDebugger::FindDebuggerWithID(int id) {
969   // No need to lock, the debugger list is thread safe
970   SBDebugger sb_debugger;
971   DebuggerSP debugger_sp = Debugger::FindDebuggerWithID(id);
972   if (debugger_sp)
973     sb_debugger.reset(debugger_sp);
974   return sb_debugger;
975 }
976
977 const char *SBDebugger::GetInstanceName() {
978   return (m_opaque_sp ? m_opaque_sp->GetInstanceName().AsCString() : nullptr);
979 }
980
981 SBError SBDebugger::SetInternalVariable(const char *var_name, const char *value,
982                                         const char *debugger_instance_name) {
983   SBError sb_error;
984   DebuggerSP debugger_sp(Debugger::FindDebuggerWithInstanceName(
985       ConstString(debugger_instance_name)));
986   Status error;
987   if (debugger_sp) {
988     ExecutionContext exe_ctx(
989         debugger_sp->GetCommandInterpreter().GetExecutionContext());
990     error = debugger_sp->SetPropertyValue(&exe_ctx, eVarSetOperationAssign,
991                                           var_name, value);
992   } else {
993     error.SetErrorStringWithFormat("invalid debugger instance name '%s'",
994                                    debugger_instance_name);
995   }
996   if (error.Fail())
997     sb_error.SetError(error);
998   return sb_error;
999 }
1000
1001 SBStringList
1002 SBDebugger::GetInternalVariableValue(const char *var_name,
1003                                      const char *debugger_instance_name) {
1004   SBStringList ret_value;
1005   DebuggerSP debugger_sp(Debugger::FindDebuggerWithInstanceName(
1006       ConstString(debugger_instance_name)));
1007   Status error;
1008   if (debugger_sp) {
1009     ExecutionContext exe_ctx(
1010         debugger_sp->GetCommandInterpreter().GetExecutionContext());
1011     lldb::OptionValueSP value_sp(
1012         debugger_sp->GetPropertyValue(&exe_ctx, var_name, false, error));
1013     if (value_sp) {
1014       StreamString value_strm;
1015       value_sp->DumpValue(&exe_ctx, value_strm, OptionValue::eDumpOptionValue);
1016       const std::string &value_str = value_strm.GetString();
1017       if (!value_str.empty()) {
1018         StringList string_list;
1019         string_list.SplitIntoLines(value_str);
1020         return SBStringList(&string_list);
1021       }
1022     }
1023   }
1024   return SBStringList();
1025 }
1026
1027 uint32_t SBDebugger::GetTerminalWidth() const {
1028   return (m_opaque_sp ? m_opaque_sp->GetTerminalWidth() : 0);
1029 }
1030
1031 void SBDebugger::SetTerminalWidth(uint32_t term_width) {
1032   if (m_opaque_sp)
1033     m_opaque_sp->SetTerminalWidth(term_width);
1034 }
1035
1036 const char *SBDebugger::GetPrompt() const {
1037   Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
1038
1039   if (log)
1040     log->Printf("SBDebugger(%p)::GetPrompt () => \"%s\"",
1041                 static_cast<void *>(m_opaque_sp.get()),
1042                 (m_opaque_sp ? m_opaque_sp->GetPrompt().str().c_str() : ""));
1043
1044   return (m_opaque_sp ? ConstString(m_opaque_sp->GetPrompt()).GetCString()
1045                       : nullptr);
1046 }
1047
1048 void SBDebugger::SetPrompt(const char *prompt) {
1049   if (m_opaque_sp)
1050     m_opaque_sp->SetPrompt(llvm::StringRef::withNullAsEmpty(prompt));
1051 }
1052
1053 ScriptLanguage SBDebugger::GetScriptLanguage() const {
1054   return (m_opaque_sp ? m_opaque_sp->GetScriptLanguage() : eScriptLanguageNone);
1055 }
1056
1057 void SBDebugger::SetScriptLanguage(ScriptLanguage script_lang) {
1058   if (m_opaque_sp) {
1059     m_opaque_sp->SetScriptLanguage(script_lang);
1060   }
1061 }
1062
1063 bool SBDebugger::SetUseExternalEditor(bool value) {
1064   return (m_opaque_sp ? m_opaque_sp->SetUseExternalEditor(value) : false);
1065 }
1066
1067 bool SBDebugger::GetUseExternalEditor() {
1068   return (m_opaque_sp ? m_opaque_sp->GetUseExternalEditor() : false);
1069 }
1070
1071 bool SBDebugger::SetUseColor(bool value) {
1072   return (m_opaque_sp ? m_opaque_sp->SetUseColor(value) : false);
1073 }
1074
1075 bool SBDebugger::GetUseColor() const {
1076   return (m_opaque_sp ? m_opaque_sp->GetUseColor() : false);
1077 }
1078
1079 bool SBDebugger::GetDescription(SBStream &description) {
1080   Stream &strm = description.ref();
1081
1082   if (m_opaque_sp) {
1083     const char *name = m_opaque_sp->GetInstanceName().AsCString();
1084     user_id_t id = m_opaque_sp->GetID();
1085     strm.Printf("Debugger (instance: \"%s\", id: %" PRIu64 ")", name, id);
1086   } else
1087     strm.PutCString("No value");
1088
1089   return true;
1090 }
1091
1092 user_id_t SBDebugger::GetID() {
1093   return (m_opaque_sp ? m_opaque_sp->GetID() : LLDB_INVALID_UID);
1094 }
1095
1096 SBError SBDebugger::SetCurrentPlatform(const char *platform_name_cstr) {
1097   SBError sb_error;
1098   if (m_opaque_sp) {
1099     if (platform_name_cstr && platform_name_cstr[0]) {
1100       ConstString platform_name(platform_name_cstr);
1101       PlatformSP platform_sp(Platform::Find(platform_name));
1102
1103       if (platform_sp) {
1104         // Already have a platform with this name, just select it
1105         m_opaque_sp->GetPlatformList().SetSelectedPlatform(platform_sp);
1106       } else {
1107         // We don't have a platform by this name yet, create one
1108         platform_sp = Platform::Create(platform_name, sb_error.ref());
1109         if (platform_sp) {
1110           // We created the platform, now append and select it
1111           bool make_selected = true;
1112           m_opaque_sp->GetPlatformList().Append(platform_sp, make_selected);
1113         }
1114       }
1115     } else {
1116       sb_error.ref().SetErrorString("invalid platform name");
1117     }
1118   } else {
1119     sb_error.ref().SetErrorString("invalid debugger");
1120   }
1121   return sb_error;
1122 }
1123
1124 bool SBDebugger::SetCurrentPlatformSDKRoot(const char *sysroot) {
1125   Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
1126   if (m_opaque_sp) {
1127     PlatformSP platform_sp(
1128         m_opaque_sp->GetPlatformList().GetSelectedPlatform());
1129
1130     if (platform_sp) {
1131       if (log && sysroot)
1132         log->Printf("SBDebugger::SetCurrentPlatformSDKRoot (\"%s\")", sysroot);
1133       platform_sp->SetSDKRootDirectory(ConstString(sysroot));
1134       return true;
1135     }
1136   }
1137   return false;
1138 }
1139
1140 bool SBDebugger::GetCloseInputOnEOF() const {
1141   return (m_opaque_sp ? m_opaque_sp->GetCloseInputOnEOF() : false);
1142 }
1143
1144 void SBDebugger::SetCloseInputOnEOF(bool b) {
1145   if (m_opaque_sp)
1146     m_opaque_sp->SetCloseInputOnEOF(b);
1147 }
1148
1149 SBTypeCategory SBDebugger::GetCategory(const char *category_name) {
1150   if (!category_name || *category_name == 0)
1151     return SBTypeCategory();
1152
1153   TypeCategoryImplSP category_sp;
1154
1155   if (DataVisualization::Categories::GetCategory(ConstString(category_name),
1156                                                  category_sp, false))
1157     return SBTypeCategory(category_sp);
1158   else
1159     return SBTypeCategory();
1160 }
1161
1162 SBTypeCategory SBDebugger::GetCategory(lldb::LanguageType lang_type) {
1163   TypeCategoryImplSP category_sp;
1164   if (DataVisualization::Categories::GetCategory(lang_type, category_sp))
1165     return SBTypeCategory(category_sp);
1166   else
1167     return SBTypeCategory();
1168 }
1169
1170 SBTypeCategory SBDebugger::CreateCategory(const char *category_name) {
1171   if (!category_name || *category_name == 0)
1172     return SBTypeCategory();
1173
1174   TypeCategoryImplSP category_sp;
1175
1176   if (DataVisualization::Categories::GetCategory(ConstString(category_name),
1177                                                  category_sp, true))
1178     return SBTypeCategory(category_sp);
1179   else
1180     return SBTypeCategory();
1181 }
1182
1183 bool SBDebugger::DeleteCategory(const char *category_name) {
1184   if (!category_name || *category_name == 0)
1185     return false;
1186
1187   return DataVisualization::Categories::Delete(ConstString(category_name));
1188 }
1189
1190 uint32_t SBDebugger::GetNumCategories() {
1191   return DataVisualization::Categories::GetCount();
1192 }
1193
1194 SBTypeCategory SBDebugger::GetCategoryAtIndex(uint32_t index) {
1195   return SBTypeCategory(
1196       DataVisualization::Categories::GetCategoryAtIndex(index));
1197 }
1198
1199 SBTypeCategory SBDebugger::GetDefaultCategory() {
1200   return GetCategory("default");
1201 }
1202
1203 SBTypeFormat SBDebugger::GetFormatForType(SBTypeNameSpecifier type_name) {
1204   SBTypeCategory default_category_sb = GetDefaultCategory();
1205   if (default_category_sb.GetEnabled())
1206     return default_category_sb.GetFormatForType(type_name);
1207   return SBTypeFormat();
1208 }
1209
1210 #ifndef LLDB_DISABLE_PYTHON
1211 SBTypeSummary SBDebugger::GetSummaryForType(SBTypeNameSpecifier type_name) {
1212   if (!type_name.IsValid())
1213     return SBTypeSummary();
1214   return SBTypeSummary(DataVisualization::GetSummaryForType(type_name.GetSP()));
1215 }
1216 #endif // LLDB_DISABLE_PYTHON
1217
1218 SBTypeFilter SBDebugger::GetFilterForType(SBTypeNameSpecifier type_name) {
1219   if (!type_name.IsValid())
1220     return SBTypeFilter();
1221   return SBTypeFilter(DataVisualization::GetFilterForType(type_name.GetSP()));
1222 }
1223
1224 #ifndef LLDB_DISABLE_PYTHON
1225 SBTypeSynthetic SBDebugger::GetSyntheticForType(SBTypeNameSpecifier type_name) {
1226   if (!type_name.IsValid())
1227     return SBTypeSynthetic();
1228   return SBTypeSynthetic(
1229       DataVisualization::GetSyntheticForType(type_name.GetSP()));
1230 }
1231 #endif // LLDB_DISABLE_PYTHON
1232
1233 static llvm::ArrayRef<const char *> GetCategoryArray(const char **categories) {
1234   if (categories == nullptr)
1235     return {};
1236   size_t len = 0;
1237   while (categories[len] != nullptr)
1238     ++len;
1239   return llvm::makeArrayRef(categories, len);
1240 }
1241
1242 bool SBDebugger::EnableLog(const char *channel, const char **categories) {
1243   if (m_opaque_sp) {
1244     uint32_t log_options =
1245         LLDB_LOG_OPTION_PREPEND_TIMESTAMP | LLDB_LOG_OPTION_PREPEND_THREAD_NAME;
1246     std::string error;
1247     llvm::raw_string_ostream error_stream(error);
1248     return m_opaque_sp->EnableLog(channel, GetCategoryArray(categories), "",
1249                                   log_options, error_stream);
1250   } else
1251     return false;
1252 }
1253
1254 void SBDebugger::SetLoggingCallback(lldb::LogOutputCallback log_callback,
1255                                     void *baton) {
1256   if (m_opaque_sp) {
1257     return m_opaque_sp->SetLoggingCallback(log_callback, baton);
1258   }
1259 }