FormatNavigator.h revision b6a4c565732b3a7b546ba2aa0e7aec3a4bb359a4
1//===-- FormatNavigator.h ----------------------------------------*- 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#ifndef lldb_FormatNavigator_h_ 11#define lldb_FormatNavigator_h_ 12 13// C Includes 14// C++ Includes 15 16// Other libraries and framework includes 17#include "clang/AST/DeclCXX.h" 18#include "clang/AST/Type.h" 19#include "clang/AST/DeclObjC.h" 20 21// Project includes 22#include "lldb/lldb-public.h" 23 24#include "lldb/Core/Log.h" 25#include "lldb/Core/RegularExpression.h" 26#include "lldb/Core/ValueObject.h" 27 28#include "lldb/DataFormatters/FormatClasses.h" 29 30#include "lldb/Symbol/ClangASTContext.h" 31#include "lldb/Symbol/ClangASTType.h" 32 33#include "lldb/Target/ObjCLanguageRuntime.h" 34#include "lldb/Target/Process.h" 35#include "lldb/Target/StackFrame.h" 36#include "lldb/Target/TargetList.h" 37 38namespace lldb_private { 39 40// this file (and its. cpp) contain the low-level implementation of LLDB Data Visualization 41// class DataVisualization is the high-level front-end of this feature 42// clients should refer to that class as the entry-point into the data formatters 43// unless they have a good reason to bypass it and prefer to use this file's objects directly 44class IFormatChangeListener 45{ 46public: 47 virtual void 48 Changed () = 0; 49 50 virtual 51 ~IFormatChangeListener () {} 52 53 virtual uint32_t 54 GetCurrentRevision () = 0; 55 56}; 57 58static inline bool 59IsWhitespace (char c) 60{ 61 return ( (c == ' ') || (c == '\t') || (c == '\v') || (c == '\f') ); 62} 63 64static inline bool 65HasPrefix (const char* str1, const char* str2) 66{ 67 return ( ::strstr(str1, str2) == str1 ); 68} 69 70// if the user tries to add formatters for, say, "struct Foo" 71// those will not match any type because of the way we strip qualifiers from typenames 72// this method looks for the case where the user is adding a "class","struct","enum" or "union" Foo 73// and strips the unnecessary qualifier 74static ConstString 75GetValidTypeName_Impl (const ConstString& type) 76{ 77 int strip_len = 0; 78 79 if (type == false) 80 return type; 81 82 const char* type_cstr = type.AsCString(); 83 84 if ( HasPrefix(type_cstr, "class ") ) 85 strip_len = 6; 86 else if ( HasPrefix(type_cstr, "enum ") ) 87 strip_len = 5; 88 else if ( HasPrefix(type_cstr, "struct ") ) 89 strip_len = 7; 90 else if ( HasPrefix(type_cstr, "union ") ) 91 strip_len = 6; 92 93 if (strip_len == 0) 94 return type; 95 96 type_cstr += strip_len; 97 while (IsWhitespace(*type_cstr) && ++type_cstr) 98 ; 99 100 return ConstString(type_cstr); 101} 102 103template<typename KeyType, typename ValueType> 104class FormatNavigator; 105 106template<typename KeyType, typename ValueType> 107class FormatMap 108{ 109public: 110 111 typedef typename ValueType::SharedPointer ValueSP; 112 typedef std::map<KeyType, ValueSP> MapType; 113 typedef typename MapType::iterator MapIterator; 114 typedef bool(*CallbackType)(void*, KeyType, const ValueSP&); 115 116 FormatMap(IFormatChangeListener* lst) : 117 m_map(), 118 m_map_mutex(Mutex::eMutexTypeRecursive), 119 listener(lst) 120 { 121 } 122 123 void 124 Add(KeyType name, 125 const ValueSP& entry) 126 { 127 if (listener) 128 entry->GetRevision() = listener->GetCurrentRevision(); 129 else 130 entry->GetRevision() = 0; 131 132 Mutex::Locker locker(m_map_mutex); 133 m_map[name] = entry; 134 if (listener) 135 listener->Changed(); 136 } 137 138 bool 139 Delete (KeyType name) 140 { 141 Mutex::Locker locker(m_map_mutex); 142 MapIterator iter = m_map.find(name); 143 if (iter == m_map.end()) 144 return false; 145 m_map.erase(name); 146 if (listener) 147 listener->Changed(); 148 return true; 149 } 150 151 void 152 Clear () 153 { 154 Mutex::Locker locker(m_map_mutex); 155 m_map.clear(); 156 if (listener) 157 listener->Changed(); 158 } 159 160 bool 161 Get(KeyType name, 162 ValueSP& entry) 163 { 164 Mutex::Locker locker(m_map_mutex); 165 MapIterator iter = m_map.find(name); 166 if (iter == m_map.end()) 167 return false; 168 entry = iter->second; 169 return true; 170 } 171 172 void 173 LoopThrough (CallbackType callback, void* param) 174 { 175 if (callback) 176 { 177 Mutex::Locker locker(m_map_mutex); 178 MapIterator pos, end = m_map.end(); 179 for (pos = m_map.begin(); pos != end; pos++) 180 { 181 KeyType type = pos->first; 182 if (!callback(param, type, pos->second)) 183 break; 184 } 185 } 186 } 187 188 uint32_t 189 GetCount () 190 { 191 return m_map.size(); 192 } 193 194 ValueSP 195 GetValueAtIndex (size_t index) 196 { 197 Mutex::Locker locker(m_map_mutex); 198 MapIterator iter = m_map.begin(); 199 MapIterator end = m_map.end(); 200 while (index > 0) 201 { 202 iter++; 203 index--; 204 if (end == iter) 205 return ValueSP(); 206 } 207 return iter->second; 208 } 209 210 KeyType 211 GetKeyAtIndex (size_t index) 212 { 213 Mutex::Locker locker(m_map_mutex); 214 MapIterator iter = m_map.begin(); 215 MapIterator end = m_map.end(); 216 while (index > 0) 217 { 218 iter++; 219 index--; 220 if (end == iter) 221 return KeyType(); 222 } 223 return iter->first; 224 } 225 226protected: 227 MapType m_map; 228 Mutex m_map_mutex; 229 IFormatChangeListener* listener; 230 231 MapType& 232 map () 233 { 234 return m_map; 235 } 236 237 Mutex& 238 mutex () 239 { 240 return m_map_mutex; 241 } 242 243 friend class FormatNavigator<KeyType, ValueType>; 244 friend class FormatManager; 245 246}; 247 248template<typename KeyType, typename ValueType> 249class FormatNavigator 250{ 251protected: 252 typedef FormatMap<KeyType,ValueType> BackEndType; 253 254public: 255 typedef typename BackEndType::MapType MapType; 256 typedef typename MapType::iterator MapIterator; 257 typedef typename MapType::key_type MapKeyType; 258 typedef typename MapType::mapped_type MapValueType; 259 typedef typename BackEndType::CallbackType CallbackType; 260 typedef typename std::shared_ptr<FormatNavigator<KeyType, ValueType> > SharedPointer; 261 262 friend class TypeCategoryImpl; 263 264 FormatNavigator(std::string name, 265 IFormatChangeListener* lst) : 266 m_format_map(lst), 267 m_name(name), 268 m_id_cs(ConstString("id")) 269 { 270 } 271 272 void 273 Add (const MapKeyType &type, const MapValueType& entry) 274 { 275 Add_Impl(type, entry, (KeyType*)NULL); 276 } 277 278 bool 279 Delete (ConstString type) 280 { 281 return Delete_Impl(type, (KeyType*)NULL); 282 } 283 284 bool 285 Get(ValueObject& valobj, 286 MapValueType& entry, 287 lldb::DynamicValueType use_dynamic, 288 uint32_t* why = NULL) 289 { 290 uint32_t value = lldb_private::eFormatterChoiceCriterionDirectChoice; 291 clang::QualType type = clang::QualType::getFromOpaquePtr(valobj.GetClangType()); 292 bool ret = Get(valobj, type, entry, use_dynamic, value); 293 if (ret) 294 entry = MapValueType(entry); 295 else 296 entry = MapValueType(); 297 if (why) 298 *why = value; 299 return ret; 300 } 301 302 bool 303 Get (ConstString type, MapValueType& entry) 304 { 305 return Get_Impl(type, entry, (KeyType*)NULL); 306 } 307 308 bool 309 GetExact (ConstString type, MapValueType& entry) 310 { 311 return GetExact_Impl(type, entry, (KeyType*)NULL); 312 } 313 314 MapValueType 315 GetAtIndex (size_t index) 316 { 317 return m_format_map.GetValueAtIndex(index); 318 } 319 320 lldb::TypeNameSpecifierImplSP 321 GetTypeNameSpecifierAtIndex (size_t index) 322 { 323 return GetTypeNameSpecifierAtIndex_Impl(index, (KeyType*)NULL); 324 } 325 326 void 327 Clear () 328 { 329 m_format_map.Clear(); 330 } 331 332 void 333 LoopThrough (CallbackType callback, void* param) 334 { 335 m_format_map.LoopThrough(callback,param); 336 } 337 338 uint32_t 339 GetCount () 340 { 341 return m_format_map.GetCount(); 342 } 343 344protected: 345 346 BackEndType m_format_map; 347 348 std::string m_name; 349 350 DISALLOW_COPY_AND_ASSIGN(FormatNavigator); 351 352 ConstString m_id_cs; 353 354 void 355 Add_Impl (const MapKeyType &type, const MapValueType& entry, lldb::RegularExpressionSP *dummy) 356 { 357 m_format_map.Add(type,entry); 358 } 359 360 void Add_Impl (const ConstString &type, const MapValueType& entry, ConstString *dummy) 361 { 362 m_format_map.Add(GetValidTypeName_Impl(type), entry); 363 } 364 365 bool 366 Delete_Impl (ConstString type, ConstString *dummy) 367 { 368 return m_format_map.Delete(type); 369 } 370 371 bool 372 Delete_Impl (ConstString type, lldb::RegularExpressionSP *dummy) 373 { 374 Mutex& x_mutex = m_format_map.mutex(); 375 lldb_private::Mutex::Locker locker(x_mutex); 376 MapIterator pos, end = m_format_map.map().end(); 377 for (pos = m_format_map.map().begin(); pos != end; pos++) 378 { 379 lldb::RegularExpressionSP regex = pos->first; 380 if ( ::strcmp(type.AsCString(),regex->GetText()) == 0) 381 { 382 m_format_map.map().erase(pos); 383 if (m_format_map.listener) 384 m_format_map.listener->Changed(); 385 return true; 386 } 387 } 388 return false; 389 } 390 391 bool 392 Get_Impl (ConstString type, MapValueType& entry, ConstString *dummy) 393 { 394 return m_format_map.Get(type, entry); 395 } 396 397 bool 398 GetExact_Impl (ConstString type, MapValueType& entry, ConstString *dummy) 399 { 400 return Get_Impl(type,entry, (KeyType*)0); 401 } 402 403 lldb::TypeNameSpecifierImplSP 404 GetTypeNameSpecifierAtIndex_Impl (size_t index, ConstString *dummy) 405 { 406 ConstString key = m_format_map.GetKeyAtIndex(index); 407 if (key) 408 return lldb::TypeNameSpecifierImplSP(new TypeNameSpecifierImpl(key.AsCString(), 409 false)); 410 else 411 return lldb::TypeNameSpecifierImplSP(); 412 } 413 414 lldb::TypeNameSpecifierImplSP 415 GetTypeNameSpecifierAtIndex_Impl (size_t index, lldb::RegularExpressionSP *dummy) 416 { 417 lldb::RegularExpressionSP regex = m_format_map.GetKeyAtIndex(index); 418 if (regex.get() == NULL) 419 return lldb::TypeNameSpecifierImplSP(); 420 return lldb::TypeNameSpecifierImplSP(new TypeNameSpecifierImpl(regex->GetText(), 421 true)); 422 } 423 424 bool 425 Get_Impl (ConstString key, MapValueType& value, lldb::RegularExpressionSP *dummy) 426 { 427 const char* key_cstr = key.AsCString(); 428 if (!key_cstr) 429 return false; 430 Mutex& x_mutex = m_format_map.mutex(); 431 lldb_private::Mutex::Locker locker(x_mutex); 432 MapIterator pos, end = m_format_map.map().end(); 433 for (pos = m_format_map.map().begin(); pos != end; pos++) 434 { 435 lldb::RegularExpressionSP regex = pos->first; 436 if (regex->Execute(key_cstr)) 437 { 438 value = pos->second; 439 return true; 440 } 441 } 442 return false; 443 } 444 445 bool 446 GetExact_Impl (ConstString key, MapValueType& value, lldb::RegularExpressionSP *dummy) 447 { 448 Mutex& x_mutex = m_format_map.mutex(); 449 lldb_private::Mutex::Locker locker(x_mutex); 450 MapIterator pos, end = m_format_map.map().end(); 451 for (pos = m_format_map.map().begin(); pos != end; pos++) 452 { 453 lldb::RegularExpressionSP regex = pos->first; 454 if (strcmp(regex->GetText(),key.AsCString()) == 0) 455 { 456 value = pos->second; 457 return true; 458 } 459 } 460 return false; 461 } 462 463 bool 464 Get_BitfieldMatch (ValueObject& valobj, 465 ConstString typeName, 466 MapValueType& entry, 467 uint32_t& reason) 468 { 469 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); 470 // for bitfields, append size to the typename so one can custom format them 471 StreamString sstring; 472 sstring.Printf("%s:%d",typeName.AsCString(),valobj.GetBitfieldBitSize()); 473 ConstString bitfieldname = ConstString(sstring.GetData()); 474 if (log) 475 log->Printf("[Get_BitfieldMatch] appended bitfield info, final result is %s", bitfieldname.GetCString()); 476 if (Get(bitfieldname, entry)) 477 { 478 if (log) 479 log->Printf("[Get_BitfieldMatch] bitfield direct match found, returning"); 480 return true; 481 } 482 else 483 { 484 reason |= lldb_private::eFormatterChoiceCriterionStrippedBitField; 485 if (log) 486 log->Printf("[Get_BitfieldMatch] no bitfield direct match"); 487 return false; 488 } 489 } 490 491 bool Get_ObjC (ValueObject& valobj, 492 MapValueType& entry) 493 { 494 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); 495 lldb::ProcessSP process_sp = valobj.GetProcessSP(); 496 ObjCLanguageRuntime* runtime = process_sp->GetObjCLanguageRuntime(); 497 if (runtime == NULL) 498 { 499 if (log) 500 log->Printf("[Get_ObjC] no valid ObjC runtime, skipping dynamic"); 501 return false; 502 } 503 ObjCLanguageRuntime::ClassDescriptorSP objc_class_sp (runtime->GetClassDescriptor(valobj)); 504 if (!objc_class_sp) 505 { 506 if (log) 507 log->Printf("[Get_ObjC] invalid ISA, skipping dynamic"); 508 return false; 509 } 510 ConstString name (objc_class_sp->GetClassName()); 511 if (log) 512 log->Printf("[Get_ObjC] dynamic type inferred is %s - looking for direct dynamic match", name.GetCString()); 513 if (Get(name, entry)) 514 { 515 if (log) 516 log->Printf("[Get_ObjC] direct dynamic match found, returning"); 517 return true; 518 } 519 if (log) 520 log->Printf("[Get_ObjC] no dynamic match"); 521 return false; 522 } 523 524 bool 525 Get_Impl (ValueObject& valobj, 526 clang::QualType type, 527 MapValueType& entry, 528 lldb::DynamicValueType use_dynamic, 529 uint32_t& reason) 530 { 531 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); 532 533 if (type.isNull()) 534 { 535 if (log) 536 log->Printf("[Get_Impl] type is NULL, returning"); 537 return false; 538 } 539 540 type.removeLocalConst(); type.removeLocalVolatile(); type.removeLocalRestrict(); 541 const clang::Type* typePtr = type.getTypePtrOrNull(); 542 if (!typePtr) 543 { 544 if (log) 545 log->Printf("[Get_Impl] type is NULL, returning"); 546 return false; 547 } 548 ConstString typeName(ClangASTType::GetTypeNameForQualType(valobj.GetClangAST(), type).c_str()); 549 550 if (valobj.GetBitfieldBitSize() > 0) 551 { 552 if (Get_BitfieldMatch(valobj, typeName, entry, reason)) 553 return true; 554 } 555 556 if (log) 557 log->Printf("[Get_Impl] trying to get %s for VO name %s of type %s", 558 m_name.c_str(), 559 valobj.GetName().AsCString(), 560 typeName.AsCString()); 561 562 if (Get(typeName, entry)) 563 { 564 if (log) 565 log->Printf("[Get] direct match found, returning"); 566 return true; 567 } 568 if (log) 569 log->Printf("[Get_Impl] no direct match"); 570 571 // strip pointers and references and see if that helps 572 if (typePtr->isReferenceType()) 573 { 574 if (log) 575 log->Printf("[Get_Impl] stripping reference"); 576 if (Get_Impl(valobj,type.getNonReferenceType(),entry, use_dynamic, reason) && !entry->SkipsReferences()) 577 { 578 reason |= lldb_private::eFormatterChoiceCriterionStrippedPointerReference; 579 return true; 580 } 581 } 582 else if (typePtr->isPointerType()) 583 { 584 if (log) 585 log->Printf("[Get_Impl] stripping pointer"); 586 clang::QualType pointee = typePtr->getPointeeType(); 587 if (Get_Impl(valobj, pointee, entry, use_dynamic, reason) && !entry->SkipsPointers()) 588 { 589 reason |= lldb_private::eFormatterChoiceCriterionStrippedPointerReference; 590 return true; 591 } 592 } 593 594 bool canBeObjCDynamic = ClangASTContext::IsPossibleDynamicType (valobj.GetClangAST(), 595 type.getAsOpaquePtr(), 596 NULL, 597 false, // no C++ 598 true); // yes ObjC 599 600 if (canBeObjCDynamic) 601 { 602 if (use_dynamic != lldb::eNoDynamicValues) 603 { 604 if (log) 605 log->Printf("[Get_Impl] allowed to figure out dynamic ObjC type"); 606 if (Get_ObjC(valobj,entry)) 607 { 608 reason |= lldb_private::eFormatterChoiceCriterionDynamicObjCDiscovery; 609 return true; 610 } 611 } 612 if (log) 613 log->Printf("[Get_Impl] dynamic disabled or failed - stripping ObjC pointer"); 614 clang::QualType pointee = typePtr->getPointeeType(); 615 if (Get_Impl(valobj, pointee, entry, use_dynamic, reason) && !entry->SkipsPointers()) 616 { 617 reason |= lldb_private::eFormatterChoiceCriterionStrippedPointerReference; 618 return true; 619 } 620 } 621 622 // try to strip typedef chains 623 const clang::TypedefType* type_tdef = type->getAs<clang::TypedefType>(); 624 if (type_tdef) 625 { 626 if (log) 627 log->Printf("[Get_Impl] stripping typedef"); 628 if ((Get_Impl(valobj, type_tdef->getDecl()->getUnderlyingType(), entry, use_dynamic, reason)) && entry->Cascades()) 629 { 630 reason |= lldb_private::eFormatterChoiceCriterionNavigatedTypedefs; 631 return true; 632 } 633 } 634 635 // out of luck here 636 return false; 637 } 638 639 // we are separately passing in valobj and type because the valobj is fixed (and is used for ObjC discovery and bitfield size) 640 // but the type can change (e.g. stripping pointers, ...) 641 bool Get (ValueObject& valobj, 642 clang::QualType type, 643 MapValueType& entry, 644 lldb::DynamicValueType use_dynamic, 645 uint32_t& reason) 646 { 647 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); 648 649 if (Get_Impl (valobj,type,entry,use_dynamic,reason)) 650 return true; 651 652 // try going to the unqualified type 653 do { 654 if (log) 655 log->Printf("[Get] trying the unqualified type"); 656 lldb::clang_type_t opaque_type = type.getAsOpaquePtr(); 657 if (!opaque_type) 658 { 659 if (log) 660 log->Printf("[Get] could not get the opaque_type"); 661 break; 662 } 663 ClangASTType unqual_clang_ast_type = ClangASTType::GetFullyUnqualifiedType(valobj.GetClangAST(),opaque_type); 664 if (!unqual_clang_ast_type.IsValid()) 665 { 666 if (log) 667 log->Printf("[Get] could not get the unqual_clang_ast_type"); 668 break; 669 } 670 clang::QualType unqualified_qual_type = clang::QualType::getFromOpaquePtr(unqual_clang_ast_type.GetOpaqueQualType()); 671 if (unqualified_qual_type.getTypePtrOrNull() != type.getTypePtrOrNull()) 672 { 673 if (log) 674 log->Printf("[Get] unqualified type is there and is not the same, let's try"); 675 if (Get_Impl (valobj,unqualified_qual_type,entry,use_dynamic,reason)) 676 return true; 677 } 678 else if (log) 679 log->Printf("[Get] unqualified type same as original type"); 680 } while(false); 681 682 // if all else fails, go to static type 683 if (valobj.IsDynamic()) 684 { 685 if (log) 686 log->Printf("[Get] going to static value"); 687 lldb::ValueObjectSP static_value_sp(valobj.GetStaticValue()); 688 if (static_value_sp) 689 { 690 if (log) 691 log->Printf("[Get] has a static value - actually use it"); 692 if (Get(*static_value_sp.get(), clang::QualType::getFromOpaquePtr(static_value_sp->GetClangType()) , entry, use_dynamic, reason)) 693 { 694 reason |= lldb_private::eFormatterChoiceCriterionWentToStaticValue; 695 return true; 696 } 697 } 698 } 699 700 return false; 701 } 702}; 703 704} // namespace lldb_private 705 706#endif // lldb_FormatNavigator_h_ 707