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