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/Core/Log.h" 21 #include "lldb/DataFormatters/FormattersHelpers.h" 22 #include "lldb/DataFormatters/LanguageCategory.h" 23 #include "lldb/Target/ExecutionContext.h" 24 #include "lldb/Target/Language.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 if (log->GetDebug()) 664 log->Printf("[FormatManager::GetFormat] Cache hits: %" PRIu64 665 " - Cache Misses: %" PRIu64, 666 m_format_cache.GetCacheHits(), 667 m_format_cache.GetCacheMisses()); 668 } 669 return retval; 670 } 671 if (log) 672 log->Printf( 673 "[FormatManager::GetFormat] Cache search failed. Going normal route"); 674 } 675 676 retval = m_categories_map.GetFormat(match_data); 677 if (!retval) { 678 if (log) 679 log->Printf("[FormatManager::GetFormat] Search failed. Giving language a " 680 "chance."); 681 for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages()) { 682 if (LanguageCategory *lang_category = GetCategoryForLanguage(lang_type)) { 683 if (lang_category->Get(match_data, retval)) 684 break; 685 } 686 } 687 if (retval) { 688 if (log) 689 log->Printf( 690 "[FormatManager::GetFormat] Language search success. Returning."); 691 return retval; 692 } 693 } 694 if (!retval) { 695 if (log) 696 log->Printf("[FormatManager::GetFormat] Search failed. Giving hardcoded " 697 "a chance."); 698 retval = GetHardcodedFormat(match_data); 699 } 700 701 if (match_data.GetTypeForCache() && (!retval || !retval->NonCacheable())) { 702 if (log) 703 log->Printf("[FormatManager::GetFormat] Caching %p for type %s", 704 static_cast<void *>(retval.get()), 705 match_data.GetTypeForCache().AsCString("<invalid>")); 706 m_format_cache.SetFormat(match_data.GetTypeForCache(), retval); 707 } 708 if (log && log->GetDebug()) 709 log->Printf("[FormatManager::GetFormat] Cache hits: %" PRIu64 710 " - Cache Misses: %" PRIu64, 711 m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses()); 712 return retval; 713 } 714 715 lldb::TypeSummaryImplSP 716 FormatManager::GetHardcodedSummaryFormat(FormattersMatchData &match_data) { 717 TypeSummaryImplSP retval_sp; 718 719 for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages()) { 720 if (LanguageCategory *lang_category = GetCategoryForLanguage(lang_type)) { 721 if (lang_category->GetHardcoded(*this, match_data, retval_sp)) 722 break; 723 } 724 } 725 726 return retval_sp; 727 } 728 729 lldb::TypeSummaryImplSP 730 FormatManager::GetSummaryFormat(ValueObject &valobj, 731 lldb::DynamicValueType use_dynamic) { 732 FormattersMatchData match_data(valobj, use_dynamic); 733 734 TypeSummaryImplSP retval; 735 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS)); 736 if (match_data.GetTypeForCache()) { 737 if (log) 738 log->Printf("\n\n[FormatManager::GetSummaryFormat] Looking into cache " 739 "for type %s", 740 match_data.GetTypeForCache().AsCString("<invalid>")); 741 if (m_format_cache.GetSummary(match_data.GetTypeForCache(), retval)) { 742 if (log) { 743 log->Printf("[FormatManager::GetSummaryFormat] Cache search success. " 744 "Returning."); 745 if (log->GetDebug()) 746 log->Printf("[FormatManager::GetSummaryFormat] Cache hits: %" PRIu64 747 " - Cache Misses: %" PRIu64, 748 m_format_cache.GetCacheHits(), 749 m_format_cache.GetCacheMisses()); 750 } 751 return retval; 752 } 753 if (log) 754 log->Printf("[FormatManager::GetSummaryFormat] Cache search failed. " 755 "Going normal route"); 756 } 757 758 retval = m_categories_map.GetSummaryFormat(match_data); 759 if (!retval) { 760 if (log) 761 log->Printf("[FormatManager::GetSummaryFormat] Search failed. Giving " 762 "language a chance."); 763 for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages()) { 764 if (LanguageCategory *lang_category = GetCategoryForLanguage(lang_type)) { 765 if (lang_category->Get(match_data, retval)) 766 break; 767 } 768 } 769 if (retval) { 770 if (log) 771 log->Printf("[FormatManager::GetSummaryFormat] Language search " 772 "success. Returning."); 773 return retval; 774 } 775 } 776 if (!retval) { 777 if (log) 778 log->Printf("[FormatManager::GetSummaryFormat] Search failed. Giving " 779 "hardcoded a chance."); 780 retval = GetHardcodedSummaryFormat(match_data); 781 } 782 783 if (match_data.GetTypeForCache() && (!retval || !retval->NonCacheable())) { 784 if (log) 785 log->Printf("[FormatManager::GetSummaryFormat] Caching %p for type %s", 786 static_cast<void *>(retval.get()), 787 match_data.GetTypeForCache().AsCString("<invalid>")); 788 m_format_cache.SetSummary(match_data.GetTypeForCache(), retval); 789 } 790 if (log && log->GetDebug()) 791 log->Printf("[FormatManager::GetSummaryFormat] Cache hits: %" PRIu64 792 " - Cache Misses: %" PRIu64, 793 m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses()); 794 return retval; 795 } 796 797 #ifndef LLDB_DISABLE_PYTHON 798 lldb::SyntheticChildrenSP 799 FormatManager::GetHardcodedSyntheticChildren(FormattersMatchData &match_data) { 800 SyntheticChildrenSP retval_sp; 801 802 for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages()) { 803 if (LanguageCategory *lang_category = GetCategoryForLanguage(lang_type)) { 804 if (lang_category->GetHardcoded(*this, match_data, retval_sp)) 805 break; 806 } 807 } 808 809 return retval_sp; 810 } 811 812 lldb::SyntheticChildrenSP 813 FormatManager::GetSyntheticChildren(ValueObject &valobj, 814 lldb::DynamicValueType use_dynamic) { 815 FormattersMatchData match_data(valobj, use_dynamic); 816 817 SyntheticChildrenSP retval; 818 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS)); 819 if (match_data.GetTypeForCache()) { 820 if (log) 821 log->Printf("\n\n[FormatManager::GetSyntheticChildren] Looking into " 822 "cache for type %s", 823 match_data.GetTypeForCache().AsCString("<invalid>")); 824 if (m_format_cache.GetSynthetic(match_data.GetTypeForCache(), retval)) { 825 if (log) { 826 log->Printf("[FormatManager::GetSyntheticChildren] Cache search " 827 "success. Returning."); 828 if (log->GetDebug()) 829 log->Printf( 830 "[FormatManager::GetSyntheticChildren] Cache hits: %" PRIu64 831 " - Cache Misses: %" PRIu64, 832 m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses()); 833 } 834 return retval; 835 } 836 if (log) 837 log->Printf("[FormatManager::GetSyntheticChildren] Cache search failed. " 838 "Going normal route"); 839 } 840 841 retval = m_categories_map.GetSyntheticChildren(match_data); 842 if (!retval) { 843 if (log) 844 log->Printf("[FormatManager::GetSyntheticChildren] Search failed. Giving " 845 "language a chance."); 846 for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages()) { 847 if (LanguageCategory *lang_category = GetCategoryForLanguage(lang_type)) { 848 if (lang_category->Get(match_data, retval)) 849 break; 850 } 851 } 852 if (retval) { 853 if (log) 854 log->Printf("[FormatManager::GetSyntheticChildren] Language search " 855 "success. Returning."); 856 return retval; 857 } 858 } 859 if (!retval) { 860 if (log) 861 log->Printf("[FormatManager::GetSyntheticChildren] Search failed. Giving " 862 "hardcoded a chance."); 863 retval = GetHardcodedSyntheticChildren(match_data); 864 } 865 866 if (match_data.GetTypeForCache() && (!retval || !retval->NonCacheable())) { 867 if (log) 868 log->Printf( 869 "[FormatManager::GetSyntheticChildren] Caching %p for type %s", 870 static_cast<void *>(retval.get()), 871 match_data.GetTypeForCache().AsCString("<invalid>")); 872 m_format_cache.SetSynthetic(match_data.GetTypeForCache(), retval); 873 } 874 if (log && log->GetDebug()) 875 log->Printf("[FormatManager::GetSyntheticChildren] Cache hits: %" PRIu64 876 " - Cache Misses: %" PRIu64, 877 m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses()); 878 return retval; 879 } 880 #endif 881 882 lldb::TypeValidatorImplSP 883 FormatManager::GetValidator(ValueObject &valobj, 884 lldb::DynamicValueType use_dynamic) { 885 FormattersMatchData match_data(valobj, use_dynamic); 886 887 TypeValidatorImplSP retval; 888 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS)); 889 if (match_data.GetTypeForCache()) { 890 if (log) 891 log->Printf( 892 "\n\n[FormatManager::GetValidator] Looking into cache for type %s", 893 match_data.GetTypeForCache().AsCString("<invalid>")); 894 if (m_format_cache.GetValidator(match_data.GetTypeForCache(), retval)) { 895 if (log) { 896 log->Printf( 897 "[FormatManager::GetValidator] Cache search success. Returning."); 898 if (log->GetDebug()) 899 log->Printf("[FormatManager::GetValidator] Cache hits: %" PRIu64 900 " - Cache Misses: %" PRIu64, 901 m_format_cache.GetCacheHits(), 902 m_format_cache.GetCacheMisses()); 903 } 904 return retval; 905 } 906 if (log) 907 log->Printf("[FormatManager::GetValidator] Cache search failed. Going " 908 "normal route"); 909 } 910 911 retval = m_categories_map.GetValidator(match_data); 912 if (!retval) { 913 if (log) 914 log->Printf("[FormatManager::GetValidator] Search failed. Giving " 915 "language a chance."); 916 for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages()) { 917 if (LanguageCategory *lang_category = GetCategoryForLanguage(lang_type)) { 918 if (lang_category->Get(match_data, retval)) 919 break; 920 } 921 } 922 if (retval) { 923 if (log) 924 log->Printf("[FormatManager::GetValidator] Language search success. " 925 "Returning."); 926 return retval; 927 } 928 } 929 if (!retval) { 930 if (log) 931 log->Printf("[FormatManager::GetValidator] Search failed. Giving " 932 "hardcoded a chance."); 933 retval = GetHardcodedValidator(match_data); 934 } 935 936 if (match_data.GetTypeForCache() && (!retval || !retval->NonCacheable())) { 937 if (log) 938 log->Printf("[FormatManager::GetValidator] Caching %p for type %s", 939 static_cast<void *>(retval.get()), 940 match_data.GetTypeForCache().AsCString("<invalid>")); 941 m_format_cache.SetValidator(match_data.GetTypeForCache(), retval); 942 } 943 if (log && log->GetDebug()) 944 log->Printf("[FormatManager::GetValidator] Cache hits: %" PRIu64 945 " - Cache Misses: %" PRIu64, 946 m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses()); 947 return retval; 948 } 949 950 lldb::TypeValidatorImplSP 951 FormatManager::GetHardcodedValidator(FormattersMatchData &match_data) { 952 TypeValidatorImplSP retval_sp; 953 954 for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages()) { 955 if (LanguageCategory *lang_category = GetCategoryForLanguage(lang_type)) { 956 if (lang_category->GetHardcoded(*this, match_data, retval_sp)) 957 break; 958 } 959 } 960 961 return retval_sp; 962 } 963 964 FormatManager::FormatManager() 965 : m_last_revision(0), m_format_cache(), m_language_categories_mutex(), 966 m_language_categories_map(), m_named_summaries_map(this), 967 m_categories_map(this), m_default_category_name(ConstString("default")), 968 m_system_category_name(ConstString("system")), 969 m_vectortypes_category_name(ConstString("VectorTypes")) { 970 LoadSystemFormatters(); 971 LoadVectorFormatters(); 972 973 EnableCategory(m_vectortypes_category_name, TypeCategoryMap::Last, 974 lldb::eLanguageTypeObjC_plus_plus); 975 EnableCategory(m_system_category_name, TypeCategoryMap::Last, 976 lldb::eLanguageTypeObjC_plus_plus); 977 } 978 979 void FormatManager::LoadSystemFormatters() { 980 TypeSummaryImpl::Flags string_flags; 981 string_flags.SetCascades(true) 982 .SetSkipPointers(true) 983 .SetSkipReferences(false) 984 .SetDontShowChildren(true) 985 .SetDontShowValue(false) 986 .SetShowMembersOneLiner(false) 987 .SetHideItemNames(false); 988 989 TypeSummaryImpl::Flags string_array_flags; 990 string_array_flags.SetCascades(true) 991 .SetSkipPointers(true) 992 .SetSkipReferences(false) 993 .SetDontShowChildren(true) 994 .SetDontShowValue(true) 995 .SetShowMembersOneLiner(false) 996 .SetHideItemNames(false); 997 998 lldb::TypeSummaryImplSP string_format( 999 new StringSummaryFormat(string_flags, "${var%s}")); 1000 1001 lldb::TypeSummaryImplSP string_array_format( 1002 new StringSummaryFormat(string_array_flags, "${var%s}")); 1003 1004 lldb::RegularExpressionSP any_size_char_arr( 1005 new RegularExpression(llvm::StringRef("char \\[[0-9]+\\]"))); 1006 lldb::RegularExpressionSP any_size_wchar_arr( 1007 new RegularExpression(llvm::StringRef("wchar_t \\[[0-9]+\\]"))); 1008 1009 TypeCategoryImpl::SharedPointer sys_category_sp = 1010 GetCategory(m_system_category_name); 1011 1012 sys_category_sp->GetTypeSummariesContainer()->Add(ConstString("char *"), 1013 string_format); 1014 sys_category_sp->GetTypeSummariesContainer()->Add( 1015 ConstString("unsigned char *"), string_format); 1016 sys_category_sp->GetRegexTypeSummariesContainer()->Add(any_size_char_arr, 1017 string_array_format); 1018 1019 lldb::TypeSummaryImplSP ostype_summary( 1020 new StringSummaryFormat(TypeSummaryImpl::Flags() 1021 .SetCascades(false) 1022 .SetSkipPointers(true) 1023 .SetSkipReferences(true) 1024 .SetDontShowChildren(true) 1025 .SetDontShowValue(false) 1026 .SetShowMembersOneLiner(false) 1027 .SetHideItemNames(false), 1028 "${var%O}")); 1029 1030 sys_category_sp->GetTypeSummariesContainer()->Add(ConstString("OSType"), 1031 ostype_summary); 1032 1033 #ifndef LLDB_DISABLE_PYTHON 1034 TypeFormatImpl::Flags fourchar_flags; 1035 fourchar_flags.SetCascades(true).SetSkipPointers(true).SetSkipReferences( 1036 true); 1037 1038 AddFormat(sys_category_sp, lldb::eFormatOSType, ConstString("FourCharCode"), 1039 fourchar_flags); 1040 #endif 1041 } 1042 1043 void FormatManager::LoadVectorFormatters() { 1044 TypeCategoryImpl::SharedPointer vectors_category_sp = 1045 GetCategory(m_vectortypes_category_name); 1046 1047 TypeSummaryImpl::Flags vector_flags; 1048 vector_flags.SetCascades(true) 1049 .SetSkipPointers(true) 1050 .SetSkipReferences(false) 1051 .SetDontShowChildren(true) 1052 .SetDontShowValue(false) 1053 .SetShowMembersOneLiner(true) 1054 .SetHideItemNames(true); 1055 1056 AddStringSummary(vectors_category_sp, "${var.uint128}", 1057 ConstString("builtin_type_vec128"), vector_flags); 1058 1059 AddStringSummary(vectors_category_sp, "", ConstString("float [4]"), 1060 vector_flags); 1061 AddStringSummary(vectors_category_sp, "", ConstString("int32_t [4]"), 1062 vector_flags); 1063 AddStringSummary(vectors_category_sp, "", ConstString("int16_t [8]"), 1064 vector_flags); 1065 AddStringSummary(vectors_category_sp, "", ConstString("vDouble"), 1066 vector_flags); 1067 AddStringSummary(vectors_category_sp, "", ConstString("vFloat"), 1068 vector_flags); 1069 AddStringSummary(vectors_category_sp, "", ConstString("vSInt8"), 1070 vector_flags); 1071 AddStringSummary(vectors_category_sp, "", ConstString("vSInt16"), 1072 vector_flags); 1073 AddStringSummary(vectors_category_sp, "", ConstString("vSInt32"), 1074 vector_flags); 1075 AddStringSummary(vectors_category_sp, "", ConstString("vUInt16"), 1076 vector_flags); 1077 AddStringSummary(vectors_category_sp, "", ConstString("vUInt8"), 1078 vector_flags); 1079 AddStringSummary(vectors_category_sp, "", ConstString("vUInt16"), 1080 vector_flags); 1081 AddStringSummary(vectors_category_sp, "", ConstString("vUInt32"), 1082 vector_flags); 1083 AddStringSummary(vectors_category_sp, "", ConstString("vBool32"), 1084 vector_flags); 1085 } 1086