1 //===-- SBTypeCategory.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/SBTypeCategory.h"
10 #include "lldb/Utility/Instrumentation.h"
11
12 #include "lldb/API/SBStream.h"
13 #include "lldb/API/SBTypeFilter.h"
14 #include "lldb/API/SBTypeFormat.h"
15 #include "lldb/API/SBTypeNameSpecifier.h"
16 #include "lldb/API/SBTypeSummary.h"
17 #include "lldb/API/SBTypeSynthetic.h"
18
19 #include "lldb/Core/Debugger.h"
20 #include "lldb/DataFormatters/DataVisualization.h"
21 #include "lldb/Interpreter/CommandInterpreter.h"
22 #include "lldb/Interpreter/ScriptInterpreter.h"
23
24 using namespace lldb;
25 using namespace lldb_private;
26
27 typedef std::pair<lldb::TypeCategoryImplSP, user_id_t> ImplType;
28
SBTypeCategory()29 SBTypeCategory::SBTypeCategory() { LLDB_INSTRUMENT_VA(this); }
30
SBTypeCategory(const char * name)31 SBTypeCategory::SBTypeCategory(const char *name) {
32 DataVisualization::Categories::GetCategory(ConstString(name), m_opaque_sp);
33 }
34
SBTypeCategory(const lldb::SBTypeCategory & rhs)35 SBTypeCategory::SBTypeCategory(const lldb::SBTypeCategory &rhs)
36 : m_opaque_sp(rhs.m_opaque_sp) {
37 LLDB_INSTRUMENT_VA(this, rhs);
38 }
39
40 SBTypeCategory::~SBTypeCategory() = default;
41
IsValid() const42 bool SBTypeCategory::IsValid() const {
43 LLDB_INSTRUMENT_VA(this);
44 return this->operator bool();
45 }
operator bool() const46 SBTypeCategory::operator bool() const {
47 LLDB_INSTRUMENT_VA(this);
48
49 return (m_opaque_sp.get() != nullptr);
50 }
51
GetEnabled()52 bool SBTypeCategory::GetEnabled() {
53 LLDB_INSTRUMENT_VA(this);
54
55 if (!IsValid())
56 return false;
57 return m_opaque_sp->IsEnabled();
58 }
59
SetEnabled(bool enabled)60 void SBTypeCategory::SetEnabled(bool enabled) {
61 LLDB_INSTRUMENT_VA(this, enabled);
62
63 if (!IsValid())
64 return;
65 if (enabled)
66 DataVisualization::Categories::Enable(m_opaque_sp);
67 else
68 DataVisualization::Categories::Disable(m_opaque_sp);
69 }
70
GetName()71 const char *SBTypeCategory::GetName() {
72 LLDB_INSTRUMENT_VA(this);
73
74 if (!IsValid())
75 return nullptr;
76 return m_opaque_sp->GetName();
77 }
78
GetLanguageAtIndex(uint32_t idx)79 lldb::LanguageType SBTypeCategory::GetLanguageAtIndex(uint32_t idx) {
80 LLDB_INSTRUMENT_VA(this, idx);
81
82 if (IsValid())
83 return m_opaque_sp->GetLanguageAtIndex(idx);
84 return lldb::eLanguageTypeUnknown;
85 }
86
GetNumLanguages()87 uint32_t SBTypeCategory::GetNumLanguages() {
88 LLDB_INSTRUMENT_VA(this);
89
90 if (IsValid())
91 return m_opaque_sp->GetNumLanguages();
92 return 0;
93 }
94
AddLanguage(lldb::LanguageType language)95 void SBTypeCategory::AddLanguage(lldb::LanguageType language) {
96 LLDB_INSTRUMENT_VA(this, language);
97
98 if (IsValid())
99 m_opaque_sp->AddLanguage(language);
100 }
101
GetNumFormats()102 uint32_t SBTypeCategory::GetNumFormats() {
103 LLDB_INSTRUMENT_VA(this);
104
105 if (!IsValid())
106 return 0;
107
108 return m_opaque_sp->GetTypeFormatsContainer()->GetCount() +
109 m_opaque_sp->GetRegexTypeFormatsContainer()->GetCount();
110 }
111
GetNumSummaries()112 uint32_t SBTypeCategory::GetNumSummaries() {
113 LLDB_INSTRUMENT_VA(this);
114
115 if (!IsValid())
116 return 0;
117 return m_opaque_sp->GetTypeSummariesContainer()->GetCount() +
118 m_opaque_sp->GetRegexTypeSummariesContainer()->GetCount();
119 }
120
GetNumFilters()121 uint32_t SBTypeCategory::GetNumFilters() {
122 LLDB_INSTRUMENT_VA(this);
123
124 if (!IsValid())
125 return 0;
126 return m_opaque_sp->GetTypeFiltersContainer()->GetCount() +
127 m_opaque_sp->GetRegexTypeFiltersContainer()->GetCount();
128 }
129
GetNumSynthetics()130 uint32_t SBTypeCategory::GetNumSynthetics() {
131 LLDB_INSTRUMENT_VA(this);
132
133 if (!IsValid())
134 return 0;
135 return m_opaque_sp->GetTypeSyntheticsContainer()->GetCount() +
136 m_opaque_sp->GetRegexTypeSyntheticsContainer()->GetCount();
137 }
138
139 lldb::SBTypeNameSpecifier
GetTypeNameSpecifierForFilterAtIndex(uint32_t index)140 SBTypeCategory::GetTypeNameSpecifierForFilterAtIndex(uint32_t index) {
141 LLDB_INSTRUMENT_VA(this, index);
142
143 if (!IsValid())
144 return SBTypeNameSpecifier();
145 return SBTypeNameSpecifier(
146 m_opaque_sp->GetTypeNameSpecifierForFilterAtIndex(index));
147 }
148
149 lldb::SBTypeNameSpecifier
GetTypeNameSpecifierForFormatAtIndex(uint32_t index)150 SBTypeCategory::GetTypeNameSpecifierForFormatAtIndex(uint32_t index) {
151 LLDB_INSTRUMENT_VA(this, index);
152
153 if (!IsValid())
154 return SBTypeNameSpecifier();
155 return SBTypeNameSpecifier(
156 m_opaque_sp->GetTypeNameSpecifierForFormatAtIndex(index));
157 }
158
159 lldb::SBTypeNameSpecifier
GetTypeNameSpecifierForSummaryAtIndex(uint32_t index)160 SBTypeCategory::GetTypeNameSpecifierForSummaryAtIndex(uint32_t index) {
161 LLDB_INSTRUMENT_VA(this, index);
162
163 if (!IsValid())
164 return SBTypeNameSpecifier();
165 return SBTypeNameSpecifier(
166 m_opaque_sp->GetTypeNameSpecifierForSummaryAtIndex(index));
167 }
168
169 lldb::SBTypeNameSpecifier
GetTypeNameSpecifierForSyntheticAtIndex(uint32_t index)170 SBTypeCategory::GetTypeNameSpecifierForSyntheticAtIndex(uint32_t index) {
171 LLDB_INSTRUMENT_VA(this, index);
172
173 if (!IsValid())
174 return SBTypeNameSpecifier();
175 return SBTypeNameSpecifier(
176 m_opaque_sp->GetTypeNameSpecifierForSyntheticAtIndex(index));
177 }
178
GetFilterForType(SBTypeNameSpecifier spec)179 SBTypeFilter SBTypeCategory::GetFilterForType(SBTypeNameSpecifier spec) {
180 LLDB_INSTRUMENT_VA(this, spec);
181
182 if (!IsValid())
183 return SBTypeFilter();
184
185 if (!spec.IsValid())
186 return SBTypeFilter();
187
188 lldb::TypeFilterImplSP children_sp;
189
190 if (spec.IsRegex())
191 m_opaque_sp->GetRegexTypeFiltersContainer()->GetExact(
192 ConstString(spec.GetName()), children_sp);
193 else
194 m_opaque_sp->GetTypeFiltersContainer()->GetExact(
195 ConstString(spec.GetName()), children_sp);
196
197 if (!children_sp)
198 return lldb::SBTypeFilter();
199
200 TypeFilterImplSP filter_sp =
201 std::static_pointer_cast<TypeFilterImpl>(children_sp);
202
203 return lldb::SBTypeFilter(filter_sp);
204 }
GetFormatForType(SBTypeNameSpecifier spec)205 SBTypeFormat SBTypeCategory::GetFormatForType(SBTypeNameSpecifier spec) {
206 LLDB_INSTRUMENT_VA(this, spec);
207
208 if (!IsValid())
209 return SBTypeFormat();
210
211 if (!spec.IsValid())
212 return SBTypeFormat();
213
214 lldb::TypeFormatImplSP format_sp;
215
216 if (spec.IsRegex())
217 m_opaque_sp->GetRegexTypeFormatsContainer()->GetExact(
218 ConstString(spec.GetName()), format_sp);
219 else
220 m_opaque_sp->GetTypeFormatsContainer()->GetExact(
221 ConstString(spec.GetName()), format_sp);
222
223 if (!format_sp)
224 return lldb::SBTypeFormat();
225
226 return lldb::SBTypeFormat(format_sp);
227 }
228
GetSummaryForType(SBTypeNameSpecifier spec)229 SBTypeSummary SBTypeCategory::GetSummaryForType(SBTypeNameSpecifier spec) {
230 LLDB_INSTRUMENT_VA(this, spec);
231
232 if (!IsValid())
233 return SBTypeSummary();
234
235 if (!spec.IsValid())
236 return SBTypeSummary();
237
238 lldb::TypeSummaryImplSP summary_sp;
239
240 if (spec.IsRegex())
241 m_opaque_sp->GetRegexTypeSummariesContainer()->GetExact(
242 ConstString(spec.GetName()), summary_sp);
243 else
244 m_opaque_sp->GetTypeSummariesContainer()->GetExact(
245 ConstString(spec.GetName()), summary_sp);
246
247 if (!summary_sp)
248 return lldb::SBTypeSummary();
249
250 return lldb::SBTypeSummary(summary_sp);
251 }
252
GetSyntheticForType(SBTypeNameSpecifier spec)253 SBTypeSynthetic SBTypeCategory::GetSyntheticForType(SBTypeNameSpecifier spec) {
254 LLDB_INSTRUMENT_VA(this, spec);
255
256 if (!IsValid())
257 return SBTypeSynthetic();
258
259 if (!spec.IsValid())
260 return SBTypeSynthetic();
261
262 lldb::SyntheticChildrenSP children_sp;
263
264 if (spec.IsRegex())
265 m_opaque_sp->GetRegexTypeSyntheticsContainer()->GetExact(
266 ConstString(spec.GetName()), children_sp);
267 else
268 m_opaque_sp->GetTypeSyntheticsContainer()->GetExact(
269 ConstString(spec.GetName()), children_sp);
270
271 if (!children_sp)
272 return lldb::SBTypeSynthetic();
273
274 ScriptedSyntheticChildrenSP synth_sp =
275 std::static_pointer_cast<ScriptedSyntheticChildren>(children_sp);
276
277 return lldb::SBTypeSynthetic(synth_sp);
278 }
279
GetFilterAtIndex(uint32_t index)280 SBTypeFilter SBTypeCategory::GetFilterAtIndex(uint32_t index) {
281 LLDB_INSTRUMENT_VA(this, index);
282
283 if (!IsValid())
284 return SBTypeFilter();
285 lldb::SyntheticChildrenSP children_sp =
286 m_opaque_sp->GetSyntheticAtIndex((index));
287
288 if (!children_sp.get())
289 return lldb::SBTypeFilter();
290
291 TypeFilterImplSP filter_sp =
292 std::static_pointer_cast<TypeFilterImpl>(children_sp);
293
294 return lldb::SBTypeFilter(filter_sp);
295 }
296
GetFormatAtIndex(uint32_t index)297 SBTypeFormat SBTypeCategory::GetFormatAtIndex(uint32_t index) {
298 LLDB_INSTRUMENT_VA(this, index);
299
300 if (!IsValid())
301 return SBTypeFormat();
302 return SBTypeFormat(m_opaque_sp->GetFormatAtIndex((index)));
303 }
304
GetSummaryAtIndex(uint32_t index)305 SBTypeSummary SBTypeCategory::GetSummaryAtIndex(uint32_t index) {
306 LLDB_INSTRUMENT_VA(this, index);
307
308 if (!IsValid())
309 return SBTypeSummary();
310 return SBTypeSummary(m_opaque_sp->GetSummaryAtIndex((index)));
311 }
312
GetSyntheticAtIndex(uint32_t index)313 SBTypeSynthetic SBTypeCategory::GetSyntheticAtIndex(uint32_t index) {
314 LLDB_INSTRUMENT_VA(this, index);
315
316 if (!IsValid())
317 return SBTypeSynthetic();
318 lldb::SyntheticChildrenSP children_sp =
319 m_opaque_sp->GetSyntheticAtIndex((index));
320
321 if (!children_sp.get())
322 return lldb::SBTypeSynthetic();
323
324 ScriptedSyntheticChildrenSP synth_sp =
325 std::static_pointer_cast<ScriptedSyntheticChildren>(children_sp);
326
327 return lldb::SBTypeSynthetic(synth_sp);
328 }
329
AddTypeFormat(SBTypeNameSpecifier type_name,SBTypeFormat format)330 bool SBTypeCategory::AddTypeFormat(SBTypeNameSpecifier type_name,
331 SBTypeFormat format) {
332 LLDB_INSTRUMENT_VA(this, type_name, format);
333
334 if (!IsValid())
335 return false;
336
337 if (!type_name.IsValid())
338 return false;
339
340 if (!format.IsValid())
341 return false;
342
343 if (type_name.IsRegex())
344 m_opaque_sp->GetRegexTypeFormatsContainer()->Add(
345 RegularExpression(type_name.GetName()), format.GetSP());
346 else
347 m_opaque_sp->GetTypeFormatsContainer()->Add(
348 ConstString(type_name.GetName()), format.GetSP());
349
350 return true;
351 }
352
DeleteTypeFormat(SBTypeNameSpecifier type_name)353 bool SBTypeCategory::DeleteTypeFormat(SBTypeNameSpecifier type_name) {
354 LLDB_INSTRUMENT_VA(this, type_name);
355
356 if (!IsValid())
357 return false;
358
359 if (!type_name.IsValid())
360 return false;
361
362 if (type_name.IsRegex())
363 return m_opaque_sp->GetRegexTypeFormatsContainer()->Delete(
364 ConstString(type_name.GetName()));
365 else
366 return m_opaque_sp->GetTypeFormatsContainer()->Delete(
367 ConstString(type_name.GetName()));
368 }
369
AddTypeSummary(SBTypeNameSpecifier type_name,SBTypeSummary summary)370 bool SBTypeCategory::AddTypeSummary(SBTypeNameSpecifier type_name,
371 SBTypeSummary summary) {
372 LLDB_INSTRUMENT_VA(this, type_name, summary);
373
374 if (!IsValid())
375 return false;
376
377 if (!type_name.IsValid())
378 return false;
379
380 if (!summary.IsValid())
381 return false;
382
383 // FIXME: we need to iterate over all the Debugger objects and have each of
384 // them contain a copy of the function
385 // since we currently have formatters live in a global space, while Python
386 // code lives in a specific Debugger-related environment this should
387 // eventually be fixed by deciding a final location in the LLDB object space
388 // for formatters
389 if (summary.IsFunctionCode()) {
390 const void *name_token =
391 (const void *)ConstString(type_name.GetName()).GetCString();
392 const char *script = summary.GetData();
393 StringList input;
394 input.SplitIntoLines(script, strlen(script));
395 uint32_t num_debuggers = lldb_private::Debugger::GetNumDebuggers();
396 bool need_set = true;
397 for (uint32_t j = 0; j < num_debuggers; j++) {
398 DebuggerSP debugger_sp = lldb_private::Debugger::GetDebuggerAtIndex(j);
399 if (debugger_sp) {
400 ScriptInterpreter *interpreter_ptr =
401 debugger_sp->GetScriptInterpreter();
402 if (interpreter_ptr) {
403 std::string output;
404 if (interpreter_ptr->GenerateTypeScriptFunction(input, output,
405 name_token) &&
406 !output.empty()) {
407 if (need_set) {
408 need_set = false;
409 summary.SetFunctionName(output.c_str());
410 }
411 }
412 }
413 }
414 }
415 }
416
417 if (type_name.IsRegex())
418 m_opaque_sp->GetRegexTypeSummariesContainer()->Add(
419 RegularExpression(type_name.GetName()), summary.GetSP());
420 else
421 m_opaque_sp->GetTypeSummariesContainer()->Add(
422 ConstString(type_name.GetName()), summary.GetSP());
423
424 return true;
425 }
426
DeleteTypeSummary(SBTypeNameSpecifier type_name)427 bool SBTypeCategory::DeleteTypeSummary(SBTypeNameSpecifier type_name) {
428 LLDB_INSTRUMENT_VA(this, type_name);
429
430 if (!IsValid())
431 return false;
432
433 if (!type_name.IsValid())
434 return false;
435
436 if (type_name.IsRegex())
437 return m_opaque_sp->GetRegexTypeSummariesContainer()->Delete(
438 ConstString(type_name.GetName()));
439 else
440 return m_opaque_sp->GetTypeSummariesContainer()->Delete(
441 ConstString(type_name.GetName()));
442 }
443
AddTypeFilter(SBTypeNameSpecifier type_name,SBTypeFilter filter)444 bool SBTypeCategory::AddTypeFilter(SBTypeNameSpecifier type_name,
445 SBTypeFilter filter) {
446 LLDB_INSTRUMENT_VA(this, type_name, filter);
447
448 if (!IsValid())
449 return false;
450
451 if (!type_name.IsValid())
452 return false;
453
454 if (!filter.IsValid())
455 return false;
456
457 if (type_name.IsRegex())
458 m_opaque_sp->GetRegexTypeFiltersContainer()->Add(
459 RegularExpression(type_name.GetName()), filter.GetSP());
460 else
461 m_opaque_sp->GetTypeFiltersContainer()->Add(
462 ConstString(type_name.GetName()), filter.GetSP());
463
464 return true;
465 }
466
DeleteTypeFilter(SBTypeNameSpecifier type_name)467 bool SBTypeCategory::DeleteTypeFilter(SBTypeNameSpecifier type_name) {
468 LLDB_INSTRUMENT_VA(this, type_name);
469
470 if (!IsValid())
471 return false;
472
473 if (!type_name.IsValid())
474 return false;
475
476 if (type_name.IsRegex())
477 return m_opaque_sp->GetRegexTypeFiltersContainer()->Delete(
478 ConstString(type_name.GetName()));
479 else
480 return m_opaque_sp->GetTypeFiltersContainer()->Delete(
481 ConstString(type_name.GetName()));
482 }
483
AddTypeSynthetic(SBTypeNameSpecifier type_name,SBTypeSynthetic synth)484 bool SBTypeCategory::AddTypeSynthetic(SBTypeNameSpecifier type_name,
485 SBTypeSynthetic synth) {
486 LLDB_INSTRUMENT_VA(this, type_name, synth);
487
488 if (!IsValid())
489 return false;
490
491 if (!type_name.IsValid())
492 return false;
493
494 if (!synth.IsValid())
495 return false;
496
497 // FIXME: we need to iterate over all the Debugger objects and have each of
498 // them contain a copy of the function
499 // since we currently have formatters live in a global space, while Python
500 // code lives in a specific Debugger-related environment this should
501 // eventually be fixed by deciding a final location in the LLDB object space
502 // for formatters
503 if (synth.IsClassCode()) {
504 const void *name_token =
505 (const void *)ConstString(type_name.GetName()).GetCString();
506 const char *script = synth.GetData();
507 StringList input;
508 input.SplitIntoLines(script, strlen(script));
509 uint32_t num_debuggers = lldb_private::Debugger::GetNumDebuggers();
510 bool need_set = true;
511 for (uint32_t j = 0; j < num_debuggers; j++) {
512 DebuggerSP debugger_sp = lldb_private::Debugger::GetDebuggerAtIndex(j);
513 if (debugger_sp) {
514 ScriptInterpreter *interpreter_ptr =
515 debugger_sp->GetScriptInterpreter();
516 if (interpreter_ptr) {
517 std::string output;
518 if (interpreter_ptr->GenerateTypeSynthClass(input, output,
519 name_token) &&
520 !output.empty()) {
521 if (need_set) {
522 need_set = false;
523 synth.SetClassName(output.c_str());
524 }
525 }
526 }
527 }
528 }
529 }
530
531 if (type_name.IsRegex())
532 m_opaque_sp->GetRegexTypeSyntheticsContainer()->Add(
533 RegularExpression(type_name.GetName()), synth.GetSP());
534 else
535 m_opaque_sp->GetTypeSyntheticsContainer()->Add(
536 ConstString(type_name.GetName()), synth.GetSP());
537
538 return true;
539 }
540
DeleteTypeSynthetic(SBTypeNameSpecifier type_name)541 bool SBTypeCategory::DeleteTypeSynthetic(SBTypeNameSpecifier type_name) {
542 LLDB_INSTRUMENT_VA(this, type_name);
543
544 if (!IsValid())
545 return false;
546
547 if (!type_name.IsValid())
548 return false;
549
550 if (type_name.IsRegex())
551 return m_opaque_sp->GetRegexTypeSyntheticsContainer()->Delete(
552 ConstString(type_name.GetName()));
553 else
554 return m_opaque_sp->GetTypeSyntheticsContainer()->Delete(
555 ConstString(type_name.GetName()));
556 }
557
GetDescription(lldb::SBStream & description,lldb::DescriptionLevel description_level)558 bool SBTypeCategory::GetDescription(lldb::SBStream &description,
559 lldb::DescriptionLevel description_level) {
560 LLDB_INSTRUMENT_VA(this, description, description_level);
561
562 if (!IsValid())
563 return false;
564 description.Printf("Category name: %s\n", GetName());
565 return true;
566 }
567
568 lldb::SBTypeCategory &SBTypeCategory::
operator =(const lldb::SBTypeCategory & rhs)569 operator=(const lldb::SBTypeCategory &rhs) {
570 LLDB_INSTRUMENT_VA(this, rhs);
571
572 if (this != &rhs) {
573 m_opaque_sp = rhs.m_opaque_sp;
574 }
575 return *this;
576 }
577
operator ==(lldb::SBTypeCategory & rhs)578 bool SBTypeCategory::operator==(lldb::SBTypeCategory &rhs) {
579 LLDB_INSTRUMENT_VA(this, rhs);
580
581 if (!IsValid())
582 return !rhs.IsValid();
583
584 return m_opaque_sp.get() == rhs.m_opaque_sp.get();
585 }
586
operator !=(lldb::SBTypeCategory & rhs)587 bool SBTypeCategory::operator!=(lldb::SBTypeCategory &rhs) {
588 LLDB_INSTRUMENT_VA(this, rhs);
589
590 if (!IsValid())
591 return rhs.IsValid();
592
593 return m_opaque_sp.get() != rhs.m_opaque_sp.get();
594 }
595
GetSP()596 lldb::TypeCategoryImplSP SBTypeCategory::GetSP() {
597 if (!IsValid())
598 return lldb::TypeCategoryImplSP();
599 return m_opaque_sp;
600 }
601
SetSP(const lldb::TypeCategoryImplSP & typecategory_impl_sp)602 void SBTypeCategory::SetSP(
603 const lldb::TypeCategoryImplSP &typecategory_impl_sp) {
604 m_opaque_sp = typecategory_impl_sp;
605 }
606
SBTypeCategory(const lldb::TypeCategoryImplSP & typecategory_impl_sp)607 SBTypeCategory::SBTypeCategory(
608 const lldb::TypeCategoryImplSP &typecategory_impl_sp)
609 : m_opaque_sp(typecategory_impl_sp) {}
610
IsDefaultCategory()611 bool SBTypeCategory::IsDefaultCategory() {
612 if (!IsValid())
613 return false;
614
615 return (strcmp(m_opaque_sp->GetName(), "default") == 0);
616 }
617