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