1 //===-- FormatManager.cpp -------------------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "lldb/DataFormatters/FormatManager.h" 11 12 #include "llvm/ADT/STLExtras.h" 13 14 // C Includes 15 // C++ Includes 16 // Other libraries and framework includes 17 // Project includes 18 19 #include "lldb/Core/Debugger.h" 20 #include "lldb/Core/Log.h" 21 #include "lldb/DataFormatters/FormattersHelpers.h" 22 #include "lldb/DataFormatters/LanguageCategory.h" 23 #include "lldb/Target/ExecutionContext.h" 24 #include "lldb/Target/Language.h" 25 26 using namespace lldb; 27 using namespace lldb_private; 28 using namespace lldb_private::formatters; 29 30 struct FormatInfo 31 { 32 Format format; 33 const char format_char; // One or more format characters that can be used for this format. 34 const char *format_name; // Long format name that can be used to specify the current format 35 }; 36 37 static FormatInfo 38 g_format_infos[] = 39 { 40 { eFormatDefault , '\0' , "default" }, 41 { eFormatBoolean , 'B' , "boolean" }, 42 { eFormatBinary , 'b' , "binary" }, 43 { eFormatBytes , 'y' , "bytes" }, 44 { eFormatBytesWithASCII , 'Y' , "bytes with ASCII" }, 45 { eFormatChar , 'c' , "character" }, 46 { eFormatCharPrintable , 'C' , "printable character" }, 47 { eFormatComplexFloat , 'F' , "complex float" }, 48 { eFormatCString , 's' , "c-string" }, 49 { eFormatDecimal , 'd' , "decimal" }, 50 { eFormatEnum , 'E' , "enumeration" }, 51 { eFormatHex , 'x' , "hex" }, 52 { eFormatHexUppercase , 'X' , "uppercase hex" }, 53 { eFormatFloat , 'f' , "float" }, 54 { eFormatOctal , 'o' , "octal" }, 55 { eFormatOSType , 'O' , "OSType" }, 56 { eFormatUnicode16 , 'U' , "unicode16" }, 57 { eFormatUnicode32 , '\0' , "unicode32" }, 58 { eFormatUnsigned , 'u' , "unsigned decimal" }, 59 { eFormatPointer , 'p' , "pointer" }, 60 { eFormatVectorOfChar , '\0' , "char[]" }, 61 { eFormatVectorOfSInt8 , '\0' , "int8_t[]" }, 62 { eFormatVectorOfUInt8 , '\0' , "uint8_t[]" }, 63 { eFormatVectorOfSInt16 , '\0' , "int16_t[]" }, 64 { eFormatVectorOfUInt16 , '\0' , "uint16_t[]" }, 65 { eFormatVectorOfSInt32 , '\0' , "int32_t[]" }, 66 { eFormatVectorOfUInt32 , '\0' , "uint32_t[]" }, 67 { eFormatVectorOfSInt64 , '\0' , "int64_t[]" }, 68 { eFormatVectorOfUInt64 , '\0' , "uint64_t[]" }, 69 { eFormatVectorOfFloat16, '\0' , "float16[]" }, 70 { eFormatVectorOfFloat32, '\0' , "float32[]" }, 71 { eFormatVectorOfFloat64, '\0' , "float64[]" }, 72 { eFormatVectorOfUInt128, '\0' , "uint128_t[]" }, 73 { eFormatComplexInteger , 'I' , "complex integer" }, 74 { eFormatCharArray , 'a' , "character array" }, 75 { eFormatAddressInfo , 'A' , "address" }, 76 { eFormatHexFloat , '\0' , "hex float" }, 77 { eFormatInstruction , 'i' , "instruction" }, 78 { eFormatVoid , 'v' , "void" } 79 }; 80 81 static uint32_t g_num_format_infos = llvm::array_lengthof(g_format_infos); 82 83 static bool 84 GetFormatFromFormatChar (char format_char, Format &format) 85 { 86 for (uint32_t i=0; i<g_num_format_infos; ++i) 87 { 88 if (g_format_infos[i].format_char == format_char) 89 { 90 format = g_format_infos[i].format; 91 return true; 92 } 93 } 94 format = eFormatInvalid; 95 return false; 96 } 97 98 static bool 99 GetFormatFromFormatName (const char *format_name, bool partial_match_ok, Format &format) 100 { 101 uint32_t i; 102 for (i=0; i<g_num_format_infos; ++i) 103 { 104 if (strcasecmp (g_format_infos[i].format_name, format_name) == 0) 105 { 106 format = g_format_infos[i].format; 107 return true; 108 } 109 } 110 111 if (partial_match_ok) 112 { 113 for (i=0; i<g_num_format_infos; ++i) 114 { 115 if (strcasestr (g_format_infos[i].format_name, format_name) == g_format_infos[i].format_name) 116 { 117 format = g_format_infos[i].format; 118 return true; 119 } 120 } 121 } 122 format = eFormatInvalid; 123 return false; 124 } 125 126 bool 127 FormatManager::GetFormatFromCString (const char *format_cstr, 128 bool partial_match_ok, 129 lldb::Format &format) 130 { 131 bool success = false; 132 if (format_cstr && format_cstr[0]) 133 { 134 if (format_cstr[1] == '\0') 135 { 136 success = GetFormatFromFormatChar (format_cstr[0], format); 137 if (success) 138 return true; 139 } 140 141 success = GetFormatFromFormatName (format_cstr, partial_match_ok, format); 142 } 143 if (!success) 144 format = eFormatInvalid; 145 return success; 146 } 147 148 char 149 FormatManager::GetFormatAsFormatChar (lldb::Format format) 150 { 151 for (uint32_t i=0; i<g_num_format_infos; ++i) 152 { 153 if (g_format_infos[i].format == format) 154 return g_format_infos[i].format_char; 155 } 156 return '\0'; 157 } 158 159 const char * 160 FormatManager::GetFormatAsCString (Format format) 161 { 162 if (format >= eFormatDefault && format < kNumFormats) 163 return g_format_infos[format].format_name; 164 return NULL; 165 } 166 167 void 168 FormatManager::EnableAllCategories () 169 { 170 m_categories_map.EnableAllCategories (); 171 Mutex::Locker lang_locker(m_language_categories_mutex); 172 for (auto& iter : m_language_categories_map) 173 { 174 if (iter.second) 175 iter.second->Enable(); 176 } 177 } 178 179 void 180 FormatManager::DisableAllCategories () 181 { 182 m_categories_map.DisableAllCategories (); 183 Mutex::Locker lang_locker(m_language_categories_mutex); 184 for (auto& iter : m_language_categories_map) 185 { 186 if (iter.second) 187 iter.second->Disable(); 188 } 189 } 190 191 void 192 FormatManager::GetPossibleMatches (ValueObject& valobj, 193 CompilerType compiler_type, 194 uint32_t reason, 195 lldb::DynamicValueType use_dynamic, 196 FormattersMatchVector& entries, 197 bool did_strip_ptr, 198 bool did_strip_ref, 199 bool did_strip_typedef, 200 bool root_level) 201 { 202 compiler_type = compiler_type.GetTypeForFormatters(); 203 ConstString type_name(compiler_type.GetConstTypeName()); 204 if (valobj.GetBitfieldBitSize() > 0) 205 { 206 StreamString sstring; 207 sstring.Printf("%s:%d",type_name.AsCString(),valobj.GetBitfieldBitSize()); 208 ConstString bitfieldname = ConstString(sstring.GetData()); 209 entries.push_back({bitfieldname,0,did_strip_ptr,did_strip_ref,did_strip_typedef}); 210 reason |= lldb_private::eFormatterChoiceCriterionStrippedBitField; 211 } 212 213 if (!compiler_type.IsMeaninglessWithoutDynamicResolution()) 214 { 215 entries.push_back({type_name,reason,did_strip_ptr,did_strip_ref,did_strip_typedef}); 216 217 ConstString display_type_name(compiler_type.GetDisplayTypeName()); 218 if (display_type_name != type_name) 219 entries.push_back({display_type_name,reason,did_strip_ptr,did_strip_ref,did_strip_typedef}); 220 } 221 222 for (bool is_rvalue_ref = true, j = true; j && compiler_type.IsReferenceType(nullptr, &is_rvalue_ref); j = false) 223 { 224 CompilerType non_ref_type = compiler_type.GetNonReferenceType(); 225 GetPossibleMatches(valobj, 226 non_ref_type, 227 reason | lldb_private::eFormatterChoiceCriterionStrippedPointerReference, 228 use_dynamic, 229 entries, 230 did_strip_ptr, 231 true, 232 did_strip_typedef); 233 if (non_ref_type.IsTypedefType()) 234 { 235 CompilerType deffed_referenced_type = non_ref_type.GetTypedefedType(); 236 deffed_referenced_type = is_rvalue_ref ? deffed_referenced_type.GetRValueReferenceType() : deffed_referenced_type.GetLValueReferenceType(); 237 GetPossibleMatches(valobj, 238 deffed_referenced_type, 239 reason | lldb_private::eFormatterChoiceCriterionNavigatedTypedefs, 240 use_dynamic, 241 entries, 242 did_strip_ptr, 243 did_strip_ref, 244 true); // this is not exactly the usual meaning of stripping typedefs 245 } 246 } 247 248 if (compiler_type.IsPointerType()) 249 { 250 CompilerType non_ptr_type = compiler_type.GetPointeeType(); 251 GetPossibleMatches(valobj, 252 non_ptr_type, 253 reason | lldb_private::eFormatterChoiceCriterionStrippedPointerReference, 254 use_dynamic, 255 entries, 256 true, 257 did_strip_ref, 258 did_strip_typedef); 259 if (non_ptr_type.IsTypedefType()) 260 { 261 CompilerType deffed_pointed_type = non_ptr_type.GetTypedefedType().GetPointerType(); 262 GetPossibleMatches(valobj, 263 deffed_pointed_type, 264 reason | lldb_private::eFormatterChoiceCriterionNavigatedTypedefs, 265 use_dynamic, 266 entries, 267 did_strip_ptr, 268 did_strip_ref, 269 true); // this is not exactly the usual meaning of stripping typedefs 270 } 271 } 272 273 for (lldb::LanguageType language_type : GetCandidateLanguages(valobj)) 274 { 275 if (Language* language = Language::FindPlugin(language_type)) 276 { 277 for (ConstString candidate : language->GetPossibleFormattersMatches(valobj, use_dynamic)) 278 { 279 entries.push_back({candidate, 280 reason | lldb_private::eFormatterChoiceCriterionLanguagePlugin, 281 did_strip_ptr, 282 did_strip_ref, 283 did_strip_typedef}); 284 } 285 } 286 } 287 288 // try to strip typedef chains 289 if (compiler_type.IsTypedefType()) 290 { 291 CompilerType deffed_type = compiler_type.GetTypedefedType(); 292 GetPossibleMatches(valobj, 293 deffed_type, 294 reason | lldb_private::eFormatterChoiceCriterionNavigatedTypedefs, 295 use_dynamic, 296 entries, 297 did_strip_ptr, 298 did_strip_ref, 299 true); 300 } 301 302 if (root_level) 303 { 304 do { 305 if (!compiler_type.IsValid()) 306 break; 307 308 CompilerType unqual_compiler_ast_type = compiler_type.GetFullyUnqualifiedType(); 309 if (!unqual_compiler_ast_type.IsValid()) 310 break; 311 if (unqual_compiler_ast_type.GetOpaqueQualType() != compiler_type.GetOpaqueQualType()) 312 GetPossibleMatches (valobj, 313 unqual_compiler_ast_type, 314 reason, 315 use_dynamic, 316 entries, 317 did_strip_ptr, 318 did_strip_ref, 319 did_strip_typedef); 320 } while(false); 321 322 323 // if all else fails, go to static type 324 if (valobj.IsDynamic()) 325 { 326 lldb::ValueObjectSP static_value_sp(valobj.GetStaticValue()); 327 if (static_value_sp) 328 GetPossibleMatches(*static_value_sp.get(), 329 static_value_sp->GetCompilerType(), 330 reason | lldb_private::eFormatterChoiceCriterionWentToStaticValue, 331 use_dynamic, 332 entries, 333 did_strip_ptr, 334 did_strip_ref, 335 did_strip_typedef, 336 true); 337 } 338 } 339 } 340 341 lldb::TypeFormatImplSP 342 FormatManager::GetFormatForType (lldb::TypeNameSpecifierImplSP type_sp) 343 { 344 if (!type_sp) 345 return lldb::TypeFormatImplSP(); 346 lldb::TypeFormatImplSP format_chosen_sp; 347 uint32_t num_categories = m_categories_map.GetCount(); 348 lldb::TypeCategoryImplSP category_sp; 349 uint32_t prio_category = UINT32_MAX; 350 for (uint32_t category_id = 0; 351 category_id < num_categories; 352 category_id++) 353 { 354 category_sp = GetCategoryAtIndex(category_id); 355 if (category_sp->IsEnabled() == false) 356 continue; 357 lldb::TypeFormatImplSP format_current_sp = category_sp->GetFormatForType(type_sp); 358 if (format_current_sp && (format_chosen_sp.get() == NULL || (prio_category > category_sp->GetEnabledPosition()))) 359 { 360 prio_category = category_sp->GetEnabledPosition(); 361 format_chosen_sp = format_current_sp; 362 } 363 } 364 return format_chosen_sp; 365 } 366 367 lldb::TypeSummaryImplSP 368 FormatManager::GetSummaryForType (lldb::TypeNameSpecifierImplSP type_sp) 369 { 370 if (!type_sp) 371 return lldb::TypeSummaryImplSP(); 372 lldb::TypeSummaryImplSP summary_chosen_sp; 373 uint32_t num_categories = m_categories_map.GetCount(); 374 lldb::TypeCategoryImplSP category_sp; 375 uint32_t prio_category = UINT32_MAX; 376 for (uint32_t category_id = 0; 377 category_id < num_categories; 378 category_id++) 379 { 380 category_sp = GetCategoryAtIndex(category_id); 381 if (category_sp->IsEnabled() == false) 382 continue; 383 lldb::TypeSummaryImplSP summary_current_sp = category_sp->GetSummaryForType(type_sp); 384 if (summary_current_sp && (summary_chosen_sp.get() == NULL || (prio_category > category_sp->GetEnabledPosition()))) 385 { 386 prio_category = category_sp->GetEnabledPosition(); 387 summary_chosen_sp = summary_current_sp; 388 } 389 } 390 return summary_chosen_sp; 391 } 392 393 lldb::TypeFilterImplSP 394 FormatManager::GetFilterForType (lldb::TypeNameSpecifierImplSP type_sp) 395 { 396 if (!type_sp) 397 return lldb::TypeFilterImplSP(); 398 lldb::TypeFilterImplSP filter_chosen_sp; 399 uint32_t num_categories = m_categories_map.GetCount(); 400 lldb::TypeCategoryImplSP category_sp; 401 uint32_t prio_category = UINT32_MAX; 402 for (uint32_t category_id = 0; 403 category_id < num_categories; 404 category_id++) 405 { 406 category_sp = GetCategoryAtIndex(category_id); 407 if (category_sp->IsEnabled() == false) 408 continue; 409 lldb::TypeFilterImplSP filter_current_sp((TypeFilterImpl*)category_sp->GetFilterForType(type_sp).get()); 410 if (filter_current_sp && (filter_chosen_sp.get() == NULL || (prio_category > category_sp->GetEnabledPosition()))) 411 { 412 prio_category = category_sp->GetEnabledPosition(); 413 filter_chosen_sp = filter_current_sp; 414 } 415 } 416 return filter_chosen_sp; 417 } 418 419 #ifndef LLDB_DISABLE_PYTHON 420 lldb::ScriptedSyntheticChildrenSP 421 FormatManager::GetSyntheticForType (lldb::TypeNameSpecifierImplSP type_sp) 422 { 423 if (!type_sp) 424 return lldb::ScriptedSyntheticChildrenSP(); 425 lldb::ScriptedSyntheticChildrenSP synth_chosen_sp; 426 uint32_t num_categories = m_categories_map.GetCount(); 427 lldb::TypeCategoryImplSP category_sp; 428 uint32_t prio_category = UINT32_MAX; 429 for (uint32_t category_id = 0; 430 category_id < num_categories; 431 category_id++) 432 { 433 category_sp = GetCategoryAtIndex(category_id); 434 if (category_sp->IsEnabled() == false) 435 continue; 436 lldb::ScriptedSyntheticChildrenSP synth_current_sp((ScriptedSyntheticChildren*)category_sp->GetSyntheticForType(type_sp).get()); 437 if (synth_current_sp && (synth_chosen_sp.get() == NULL || (prio_category > category_sp->GetEnabledPosition()))) 438 { 439 prio_category = category_sp->GetEnabledPosition(); 440 synth_chosen_sp = synth_current_sp; 441 } 442 } 443 return synth_chosen_sp; 444 } 445 #endif 446 447 #ifndef LLDB_DISABLE_PYTHON 448 lldb::SyntheticChildrenSP 449 FormatManager::GetSyntheticChildrenForType (lldb::TypeNameSpecifierImplSP type_sp) 450 { 451 if (!type_sp) 452 return lldb::SyntheticChildrenSP(); 453 lldb::TypeFilterImplSP filter_sp = GetFilterForType(type_sp); 454 lldb::ScriptedSyntheticChildrenSP synth_sp = GetSyntheticForType(type_sp); 455 if (filter_sp->GetRevision() > synth_sp->GetRevision()) 456 return lldb::SyntheticChildrenSP(filter_sp.get()); 457 else 458 return lldb::SyntheticChildrenSP(synth_sp.get()); 459 } 460 #endif 461 462 lldb::TypeValidatorImplSP 463 FormatManager::GetValidatorForType (lldb::TypeNameSpecifierImplSP type_sp) 464 { 465 if (!type_sp) 466 return lldb::TypeValidatorImplSP(); 467 lldb::TypeValidatorImplSP validator_chosen_sp; 468 uint32_t num_categories = m_categories_map.GetCount(); 469 lldb::TypeCategoryImplSP category_sp; 470 uint32_t prio_category = UINT32_MAX; 471 for (uint32_t category_id = 0; 472 category_id < num_categories; 473 category_id++) 474 { 475 category_sp = GetCategoryAtIndex(category_id); 476 if (category_sp->IsEnabled() == false) 477 continue; 478 lldb::TypeValidatorImplSP validator_current_sp(category_sp->GetValidatorForType(type_sp).get()); 479 if (validator_current_sp && (validator_chosen_sp.get() == NULL || (prio_category > category_sp->GetEnabledPosition()))) 480 { 481 prio_category = category_sp->GetEnabledPosition(); 482 validator_chosen_sp = validator_current_sp; 483 } 484 } 485 return validator_chosen_sp; 486 } 487 488 void 489 FormatManager::ForEachCategory(TypeCategoryMap::ForEachCallback callback) 490 { 491 m_categories_map.ForEach(callback); 492 Mutex::Locker locker(m_language_categories_mutex); 493 for (const auto& entry : m_language_categories_map) 494 { 495 if (auto category_sp = entry.second->GetCategory()) 496 { 497 if (!callback(category_sp)) 498 break; 499 } 500 } 501 } 502 503 lldb::TypeCategoryImplSP 504 FormatManager::GetCategory (const ConstString& category_name, 505 bool can_create) 506 { 507 if (!category_name) 508 return GetCategory(m_default_category_name); 509 lldb::TypeCategoryImplSP category; 510 if (m_categories_map.Get(category_name, category)) 511 return category; 512 513 if (!can_create) 514 return lldb::TypeCategoryImplSP(); 515 516 m_categories_map.Add(category_name,lldb::TypeCategoryImplSP(new TypeCategoryImpl(this, category_name))); 517 return GetCategory(category_name); 518 } 519 520 lldb::Format 521 FormatManager::GetSingleItemFormat(lldb::Format vector_format) 522 { 523 switch(vector_format) 524 { 525 case eFormatVectorOfChar: 526 return eFormatCharArray; 527 528 case eFormatVectorOfSInt8: 529 case eFormatVectorOfSInt16: 530 case eFormatVectorOfSInt32: 531 case eFormatVectorOfSInt64: 532 return eFormatDecimal; 533 534 case eFormatVectorOfUInt8: 535 case eFormatVectorOfUInt16: 536 case eFormatVectorOfUInt32: 537 case eFormatVectorOfUInt64: 538 case eFormatVectorOfUInt128: 539 return eFormatHex; 540 541 case eFormatVectorOfFloat16: 542 case eFormatVectorOfFloat32: 543 case eFormatVectorOfFloat64: 544 return eFormatFloat; 545 546 default: 547 return lldb::eFormatInvalid; 548 } 549 } 550 551 bool 552 FormatManager::ShouldPrintAsOneLiner (ValueObject& valobj) 553 { 554 // if settings say no oneline whatsoever 555 if (valobj.GetTargetSP().get() && valobj.GetTargetSP()->GetDebugger().GetAutoOneLineSummaries() == false) 556 return false; // then don't oneline 557 558 // if this object has a summary, then ask the summary 559 if (valobj.GetSummaryFormat().get() != nullptr) 560 return valobj.GetSummaryFormat()->IsOneLiner(); 561 562 // no children, no party 563 if (valobj.GetNumChildren() == 0) 564 return false; 565 566 // ask the type if it has any opinion about this 567 // eLazyBoolCalculate == no opinion; other values should be self explanatory 568 CompilerType compiler_type(valobj.GetCompilerType()); 569 if (compiler_type.IsValid()) 570 { 571 switch (compiler_type.ShouldPrintAsOneLiner(&valobj)) 572 { 573 case eLazyBoolNo: 574 return false; 575 case eLazyBoolYes: 576 return true; 577 case eLazyBoolCalculate: 578 break; 579 } 580 } 581 582 size_t total_children_name_len = 0; 583 584 for (size_t idx = 0; 585 idx < valobj.GetNumChildren(); 586 idx++) 587 { 588 bool is_synth_val = false; 589 ValueObjectSP child_sp(valobj.GetChildAtIndex(idx, true)); 590 // something is wrong here - bail out 591 if (!child_sp) 592 return false; 593 594 // also ask the child's type if it has any opinion 595 CompilerType child_compiler_type(child_sp->GetCompilerType()); 596 if (child_compiler_type.IsValid()) 597 { 598 switch (child_compiler_type.ShouldPrintAsOneLiner(child_sp.get())) 599 { 600 case eLazyBoolYes: 601 // an opinion of yes is only binding for the child, so keep going 602 case eLazyBoolCalculate: 603 break; 604 case eLazyBoolNo: 605 // but if the child says no, then it's a veto on the whole thing 606 return false; 607 } 608 } 609 610 // if we decided to define synthetic children for a type, we probably care enough 611 // to show them, but avoid nesting children in children 612 if (child_sp->GetSyntheticChildren().get() != nullptr) 613 { 614 ValueObjectSP synth_sp(child_sp->GetSyntheticValue()); 615 // wait.. wat? just get out of here.. 616 if (!synth_sp) 617 return false; 618 // but if we only have them to provide a value, keep going 619 if (synth_sp->MightHaveChildren() == false && synth_sp->DoesProvideSyntheticValue()) 620 is_synth_val = true; 621 else 622 return false; 623 } 624 625 total_children_name_len += child_sp->GetName().GetLength(); 626 627 // 50 itself is a "randomly" chosen number - the idea is that 628 // overly long structs should not get this treatment 629 // FIXME: maybe make this a user-tweakable setting? 630 if (total_children_name_len > 50) 631 return false; 632 633 // if a summary is there.. 634 if (child_sp->GetSummaryFormat()) 635 { 636 // and it wants children, then bail out 637 if (child_sp->GetSummaryFormat()->DoesPrintChildren(child_sp.get())) 638 return false; 639 } 640 641 // if this child has children.. 642 if (child_sp->GetNumChildren()) 643 { 644 // ...and no summary... 645 // (if it had a summary and the summary wanted children, we would have bailed out anyway 646 // so this only makes us bail out if this has no summary and we would then print children) 647 if (!child_sp->GetSummaryFormat() && !is_synth_val) // but again only do that if not a synthetic valued child 648 return false; // then bail out 649 } 650 } 651 return true; 652 } 653 654 ConstString 655 FormatManager::GetValidTypeName (const ConstString& type) 656 { 657 return ::GetValidTypeName_Impl(type); 658 } 659 660 ConstString 661 FormatManager::GetTypeForCache (ValueObject& valobj, 662 lldb::DynamicValueType use_dynamic) 663 { 664 ValueObjectSP valobj_sp = valobj.GetQualifiedRepresentationIfAvailable(use_dynamic, valobj.IsSynthetic()); 665 if (valobj_sp && valobj_sp->GetCompilerType().IsValid()) 666 { 667 if (!valobj_sp->GetCompilerType().IsMeaninglessWithoutDynamicResolution()) 668 return valobj_sp->GetQualifiedTypeName(); 669 } 670 return ConstString(); 671 } 672 673 std::vector<lldb::LanguageType> 674 FormatManager::GetCandidateLanguages (ValueObject& valobj) 675 { 676 lldb::LanguageType lang_type = valobj.GetObjectRuntimeLanguage(); 677 return GetCandidateLanguages(lang_type); 678 } 679 680 std::vector<lldb::LanguageType> 681 FormatManager::GetCandidateLanguages (lldb::LanguageType lang_type) 682 { 683 switch (lang_type) 684 { 685 case lldb::eLanguageTypeC: 686 case lldb::eLanguageTypeC89: 687 case lldb::eLanguageTypeC99: 688 case lldb::eLanguageTypeC11: 689 case lldb::eLanguageTypeC_plus_plus: 690 case lldb::eLanguageTypeC_plus_plus_03: 691 case lldb::eLanguageTypeC_plus_plus_11: 692 case lldb::eLanguageTypeC_plus_plus_14: 693 return {lldb::eLanguageTypeC_plus_plus, lldb::eLanguageTypeObjC}; 694 default: 695 return {lang_type}; 696 } 697 } 698 699 LanguageCategory* 700 FormatManager::GetCategoryForLanguage (lldb::LanguageType lang_type) 701 { 702 Mutex::Locker locker(m_language_categories_mutex); 703 auto iter = m_language_categories_map.find(lang_type), end = m_language_categories_map.end(); 704 if (iter != end) 705 return iter->second.get(); 706 LanguageCategory* lang_category = new LanguageCategory(lang_type); 707 m_language_categories_map[lang_type] = LanguageCategory::UniquePointer(lang_category); 708 return lang_category; 709 } 710 711 lldb::TypeFormatImplSP 712 FormatManager::GetHardcodedFormat (FormattersMatchData& match_data) 713 { 714 TypeFormatImplSP retval_sp; 715 716 for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages()) 717 { 718 if (LanguageCategory* lang_category = GetCategoryForLanguage(lang_type)) 719 { 720 if (lang_category->GetHardcoded(*this, match_data, retval_sp)) 721 break; 722 } 723 } 724 725 return retval_sp; 726 } 727 728 lldb::TypeFormatImplSP 729 FormatManager::GetFormat (ValueObject& valobj, 730 lldb::DynamicValueType use_dynamic) 731 { 732 FormattersMatchData match_data(valobj, use_dynamic); 733 734 TypeFormatImplSP retval; 735 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_DATAFORMATTERS)); 736 if (match_data.GetTypeForCache()) 737 { 738 if (log) 739 log->Printf("\n\n[FormatManager::GetFormat] Looking into cache for type %s", match_data.GetTypeForCache().AsCString("<invalid>")); 740 if (m_format_cache.GetFormat(match_data.GetTypeForCache(),retval)) 741 { 742 if (log) 743 { 744 log->Printf("[FormatManager::GetFormat] Cache search success. Returning."); 745 if (log->GetDebug()) 746 log->Printf("[FormatManager::GetFormat] Cache hits: %" PRIu64 " - Cache Misses: %" PRIu64, m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses()); 747 } 748 return retval; 749 } 750 if (log) 751 log->Printf("[FormatManager::GetFormat] Cache search failed. Going normal route"); 752 } 753 754 retval = m_categories_map.GetFormat(match_data); 755 if (!retval) 756 { 757 if (log) 758 log->Printf("[FormatManager::GetFormat] Search failed. Giving language a chance."); 759 for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages()) 760 { 761 if (LanguageCategory* lang_category = GetCategoryForLanguage(lang_type)) 762 { 763 if (lang_category->Get(match_data, retval)) 764 break; 765 } 766 } 767 if (retval) 768 { 769 if (log) 770 log->Printf("[FormatManager::GetFormat] Language search success. Returning."); 771 return retval; 772 } 773 } 774 if (!retval) 775 { 776 if (log) 777 log->Printf("[FormatManager::GetFormat] Search failed. Giving hardcoded a chance."); 778 retval = GetHardcodedFormat(match_data); 779 } 780 781 if (match_data.GetTypeForCache() && (!retval || !retval->NonCacheable())) 782 { 783 if (log) 784 log->Printf("[FormatManager::GetFormat] Caching %p for type %s", 785 static_cast<void*>(retval.get()), 786 match_data.GetTypeForCache().AsCString("<invalid>")); 787 m_format_cache.SetFormat(match_data.GetTypeForCache(),retval); 788 } 789 if (log && log->GetDebug()) 790 log->Printf("[FormatManager::GetFormat] Cache hits: %" PRIu64 " - Cache Misses: %" PRIu64, m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses()); 791 return retval; 792 } 793 794 lldb::TypeSummaryImplSP 795 FormatManager::GetHardcodedSummaryFormat (FormattersMatchData& match_data) 796 { 797 TypeSummaryImplSP retval_sp; 798 799 for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages()) 800 { 801 if (LanguageCategory* lang_category = GetCategoryForLanguage(lang_type)) 802 { 803 if (lang_category->GetHardcoded(*this, match_data, retval_sp)) 804 break; 805 } 806 } 807 808 return retval_sp; 809 } 810 811 lldb::TypeSummaryImplSP 812 FormatManager::GetSummaryFormat (ValueObject& valobj, 813 lldb::DynamicValueType use_dynamic) 814 { 815 FormattersMatchData match_data(valobj, use_dynamic); 816 817 TypeSummaryImplSP retval; 818 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_DATAFORMATTERS)); 819 if (match_data.GetTypeForCache()) 820 { 821 if (log) 822 log->Printf("\n\n[FormatManager::GetSummaryFormat] Looking into cache for type %s", match_data.GetTypeForCache().AsCString("<invalid>")); 823 if (m_format_cache.GetSummary(match_data.GetTypeForCache(),retval)) 824 { 825 if (log) 826 { 827 log->Printf("[FormatManager::GetSummaryFormat] Cache search success. Returning."); 828 if (log->GetDebug()) 829 log->Printf("[FormatManager::GetSummaryFormat] Cache hits: %" PRIu64 " - Cache Misses: %" PRIu64, m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses()); 830 } 831 return retval; 832 } 833 if (log) 834 log->Printf("[FormatManager::GetSummaryFormat] Cache search failed. Going normal route"); 835 } 836 837 retval = m_categories_map.GetSummaryFormat(match_data); 838 if (!retval) 839 { 840 if (log) 841 log->Printf("[FormatManager::GetSummaryFormat] Search failed. Giving language a chance."); 842 for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages()) 843 { 844 if (LanguageCategory* lang_category = GetCategoryForLanguage(lang_type)) 845 { 846 if (lang_category->Get(match_data, retval)) 847 break; 848 } 849 } 850 if (retval) 851 { 852 if (log) 853 log->Printf("[FormatManager::GetSummaryFormat] Language search success. Returning."); 854 return retval; 855 } 856 } 857 if (!retval) 858 { 859 if (log) 860 log->Printf("[FormatManager::GetSummaryFormat] Search failed. Giving hardcoded a chance."); 861 retval = GetHardcodedSummaryFormat(match_data); 862 } 863 864 if (match_data.GetTypeForCache() && (!retval || !retval->NonCacheable())) 865 { 866 if (log) 867 log->Printf("[FormatManager::GetSummaryFormat] Caching %p for type %s", 868 static_cast<void*>(retval.get()), 869 match_data.GetTypeForCache().AsCString("<invalid>")); 870 m_format_cache.SetSummary(match_data.GetTypeForCache(),retval); 871 } 872 if (log && log->GetDebug()) 873 log->Printf("[FormatManager::GetSummaryFormat] Cache hits: %" PRIu64 " - Cache Misses: %" PRIu64, m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses()); 874 return retval; 875 } 876 877 #ifndef LLDB_DISABLE_PYTHON 878 lldb::SyntheticChildrenSP 879 FormatManager::GetHardcodedSyntheticChildren (FormattersMatchData& match_data) 880 { 881 SyntheticChildrenSP retval_sp; 882 883 for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages()) 884 { 885 if (LanguageCategory* lang_category = GetCategoryForLanguage(lang_type)) 886 { 887 if (lang_category->GetHardcoded(*this, match_data, retval_sp)) 888 break; 889 } 890 } 891 892 return retval_sp; 893 } 894 895 lldb::SyntheticChildrenSP 896 FormatManager::GetSyntheticChildren (ValueObject& valobj, 897 lldb::DynamicValueType use_dynamic) 898 { 899 FormattersMatchData match_data(valobj, use_dynamic); 900 901 SyntheticChildrenSP retval; 902 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_DATAFORMATTERS)); 903 if (match_data.GetTypeForCache()) 904 { 905 if (log) 906 log->Printf("\n\n[FormatManager::GetSyntheticChildren] Looking into cache for type %s", match_data.GetTypeForCache().AsCString("<invalid>")); 907 if (m_format_cache.GetSynthetic(match_data.GetTypeForCache(),retval)) 908 { 909 if (log) 910 { 911 log->Printf("[FormatManager::GetSyntheticChildren] Cache search success. Returning."); 912 if (log->GetDebug()) 913 log->Printf("[FormatManager::GetSyntheticChildren] Cache hits: %" PRIu64 " - Cache Misses: %" PRIu64, m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses()); 914 } 915 return retval; 916 } 917 if (log) 918 log->Printf("[FormatManager::GetSyntheticChildren] Cache search failed. Going normal route"); 919 } 920 921 retval = m_categories_map.GetSyntheticChildren(match_data); 922 if (!retval) 923 { 924 if (log) 925 log->Printf("[FormatManager::GetSyntheticChildren] Search failed. Giving language a chance."); 926 for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages()) 927 { 928 if (LanguageCategory* lang_category = GetCategoryForLanguage(lang_type)) 929 { 930 if (lang_category->Get(match_data, retval)) 931 break; 932 } 933 } 934 if (retval) 935 { 936 if (log) 937 log->Printf("[FormatManager::GetSyntheticChildren] Language search success. Returning."); 938 return retval; 939 } 940 } 941 if (!retval) 942 { 943 if (log) 944 log->Printf("[FormatManager::GetSyntheticChildren] Search failed. Giving hardcoded a chance."); 945 retval = GetHardcodedSyntheticChildren(match_data); 946 } 947 948 if (match_data.GetTypeForCache() && (!retval || !retval->NonCacheable())) 949 { 950 if (log) 951 log->Printf("[FormatManager::GetSyntheticChildren] Caching %p for type %s", 952 static_cast<void*>(retval.get()), 953 match_data.GetTypeForCache().AsCString("<invalid>")); 954 m_format_cache.SetSynthetic(match_data.GetTypeForCache(),retval); 955 } 956 if (log && log->GetDebug()) 957 log->Printf("[FormatManager::GetSyntheticChildren] Cache hits: %" PRIu64 " - Cache Misses: %" PRIu64, m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses()); 958 return retval; 959 } 960 #endif 961 962 lldb::TypeValidatorImplSP 963 FormatManager::GetValidator (ValueObject& valobj, 964 lldb::DynamicValueType use_dynamic) 965 { 966 FormattersMatchData match_data(valobj, use_dynamic); 967 968 TypeValidatorImplSP retval; 969 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_DATAFORMATTERS)); 970 if (match_data.GetTypeForCache()) 971 { 972 if (log) 973 log->Printf("\n\n[FormatManager::GetValidator] Looking into cache for type %s", match_data.GetTypeForCache().AsCString("<invalid>")); 974 if (m_format_cache.GetValidator(match_data.GetTypeForCache(),retval)) 975 { 976 if (log) 977 { 978 log->Printf("[FormatManager::GetValidator] Cache search success. Returning."); 979 if (log->GetDebug()) 980 log->Printf("[FormatManager::GetValidator] Cache hits: %" PRIu64 " - Cache Misses: %" PRIu64, m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses()); 981 } 982 return retval; 983 } 984 if (log) 985 log->Printf("[FormatManager::GetValidator] Cache search failed. Going normal route"); 986 } 987 988 retval = m_categories_map.GetValidator(match_data); 989 if (!retval) 990 { 991 if (log) 992 log->Printf("[FormatManager::GetValidator] Search failed. Giving language a chance."); 993 for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages()) 994 { 995 if (LanguageCategory* lang_category = GetCategoryForLanguage(lang_type)) 996 { 997 if (lang_category->Get(match_data, retval)) 998 break; 999 } 1000 } 1001 if (retval) 1002 { 1003 if (log) 1004 log->Printf("[FormatManager::GetValidator] Language search success. Returning."); 1005 return retval; 1006 } 1007 } 1008 if (!retval) 1009 { 1010 if (log) 1011 log->Printf("[FormatManager::GetValidator] Search failed. Giving hardcoded a chance."); 1012 retval = GetHardcodedValidator(match_data); 1013 } 1014 1015 if (match_data.GetTypeForCache() && (!retval || !retval->NonCacheable())) 1016 { 1017 if (log) 1018 log->Printf("[FormatManager::GetValidator] Caching %p for type %s", 1019 static_cast<void*>(retval.get()), 1020 match_data.GetTypeForCache().AsCString("<invalid>")); 1021 m_format_cache.SetValidator(match_data.GetTypeForCache(),retval); 1022 } 1023 if (log && log->GetDebug()) 1024 log->Printf("[FormatManager::GetValidator] Cache hits: %" PRIu64 " - Cache Misses: %" PRIu64, m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses()); 1025 return retval; 1026 } 1027 1028 lldb::TypeValidatorImplSP 1029 FormatManager::GetHardcodedValidator (FormattersMatchData& match_data) 1030 { 1031 TypeValidatorImplSP retval_sp; 1032 1033 for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages()) 1034 { 1035 if (LanguageCategory* lang_category = GetCategoryForLanguage(lang_type)) 1036 { 1037 if (lang_category->GetHardcoded(*this, match_data, retval_sp)) 1038 break; 1039 } 1040 } 1041 1042 return retval_sp; 1043 } 1044 1045 FormatManager::FormatManager() : 1046 m_format_cache(), 1047 m_named_summaries_map(this), 1048 m_last_revision(0), 1049 m_categories_map(this), 1050 m_language_categories_map(), 1051 m_language_categories_mutex(Mutex::eMutexTypeRecursive), 1052 m_default_category_name(ConstString("default")), 1053 m_system_category_name(ConstString("system")), 1054 m_vectortypes_category_name(ConstString("VectorTypes")) 1055 { 1056 LoadSystemFormatters(); 1057 LoadVectorFormatters(); 1058 1059 EnableCategory(m_vectortypes_category_name,TypeCategoryMap::Last, lldb::eLanguageTypeObjC_plus_plus); 1060 EnableCategory(m_system_category_name,TypeCategoryMap::Last, lldb::eLanguageTypeObjC_plus_plus); 1061 } 1062 1063 void 1064 FormatManager::LoadSystemFormatters() 1065 { 1066 1067 TypeSummaryImpl::Flags string_flags; 1068 string_flags.SetCascades(true) 1069 .SetSkipPointers(true) 1070 .SetSkipReferences(false) 1071 .SetDontShowChildren(true) 1072 .SetDontShowValue(false) 1073 .SetShowMembersOneLiner(false) 1074 .SetHideItemNames(false); 1075 1076 TypeSummaryImpl::Flags string_array_flags; 1077 string_array_flags.SetCascades(true) 1078 .SetSkipPointers(true) 1079 .SetSkipReferences(false) 1080 .SetDontShowChildren(true) 1081 .SetDontShowValue(true) 1082 .SetShowMembersOneLiner(false) 1083 .SetHideItemNames(false); 1084 1085 lldb::TypeSummaryImplSP string_format(new StringSummaryFormat(string_flags, "${var%s}")); 1086 1087 1088 lldb::TypeSummaryImplSP string_array_format(new StringSummaryFormat(string_array_flags, 1089 "${var%s}")); 1090 1091 lldb::RegularExpressionSP any_size_char_arr(new RegularExpression("char \\[[0-9]+\\]")); 1092 lldb::RegularExpressionSP any_size_wchar_arr(new RegularExpression("wchar_t \\[[0-9]+\\]")); 1093 1094 TypeCategoryImpl::SharedPointer sys_category_sp = GetCategory(m_system_category_name); 1095 1096 sys_category_sp->GetTypeSummariesContainer()->Add(ConstString("char *"), string_format); 1097 sys_category_sp->GetTypeSummariesContainer()->Add(ConstString("unsigned char *"), string_format); 1098 sys_category_sp->GetRegexTypeSummariesContainer()->Add(any_size_char_arr, string_array_format); 1099 1100 lldb::TypeSummaryImplSP ostype_summary(new StringSummaryFormat(TypeSummaryImpl::Flags().SetCascades(false) 1101 .SetSkipPointers(true) 1102 .SetSkipReferences(true) 1103 .SetDontShowChildren(true) 1104 .SetDontShowValue(false) 1105 .SetShowMembersOneLiner(false) 1106 .SetHideItemNames(false), 1107 "${var%O}")); 1108 1109 sys_category_sp->GetTypeSummariesContainer()->Add(ConstString("OSType"), ostype_summary); 1110 1111 #ifndef LLDB_DISABLE_PYTHON 1112 TypeFormatImpl::Flags fourchar_flags; 1113 fourchar_flags.SetCascades(true).SetSkipPointers(true).SetSkipReferences(true); 1114 1115 AddFormat(sys_category_sp, lldb::eFormatOSType, ConstString("FourCharCode"), fourchar_flags); 1116 #endif 1117 } 1118 1119 void 1120 FormatManager::LoadVectorFormatters() 1121 { 1122 TypeCategoryImpl::SharedPointer vectors_category_sp = GetCategory(m_vectortypes_category_name); 1123 1124 TypeSummaryImpl::Flags vector_flags; 1125 vector_flags.SetCascades(true) 1126 .SetSkipPointers(true) 1127 .SetSkipReferences(false) 1128 .SetDontShowChildren(true) 1129 .SetDontShowValue(false) 1130 .SetShowMembersOneLiner(true) 1131 .SetHideItemNames(true); 1132 1133 AddStringSummary(vectors_category_sp, 1134 "${var.uint128}", 1135 ConstString("builtin_type_vec128"), 1136 vector_flags); 1137 1138 AddStringSummary(vectors_category_sp, 1139 "", 1140 ConstString("float [4]"), 1141 vector_flags); 1142 AddStringSummary(vectors_category_sp, 1143 "", 1144 ConstString("int32_t [4]"), 1145 vector_flags); 1146 AddStringSummary(vectors_category_sp, 1147 "", 1148 ConstString("int16_t [8]"), 1149 vector_flags); 1150 AddStringSummary(vectors_category_sp, 1151 "", 1152 ConstString("vDouble"), 1153 vector_flags); 1154 AddStringSummary(vectors_category_sp, 1155 "", 1156 ConstString("vFloat"), 1157 vector_flags); 1158 AddStringSummary(vectors_category_sp, 1159 "", 1160 ConstString("vSInt8"), 1161 vector_flags); 1162 AddStringSummary(vectors_category_sp, 1163 "", 1164 ConstString("vSInt16"), 1165 vector_flags); 1166 AddStringSummary(vectors_category_sp, 1167 "", 1168 ConstString("vSInt32"), 1169 vector_flags); 1170 AddStringSummary(vectors_category_sp, 1171 "", 1172 ConstString("vUInt16"), 1173 vector_flags); 1174 AddStringSummary(vectors_category_sp, 1175 "", 1176 ConstString("vUInt8"), 1177 vector_flags); 1178 AddStringSummary(vectors_category_sp, 1179 "", 1180 ConstString("vUInt16"), 1181 vector_flags); 1182 AddStringSummary(vectors_category_sp, 1183 "", 1184 ConstString("vUInt32"), 1185 vector_flags); 1186 AddStringSummary(vectors_category_sp, 1187 "", 1188 ConstString("vBool32"), 1189 vector_flags); 1190 } 1191