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