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 inline 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 ClangASTType ast_type(valobj.GetClangType()); 292 bool ret = Get(valobj, ast_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 ClangASTType clang_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 (!clang_type.IsValid()) 534 { 535 if (log) 536 log->Printf("[Get_Impl] type is invalid, returning"); 537 return false; 538 } 539 540 clang_type = clang_type.RemoveFastQualifiers(); 541 542 ConstString typeName(clang_type.GetConstTypeName()); 543 544 if (valobj.GetBitfieldBitSize() > 0) 545 { 546 if (Get_BitfieldMatch(valobj, typeName, entry, reason)) 547 return true; 548 } 549 550 if (log) 551 log->Printf("[Get_Impl] trying to get %s for VO name %s of type %s", 552 m_name.c_str(), 553 valobj.GetName().AsCString(), 554 typeName.AsCString()); 555 556 if (Get(typeName, entry)) 557 { 558 if (log) 559 log->Printf("[Get] direct match found, returning"); 560 return true; 561 } 562 if (log) 563 log->Printf("[Get_Impl] no direct match"); 564 565 // strip pointers and references and see if that helps 566 if (clang_type.IsReferenceType()) 567 { 568 if (log) 569 log->Printf("[Get_Impl] stripping reference"); 570 if (Get_Impl(valobj, clang_type.GetNonReferenceType(), entry, use_dynamic, reason) && !entry->SkipsReferences()) 571 { 572 reason |= lldb_private::eFormatterChoiceCriterionStrippedPointerReference; 573 return true; 574 } 575 } 576 else if (clang_type.IsPointerType()) 577 { 578 if (log) 579 log->Printf("[Get_Impl] stripping pointer"); 580 if (Get_Impl(valobj, clang_type.GetPointeeType(), entry, use_dynamic, reason) && !entry->SkipsPointers()) 581 { 582 reason |= lldb_private::eFormatterChoiceCriterionStrippedPointerReference; 583 return true; 584 } 585 } 586 587 bool canBeObjCDynamic = valobj.GetClangType().IsPossibleDynamicType (NULL, 588 false, // no C++ 589 true); // yes ObjC 590 591 if (canBeObjCDynamic) 592 { 593 if (use_dynamic != lldb::eNoDynamicValues) 594 { 595 if (log) 596 log->Printf("[Get_Impl] allowed to figure out dynamic ObjC type"); 597 if (Get_ObjC(valobj,entry)) 598 { 599 reason |= lldb_private::eFormatterChoiceCriterionDynamicObjCDiscovery; 600 return true; 601 } 602 } 603 if (log) 604 log->Printf("[Get_Impl] dynamic disabled or failed - stripping ObjC pointer"); 605 if (Get_Impl(valobj, clang_type.GetPointeeType(), entry, use_dynamic, reason) && !entry->SkipsPointers()) 606 { 607 reason |= lldb_private::eFormatterChoiceCriterionStrippedPointerReference; 608 return true; 609 } 610 } 611 612 // try to strip typedef chains 613 if (clang_type.IsTypedefType()) 614 { 615 if (log) 616 log->Printf("[Get_Impl] stripping typedef"); 617 if ((Get_Impl(valobj, clang_type.GetTypedefedType(), entry, use_dynamic, reason)) && entry->Cascades()) 618 { 619 reason |= lldb_private::eFormatterChoiceCriterionNavigatedTypedefs; 620 return true; 621 } 622 } 623 624 // out of luck here 625 return false; 626 } 627 628 // we are separately passing in valobj and type because the valobj is fixed (and is used for ObjC discovery and bitfield size) 629 // but the type can change (e.g. stripping pointers, ...) 630 bool Get (ValueObject& valobj, 631 ClangASTType clang_type, 632 MapValueType& entry, 633 lldb::DynamicValueType use_dynamic, 634 uint32_t& reason) 635 { 636 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); 637 638 if (Get_Impl (valobj, clang_type, entry, use_dynamic, reason)) 639 return true; 640 641 // try going to the unqualified type 642 do { 643 if (log) 644 log->Printf("[Get] trying the unqualified type"); 645 if (!clang_type.IsValid()) 646 break; 647 648 ClangASTType unqual_clang_ast_type = clang_type.GetFullyUnqualifiedType(); 649 if (!unqual_clang_ast_type.IsValid()) 650 { 651 if (log) 652 log->Printf("[Get] could not get the unqual_clang_ast_type"); 653 break; 654 } 655 if (unqual_clang_ast_type.GetOpaqueQualType() != clang_type.GetOpaqueQualType()) 656 { 657 if (log) 658 log->Printf("[Get] unqualified type is there and is not the same, let's try"); 659 if (Get_Impl (valobj, unqual_clang_ast_type,entry, use_dynamic, reason)) 660 return true; 661 } 662 else if (log) 663 log->Printf("[Get] unqualified type same as original type"); 664 } while(false); 665 666 // if all else fails, go to static type 667 if (valobj.IsDynamic()) 668 { 669 if (log) 670 log->Printf("[Get] going to static value"); 671 lldb::ValueObjectSP static_value_sp(valobj.GetStaticValue()); 672 if (static_value_sp) 673 { 674 if (log) 675 log->Printf("[Get] has a static value - actually use it"); 676 if (Get(*static_value_sp.get(), static_value_sp->GetClangType(), entry, use_dynamic, reason)) 677 { 678 reason |= lldb_private::eFormatterChoiceCriterionWentToStaticValue; 679 return true; 680 } 681 } 682 } 683 684 return false; 685 } 686}; 687 688} // namespace lldb_private 689 690#endif // lldb_FormatNavigator_h_ 691