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