1 //===-- SBDebugger.cpp ----------------------------------------------------===//
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 #include "lldb/Utility/ReproducerInstrumentation.h"
10 #include "SystemInitializerFull.h"
11 
12 #include "lldb/API/SBDebugger.h"
13 
14 #include "lldb/API/SBBroadcaster.h"
15 #include "lldb/API/SBCommandInterpreter.h"
16 #include "lldb/API/SBCommandInterpreterRunOptions.h"
17 #include "lldb/API/SBCommandReturnObject.h"
18 #include "lldb/API/SBError.h"
19 #include "lldb/API/SBEvent.h"
20 #include "lldb/API/SBFile.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/Progress.h"
40 #include "lldb/Core/StreamFile.h"
41 #include "lldb/Core/StructuredDataImpl.h"
42 #include "lldb/DataFormatters/DataVisualization.h"
43 #include "lldb/Host/Config.h"
44 #include "lldb/Host/XML.h"
45 #include "lldb/Initialization/SystemLifetimeManager.h"
46 #include "lldb/Interpreter/CommandInterpreter.h"
47 #include "lldb/Interpreter/OptionArgParser.h"
48 #include "lldb/Interpreter/OptionGroupPlatform.h"
49 #include "lldb/Target/Process.h"
50 #include "lldb/Target/TargetList.h"
51 #include "lldb/Utility/Args.h"
52 #include "lldb/Utility/State.h"
53 #include "lldb/Version/Version.h"
54 
55 #include "llvm/ADT/STLExtras.h"
56 #include "llvm/ADT/StringRef.h"
57 #include "llvm/Support/DynamicLibrary.h"
58 #include "llvm/Support/ManagedStatic.h"
59 
60 using namespace lldb;
61 using namespace lldb_private;
62 
63 static llvm::sys::DynamicLibrary LoadPlugin(const lldb::DebuggerSP &debugger_sp,
64                                             const FileSpec &spec,
65                                             Status &error) {
66   llvm::sys::DynamicLibrary dynlib =
67       llvm::sys::DynamicLibrary::getPermanentLibrary(spec.GetPath().c_str());
68   if (dynlib.isValid()) {
69     typedef bool (*LLDBCommandPluginInit)(lldb::SBDebugger & debugger);
70 
71     lldb::SBDebugger debugger_sb(debugger_sp);
72     // This calls the bool lldb::PluginInitialize(lldb::SBDebugger debugger)
73     // function.
74     // TODO: mangle this differently for your system - on OSX, the first
75     // underscore needs to be removed and the second one stays
76     LLDBCommandPluginInit init_func =
77         (LLDBCommandPluginInit)(uintptr_t)dynlib.getAddressOfSymbol(
78             "_ZN4lldb16PluginInitializeENS_10SBDebuggerE");
79     if (init_func) {
80       if (init_func(debugger_sb))
81         return dynlib;
82       else
83         error.SetErrorString("plug-in refused to load "
84                              "(lldb::PluginInitialize(lldb::SBDebugger) "
85                              "returned false)");
86     } else {
87       error.SetErrorString("plug-in is missing the required initialization: "
88                            "lldb::PluginInitialize(lldb::SBDebugger)");
89     }
90   } else {
91     if (FileSystem::Instance().Exists(spec))
92       error.SetErrorString("this file does not represent a loadable dylib");
93     else
94       error.SetErrorString("no such file");
95   }
96   return llvm::sys::DynamicLibrary();
97 }
98 
99 static llvm::ManagedStatic<SystemLifetimeManager> g_debugger_lifetime;
100 
101 SBError SBInputReader::Initialize(
102     lldb::SBDebugger &sb_debugger,
103     unsigned long (*callback)(void *, lldb::SBInputReader *,
104                               lldb::InputReaderAction, char const *,
105                               unsigned long),
106     void *a, lldb::InputReaderGranularity b, char const *c, char const *d,
107     bool e) {
108   LLDB_RECORD_DUMMY(
109       lldb::SBError, SBInputReader, Initialize,
110       (lldb::SBDebugger &,
111        unsigned long (*)(void *, lldb::SBInputReader *, lldb::InputReaderAction,
112                          const char *, unsigned long),
113        void *, lldb::InputReaderGranularity, const char *, const char *, bool),
114       sb_debugger, callback, a, b, c, d, e);
115 
116   return SBError();
117 }
118 
119 void SBInputReader::SetIsDone(bool b) {
120   LLDB_RECORD_METHOD(void, SBInputReader, SetIsDone, (bool), b);
121 }
122 
123 bool SBInputReader::IsActive() const {
124   LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBInputReader, IsActive);
125 
126   return false;
127 }
128 
129 SBDebugger::SBDebugger() { LLDB_RECORD_CONSTRUCTOR_NO_ARGS(SBDebugger); }
130 
131 SBDebugger::SBDebugger(const lldb::DebuggerSP &debugger_sp)
132     : m_opaque_sp(debugger_sp) {
133   LLDB_RECORD_CONSTRUCTOR(SBDebugger, (const lldb::DebuggerSP &), debugger_sp);
134 }
135 
136 SBDebugger::SBDebugger(const SBDebugger &rhs) : m_opaque_sp(rhs.m_opaque_sp) {
137   LLDB_RECORD_CONSTRUCTOR(SBDebugger, (const lldb::SBDebugger &), rhs);
138 }
139 
140 SBDebugger::~SBDebugger() = default;
141 
142 SBDebugger &SBDebugger::operator=(const SBDebugger &rhs) {
143   LLDB_RECORD_METHOD(lldb::SBDebugger &,
144                      SBDebugger, operator=,(const lldb::SBDebugger &), rhs);
145 
146   if (this != &rhs) {
147     m_opaque_sp = rhs.m_opaque_sp;
148   }
149   return *this;
150 }
151 
152 const char *SBDebugger::GetBroadcasterClass() {
153   LLDB_RECORD_STATIC_METHOD_NO_ARGS(const char *, SBDebugger,
154                                     GetBroadcasterClass);
155 
156   return Debugger::GetStaticBroadcasterClass().AsCString();
157 }
158 
159 const char *SBDebugger::GetProgressFromEvent(const lldb::SBEvent &event,
160                                              uint64_t &progress_id,
161                                              uint64_t &completed,
162                                              uint64_t &total,
163                                              bool &is_debugger_specific) {
164   const Debugger::ProgressEventData *progress_data =
165       Debugger::ProgressEventData::GetEventDataFromEvent(event.get());
166   if (progress_data == nullptr)
167     return nullptr;
168   progress_id = progress_data->GetID();
169   completed = progress_data->GetCompleted();
170   total = progress_data->GetTotal();
171   is_debugger_specific = progress_data->IsDebuggerSpecific();
172   // We must record the static method _after_ the out parameters have been
173   // filled in.
174   LLDB_RECORD_STATIC_METHOD(
175       const char *, SBDebugger, GetProgressFromEvent,
176       (const lldb::SBEvent &, uint64_t &, uint64_t &, uint64_t &, bool &),
177       event, progress_id, completed, total, is_debugger_specific);
178   return progress_data->GetMessage().c_str();
179 }
180 
181 SBBroadcaster SBDebugger::GetBroadcaster() {
182   LLDB_RECORD_METHOD_NO_ARGS(lldb::SBBroadcaster, SBDebugger, GetBroadcaster);
183   SBBroadcaster broadcaster(&m_opaque_sp->GetBroadcaster(), false);
184   return broadcaster;
185 }
186 
187 void SBDebugger::Initialize() {
188   LLDB_RECORD_STATIC_METHOD_NO_ARGS(void, SBDebugger, Initialize);
189   SBError ignored = SBDebugger::InitializeWithErrorHandling();
190 }
191 
192 lldb::SBError SBDebugger::InitializeWithErrorHandling() {
193   LLDB_RECORD_STATIC_METHOD_NO_ARGS(lldb::SBError, SBDebugger,
194                                     InitializeWithErrorHandling);
195 
196   SBError error;
197   if (auto e = g_debugger_lifetime->Initialize(
198           std::make_unique<SystemInitializerFull>(), LoadPlugin)) {
199     error.SetError(Status(std::move(e)));
200   }
201   return error;
202 }
203 
204 void SBDebugger::Terminate() {
205   LLDB_RECORD_STATIC_METHOD_NO_ARGS(void, SBDebugger, Terminate);
206 
207   g_debugger_lifetime->Terminate();
208 }
209 
210 void SBDebugger::Clear() {
211   LLDB_RECORD_METHOD_NO_ARGS(void, SBDebugger, Clear);
212 
213   if (m_opaque_sp)
214     m_opaque_sp->ClearIOHandlers();
215 
216   m_opaque_sp.reset();
217 }
218 
219 SBDebugger SBDebugger::Create() {
220   LLDB_RECORD_STATIC_METHOD_NO_ARGS(lldb::SBDebugger, SBDebugger, Create);
221 
222   return SBDebugger::Create(false, nullptr, nullptr);
223 }
224 
225 SBDebugger SBDebugger::Create(bool source_init_files) {
226   LLDB_RECORD_STATIC_METHOD(lldb::SBDebugger, SBDebugger, Create, (bool),
227                             source_init_files);
228 
229   return SBDebugger::Create(source_init_files, nullptr, nullptr);
230 }
231 
232 SBDebugger SBDebugger::Create(bool source_init_files,
233                               lldb::LogOutputCallback callback, void *baton)
234 
235 {
236   LLDB_RECORD_DUMMY(lldb::SBDebugger, SBDebugger, Create,
237                     (bool, lldb::LogOutputCallback, void *), source_init_files,
238                     callback, baton);
239 
240   SBDebugger debugger;
241 
242   // Currently we have issues if this function is called simultaneously on two
243   // different threads. The issues mainly revolve around the fact that the
244   // lldb_private::FormatManager uses global collections and having two threads
245   // parsing the .lldbinit files can cause mayhem. So to get around this for
246   // now we need to use a mutex to prevent bad things from happening.
247   static std::recursive_mutex g_mutex;
248   std::lock_guard<std::recursive_mutex> guard(g_mutex);
249 
250   debugger.reset(Debugger::CreateInstance(callback, baton));
251 
252   SBCommandInterpreter interp = debugger.GetCommandInterpreter();
253   if (source_init_files) {
254     interp.get()->SkipLLDBInitFiles(false);
255     interp.get()->SkipAppInitFiles(false);
256     SBCommandReturnObject result;
257     interp.SourceInitFileInHomeDirectory(result, false);
258   } else {
259     interp.get()->SkipLLDBInitFiles(true);
260     interp.get()->SkipAppInitFiles(true);
261   }
262   return debugger;
263 }
264 
265 void SBDebugger::Destroy(SBDebugger &debugger) {
266   LLDB_RECORD_STATIC_METHOD(void, SBDebugger, Destroy, (lldb::SBDebugger &),
267                             debugger);
268 
269   Debugger::Destroy(debugger.m_opaque_sp);
270 
271   if (debugger.m_opaque_sp.get() != nullptr)
272     debugger.m_opaque_sp.reset();
273 }
274 
275 void SBDebugger::MemoryPressureDetected() {
276   LLDB_RECORD_STATIC_METHOD_NO_ARGS(void, SBDebugger, MemoryPressureDetected);
277 
278   // Since this function can be call asynchronously, we allow it to be non-
279   // mandatory. We have seen deadlocks with this function when called so we
280   // need to safeguard against this until we can determine what is causing the
281   // deadlocks.
282 
283   const bool mandatory = false;
284 
285   ModuleList::RemoveOrphanSharedModules(mandatory);
286 }
287 
288 bool SBDebugger::IsValid() const {
289   LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBDebugger, IsValid);
290   return this->operator bool();
291 }
292 SBDebugger::operator bool() const {
293   LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBDebugger, operator bool);
294 
295   return m_opaque_sp.get() != nullptr;
296 }
297 
298 void SBDebugger::SetAsync(bool b) {
299   LLDB_RECORD_METHOD(void, SBDebugger, SetAsync, (bool), b);
300 
301   if (m_opaque_sp)
302     m_opaque_sp->SetAsyncExecution(b);
303 }
304 
305 bool SBDebugger::GetAsync() {
306   LLDB_RECORD_METHOD_NO_ARGS(bool, SBDebugger, GetAsync);
307 
308   return (m_opaque_sp ? m_opaque_sp->GetAsyncExecution() : false);
309 }
310 
311 void SBDebugger::SkipLLDBInitFiles(bool b) {
312   LLDB_RECORD_METHOD(void, SBDebugger, SkipLLDBInitFiles, (bool), b);
313 
314   if (m_opaque_sp)
315     m_opaque_sp->GetCommandInterpreter().SkipLLDBInitFiles(b);
316 }
317 
318 void SBDebugger::SkipAppInitFiles(bool b) {
319   LLDB_RECORD_METHOD(void, SBDebugger, SkipAppInitFiles, (bool), b);
320 
321   if (m_opaque_sp)
322     m_opaque_sp->GetCommandInterpreter().SkipAppInitFiles(b);
323 }
324 
325 void SBDebugger::SetInputFileHandle(FILE *fh, bool transfer_ownership) {
326   LLDB_RECORD_METHOD(void, SBDebugger, SetInputFileHandle, (FILE *, bool), fh,
327                      transfer_ownership);
328   if (m_opaque_sp)
329     m_opaque_sp->SetInputFile(
330         (FileSP)std::make_shared<NativeFile>(fh, transfer_ownership));
331 }
332 
333 SBError SBDebugger::SetInputString(const char *data) {
334   LLDB_RECORD_METHOD(SBError, SBDebugger, SetInputString, (const char *), data);
335   SBError sb_error;
336   if (data == nullptr) {
337     sb_error.SetErrorString("String data is null");
338     return sb_error;
339   }
340 
341   size_t size = strlen(data);
342   if (size == 0) {
343     sb_error.SetErrorString("String data is empty");
344     return sb_error;
345   }
346 
347   if (!m_opaque_sp) {
348     sb_error.SetErrorString("invalid debugger");
349     return sb_error;
350   }
351 
352   sb_error.SetError(m_opaque_sp->SetInputString(data));
353   return sb_error;
354 }
355 
356 // Shouldn't really be settable after initialization as this could cause lots
357 // of problems; don't want users trying to switch modes in the middle of a
358 // debugging session.
359 SBError SBDebugger::SetInputFile(SBFile file) {
360   LLDB_RECORD_METHOD(SBError, SBDebugger, SetInputFile, (SBFile), file);
361 
362   SBError error;
363   if (!m_opaque_sp) {
364     error.ref().SetErrorString("invalid debugger");
365     return error;
366   }
367   error.SetError(m_opaque_sp->SetInputFile(file.m_opaque_sp));
368   return error;
369 }
370 
371 SBError SBDebugger::SetInputFile(FileSP file_sp) {
372   LLDB_RECORD_METHOD(SBError, SBDebugger, SetInputFile, (FileSP), file_sp);
373   return SetInputFile(SBFile(file_sp));
374 }
375 
376 SBError SBDebugger::SetOutputFile(FileSP file_sp) {
377   LLDB_RECORD_METHOD(SBError, SBDebugger, SetOutputFile, (FileSP), file_sp);
378   return SetOutputFile(SBFile(file_sp));
379 }
380 
381 void SBDebugger::SetOutputFileHandle(FILE *fh, bool transfer_ownership) {
382   LLDB_RECORD_METHOD(void, SBDebugger, SetOutputFileHandle, (FILE *, bool), fh,
383                      transfer_ownership);
384   SetOutputFile((FileSP)std::make_shared<NativeFile>(fh, transfer_ownership));
385 }
386 
387 SBError SBDebugger::SetOutputFile(SBFile file) {
388   LLDB_RECORD_METHOD(SBError, SBDebugger, SetOutputFile, (SBFile file), file);
389   SBError error;
390   if (!m_opaque_sp) {
391     error.ref().SetErrorString("invalid debugger");
392     return error;
393   }
394   if (!file) {
395     error.ref().SetErrorString("invalid file");
396     return error;
397   }
398   m_opaque_sp->SetOutputFile(file.m_opaque_sp);
399   return error;
400 }
401 
402 void SBDebugger::SetErrorFileHandle(FILE *fh, bool transfer_ownership) {
403   LLDB_RECORD_METHOD(void, SBDebugger, SetErrorFileHandle, (FILE *, bool), fh,
404                      transfer_ownership);
405   SetErrorFile((FileSP)std::make_shared<NativeFile>(fh, transfer_ownership));
406 }
407 
408 SBError SBDebugger::SetErrorFile(FileSP file_sp) {
409   LLDB_RECORD_METHOD(SBError, SBDebugger, SetErrorFile, (FileSP), file_sp);
410   return SetErrorFile(SBFile(file_sp));
411 }
412 
413 SBError SBDebugger::SetErrorFile(SBFile file) {
414   LLDB_RECORD_METHOD(SBError, SBDebugger, SetErrorFile, (SBFile file), file);
415   SBError error;
416   if (!m_opaque_sp) {
417     error.ref().SetErrorString("invalid debugger");
418     return error;
419   }
420   if (!file) {
421     error.ref().SetErrorString("invalid file");
422     return error;
423   }
424   m_opaque_sp->SetErrorFile(file.m_opaque_sp);
425   return error;
426 }
427 
428 FILE *SBDebugger::GetInputFileHandle() {
429   LLDB_RECORD_METHOD_NO_ARGS(FILE *, SBDebugger, GetInputFileHandle);
430   if (m_opaque_sp) {
431     File &file_sp = m_opaque_sp->GetInputFile();
432     return file_sp.GetStream();
433   }
434   return nullptr;
435 }
436 
437 SBFile SBDebugger::GetInputFile() {
438   LLDB_RECORD_METHOD_NO_ARGS(SBFile, SBDebugger, GetInputFile);
439   if (m_opaque_sp) {
440     return SBFile(m_opaque_sp->GetInputFileSP());
441   }
442   return SBFile();
443 }
444 
445 FILE *SBDebugger::GetOutputFileHandle() {
446   LLDB_RECORD_METHOD_NO_ARGS(FILE *, SBDebugger, GetOutputFileHandle);
447   if (m_opaque_sp) {
448     StreamFile &stream_file = m_opaque_sp->GetOutputStream();
449     return stream_file.GetFile().GetStream();
450   }
451   return nullptr;
452 }
453 
454 SBFile SBDebugger::GetOutputFile() {
455   LLDB_RECORD_METHOD_NO_ARGS(SBFile, SBDebugger, GetOutputFile);
456   if (m_opaque_sp) {
457     SBFile file(m_opaque_sp->GetOutputStream().GetFileSP());
458     return file;
459   }
460   return SBFile();
461 }
462 
463 FILE *SBDebugger::GetErrorFileHandle() {
464   LLDB_RECORD_METHOD_NO_ARGS(FILE *, SBDebugger, GetErrorFileHandle);
465 
466   if (m_opaque_sp) {
467     StreamFile &stream_file = m_opaque_sp->GetErrorStream();
468     return stream_file.GetFile().GetStream();
469   }
470   return nullptr;
471 }
472 
473 SBFile SBDebugger::GetErrorFile() {
474   LLDB_RECORD_METHOD_NO_ARGS(SBFile, SBDebugger, GetErrorFile);
475   SBFile file;
476   if (m_opaque_sp) {
477     SBFile file(m_opaque_sp->GetErrorStream().GetFileSP());
478     return file;
479   }
480   return SBFile();
481 }
482 
483 void SBDebugger::SaveInputTerminalState() {
484   LLDB_RECORD_DUMMY_NO_ARGS(void, SBDebugger, SaveInputTerminalState);
485 
486   if (m_opaque_sp)
487     m_opaque_sp->SaveInputTerminalState();
488 }
489 
490 void SBDebugger::RestoreInputTerminalState() {
491   LLDB_RECORD_DUMMY_NO_ARGS(void, SBDebugger, RestoreInputTerminalState);
492 
493   if (m_opaque_sp)
494     m_opaque_sp->RestoreInputTerminalState();
495 }
496 SBCommandInterpreter SBDebugger::GetCommandInterpreter() {
497   LLDB_RECORD_METHOD_NO_ARGS(lldb::SBCommandInterpreter, SBDebugger,
498                              GetCommandInterpreter);
499 
500   SBCommandInterpreter sb_interpreter;
501   if (m_opaque_sp)
502     sb_interpreter.reset(&m_opaque_sp->GetCommandInterpreter());
503 
504   return sb_interpreter;
505 }
506 
507 void SBDebugger::HandleCommand(const char *command) {
508   LLDB_RECORD_METHOD(void, SBDebugger, HandleCommand, (const char *), command);
509 
510   if (m_opaque_sp) {
511     TargetSP target_sp(m_opaque_sp->GetSelectedTarget());
512     std::unique_lock<std::recursive_mutex> lock;
513     if (target_sp)
514       lock = std::unique_lock<std::recursive_mutex>(target_sp->GetAPIMutex());
515 
516     SBCommandInterpreter sb_interpreter(GetCommandInterpreter());
517     SBCommandReturnObject result;
518 
519     sb_interpreter.HandleCommand(command, result, false);
520 
521     result.PutError(m_opaque_sp->GetErrorStream().GetFileSP());
522     result.PutOutput(m_opaque_sp->GetOutputStream().GetFileSP());
523 
524     if (!m_opaque_sp->GetAsyncExecution()) {
525       SBProcess process(GetCommandInterpreter().GetProcess());
526       ProcessSP process_sp(process.GetSP());
527       if (process_sp) {
528         EventSP event_sp;
529         ListenerSP lldb_listener_sp = m_opaque_sp->GetListener();
530         while (lldb_listener_sp->GetEventForBroadcaster(
531             process_sp.get(), event_sp, std::chrono::seconds(0))) {
532           SBEvent event(event_sp);
533           HandleProcessEvent(process, event, GetOutputFile(), GetErrorFile());
534         }
535       }
536     }
537   }
538 }
539 
540 SBListener SBDebugger::GetListener() {
541   LLDB_RECORD_METHOD_NO_ARGS(lldb::SBListener, SBDebugger, GetListener);
542 
543   SBListener sb_listener;
544   if (m_opaque_sp)
545     sb_listener.reset(m_opaque_sp->GetListener());
546 
547   return sb_listener;
548 }
549 
550 void SBDebugger::HandleProcessEvent(const SBProcess &process,
551                                     const SBEvent &event, SBFile out,
552                                     SBFile err) {
553   LLDB_RECORD_METHOD(
554       void, SBDebugger, HandleProcessEvent,
555       (const lldb::SBProcess &, const lldb::SBEvent &, SBFile, SBFile), process,
556       event, out, err);
557 
558   return HandleProcessEvent(process, event, out.m_opaque_sp, err.m_opaque_sp);
559 }
560 
561 void SBDebugger::HandleProcessEvent(const SBProcess &process,
562                                     const SBEvent &event, FILE *out,
563                                     FILE *err) {
564   LLDB_RECORD_METHOD(
565       void, SBDebugger, HandleProcessEvent,
566       (const lldb::SBProcess &, const lldb::SBEvent &, FILE *, FILE *), process,
567       event, out, err);
568 
569   FileSP outfile = std::make_shared<NativeFile>(out, false);
570   FileSP errfile = std::make_shared<NativeFile>(err, false);
571   return HandleProcessEvent(process, event, outfile, errfile);
572 }
573 
574 void SBDebugger::HandleProcessEvent(const SBProcess &process,
575                                     const SBEvent &event, FileSP out_sp,
576                                     FileSP err_sp) {
577 
578   LLDB_RECORD_METHOD(
579       void, SBDebugger, HandleProcessEvent,
580       (const lldb::SBProcess &, const lldb::SBEvent &, FileSP, FileSP), process,
581       event, out_sp, err_sp);
582 
583   if (!process.IsValid())
584     return;
585 
586   TargetSP target_sp(process.GetTarget().GetSP());
587   if (!target_sp)
588     return;
589 
590   const uint32_t event_type = event.GetType();
591   char stdio_buffer[1024];
592   size_t len;
593 
594   std::lock_guard<std::recursive_mutex> guard(target_sp->GetAPIMutex());
595 
596   if (event_type &
597       (Process::eBroadcastBitSTDOUT | Process::eBroadcastBitStateChanged)) {
598     // Drain stdout when we stop just in case we have any bytes
599     while ((len = process.GetSTDOUT(stdio_buffer, sizeof(stdio_buffer))) > 0)
600       if (out_sp)
601         out_sp->Write(stdio_buffer, len);
602   }
603 
604   if (event_type &
605       (Process::eBroadcastBitSTDERR | Process::eBroadcastBitStateChanged)) {
606     // Drain stderr when we stop just in case we have any bytes
607     while ((len = process.GetSTDERR(stdio_buffer, sizeof(stdio_buffer))) > 0)
608       if (err_sp)
609         err_sp->Write(stdio_buffer, len);
610   }
611 
612   if (event_type & Process::eBroadcastBitStateChanged) {
613     StateType event_state = SBProcess::GetStateFromEvent(event);
614 
615     if (event_state == eStateInvalid)
616       return;
617 
618     bool is_stopped = StateIsStoppedState(event_state);
619     if (!is_stopped)
620       process.ReportEventState(event, out_sp);
621   }
622 }
623 
624 SBSourceManager SBDebugger::GetSourceManager() {
625   LLDB_RECORD_METHOD_NO_ARGS(lldb::SBSourceManager, SBDebugger,
626                              GetSourceManager);
627 
628   SBSourceManager sb_source_manager(*this);
629   return sb_source_manager;
630 }
631 
632 bool SBDebugger::GetDefaultArchitecture(char *arch_name, size_t arch_name_len) {
633   LLDB_RECORD_CHAR_PTR_STATIC_METHOD(bool, SBDebugger, GetDefaultArchitecture,
634                                      (char *, size_t), arch_name, "",
635                                      arch_name_len);
636 
637   if (arch_name && arch_name_len) {
638     ArchSpec default_arch = Target::GetDefaultArchitecture();
639 
640     if (default_arch.IsValid()) {
641       const std::string &triple_str = default_arch.GetTriple().str();
642       if (!triple_str.empty())
643         ::snprintf(arch_name, arch_name_len, "%s", triple_str.c_str());
644       else
645         ::snprintf(arch_name, arch_name_len, "%s",
646                    default_arch.GetArchitectureName());
647       return true;
648     }
649   }
650   if (arch_name && arch_name_len)
651     arch_name[0] = '\0';
652   return false;
653 }
654 
655 bool SBDebugger::SetDefaultArchitecture(const char *arch_name) {
656   LLDB_RECORD_STATIC_METHOD(bool, SBDebugger, SetDefaultArchitecture,
657                             (const char *), arch_name);
658 
659   if (arch_name) {
660     ArchSpec arch(arch_name);
661     if (arch.IsValid()) {
662       Target::SetDefaultArchitecture(arch);
663       return true;
664     }
665   }
666   return false;
667 }
668 
669 ScriptLanguage
670 SBDebugger::GetScriptingLanguage(const char *script_language_name) {
671   LLDB_RECORD_METHOD(lldb::ScriptLanguage, SBDebugger, GetScriptingLanguage,
672                      (const char *), script_language_name);
673 
674   if (!script_language_name)
675     return eScriptLanguageDefault;
676   return OptionArgParser::ToScriptLanguage(
677       llvm::StringRef(script_language_name), eScriptLanguageDefault, nullptr);
678 }
679 
680 SBStructuredData
681 SBDebugger::GetScriptInterpreterInfo(lldb::ScriptLanguage language) {
682   LLDB_RECORD_METHOD(SBStructuredData, SBDebugger, GetScriptInterpreterInfo,
683                      (lldb::ScriptLanguage), language);
684   SBStructuredData data;
685   if (m_opaque_sp) {
686     lldb_private::ScriptInterpreter *interp =
687         m_opaque_sp->GetScriptInterpreter(language);
688     if (interp) {
689       data.m_impl_up->SetObjectSP(interp->GetInterpreterInfo());
690     }
691   }
692   return data;
693 }
694 
695 const char *SBDebugger::GetVersionString() {
696   LLDB_RECORD_STATIC_METHOD_NO_ARGS(const char *, SBDebugger, GetVersionString);
697 
698   return lldb_private::GetVersion();
699 }
700 
701 const char *SBDebugger::StateAsCString(StateType state) {
702   LLDB_RECORD_STATIC_METHOD(const char *, SBDebugger, StateAsCString,
703                             (lldb::StateType), state);
704 
705   return lldb_private::StateAsCString(state);
706 }
707 
708 static void AddBoolConfigEntry(StructuredData::Dictionary &dict,
709                                llvm::StringRef name, bool value,
710                                llvm::StringRef description) {
711   auto entry_up = std::make_unique<StructuredData::Dictionary>();
712   entry_up->AddBooleanItem("value", value);
713   entry_up->AddStringItem("description", description);
714   dict.AddItem(name, std::move(entry_up));
715 }
716 
717 static void AddLLVMTargets(StructuredData::Dictionary &dict) {
718   auto array_up = std::make_unique<StructuredData::Array>();
719 #define LLVM_TARGET(target)                                                    \
720   array_up->AddItem(std::make_unique<StructuredData::String>(#target));
721 #include "llvm/Config/Targets.def"
722   auto entry_up = std::make_unique<StructuredData::Dictionary>();
723   entry_up->AddItem("value", std::move(array_up));
724   entry_up->AddStringItem("description", "A list of configured LLVM targets.");
725   dict.AddItem("targets", std::move(entry_up));
726 }
727 
728 SBStructuredData SBDebugger::GetBuildConfiguration() {
729   LLDB_RECORD_STATIC_METHOD_NO_ARGS(lldb::SBStructuredData, SBDebugger,
730                                     GetBuildConfiguration);
731 
732   auto config_up = std::make_unique<StructuredData::Dictionary>();
733   AddBoolConfigEntry(
734       *config_up, "xml", XMLDocument::XMLEnabled(),
735       "A boolean value that indicates if XML support is enabled in LLDB");
736   AddBoolConfigEntry(
737       *config_up, "curses", LLDB_ENABLE_CURSES,
738       "A boolean value that indicates if curses support is enabled in LLDB");
739   AddBoolConfigEntry(
740       *config_up, "editline", LLDB_ENABLE_LIBEDIT,
741       "A boolean value that indicates if editline support is enabled in LLDB");
742   AddBoolConfigEntry(
743       *config_up, "lzma", LLDB_ENABLE_LZMA,
744       "A boolean value that indicates if lzma support is enabled in LLDB");
745   AddBoolConfigEntry(
746       *config_up, "python", LLDB_ENABLE_PYTHON,
747       "A boolean value that indicates if python support is enabled in LLDB");
748   AddBoolConfigEntry(
749       *config_up, "lua", LLDB_ENABLE_LUA,
750       "A boolean value that indicates if lua support is enabled in LLDB");
751   AddBoolConfigEntry(*config_up, "fbsdvmcore", LLDB_ENABLE_FBSDVMCORE,
752                      "A boolean value that indicates if fbsdvmcore support is "
753                      "enabled in LLDB");
754   AddLLVMTargets(*config_up);
755 
756   SBStructuredData data;
757   data.m_impl_up->SetObjectSP(std::move(config_up));
758   return data;
759 }
760 
761 bool SBDebugger::StateIsRunningState(StateType state) {
762   LLDB_RECORD_STATIC_METHOD(bool, SBDebugger, StateIsRunningState,
763                             (lldb::StateType), state);
764 
765   const bool result = lldb_private::StateIsRunningState(state);
766 
767   return result;
768 }
769 
770 bool SBDebugger::StateIsStoppedState(StateType state) {
771   LLDB_RECORD_STATIC_METHOD(bool, SBDebugger, StateIsStoppedState,
772                             (lldb::StateType), state);
773 
774   const bool result = lldb_private::StateIsStoppedState(state, false);
775 
776   return result;
777 }
778 
779 lldb::SBTarget SBDebugger::CreateTarget(const char *filename,
780                                         const char *target_triple,
781                                         const char *platform_name,
782                                         bool add_dependent_modules,
783                                         lldb::SBError &sb_error) {
784   LLDB_RECORD_METHOD(
785       lldb::SBTarget, SBDebugger, CreateTarget,
786       (const char *, const char *, const char *, bool, lldb::SBError &),
787       filename, target_triple, platform_name, add_dependent_modules, sb_error);
788 
789   SBTarget sb_target;
790   TargetSP target_sp;
791   if (m_opaque_sp) {
792     sb_error.Clear();
793     OptionGroupPlatform platform_options(false);
794     platform_options.SetPlatformName(platform_name);
795 
796     sb_error.ref() = m_opaque_sp->GetTargetList().CreateTarget(
797         *m_opaque_sp, filename, target_triple,
798         add_dependent_modules ? eLoadDependentsYes : eLoadDependentsNo,
799         &platform_options, target_sp);
800 
801     if (sb_error.Success())
802       sb_target.SetSP(target_sp);
803   } else {
804     sb_error.SetErrorString("invalid debugger");
805   }
806 
807   Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
808   LLDB_LOGF(log,
809             "SBDebugger(%p)::CreateTarget (filename=\"%s\", triple=%s, "
810             "platform_name=%s, add_dependent_modules=%u, error=%s) => "
811             "SBTarget(%p)",
812             static_cast<void *>(m_opaque_sp.get()), filename, target_triple,
813             platform_name, add_dependent_modules, sb_error.GetCString(),
814             static_cast<void *>(target_sp.get()));
815 
816   return sb_target;
817 }
818 
819 SBTarget
820 SBDebugger::CreateTargetWithFileAndTargetTriple(const char *filename,
821                                                 const char *target_triple) {
822   LLDB_RECORD_METHOD(lldb::SBTarget, SBDebugger,
823                      CreateTargetWithFileAndTargetTriple,
824                      (const char *, const char *), filename, target_triple);
825 
826   SBTarget sb_target;
827   TargetSP target_sp;
828   if (m_opaque_sp) {
829     const bool add_dependent_modules = true;
830     Status error(m_opaque_sp->GetTargetList().CreateTarget(
831         *m_opaque_sp, filename, target_triple,
832         add_dependent_modules ? eLoadDependentsYes : eLoadDependentsNo, nullptr,
833         target_sp));
834     sb_target.SetSP(target_sp);
835   }
836 
837   Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
838   LLDB_LOGF(log,
839             "SBDebugger(%p)::CreateTargetWithFileAndTargetTriple "
840             "(filename=\"%s\", triple=%s) => SBTarget(%p)",
841             static_cast<void *>(m_opaque_sp.get()), filename, target_triple,
842             static_cast<void *>(target_sp.get()));
843 
844   return sb_target;
845 }
846 
847 SBTarget SBDebugger::CreateTargetWithFileAndArch(const char *filename,
848                                                  const char *arch_cstr) {
849   LLDB_RECORD_METHOD(lldb::SBTarget, SBDebugger, CreateTargetWithFileAndArch,
850                      (const char *, const char *), filename, arch_cstr);
851 
852   Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
853 
854   SBTarget sb_target;
855   TargetSP target_sp;
856   if (m_opaque_sp) {
857     Status error;
858     if (arch_cstr == nullptr) {
859       // The version of CreateTarget that takes an ArchSpec won't accept an
860       // empty ArchSpec, so when the arch hasn't been specified, we need to
861       // call the target triple version.
862       error = m_opaque_sp->GetTargetList().CreateTarget(*m_opaque_sp, filename,
863           arch_cstr, eLoadDependentsYes, nullptr, target_sp);
864     } else {
865       PlatformSP platform_sp = m_opaque_sp->GetPlatformList()
866           .GetSelectedPlatform();
867       ArchSpec arch = Platform::GetAugmentedArchSpec(platform_sp.get(),
868           arch_cstr);
869       if (arch.IsValid())
870         error = m_opaque_sp->GetTargetList().CreateTarget(*m_opaque_sp, filename,
871             arch, eLoadDependentsYes, platform_sp, target_sp);
872       else
873         error.SetErrorStringWithFormat("invalid arch_cstr: %s", arch_cstr);
874     }
875     if (error.Success())
876       sb_target.SetSP(target_sp);
877   }
878 
879   LLDB_LOGF(log,
880             "SBDebugger(%p)::CreateTargetWithFileAndArch (filename=\"%s\", "
881             "arch=%s) => SBTarget(%p)",
882             static_cast<void *>(m_opaque_sp.get()),
883             filename ? filename : "<unspecified>",
884             arch_cstr ? arch_cstr : "<unspecified>",
885             static_cast<void *>(target_sp.get()));
886 
887   return sb_target;
888 }
889 
890 SBTarget SBDebugger::CreateTarget(const char *filename) {
891   LLDB_RECORD_METHOD(lldb::SBTarget, SBDebugger, CreateTarget, (const char *),
892                      filename);
893 
894   SBTarget sb_target;
895   TargetSP target_sp;
896   if (m_opaque_sp) {
897     Status error;
898     const bool add_dependent_modules = true;
899     error = m_opaque_sp->GetTargetList().CreateTarget(
900         *m_opaque_sp, filename, "",
901         add_dependent_modules ? eLoadDependentsYes : eLoadDependentsNo, nullptr,
902         target_sp);
903 
904     if (error.Success())
905       sb_target.SetSP(target_sp);
906   }
907   Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
908   LLDB_LOGF(log,
909             "SBDebugger(%p)::CreateTarget (filename=\"%s\") => SBTarget(%p)",
910             static_cast<void *>(m_opaque_sp.get()), filename,
911             static_cast<void *>(target_sp.get()));
912   return sb_target;
913 }
914 
915 SBTarget SBDebugger::GetDummyTarget() {
916   LLDB_RECORD_METHOD_NO_ARGS(lldb::SBTarget, SBDebugger, GetDummyTarget);
917 
918   SBTarget sb_target;
919   if (m_opaque_sp) {
920     sb_target.SetSP(m_opaque_sp->GetDummyTarget().shared_from_this());
921   }
922   Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
923   LLDB_LOGF(log, "SBDebugger(%p)::GetDummyTarget() => SBTarget(%p)",
924             static_cast<void *>(m_opaque_sp.get()),
925             static_cast<void *>(sb_target.GetSP().get()));
926   return sb_target;
927 }
928 
929 bool SBDebugger::DeleteTarget(lldb::SBTarget &target) {
930   LLDB_RECORD_METHOD(bool, SBDebugger, DeleteTarget, (lldb::SBTarget &),
931                      target);
932 
933   bool result = false;
934   if (m_opaque_sp) {
935     TargetSP target_sp(target.GetSP());
936     if (target_sp) {
937       // No need to lock, the target list is thread safe
938       result = m_opaque_sp->GetTargetList().DeleteTarget(target_sp);
939       target_sp->Destroy();
940       target.Clear();
941     }
942   }
943 
944   Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
945   LLDB_LOGF(log, "SBDebugger(%p)::DeleteTarget (SBTarget(%p)) => %i",
946             static_cast<void *>(m_opaque_sp.get()),
947             static_cast<void *>(target.m_opaque_sp.get()), result);
948 
949   return result;
950 }
951 
952 SBTarget SBDebugger::GetTargetAtIndex(uint32_t idx) {
953   LLDB_RECORD_METHOD(lldb::SBTarget, SBDebugger, GetTargetAtIndex, (uint32_t),
954                      idx);
955 
956   SBTarget sb_target;
957   if (m_opaque_sp) {
958     // No need to lock, the target list is thread safe
959     sb_target.SetSP(m_opaque_sp->GetTargetList().GetTargetAtIndex(idx));
960   }
961   return sb_target;
962 }
963 
964 uint32_t SBDebugger::GetIndexOfTarget(lldb::SBTarget target) {
965   LLDB_RECORD_METHOD(uint32_t, SBDebugger, GetIndexOfTarget, (lldb::SBTarget),
966                      target);
967 
968   lldb::TargetSP target_sp = target.GetSP();
969   if (!target_sp)
970     return UINT32_MAX;
971 
972   if (!m_opaque_sp)
973     return UINT32_MAX;
974 
975   return m_opaque_sp->GetTargetList().GetIndexOfTarget(target.GetSP());
976 }
977 
978 SBTarget SBDebugger::FindTargetWithProcessID(lldb::pid_t pid) {
979   LLDB_RECORD_METHOD(lldb::SBTarget, SBDebugger, FindTargetWithProcessID,
980                      (lldb::pid_t), pid);
981 
982   SBTarget sb_target;
983   if (m_opaque_sp) {
984     // No need to lock, the target list is thread safe
985     sb_target.SetSP(m_opaque_sp->GetTargetList().FindTargetWithProcessID(pid));
986   }
987   return sb_target;
988 }
989 
990 SBTarget SBDebugger::FindTargetWithFileAndArch(const char *filename,
991                                                const char *arch_name) {
992   LLDB_RECORD_METHOD(lldb::SBTarget, SBDebugger, FindTargetWithFileAndArch,
993                      (const char *, const char *), filename, arch_name);
994 
995   SBTarget sb_target;
996   if (m_opaque_sp && filename && filename[0]) {
997     // No need to lock, the target list is thread safe
998     ArchSpec arch = Platform::GetAugmentedArchSpec(
999         m_opaque_sp->GetPlatformList().GetSelectedPlatform().get(), arch_name);
1000     TargetSP target_sp(
1001         m_opaque_sp->GetTargetList().FindTargetWithExecutableAndArchitecture(
1002             FileSpec(filename), arch_name ? &arch : nullptr));
1003     sb_target.SetSP(target_sp);
1004   }
1005   return sb_target;
1006 }
1007 
1008 SBTarget SBDebugger::FindTargetWithLLDBProcess(const ProcessSP &process_sp) {
1009   SBTarget sb_target;
1010   if (m_opaque_sp) {
1011     // No need to lock, the target list is thread safe
1012     sb_target.SetSP(
1013         m_opaque_sp->GetTargetList().FindTargetWithProcess(process_sp.get()));
1014   }
1015   return sb_target;
1016 }
1017 
1018 uint32_t SBDebugger::GetNumTargets() {
1019   LLDB_RECORD_METHOD_NO_ARGS(uint32_t, SBDebugger, GetNumTargets);
1020 
1021   if (m_opaque_sp) {
1022     // No need to lock, the target list is thread safe
1023     return m_opaque_sp->GetTargetList().GetNumTargets();
1024   }
1025   return 0;
1026 }
1027 
1028 SBTarget SBDebugger::GetSelectedTarget() {
1029   LLDB_RECORD_METHOD_NO_ARGS(lldb::SBTarget, SBDebugger, GetSelectedTarget);
1030 
1031   Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
1032 
1033   SBTarget sb_target;
1034   TargetSP target_sp;
1035   if (m_opaque_sp) {
1036     // No need to lock, the target list is thread safe
1037     target_sp = m_opaque_sp->GetTargetList().GetSelectedTarget();
1038     sb_target.SetSP(target_sp);
1039   }
1040 
1041   if (log) {
1042     SBStream sstr;
1043     sb_target.GetDescription(sstr, eDescriptionLevelBrief);
1044     LLDB_LOGF(log, "SBDebugger(%p)::GetSelectedTarget () => SBTarget(%p): %s",
1045               static_cast<void *>(m_opaque_sp.get()),
1046               static_cast<void *>(target_sp.get()), sstr.GetData());
1047   }
1048 
1049   return sb_target;
1050 }
1051 
1052 void SBDebugger::SetSelectedTarget(SBTarget &sb_target) {
1053   LLDB_RECORD_METHOD(void, SBDebugger, SetSelectedTarget, (lldb::SBTarget &),
1054                      sb_target);
1055 
1056   Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
1057 
1058   TargetSP target_sp(sb_target.GetSP());
1059   if (m_opaque_sp) {
1060     m_opaque_sp->GetTargetList().SetSelectedTarget(target_sp);
1061   }
1062   if (log) {
1063     SBStream sstr;
1064     sb_target.GetDescription(sstr, eDescriptionLevelBrief);
1065     LLDB_LOGF(log, "SBDebugger(%p)::SetSelectedTarget () => SBTarget(%p): %s",
1066               static_cast<void *>(m_opaque_sp.get()),
1067               static_cast<void *>(target_sp.get()), sstr.GetData());
1068   }
1069 }
1070 
1071 SBPlatform SBDebugger::GetSelectedPlatform() {
1072   LLDB_RECORD_METHOD_NO_ARGS(lldb::SBPlatform, SBDebugger, GetSelectedPlatform);
1073 
1074   Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
1075 
1076   SBPlatform sb_platform;
1077   DebuggerSP debugger_sp(m_opaque_sp);
1078   if (debugger_sp) {
1079     sb_platform.SetSP(debugger_sp->GetPlatformList().GetSelectedPlatform());
1080   }
1081   LLDB_LOGF(log, "SBDebugger(%p)::GetSelectedPlatform () => SBPlatform(%p): %s",
1082             static_cast<void *>(m_opaque_sp.get()),
1083             static_cast<void *>(sb_platform.GetSP().get()),
1084             sb_platform.GetName());
1085   return sb_platform;
1086 }
1087 
1088 void SBDebugger::SetSelectedPlatform(SBPlatform &sb_platform) {
1089   LLDB_RECORD_METHOD(void, SBDebugger, SetSelectedPlatform,
1090                      (lldb::SBPlatform &), sb_platform);
1091 
1092   Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
1093 
1094   DebuggerSP debugger_sp(m_opaque_sp);
1095   if (debugger_sp) {
1096     debugger_sp->GetPlatformList().SetSelectedPlatform(sb_platform.GetSP());
1097   }
1098 
1099   LLDB_LOGF(log, "SBDebugger(%p)::SetSelectedPlatform (SBPlatform(%p) %s)",
1100             static_cast<void *>(m_opaque_sp.get()),
1101             static_cast<void *>(sb_platform.GetSP().get()),
1102             sb_platform.GetName());
1103 }
1104 
1105 uint32_t SBDebugger::GetNumPlatforms() {
1106   LLDB_RECORD_METHOD_NO_ARGS(uint32_t, SBDebugger, GetNumPlatforms);
1107 
1108   if (m_opaque_sp) {
1109     // No need to lock, the platform list is thread safe
1110     return m_opaque_sp->GetPlatformList().GetSize();
1111   }
1112   return 0;
1113 }
1114 
1115 SBPlatform SBDebugger::GetPlatformAtIndex(uint32_t idx) {
1116   LLDB_RECORD_METHOD(lldb::SBPlatform, SBDebugger, GetPlatformAtIndex,
1117                      (uint32_t), idx);
1118 
1119   SBPlatform sb_platform;
1120   if (m_opaque_sp) {
1121     // No need to lock, the platform list is thread safe
1122     sb_platform.SetSP(m_opaque_sp->GetPlatformList().GetAtIndex(idx));
1123   }
1124   return sb_platform;
1125 }
1126 
1127 uint32_t SBDebugger::GetNumAvailablePlatforms() {
1128   LLDB_RECORD_METHOD_NO_ARGS(uint32_t, SBDebugger, GetNumAvailablePlatforms);
1129 
1130   uint32_t idx = 0;
1131   while (true) {
1132     if (PluginManager::GetPlatformPluginNameAtIndex(idx).empty()) {
1133       break;
1134     }
1135     ++idx;
1136   }
1137   // +1 for the host platform, which should always appear first in the list.
1138   return idx + 1;
1139 }
1140 
1141 SBStructuredData SBDebugger::GetAvailablePlatformInfoAtIndex(uint32_t idx) {
1142   LLDB_RECORD_METHOD(lldb::SBStructuredData, SBDebugger,
1143                      GetAvailablePlatformInfoAtIndex, (uint32_t), idx);
1144 
1145   SBStructuredData data;
1146   auto platform_dict = std::make_unique<StructuredData::Dictionary>();
1147   llvm::StringRef name_str("name"), desc_str("description");
1148 
1149   if (idx == 0) {
1150     PlatformSP host_platform_sp(Platform::GetHostPlatform());
1151     platform_dict->AddStringItem(name_str, host_platform_sp->GetPluginName());
1152     platform_dict->AddStringItem(
1153         desc_str, llvm::StringRef(host_platform_sp->GetDescription()));
1154   } else if (idx > 0) {
1155     llvm::StringRef plugin_name =
1156         PluginManager::GetPlatformPluginNameAtIndex(idx - 1);
1157     if (plugin_name.empty()) {
1158       return data;
1159     }
1160     platform_dict->AddStringItem(name_str, llvm::StringRef(plugin_name));
1161 
1162     llvm::StringRef plugin_desc =
1163         PluginManager::GetPlatformPluginDescriptionAtIndex(idx - 1);
1164     platform_dict->AddStringItem(desc_str, llvm::StringRef(plugin_desc));
1165   }
1166 
1167   data.m_impl_up->SetObjectSP(
1168       StructuredData::ObjectSP(platform_dict.release()));
1169   return data;
1170 }
1171 
1172 void SBDebugger::DispatchInput(void *baton, const void *data, size_t data_len) {
1173   LLDB_RECORD_DUMMY(void, SBDebugger, DispatchInput,
1174                     (void *, const void *, size_t), baton, data, data_len);
1175 
1176   DispatchInput(data, data_len);
1177 }
1178 
1179 void SBDebugger::DispatchInput(const void *data, size_t data_len) {
1180   LLDB_RECORD_DUMMY(void, SBDebugger, DispatchInput, (const void *, size_t),
1181                     data, data_len);
1182 
1183   //    Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
1184   //
1185   //    if (log)
1186   //        LLDB_LOGF(log, "SBDebugger(%p)::DispatchInput (data=\"%.*s\",
1187   //        size_t=%" PRIu64 ")",
1188   //                     m_opaque_sp.get(),
1189   //                     (int) data_len,
1190   //                     (const char *) data,
1191   //                     (uint64_t)data_len);
1192   //
1193   //    if (m_opaque_sp)
1194   //        m_opaque_sp->DispatchInput ((const char *) data, data_len);
1195 }
1196 
1197 void SBDebugger::DispatchInputInterrupt() {
1198   LLDB_RECORD_DUMMY_NO_ARGS(void, SBDebugger, DispatchInputInterrupt);
1199 
1200   if (m_opaque_sp)
1201     m_opaque_sp->DispatchInputInterrupt();
1202 }
1203 
1204 void SBDebugger::DispatchInputEndOfFile() {
1205   LLDB_RECORD_METHOD_NO_ARGS(void, SBDebugger, DispatchInputEndOfFile);
1206 
1207   if (m_opaque_sp)
1208     m_opaque_sp->DispatchInputEndOfFile();
1209 }
1210 
1211 void SBDebugger::PushInputReader(SBInputReader &reader) {
1212   LLDB_RECORD_METHOD(void, SBDebugger, PushInputReader, (lldb::SBInputReader &),
1213                      reader);
1214 }
1215 
1216 void SBDebugger::RunCommandInterpreter(bool auto_handle_events,
1217                                        bool spawn_thread) {
1218   LLDB_RECORD_METHOD(void, SBDebugger, RunCommandInterpreter, (bool, bool),
1219                      auto_handle_events, spawn_thread);
1220 
1221   if (m_opaque_sp) {
1222     CommandInterpreterRunOptions options;
1223     options.SetAutoHandleEvents(auto_handle_events);
1224     options.SetSpawnThread(spawn_thread);
1225     m_opaque_sp->GetCommandInterpreter().RunCommandInterpreter(options);
1226   }
1227 }
1228 
1229 void SBDebugger::RunCommandInterpreter(bool auto_handle_events,
1230                                        bool spawn_thread,
1231                                        SBCommandInterpreterRunOptions &options,
1232                                        int &num_errors, bool &quit_requested,
1233                                        bool &stopped_for_crash)
1234 
1235 {
1236   LLDB_RECORD_METHOD(void, SBDebugger, RunCommandInterpreter,
1237                      (bool, bool, lldb::SBCommandInterpreterRunOptions &, int &,
1238                       bool &, bool &),
1239                      auto_handle_events, spawn_thread, options, num_errors,
1240                      quit_requested, stopped_for_crash);
1241 
1242   if (m_opaque_sp) {
1243     options.SetAutoHandleEvents(auto_handle_events);
1244     options.SetSpawnThread(spawn_thread);
1245     CommandInterpreter &interp = m_opaque_sp->GetCommandInterpreter();
1246     CommandInterpreterRunResult result =
1247         interp.RunCommandInterpreter(options.ref());
1248     num_errors = result.GetNumErrors();
1249     quit_requested =
1250         result.IsResult(lldb::eCommandInterpreterResultQuitRequested);
1251     stopped_for_crash =
1252         result.IsResult(lldb::eCommandInterpreterResultInferiorCrash);
1253   }
1254 }
1255 
1256 SBCommandInterpreterRunResult SBDebugger::RunCommandInterpreter(
1257     const SBCommandInterpreterRunOptions &options) {
1258   LLDB_RECORD_METHOD(lldb::SBCommandInterpreterRunResult, SBDebugger,
1259                      RunCommandInterpreter,
1260                      (const lldb::SBCommandInterpreterRunOptions &), options);
1261 
1262   if (!m_opaque_sp)
1263     return SBCommandInterpreterRunResult();
1264 
1265   CommandInterpreter &interp = m_opaque_sp->GetCommandInterpreter();
1266   CommandInterpreterRunResult result =
1267       interp.RunCommandInterpreter(options.ref());
1268 
1269   return SBCommandInterpreterRunResult(result);
1270 }
1271 
1272 SBError SBDebugger::RunREPL(lldb::LanguageType language,
1273                             const char *repl_options) {
1274   LLDB_RECORD_METHOD(lldb::SBError, SBDebugger, RunREPL,
1275                      (lldb::LanguageType, const char *), language,
1276                      repl_options);
1277 
1278   SBError error;
1279   if (m_opaque_sp)
1280     error.ref() = m_opaque_sp->RunREPL(language, repl_options);
1281   else
1282     error.SetErrorString("invalid debugger");
1283   return error;
1284 }
1285 
1286 void SBDebugger::reset(const DebuggerSP &debugger_sp) {
1287   m_opaque_sp = debugger_sp;
1288 }
1289 
1290 Debugger *SBDebugger::get() const { return m_opaque_sp.get(); }
1291 
1292 Debugger &SBDebugger::ref() const {
1293   assert(m_opaque_sp.get());
1294   return *m_opaque_sp;
1295 }
1296 
1297 const lldb::DebuggerSP &SBDebugger::get_sp() const { return m_opaque_sp; }
1298 
1299 SBDebugger SBDebugger::FindDebuggerWithID(int id) {
1300   LLDB_RECORD_STATIC_METHOD(lldb::SBDebugger, SBDebugger, FindDebuggerWithID,
1301                             (int), id);
1302 
1303   // No need to lock, the debugger list is thread safe
1304   SBDebugger sb_debugger;
1305   DebuggerSP debugger_sp = Debugger::FindDebuggerWithID(id);
1306   if (debugger_sp)
1307     sb_debugger.reset(debugger_sp);
1308   return sb_debugger;
1309 }
1310 
1311 const char *SBDebugger::GetInstanceName() {
1312   LLDB_RECORD_METHOD_NO_ARGS(const char *, SBDebugger, GetInstanceName);
1313 
1314   return (m_opaque_sp ? m_opaque_sp->GetInstanceName().AsCString() : nullptr);
1315 }
1316 
1317 SBError SBDebugger::SetInternalVariable(const char *var_name, const char *value,
1318                                         const char *debugger_instance_name) {
1319   LLDB_RECORD_STATIC_METHOD(lldb::SBError, SBDebugger, SetInternalVariable,
1320                             (const char *, const char *, const char *),
1321                             var_name, value, debugger_instance_name);
1322 
1323   SBError sb_error;
1324   DebuggerSP debugger_sp(Debugger::FindDebuggerWithInstanceName(
1325       ConstString(debugger_instance_name)));
1326   Status error;
1327   if (debugger_sp) {
1328     ExecutionContext exe_ctx(
1329         debugger_sp->GetCommandInterpreter().GetExecutionContext());
1330     error = debugger_sp->SetPropertyValue(&exe_ctx, eVarSetOperationAssign,
1331                                           var_name, value);
1332   } else {
1333     error.SetErrorStringWithFormat("invalid debugger instance name '%s'",
1334                                    debugger_instance_name);
1335   }
1336   if (error.Fail())
1337     sb_error.SetError(error);
1338   return sb_error;
1339 }
1340 
1341 SBStringList
1342 SBDebugger::GetInternalVariableValue(const char *var_name,
1343                                      const char *debugger_instance_name) {
1344   LLDB_RECORD_STATIC_METHOD(
1345       lldb::SBStringList, SBDebugger, GetInternalVariableValue,
1346       (const char *, const char *), var_name, debugger_instance_name);
1347 
1348   DebuggerSP debugger_sp(Debugger::FindDebuggerWithInstanceName(
1349       ConstString(debugger_instance_name)));
1350   Status error;
1351   if (debugger_sp) {
1352     ExecutionContext exe_ctx(
1353         debugger_sp->GetCommandInterpreter().GetExecutionContext());
1354     lldb::OptionValueSP value_sp(
1355         debugger_sp->GetPropertyValue(&exe_ctx, var_name, false, error));
1356     if (value_sp) {
1357       StreamString value_strm;
1358       value_sp->DumpValue(&exe_ctx, value_strm, OptionValue::eDumpOptionValue);
1359       const std::string &value_str = std::string(value_strm.GetString());
1360       if (!value_str.empty()) {
1361         StringList string_list;
1362         string_list.SplitIntoLines(value_str);
1363         return SBStringList(&string_list);
1364       }
1365     }
1366   }
1367   return SBStringList();
1368 }
1369 
1370 uint32_t SBDebugger::GetTerminalWidth() const {
1371   LLDB_RECORD_METHOD_CONST_NO_ARGS(uint32_t, SBDebugger, GetTerminalWidth);
1372 
1373   return (m_opaque_sp ? m_opaque_sp->GetTerminalWidth() : 0);
1374 }
1375 
1376 void SBDebugger::SetTerminalWidth(uint32_t term_width) {
1377   LLDB_RECORD_DUMMY(void, SBDebugger, SetTerminalWidth, (uint32_t), term_width);
1378 
1379   if (m_opaque_sp)
1380     m_opaque_sp->SetTerminalWidth(term_width);
1381 }
1382 
1383 const char *SBDebugger::GetPrompt() const {
1384   LLDB_RECORD_METHOD_CONST_NO_ARGS(const char *, SBDebugger, GetPrompt);
1385 
1386   Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
1387 
1388   LLDB_LOGF(log, "SBDebugger(%p)::GetPrompt () => \"%s\"",
1389             static_cast<void *>(m_opaque_sp.get()),
1390             (m_opaque_sp ? m_opaque_sp->GetPrompt().str().c_str() : ""));
1391 
1392   return (m_opaque_sp ? ConstString(m_opaque_sp->GetPrompt()).GetCString()
1393                       : nullptr);
1394 }
1395 
1396 void SBDebugger::SetPrompt(const char *prompt) {
1397   LLDB_RECORD_METHOD(void, SBDebugger, SetPrompt, (const char *), prompt);
1398 
1399   if (m_opaque_sp)
1400     m_opaque_sp->SetPrompt(llvm::StringRef(prompt));
1401 }
1402 
1403 const char *SBDebugger::GetReproducerPath() const {
1404   LLDB_RECORD_METHOD_CONST_NO_ARGS(const char *, SBDebugger, GetReproducerPath);
1405 
1406   return (m_opaque_sp
1407               ? ConstString(m_opaque_sp->GetReproducerPath()).GetCString()
1408               : nullptr);
1409 }
1410 
1411 ScriptLanguage SBDebugger::GetScriptLanguage() const {
1412   LLDB_RECORD_METHOD_CONST_NO_ARGS(lldb::ScriptLanguage, SBDebugger,
1413                                    GetScriptLanguage);
1414 
1415   return (m_opaque_sp ? m_opaque_sp->GetScriptLanguage() : eScriptLanguageNone);
1416 }
1417 
1418 void SBDebugger::SetScriptLanguage(ScriptLanguage script_lang) {
1419   LLDB_RECORD_METHOD(void, SBDebugger, SetScriptLanguage,
1420                      (lldb::ScriptLanguage), script_lang);
1421 
1422   if (m_opaque_sp) {
1423     m_opaque_sp->SetScriptLanguage(script_lang);
1424   }
1425 }
1426 
1427 LanguageType SBDebugger::GetREPLLanguage() const {
1428   LLDB_RECORD_METHOD_CONST_NO_ARGS(lldb::LanguageType, SBDebugger,
1429                                    GetREPLLanguage);
1430 
1431   return (m_opaque_sp ? m_opaque_sp->GetREPLLanguage() : eLanguageTypeUnknown);
1432 }
1433 
1434 void SBDebugger::SetREPLLanguage(LanguageType repl_lang) {
1435   LLDB_RECORD_METHOD(void, SBDebugger, SetREPLLanguage, (lldb::LanguageType),
1436                      repl_lang);
1437 
1438   if (m_opaque_sp) {
1439     m_opaque_sp->SetREPLLanguage(repl_lang);
1440   }
1441 }
1442 
1443 bool SBDebugger::SetUseExternalEditor(bool value) {
1444   LLDB_RECORD_METHOD(bool, SBDebugger, SetUseExternalEditor, (bool), value);
1445 
1446   return (m_opaque_sp ? m_opaque_sp->SetUseExternalEditor(value) : false);
1447 }
1448 
1449 bool SBDebugger::GetUseExternalEditor() {
1450   LLDB_RECORD_METHOD_NO_ARGS(bool, SBDebugger, GetUseExternalEditor);
1451 
1452   return (m_opaque_sp ? m_opaque_sp->GetUseExternalEditor() : false);
1453 }
1454 
1455 bool SBDebugger::SetUseColor(bool value) {
1456   LLDB_RECORD_METHOD(bool, SBDebugger, SetUseColor, (bool), value);
1457 
1458   return (m_opaque_sp ? m_opaque_sp->SetUseColor(value) : false);
1459 }
1460 
1461 bool SBDebugger::GetUseColor() const {
1462   LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBDebugger, GetUseColor);
1463 
1464   return (m_opaque_sp ? m_opaque_sp->GetUseColor() : false);
1465 }
1466 
1467 bool SBDebugger::SetUseSourceCache(bool value) {
1468   LLDB_RECORD_METHOD(bool, SBDebugger, SetUseSourceCache, (bool), value);
1469 
1470   return (m_opaque_sp ? m_opaque_sp->SetUseSourceCache(value) : false);
1471 }
1472 
1473 bool SBDebugger::GetUseSourceCache() const {
1474   LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBDebugger, GetUseSourceCache);
1475 
1476   return (m_opaque_sp ? m_opaque_sp->GetUseSourceCache() : false);
1477 }
1478 
1479 bool SBDebugger::GetDescription(SBStream &description) {
1480   LLDB_RECORD_METHOD(bool, SBDebugger, GetDescription, (lldb::SBStream &),
1481                      description);
1482 
1483   Stream &strm = description.ref();
1484 
1485   if (m_opaque_sp) {
1486     const char *name = m_opaque_sp->GetInstanceName().AsCString();
1487     user_id_t id = m_opaque_sp->GetID();
1488     strm.Printf("Debugger (instance: \"%s\", id: %" PRIu64 ")", name, id);
1489   } else
1490     strm.PutCString("No value");
1491 
1492   return true;
1493 }
1494 
1495 user_id_t SBDebugger::GetID() {
1496   LLDB_RECORD_METHOD_NO_ARGS(lldb::user_id_t, SBDebugger, GetID);
1497 
1498   return (m_opaque_sp ? m_opaque_sp->GetID() : LLDB_INVALID_UID);
1499 }
1500 
1501 SBError SBDebugger::SetCurrentPlatform(const char *platform_name_cstr) {
1502   LLDB_RECORD_METHOD(lldb::SBError, SBDebugger, SetCurrentPlatform,
1503                      (const char *), platform_name_cstr);
1504 
1505   SBError sb_error;
1506   if (m_opaque_sp) {
1507     if (platform_name_cstr && platform_name_cstr[0]) {
1508       ConstString platform_name(platform_name_cstr);
1509       PlatformSP platform_sp(Platform::Find(platform_name));
1510 
1511       if (platform_sp) {
1512         // Already have a platform with this name, just select it
1513         m_opaque_sp->GetPlatformList().SetSelectedPlatform(platform_sp);
1514       } else {
1515         // We don't have a platform by this name yet, create one
1516         platform_sp = Platform::Create(platform_name, sb_error.ref());
1517         if (platform_sp) {
1518           // We created the platform, now append and select it
1519           bool make_selected = true;
1520           m_opaque_sp->GetPlatformList().Append(platform_sp, make_selected);
1521         }
1522       }
1523     } else {
1524       sb_error.ref().SetErrorString("invalid platform name");
1525     }
1526   } else {
1527     sb_error.ref().SetErrorString("invalid debugger");
1528   }
1529   return sb_error;
1530 }
1531 
1532 bool SBDebugger::SetCurrentPlatformSDKRoot(const char *sysroot) {
1533   LLDB_RECORD_METHOD(bool, SBDebugger, SetCurrentPlatformSDKRoot,
1534                      (const char *), sysroot);
1535 
1536   Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
1537   if (m_opaque_sp) {
1538     PlatformSP platform_sp(
1539         m_opaque_sp->GetPlatformList().GetSelectedPlatform());
1540 
1541     if (platform_sp) {
1542       if (log && sysroot)
1543         LLDB_LOGF(log, "SBDebugger::SetCurrentPlatformSDKRoot (\"%s\")",
1544                   sysroot);
1545       platform_sp->SetSDKRootDirectory(ConstString(sysroot));
1546       return true;
1547     }
1548   }
1549   return false;
1550 }
1551 
1552 bool SBDebugger::GetCloseInputOnEOF() const {
1553   LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBDebugger, GetCloseInputOnEOF);
1554 
1555   return (m_opaque_sp ? m_opaque_sp->GetCloseInputOnEOF() : false);
1556 }
1557 
1558 void SBDebugger::SetCloseInputOnEOF(bool b) {
1559   LLDB_RECORD_METHOD(void, SBDebugger, SetCloseInputOnEOF, (bool), b);
1560 
1561   if (m_opaque_sp)
1562     m_opaque_sp->SetCloseInputOnEOF(b);
1563 }
1564 
1565 SBTypeCategory SBDebugger::GetCategory(const char *category_name) {
1566   LLDB_RECORD_METHOD(lldb::SBTypeCategory, SBDebugger, GetCategory,
1567                      (const char *), category_name);
1568 
1569   if (!category_name || *category_name == 0)
1570     return SBTypeCategory();
1571 
1572   TypeCategoryImplSP category_sp;
1573 
1574   if (DataVisualization::Categories::GetCategory(ConstString(category_name),
1575                                                  category_sp, false)) {
1576     return SBTypeCategory(category_sp);
1577   } else {
1578     return SBTypeCategory();
1579   }
1580 }
1581 
1582 SBTypeCategory SBDebugger::GetCategory(lldb::LanguageType lang_type) {
1583   LLDB_RECORD_METHOD(lldb::SBTypeCategory, SBDebugger, GetCategory,
1584                      (lldb::LanguageType), lang_type);
1585 
1586   TypeCategoryImplSP category_sp;
1587   if (DataVisualization::Categories::GetCategory(lang_type, category_sp)) {
1588     return SBTypeCategory(category_sp);
1589   } else {
1590     return SBTypeCategory();
1591   }
1592 }
1593 
1594 SBTypeCategory SBDebugger::CreateCategory(const char *category_name) {
1595   LLDB_RECORD_METHOD(lldb::SBTypeCategory, SBDebugger, CreateCategory,
1596                      (const char *), category_name);
1597 
1598   if (!category_name || *category_name == 0)
1599     return SBTypeCategory();
1600 
1601   TypeCategoryImplSP category_sp;
1602 
1603   if (DataVisualization::Categories::GetCategory(ConstString(category_name),
1604                                                  category_sp, true)) {
1605     return SBTypeCategory(category_sp);
1606   } else {
1607     return SBTypeCategory();
1608   }
1609 }
1610 
1611 bool SBDebugger::DeleteCategory(const char *category_name) {
1612   LLDB_RECORD_METHOD(bool, SBDebugger, DeleteCategory, (const char *),
1613                      category_name);
1614 
1615   if (!category_name || *category_name == 0)
1616     return false;
1617 
1618   return DataVisualization::Categories::Delete(ConstString(category_name));
1619 }
1620 
1621 uint32_t SBDebugger::GetNumCategories() {
1622   LLDB_RECORD_METHOD_NO_ARGS(uint32_t, SBDebugger, GetNumCategories);
1623 
1624   return DataVisualization::Categories::GetCount();
1625 }
1626 
1627 SBTypeCategory SBDebugger::GetCategoryAtIndex(uint32_t index) {
1628   LLDB_RECORD_METHOD(lldb::SBTypeCategory, SBDebugger, GetCategoryAtIndex,
1629                      (uint32_t), index);
1630 
1631   return SBTypeCategory(
1632       DataVisualization::Categories::GetCategoryAtIndex(index));
1633 }
1634 
1635 SBTypeCategory SBDebugger::GetDefaultCategory() {
1636   LLDB_RECORD_METHOD_NO_ARGS(lldb::SBTypeCategory, SBDebugger,
1637                              GetDefaultCategory);
1638 
1639   return GetCategory("default");
1640 }
1641 
1642 SBTypeFormat SBDebugger::GetFormatForType(SBTypeNameSpecifier type_name) {
1643   LLDB_RECORD_METHOD(lldb::SBTypeFormat, SBDebugger, GetFormatForType,
1644                      (lldb::SBTypeNameSpecifier), type_name);
1645 
1646   SBTypeCategory default_category_sb = GetDefaultCategory();
1647   if (default_category_sb.GetEnabled())
1648     return default_category_sb.GetFormatForType(type_name);
1649   return SBTypeFormat();
1650 }
1651 
1652 SBTypeSummary SBDebugger::GetSummaryForType(SBTypeNameSpecifier type_name) {
1653   LLDB_RECORD_METHOD(lldb::SBTypeSummary, SBDebugger, GetSummaryForType,
1654                      (lldb::SBTypeNameSpecifier), type_name);
1655 
1656   if (!type_name.IsValid())
1657     return SBTypeSummary();
1658   return SBTypeSummary(DataVisualization::GetSummaryForType(type_name.GetSP()));
1659 }
1660 
1661 SBTypeFilter SBDebugger::GetFilterForType(SBTypeNameSpecifier type_name) {
1662   LLDB_RECORD_METHOD(lldb::SBTypeFilter, SBDebugger, GetFilterForType,
1663                      (lldb::SBTypeNameSpecifier), type_name);
1664 
1665   if (!type_name.IsValid())
1666     return SBTypeFilter();
1667   return SBTypeFilter(DataVisualization::GetFilterForType(type_name.GetSP()));
1668 }
1669 
1670 SBTypeSynthetic SBDebugger::GetSyntheticForType(SBTypeNameSpecifier type_name) {
1671   LLDB_RECORD_METHOD(lldb::SBTypeSynthetic, SBDebugger, GetSyntheticForType,
1672                      (lldb::SBTypeNameSpecifier), type_name);
1673 
1674   if (!type_name.IsValid())
1675     return SBTypeSynthetic();
1676   return SBTypeSynthetic(
1677       DataVisualization::GetSyntheticForType(type_name.GetSP()));
1678 }
1679 
1680 static llvm::ArrayRef<const char *> GetCategoryArray(const char **categories) {
1681   if (categories == nullptr)
1682     return {};
1683   size_t len = 0;
1684   while (categories[len] != nullptr)
1685     ++len;
1686   return llvm::makeArrayRef(categories, len);
1687 }
1688 
1689 bool SBDebugger::EnableLog(const char *channel, const char **categories) {
1690   LLDB_RECORD_METHOD(bool, SBDebugger, EnableLog, (const char *, const char **),
1691                      channel, categories);
1692 
1693   if (m_opaque_sp) {
1694     uint32_t log_options =
1695         LLDB_LOG_OPTION_PREPEND_TIMESTAMP | LLDB_LOG_OPTION_PREPEND_THREAD_NAME;
1696     std::string error;
1697     llvm::raw_string_ostream error_stream(error);
1698     return m_opaque_sp->EnableLog(channel, GetCategoryArray(categories), "",
1699                                   log_options, error_stream);
1700   } else
1701     return false;
1702 }
1703 
1704 void SBDebugger::SetLoggingCallback(lldb::LogOutputCallback log_callback,
1705                                     void *baton) {
1706   LLDB_RECORD_DUMMY(void, SBDebugger, SetLoggingCallback,
1707                     (lldb::LogOutputCallback, void *), log_callback, baton);
1708 
1709   if (m_opaque_sp) {
1710     return m_opaque_sp->SetLoggingCallback(log_callback, baton);
1711   }
1712 }
1713