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