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