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::LoopThroughCategories (CategoryCallback callback, void* param) 490 { 491 m_categories_map.LoopThrough(callback, param); 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(param, 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()) 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 // if we decided to define synthetic children for a type, we probably care enough 594 // to show them, but avoid nesting children in children 595 if (child_sp->GetSyntheticChildren().get() != nullptr) 596 { 597 ValueObjectSP synth_sp(child_sp->GetSyntheticValue()); 598 // wait.. wat? just get out of here.. 599 if (!synth_sp) 600 return false; 601 // but if we only have them to provide a value, keep going 602 if (synth_sp->MightHaveChildren() == false && synth_sp->DoesProvideSyntheticValue()) 603 is_synth_val = true; 604 else 605 return false; 606 } 607 608 total_children_name_len += child_sp->GetName().GetLength(); 609 610 // 50 itself is a "randomly" chosen number - the idea is that 611 // overly long structs should not get this treatment 612 // FIXME: maybe make this a user-tweakable setting? 613 if (total_children_name_len > 50) 614 return false; 615 616 // if a summary is there.. 617 if (child_sp->GetSummaryFormat()) 618 { 619 // and it wants children, then bail out 620 if (child_sp->GetSummaryFormat()->DoesPrintChildren(child_sp.get())) 621 return false; 622 } 623 624 // if this child has children.. 625 if (child_sp->GetNumChildren()) 626 { 627 // ...and no summary... 628 // (if it had a summary and the summary wanted children, we would have bailed out anyway 629 // so this only makes us bail out if this has no summary and we would then print children) 630 if (!child_sp->GetSummaryFormat() && !is_synth_val) // but again only do that if not a synthetic valued child 631 return false; // then bail out 632 } 633 } 634 return true; 635 } 636 637 ConstString 638 FormatManager::GetValidTypeName (const ConstString& type) 639 { 640 return ::GetValidTypeName_Impl(type); 641 } 642 643 ConstString 644 FormatManager::GetTypeForCache (ValueObject& valobj, 645 lldb::DynamicValueType use_dynamic) 646 { 647 ValueObjectSP valobj_sp = valobj.GetQualifiedRepresentationIfAvailable(use_dynamic, valobj.IsSynthetic()); 648 if (valobj_sp && valobj_sp->GetCompilerType().IsValid()) 649 { 650 if (!valobj_sp->GetCompilerType().IsMeaninglessWithoutDynamicResolution()) 651 return valobj_sp->GetQualifiedTypeName(); 652 } 653 return ConstString(); 654 } 655 656 std::vector<lldb::LanguageType> 657 FormatManager::GetCandidateLanguages (ValueObject& valobj) 658 { 659 lldb::LanguageType lang_type = valobj.GetObjectRuntimeLanguage(); 660 return GetCandidateLanguages(lang_type); 661 } 662 663 std::vector<lldb::LanguageType> 664 FormatManager::GetCandidateLanguages (lldb::LanguageType lang_type) 665 { 666 switch (lang_type) 667 { 668 case lldb::eLanguageTypeC: 669 case lldb::eLanguageTypeC89: 670 case lldb::eLanguageTypeC99: 671 case lldb::eLanguageTypeC11: 672 case lldb::eLanguageTypeC_plus_plus: 673 case lldb::eLanguageTypeC_plus_plus_03: 674 case lldb::eLanguageTypeC_plus_plus_11: 675 case lldb::eLanguageTypeC_plus_plus_14: 676 return {lldb::eLanguageTypeC_plus_plus, lldb::eLanguageTypeObjC}; 677 default: 678 return {lang_type}; 679 } 680 } 681 682 LanguageCategory* 683 FormatManager::GetCategoryForLanguage (lldb::LanguageType lang_type) 684 { 685 Mutex::Locker locker(m_language_categories_mutex); 686 auto iter = m_language_categories_map.find(lang_type), end = m_language_categories_map.end(); 687 if (iter != end) 688 return iter->second.get(); 689 LanguageCategory* lang_category = new LanguageCategory(lang_type); 690 m_language_categories_map[lang_type] = LanguageCategory::UniquePointer(lang_category); 691 return lang_category; 692 } 693 694 lldb::TypeFormatImplSP 695 FormatManager::GetHardcodedFormat (FormattersMatchData& match_data) 696 { 697 TypeFormatImplSP retval_sp; 698 699 for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages()) 700 { 701 if (LanguageCategory* lang_category = GetCategoryForLanguage(lang_type)) 702 { 703 if (lang_category->GetHardcoded(*this, match_data, retval_sp)) 704 break; 705 } 706 } 707 708 return retval_sp; 709 } 710 711 lldb::TypeFormatImplSP 712 FormatManager::GetFormat (ValueObject& valobj, 713 lldb::DynamicValueType use_dynamic) 714 { 715 FormattersMatchData match_data(valobj, use_dynamic); 716 717 TypeFormatImplSP retval; 718 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_DATAFORMATTERS)); 719 if (match_data.GetTypeForCache()) 720 { 721 if (log) 722 log->Printf("\n\n[FormatManager::GetFormat] Looking into cache for type %s", match_data.GetTypeForCache().AsCString("<invalid>")); 723 if (m_format_cache.GetFormat(match_data.GetTypeForCache(),retval)) 724 { 725 if (log) 726 { 727 log->Printf("[FormatManager::GetFormat] Cache search success. Returning."); 728 if (log->GetDebug()) 729 log->Printf("[FormatManager::GetFormat] Cache hits: %" PRIu64 " - Cache Misses: %" PRIu64, m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses()); 730 } 731 return retval; 732 } 733 if (log) 734 log->Printf("[FormatManager::GetFormat] Cache search failed. Going normal route"); 735 } 736 737 retval = m_categories_map.GetFormat(match_data); 738 if (!retval) 739 { 740 if (log) 741 log->Printf("[FormatManager::GetFormat] Search failed. Giving language a chance."); 742 for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages()) 743 { 744 if (LanguageCategory* lang_category = GetCategoryForLanguage(lang_type)) 745 { 746 if (lang_category->Get(match_data, retval)) 747 break; 748 } 749 } 750 if (retval) 751 { 752 if (log) 753 log->Printf("[FormatManager::GetFormat] Language search success. Returning."); 754 return retval; 755 } 756 } 757 if (!retval) 758 { 759 if (log) 760 log->Printf("[FormatManager::GetFormat] Search failed. Giving hardcoded a chance."); 761 retval = GetHardcodedFormat(match_data); 762 } 763 764 if (match_data.GetTypeForCache() && (!retval || !retval->NonCacheable())) 765 { 766 if (log) 767 log->Printf("[FormatManager::GetFormat] Caching %p for type %s", 768 static_cast<void*>(retval.get()), 769 match_data.GetTypeForCache().AsCString("<invalid>")); 770 m_format_cache.SetFormat(match_data.GetTypeForCache(),retval); 771 } 772 if (log && log->GetDebug()) 773 log->Printf("[FormatManager::GetFormat] Cache hits: %" PRIu64 " - Cache Misses: %" PRIu64, m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses()); 774 return retval; 775 } 776 777 lldb::TypeSummaryImplSP 778 FormatManager::GetHardcodedSummaryFormat (FormattersMatchData& match_data) 779 { 780 TypeSummaryImplSP retval_sp; 781 782 for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages()) 783 { 784 if (LanguageCategory* lang_category = GetCategoryForLanguage(lang_type)) 785 { 786 if (lang_category->GetHardcoded(*this, match_data, retval_sp)) 787 break; 788 } 789 } 790 791 return retval_sp; 792 } 793 794 lldb::TypeSummaryImplSP 795 FormatManager::GetSummaryFormat (ValueObject& valobj, 796 lldb::DynamicValueType use_dynamic) 797 { 798 FormattersMatchData match_data(valobj, use_dynamic); 799 800 TypeSummaryImplSP retval; 801 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_DATAFORMATTERS)); 802 if (match_data.GetTypeForCache()) 803 { 804 if (log) 805 log->Printf("\n\n[FormatManager::GetSummaryFormat] Looking into cache for type %s", match_data.GetTypeForCache().AsCString("<invalid>")); 806 if (m_format_cache.GetSummary(match_data.GetTypeForCache(),retval)) 807 { 808 if (log) 809 { 810 log->Printf("[FormatManager::GetSummaryFormat] Cache search success. Returning."); 811 if (log->GetDebug()) 812 log->Printf("[FormatManager::GetSummaryFormat] Cache hits: %" PRIu64 " - Cache Misses: %" PRIu64, m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses()); 813 } 814 return retval; 815 } 816 if (log) 817 log->Printf("[FormatManager::GetSummaryFormat] Cache search failed. Going normal route"); 818 } 819 820 retval = m_categories_map.GetSummaryFormat(match_data); 821 if (!retval) 822 { 823 if (log) 824 log->Printf("[FormatManager::GetSummaryFormat] Search failed. Giving language a chance."); 825 for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages()) 826 { 827 if (LanguageCategory* lang_category = GetCategoryForLanguage(lang_type)) 828 { 829 if (lang_category->Get(match_data, retval)) 830 break; 831 } 832 } 833 if (retval) 834 { 835 if (log) 836 log->Printf("[FormatManager::GetSummaryFormat] Language search success. Returning."); 837 return retval; 838 } 839 } 840 if (!retval) 841 { 842 if (log) 843 log->Printf("[FormatManager::GetSummaryFormat] Search failed. Giving hardcoded a chance."); 844 retval = GetHardcodedSummaryFormat(match_data); 845 } 846 847 if (match_data.GetTypeForCache() && (!retval || !retval->NonCacheable())) 848 { 849 if (log) 850 log->Printf("[FormatManager::GetSummaryFormat] Caching %p for type %s", 851 static_cast<void*>(retval.get()), 852 match_data.GetTypeForCache().AsCString("<invalid>")); 853 m_format_cache.SetSummary(match_data.GetTypeForCache(),retval); 854 } 855 if (log && log->GetDebug()) 856 log->Printf("[FormatManager::GetSummaryFormat] Cache hits: %" PRIu64 " - Cache Misses: %" PRIu64, m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses()); 857 return retval; 858 } 859 860 #ifndef LLDB_DISABLE_PYTHON 861 lldb::SyntheticChildrenSP 862 FormatManager::GetHardcodedSyntheticChildren (FormattersMatchData& match_data) 863 { 864 SyntheticChildrenSP retval_sp; 865 866 for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages()) 867 { 868 if (LanguageCategory* lang_category = GetCategoryForLanguage(lang_type)) 869 { 870 if (lang_category->GetHardcoded(*this, match_data, retval_sp)) 871 break; 872 } 873 } 874 875 return retval_sp; 876 } 877 878 lldb::SyntheticChildrenSP 879 FormatManager::GetSyntheticChildren (ValueObject& valobj, 880 lldb::DynamicValueType use_dynamic) 881 { 882 FormattersMatchData match_data(valobj, use_dynamic); 883 884 SyntheticChildrenSP retval; 885 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_DATAFORMATTERS)); 886 if (match_data.GetTypeForCache()) 887 { 888 if (log) 889 log->Printf("\n\n[FormatManager::GetSyntheticChildren] Looking into cache for type %s", match_data.GetTypeForCache().AsCString("<invalid>")); 890 if (m_format_cache.GetSynthetic(match_data.GetTypeForCache(),retval)) 891 { 892 if (log) 893 { 894 log->Printf("[FormatManager::GetSyntheticChildren] Cache search success. Returning."); 895 if (log->GetDebug()) 896 log->Printf("[FormatManager::GetSyntheticChildren] Cache hits: %" PRIu64 " - Cache Misses: %" PRIu64, m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses()); 897 } 898 return retval; 899 } 900 if (log) 901 log->Printf("[FormatManager::GetSyntheticChildren] Cache search failed. Going normal route"); 902 } 903 904 retval = m_categories_map.GetSyntheticChildren(match_data); 905 if (!retval) 906 { 907 if (log) 908 log->Printf("[FormatManager::GetSyntheticChildren] Search failed. Giving language a chance."); 909 for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages()) 910 { 911 if (LanguageCategory* lang_category = GetCategoryForLanguage(lang_type)) 912 { 913 if (lang_category->Get(match_data, retval)) 914 break; 915 } 916 } 917 if (retval) 918 { 919 if (log) 920 log->Printf("[FormatManager::GetSyntheticChildren] Language search success. Returning."); 921 return retval; 922 } 923 } 924 if (!retval) 925 { 926 if (log) 927 log->Printf("[FormatManager::GetSyntheticChildren] Search failed. Giving hardcoded a chance."); 928 retval = GetHardcodedSyntheticChildren(match_data); 929 } 930 931 if (match_data.GetTypeForCache() && (!retval || !retval->NonCacheable())) 932 { 933 if (log) 934 log->Printf("[FormatManager::GetSyntheticChildren] Caching %p for type %s", 935 static_cast<void*>(retval.get()), 936 match_data.GetTypeForCache().AsCString("<invalid>")); 937 m_format_cache.SetSynthetic(match_data.GetTypeForCache(),retval); 938 } 939 if (log && log->GetDebug()) 940 log->Printf("[FormatManager::GetSyntheticChildren] Cache hits: %" PRIu64 " - Cache Misses: %" PRIu64, m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses()); 941 return retval; 942 } 943 #endif 944 945 lldb::TypeValidatorImplSP 946 FormatManager::GetValidator (ValueObject& valobj, 947 lldb::DynamicValueType use_dynamic) 948 { 949 FormattersMatchData match_data(valobj, use_dynamic); 950 951 TypeValidatorImplSP retval; 952 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_DATAFORMATTERS)); 953 if (match_data.GetTypeForCache()) 954 { 955 if (log) 956 log->Printf("\n\n[FormatManager::GetValidator] Looking into cache for type %s", match_data.GetTypeForCache().AsCString("<invalid>")); 957 if (m_format_cache.GetValidator(match_data.GetTypeForCache(),retval)) 958 { 959 if (log) 960 { 961 log->Printf("[FormatManager::GetValidator] Cache search success. Returning."); 962 if (log->GetDebug()) 963 log->Printf("[FormatManager::GetValidator] Cache hits: %" PRIu64 " - Cache Misses: %" PRIu64, m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses()); 964 } 965 return retval; 966 } 967 if (log) 968 log->Printf("[FormatManager::GetValidator] Cache search failed. Going normal route"); 969 } 970 971 retval = m_categories_map.GetValidator(match_data); 972 if (!retval) 973 { 974 if (log) 975 log->Printf("[FormatManager::GetValidator] Search failed. Giving language a chance."); 976 for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages()) 977 { 978 if (LanguageCategory* lang_category = GetCategoryForLanguage(lang_type)) 979 { 980 if (lang_category->Get(match_data, retval)) 981 break; 982 } 983 } 984 if (retval) 985 { 986 if (log) 987 log->Printf("[FormatManager::GetValidator] Language search success. Returning."); 988 return retval; 989 } 990 } 991 if (!retval) 992 { 993 if (log) 994 log->Printf("[FormatManager::GetValidator] Search failed. Giving hardcoded a chance."); 995 retval = GetHardcodedValidator(match_data); 996 } 997 998 if (match_data.GetTypeForCache() && (!retval || !retval->NonCacheable())) 999 { 1000 if (log) 1001 log->Printf("[FormatManager::GetValidator] Caching %p for type %s", 1002 static_cast<void*>(retval.get()), 1003 match_data.GetTypeForCache().AsCString("<invalid>")); 1004 m_format_cache.SetValidator(match_data.GetTypeForCache(),retval); 1005 } 1006 if (log && log->GetDebug()) 1007 log->Printf("[FormatManager::GetValidator] Cache hits: %" PRIu64 " - Cache Misses: %" PRIu64, m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses()); 1008 return retval; 1009 } 1010 1011 lldb::TypeValidatorImplSP 1012 FormatManager::GetHardcodedValidator (FormattersMatchData& match_data) 1013 { 1014 TypeValidatorImplSP retval_sp; 1015 1016 for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages()) 1017 { 1018 if (LanguageCategory* lang_category = GetCategoryForLanguage(lang_type)) 1019 { 1020 if (lang_category->GetHardcoded(*this, match_data, retval_sp)) 1021 break; 1022 } 1023 } 1024 1025 return retval_sp; 1026 } 1027 1028 FormatManager::FormatManager() : 1029 m_format_cache(), 1030 m_named_summaries_map(this), 1031 m_last_revision(0), 1032 m_categories_map(this), 1033 m_language_categories_map(), 1034 m_language_categories_mutex(Mutex::eMutexTypeRecursive), 1035 m_default_category_name(ConstString("default")), 1036 m_system_category_name(ConstString("system")), 1037 m_vectortypes_category_name(ConstString("VectorTypes")) 1038 { 1039 LoadSystemFormatters(); 1040 LoadVectorFormatters(); 1041 1042 EnableCategory(m_vectortypes_category_name,TypeCategoryMap::Last, lldb::eLanguageTypeObjC_plus_plus); 1043 EnableCategory(m_system_category_name,TypeCategoryMap::Last, lldb::eLanguageTypeObjC_plus_plus); 1044 } 1045 1046 void 1047 FormatManager::LoadSystemFormatters() 1048 { 1049 1050 TypeSummaryImpl::Flags string_flags; 1051 string_flags.SetCascades(true) 1052 .SetSkipPointers(true) 1053 .SetSkipReferences(false) 1054 .SetDontShowChildren(true) 1055 .SetDontShowValue(false) 1056 .SetShowMembersOneLiner(false) 1057 .SetHideItemNames(false); 1058 1059 TypeSummaryImpl::Flags string_array_flags; 1060 string_array_flags.SetCascades(true) 1061 .SetSkipPointers(true) 1062 .SetSkipReferences(false) 1063 .SetDontShowChildren(true) 1064 .SetDontShowValue(true) 1065 .SetShowMembersOneLiner(false) 1066 .SetHideItemNames(false); 1067 1068 lldb::TypeSummaryImplSP string_format(new StringSummaryFormat(string_flags, "${var%s}")); 1069 1070 1071 lldb::TypeSummaryImplSP string_array_format(new StringSummaryFormat(string_array_flags, 1072 "${var%s}")); 1073 1074 lldb::RegularExpressionSP any_size_char_arr(new RegularExpression("char \\[[0-9]+\\]")); 1075 lldb::RegularExpressionSP any_size_wchar_arr(new RegularExpression("wchar_t \\[[0-9]+\\]")); 1076 1077 TypeCategoryImpl::SharedPointer sys_category_sp = GetCategory(m_system_category_name); 1078 1079 sys_category_sp->GetTypeSummariesContainer()->Add(ConstString("char *"), string_format); 1080 sys_category_sp->GetTypeSummariesContainer()->Add(ConstString("unsigned char *"), string_format); 1081 sys_category_sp->GetRegexTypeSummariesContainer()->Add(any_size_char_arr, string_array_format); 1082 1083 lldb::TypeSummaryImplSP ostype_summary(new StringSummaryFormat(TypeSummaryImpl::Flags().SetCascades(false) 1084 .SetSkipPointers(true) 1085 .SetSkipReferences(true) 1086 .SetDontShowChildren(true) 1087 .SetDontShowValue(false) 1088 .SetShowMembersOneLiner(false) 1089 .SetHideItemNames(false), 1090 "${var%O}")); 1091 1092 sys_category_sp->GetTypeSummariesContainer()->Add(ConstString("OSType"), ostype_summary); 1093 1094 #ifndef LLDB_DISABLE_PYTHON 1095 TypeFormatImpl::Flags fourchar_flags; 1096 fourchar_flags.SetCascades(true).SetSkipPointers(true).SetSkipReferences(true); 1097 1098 AddFormat(sys_category_sp, lldb::eFormatOSType, ConstString("FourCharCode"), fourchar_flags); 1099 #endif 1100 } 1101 1102 void 1103 FormatManager::LoadVectorFormatters() 1104 { 1105 TypeCategoryImpl::SharedPointer vectors_category_sp = GetCategory(m_vectortypes_category_name); 1106 1107 TypeSummaryImpl::Flags vector_flags; 1108 vector_flags.SetCascades(true) 1109 .SetSkipPointers(true) 1110 .SetSkipReferences(false) 1111 .SetDontShowChildren(true) 1112 .SetDontShowValue(false) 1113 .SetShowMembersOneLiner(true) 1114 .SetHideItemNames(true); 1115 1116 AddStringSummary(vectors_category_sp, 1117 "${var.uint128}", 1118 ConstString("builtin_type_vec128"), 1119 vector_flags); 1120 1121 AddStringSummary(vectors_category_sp, 1122 "", 1123 ConstString("float [4]"), 1124 vector_flags); 1125 AddStringSummary(vectors_category_sp, 1126 "", 1127 ConstString("int32_t [4]"), 1128 vector_flags); 1129 AddStringSummary(vectors_category_sp, 1130 "", 1131 ConstString("int16_t [8]"), 1132 vector_flags); 1133 AddStringSummary(vectors_category_sp, 1134 "", 1135 ConstString("vDouble"), 1136 vector_flags); 1137 AddStringSummary(vectors_category_sp, 1138 "", 1139 ConstString("vFloat"), 1140 vector_flags); 1141 AddStringSummary(vectors_category_sp, 1142 "", 1143 ConstString("vSInt8"), 1144 vector_flags); 1145 AddStringSummary(vectors_category_sp, 1146 "", 1147 ConstString("vSInt16"), 1148 vector_flags); 1149 AddStringSummary(vectors_category_sp, 1150 "", 1151 ConstString("vSInt32"), 1152 vector_flags); 1153 AddStringSummary(vectors_category_sp, 1154 "", 1155 ConstString("vUInt16"), 1156 vector_flags); 1157 AddStringSummary(vectors_category_sp, 1158 "", 1159 ConstString("vUInt8"), 1160 vector_flags); 1161 AddStringSummary(vectors_category_sp, 1162 "", 1163 ConstString("vUInt16"), 1164 vector_flags); 1165 AddStringSummary(vectors_category_sp, 1166 "", 1167 ConstString("vUInt32"), 1168 vector_flags); 1169 AddStringSummary(vectors_category_sp, 1170 "", 1171 ConstString("vBool32"), 1172 vector_flags); 1173 } 1174