1 //===-- PluginManager.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/Core/PluginManager.h" 11 12 // C Includes 13 // C++ Includes 14 #include <climits> 15 #include <string> 16 #include <vector> 17 18 // Other libraries and framework includes 19 #include "llvm/ADT/StringRef.h" 20 #include "llvm/Support/DynamicLibrary.h" 21 22 // Project includes 23 #include "lldb/Core/Debugger.h" 24 #include "lldb/Core/Error.h" 25 #include "lldb/Host/FileSpec.h" 26 #include "lldb/Host/Host.h" 27 #include "lldb/Host/HostInfo.h" 28 #include "lldb/Host/Mutex.h" 29 #include "lldb/Interpreter/OptionValueProperties.h" 30 31 using namespace lldb; 32 using namespace lldb_private; 33 34 enum PluginAction 35 { 36 ePluginRegisterInstance, 37 ePluginUnregisterInstance, 38 ePluginGetInstanceAtIndex 39 }; 40 41 typedef bool (*PluginInitCallback)(); 42 typedef void (*PluginTermCallback)(); 43 44 struct PluginInfo 45 { 46 PluginInfo() 47 : plugin_init_callback(nullptr), plugin_term_callback(nullptr) 48 { 49 } 50 51 llvm::sys::DynamicLibrary library; 52 PluginInitCallback plugin_init_callback; 53 PluginTermCallback plugin_term_callback; 54 }; 55 56 typedef std::map<FileSpec, PluginInfo> PluginTerminateMap; 57 58 static Mutex & 59 GetPluginMapMutex () 60 { 61 static Mutex g_plugin_map_mutex (Mutex::eMutexTypeRecursive); 62 return g_plugin_map_mutex; 63 } 64 65 static PluginTerminateMap & 66 GetPluginMap () 67 { 68 static PluginTerminateMap g_plugin_map; 69 return g_plugin_map; 70 } 71 72 static bool 73 PluginIsLoaded (const FileSpec &plugin_file_spec) 74 { 75 Mutex::Locker locker (GetPluginMapMutex ()); 76 PluginTerminateMap &plugin_map = GetPluginMap (); 77 return plugin_map.find (plugin_file_spec) != plugin_map.end(); 78 } 79 80 static void 81 SetPluginInfo (const FileSpec &plugin_file_spec, const PluginInfo &plugin_info) 82 { 83 Mutex::Locker locker (GetPluginMapMutex ()); 84 PluginTerminateMap &plugin_map = GetPluginMap (); 85 assert (plugin_map.find (plugin_file_spec) == plugin_map.end()); 86 plugin_map[plugin_file_spec] = plugin_info; 87 } 88 89 template <typename FPtrTy> 90 static FPtrTy 91 CastToFPtr (void *VPtr) 92 { 93 return reinterpret_cast<FPtrTy>(reinterpret_cast<intptr_t>(VPtr)); 94 } 95 96 static FileSpec::EnumerateDirectoryResult 97 LoadPluginCallback(void *baton, 98 FileSpec::FileType file_type, 99 const FileSpec &file_spec) 100 { 101 // PluginManager *plugin_manager = (PluginManager *)baton; 102 Error error; 103 104 // If we have a regular file, a symbolic link or unknown file type, try 105 // and process the file. We must handle unknown as sometimes the directory 106 // enumeration might be enumerating a file system that doesn't have correct 107 // file type information. 108 if (file_type == FileSpec::eFileTypeRegular || 109 file_type == FileSpec::eFileTypeSymbolicLink || 110 file_type == FileSpec::eFileTypeUnknown ) 111 { 112 FileSpec plugin_file_spec (file_spec); 113 plugin_file_spec.ResolvePath(); 114 115 if (PluginIsLoaded (plugin_file_spec)) 116 return FileSpec::eEnumerateDirectoryResultNext; 117 else 118 { 119 PluginInfo plugin_info; 120 121 std::string pluginLoadError; 122 plugin_info.library = llvm::sys::DynamicLibrary::getPermanentLibrary (plugin_file_spec.GetPath().c_str(), &pluginLoadError); 123 if (plugin_info.library.isValid()) 124 { 125 bool success = false; 126 plugin_info.plugin_init_callback = 127 CastToFPtr<PluginInitCallback>(plugin_info.library.getAddressOfSymbol("LLDBPluginInitialize")); 128 if (plugin_info.plugin_init_callback) 129 { 130 // Call the plug-in "bool LLDBPluginInitialize(void)" function 131 success = plugin_info.plugin_init_callback(); 132 } 133 134 if (success) 135 { 136 // It is ok for the "LLDBPluginTerminate" symbol to be nullptr 137 plugin_info.plugin_term_callback = 138 CastToFPtr<PluginTermCallback>(plugin_info.library.getAddressOfSymbol("LLDBPluginTerminate")); 139 } 140 else 141 { 142 // The initialize function returned FALSE which means the plug-in might not be 143 // compatible, or might be too new or too old, or might not want to run on this 144 // machine. Set it to a default-constructed instance to invalidate it. 145 plugin_info = PluginInfo(); 146 } 147 148 // Regardless of success or failure, cache the plug-in load 149 // in our plug-in info so we don't try to load it again and 150 // again. 151 SetPluginInfo (plugin_file_spec, plugin_info); 152 153 return FileSpec::eEnumerateDirectoryResultNext; 154 } 155 } 156 } 157 158 if (file_type == FileSpec::eFileTypeUnknown || 159 file_type == FileSpec::eFileTypeDirectory || 160 file_type == FileSpec::eFileTypeSymbolicLink ) 161 { 162 // Try and recurse into anything that a directory or symbolic link. 163 // We must also do this for unknown as sometimes the directory enumeration 164 // might be enumerating a file system that doesn't have correct file type 165 // information. 166 return FileSpec::eEnumerateDirectoryResultEnter; 167 } 168 169 return FileSpec::eEnumerateDirectoryResultNext; 170 } 171 172 void 173 PluginManager::Initialize () 174 { 175 #if 1 176 FileSpec dir_spec; 177 const bool find_directories = true; 178 const bool find_files = true; 179 const bool find_other = true; 180 char dir_path[PATH_MAX]; 181 if (HostInfo::GetLLDBPath(ePathTypeLLDBSystemPlugins, dir_spec)) 182 { 183 if (dir_spec.Exists() && dir_spec.GetPath(dir_path, sizeof(dir_path))) 184 { 185 FileSpec::EnumerateDirectory(dir_path, 186 find_directories, 187 find_files, 188 find_other, 189 LoadPluginCallback, 190 nullptr); 191 } 192 } 193 194 if (HostInfo::GetLLDBPath(ePathTypeLLDBUserPlugins, dir_spec)) 195 { 196 if (dir_spec.Exists() && dir_spec.GetPath(dir_path, sizeof(dir_path))) 197 { 198 FileSpec::EnumerateDirectory(dir_path, 199 find_directories, 200 find_files, 201 find_other, 202 LoadPluginCallback, 203 nullptr); 204 } 205 } 206 #endif 207 } 208 209 void 210 PluginManager::Terminate () 211 { 212 Mutex::Locker locker (GetPluginMapMutex ()); 213 PluginTerminateMap &plugin_map = GetPluginMap (); 214 215 PluginTerminateMap::const_iterator pos, end = plugin_map.end(); 216 for (pos = plugin_map.begin(); pos != end; ++pos) 217 { 218 // Call the plug-in "void LLDBPluginTerminate (void)" function if there 219 // is one (if the symbol was not nullptr). 220 if (pos->second.library.isValid()) 221 { 222 if (pos->second.plugin_term_callback) 223 pos->second.plugin_term_callback(); 224 } 225 } 226 plugin_map.clear(); 227 } 228 229 #pragma mark ABI 230 231 struct ABIInstance 232 { 233 ABIInstance() : 234 name(), 235 description(), 236 create_callback(nullptr) 237 { 238 } 239 240 ConstString name; 241 std::string description; 242 ABICreateInstance create_callback; 243 }; 244 245 typedef std::vector<ABIInstance> ABIInstances; 246 247 static Mutex & 248 GetABIInstancesMutex () 249 { 250 static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive); 251 return g_instances_mutex; 252 } 253 254 static ABIInstances & 255 GetABIInstances () 256 { 257 static ABIInstances g_instances; 258 return g_instances; 259 } 260 261 bool 262 PluginManager::RegisterPlugin(const ConstString &name, 263 const char *description, 264 ABICreateInstance create_callback) 265 { 266 if (create_callback) 267 { 268 ABIInstance instance; 269 assert ((bool)name); 270 instance.name = name; 271 if (description && description[0]) 272 instance.description = description; 273 instance.create_callback = create_callback; 274 Mutex::Locker locker (GetABIInstancesMutex ()); 275 GetABIInstances ().push_back (instance); 276 return true; 277 } 278 return false; 279 } 280 281 bool 282 PluginManager::UnregisterPlugin (ABICreateInstance create_callback) 283 { 284 if (create_callback) 285 { 286 Mutex::Locker locker (GetABIInstancesMutex ()); 287 ABIInstances &instances = GetABIInstances (); 288 289 ABIInstances::iterator pos, end = instances.end(); 290 for (pos = instances.begin(); pos != end; ++ pos) 291 { 292 if (pos->create_callback == create_callback) 293 { 294 instances.erase(pos); 295 return true; 296 } 297 } 298 } 299 return false; 300 } 301 302 ABICreateInstance 303 PluginManager::GetABICreateCallbackAtIndex (uint32_t idx) 304 { 305 Mutex::Locker locker (GetABIInstancesMutex ()); 306 ABIInstances &instances = GetABIInstances (); 307 if (idx < instances.size()) 308 return instances[idx].create_callback; 309 return nullptr; 310 } 311 312 ABICreateInstance 313 PluginManager::GetABICreateCallbackForPluginName (const ConstString &name) 314 { 315 if (name) 316 { 317 Mutex::Locker locker (GetABIInstancesMutex ()); 318 ABIInstances &instances = GetABIInstances (); 319 320 ABIInstances::iterator pos, end = instances.end(); 321 for (pos = instances.begin(); pos != end; ++ pos) 322 { 323 if (name == pos->name) 324 return pos->create_callback; 325 } 326 } 327 return nullptr; 328 } 329 330 #pragma mark Disassembler 331 332 struct DisassemblerInstance 333 { 334 DisassemblerInstance() : 335 name(), 336 description(), 337 create_callback(nullptr) 338 { 339 } 340 341 ConstString name; 342 std::string description; 343 DisassemblerCreateInstance create_callback; 344 }; 345 346 typedef std::vector<DisassemblerInstance> DisassemblerInstances; 347 348 static Mutex & 349 GetDisassemblerMutex () 350 { 351 static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive); 352 return g_instances_mutex; 353 } 354 355 static DisassemblerInstances & 356 GetDisassemblerInstances () 357 { 358 static DisassemblerInstances g_instances; 359 return g_instances; 360 } 361 362 bool 363 PluginManager::RegisterPlugin(const ConstString &name, 364 const char *description, 365 DisassemblerCreateInstance create_callback) 366 { 367 if (create_callback) 368 { 369 DisassemblerInstance instance; 370 assert ((bool)name); 371 instance.name = name; 372 if (description && description[0]) 373 instance.description = description; 374 instance.create_callback = create_callback; 375 Mutex::Locker locker (GetDisassemblerMutex ()); 376 GetDisassemblerInstances ().push_back (instance); 377 return true; 378 } 379 return false; 380 } 381 382 bool 383 PluginManager::UnregisterPlugin (DisassemblerCreateInstance create_callback) 384 { 385 if (create_callback) 386 { 387 Mutex::Locker locker (GetDisassemblerMutex ()); 388 DisassemblerInstances &instances = GetDisassemblerInstances (); 389 390 DisassemblerInstances::iterator pos, end = instances.end(); 391 for (pos = instances.begin(); pos != end; ++ pos) 392 { 393 if (pos->create_callback == create_callback) 394 { 395 instances.erase(pos); 396 return true; 397 } 398 } 399 } 400 return false; 401 } 402 403 DisassemblerCreateInstance 404 PluginManager::GetDisassemblerCreateCallbackAtIndex (uint32_t idx) 405 { 406 Mutex::Locker locker (GetDisassemblerMutex ()); 407 DisassemblerInstances &instances = GetDisassemblerInstances (); 408 if (idx < instances.size()) 409 return instances[idx].create_callback; 410 return nullptr; 411 } 412 413 DisassemblerCreateInstance 414 PluginManager::GetDisassemblerCreateCallbackForPluginName (const ConstString &name) 415 { 416 if (name) 417 { 418 Mutex::Locker locker (GetDisassemblerMutex ()); 419 DisassemblerInstances &instances = GetDisassemblerInstances (); 420 421 DisassemblerInstances::iterator pos, end = instances.end(); 422 for (pos = instances.begin(); pos != end; ++ pos) 423 { 424 if (name == pos->name) 425 return pos->create_callback; 426 } 427 } 428 return nullptr; 429 } 430 431 #pragma mark DynamicLoader 432 433 struct DynamicLoaderInstance 434 { 435 DynamicLoaderInstance() : 436 name(), 437 description(), 438 create_callback(nullptr), 439 debugger_init_callback(nullptr) 440 { 441 } 442 443 ConstString name; 444 std::string description; 445 DynamicLoaderCreateInstance create_callback; 446 DebuggerInitializeCallback debugger_init_callback; 447 }; 448 449 typedef std::vector<DynamicLoaderInstance> DynamicLoaderInstances; 450 451 static Mutex & 452 GetDynamicLoaderMutex () 453 { 454 static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive); 455 return g_instances_mutex; 456 } 457 458 static DynamicLoaderInstances & 459 GetDynamicLoaderInstances () 460 { 461 static DynamicLoaderInstances g_instances; 462 return g_instances; 463 } 464 465 bool 466 PluginManager::RegisterPlugin(const ConstString &name, 467 const char *description, 468 DynamicLoaderCreateInstance create_callback, 469 DebuggerInitializeCallback debugger_init_callback) 470 { 471 if (create_callback) 472 { 473 DynamicLoaderInstance instance; 474 assert ((bool)name); 475 instance.name = name; 476 if (description && description[0]) 477 instance.description = description; 478 instance.create_callback = create_callback; 479 instance.debugger_init_callback = debugger_init_callback; 480 Mutex::Locker locker (GetDynamicLoaderMutex ()); 481 GetDynamicLoaderInstances ().push_back (instance); 482 } 483 return false; 484 } 485 486 bool 487 PluginManager::UnregisterPlugin (DynamicLoaderCreateInstance create_callback) 488 { 489 if (create_callback) 490 { 491 Mutex::Locker locker (GetDynamicLoaderMutex ()); 492 DynamicLoaderInstances &instances = GetDynamicLoaderInstances (); 493 494 DynamicLoaderInstances::iterator pos, end = instances.end(); 495 for (pos = instances.begin(); pos != end; ++ pos) 496 { 497 if (pos->create_callback == create_callback) 498 { 499 instances.erase(pos); 500 return true; 501 } 502 } 503 } 504 return false; 505 } 506 507 DynamicLoaderCreateInstance 508 PluginManager::GetDynamicLoaderCreateCallbackAtIndex (uint32_t idx) 509 { 510 Mutex::Locker locker (GetDynamicLoaderMutex ()); 511 DynamicLoaderInstances &instances = GetDynamicLoaderInstances (); 512 if (idx < instances.size()) 513 return instances[idx].create_callback; 514 return nullptr; 515 } 516 517 DynamicLoaderCreateInstance 518 PluginManager::GetDynamicLoaderCreateCallbackForPluginName (const ConstString &name) 519 { 520 if (name) 521 { 522 Mutex::Locker locker (GetDynamicLoaderMutex ()); 523 DynamicLoaderInstances &instances = GetDynamicLoaderInstances (); 524 525 DynamicLoaderInstances::iterator pos, end = instances.end(); 526 for (pos = instances.begin(); pos != end; ++ pos) 527 { 528 if (name == pos->name) 529 return pos->create_callback; 530 } 531 } 532 return nullptr; 533 } 534 535 #pragma mark JITLoader 536 537 struct JITLoaderInstance 538 { 539 JITLoaderInstance() : 540 name(), 541 description(), 542 create_callback(nullptr), 543 debugger_init_callback(nullptr) 544 { 545 } 546 547 ConstString name; 548 std::string description; 549 JITLoaderCreateInstance create_callback; 550 DebuggerInitializeCallback debugger_init_callback; 551 }; 552 553 typedef std::vector<JITLoaderInstance> JITLoaderInstances; 554 555 static Mutex & 556 GetJITLoaderMutex () 557 { 558 static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive); 559 return g_instances_mutex; 560 } 561 562 static JITLoaderInstances & 563 GetJITLoaderInstances () 564 { 565 static JITLoaderInstances g_instances; 566 return g_instances; 567 } 568 569 bool 570 PluginManager::RegisterPlugin(const ConstString &name, 571 const char *description, 572 JITLoaderCreateInstance create_callback, 573 DebuggerInitializeCallback debugger_init_callback) 574 { 575 if (create_callback) 576 { 577 JITLoaderInstance instance; 578 assert ((bool)name); 579 instance.name = name; 580 if (description && description[0]) 581 instance.description = description; 582 instance.create_callback = create_callback; 583 instance.debugger_init_callback = debugger_init_callback; 584 Mutex::Locker locker (GetJITLoaderMutex ()); 585 GetJITLoaderInstances ().push_back (instance); 586 } 587 return false; 588 } 589 590 bool 591 PluginManager::UnregisterPlugin (JITLoaderCreateInstance create_callback) 592 { 593 if (create_callback) 594 { 595 Mutex::Locker locker (GetJITLoaderMutex ()); 596 JITLoaderInstances &instances = GetJITLoaderInstances (); 597 598 JITLoaderInstances::iterator pos, end = instances.end(); 599 for (pos = instances.begin(); pos != end; ++ pos) 600 { 601 if (pos->create_callback == create_callback) 602 { 603 instances.erase(pos); 604 return true; 605 } 606 } 607 } 608 return false; 609 } 610 611 JITLoaderCreateInstance 612 PluginManager::GetJITLoaderCreateCallbackAtIndex (uint32_t idx) 613 { 614 Mutex::Locker locker (GetJITLoaderMutex ()); 615 JITLoaderInstances &instances = GetJITLoaderInstances (); 616 if (idx < instances.size()) 617 return instances[idx].create_callback; 618 return nullptr; 619 } 620 621 JITLoaderCreateInstance 622 PluginManager::GetJITLoaderCreateCallbackForPluginName (const ConstString &name) 623 { 624 if (name) 625 { 626 Mutex::Locker locker (GetJITLoaderMutex ()); 627 JITLoaderInstances &instances = GetJITLoaderInstances (); 628 629 JITLoaderInstances::iterator pos, end = instances.end(); 630 for (pos = instances.begin(); pos != end; ++ pos) 631 { 632 if (name == pos->name) 633 return pos->create_callback; 634 } 635 } 636 return nullptr; 637 } 638 639 #pragma mark EmulateInstruction 640 641 struct EmulateInstructionInstance 642 { 643 EmulateInstructionInstance() : 644 name(), 645 description(), 646 create_callback(nullptr) 647 { 648 } 649 650 ConstString name; 651 std::string description; 652 EmulateInstructionCreateInstance create_callback; 653 }; 654 655 typedef std::vector<EmulateInstructionInstance> EmulateInstructionInstances; 656 657 static Mutex & 658 GetEmulateInstructionMutex () 659 { 660 static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive); 661 return g_instances_mutex; 662 } 663 664 static EmulateInstructionInstances & 665 GetEmulateInstructionInstances () 666 { 667 static EmulateInstructionInstances g_instances; 668 return g_instances; 669 } 670 671 bool 672 PluginManager::RegisterPlugin(const ConstString &name, 673 const char *description, 674 EmulateInstructionCreateInstance create_callback) 675 { 676 if (create_callback) 677 { 678 EmulateInstructionInstance instance; 679 assert ((bool)name); 680 instance.name = name; 681 if (description && description[0]) 682 instance.description = description; 683 instance.create_callback = create_callback; 684 Mutex::Locker locker (GetEmulateInstructionMutex ()); 685 GetEmulateInstructionInstances ().push_back (instance); 686 } 687 return false; 688 } 689 690 bool 691 PluginManager::UnregisterPlugin (EmulateInstructionCreateInstance create_callback) 692 { 693 if (create_callback) 694 { 695 Mutex::Locker locker (GetEmulateInstructionMutex ()); 696 EmulateInstructionInstances &instances = GetEmulateInstructionInstances (); 697 698 EmulateInstructionInstances::iterator pos, end = instances.end(); 699 for (pos = instances.begin(); pos != end; ++ pos) 700 { 701 if (pos->create_callback == create_callback) 702 { 703 instances.erase(pos); 704 return true; 705 } 706 } 707 } 708 return false; 709 } 710 711 EmulateInstructionCreateInstance 712 PluginManager::GetEmulateInstructionCreateCallbackAtIndex (uint32_t idx) 713 { 714 Mutex::Locker locker (GetEmulateInstructionMutex ()); 715 EmulateInstructionInstances &instances = GetEmulateInstructionInstances (); 716 if (idx < instances.size()) 717 return instances[idx].create_callback; 718 return nullptr; 719 } 720 721 EmulateInstructionCreateInstance 722 PluginManager::GetEmulateInstructionCreateCallbackForPluginName (const ConstString &name) 723 { 724 if (name) 725 { 726 Mutex::Locker locker (GetEmulateInstructionMutex ()); 727 EmulateInstructionInstances &instances = GetEmulateInstructionInstances (); 728 729 EmulateInstructionInstances::iterator pos, end = instances.end(); 730 for (pos = instances.begin(); pos != end; ++ pos) 731 { 732 if (name == pos->name) 733 return pos->create_callback; 734 } 735 } 736 return nullptr; 737 } 738 739 #pragma mark OperatingSystem 740 741 struct OperatingSystemInstance 742 { 743 OperatingSystemInstance () : 744 name (), 745 description (), 746 create_callback (nullptr), 747 debugger_init_callback (nullptr) 748 { 749 } 750 751 ConstString name; 752 std::string description; 753 OperatingSystemCreateInstance create_callback; 754 DebuggerInitializeCallback debugger_init_callback; 755 }; 756 757 typedef std::vector<OperatingSystemInstance> OperatingSystemInstances; 758 759 static Mutex & 760 GetOperatingSystemMutex () 761 { 762 static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive); 763 return g_instances_mutex; 764 } 765 766 static OperatingSystemInstances & 767 GetOperatingSystemInstances () 768 { 769 static OperatingSystemInstances g_instances; 770 return g_instances; 771 } 772 773 bool 774 PluginManager::RegisterPlugin(const ConstString &name, const char *description, 775 OperatingSystemCreateInstance create_callback, 776 DebuggerInitializeCallback debugger_init_callback) 777 { 778 if (create_callback) 779 { 780 OperatingSystemInstance instance; 781 assert ((bool)name); 782 instance.name = name; 783 if (description && description[0]) 784 instance.description = description; 785 instance.create_callback = create_callback; 786 instance.debugger_init_callback = debugger_init_callback; 787 Mutex::Locker locker (GetOperatingSystemMutex ()); 788 GetOperatingSystemInstances ().push_back (instance); 789 } 790 return false; 791 } 792 793 bool 794 PluginManager::UnregisterPlugin (OperatingSystemCreateInstance create_callback) 795 { 796 if (create_callback) 797 { 798 Mutex::Locker locker (GetOperatingSystemMutex ()); 799 OperatingSystemInstances &instances = GetOperatingSystemInstances (); 800 801 OperatingSystemInstances::iterator pos, end = instances.end(); 802 for (pos = instances.begin(); pos != end; ++ pos) 803 { 804 if (pos->create_callback == create_callback) 805 { 806 instances.erase(pos); 807 return true; 808 } 809 } 810 } 811 return false; 812 } 813 814 OperatingSystemCreateInstance 815 PluginManager::GetOperatingSystemCreateCallbackAtIndex (uint32_t idx) 816 { 817 Mutex::Locker locker (GetOperatingSystemMutex ()); 818 OperatingSystemInstances &instances = GetOperatingSystemInstances (); 819 if (idx < instances.size()) 820 return instances[idx].create_callback; 821 return nullptr; 822 } 823 824 OperatingSystemCreateInstance 825 PluginManager::GetOperatingSystemCreateCallbackForPluginName (const ConstString &name) 826 { 827 if (name) 828 { 829 Mutex::Locker locker (GetOperatingSystemMutex ()); 830 OperatingSystemInstances &instances = GetOperatingSystemInstances (); 831 832 OperatingSystemInstances::iterator pos, end = instances.end(); 833 for (pos = instances.begin(); pos != end; ++ pos) 834 { 835 if (name == pos->name) 836 return pos->create_callback; 837 } 838 } 839 return nullptr; 840 } 841 842 #pragma mark Language 843 844 struct LanguageInstance 845 { 846 LanguageInstance() : 847 name(), 848 description(), 849 create_callback(nullptr) 850 { 851 } 852 853 ConstString name; 854 std::string description; 855 LanguageCreateInstance create_callback; 856 }; 857 858 typedef std::vector<LanguageInstance> LanguageInstances; 859 860 static Mutex & 861 GetLanguageMutex () 862 { 863 static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive); 864 return g_instances_mutex; 865 } 866 867 static LanguageInstances & 868 GetLanguageInstances () 869 { 870 static LanguageInstances g_instances; 871 return g_instances; 872 } 873 874 bool 875 PluginManager::RegisterPlugin(const ConstString &name, 876 const char *description, 877 LanguageCreateInstance create_callback) 878 { 879 if (create_callback) 880 { 881 LanguageInstance instance; 882 assert ((bool)name); 883 instance.name = name; 884 if (description && description[0]) 885 instance.description = description; 886 instance.create_callback = create_callback; 887 Mutex::Locker locker (GetLanguageMutex ()); 888 GetLanguageInstances ().push_back (instance); 889 } 890 return false; 891 } 892 893 bool 894 PluginManager::UnregisterPlugin (LanguageCreateInstance create_callback) 895 { 896 if (create_callback) 897 { 898 Mutex::Locker locker (GetLanguageMutex ()); 899 LanguageInstances &instances = GetLanguageInstances (); 900 901 LanguageInstances::iterator pos, end = instances.end(); 902 for (pos = instances.begin(); pos != end; ++ pos) 903 { 904 if (pos->create_callback == create_callback) 905 { 906 instances.erase(pos); 907 return true; 908 } 909 } 910 } 911 return false; 912 } 913 914 LanguageCreateInstance 915 PluginManager::GetLanguageCreateCallbackAtIndex (uint32_t idx) 916 { 917 Mutex::Locker locker (GetLanguageMutex ()); 918 LanguageInstances &instances = GetLanguageInstances (); 919 if (idx < instances.size()) 920 return instances[idx].create_callback; 921 return nullptr; 922 } 923 924 LanguageCreateInstance 925 PluginManager::GetLanguageCreateCallbackForPluginName (const ConstString &name) 926 { 927 if (name) 928 { 929 Mutex::Locker locker (GetLanguageMutex ()); 930 LanguageInstances &instances = GetLanguageInstances (); 931 932 LanguageInstances::iterator pos, end = instances.end(); 933 for (pos = instances.begin(); pos != end; ++ pos) 934 { 935 if (name == pos->name) 936 return pos->create_callback; 937 } 938 } 939 return nullptr; 940 } 941 942 #pragma mark LanguageRuntime 943 944 struct LanguageRuntimeInstance 945 { 946 LanguageRuntimeInstance() : 947 name(), 948 description(), 949 create_callback(nullptr) 950 { 951 } 952 953 ConstString name; 954 std::string description; 955 LanguageRuntimeCreateInstance create_callback; 956 LanguageRuntimeGetCommandObject command_callback; 957 }; 958 959 typedef std::vector<LanguageRuntimeInstance> LanguageRuntimeInstances; 960 961 static Mutex & 962 GetLanguageRuntimeMutex () 963 { 964 static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive); 965 return g_instances_mutex; 966 } 967 968 static LanguageRuntimeInstances & 969 GetLanguageRuntimeInstances () 970 { 971 static LanguageRuntimeInstances g_instances; 972 return g_instances; 973 } 974 975 bool 976 PluginManager::RegisterPlugin(const ConstString &name, 977 const char *description, 978 LanguageRuntimeCreateInstance create_callback, 979 LanguageRuntimeGetCommandObject command_callback) 980 { 981 if (create_callback) 982 { 983 LanguageRuntimeInstance instance; 984 assert ((bool)name); 985 instance.name = name; 986 if (description && description[0]) 987 instance.description = description; 988 instance.create_callback = create_callback; 989 instance.command_callback = command_callback; 990 Mutex::Locker locker (GetLanguageRuntimeMutex ()); 991 GetLanguageRuntimeInstances ().push_back (instance); 992 } 993 return false; 994 } 995 996 bool 997 PluginManager::UnregisterPlugin (LanguageRuntimeCreateInstance create_callback) 998 { 999 if (create_callback) 1000 { 1001 Mutex::Locker locker (GetLanguageRuntimeMutex ()); 1002 LanguageRuntimeInstances &instances = GetLanguageRuntimeInstances (); 1003 1004 LanguageRuntimeInstances::iterator pos, end = instances.end(); 1005 for (pos = instances.begin(); pos != end; ++ pos) 1006 { 1007 if (pos->create_callback == create_callback) 1008 { 1009 instances.erase(pos); 1010 return true; 1011 } 1012 } 1013 } 1014 return false; 1015 } 1016 1017 LanguageRuntimeCreateInstance 1018 PluginManager::GetLanguageRuntimeCreateCallbackAtIndex (uint32_t idx) 1019 { 1020 Mutex::Locker locker (GetLanguageRuntimeMutex ()); 1021 LanguageRuntimeInstances &instances = GetLanguageRuntimeInstances (); 1022 if (idx < instances.size()) 1023 return instances[idx].create_callback; 1024 return nullptr; 1025 } 1026 1027 LanguageRuntimeGetCommandObject 1028 PluginManager::GetLanguageRuntimeGetCommandObjectAtIndex (uint32_t idx) 1029 { 1030 Mutex::Locker locker (GetLanguageRuntimeMutex ()); 1031 LanguageRuntimeInstances &instances = GetLanguageRuntimeInstances (); 1032 if (idx < instances.size()) 1033 return instances[idx].command_callback; 1034 return nullptr; 1035 } 1036 1037 LanguageRuntimeCreateInstance 1038 PluginManager::GetLanguageRuntimeCreateCallbackForPluginName (const ConstString &name) 1039 { 1040 if (name) 1041 { 1042 Mutex::Locker locker (GetLanguageRuntimeMutex ()); 1043 LanguageRuntimeInstances &instances = GetLanguageRuntimeInstances (); 1044 1045 LanguageRuntimeInstances::iterator pos, end = instances.end(); 1046 for (pos = instances.begin(); pos != end; ++ pos) 1047 { 1048 if (name == pos->name) 1049 return pos->create_callback; 1050 } 1051 } 1052 return nullptr; 1053 } 1054 1055 #pragma mark SystemRuntime 1056 1057 struct SystemRuntimeInstance 1058 { 1059 SystemRuntimeInstance() : 1060 name(), 1061 description(), 1062 create_callback(nullptr) 1063 { 1064 } 1065 1066 ConstString name; 1067 std::string description; 1068 SystemRuntimeCreateInstance create_callback; 1069 }; 1070 1071 typedef std::vector<SystemRuntimeInstance> SystemRuntimeInstances; 1072 1073 static Mutex & 1074 GetSystemRuntimeMutex () 1075 { 1076 static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive); 1077 return g_instances_mutex; 1078 } 1079 1080 static SystemRuntimeInstances & 1081 GetSystemRuntimeInstances () 1082 { 1083 static SystemRuntimeInstances g_instances; 1084 return g_instances; 1085 } 1086 1087 bool 1088 PluginManager::RegisterPlugin(const ConstString &name, 1089 const char *description, 1090 SystemRuntimeCreateInstance create_callback) 1091 { 1092 if (create_callback) 1093 { 1094 SystemRuntimeInstance instance; 1095 assert ((bool)name); 1096 instance.name = name; 1097 if (description && description[0]) 1098 instance.description = description; 1099 instance.create_callback = create_callback; 1100 Mutex::Locker locker (GetSystemRuntimeMutex ()); 1101 GetSystemRuntimeInstances ().push_back (instance); 1102 } 1103 return false; 1104 } 1105 1106 bool 1107 PluginManager::UnregisterPlugin (SystemRuntimeCreateInstance create_callback) 1108 { 1109 if (create_callback) 1110 { 1111 Mutex::Locker locker (GetSystemRuntimeMutex ()); 1112 SystemRuntimeInstances &instances = GetSystemRuntimeInstances (); 1113 1114 SystemRuntimeInstances::iterator pos, end = instances.end(); 1115 for (pos = instances.begin(); pos != end; ++ pos) 1116 { 1117 if (pos->create_callback == create_callback) 1118 { 1119 instances.erase(pos); 1120 return true; 1121 } 1122 } 1123 } 1124 return false; 1125 } 1126 1127 SystemRuntimeCreateInstance 1128 PluginManager::GetSystemRuntimeCreateCallbackAtIndex (uint32_t idx) 1129 { 1130 Mutex::Locker locker (GetSystemRuntimeMutex ()); 1131 SystemRuntimeInstances &instances = GetSystemRuntimeInstances (); 1132 if (idx < instances.size()) 1133 return instances[idx].create_callback; 1134 return nullptr; 1135 } 1136 1137 SystemRuntimeCreateInstance 1138 PluginManager::GetSystemRuntimeCreateCallbackForPluginName (const ConstString &name) 1139 { 1140 if (name) 1141 { 1142 Mutex::Locker locker (GetSystemRuntimeMutex ()); 1143 SystemRuntimeInstances &instances = GetSystemRuntimeInstances (); 1144 1145 SystemRuntimeInstances::iterator pos, end = instances.end(); 1146 for (pos = instances.begin(); pos != end; ++ pos) 1147 { 1148 if (name == pos->name) 1149 return pos->create_callback; 1150 } 1151 } 1152 return nullptr; 1153 } 1154 1155 #pragma mark ObjectFile 1156 1157 struct ObjectFileInstance 1158 { 1159 ObjectFileInstance() : 1160 name(), 1161 description(), 1162 create_callback(nullptr), 1163 create_memory_callback(nullptr), 1164 get_module_specifications(nullptr), 1165 save_core(nullptr) 1166 { 1167 } 1168 1169 ConstString name; 1170 std::string description; 1171 ObjectFileCreateInstance create_callback; 1172 ObjectFileCreateMemoryInstance create_memory_callback; 1173 ObjectFileGetModuleSpecifications get_module_specifications; 1174 ObjectFileSaveCore save_core; 1175 }; 1176 1177 typedef std::vector<ObjectFileInstance> ObjectFileInstances; 1178 1179 static Mutex & 1180 GetObjectFileMutex () 1181 { 1182 static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive); 1183 return g_instances_mutex; 1184 } 1185 1186 static ObjectFileInstances & 1187 GetObjectFileInstances () 1188 { 1189 static ObjectFileInstances g_instances; 1190 return g_instances; 1191 } 1192 1193 bool 1194 PluginManager::RegisterPlugin (const ConstString &name, 1195 const char *description, 1196 ObjectFileCreateInstance create_callback, 1197 ObjectFileCreateMemoryInstance create_memory_callback, 1198 ObjectFileGetModuleSpecifications get_module_specifications, 1199 ObjectFileSaveCore save_core) 1200 { 1201 if (create_callback) 1202 { 1203 ObjectFileInstance instance; 1204 assert ((bool)name); 1205 instance.name = name; 1206 if (description && description[0]) 1207 instance.description = description; 1208 instance.create_callback = create_callback; 1209 instance.create_memory_callback = create_memory_callback; 1210 instance.save_core = save_core; 1211 instance.get_module_specifications = get_module_specifications; 1212 Mutex::Locker locker (GetObjectFileMutex ()); 1213 GetObjectFileInstances ().push_back (instance); 1214 } 1215 return false; 1216 } 1217 1218 bool 1219 PluginManager::UnregisterPlugin (ObjectFileCreateInstance create_callback) 1220 { 1221 if (create_callback) 1222 { 1223 Mutex::Locker locker (GetObjectFileMutex ()); 1224 ObjectFileInstances &instances = GetObjectFileInstances (); 1225 1226 ObjectFileInstances::iterator pos, end = instances.end(); 1227 for (pos = instances.begin(); pos != end; ++ pos) 1228 { 1229 if (pos->create_callback == create_callback) 1230 { 1231 instances.erase(pos); 1232 return true; 1233 } 1234 } 1235 } 1236 return false; 1237 } 1238 1239 ObjectFileCreateInstance 1240 PluginManager::GetObjectFileCreateCallbackAtIndex (uint32_t idx) 1241 { 1242 Mutex::Locker locker (GetObjectFileMutex ()); 1243 ObjectFileInstances &instances = GetObjectFileInstances (); 1244 if (idx < instances.size()) 1245 return instances[idx].create_callback; 1246 return nullptr; 1247 } 1248 1249 ObjectFileCreateMemoryInstance 1250 PluginManager::GetObjectFileCreateMemoryCallbackAtIndex (uint32_t idx) 1251 { 1252 Mutex::Locker locker (GetObjectFileMutex ()); 1253 ObjectFileInstances &instances = GetObjectFileInstances (); 1254 if (idx < instances.size()) 1255 return instances[idx].create_memory_callback; 1256 return nullptr; 1257 } 1258 1259 ObjectFileGetModuleSpecifications 1260 PluginManager::GetObjectFileGetModuleSpecificationsCallbackAtIndex (uint32_t idx) 1261 { 1262 Mutex::Locker locker (GetObjectFileMutex ()); 1263 ObjectFileInstances &instances = GetObjectFileInstances (); 1264 if (idx < instances.size()) 1265 return instances[idx].get_module_specifications; 1266 return nullptr; 1267 } 1268 1269 ObjectFileCreateInstance 1270 PluginManager::GetObjectFileCreateCallbackForPluginName (const ConstString &name) 1271 { 1272 if (name) 1273 { 1274 Mutex::Locker locker (GetObjectFileMutex ()); 1275 ObjectFileInstances &instances = GetObjectFileInstances (); 1276 1277 ObjectFileInstances::iterator pos, end = instances.end(); 1278 for (pos = instances.begin(); pos != end; ++ pos) 1279 { 1280 if (name == pos->name) 1281 return pos->create_callback; 1282 } 1283 } 1284 return nullptr; 1285 } 1286 1287 ObjectFileCreateMemoryInstance 1288 PluginManager::GetObjectFileCreateMemoryCallbackForPluginName (const ConstString &name) 1289 { 1290 if (name) 1291 { 1292 Mutex::Locker locker (GetObjectFileMutex ()); 1293 ObjectFileInstances &instances = GetObjectFileInstances (); 1294 1295 ObjectFileInstances::iterator pos, end = instances.end(); 1296 for (pos = instances.begin(); pos != end; ++ pos) 1297 { 1298 if (name == pos->name) 1299 return pos->create_memory_callback; 1300 } 1301 } 1302 return nullptr; 1303 } 1304 1305 Error 1306 PluginManager::SaveCore (const lldb::ProcessSP &process_sp, const FileSpec &outfile) 1307 { 1308 Error error; 1309 Mutex::Locker locker (GetObjectFileMutex ()); 1310 ObjectFileInstances &instances = GetObjectFileInstances (); 1311 1312 ObjectFileInstances::iterator pos, end = instances.end(); 1313 for (pos = instances.begin(); pos != end; ++ pos) 1314 { 1315 if (pos->save_core && pos->save_core (process_sp, outfile, error)) 1316 return error; 1317 } 1318 error.SetErrorString("no ObjectFile plugins were able to save a core for this process"); 1319 return error; 1320 } 1321 1322 #pragma mark ObjectContainer 1323 1324 struct ObjectContainerInstance 1325 { 1326 ObjectContainerInstance() : 1327 name(), 1328 description(), 1329 create_callback(nullptr), 1330 get_module_specifications(nullptr) 1331 { 1332 } 1333 1334 ConstString name; 1335 std::string description; 1336 ObjectContainerCreateInstance create_callback; 1337 ObjectFileGetModuleSpecifications get_module_specifications; 1338 }; 1339 1340 typedef std::vector<ObjectContainerInstance> ObjectContainerInstances; 1341 1342 static Mutex & 1343 GetObjectContainerMutex () 1344 { 1345 static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive); 1346 return g_instances_mutex; 1347 } 1348 1349 static ObjectContainerInstances & 1350 GetObjectContainerInstances () 1351 { 1352 static ObjectContainerInstances g_instances; 1353 return g_instances; 1354 } 1355 1356 bool 1357 PluginManager::RegisterPlugin (const ConstString &name, 1358 const char *description, 1359 ObjectContainerCreateInstance create_callback, 1360 ObjectFileGetModuleSpecifications get_module_specifications) 1361 { 1362 if (create_callback) 1363 { 1364 ObjectContainerInstance instance; 1365 assert ((bool)name); 1366 instance.name = name; 1367 if (description && description[0]) 1368 instance.description = description; 1369 instance.create_callback = create_callback; 1370 instance.get_module_specifications = get_module_specifications; 1371 Mutex::Locker locker (GetObjectContainerMutex ()); 1372 GetObjectContainerInstances ().push_back (instance); 1373 } 1374 return false; 1375 } 1376 1377 bool 1378 PluginManager::UnregisterPlugin (ObjectContainerCreateInstance create_callback) 1379 { 1380 if (create_callback) 1381 { 1382 Mutex::Locker locker (GetObjectContainerMutex ()); 1383 ObjectContainerInstances &instances = GetObjectContainerInstances (); 1384 1385 ObjectContainerInstances::iterator pos, end = instances.end(); 1386 for (pos = instances.begin(); pos != end; ++ pos) 1387 { 1388 if (pos->create_callback == create_callback) 1389 { 1390 instances.erase(pos); 1391 return true; 1392 } 1393 } 1394 } 1395 return false; 1396 } 1397 1398 ObjectContainerCreateInstance 1399 PluginManager::GetObjectContainerCreateCallbackAtIndex (uint32_t idx) 1400 { 1401 Mutex::Locker locker (GetObjectContainerMutex ()); 1402 ObjectContainerInstances &instances = GetObjectContainerInstances (); 1403 if (idx < instances.size()) 1404 return instances[idx].create_callback; 1405 return nullptr; 1406 } 1407 1408 ObjectContainerCreateInstance 1409 PluginManager::GetObjectContainerCreateCallbackForPluginName (const ConstString &name) 1410 { 1411 if (name) 1412 { 1413 Mutex::Locker locker (GetObjectContainerMutex ()); 1414 ObjectContainerInstances &instances = GetObjectContainerInstances (); 1415 1416 ObjectContainerInstances::iterator pos, end = instances.end(); 1417 for (pos = instances.begin(); pos != end; ++ pos) 1418 { 1419 if (name == pos->name) 1420 return pos->create_callback; 1421 } 1422 } 1423 return nullptr; 1424 } 1425 1426 ObjectFileGetModuleSpecifications 1427 PluginManager::GetObjectContainerGetModuleSpecificationsCallbackAtIndex (uint32_t idx) 1428 { 1429 Mutex::Locker locker (GetObjectContainerMutex ()); 1430 ObjectContainerInstances &instances = GetObjectContainerInstances (); 1431 if (idx < instances.size()) 1432 return instances[idx].get_module_specifications; 1433 return nullptr; 1434 } 1435 1436 #pragma mark LogChannel 1437 1438 struct LogInstance 1439 { 1440 LogInstance() : 1441 name(), 1442 description(), 1443 create_callback(nullptr) 1444 { 1445 } 1446 1447 ConstString name; 1448 std::string description; 1449 LogChannelCreateInstance create_callback; 1450 }; 1451 1452 typedef std::vector<LogInstance> LogInstances; 1453 1454 static Mutex & 1455 GetLogMutex () 1456 { 1457 static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive); 1458 return g_instances_mutex; 1459 } 1460 1461 static LogInstances & 1462 GetLogInstances () 1463 { 1464 static LogInstances g_instances; 1465 return g_instances; 1466 } 1467 1468 bool 1469 PluginManager::RegisterPlugin(const ConstString &name, 1470 const char *description, 1471 LogChannelCreateInstance create_callback) 1472 { 1473 if (create_callback) 1474 { 1475 LogInstance instance; 1476 assert ((bool)name); 1477 instance.name = name; 1478 if (description && description[0]) 1479 instance.description = description; 1480 instance.create_callback = create_callback; 1481 Mutex::Locker locker (GetLogMutex ()); 1482 GetLogInstances ().push_back (instance); 1483 } 1484 return false; 1485 } 1486 1487 bool 1488 PluginManager::UnregisterPlugin (LogChannelCreateInstance create_callback) 1489 { 1490 if (create_callback) 1491 { 1492 Mutex::Locker locker (GetLogMutex ()); 1493 LogInstances &instances = GetLogInstances (); 1494 1495 LogInstances::iterator pos, end = instances.end(); 1496 for (pos = instances.begin(); pos != end; ++ pos) 1497 { 1498 if (pos->create_callback == create_callback) 1499 { 1500 instances.erase(pos); 1501 return true; 1502 } 1503 } 1504 } 1505 return false; 1506 } 1507 1508 const char * 1509 PluginManager::GetLogChannelCreateNameAtIndex (uint32_t idx) 1510 { 1511 Mutex::Locker locker (GetLogMutex ()); 1512 LogInstances &instances = GetLogInstances (); 1513 if (idx < instances.size()) 1514 return instances[idx].name.GetCString(); 1515 return nullptr; 1516 } 1517 1518 LogChannelCreateInstance 1519 PluginManager::GetLogChannelCreateCallbackAtIndex (uint32_t idx) 1520 { 1521 Mutex::Locker locker (GetLogMutex ()); 1522 LogInstances &instances = GetLogInstances (); 1523 if (idx < instances.size()) 1524 return instances[idx].create_callback; 1525 return nullptr; 1526 } 1527 1528 LogChannelCreateInstance 1529 PluginManager::GetLogChannelCreateCallbackForPluginName (const ConstString &name) 1530 { 1531 if (name) 1532 { 1533 Mutex::Locker locker (GetLogMutex ()); 1534 LogInstances &instances = GetLogInstances (); 1535 1536 LogInstances::iterator pos, end = instances.end(); 1537 for (pos = instances.begin(); pos != end; ++ pos) 1538 { 1539 if (name == pos->name) 1540 return pos->create_callback; 1541 } 1542 } 1543 return nullptr; 1544 } 1545 1546 #pragma mark Platform 1547 1548 struct PlatformInstance 1549 { 1550 PlatformInstance() : 1551 name(), 1552 description(), 1553 create_callback(nullptr), 1554 debugger_init_callback(nullptr) 1555 { 1556 } 1557 1558 ConstString name; 1559 std::string description; 1560 PlatformCreateInstance create_callback; 1561 DebuggerInitializeCallback debugger_init_callback; 1562 }; 1563 1564 typedef std::vector<PlatformInstance> PlatformInstances; 1565 1566 static Mutex & 1567 GetPlatformInstancesMutex () 1568 { 1569 static Mutex g_platform_instances_mutex (Mutex::eMutexTypeRecursive); 1570 return g_platform_instances_mutex; 1571 } 1572 1573 static PlatformInstances & 1574 GetPlatformInstances () 1575 { 1576 static PlatformInstances g_platform_instances; 1577 return g_platform_instances; 1578 } 1579 1580 bool 1581 PluginManager::RegisterPlugin (const ConstString &name, 1582 const char *description, 1583 PlatformCreateInstance create_callback, 1584 DebuggerInitializeCallback debugger_init_callback) 1585 { 1586 if (create_callback) 1587 { 1588 Mutex::Locker locker (GetPlatformInstancesMutex ()); 1589 1590 PlatformInstance instance; 1591 assert ((bool)name); 1592 instance.name = name; 1593 if (description && description[0]) 1594 instance.description = description; 1595 instance.create_callback = create_callback; 1596 instance.debugger_init_callback = debugger_init_callback; 1597 GetPlatformInstances ().push_back (instance); 1598 return true; 1599 } 1600 return false; 1601 } 1602 1603 const char * 1604 PluginManager::GetPlatformPluginNameAtIndex (uint32_t idx) 1605 { 1606 Mutex::Locker locker (GetPlatformInstancesMutex ()); 1607 PlatformInstances &instances = GetPlatformInstances (); 1608 if (idx < instances.size()) 1609 return instances[idx].name.GetCString(); 1610 return nullptr; 1611 } 1612 1613 const char * 1614 PluginManager::GetPlatformPluginDescriptionAtIndex (uint32_t idx) 1615 { 1616 Mutex::Locker locker (GetPlatformInstancesMutex ()); 1617 PlatformInstances &instances = GetPlatformInstances (); 1618 if (idx < instances.size()) 1619 return instances[idx].description.c_str(); 1620 return nullptr; 1621 } 1622 1623 bool 1624 PluginManager::UnregisterPlugin (PlatformCreateInstance create_callback) 1625 { 1626 if (create_callback) 1627 { 1628 Mutex::Locker locker (GetPlatformInstancesMutex ()); 1629 PlatformInstances &instances = GetPlatformInstances (); 1630 1631 PlatformInstances::iterator pos, end = instances.end(); 1632 for (pos = instances.begin(); pos != end; ++ pos) 1633 { 1634 if (pos->create_callback == create_callback) 1635 { 1636 instances.erase(pos); 1637 return true; 1638 } 1639 } 1640 } 1641 return false; 1642 } 1643 1644 PlatformCreateInstance 1645 PluginManager::GetPlatformCreateCallbackAtIndex (uint32_t idx) 1646 { 1647 Mutex::Locker locker (GetPlatformInstancesMutex ()); 1648 PlatformInstances &instances = GetPlatformInstances (); 1649 if (idx < instances.size()) 1650 return instances[idx].create_callback; 1651 return nullptr; 1652 } 1653 1654 PlatformCreateInstance 1655 PluginManager::GetPlatformCreateCallbackForPluginName (const ConstString &name) 1656 { 1657 if (name) 1658 { 1659 Mutex::Locker locker (GetPlatformInstancesMutex ()); 1660 PlatformInstances &instances = GetPlatformInstances (); 1661 1662 PlatformInstances::iterator pos, end = instances.end(); 1663 for (pos = instances.begin(); pos != end; ++ pos) 1664 { 1665 if (name == pos->name) 1666 return pos->create_callback; 1667 } 1668 } 1669 return nullptr; 1670 } 1671 1672 size_t 1673 PluginManager::AutoCompletePlatformName (const char *name, StringList &matches) 1674 { 1675 if (name) 1676 { 1677 Mutex::Locker locker (GetPlatformInstancesMutex ()); 1678 PlatformInstances &instances = GetPlatformInstances (); 1679 llvm::StringRef name_sref(name); 1680 1681 PlatformInstances::iterator pos, end = instances.end(); 1682 for (pos = instances.begin(); pos != end; ++ pos) 1683 { 1684 llvm::StringRef plugin_name (pos->name.GetCString()); 1685 if (plugin_name.startswith(name_sref)) 1686 matches.AppendString (plugin_name.data()); 1687 } 1688 } 1689 return matches.GetSize(); 1690 } 1691 1692 #pragma mark Process 1693 1694 struct ProcessInstance 1695 { 1696 ProcessInstance() : 1697 name(), 1698 description(), 1699 create_callback(nullptr), 1700 debugger_init_callback(nullptr) 1701 { 1702 } 1703 1704 ConstString name; 1705 std::string description; 1706 ProcessCreateInstance create_callback; 1707 DebuggerInitializeCallback debugger_init_callback; 1708 }; 1709 1710 typedef std::vector<ProcessInstance> ProcessInstances; 1711 1712 static Mutex & 1713 GetProcessMutex () 1714 { 1715 static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive); 1716 return g_instances_mutex; 1717 } 1718 1719 static ProcessInstances & 1720 GetProcessInstances () 1721 { 1722 static ProcessInstances g_instances; 1723 return g_instances; 1724 } 1725 1726 bool 1727 PluginManager::RegisterPlugin (const ConstString &name, 1728 const char *description, 1729 ProcessCreateInstance create_callback, 1730 DebuggerInitializeCallback debugger_init_callback) 1731 { 1732 if (create_callback) 1733 { 1734 ProcessInstance instance; 1735 assert ((bool)name); 1736 instance.name = name; 1737 if (description && description[0]) 1738 instance.description = description; 1739 instance.create_callback = create_callback; 1740 instance.debugger_init_callback = debugger_init_callback; 1741 Mutex::Locker locker (GetProcessMutex ()); 1742 GetProcessInstances ().push_back (instance); 1743 } 1744 return false; 1745 } 1746 1747 const char * 1748 PluginManager::GetProcessPluginNameAtIndex (uint32_t idx) 1749 { 1750 Mutex::Locker locker (GetProcessMutex ()); 1751 ProcessInstances &instances = GetProcessInstances (); 1752 if (idx < instances.size()) 1753 return instances[idx].name.GetCString(); 1754 return nullptr; 1755 } 1756 1757 const char * 1758 PluginManager::GetProcessPluginDescriptionAtIndex (uint32_t idx) 1759 { 1760 Mutex::Locker locker (GetProcessMutex ()); 1761 ProcessInstances &instances = GetProcessInstances (); 1762 if (idx < instances.size()) 1763 return instances[idx].description.c_str(); 1764 return nullptr; 1765 } 1766 1767 bool 1768 PluginManager::UnregisterPlugin (ProcessCreateInstance create_callback) 1769 { 1770 if (create_callback) 1771 { 1772 Mutex::Locker locker (GetProcessMutex ()); 1773 ProcessInstances &instances = GetProcessInstances (); 1774 1775 ProcessInstances::iterator pos, end = instances.end(); 1776 for (pos = instances.begin(); pos != end; ++ pos) 1777 { 1778 if (pos->create_callback == create_callback) 1779 { 1780 instances.erase(pos); 1781 return true; 1782 } 1783 } 1784 } 1785 return false; 1786 } 1787 1788 ProcessCreateInstance 1789 PluginManager::GetProcessCreateCallbackAtIndex (uint32_t idx) 1790 { 1791 Mutex::Locker locker (GetProcessMutex ()); 1792 ProcessInstances &instances = GetProcessInstances (); 1793 if (idx < instances.size()) 1794 return instances[idx].create_callback; 1795 return nullptr; 1796 } 1797 1798 ProcessCreateInstance 1799 PluginManager::GetProcessCreateCallbackForPluginName (const ConstString &name) 1800 { 1801 if (name) 1802 { 1803 Mutex::Locker locker (GetProcessMutex ()); 1804 ProcessInstances &instances = GetProcessInstances (); 1805 1806 ProcessInstances::iterator pos, end = instances.end(); 1807 for (pos = instances.begin(); pos != end; ++ pos) 1808 { 1809 if (name == pos->name) 1810 return pos->create_callback; 1811 } 1812 } 1813 return nullptr; 1814 } 1815 1816 #pragma mark ScriptInterpreter 1817 1818 struct ScriptInterpreterInstance 1819 { 1820 ScriptInterpreterInstance() 1821 : name() 1822 , language(lldb::eScriptLanguageNone) 1823 , description() 1824 , create_callback(nullptr) 1825 { 1826 } 1827 1828 ConstString name; 1829 lldb::ScriptLanguage language; 1830 std::string description; 1831 ScriptInterpreterCreateInstance create_callback; 1832 }; 1833 1834 typedef std::vector<ScriptInterpreterInstance> ScriptInterpreterInstances; 1835 1836 static Mutex & 1837 GetScriptInterpreterMutex() 1838 { 1839 static Mutex g_instances_mutex(Mutex::eMutexTypeRecursive); 1840 return g_instances_mutex; 1841 } 1842 1843 static ScriptInterpreterInstances & 1844 GetScriptInterpreterInstances() 1845 { 1846 static ScriptInterpreterInstances g_instances; 1847 return g_instances; 1848 } 1849 1850 bool 1851 PluginManager::RegisterPlugin(const ConstString &name, const char *description, lldb::ScriptLanguage script_language, 1852 ScriptInterpreterCreateInstance create_callback) 1853 { 1854 if (!create_callback) 1855 return false; 1856 ScriptInterpreterInstance instance; 1857 assert((bool)name); 1858 instance.name = name; 1859 if (description && description[0]) 1860 instance.description = description; 1861 instance.create_callback = create_callback; 1862 instance.language = script_language; 1863 Mutex::Locker locker(GetScriptInterpreterMutex()); 1864 GetScriptInterpreterInstances().push_back(instance); 1865 return false; 1866 } 1867 1868 bool 1869 PluginManager::UnregisterPlugin(ScriptInterpreterCreateInstance create_callback) 1870 { 1871 if (!create_callback) 1872 return false; 1873 Mutex::Locker locker(GetScriptInterpreterMutex()); 1874 ScriptInterpreterInstances &instances = GetScriptInterpreterInstances(); 1875 1876 ScriptInterpreterInstances::iterator pos, end = instances.end(); 1877 for (pos = instances.begin(); pos != end; ++pos) 1878 { 1879 if (pos->create_callback != create_callback) 1880 continue; 1881 1882 instances.erase(pos); 1883 return true; 1884 } 1885 return false; 1886 } 1887 1888 ScriptInterpreterCreateInstance 1889 PluginManager::GetScriptInterpreterCreateCallbackAtIndex(uint32_t idx) 1890 { 1891 Mutex::Locker locker(GetScriptInterpreterMutex()); 1892 ScriptInterpreterInstances &instances = GetScriptInterpreterInstances(); 1893 if (idx < instances.size()) 1894 return instances[idx].create_callback; 1895 return nullptr; 1896 } 1897 1898 lldb::ScriptInterpreterSP 1899 PluginManager::GetScriptInterpreterForLanguage(lldb::ScriptLanguage script_lang, CommandInterpreter &interpreter) 1900 { 1901 Mutex::Locker locker(GetScriptInterpreterMutex()); 1902 ScriptInterpreterInstances &instances = GetScriptInterpreterInstances(); 1903 1904 ScriptInterpreterInstances::iterator pos, end = instances.end(); 1905 ScriptInterpreterCreateInstance none_instance = nullptr; 1906 for (pos = instances.begin(); pos != end; ++pos) 1907 { 1908 if (pos->language == lldb::eScriptLanguageNone) 1909 none_instance = pos->create_callback; 1910 1911 if (script_lang == pos->language) 1912 return pos->create_callback(interpreter); 1913 } 1914 1915 // If we didn't find one, return the ScriptInterpreter for the null language. 1916 assert(none_instance != nullptr); 1917 return none_instance(interpreter); 1918 } 1919 1920 #pragma mark SymbolFile 1921 1922 struct SymbolFileInstance 1923 { 1924 SymbolFileInstance() : 1925 name(), 1926 description(), 1927 create_callback(nullptr), 1928 debugger_init_callback(nullptr) 1929 { 1930 } 1931 1932 ConstString name; 1933 std::string description; 1934 SymbolFileCreateInstance create_callback; 1935 DebuggerInitializeCallback debugger_init_callback; 1936 }; 1937 1938 typedef std::vector<SymbolFileInstance> SymbolFileInstances; 1939 1940 static Mutex & 1941 GetSymbolFileMutex () 1942 { 1943 static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive); 1944 return g_instances_mutex; 1945 } 1946 1947 static SymbolFileInstances & 1948 GetSymbolFileInstances () 1949 { 1950 static SymbolFileInstances g_instances; 1951 return g_instances; 1952 } 1953 1954 bool 1955 PluginManager::RegisterPlugin(const ConstString &name, 1956 const char *description, 1957 SymbolFileCreateInstance create_callback, 1958 DebuggerInitializeCallback debugger_init_callback) 1959 { 1960 if (create_callback) 1961 { 1962 SymbolFileInstance instance; 1963 assert ((bool)name); 1964 instance.name = name; 1965 if (description && description[0]) 1966 instance.description = description; 1967 instance.create_callback = create_callback; 1968 instance.debugger_init_callback = debugger_init_callback; 1969 Mutex::Locker locker (GetSymbolFileMutex ()); 1970 GetSymbolFileInstances ().push_back (instance); 1971 } 1972 return false; 1973 } 1974 1975 bool 1976 PluginManager::UnregisterPlugin (SymbolFileCreateInstance create_callback) 1977 { 1978 if (create_callback) 1979 { 1980 Mutex::Locker locker (GetSymbolFileMutex ()); 1981 SymbolFileInstances &instances = GetSymbolFileInstances (); 1982 1983 SymbolFileInstances::iterator pos, end = instances.end(); 1984 for (pos = instances.begin(); pos != end; ++ pos) 1985 { 1986 if (pos->create_callback == create_callback) 1987 { 1988 instances.erase(pos); 1989 return true; 1990 } 1991 } 1992 } 1993 return false; 1994 } 1995 1996 SymbolFileCreateInstance 1997 PluginManager::GetSymbolFileCreateCallbackAtIndex (uint32_t idx) 1998 { 1999 Mutex::Locker locker (GetSymbolFileMutex ()); 2000 SymbolFileInstances &instances = GetSymbolFileInstances (); 2001 if (idx < instances.size()) 2002 return instances[idx].create_callback; 2003 return nullptr; 2004 } 2005 2006 SymbolFileCreateInstance 2007 PluginManager::GetSymbolFileCreateCallbackForPluginName (const ConstString &name) 2008 { 2009 if (name) 2010 { 2011 Mutex::Locker locker (GetSymbolFileMutex ()); 2012 SymbolFileInstances &instances = GetSymbolFileInstances (); 2013 2014 SymbolFileInstances::iterator pos, end = instances.end(); 2015 for (pos = instances.begin(); pos != end; ++ pos) 2016 { 2017 if (name == pos->name) 2018 return pos->create_callback; 2019 } 2020 } 2021 return nullptr; 2022 } 2023 2024 #pragma mark SymbolVendor 2025 2026 struct SymbolVendorInstance 2027 { 2028 SymbolVendorInstance() : 2029 name(), 2030 description(), 2031 create_callback(nullptr) 2032 { 2033 } 2034 2035 ConstString name; 2036 std::string description; 2037 SymbolVendorCreateInstance create_callback; 2038 }; 2039 2040 typedef std::vector<SymbolVendorInstance> SymbolVendorInstances; 2041 2042 static Mutex & 2043 GetSymbolVendorMutex () 2044 { 2045 static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive); 2046 return g_instances_mutex; 2047 } 2048 2049 static SymbolVendorInstances & 2050 GetSymbolVendorInstances () 2051 { 2052 static SymbolVendorInstances g_instances; 2053 return g_instances; 2054 } 2055 2056 bool 2057 PluginManager::RegisterPlugin(const ConstString &name, 2058 const char *description, 2059 SymbolVendorCreateInstance create_callback) 2060 { 2061 if (create_callback) 2062 { 2063 SymbolVendorInstance instance; 2064 assert ((bool)name); 2065 instance.name = name; 2066 if (description && description[0]) 2067 instance.description = description; 2068 instance.create_callback = create_callback; 2069 Mutex::Locker locker (GetSymbolVendorMutex ()); 2070 GetSymbolVendorInstances ().push_back (instance); 2071 } 2072 return false; 2073 } 2074 2075 bool 2076 PluginManager::UnregisterPlugin (SymbolVendorCreateInstance create_callback) 2077 { 2078 if (create_callback) 2079 { 2080 Mutex::Locker locker (GetSymbolVendorMutex ()); 2081 SymbolVendorInstances &instances = GetSymbolVendorInstances (); 2082 2083 SymbolVendorInstances::iterator pos, end = instances.end(); 2084 for (pos = instances.begin(); pos != end; ++ pos) 2085 { 2086 if (pos->create_callback == create_callback) 2087 { 2088 instances.erase(pos); 2089 return true; 2090 } 2091 } 2092 } 2093 return false; 2094 } 2095 2096 SymbolVendorCreateInstance 2097 PluginManager::GetSymbolVendorCreateCallbackAtIndex (uint32_t idx) 2098 { 2099 Mutex::Locker locker (GetSymbolVendorMutex ()); 2100 SymbolVendorInstances &instances = GetSymbolVendorInstances (); 2101 if (idx < instances.size()) 2102 return instances[idx].create_callback; 2103 return nullptr; 2104 } 2105 2106 SymbolVendorCreateInstance 2107 PluginManager::GetSymbolVendorCreateCallbackForPluginName (const ConstString &name) 2108 { 2109 if (name) 2110 { 2111 Mutex::Locker locker (GetSymbolVendorMutex ()); 2112 SymbolVendorInstances &instances = GetSymbolVendorInstances (); 2113 2114 SymbolVendorInstances::iterator pos, end = instances.end(); 2115 for (pos = instances.begin(); pos != end; ++ pos) 2116 { 2117 if (name == pos->name) 2118 return pos->create_callback; 2119 } 2120 } 2121 return nullptr; 2122 } 2123 2124 #pragma mark UnwindAssembly 2125 2126 struct UnwindAssemblyInstance 2127 { 2128 UnwindAssemblyInstance() : 2129 name(), 2130 description(), 2131 create_callback(nullptr) 2132 { 2133 } 2134 2135 ConstString name; 2136 std::string description; 2137 UnwindAssemblyCreateInstance create_callback; 2138 }; 2139 2140 typedef std::vector<UnwindAssemblyInstance> UnwindAssemblyInstances; 2141 2142 static Mutex & 2143 GetUnwindAssemblyMutex () 2144 { 2145 static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive); 2146 return g_instances_mutex; 2147 } 2148 2149 static UnwindAssemblyInstances & 2150 GetUnwindAssemblyInstances () 2151 { 2152 static UnwindAssemblyInstances g_instances; 2153 return g_instances; 2154 } 2155 2156 bool 2157 PluginManager::RegisterPlugin(const ConstString &name, 2158 const char *description, 2159 UnwindAssemblyCreateInstance create_callback) 2160 { 2161 if (create_callback) 2162 { 2163 UnwindAssemblyInstance instance; 2164 assert ((bool)name); 2165 instance.name = name; 2166 if (description && description[0]) 2167 instance.description = description; 2168 instance.create_callback = create_callback; 2169 Mutex::Locker locker (GetUnwindAssemblyMutex ()); 2170 GetUnwindAssemblyInstances ().push_back (instance); 2171 } 2172 return false; 2173 } 2174 2175 bool 2176 PluginManager::UnregisterPlugin (UnwindAssemblyCreateInstance create_callback) 2177 { 2178 if (create_callback) 2179 { 2180 Mutex::Locker locker (GetUnwindAssemblyMutex ()); 2181 UnwindAssemblyInstances &instances = GetUnwindAssemblyInstances (); 2182 2183 UnwindAssemblyInstances::iterator pos, end = instances.end(); 2184 for (pos = instances.begin(); pos != end; ++ pos) 2185 { 2186 if (pos->create_callback == create_callback) 2187 { 2188 instances.erase(pos); 2189 return true; 2190 } 2191 } 2192 } 2193 return false; 2194 } 2195 2196 UnwindAssemblyCreateInstance 2197 PluginManager::GetUnwindAssemblyCreateCallbackAtIndex (uint32_t idx) 2198 { 2199 Mutex::Locker locker (GetUnwindAssemblyMutex ()); 2200 UnwindAssemblyInstances &instances = GetUnwindAssemblyInstances (); 2201 if (idx < instances.size()) 2202 return instances[idx].create_callback; 2203 return nullptr; 2204 } 2205 2206 UnwindAssemblyCreateInstance 2207 PluginManager::GetUnwindAssemblyCreateCallbackForPluginName (const ConstString &name) 2208 { 2209 if (name) 2210 { 2211 Mutex::Locker locker (GetUnwindAssemblyMutex ()); 2212 UnwindAssemblyInstances &instances = GetUnwindAssemblyInstances (); 2213 2214 UnwindAssemblyInstances::iterator pos, end = instances.end(); 2215 for (pos = instances.begin(); pos != end; ++ pos) 2216 { 2217 if (name == pos->name) 2218 return pos->create_callback; 2219 } 2220 } 2221 return nullptr; 2222 } 2223 2224 #pragma mark MemoryHistory 2225 2226 struct MemoryHistoryInstance 2227 { 2228 MemoryHistoryInstance() : 2229 name(), 2230 description(), 2231 create_callback(nullptr) 2232 { 2233 } 2234 2235 ConstString name; 2236 std::string description; 2237 MemoryHistoryCreateInstance create_callback; 2238 }; 2239 2240 typedef std::vector<MemoryHistoryInstance> MemoryHistoryInstances; 2241 2242 static Mutex & 2243 GetMemoryHistoryMutex () 2244 { 2245 static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive); 2246 return g_instances_mutex; 2247 } 2248 2249 static MemoryHistoryInstances & 2250 GetMemoryHistoryInstances () 2251 { 2252 static MemoryHistoryInstances g_instances; 2253 return g_instances; 2254 } 2255 2256 bool 2257 PluginManager::RegisterPlugin(const ConstString &name, 2258 const char *description, 2259 MemoryHistoryCreateInstance create_callback) 2260 { 2261 if (create_callback) 2262 { 2263 MemoryHistoryInstance instance; 2264 assert ((bool)name); 2265 instance.name = name; 2266 if (description && description[0]) 2267 instance.description = description; 2268 instance.create_callback = create_callback; 2269 Mutex::Locker locker (GetMemoryHistoryMutex ()); 2270 GetMemoryHistoryInstances ().push_back (instance); 2271 } 2272 return false; 2273 } 2274 2275 bool 2276 PluginManager::UnregisterPlugin (MemoryHistoryCreateInstance create_callback) 2277 { 2278 if (create_callback) 2279 { 2280 Mutex::Locker locker (GetMemoryHistoryMutex ()); 2281 MemoryHistoryInstances &instances = GetMemoryHistoryInstances (); 2282 2283 MemoryHistoryInstances::iterator pos, end = instances.end(); 2284 for (pos = instances.begin(); pos != end; ++ pos) 2285 { 2286 if (pos->create_callback == create_callback) 2287 { 2288 instances.erase(pos); 2289 return true; 2290 } 2291 } 2292 } 2293 return false; 2294 } 2295 2296 MemoryHistoryCreateInstance 2297 PluginManager::GetMemoryHistoryCreateCallbackAtIndex (uint32_t idx) 2298 { 2299 Mutex::Locker locker (GetMemoryHistoryMutex ()); 2300 MemoryHistoryInstances &instances = GetMemoryHistoryInstances (); 2301 if (idx < instances.size()) 2302 return instances[idx].create_callback; 2303 return nullptr; 2304 } 2305 2306 MemoryHistoryCreateInstance 2307 PluginManager::GetMemoryHistoryCreateCallbackForPluginName (const ConstString &name) 2308 { 2309 if (name) 2310 { 2311 Mutex::Locker locker (GetMemoryHistoryMutex ()); 2312 MemoryHistoryInstances &instances = GetMemoryHistoryInstances (); 2313 2314 MemoryHistoryInstances::iterator pos, end = instances.end(); 2315 for (pos = instances.begin(); pos != end; ++ pos) 2316 { 2317 if (name == pos->name) 2318 return pos->create_callback; 2319 } 2320 } 2321 return nullptr; 2322 } 2323 2324 #pragma mark InstrumentationRuntime 2325 2326 struct InstrumentationRuntimeInstance 2327 { 2328 InstrumentationRuntimeInstance() : 2329 name(), 2330 description(), 2331 create_callback(nullptr) 2332 { 2333 } 2334 2335 ConstString name; 2336 std::string description; 2337 InstrumentationRuntimeCreateInstance create_callback; 2338 InstrumentationRuntimeGetType get_type_callback; 2339 }; 2340 2341 typedef std::vector<InstrumentationRuntimeInstance> InstrumentationRuntimeInstances; 2342 2343 static Mutex & 2344 GetInstrumentationRuntimeMutex () 2345 { 2346 static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive); 2347 return g_instances_mutex; 2348 } 2349 2350 static InstrumentationRuntimeInstances & 2351 GetInstrumentationRuntimeInstances () 2352 { 2353 static InstrumentationRuntimeInstances g_instances; 2354 return g_instances; 2355 } 2356 2357 bool 2358 PluginManager::RegisterPlugin(const ConstString &name, 2359 const char *description, 2360 InstrumentationRuntimeCreateInstance create_callback, 2361 InstrumentationRuntimeGetType get_type_callback) 2362 { 2363 if (create_callback) 2364 { 2365 InstrumentationRuntimeInstance instance; 2366 assert ((bool)name); 2367 instance.name = name; 2368 if (description && description[0]) 2369 instance.description = description; 2370 instance.create_callback = create_callback; 2371 instance.get_type_callback = get_type_callback; 2372 Mutex::Locker locker (GetInstrumentationRuntimeMutex ()); 2373 GetInstrumentationRuntimeInstances ().push_back (instance); 2374 } 2375 return false; 2376 } 2377 2378 bool 2379 PluginManager::UnregisterPlugin (InstrumentationRuntimeCreateInstance create_callback) 2380 { 2381 if (create_callback) 2382 { 2383 Mutex::Locker locker (GetInstrumentationRuntimeMutex ()); 2384 InstrumentationRuntimeInstances &instances = GetInstrumentationRuntimeInstances (); 2385 2386 InstrumentationRuntimeInstances::iterator pos, end = instances.end(); 2387 for (pos = instances.begin(); pos != end; ++ pos) 2388 { 2389 if (pos->create_callback == create_callback) 2390 { 2391 instances.erase(pos); 2392 return true; 2393 } 2394 } 2395 } 2396 return false; 2397 } 2398 2399 InstrumentationRuntimeGetType 2400 PluginManager::GetInstrumentationRuntimeGetTypeCallbackAtIndex (uint32_t idx) 2401 { 2402 Mutex::Locker locker (GetInstrumentationRuntimeMutex ()); 2403 InstrumentationRuntimeInstances &instances = GetInstrumentationRuntimeInstances (); 2404 if (idx < instances.size()) 2405 return instances[idx].get_type_callback; 2406 return nullptr; 2407 } 2408 2409 InstrumentationRuntimeCreateInstance 2410 PluginManager::GetInstrumentationRuntimeCreateCallbackAtIndex (uint32_t idx) 2411 { 2412 Mutex::Locker locker (GetInstrumentationRuntimeMutex ()); 2413 InstrumentationRuntimeInstances &instances = GetInstrumentationRuntimeInstances (); 2414 if (idx < instances.size()) 2415 return instances[idx].create_callback; 2416 return nullptr; 2417 } 2418 2419 InstrumentationRuntimeCreateInstance 2420 PluginManager::GetInstrumentationRuntimeCreateCallbackForPluginName (const ConstString &name) 2421 { 2422 if (name) 2423 { 2424 Mutex::Locker locker (GetInstrumentationRuntimeMutex ()); 2425 InstrumentationRuntimeInstances &instances = GetInstrumentationRuntimeInstances (); 2426 2427 InstrumentationRuntimeInstances::iterator pos, end = instances.end(); 2428 for (pos = instances.begin(); pos != end; ++ pos) 2429 { 2430 if (name == pos->name) 2431 return pos->create_callback; 2432 } 2433 } 2434 return nullptr; 2435 } 2436 2437 #pragma mark TypeSystem 2438 2439 struct TypeSystemInstance 2440 { 2441 TypeSystemInstance() : 2442 name(), 2443 description(), 2444 create_callback(nullptr) 2445 { 2446 } 2447 2448 ConstString name; 2449 std::string description; 2450 TypeSystemCreateInstance create_callback; 2451 TypeSystemEnumerateSupportedLanguages enumerate_callback; 2452 }; 2453 2454 typedef std::vector<TypeSystemInstance> TypeSystemInstances; 2455 2456 static Mutex & 2457 GetTypeSystemMutex () 2458 { 2459 static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive); 2460 return g_instances_mutex; 2461 } 2462 2463 static TypeSystemInstances & 2464 GetTypeSystemInstances () 2465 { 2466 static TypeSystemInstances g_instances; 2467 return g_instances; 2468 } 2469 2470 bool 2471 PluginManager::RegisterPlugin (const ConstString &name, 2472 const char *description, 2473 TypeSystemCreateInstance create_callback, 2474 TypeSystemEnumerateSupportedLanguages enumerate_supported_languages_callback) 2475 { 2476 if (create_callback) 2477 { 2478 TypeSystemInstance instance; 2479 assert ((bool)name); 2480 instance.name = name; 2481 if (description && description[0]) 2482 instance.description = description; 2483 instance.create_callback = create_callback; 2484 instance.enumerate_callback = enumerate_supported_languages_callback; 2485 Mutex::Locker locker (GetTypeSystemMutex ()); 2486 GetTypeSystemInstances ().push_back (instance); 2487 } 2488 return false; 2489 } 2490 2491 bool 2492 PluginManager::UnregisterPlugin (TypeSystemCreateInstance create_callback) 2493 { 2494 if (create_callback) 2495 { 2496 Mutex::Locker locker (GetTypeSystemMutex ()); 2497 TypeSystemInstances &instances = GetTypeSystemInstances (); 2498 2499 TypeSystemInstances::iterator pos, end = instances.end(); 2500 for (pos = instances.begin(); pos != end; ++ pos) 2501 { 2502 if (pos->create_callback == create_callback) 2503 { 2504 instances.erase(pos); 2505 return true; 2506 } 2507 } 2508 } 2509 return false; 2510 } 2511 2512 TypeSystemCreateInstance 2513 PluginManager::GetTypeSystemCreateCallbackAtIndex (uint32_t idx) 2514 { 2515 Mutex::Locker locker (GetTypeSystemMutex ()); 2516 TypeSystemInstances &instances = GetTypeSystemInstances (); 2517 if (idx < instances.size()) 2518 return instances[idx].create_callback; 2519 return nullptr; 2520 } 2521 2522 TypeSystemCreateInstance 2523 PluginManager::GetTypeSystemCreateCallbackForPluginName (const ConstString &name) 2524 { 2525 if (name) 2526 { 2527 Mutex::Locker locker (GetTypeSystemMutex ()); 2528 TypeSystemInstances &instances = GetTypeSystemInstances (); 2529 2530 TypeSystemInstances::iterator pos, end = instances.end(); 2531 for (pos = instances.begin(); pos != end; ++ pos) 2532 { 2533 if (name == pos->name) 2534 return pos->create_callback; 2535 } 2536 } 2537 return nullptr; 2538 } 2539 2540 TypeSystemEnumerateSupportedLanguages 2541 PluginManager::GetTypeSystemEnumerateSupportedLanguagesCallbackAtIndex (uint32_t idx) 2542 { 2543 Mutex::Locker locker (GetTypeSystemMutex ()); 2544 TypeSystemInstances &instances = GetTypeSystemInstances (); 2545 if (idx < instances.size()) 2546 return instances[idx].enumerate_callback; 2547 return nullptr; 2548 } 2549 2550 TypeSystemEnumerateSupportedLanguages 2551 PluginManager::GetTypeSystemEnumerateSupportedLanguagesCallbackForPluginName (const ConstString &name) 2552 { 2553 if (name) 2554 { 2555 Mutex::Locker locker (GetTypeSystemMutex ()); 2556 TypeSystemInstances &instances = GetTypeSystemInstances (); 2557 2558 TypeSystemInstances::iterator pos, end = instances.end(); 2559 for (pos = instances.begin(); pos != end; ++ pos) 2560 { 2561 if (name == pos->name) 2562 return pos->enumerate_callback; 2563 } 2564 } 2565 return nullptr; 2566 } 2567 2568 #pragma mark REPL 2569 2570 struct REPLInstance 2571 { 2572 REPLInstance() : 2573 name(), 2574 description(), 2575 create_callback(nullptr) 2576 { 2577 } 2578 2579 ConstString name; 2580 std::string description; 2581 REPLCreateInstance create_callback; 2582 REPLEnumerateSupportedLanguages enumerate_languages_callback; 2583 }; 2584 2585 typedef std::vector<REPLInstance> REPLInstances; 2586 2587 static Mutex & 2588 GetREPLMutex () 2589 { 2590 static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive); 2591 return g_instances_mutex; 2592 } 2593 2594 static REPLInstances & 2595 GetREPLInstances () 2596 { 2597 static REPLInstances g_instances; 2598 return g_instances; 2599 } 2600 2601 bool 2602 PluginManager::RegisterPlugin (const ConstString &name, 2603 const char *description, 2604 REPLCreateInstance create_callback, 2605 REPLEnumerateSupportedLanguages enumerate_languages_callback) 2606 { 2607 if (create_callback) 2608 { 2609 REPLInstance instance; 2610 assert ((bool)name); 2611 instance.name = name; 2612 if (description && description[0]) 2613 instance.description = description; 2614 instance.create_callback = create_callback; 2615 instance.enumerate_languages_callback = enumerate_languages_callback; 2616 Mutex::Locker locker (GetREPLMutex ()); 2617 GetREPLInstances ().push_back (instance); 2618 } 2619 return false; 2620 } 2621 2622 bool 2623 PluginManager::UnregisterPlugin (REPLCreateInstance create_callback) 2624 { 2625 if (create_callback) 2626 { 2627 Mutex::Locker locker (GetREPLMutex ()); 2628 REPLInstances &instances = GetREPLInstances (); 2629 2630 REPLInstances::iterator pos, end = instances.end(); 2631 for (pos = instances.begin(); pos != end; ++ pos) 2632 { 2633 if (pos->create_callback == create_callback) 2634 { 2635 instances.erase(pos); 2636 return true; 2637 } 2638 } 2639 } 2640 return false; 2641 } 2642 2643 REPLCreateInstance 2644 PluginManager::GetREPLCreateCallbackAtIndex (uint32_t idx) 2645 { 2646 Mutex::Locker locker (GetREPLMutex ()); 2647 REPLInstances &instances = GetREPLInstances (); 2648 if (idx < instances.size()) 2649 return instances[idx].create_callback; 2650 return nullptr; 2651 } 2652 2653 REPLCreateInstance 2654 PluginManager::GetREPLCreateCallbackForPluginName (const ConstString &name) 2655 { 2656 if (name) 2657 { 2658 Mutex::Locker locker (GetREPLMutex ()); 2659 REPLInstances &instances = GetREPLInstances (); 2660 2661 REPLInstances::iterator pos, end = instances.end(); 2662 for (pos = instances.begin(); pos != end; ++ pos) 2663 { 2664 if (name == pos->name) 2665 return pos->create_callback; 2666 } 2667 } 2668 return nullptr; 2669 } 2670 2671 REPLEnumerateSupportedLanguages 2672 PluginManager::GetREPLEnumerateSupportedLanguagesCallbackAtIndex (uint32_t idx) 2673 { 2674 Mutex::Locker locker (GetREPLMutex ()); 2675 REPLInstances &instances = GetREPLInstances (); 2676 if (idx < instances.size()) 2677 return instances[idx].enumerate_languages_callback; 2678 return nullptr; 2679 } 2680 2681 REPLEnumerateSupportedLanguages 2682 PluginManager::GetREPLSystemEnumerateSupportedLanguagesCallbackForPluginName (const ConstString &name) 2683 { 2684 if (name) 2685 { 2686 Mutex::Locker locker (GetREPLMutex ()); 2687 REPLInstances &instances = GetREPLInstances (); 2688 2689 REPLInstances::iterator pos, end = instances.end(); 2690 for (pos = instances.begin(); pos != end; ++ pos) 2691 { 2692 if (name == pos->name) 2693 return pos->enumerate_languages_callback; 2694 } 2695 } 2696 return nullptr; 2697 } 2698 2699 #pragma mark PluginManager 2700 2701 void 2702 PluginManager::DebuggerInitialize (Debugger &debugger) 2703 { 2704 // Initialize the DynamicLoader plugins 2705 { 2706 Mutex::Locker locker (GetDynamicLoaderMutex ()); 2707 DynamicLoaderInstances &instances = GetDynamicLoaderInstances (); 2708 2709 DynamicLoaderInstances::iterator pos, end = instances.end(); 2710 for (pos = instances.begin(); pos != end; ++ pos) 2711 { 2712 if (pos->debugger_init_callback) 2713 pos->debugger_init_callback (debugger); 2714 } 2715 } 2716 2717 // Initialize the JITLoader plugins 2718 { 2719 Mutex::Locker locker (GetJITLoaderMutex ()); 2720 JITLoaderInstances &instances = GetJITLoaderInstances (); 2721 2722 JITLoaderInstances::iterator pos, end = instances.end(); 2723 for (pos = instances.begin(); pos != end; ++ pos) 2724 { 2725 if (pos->debugger_init_callback) 2726 pos->debugger_init_callback (debugger); 2727 } 2728 } 2729 2730 // Initialize the Platform plugins 2731 { 2732 Mutex::Locker locker (GetPlatformInstancesMutex ()); 2733 PlatformInstances &instances = GetPlatformInstances (); 2734 2735 PlatformInstances::iterator pos, end = instances.end(); 2736 for (pos = instances.begin(); pos != end; ++ pos) 2737 { 2738 if (pos->debugger_init_callback) 2739 pos->debugger_init_callback (debugger); 2740 } 2741 } 2742 2743 // Initialize the Process plugins 2744 { 2745 Mutex::Locker locker (GetProcessMutex()); 2746 ProcessInstances &instances = GetProcessInstances(); 2747 2748 ProcessInstances::iterator pos, end = instances.end(); 2749 for (pos = instances.begin(); pos != end; ++ pos) 2750 { 2751 if (pos->debugger_init_callback) 2752 pos->debugger_init_callback (debugger); 2753 } 2754 } 2755 2756 // Initialize the SymbolFile plugins 2757 { 2758 Mutex::Locker locker (GetSymbolFileMutex()); 2759 for (auto& sym_file: GetSymbolFileInstances()) 2760 { 2761 if (sym_file.debugger_init_callback) 2762 sym_file.debugger_init_callback (debugger); 2763 } 2764 } 2765 2766 // Initialize the OperatingSystem plugins 2767 { 2768 Mutex::Locker locker(GetOperatingSystemMutex()); 2769 for (auto &os : GetOperatingSystemInstances()) 2770 { 2771 if (os.debugger_init_callback) 2772 os.debugger_init_callback(debugger); 2773 } 2774 } 2775 } 2776 2777 // This is the preferred new way to register plugin specific settings. e.g. 2778 // This will put a plugin's settings under e.g. "plugin.<plugin_type_name>.<plugin_type_desc>.SETTINGNAME". 2779 static lldb::OptionValuePropertiesSP 2780 GetDebuggerPropertyForPlugins (Debugger &debugger, 2781 const ConstString &plugin_type_name, 2782 const ConstString &plugin_type_desc, 2783 bool can_create) 2784 { 2785 lldb::OptionValuePropertiesSP parent_properties_sp (debugger.GetValueProperties()); 2786 if (parent_properties_sp) 2787 { 2788 static ConstString g_property_name("plugin"); 2789 2790 OptionValuePropertiesSP plugin_properties_sp = parent_properties_sp->GetSubProperty(nullptr, g_property_name); 2791 if (!plugin_properties_sp && can_create) 2792 { 2793 plugin_properties_sp.reset (new OptionValueProperties (g_property_name)); 2794 parent_properties_sp->AppendProperty (g_property_name, 2795 ConstString("Settings specify to plugins."), 2796 true, 2797 plugin_properties_sp); 2798 } 2799 2800 if (plugin_properties_sp) 2801 { 2802 lldb::OptionValuePropertiesSP plugin_type_properties_sp = plugin_properties_sp->GetSubProperty(nullptr, plugin_type_name); 2803 if (!plugin_type_properties_sp && can_create) 2804 { 2805 plugin_type_properties_sp.reset (new OptionValueProperties (plugin_type_name)); 2806 plugin_properties_sp->AppendProperty (plugin_type_name, 2807 plugin_type_desc, 2808 true, 2809 plugin_type_properties_sp); 2810 } 2811 return plugin_type_properties_sp; 2812 } 2813 } 2814 return lldb::OptionValuePropertiesSP(); 2815 } 2816 2817 // This is deprecated way to register plugin specific settings. e.g. 2818 // "<plugin_type_name>.plugin.<plugin_type_desc>.SETTINGNAME" 2819 // and Platform generic settings would be under "platform.SETTINGNAME". 2820 static lldb::OptionValuePropertiesSP 2821 GetDebuggerPropertyForPluginsOldStyle (Debugger &debugger, 2822 const ConstString &plugin_type_name, 2823 const ConstString &plugin_type_desc, 2824 bool can_create) 2825 { 2826 static ConstString g_property_name("plugin"); 2827 lldb::OptionValuePropertiesSP parent_properties_sp (debugger.GetValueProperties()); 2828 if (parent_properties_sp) 2829 { 2830 OptionValuePropertiesSP plugin_properties_sp = parent_properties_sp->GetSubProperty(nullptr, plugin_type_name); 2831 if (!plugin_properties_sp && can_create) 2832 { 2833 plugin_properties_sp.reset (new OptionValueProperties (plugin_type_name)); 2834 parent_properties_sp->AppendProperty (plugin_type_name, 2835 plugin_type_desc, 2836 true, 2837 plugin_properties_sp); 2838 } 2839 2840 if (plugin_properties_sp) 2841 { 2842 lldb::OptionValuePropertiesSP plugin_type_properties_sp = plugin_properties_sp->GetSubProperty(nullptr, g_property_name); 2843 if (!plugin_type_properties_sp && can_create) 2844 { 2845 plugin_type_properties_sp.reset (new OptionValueProperties (g_property_name)); 2846 plugin_properties_sp->AppendProperty (g_property_name, 2847 ConstString("Settings specific to plugins"), 2848 true, 2849 plugin_type_properties_sp); 2850 } 2851 return plugin_type_properties_sp; 2852 } 2853 } 2854 return lldb::OptionValuePropertiesSP(); 2855 } 2856 2857 namespace { 2858 2859 typedef lldb::OptionValuePropertiesSP 2860 GetDebuggerPropertyForPluginsPtr (Debugger&, const ConstString&, const ConstString&, bool can_create); 2861 2862 lldb::OptionValuePropertiesSP 2863 GetSettingForPlugin (Debugger &debugger, 2864 const ConstString &setting_name, 2865 const ConstString &plugin_type_name, 2866 GetDebuggerPropertyForPluginsPtr get_debugger_property= GetDebuggerPropertyForPlugins) 2867 { 2868 lldb::OptionValuePropertiesSP properties_sp; 2869 lldb::OptionValuePropertiesSP plugin_type_properties_sp (get_debugger_property (debugger, 2870 plugin_type_name, 2871 ConstString(), // not creating to so we don't need the description 2872 false)); 2873 if (plugin_type_properties_sp) 2874 properties_sp = plugin_type_properties_sp->GetSubProperty (nullptr, setting_name); 2875 return properties_sp; 2876 } 2877 2878 bool 2879 CreateSettingForPlugin (Debugger &debugger, 2880 const ConstString &plugin_type_name, 2881 const ConstString &plugin_type_desc, 2882 const lldb::OptionValuePropertiesSP &properties_sp, 2883 const ConstString &description, 2884 bool is_global_property, 2885 GetDebuggerPropertyForPluginsPtr get_debugger_property = GetDebuggerPropertyForPlugins) 2886 { 2887 if (properties_sp) 2888 { 2889 lldb::OptionValuePropertiesSP plugin_type_properties_sp (get_debugger_property ( 2890 debugger, plugin_type_name, plugin_type_desc, true)); 2891 if (plugin_type_properties_sp) 2892 { 2893 plugin_type_properties_sp->AppendProperty (properties_sp->GetName(), 2894 description, 2895 is_global_property, 2896 properties_sp); 2897 return true; 2898 } 2899 } 2900 return false; 2901 } 2902 2903 const char* kDynamicLoaderPluginName("dynamic-loader"); 2904 const char* kPlatformPluginName("platform"); 2905 const char* kProcessPluginName("process"); 2906 const char* kSymbolFilePluginName("symbol-file"); 2907 const char* kJITLoaderPluginName("jit-loader"); 2908 2909 } // anonymous namespace 2910 2911 lldb::OptionValuePropertiesSP 2912 PluginManager::GetSettingForDynamicLoaderPlugin (Debugger &debugger, 2913 const ConstString &setting_name) 2914 { 2915 return GetSettingForPlugin(debugger, setting_name, ConstString(kDynamicLoaderPluginName)); 2916 } 2917 2918 bool 2919 PluginManager::CreateSettingForDynamicLoaderPlugin (Debugger &debugger, 2920 const lldb::OptionValuePropertiesSP &properties_sp, 2921 const ConstString &description, 2922 bool is_global_property) 2923 { 2924 return CreateSettingForPlugin(debugger, 2925 ConstString(kDynamicLoaderPluginName), 2926 ConstString("Settings for dynamic loader plug-ins"), 2927 properties_sp, 2928 description, 2929 is_global_property); 2930 } 2931 2932 lldb::OptionValuePropertiesSP 2933 PluginManager::GetSettingForPlatformPlugin (Debugger &debugger, const ConstString &setting_name) 2934 { 2935 return GetSettingForPlugin(debugger, 2936 setting_name, 2937 ConstString(kPlatformPluginName), 2938 GetDebuggerPropertyForPluginsOldStyle); 2939 } 2940 2941 bool 2942 PluginManager::CreateSettingForPlatformPlugin (Debugger &debugger, 2943 const lldb::OptionValuePropertiesSP &properties_sp, 2944 const ConstString &description, 2945 bool is_global_property) 2946 { 2947 return CreateSettingForPlugin(debugger, 2948 ConstString(kPlatformPluginName), 2949 ConstString("Settings for platform plug-ins"), 2950 properties_sp, 2951 description, 2952 is_global_property, 2953 GetDebuggerPropertyForPluginsOldStyle); 2954 } 2955 2956 lldb::OptionValuePropertiesSP 2957 PluginManager::GetSettingForProcessPlugin (Debugger &debugger, const ConstString &setting_name) 2958 { 2959 return GetSettingForPlugin(debugger, setting_name, ConstString(kProcessPluginName)); 2960 } 2961 2962 bool 2963 PluginManager::CreateSettingForProcessPlugin (Debugger &debugger, 2964 const lldb::OptionValuePropertiesSP &properties_sp, 2965 const ConstString &description, 2966 bool is_global_property) 2967 { 2968 return CreateSettingForPlugin(debugger, 2969 ConstString(kProcessPluginName), 2970 ConstString("Settings for process plug-ins"), 2971 properties_sp, 2972 description, 2973 is_global_property); 2974 } 2975 2976 lldb::OptionValuePropertiesSP 2977 PluginManager::GetSettingForSymbolFilePlugin (Debugger &debugger, 2978 const ConstString &setting_name) 2979 { 2980 return GetSettingForPlugin(debugger, setting_name, ConstString(kSymbolFilePluginName)); 2981 } 2982 2983 bool 2984 PluginManager::CreateSettingForSymbolFilePlugin (Debugger &debugger, 2985 const lldb::OptionValuePropertiesSP &properties_sp, 2986 const ConstString &description, 2987 bool is_global_property) 2988 { 2989 return CreateSettingForPlugin(debugger, 2990 ConstString(kSymbolFilePluginName), 2991 ConstString("Settings for symbol file plug-ins"), 2992 properties_sp, 2993 description, 2994 is_global_property); 2995 } 2996 2997 lldb::OptionValuePropertiesSP 2998 PluginManager::GetSettingForJITLoaderPlugin (Debugger &debugger, 2999 const ConstString &setting_name) 3000 { 3001 return GetSettingForPlugin(debugger, setting_name, ConstString(kJITLoaderPluginName)); 3002 } 3003 3004 bool 3005 PluginManager::CreateSettingForJITLoaderPlugin (Debugger &debugger, 3006 const lldb::OptionValuePropertiesSP &properties_sp, 3007 const ConstString &description, 3008 bool is_global_property) 3009 { 3010 return CreateSettingForPlugin(debugger, 3011 ConstString(kJITLoaderPluginName), 3012 ConstString("Settings for JIT loader plug-ins"), 3013 properties_sp, 3014 description, 3015 is_global_property); 3016 } 3017 3018 static const char *kOperatingSystemPluginName("os"); 3019 3020 lldb::OptionValuePropertiesSP 3021 PluginManager::GetSettingForOperatingSystemPlugin(Debugger &debugger, const ConstString &setting_name) 3022 { 3023 lldb::OptionValuePropertiesSP properties_sp; 3024 lldb::OptionValuePropertiesSP plugin_type_properties_sp( 3025 GetDebuggerPropertyForPlugins(debugger, ConstString(kOperatingSystemPluginName), 3026 ConstString(), // not creating to so we don't need the description 3027 false)); 3028 if (plugin_type_properties_sp) 3029 properties_sp = plugin_type_properties_sp->GetSubProperty(nullptr, setting_name); 3030 return properties_sp; 3031 } 3032 3033 bool 3034 PluginManager::CreateSettingForOperatingSystemPlugin(Debugger &debugger, 3035 const lldb::OptionValuePropertiesSP &properties_sp, 3036 const ConstString &description, bool is_global_property) 3037 { 3038 if (properties_sp) 3039 { 3040 lldb::OptionValuePropertiesSP plugin_type_properties_sp( 3041 GetDebuggerPropertyForPlugins(debugger, ConstString(kOperatingSystemPluginName), 3042 ConstString("Settings for operating system plug-ins"), true)); 3043 if (plugin_type_properties_sp) 3044 { 3045 plugin_type_properties_sp->AppendProperty(properties_sp->GetName(), description, is_global_property, 3046 properties_sp); 3047 return true; 3048 } 3049 } 3050 return false; 3051 } 3052