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