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