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