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