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 29 SBTypeCategory::SBTypeCategory() { LLDB_INSTRUMENT_VA(this); } 30 31 SBTypeCategory::SBTypeCategory(const char *name) { 32 DataVisualization::Categories::GetCategory(ConstString(name), m_opaque_sp); 33 } 34 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 42 bool SBTypeCategory::IsValid() const { 43 LLDB_INSTRUMENT_VA(this); 44 return this->operator bool(); 45 } 46 SBTypeCategory::operator bool() const { 47 LLDB_INSTRUMENT_VA(this); 48 49 return (m_opaque_sp.get() != nullptr); 50 } 51 52 bool SBTypeCategory::GetEnabled() { 53 LLDB_INSTRUMENT_VA(this); 54 55 if (!IsValid()) 56 return false; 57 return m_opaque_sp->IsEnabled(); 58 } 59 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 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 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 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 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 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 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 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 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 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 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 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 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 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 } 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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:: 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 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 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 596 lldb::TypeCategoryImplSP SBTypeCategory::GetSP() { 597 if (!IsValid()) 598 return lldb::TypeCategoryImplSP(); 599 return m_opaque_sp; 600 } 601 602 void SBTypeCategory::SetSP( 603 const lldb::TypeCategoryImplSP &typecategory_impl_sp) { 604 m_opaque_sp = typecategory_impl_sp; 605 } 606 607 SBTypeCategory::SBTypeCategory( 608 const lldb::TypeCategoryImplSP &typecategory_impl_sp) 609 : m_opaque_sp(typecategory_impl_sp) {} 610 611 bool SBTypeCategory::IsDefaultCategory() { 612 if (!IsValid()) 613 return false; 614 615 return (strcmp(m_opaque_sp->GetName(), "default") == 0); 616 } 617