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 <limits.h>
13 
14 #include <string>
15 #include <vector>
16 
17 #include "lldb/Core/Debugger.h"
18 #include "lldb/Core/Error.h"
19 #include "lldb/Host/FileSpec.h"
20 #include "lldb/Host/Host.h"
21 #include "lldb/Host/Mutex.h"
22 #include "lldb/Interpreter/OptionValueProperties.h"
23 
24 #include "llvm/ADT/StringRef.h"
25 
26 using namespace lldb;
27 using namespace lldb_private;
28 
29 enum PluginAction
30 {
31     ePluginRegisterInstance,
32     ePluginUnregisterInstance,
33     ePluginGetInstanceAtIndex
34 };
35 
36 struct PluginInfo
37 {
38     void *plugin_handle;
39     void *plugin_init_callback;
40     void *plugin_term_callback;
41 };
42 
43 typedef std::map<FileSpec, PluginInfo> PluginTerminateMap;
44 
45 static Mutex &
46 GetPluginMapMutex ()
47 {
48     static Mutex g_plugin_map_mutex (Mutex::eMutexTypeRecursive);
49     return g_plugin_map_mutex;
50 }
51 
52 static PluginTerminateMap &
53 GetPluginMap ()
54 {
55     static PluginTerminateMap g_plugin_map;
56     return g_plugin_map;
57 }
58 
59 static bool
60 PluginIsLoaded (const FileSpec &plugin_file_spec)
61 {
62     Mutex::Locker locker (GetPluginMapMutex ());
63     PluginTerminateMap &plugin_map = GetPluginMap ();
64     return plugin_map.find (plugin_file_spec) != plugin_map.end();
65 }
66 
67 static void
68 SetPluginInfo (const FileSpec &plugin_file_spec, const PluginInfo &plugin_info)
69 {
70     Mutex::Locker locker (GetPluginMapMutex ());
71     PluginTerminateMap &plugin_map = GetPluginMap ();
72     assert (plugin_map.find (plugin_file_spec) != plugin_map.end());
73     plugin_map[plugin_file_spec] = plugin_info;
74 }
75 
76 
77 static FileSpec::EnumerateDirectoryResult
78 LoadPluginCallback
79 (
80     void *baton,
81     FileSpec::FileType file_type,
82     const FileSpec &file_spec
83 )
84 {
85 //    PluginManager *plugin_manager = (PluginManager *)baton;
86     Error error;
87 
88     // If we have a regular file, a symbolic link or unknown file type, try
89     // and process the file. We must handle unknown as sometimes the directory
90     // enumeration might be enumerating a file system that doesn't have correct
91     // file type information.
92     if (file_type == FileSpec::eFileTypeRegular         ||
93         file_type == FileSpec::eFileTypeSymbolicLink    ||
94         file_type == FileSpec::eFileTypeUnknown          )
95     {
96         FileSpec plugin_file_spec (file_spec);
97         plugin_file_spec.ResolvePath();
98 
99         if (PluginIsLoaded (plugin_file_spec))
100             return FileSpec::eEnumerateDirectoryResultNext;
101         else
102         {
103             PluginInfo plugin_info = { NULL, NULL, NULL };
104             uint32_t flags = Host::eDynamicLibraryOpenOptionLazy |
105                              Host::eDynamicLibraryOpenOptionLocal |
106                              Host::eDynamicLibraryOpenOptionLimitGetSymbol;
107 
108             plugin_info.plugin_handle = Host::DynamicLibraryOpen (plugin_file_spec, flags, error);
109             if (plugin_info.plugin_handle)
110             {
111                 bool success = false;
112                 plugin_info.plugin_init_callback = Host::DynamicLibraryGetSymbol (plugin_info.plugin_handle, "LLDBPluginInitialize", error);
113                 if (plugin_info.plugin_init_callback)
114                 {
115                     // Call the plug-in "bool LLDBPluginInitialize(void)" function
116                     success = ((bool (*)(void))plugin_info.plugin_init_callback)();
117                 }
118 
119                 if (success)
120                 {
121                     // It is ok for the "LLDBPluginTerminate" symbol to be NULL
122                     plugin_info.plugin_term_callback = Host::DynamicLibraryGetSymbol (plugin_info.plugin_handle, "LLDBPluginTerminate", error);
123                 }
124                 else
125                 {
126                     // The initialize function returned FALSE which means the
127                     // plug-in might not be compatible, or might be too new or
128                     // too old, or might not want to run on this machine.
129                     Host::DynamicLibraryClose (plugin_info.plugin_handle);
130                     plugin_info.plugin_handle = NULL;
131                     plugin_info.plugin_init_callback = NULL;
132                 }
133 
134                 // Regardless of success or failure, cache the plug-in load
135                 // in our plug-in info so we don't try to load it again and
136                 // again.
137                 SetPluginInfo (plugin_file_spec, plugin_info);
138 
139                 return FileSpec::eEnumerateDirectoryResultNext;
140             }
141         }
142     }
143 
144     if (file_type == FileSpec::eFileTypeUnknown     ||
145         file_type == FileSpec::eFileTypeDirectory   ||
146         file_type == FileSpec::eFileTypeSymbolicLink )
147     {
148         // Try and recurse into anything that a directory or symbolic link.
149         // We must also do this for unknown as sometimes the directory enumeration
150         // might be enurating a file system that doesn't have correct file type
151         // information.
152         return FileSpec::eEnumerateDirectoryResultEnter;
153     }
154 
155     return FileSpec::eEnumerateDirectoryResultNext;
156 }
157 
158 
159 void
160 PluginManager::Initialize ()
161 {
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 (Host::GetLLDBPath (ePathTypeLLDBSystemPlugins, dir_spec))
169     {
170         if (dir_spec.Exists() && dir_spec.GetPath(dir_path, sizeof(dir_path)))
171         {
172             FileSpec::EnumerateDirectory (dir_path,
173                                           find_directories,
174                                           find_files,
175                                           find_other,
176                                           LoadPluginCallback,
177                                           NULL);
178         }
179     }
180 
181     if (Host::GetLLDBPath (ePathTypeLLDBUserPlugins, 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                                           NULL);
191         }
192     }
193 #endif
194 }
195 
196 void
197 PluginManager::Terminate ()
198 {
199     Mutex::Locker locker (GetPluginMapMutex ());
200     PluginTerminateMap &plugin_map = GetPluginMap ();
201 
202     PluginTerminateMap::const_iterator pos, end = plugin_map.end();
203     for (pos = plugin_map.begin(); pos != end; ++pos)
204     {
205         // Call the plug-in "void LLDBPluginTerminate (void)" function if there
206         // is one (if the symbol was not NULL).
207         if (pos->second.plugin_handle)
208         {
209             if (pos->second.plugin_term_callback)
210                 ((void (*)(void))pos->second.plugin_term_callback)();
211             Host::DynamicLibraryClose (pos->second.plugin_handle);
212         }
213     }
214     plugin_map.clear();
215 }
216 
217 
218 #pragma mark ABI
219 
220 
221 struct ABIInstance
222 {
223     ABIInstance() :
224         name(),
225         description(),
226         create_callback(NULL)
227     {
228     }
229 
230     std::string name;
231     std::string description;
232     ABICreateInstance create_callback;
233 };
234 
235 typedef std::vector<ABIInstance> ABIInstances;
236 
237 static Mutex &
238 GetABIInstancesMutex ()
239 {
240     static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive);
241     return g_instances_mutex;
242 }
243 
244 static ABIInstances &
245 GetABIInstances ()
246 {
247     static ABIInstances g_instances;
248     return g_instances;
249 }
250 
251 bool
252 PluginManager::RegisterPlugin
253 (
254     const char *name,
255     const char *description,
256     ABICreateInstance create_callback
257 )
258 {
259     if (create_callback)
260     {
261         ABIInstance instance;
262         assert (name && name[0]);
263         instance.name.assign (name);
264         if (description && description[0])
265             instance.description = description;
266         instance.create_callback = create_callback;
267         Mutex::Locker locker (GetABIInstancesMutex ());
268         GetABIInstances ().push_back (instance);
269         return true;
270     }
271     return false;
272 }
273 
274 bool
275 PluginManager::UnregisterPlugin (ABICreateInstance create_callback)
276 {
277     if (create_callback)
278     {
279         Mutex::Locker locker (GetABIInstancesMutex ());
280         ABIInstances &instances = GetABIInstances ();
281 
282         ABIInstances::iterator pos, end = instances.end();
283         for (pos = instances.begin(); pos != end; ++ pos)
284         {
285             if (pos->create_callback == create_callback)
286             {
287                 instances.erase(pos);
288                 return true;
289             }
290         }
291     }
292     return false;
293 }
294 
295 ABICreateInstance
296 PluginManager::GetABICreateCallbackAtIndex (uint32_t idx)
297 {
298     Mutex::Locker locker (GetABIInstancesMutex ());
299     ABIInstances &instances = GetABIInstances ();
300     if (idx < instances.size())
301         return instances[idx].create_callback;
302     return NULL;
303 }
304 
305 ABICreateInstance
306 PluginManager::GetABICreateCallbackForPluginName (const char *name)
307 {
308     if (name && name[0])
309     {
310         Mutex::Locker locker (GetABIInstancesMutex ());
311         llvm::StringRef name_sref(name);
312         ABIInstances &instances = GetABIInstances ();
313 
314         ABIInstances::iterator pos, end = instances.end();
315         for (pos = instances.begin(); pos != end; ++ pos)
316         {
317             if (name_sref.equals (pos->name))
318                 return pos->create_callback;
319         }
320     }
321     return NULL;
322 }
323 
324 
325 #pragma mark Disassembler
326 
327 
328 struct DisassemblerInstance
329 {
330     DisassemblerInstance() :
331         name(),
332         description(),
333         create_callback(NULL)
334     {
335     }
336 
337     std::string name;
338     std::string description;
339     DisassemblerCreateInstance create_callback;
340 };
341 
342 typedef std::vector<DisassemblerInstance> DisassemblerInstances;
343 
344 static Mutex &
345 GetDisassemblerMutex ()
346 {
347     static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive);
348     return g_instances_mutex;
349 }
350 
351 static DisassemblerInstances &
352 GetDisassemblerInstances ()
353 {
354     static DisassemblerInstances g_instances;
355     return g_instances;
356 }
357 
358 bool
359 PluginManager::RegisterPlugin
360 (
361     const char *name,
362     const char *description,
363     DisassemblerCreateInstance create_callback
364 )
365 {
366     if (create_callback)
367     {
368         DisassemblerInstance instance;
369         assert (name && name[0]);
370         instance.name = name;
371         if (description && description[0])
372             instance.description = description;
373         instance.create_callback = create_callback;
374         Mutex::Locker locker (GetDisassemblerMutex ());
375         GetDisassemblerInstances ().push_back (instance);
376         return true;
377     }
378     return false;
379 }
380 
381 bool
382 PluginManager::UnregisterPlugin (DisassemblerCreateInstance create_callback)
383 {
384     if (create_callback)
385     {
386         Mutex::Locker locker (GetDisassemblerMutex ());
387         DisassemblerInstances &instances = GetDisassemblerInstances ();
388 
389         DisassemblerInstances::iterator pos, end = instances.end();
390         for (pos = instances.begin(); pos != end; ++ pos)
391         {
392             if (pos->create_callback == create_callback)
393             {
394                 instances.erase(pos);
395                 return true;
396             }
397         }
398     }
399     return false;
400 }
401 
402 DisassemblerCreateInstance
403 PluginManager::GetDisassemblerCreateCallbackAtIndex (uint32_t idx)
404 {
405     Mutex::Locker locker (GetDisassemblerMutex ());
406     DisassemblerInstances &instances = GetDisassemblerInstances ();
407     if (idx < instances.size())
408         return instances[idx].create_callback;
409     return NULL;
410 }
411 
412 DisassemblerCreateInstance
413 PluginManager::GetDisassemblerCreateCallbackForPluginName (const char *name)
414 {
415     if (name && name[0])
416     {
417         llvm::StringRef name_sref(name);
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_sref.equals (pos->name))
425                 return pos->create_callback;
426         }
427     }
428     return NULL;
429 }
430 
431 
432 
433 #pragma mark DynamicLoader
434 
435 
436 struct DynamicLoaderInstance
437 {
438     DynamicLoaderInstance() :
439         name(),
440         description(),
441         create_callback(NULL),
442         debugger_init_callback (NULL)
443     {
444     }
445 
446     std::string name;
447     std::string description;
448     DynamicLoaderCreateInstance create_callback;
449     DebuggerInitializeCallback debugger_init_callback;
450 };
451 
452 typedef std::vector<DynamicLoaderInstance> DynamicLoaderInstances;
453 
454 
455 static Mutex &
456 GetDynamicLoaderMutex ()
457 {
458     static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive);
459     return g_instances_mutex;
460 }
461 
462 static DynamicLoaderInstances &
463 GetDynamicLoaderInstances ()
464 {
465     static DynamicLoaderInstances g_instances;
466     return g_instances;
467 }
468 
469 
470 bool
471 PluginManager::RegisterPlugin
472 (
473     const char *name,
474     const char *description,
475     DynamicLoaderCreateInstance create_callback,
476     DebuggerInitializeCallback debugger_init_callback
477 )
478 {
479     if (create_callback)
480     {
481         DynamicLoaderInstance instance;
482         assert (name && name[0]);
483         instance.name = name;
484         if (description && description[0])
485             instance.description = description;
486         instance.create_callback = create_callback;
487         instance.debugger_init_callback = debugger_init_callback;
488         Mutex::Locker locker (GetDynamicLoaderMutex ());
489         GetDynamicLoaderInstances ().push_back (instance);
490     }
491     return false;
492 }
493 
494 bool
495 PluginManager::UnregisterPlugin (DynamicLoaderCreateInstance create_callback)
496 {
497     if (create_callback)
498     {
499         Mutex::Locker locker (GetDynamicLoaderMutex ());
500         DynamicLoaderInstances &instances = GetDynamicLoaderInstances ();
501 
502         DynamicLoaderInstances::iterator pos, end = instances.end();
503         for (pos = instances.begin(); pos != end; ++ pos)
504         {
505             if (pos->create_callback == create_callback)
506             {
507                 instances.erase(pos);
508                 return true;
509             }
510         }
511     }
512     return false;
513 }
514 
515 DynamicLoaderCreateInstance
516 PluginManager::GetDynamicLoaderCreateCallbackAtIndex (uint32_t idx)
517 {
518     Mutex::Locker locker (GetDynamicLoaderMutex ());
519     DynamicLoaderInstances &instances = GetDynamicLoaderInstances ();
520     if (idx < instances.size())
521         return instances[idx].create_callback;
522     return NULL;
523 }
524 
525 DynamicLoaderCreateInstance
526 PluginManager::GetDynamicLoaderCreateCallbackForPluginName (const char *name)
527 {
528     if (name && name[0])
529     {
530         llvm::StringRef name_sref(name);
531         Mutex::Locker locker (GetDynamicLoaderMutex ());
532         DynamicLoaderInstances &instances = GetDynamicLoaderInstances ();
533 
534         DynamicLoaderInstances::iterator pos, end = instances.end();
535         for (pos = instances.begin(); pos != end; ++ pos)
536         {
537             if (name_sref.equals (pos->name))
538                 return pos->create_callback;
539         }
540     }
541     return NULL;
542 }
543 
544 #pragma mark EmulateInstruction
545 
546 
547 struct EmulateInstructionInstance
548 {
549     EmulateInstructionInstance() :
550     name(),
551     description(),
552     create_callback(NULL)
553     {
554     }
555 
556     std::string name;
557     std::string description;
558     EmulateInstructionCreateInstance create_callback;
559 };
560 
561 typedef std::vector<EmulateInstructionInstance> EmulateInstructionInstances;
562 
563 static Mutex &
564 GetEmulateInstructionMutex ()
565 {
566     static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive);
567     return g_instances_mutex;
568 }
569 
570 static EmulateInstructionInstances &
571 GetEmulateInstructionInstances ()
572 {
573     static EmulateInstructionInstances g_instances;
574     return g_instances;
575 }
576 
577 
578 bool
579 PluginManager::RegisterPlugin
580 (
581     const char *name,
582     const char *description,
583     EmulateInstructionCreateInstance create_callback
584 )
585 {
586     if (create_callback)
587     {
588         EmulateInstructionInstance instance;
589         assert (name && name[0]);
590         instance.name = name;
591         if (description && description[0])
592             instance.description = description;
593         instance.create_callback = create_callback;
594         Mutex::Locker locker (GetEmulateInstructionMutex ());
595         GetEmulateInstructionInstances ().push_back (instance);
596     }
597     return false;
598 }
599 
600 bool
601 PluginManager::UnregisterPlugin (EmulateInstructionCreateInstance create_callback)
602 {
603     if (create_callback)
604     {
605         Mutex::Locker locker (GetEmulateInstructionMutex ());
606         EmulateInstructionInstances &instances = GetEmulateInstructionInstances ();
607 
608         EmulateInstructionInstances::iterator pos, end = instances.end();
609         for (pos = instances.begin(); pos != end; ++ pos)
610         {
611             if (pos->create_callback == create_callback)
612             {
613                 instances.erase(pos);
614                 return true;
615             }
616         }
617     }
618     return false;
619 }
620 
621 EmulateInstructionCreateInstance
622 PluginManager::GetEmulateInstructionCreateCallbackAtIndex (uint32_t idx)
623 {
624     Mutex::Locker locker (GetEmulateInstructionMutex ());
625     EmulateInstructionInstances &instances = GetEmulateInstructionInstances ();
626     if (idx < instances.size())
627         return instances[idx].create_callback;
628     return NULL;
629 }
630 
631 EmulateInstructionCreateInstance
632 PluginManager::GetEmulateInstructionCreateCallbackForPluginName (const char *name)
633 {
634     if (name && name[0])
635     {
636         llvm::StringRef name_sref(name);
637         Mutex::Locker locker (GetEmulateInstructionMutex ());
638         EmulateInstructionInstances &instances = GetEmulateInstructionInstances ();
639 
640         EmulateInstructionInstances::iterator pos, end = instances.end();
641         for (pos = instances.begin(); pos != end; ++ pos)
642         {
643             if (name_sref.equals (pos->name))
644                 return pos->create_callback;
645         }
646     }
647     return NULL;
648 }
649 #pragma mark OperatingSystem
650 
651 
652 struct OperatingSystemInstance
653 {
654     OperatingSystemInstance() :
655         name(),
656         description(),
657         create_callback(NULL)
658     {
659     }
660 
661     std::string name;
662     std::string description;
663     OperatingSystemCreateInstance create_callback;
664 };
665 
666 typedef std::vector<OperatingSystemInstance> OperatingSystemInstances;
667 
668 static Mutex &
669 GetOperatingSystemMutex ()
670 {
671     static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive);
672     return g_instances_mutex;
673 }
674 
675 static OperatingSystemInstances &
676 GetOperatingSystemInstances ()
677 {
678     static OperatingSystemInstances g_instances;
679     return g_instances;
680 }
681 
682 bool
683 PluginManager::RegisterPlugin
684 (
685  const char *name,
686  const char *description,
687  OperatingSystemCreateInstance create_callback
688  )
689 {
690     if (create_callback)
691     {
692         OperatingSystemInstance instance;
693         assert (name && name[0]);
694         instance.name = name;
695         if (description && description[0])
696             instance.description = description;
697         instance.create_callback = create_callback;
698         Mutex::Locker locker (GetOperatingSystemMutex ());
699         GetOperatingSystemInstances ().push_back (instance);
700     }
701     return false;
702 }
703 
704 bool
705 PluginManager::UnregisterPlugin (OperatingSystemCreateInstance create_callback)
706 {
707     if (create_callback)
708     {
709         Mutex::Locker locker (GetOperatingSystemMutex ());
710         OperatingSystemInstances &instances = GetOperatingSystemInstances ();
711 
712         OperatingSystemInstances::iterator pos, end = instances.end();
713         for (pos = instances.begin(); pos != end; ++ pos)
714         {
715             if (pos->create_callback == create_callback)
716             {
717                 instances.erase(pos);
718                 return true;
719             }
720         }
721     }
722     return false;
723 }
724 
725 OperatingSystemCreateInstance
726 PluginManager::GetOperatingSystemCreateCallbackAtIndex (uint32_t idx)
727 {
728     Mutex::Locker locker (GetOperatingSystemMutex ());
729     OperatingSystemInstances &instances = GetOperatingSystemInstances ();
730     if (idx < instances.size())
731         return instances[idx].create_callback;
732     return NULL;
733 }
734 
735 OperatingSystemCreateInstance
736 PluginManager::GetOperatingSystemCreateCallbackForPluginName (const char *name)
737 {
738     if (name && name[0])
739     {
740         llvm::StringRef name_sref(name);
741         Mutex::Locker locker (GetOperatingSystemMutex ());
742         OperatingSystemInstances &instances = GetOperatingSystemInstances ();
743 
744         OperatingSystemInstances::iterator pos, end = instances.end();
745         for (pos = instances.begin(); pos != end; ++ pos)
746         {
747             if (name_sref.equals (pos->name))
748                 return pos->create_callback;
749         }
750     }
751     return NULL;
752 }
753 
754 
755 #pragma mark LanguageRuntime
756 
757 
758 struct LanguageRuntimeInstance
759 {
760     LanguageRuntimeInstance() :
761         name(),
762         description(),
763         create_callback(NULL)
764     {
765     }
766 
767     std::string name;
768     std::string description;
769     LanguageRuntimeCreateInstance create_callback;
770 };
771 
772 typedef std::vector<LanguageRuntimeInstance> LanguageRuntimeInstances;
773 
774 static Mutex &
775 GetLanguageRuntimeMutex ()
776 {
777     static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive);
778     return g_instances_mutex;
779 }
780 
781 static LanguageRuntimeInstances &
782 GetLanguageRuntimeInstances ()
783 {
784     static LanguageRuntimeInstances g_instances;
785     return g_instances;
786 }
787 
788 bool
789 PluginManager::RegisterPlugin
790 (
791     const char *name,
792     const char *description,
793     LanguageRuntimeCreateInstance create_callback
794 )
795 {
796     if (create_callback)
797     {
798         LanguageRuntimeInstance instance;
799         assert (name && name[0]);
800         instance.name = name;
801         if (description && description[0])
802             instance.description = description;
803         instance.create_callback = create_callback;
804         Mutex::Locker locker (GetLanguageRuntimeMutex ());
805         GetLanguageRuntimeInstances ().push_back (instance);
806     }
807     return false;
808 }
809 
810 bool
811 PluginManager::UnregisterPlugin (LanguageRuntimeCreateInstance create_callback)
812 {
813     if (create_callback)
814     {
815         Mutex::Locker locker (GetLanguageRuntimeMutex ());
816         LanguageRuntimeInstances &instances = GetLanguageRuntimeInstances ();
817 
818         LanguageRuntimeInstances::iterator pos, end = instances.end();
819         for (pos = instances.begin(); pos != end; ++ pos)
820         {
821             if (pos->create_callback == create_callback)
822             {
823                 instances.erase(pos);
824                 return true;
825             }
826         }
827     }
828     return false;
829 }
830 
831 LanguageRuntimeCreateInstance
832 PluginManager::GetLanguageRuntimeCreateCallbackAtIndex (uint32_t idx)
833 {
834     Mutex::Locker locker (GetLanguageRuntimeMutex ());
835     LanguageRuntimeInstances &instances = GetLanguageRuntimeInstances ();
836     if (idx < instances.size())
837         return instances[idx].create_callback;
838     return NULL;
839 }
840 
841 LanguageRuntimeCreateInstance
842 PluginManager::GetLanguageRuntimeCreateCallbackForPluginName (const char *name)
843 {
844     if (name && name[0])
845     {
846         llvm::StringRef name_sref(name);
847         Mutex::Locker locker (GetLanguageRuntimeMutex ());
848         LanguageRuntimeInstances &instances = GetLanguageRuntimeInstances ();
849 
850         LanguageRuntimeInstances::iterator pos, end = instances.end();
851         for (pos = instances.begin(); pos != end; ++ pos)
852         {
853             if (name_sref.equals (pos->name))
854                 return pos->create_callback;
855         }
856     }
857     return NULL;
858 }
859 
860 #pragma mark ObjectFile
861 
862 struct ObjectFileInstance
863 {
864     ObjectFileInstance() :
865         name(),
866         description(),
867         create_callback(NULL)
868     {
869     }
870 
871     std::string name;
872     std::string description;
873     ObjectFileCreateInstance create_callback;
874     ObjectFileCreateMemoryInstance create_memory_callback;
875 
876 };
877 
878 typedef std::vector<ObjectFileInstance> ObjectFileInstances;
879 
880 static Mutex &
881 GetObjectFileMutex ()
882 {
883     static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive);
884     return g_instances_mutex;
885 }
886 
887 static ObjectFileInstances &
888 GetObjectFileInstances ()
889 {
890     static ObjectFileInstances g_instances;
891     return g_instances;
892 }
893 
894 
895 bool
896 PluginManager::RegisterPlugin
897 (
898     const char *name,
899     const char *description,
900     ObjectFileCreateInstance create_callback,
901     ObjectFileCreateMemoryInstance create_memory_callback
902 )
903 {
904     if (create_callback)
905     {
906         ObjectFileInstance instance;
907         assert (name && name[0]);
908         instance.name = name;
909         if (description && description[0])
910             instance.description = description;
911         instance.create_callback = create_callback;
912         instance.create_memory_callback = create_memory_callback;
913         Mutex::Locker locker (GetObjectFileMutex ());
914         GetObjectFileInstances ().push_back (instance);
915     }
916     return false;
917 }
918 
919 bool
920 PluginManager::UnregisterPlugin (ObjectFileCreateInstance create_callback)
921 {
922     if (create_callback)
923     {
924         Mutex::Locker locker (GetObjectFileMutex ());
925         ObjectFileInstances &instances = GetObjectFileInstances ();
926 
927         ObjectFileInstances::iterator pos, end = instances.end();
928         for (pos = instances.begin(); pos != end; ++ pos)
929         {
930             if (pos->create_callback == create_callback)
931             {
932                 instances.erase(pos);
933                 return true;
934             }
935         }
936     }
937     return false;
938 }
939 
940 ObjectFileCreateInstance
941 PluginManager::GetObjectFileCreateCallbackAtIndex (uint32_t idx)
942 {
943     Mutex::Locker locker (GetObjectFileMutex ());
944     ObjectFileInstances &instances = GetObjectFileInstances ();
945     if (idx < instances.size())
946         return instances[idx].create_callback;
947     return NULL;
948 }
949 
950 
951 ObjectFileCreateMemoryInstance
952 PluginManager::GetObjectFileCreateMemoryCallbackAtIndex (uint32_t idx)
953 {
954     Mutex::Locker locker (GetObjectFileMutex ());
955     ObjectFileInstances &instances = GetObjectFileInstances ();
956     if (idx < instances.size())
957         return instances[idx].create_memory_callback;
958     return NULL;
959 }
960 
961 ObjectFileCreateInstance
962 PluginManager::GetObjectFileCreateCallbackForPluginName (const char *name)
963 {
964     if (name && name[0])
965     {
966         llvm::StringRef name_sref(name);
967         Mutex::Locker locker (GetObjectFileMutex ());
968         ObjectFileInstances &instances = GetObjectFileInstances ();
969 
970         ObjectFileInstances::iterator pos, end = instances.end();
971         for (pos = instances.begin(); pos != end; ++ pos)
972         {
973             if (name_sref.equals (pos->name))
974                 return pos->create_callback;
975         }
976     }
977     return NULL;
978 }
979 
980 
981 ObjectFileCreateMemoryInstance
982 PluginManager::GetObjectFileCreateMemoryCallbackForPluginName (const char *name)
983 {
984     if (name && name[0])
985     {
986         llvm::StringRef name_sref(name);
987         Mutex::Locker locker (GetObjectFileMutex ());
988         ObjectFileInstances &instances = GetObjectFileInstances ();
989 
990         ObjectFileInstances::iterator pos, end = instances.end();
991         for (pos = instances.begin(); pos != end; ++ pos)
992         {
993             if (name_sref.equals (pos->name))
994                 return pos->create_memory_callback;
995         }
996     }
997     return NULL;
998 }
999 
1000 
1001 
1002 #pragma mark ObjectContainer
1003 
1004 struct ObjectContainerInstance
1005 {
1006     ObjectContainerInstance() :
1007         name(),
1008         description(),
1009         create_callback(NULL)
1010     {
1011     }
1012 
1013     std::string name;
1014     std::string description;
1015     ObjectContainerCreateInstance create_callback;
1016 };
1017 
1018 typedef std::vector<ObjectContainerInstance> ObjectContainerInstances;
1019 
1020 static Mutex &
1021 GetObjectContainerMutex ()
1022 {
1023     static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive);
1024     return g_instances_mutex;
1025 }
1026 
1027 static ObjectContainerInstances &
1028 GetObjectContainerInstances ()
1029 {
1030     static ObjectContainerInstances g_instances;
1031     return g_instances;
1032 }
1033 
1034 bool
1035 PluginManager::RegisterPlugin
1036 (
1037     const char *name,
1038     const char *description,
1039     ObjectContainerCreateInstance create_callback
1040 )
1041 {
1042     if (create_callback)
1043     {
1044         ObjectContainerInstance instance;
1045         assert (name && name[0]);
1046         instance.name = name;
1047         if (description && description[0])
1048             instance.description = description;
1049         instance.create_callback = create_callback;
1050         Mutex::Locker locker (GetObjectContainerMutex ());
1051         GetObjectContainerInstances ().push_back (instance);
1052     }
1053     return false;
1054 }
1055 
1056 bool
1057 PluginManager::UnregisterPlugin (ObjectContainerCreateInstance create_callback)
1058 {
1059     if (create_callback)
1060     {
1061         Mutex::Locker locker (GetObjectContainerMutex ());
1062         ObjectContainerInstances &instances = GetObjectContainerInstances ();
1063 
1064         ObjectContainerInstances::iterator pos, end = instances.end();
1065         for (pos = instances.begin(); pos != end; ++ pos)
1066         {
1067             if (pos->create_callback == create_callback)
1068             {
1069                 instances.erase(pos);
1070                 return true;
1071             }
1072         }
1073     }
1074     return false;
1075 }
1076 
1077 ObjectContainerCreateInstance
1078 PluginManager::GetObjectContainerCreateCallbackAtIndex (uint32_t idx)
1079 {
1080     Mutex::Locker locker (GetObjectContainerMutex ());
1081     ObjectContainerInstances &instances = GetObjectContainerInstances ();
1082     if (idx < instances.size())
1083         return instances[idx].create_callback;
1084     return NULL;
1085 }
1086 
1087 ObjectContainerCreateInstance
1088 PluginManager::GetObjectContainerCreateCallbackForPluginName (const char *name)
1089 {
1090     if (name && name[0])
1091     {
1092         llvm::StringRef name_sref(name);
1093         Mutex::Locker locker (GetObjectContainerMutex ());
1094         ObjectContainerInstances &instances = GetObjectContainerInstances ();
1095 
1096         ObjectContainerInstances::iterator pos, end = instances.end();
1097         for (pos = instances.begin(); pos != end; ++ pos)
1098         {
1099             if (name_sref.equals (pos->name))
1100                 return pos->create_callback;
1101         }
1102     }
1103     return NULL;
1104 }
1105 
1106 #pragma mark LogChannel
1107 
1108 struct LogInstance
1109 {
1110     LogInstance() :
1111         name(),
1112         description(),
1113         create_callback(NULL)
1114     {
1115     }
1116 
1117     std::string name;
1118     std::string description;
1119     LogChannelCreateInstance create_callback;
1120 };
1121 
1122 typedef std::vector<LogInstance> LogInstances;
1123 
1124 static Mutex &
1125 GetLogMutex ()
1126 {
1127     static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive);
1128     return g_instances_mutex;
1129 }
1130 
1131 static LogInstances &
1132 GetLogInstances ()
1133 {
1134     static LogInstances g_instances;
1135     return g_instances;
1136 }
1137 
1138 
1139 
1140 bool
1141 PluginManager::RegisterPlugin
1142 (
1143     const char *name,
1144     const char *description,
1145     LogChannelCreateInstance create_callback
1146 )
1147 {
1148     if (create_callback)
1149     {
1150         LogInstance instance;
1151         assert (name && name[0]);
1152         instance.name = name;
1153         if (description && description[0])
1154             instance.description = description;
1155         instance.create_callback = create_callback;
1156         Mutex::Locker locker (GetLogMutex ());
1157         GetLogInstances ().push_back (instance);
1158     }
1159     return false;
1160 }
1161 
1162 bool
1163 PluginManager::UnregisterPlugin (LogChannelCreateInstance create_callback)
1164 {
1165     if (create_callback)
1166     {
1167         Mutex::Locker locker (GetLogMutex ());
1168         LogInstances &instances = GetLogInstances ();
1169 
1170         LogInstances::iterator pos, end = instances.end();
1171         for (pos = instances.begin(); pos != end; ++ pos)
1172         {
1173             if (pos->create_callback == create_callback)
1174             {
1175                 instances.erase(pos);
1176                 return true;
1177             }
1178         }
1179     }
1180     return false;
1181 }
1182 
1183 const char *
1184 PluginManager::GetLogChannelCreateNameAtIndex (uint32_t idx)
1185 {
1186     Mutex::Locker locker (GetLogMutex ());
1187     LogInstances &instances = GetLogInstances ();
1188     if (idx < instances.size())
1189         return instances[idx].name.c_str();
1190     return NULL;
1191 }
1192 
1193 
1194 LogChannelCreateInstance
1195 PluginManager::GetLogChannelCreateCallbackAtIndex (uint32_t idx)
1196 {
1197     Mutex::Locker locker (GetLogMutex ());
1198     LogInstances &instances = GetLogInstances ();
1199     if (idx < instances.size())
1200         return instances[idx].create_callback;
1201     return NULL;
1202 }
1203 
1204 LogChannelCreateInstance
1205 PluginManager::GetLogChannelCreateCallbackForPluginName (const char *name)
1206 {
1207     if (name && name[0])
1208     {
1209         llvm::StringRef name_sref(name);
1210         Mutex::Locker locker (GetLogMutex ());
1211         LogInstances &instances = GetLogInstances ();
1212 
1213         LogInstances::iterator pos, end = instances.end();
1214         for (pos = instances.begin(); pos != end; ++ pos)
1215         {
1216             if (name_sref.equals (pos->name))
1217                 return pos->create_callback;
1218         }
1219     }
1220     return NULL;
1221 }
1222 
1223 #pragma mark Platform
1224 
1225 struct PlatformInstance
1226 {
1227     PlatformInstance() :
1228         name(),
1229         description(),
1230         create_callback(NULL)
1231     {
1232     }
1233 
1234     std::string name;
1235     std::string description;
1236     PlatformCreateInstance create_callback;
1237 };
1238 
1239 typedef std::vector<PlatformInstance> PlatformInstances;
1240 
1241 static Mutex &
1242 GetPlatformInstancesMutex ()
1243 {
1244     static Mutex g_platform_instances_mutex (Mutex::eMutexTypeRecursive);
1245     return g_platform_instances_mutex;
1246 }
1247 
1248 static PlatformInstances &
1249 GetPlatformInstances ()
1250 {
1251     static PlatformInstances g_platform_instances;
1252     return g_platform_instances;
1253 }
1254 
1255 
1256 bool
1257 PluginManager::RegisterPlugin (const char *name,
1258                                const char *description,
1259                                PlatformCreateInstance create_callback)
1260 {
1261     if (create_callback)
1262     {
1263         Mutex::Locker locker (GetPlatformInstancesMutex ());
1264 
1265         PlatformInstance instance;
1266         assert (name && name[0]);
1267         instance.name = name;
1268         if (description && description[0])
1269             instance.description = description;
1270         instance.create_callback = create_callback;
1271         GetPlatformInstances ().push_back (instance);
1272         return true;
1273     }
1274     return false;
1275 }
1276 
1277 const char *
1278 PluginManager::GetPlatformPluginNameAtIndex (uint32_t idx)
1279 {
1280     Mutex::Locker locker (GetPlatformInstancesMutex ());
1281     PlatformInstances &instances = GetPlatformInstances ();
1282     if (idx < instances.size())
1283         return instances[idx].name.c_str();
1284     return NULL;
1285 }
1286 
1287 const char *
1288 PluginManager::GetPlatformPluginDescriptionAtIndex (uint32_t idx)
1289 {
1290     Mutex::Locker locker (GetPlatformInstancesMutex ());
1291     PlatformInstances &instances = GetPlatformInstances ();
1292     if (idx < instances.size())
1293         return instances[idx].description.c_str();
1294     return NULL;
1295 }
1296 
1297 bool
1298 PluginManager::UnregisterPlugin (PlatformCreateInstance create_callback)
1299 {
1300     if (create_callback)
1301     {
1302         Mutex::Locker locker (GetPlatformInstancesMutex ());
1303         PlatformInstances &instances = GetPlatformInstances ();
1304 
1305         PlatformInstances::iterator pos, end = instances.end();
1306         for (pos = instances.begin(); pos != end; ++ pos)
1307         {
1308             if (pos->create_callback == create_callback)
1309             {
1310                 instances.erase(pos);
1311                 return true;
1312             }
1313         }
1314     }
1315     return false;
1316 }
1317 
1318 PlatformCreateInstance
1319 PluginManager::GetPlatformCreateCallbackAtIndex (uint32_t idx)
1320 {
1321     Mutex::Locker locker (GetPlatformInstancesMutex ());
1322     PlatformInstances &instances = GetPlatformInstances ();
1323     if (idx < instances.size())
1324         return instances[idx].create_callback;
1325     return NULL;
1326 }
1327 
1328 PlatformCreateInstance
1329 PluginManager::GetPlatformCreateCallbackForPluginName (const char *name)
1330 {
1331     if (name && name[0])
1332     {
1333         Mutex::Locker locker (GetPlatformInstancesMutex ());
1334         PlatformInstances &instances = GetPlatformInstances ();
1335         llvm::StringRef name_sref(name);
1336 
1337         PlatformInstances::iterator pos, end = instances.end();
1338         for (pos = instances.begin(); pos != end; ++ pos)
1339         {
1340             if (name_sref.equals (pos->name))
1341                 return pos->create_callback;
1342         }
1343     }
1344     return NULL;
1345 }
1346 
1347 uint32_t
1348 PluginManager::AutoCompletePlatformName (const char *name, StringList &matches)
1349 {
1350     if (name && name[0])
1351     {
1352         Mutex::Locker locker (GetPlatformInstancesMutex ());
1353         PlatformInstances &instances = GetPlatformInstances ();
1354         llvm::StringRef name_sref(name);
1355 
1356         PlatformInstances::iterator pos, end = instances.end();
1357         for (pos = instances.begin(); pos != end; ++ pos)
1358         {
1359             llvm::StringRef plugin_name (pos->name);
1360             if (plugin_name.startswith(name_sref))
1361                 matches.AppendString (plugin_name.data());
1362         }
1363     }
1364     return matches.GetSize();
1365 }
1366 
1367 #pragma mark Process
1368 
1369 struct ProcessInstance
1370 {
1371     ProcessInstance() :
1372     name(),
1373     description(),
1374     create_callback(NULL)
1375     {
1376     }
1377 
1378     std::string name;
1379     std::string description;
1380     ProcessCreateInstance create_callback;
1381 };
1382 
1383 typedef std::vector<ProcessInstance> ProcessInstances;
1384 
1385 static Mutex &
1386 GetProcessMutex ()
1387 {
1388     static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive);
1389     return g_instances_mutex;
1390 }
1391 
1392 static ProcessInstances &
1393 GetProcessInstances ()
1394 {
1395     static ProcessInstances g_instances;
1396     return g_instances;
1397 }
1398 
1399 
1400 bool
1401 PluginManager::RegisterPlugin
1402 (
1403  const char *name,
1404  const char *description,
1405  ProcessCreateInstance create_callback
1406  )
1407 {
1408     if (create_callback)
1409     {
1410         ProcessInstance instance;
1411         assert (name && name[0]);
1412         instance.name = name;
1413         if (description && description[0])
1414             instance.description = description;
1415         instance.create_callback = create_callback;
1416         Mutex::Locker locker (GetProcessMutex ());
1417         GetProcessInstances ().push_back (instance);
1418     }
1419     return false;
1420 }
1421 
1422 const char *
1423 PluginManager::GetProcessPluginNameAtIndex (uint32_t idx)
1424 {
1425     Mutex::Locker locker (GetProcessMutex ());
1426     ProcessInstances &instances = GetProcessInstances ();
1427     if (idx < instances.size())
1428         return instances[idx].name.c_str();
1429     return NULL;
1430 }
1431 
1432 const char *
1433 PluginManager::GetProcessPluginDescriptionAtIndex (uint32_t idx)
1434 {
1435     Mutex::Locker locker (GetProcessMutex ());
1436     ProcessInstances &instances = GetProcessInstances ();
1437     if (idx < instances.size())
1438         return instances[idx].description.c_str();
1439     return NULL;
1440 }
1441 
1442 bool
1443 PluginManager::UnregisterPlugin (ProcessCreateInstance create_callback)
1444 {
1445     if (create_callback)
1446     {
1447         Mutex::Locker locker (GetProcessMutex ());
1448         ProcessInstances &instances = GetProcessInstances ();
1449 
1450         ProcessInstances::iterator pos, end = instances.end();
1451         for (pos = instances.begin(); pos != end; ++ pos)
1452         {
1453             if (pos->create_callback == create_callback)
1454             {
1455                 instances.erase(pos);
1456                 return true;
1457             }
1458         }
1459     }
1460     return false;
1461 }
1462 
1463 ProcessCreateInstance
1464 PluginManager::GetProcessCreateCallbackAtIndex (uint32_t idx)
1465 {
1466     Mutex::Locker locker (GetProcessMutex ());
1467     ProcessInstances &instances = GetProcessInstances ();
1468     if (idx < instances.size())
1469         return instances[idx].create_callback;
1470     return NULL;
1471 }
1472 
1473 
1474 ProcessCreateInstance
1475 PluginManager::GetProcessCreateCallbackForPluginName (const char *name)
1476 {
1477     if (name && name[0])
1478     {
1479         llvm::StringRef name_sref(name);
1480         Mutex::Locker locker (GetProcessMutex ());
1481         ProcessInstances &instances = GetProcessInstances ();
1482 
1483         ProcessInstances::iterator pos, end = instances.end();
1484         for (pos = instances.begin(); pos != end; ++ pos)
1485         {
1486             if (name_sref.equals (pos->name))
1487                 return pos->create_callback;
1488         }
1489     }
1490     return NULL;
1491 }
1492 
1493 #pragma mark SymbolFile
1494 
1495 struct SymbolFileInstance
1496 {
1497     SymbolFileInstance() :
1498         name(),
1499         description(),
1500         create_callback(NULL)
1501     {
1502     }
1503 
1504     std::string name;
1505     std::string description;
1506     SymbolFileCreateInstance create_callback;
1507 };
1508 
1509 typedef std::vector<SymbolFileInstance> SymbolFileInstances;
1510 
1511 static Mutex &
1512 GetSymbolFileMutex ()
1513 {
1514     static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive);
1515     return g_instances_mutex;
1516 }
1517 
1518 static SymbolFileInstances &
1519 GetSymbolFileInstances ()
1520 {
1521     static SymbolFileInstances g_instances;
1522     return g_instances;
1523 }
1524 
1525 
1526 bool
1527 PluginManager::RegisterPlugin
1528 (
1529     const char *name,
1530     const char *description,
1531     SymbolFileCreateInstance create_callback
1532 )
1533 {
1534     if (create_callback)
1535     {
1536         SymbolFileInstance instance;
1537         assert (name && name[0]);
1538         instance.name = name;
1539         if (description && description[0])
1540             instance.description = description;
1541         instance.create_callback = create_callback;
1542         Mutex::Locker locker (GetSymbolFileMutex ());
1543         GetSymbolFileInstances ().push_back (instance);
1544     }
1545     return false;
1546 }
1547 
1548 bool
1549 PluginManager::UnregisterPlugin (SymbolFileCreateInstance create_callback)
1550 {
1551     if (create_callback)
1552     {
1553         Mutex::Locker locker (GetSymbolFileMutex ());
1554         SymbolFileInstances &instances = GetSymbolFileInstances ();
1555 
1556         SymbolFileInstances::iterator pos, end = instances.end();
1557         for (pos = instances.begin(); pos != end; ++ pos)
1558         {
1559             if (pos->create_callback == create_callback)
1560             {
1561                 instances.erase(pos);
1562                 return true;
1563             }
1564         }
1565     }
1566     return false;
1567 }
1568 
1569 SymbolFileCreateInstance
1570 PluginManager::GetSymbolFileCreateCallbackAtIndex (uint32_t idx)
1571 {
1572     Mutex::Locker locker (GetSymbolFileMutex ());
1573     SymbolFileInstances &instances = GetSymbolFileInstances ();
1574     if (idx < instances.size())
1575         return instances[idx].create_callback;
1576     return NULL;
1577 }
1578 
1579 SymbolFileCreateInstance
1580 PluginManager::GetSymbolFileCreateCallbackForPluginName (const char *name)
1581 {
1582     if (name && name[0])
1583     {
1584         llvm::StringRef name_sref(name);
1585         Mutex::Locker locker (GetSymbolFileMutex ());
1586         SymbolFileInstances &instances = GetSymbolFileInstances ();
1587 
1588         SymbolFileInstances::iterator pos, end = instances.end();
1589         for (pos = instances.begin(); pos != end; ++ pos)
1590         {
1591             if (name_sref.equals (pos->name))
1592                 return pos->create_callback;
1593         }
1594     }
1595     return NULL;
1596 }
1597 
1598 
1599 
1600 #pragma mark SymbolVendor
1601 
1602 struct SymbolVendorInstance
1603 {
1604     SymbolVendorInstance() :
1605         name(),
1606         description(),
1607         create_callback(NULL)
1608     {
1609     }
1610 
1611     std::string name;
1612     std::string description;
1613     SymbolVendorCreateInstance create_callback;
1614 };
1615 
1616 typedef std::vector<SymbolVendorInstance> SymbolVendorInstances;
1617 
1618 static Mutex &
1619 GetSymbolVendorMutex ()
1620 {
1621     static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive);
1622     return g_instances_mutex;
1623 }
1624 
1625 static SymbolVendorInstances &
1626 GetSymbolVendorInstances ()
1627 {
1628     static SymbolVendorInstances g_instances;
1629     return g_instances;
1630 }
1631 
1632 bool
1633 PluginManager::RegisterPlugin
1634 (
1635     const char *name,
1636     const char *description,
1637     SymbolVendorCreateInstance create_callback
1638 )
1639 {
1640     if (create_callback)
1641     {
1642         SymbolVendorInstance instance;
1643         assert (name && name[0]);
1644         instance.name = name;
1645         if (description && description[0])
1646             instance.description = description;
1647         instance.create_callback = create_callback;
1648         Mutex::Locker locker (GetSymbolVendorMutex ());
1649         GetSymbolVendorInstances ().push_back (instance);
1650     }
1651     return false;
1652 }
1653 
1654 bool
1655 PluginManager::UnregisterPlugin (SymbolVendorCreateInstance create_callback)
1656 {
1657     if (create_callback)
1658     {
1659         Mutex::Locker locker (GetSymbolVendorMutex ());
1660         SymbolVendorInstances &instances = GetSymbolVendorInstances ();
1661 
1662         SymbolVendorInstances::iterator pos, end = instances.end();
1663         for (pos = instances.begin(); pos != end; ++ pos)
1664         {
1665             if (pos->create_callback == create_callback)
1666             {
1667                 instances.erase(pos);
1668                 return true;
1669             }
1670         }
1671     }
1672     return false;
1673 }
1674 
1675 SymbolVendorCreateInstance
1676 PluginManager::GetSymbolVendorCreateCallbackAtIndex (uint32_t idx)
1677 {
1678     Mutex::Locker locker (GetSymbolVendorMutex ());
1679     SymbolVendorInstances &instances = GetSymbolVendorInstances ();
1680     if (idx < instances.size())
1681         return instances[idx].create_callback;
1682     return NULL;
1683 }
1684 
1685 
1686 SymbolVendorCreateInstance
1687 PluginManager::GetSymbolVendorCreateCallbackForPluginName (const char *name)
1688 {
1689     if (name && name[0])
1690     {
1691         llvm::StringRef name_sref(name);
1692         Mutex::Locker locker (GetSymbolVendorMutex ());
1693         SymbolVendorInstances &instances = GetSymbolVendorInstances ();
1694 
1695         SymbolVendorInstances::iterator pos, end = instances.end();
1696         for (pos = instances.begin(); pos != end; ++ pos)
1697         {
1698             if (name_sref.equals (pos->name))
1699                 return pos->create_callback;
1700         }
1701     }
1702     return NULL;
1703 }
1704 
1705 
1706 #pragma mark UnwindAssembly
1707 
1708 struct UnwindAssemblyInstance
1709 {
1710     UnwindAssemblyInstance() :
1711         name(),
1712         description(),
1713         create_callback(NULL)
1714     {
1715     }
1716 
1717     std::string name;
1718     std::string description;
1719     UnwindAssemblyCreateInstance create_callback;
1720 };
1721 
1722 typedef std::vector<UnwindAssemblyInstance> UnwindAssemblyInstances;
1723 
1724 static Mutex &
1725 GetUnwindAssemblyMutex ()
1726 {
1727     static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive);
1728     return g_instances_mutex;
1729 }
1730 
1731 static UnwindAssemblyInstances &
1732 GetUnwindAssemblyInstances ()
1733 {
1734     static UnwindAssemblyInstances g_instances;
1735     return g_instances;
1736 }
1737 
1738 bool
1739 PluginManager::RegisterPlugin
1740 (
1741     const char *name,
1742     const char *description,
1743     UnwindAssemblyCreateInstance create_callback
1744 )
1745 {
1746     if (create_callback)
1747     {
1748         UnwindAssemblyInstance instance;
1749         assert (name && name[0]);
1750         instance.name = name;
1751         if (description && description[0])
1752             instance.description = description;
1753         instance.create_callback = create_callback;
1754         Mutex::Locker locker (GetUnwindAssemblyMutex ());
1755         GetUnwindAssemblyInstances ().push_back (instance);
1756     }
1757     return false;
1758 }
1759 
1760 bool
1761 PluginManager::UnregisterPlugin (UnwindAssemblyCreateInstance create_callback)
1762 {
1763     if (create_callback)
1764     {
1765         Mutex::Locker locker (GetUnwindAssemblyMutex ());
1766         UnwindAssemblyInstances &instances = GetUnwindAssemblyInstances ();
1767 
1768         UnwindAssemblyInstances::iterator pos, end = instances.end();
1769         for (pos = instances.begin(); pos != end; ++ pos)
1770         {
1771             if (pos->create_callback == create_callback)
1772             {
1773                 instances.erase(pos);
1774                 return true;
1775             }
1776         }
1777     }
1778     return false;
1779 }
1780 
1781 UnwindAssemblyCreateInstance
1782 PluginManager::GetUnwindAssemblyCreateCallbackAtIndex (uint32_t idx)
1783 {
1784     Mutex::Locker locker (GetUnwindAssemblyMutex ());
1785     UnwindAssemblyInstances &instances = GetUnwindAssemblyInstances ();
1786     if (idx < instances.size())
1787         return instances[idx].create_callback;
1788     return NULL;
1789 }
1790 
1791 
1792 UnwindAssemblyCreateInstance
1793 PluginManager::GetUnwindAssemblyCreateCallbackForPluginName (const char *name)
1794 {
1795     if (name && name[0])
1796     {
1797         llvm::StringRef name_sref(name);
1798         Mutex::Locker locker (GetUnwindAssemblyMutex ());
1799         UnwindAssemblyInstances &instances = GetUnwindAssemblyInstances ();
1800 
1801         UnwindAssemblyInstances::iterator pos, end = instances.end();
1802         for (pos = instances.begin(); pos != end; ++ pos)
1803         {
1804             if (name_sref.equals (pos->name))
1805                 return pos->create_callback;
1806         }
1807     }
1808     return NULL;
1809 }
1810 
1811 void
1812 PluginManager::DebuggerInitialize (Debugger &debugger)
1813 {
1814     Mutex::Locker locker (GetDynamicLoaderMutex ());
1815     DynamicLoaderInstances &instances = GetDynamicLoaderInstances ();
1816 
1817     DynamicLoaderInstances::iterator pos, end = instances.end();
1818     for (pos = instances.begin(); pos != end; ++ pos)
1819     {
1820         if (pos->debugger_init_callback)
1821             pos->debugger_init_callback (debugger);
1822     }
1823 }
1824 
1825 static lldb::OptionValuePropertiesSP
1826 GetDebuggerPropertyForPlugins (Debugger &debugger,
1827                                const ConstString &plugin_type_name,
1828                                const ConstString &plugin_type_desc,
1829                                bool can_create)
1830 {
1831     lldb::OptionValuePropertiesSP parent_properties_sp (debugger.GetValueProperties());
1832     if (parent_properties_sp)
1833     {
1834         static ConstString g_property_name("plugin");
1835 
1836         OptionValuePropertiesSP plugin_properties_sp = parent_properties_sp->GetSubProperty (NULL, g_property_name);
1837         if (!plugin_properties_sp && can_create)
1838         {
1839             plugin_properties_sp.reset (new OptionValueProperties (g_property_name));
1840             parent_properties_sp->AppendProperty (g_property_name,
1841                                                   ConstString("Settings specify to plugins."),
1842                                                   true,
1843                                                   plugin_properties_sp);
1844         }
1845 
1846         if (plugin_properties_sp)
1847         {
1848             lldb::OptionValuePropertiesSP plugin_type_properties_sp = plugin_properties_sp->GetSubProperty (NULL, plugin_type_name);
1849             if (!plugin_type_properties_sp && can_create)
1850             {
1851                 plugin_type_properties_sp.reset (new OptionValueProperties (plugin_type_name));
1852                 plugin_properties_sp->AppendProperty (plugin_type_name,
1853                                                       plugin_type_desc,
1854                                                       true,
1855                                                       plugin_type_properties_sp);
1856             }
1857             return plugin_type_properties_sp;
1858         }
1859     }
1860     return lldb::OptionValuePropertiesSP();
1861 }
1862 
1863 lldb::OptionValuePropertiesSP
1864 PluginManager::GetSettingForDynamicLoaderPlugin (Debugger &debugger, const ConstString &setting_name)
1865 {
1866     lldb::OptionValuePropertiesSP properties_sp;
1867     lldb::OptionValuePropertiesSP plugin_type_properties_sp (GetDebuggerPropertyForPlugins (debugger,
1868                                                                                             ConstString("dynamic-loader"),
1869                                                                                             ConstString(), // not creating to so we don't need the description
1870                                                                                             false));
1871     if (plugin_type_properties_sp)
1872         properties_sp = plugin_type_properties_sp->GetSubProperty (NULL, setting_name);
1873     return properties_sp;
1874 }
1875 
1876 bool
1877 PluginManager::CreateSettingForDynamicLoaderPlugin (Debugger &debugger,
1878                                                     const lldb::OptionValuePropertiesSP &properties_sp,
1879                                                     const ConstString &description,
1880                                                     bool is_global_property)
1881 {
1882     if (properties_sp)
1883     {
1884         lldb::OptionValuePropertiesSP plugin_type_properties_sp (GetDebuggerPropertyForPlugins (debugger,
1885                                                                                                 ConstString("dynamic-loader"),
1886                                                                                                 ConstString("Settings for dynamic loader plug-ins"),
1887                                                                                                 true));
1888         if (plugin_type_properties_sp)
1889         {
1890             plugin_type_properties_sp->AppendProperty (properties_sp->GetName(),
1891                                                        description,
1892                                                        is_global_property,
1893                                                        properties_sp);
1894             return true;
1895         }
1896     }
1897     return false;
1898 }
1899 
1900