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