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