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     ObjectFileCreateMemoryInstance create_memory_callback;
869 
870 };
871 
872 typedef std::vector<ObjectFileInstance> ObjectFileInstances;
873 
874 static Mutex &
875 GetObjectFileMutex ()
876 {
877     static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive);
878     return g_instances_mutex;
879 }
880 
881 static ObjectFileInstances &
882 GetObjectFileInstances ()
883 {
884     static ObjectFileInstances g_instances;
885     return g_instances;
886 }
887 
888 
889 bool
890 PluginManager::RegisterPlugin
891 (
892     const char *name,
893     const char *description,
894     ObjectFileCreateInstance create_callback,
895     ObjectFileCreateMemoryInstance create_memory_callback
896 )
897 {
898     if (create_callback)
899     {
900         ObjectFileInstance instance;
901         assert (name && name[0]);
902         instance.name = name;
903         if (description && description[0])
904             instance.description = description;
905         instance.create_callback = create_callback;
906         instance.create_memory_callback = create_memory_callback;
907         Mutex::Locker locker (GetObjectFileMutex ());
908         GetObjectFileInstances ().push_back (instance);
909     }
910     return false;
911 }
912 
913 bool
914 PluginManager::UnregisterPlugin (ObjectFileCreateInstance create_callback)
915 {
916     if (create_callback)
917     {
918         Mutex::Locker locker (GetObjectFileMutex ());
919         ObjectFileInstances &instances = GetObjectFileInstances ();
920 
921         ObjectFileInstances::iterator pos, end = instances.end();
922         for (pos = instances.begin(); pos != end; ++ pos)
923         {
924             if (pos->create_callback == create_callback)
925             {
926                 instances.erase(pos);
927                 return true;
928             }
929         }
930     }
931     return false;
932 }
933 
934 ObjectFileCreateInstance
935 PluginManager::GetObjectFileCreateCallbackAtIndex (uint32_t idx)
936 {
937     Mutex::Locker locker (GetObjectFileMutex ());
938     ObjectFileInstances &instances = GetObjectFileInstances ();
939     if (idx < instances.size())
940         return instances[idx].create_callback;
941     return NULL;
942 }
943 
944 
945 ObjectFileCreateMemoryInstance
946 PluginManager::GetObjectFileCreateMemoryCallbackAtIndex (uint32_t idx)
947 {
948     Mutex::Locker locker (GetObjectFileMutex ());
949     ObjectFileInstances &instances = GetObjectFileInstances ();
950     if (idx < instances.size())
951         return instances[idx].create_memory_callback;
952     return NULL;
953 }
954 
955 ObjectFileCreateInstance
956 PluginManager::GetObjectFileCreateCallbackForPluginName (const char *name)
957 {
958     if (name && name[0])
959     {
960         llvm::StringRef name_sref(name);
961         Mutex::Locker locker (GetObjectFileMutex ());
962         ObjectFileInstances &instances = GetObjectFileInstances ();
963 
964         ObjectFileInstances::iterator pos, end = instances.end();
965         for (pos = instances.begin(); pos != end; ++ pos)
966         {
967             if (name_sref.equals (pos->name))
968                 return pos->create_callback;
969         }
970     }
971     return NULL;
972 }
973 
974 
975 ObjectFileCreateMemoryInstance
976 PluginManager::GetObjectFileCreateMemoryCallbackForPluginName (const char *name)
977 {
978     if (name && name[0])
979     {
980         llvm::StringRef name_sref(name);
981         Mutex::Locker locker (GetObjectFileMutex ());
982         ObjectFileInstances &instances = GetObjectFileInstances ();
983 
984         ObjectFileInstances::iterator pos, end = instances.end();
985         for (pos = instances.begin(); pos != end; ++ pos)
986         {
987             if (name_sref.equals (pos->name))
988                 return pos->create_memory_callback;
989         }
990     }
991     return NULL;
992 }
993 
994 
995 
996 #pragma mark ObjectContainer
997 
998 struct ObjectContainerInstance
999 {
1000     ObjectContainerInstance() :
1001         name(),
1002         description(),
1003         create_callback(NULL)
1004     {
1005     }
1006 
1007     std::string name;
1008     std::string description;
1009     ObjectContainerCreateInstance create_callback;
1010 };
1011 
1012 typedef std::vector<ObjectContainerInstance> ObjectContainerInstances;
1013 
1014 static Mutex &
1015 GetObjectContainerMutex ()
1016 {
1017     static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive);
1018     return g_instances_mutex;
1019 }
1020 
1021 static ObjectContainerInstances &
1022 GetObjectContainerInstances ()
1023 {
1024     static ObjectContainerInstances g_instances;
1025     return g_instances;
1026 }
1027 
1028 bool
1029 PluginManager::RegisterPlugin
1030 (
1031     const char *name,
1032     const char *description,
1033     ObjectContainerCreateInstance create_callback
1034 )
1035 {
1036     if (create_callback)
1037     {
1038         ObjectContainerInstance instance;
1039         assert (name && name[0]);
1040         instance.name = name;
1041         if (description && description[0])
1042             instance.description = description;
1043         instance.create_callback = create_callback;
1044         Mutex::Locker locker (GetObjectContainerMutex ());
1045         GetObjectContainerInstances ().push_back (instance);
1046     }
1047     return false;
1048 }
1049 
1050 bool
1051 PluginManager::UnregisterPlugin (ObjectContainerCreateInstance create_callback)
1052 {
1053     if (create_callback)
1054     {
1055         Mutex::Locker locker (GetObjectContainerMutex ());
1056         ObjectContainerInstances &instances = GetObjectContainerInstances ();
1057 
1058         ObjectContainerInstances::iterator pos, end = instances.end();
1059         for (pos = instances.begin(); pos != end; ++ pos)
1060         {
1061             if (pos->create_callback == create_callback)
1062             {
1063                 instances.erase(pos);
1064                 return true;
1065             }
1066         }
1067     }
1068     return false;
1069 }
1070 
1071 ObjectContainerCreateInstance
1072 PluginManager::GetObjectContainerCreateCallbackAtIndex (uint32_t idx)
1073 {
1074     Mutex::Locker locker (GetObjectContainerMutex ());
1075     ObjectContainerInstances &instances = GetObjectContainerInstances ();
1076     if (idx < instances.size())
1077         return instances[idx].create_callback;
1078     return NULL;
1079 }
1080 
1081 ObjectContainerCreateInstance
1082 PluginManager::GetObjectContainerCreateCallbackForPluginName (const char *name)
1083 {
1084     if (name && name[0])
1085     {
1086         llvm::StringRef name_sref(name);
1087         Mutex::Locker locker (GetObjectContainerMutex ());
1088         ObjectContainerInstances &instances = GetObjectContainerInstances ();
1089 
1090         ObjectContainerInstances::iterator pos, end = instances.end();
1091         for (pos = instances.begin(); pos != end; ++ pos)
1092         {
1093             if (name_sref.equals (pos->name))
1094                 return pos->create_callback;
1095         }
1096     }
1097     return NULL;
1098 }
1099 
1100 #pragma mark LogChannel
1101 
1102 struct LogInstance
1103 {
1104     LogInstance() :
1105         name(),
1106         description(),
1107         create_callback(NULL)
1108     {
1109     }
1110 
1111     std::string name;
1112     std::string description;
1113     LogChannelCreateInstance create_callback;
1114 };
1115 
1116 typedef std::vector<LogInstance> LogInstances;
1117 
1118 static Mutex &
1119 GetLogMutex ()
1120 {
1121     static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive);
1122     return g_instances_mutex;
1123 }
1124 
1125 static LogInstances &
1126 GetLogInstances ()
1127 {
1128     static LogInstances g_instances;
1129     return g_instances;
1130 }
1131 
1132 
1133 
1134 bool
1135 PluginManager::RegisterPlugin
1136 (
1137     const char *name,
1138     const char *description,
1139     LogChannelCreateInstance create_callback
1140 )
1141 {
1142     if (create_callback)
1143     {
1144         LogInstance instance;
1145         assert (name && name[0]);
1146         instance.name = name;
1147         if (description && description[0])
1148             instance.description = description;
1149         instance.create_callback = create_callback;
1150         Mutex::Locker locker (GetLogMutex ());
1151         GetLogInstances ().push_back (instance);
1152     }
1153     return false;
1154 }
1155 
1156 bool
1157 PluginManager::UnregisterPlugin (LogChannelCreateInstance create_callback)
1158 {
1159     if (create_callback)
1160     {
1161         Mutex::Locker locker (GetLogMutex ());
1162         LogInstances &instances = GetLogInstances ();
1163 
1164         LogInstances::iterator pos, end = instances.end();
1165         for (pos = instances.begin(); pos != end; ++ pos)
1166         {
1167             if (pos->create_callback == create_callback)
1168             {
1169                 instances.erase(pos);
1170                 return true;
1171             }
1172         }
1173     }
1174     return false;
1175 }
1176 
1177 const char *
1178 PluginManager::GetLogChannelCreateNameAtIndex (uint32_t idx)
1179 {
1180     Mutex::Locker locker (GetLogMutex ());
1181     LogInstances &instances = GetLogInstances ();
1182     if (idx < instances.size())
1183         return instances[idx].name.c_str();
1184     return NULL;
1185 }
1186 
1187 
1188 LogChannelCreateInstance
1189 PluginManager::GetLogChannelCreateCallbackAtIndex (uint32_t idx)
1190 {
1191     Mutex::Locker locker (GetLogMutex ());
1192     LogInstances &instances = GetLogInstances ();
1193     if (idx < instances.size())
1194         return instances[idx].create_callback;
1195     return NULL;
1196 }
1197 
1198 LogChannelCreateInstance
1199 PluginManager::GetLogChannelCreateCallbackForPluginName (const char *name)
1200 {
1201     if (name && name[0])
1202     {
1203         llvm::StringRef name_sref(name);
1204         Mutex::Locker locker (GetLogMutex ());
1205         LogInstances &instances = GetLogInstances ();
1206 
1207         LogInstances::iterator pos, end = instances.end();
1208         for (pos = instances.begin(); pos != end; ++ pos)
1209         {
1210             if (name_sref.equals (pos->name))
1211                 return pos->create_callback;
1212         }
1213     }
1214     return NULL;
1215 }
1216 
1217 #pragma mark Platform
1218 
1219 struct PlatformInstance
1220 {
1221     PlatformInstance() :
1222         name(),
1223         description(),
1224         create_callback(NULL)
1225     {
1226     }
1227 
1228     std::string name;
1229     std::string description;
1230     PlatformCreateInstance create_callback;
1231 };
1232 
1233 typedef std::vector<PlatformInstance> PlatformInstances;
1234 
1235 static Mutex &
1236 GetPlatformInstancesMutex ()
1237 {
1238     static Mutex g_platform_instances_mutex (Mutex::eMutexTypeRecursive);
1239     return g_platform_instances_mutex;
1240 }
1241 
1242 static PlatformInstances &
1243 GetPlatformInstances ()
1244 {
1245     static PlatformInstances g_platform_instances;
1246     return g_platform_instances;
1247 }
1248 
1249 
1250 bool
1251 PluginManager::RegisterPlugin (const char *name,
1252                                const char *description,
1253                                PlatformCreateInstance create_callback)
1254 {
1255     if (create_callback)
1256     {
1257         Mutex::Locker locker (GetPlatformInstancesMutex ());
1258 
1259         PlatformInstance instance;
1260         assert (name && name[0]);
1261         instance.name = name;
1262         if (description && description[0])
1263             instance.description = description;
1264         instance.create_callback = create_callback;
1265         GetPlatformInstances ().push_back (instance);
1266         return true;
1267     }
1268     return false;
1269 }
1270 
1271 const char *
1272 PluginManager::GetPlatformPluginNameAtIndex (uint32_t idx)
1273 {
1274     Mutex::Locker locker (GetPlatformInstancesMutex ());
1275     PlatformInstances &instances = GetPlatformInstances ();
1276     if (idx < instances.size())
1277         return instances[idx].name.c_str();
1278     return NULL;
1279 }
1280 
1281 const char *
1282 PluginManager::GetPlatformPluginDescriptionAtIndex (uint32_t idx)
1283 {
1284     Mutex::Locker locker (GetPlatformInstancesMutex ());
1285     PlatformInstances &instances = GetPlatformInstances ();
1286     if (idx < instances.size())
1287         return instances[idx].description.c_str();
1288     return NULL;
1289 }
1290 
1291 bool
1292 PluginManager::UnregisterPlugin (PlatformCreateInstance create_callback)
1293 {
1294     if (create_callback)
1295     {
1296         Mutex::Locker locker (GetPlatformInstancesMutex ());
1297         PlatformInstances &instances = GetPlatformInstances ();
1298 
1299         PlatformInstances::iterator pos, end = instances.end();
1300         for (pos = instances.begin(); pos != end; ++ pos)
1301         {
1302             if (pos->create_callback == create_callback)
1303             {
1304                 instances.erase(pos);
1305                 return true;
1306             }
1307         }
1308     }
1309     return false;
1310 }
1311 
1312 PlatformCreateInstance
1313 PluginManager::GetPlatformCreateCallbackAtIndex (uint32_t idx)
1314 {
1315     Mutex::Locker locker (GetPlatformInstancesMutex ());
1316     PlatformInstances &instances = GetPlatformInstances ();
1317     if (idx < instances.size())
1318         return instances[idx].create_callback;
1319     return NULL;
1320 }
1321 
1322 PlatformCreateInstance
1323 PluginManager::GetPlatformCreateCallbackForPluginName (const char *name)
1324 {
1325     if (name && name[0])
1326     {
1327         Mutex::Locker locker (GetPlatformInstancesMutex ());
1328         PlatformInstances &instances = GetPlatformInstances ();
1329         llvm::StringRef name_sref(name);
1330 
1331         PlatformInstances::iterator pos, end = instances.end();
1332         for (pos = instances.begin(); pos != end; ++ pos)
1333         {
1334             if (name_sref.equals (pos->name))
1335                 return pos->create_callback;
1336         }
1337     }
1338     return NULL;
1339 }
1340 
1341 uint32_t
1342 PluginManager::AutoCompletePlatformName (const char *name, StringList &matches)
1343 {
1344     if (name && name[0])
1345     {
1346         Mutex::Locker locker (GetPlatformInstancesMutex ());
1347         PlatformInstances &instances = GetPlatformInstances ();
1348         llvm::StringRef name_sref(name);
1349 
1350         PlatformInstances::iterator pos, end = instances.end();
1351         for (pos = instances.begin(); pos != end; ++ pos)
1352         {
1353             llvm::StringRef plugin_name (pos->name);
1354             if (plugin_name.startswith(name_sref))
1355                 matches.AppendString (plugin_name.data());
1356         }
1357     }
1358     return matches.GetSize();
1359 }
1360 
1361 #pragma mark Process
1362 
1363 struct ProcessInstance
1364 {
1365     ProcessInstance() :
1366     name(),
1367     description(),
1368     create_callback(NULL)
1369     {
1370     }
1371 
1372     std::string name;
1373     std::string description;
1374     ProcessCreateInstance create_callback;
1375 };
1376 
1377 typedef std::vector<ProcessInstance> ProcessInstances;
1378 
1379 static Mutex &
1380 GetProcessMutex ()
1381 {
1382     static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive);
1383     return g_instances_mutex;
1384 }
1385 
1386 static ProcessInstances &
1387 GetProcessInstances ()
1388 {
1389     static ProcessInstances g_instances;
1390     return g_instances;
1391 }
1392 
1393 
1394 bool
1395 PluginManager::RegisterPlugin
1396 (
1397  const char *name,
1398  const char *description,
1399  ProcessCreateInstance create_callback
1400  )
1401 {
1402     if (create_callback)
1403     {
1404         ProcessInstance instance;
1405         assert (name && name[0]);
1406         instance.name = name;
1407         if (description && description[0])
1408             instance.description = description;
1409         instance.create_callback = create_callback;
1410         Mutex::Locker locker (GetProcessMutex ());
1411         GetProcessInstances ().push_back (instance);
1412     }
1413     return false;
1414 }
1415 
1416 const char *
1417 PluginManager::GetProcessPluginNameAtIndex (uint32_t idx)
1418 {
1419     Mutex::Locker locker (GetProcessMutex ());
1420     ProcessInstances &instances = GetProcessInstances ();
1421     if (idx < instances.size())
1422         return instances[idx].name.c_str();
1423     return NULL;
1424 }
1425 
1426 const char *
1427 PluginManager::GetProcessPluginDescriptionAtIndex (uint32_t idx)
1428 {
1429     Mutex::Locker locker (GetProcessMutex ());
1430     ProcessInstances &instances = GetProcessInstances ();
1431     if (idx < instances.size())
1432         return instances[idx].description.c_str();
1433     return NULL;
1434 }
1435 
1436 bool
1437 PluginManager::UnregisterPlugin (ProcessCreateInstance create_callback)
1438 {
1439     if (create_callback)
1440     {
1441         Mutex::Locker locker (GetProcessMutex ());
1442         ProcessInstances &instances = GetProcessInstances ();
1443 
1444         ProcessInstances::iterator pos, end = instances.end();
1445         for (pos = instances.begin(); pos != end; ++ pos)
1446         {
1447             if (pos->create_callback == create_callback)
1448             {
1449                 instances.erase(pos);
1450                 return true;
1451             }
1452         }
1453     }
1454     return false;
1455 }
1456 
1457 ProcessCreateInstance
1458 PluginManager::GetProcessCreateCallbackAtIndex (uint32_t idx)
1459 {
1460     Mutex::Locker locker (GetProcessMutex ());
1461     ProcessInstances &instances = GetProcessInstances ();
1462     if (idx < instances.size())
1463         return instances[idx].create_callback;
1464     return NULL;
1465 }
1466 
1467 
1468 ProcessCreateInstance
1469 PluginManager::GetProcessCreateCallbackForPluginName (const char *name)
1470 {
1471     if (name && name[0])
1472     {
1473         llvm::StringRef name_sref(name);
1474         Mutex::Locker locker (GetProcessMutex ());
1475         ProcessInstances &instances = GetProcessInstances ();
1476 
1477         ProcessInstances::iterator pos, end = instances.end();
1478         for (pos = instances.begin(); pos != end; ++ pos)
1479         {
1480             if (name_sref.equals (pos->name))
1481                 return pos->create_callback;
1482         }
1483     }
1484     return NULL;
1485 }
1486 
1487 #pragma mark SymbolFile
1488 
1489 struct SymbolFileInstance
1490 {
1491     SymbolFileInstance() :
1492         name(),
1493         description(),
1494         create_callback(NULL)
1495     {
1496     }
1497 
1498     std::string name;
1499     std::string description;
1500     SymbolFileCreateInstance create_callback;
1501 };
1502 
1503 typedef std::vector<SymbolFileInstance> SymbolFileInstances;
1504 
1505 static Mutex &
1506 GetSymbolFileMutex ()
1507 {
1508     static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive);
1509     return g_instances_mutex;
1510 }
1511 
1512 static SymbolFileInstances &
1513 GetSymbolFileInstances ()
1514 {
1515     static SymbolFileInstances g_instances;
1516     return g_instances;
1517 }
1518 
1519 
1520 bool
1521 PluginManager::RegisterPlugin
1522 (
1523     const char *name,
1524     const char *description,
1525     SymbolFileCreateInstance create_callback
1526 )
1527 {
1528     if (create_callback)
1529     {
1530         SymbolFileInstance instance;
1531         assert (name && name[0]);
1532         instance.name = name;
1533         if (description && description[0])
1534             instance.description = description;
1535         instance.create_callback = create_callback;
1536         Mutex::Locker locker (GetSymbolFileMutex ());
1537         GetSymbolFileInstances ().push_back (instance);
1538     }
1539     return false;
1540 }
1541 
1542 bool
1543 PluginManager::UnregisterPlugin (SymbolFileCreateInstance create_callback)
1544 {
1545     if (create_callback)
1546     {
1547         Mutex::Locker locker (GetSymbolFileMutex ());
1548         SymbolFileInstances &instances = GetSymbolFileInstances ();
1549 
1550         SymbolFileInstances::iterator pos, end = instances.end();
1551         for (pos = instances.begin(); pos != end; ++ pos)
1552         {
1553             if (pos->create_callback == create_callback)
1554             {
1555                 instances.erase(pos);
1556                 return true;
1557             }
1558         }
1559     }
1560     return false;
1561 }
1562 
1563 SymbolFileCreateInstance
1564 PluginManager::GetSymbolFileCreateCallbackAtIndex (uint32_t idx)
1565 {
1566     Mutex::Locker locker (GetSymbolFileMutex ());
1567     SymbolFileInstances &instances = GetSymbolFileInstances ();
1568     if (idx < instances.size())
1569         return instances[idx].create_callback;
1570     return NULL;
1571 }
1572 
1573 SymbolFileCreateInstance
1574 PluginManager::GetSymbolFileCreateCallbackForPluginName (const char *name)
1575 {
1576     if (name && name[0])
1577     {
1578         llvm::StringRef name_sref(name);
1579         Mutex::Locker locker (GetSymbolFileMutex ());
1580         SymbolFileInstances &instances = GetSymbolFileInstances ();
1581 
1582         SymbolFileInstances::iterator pos, end = instances.end();
1583         for (pos = instances.begin(); pos != end; ++ pos)
1584         {
1585             if (name_sref.equals (pos->name))
1586                 return pos->create_callback;
1587         }
1588     }
1589     return NULL;
1590 }
1591 
1592 
1593 
1594 #pragma mark SymbolVendor
1595 
1596 struct SymbolVendorInstance
1597 {
1598     SymbolVendorInstance() :
1599         name(),
1600         description(),
1601         create_callback(NULL)
1602     {
1603     }
1604 
1605     std::string name;
1606     std::string description;
1607     SymbolVendorCreateInstance create_callback;
1608 };
1609 
1610 typedef std::vector<SymbolVendorInstance> SymbolVendorInstances;
1611 
1612 static Mutex &
1613 GetSymbolVendorMutex ()
1614 {
1615     static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive);
1616     return g_instances_mutex;
1617 }
1618 
1619 static SymbolVendorInstances &
1620 GetSymbolVendorInstances ()
1621 {
1622     static SymbolVendorInstances g_instances;
1623     return g_instances;
1624 }
1625 
1626 bool
1627 PluginManager::RegisterPlugin
1628 (
1629     const char *name,
1630     const char *description,
1631     SymbolVendorCreateInstance create_callback
1632 )
1633 {
1634     if (create_callback)
1635     {
1636         SymbolVendorInstance instance;
1637         assert (name && name[0]);
1638         instance.name = name;
1639         if (description && description[0])
1640             instance.description = description;
1641         instance.create_callback = create_callback;
1642         Mutex::Locker locker (GetSymbolVendorMutex ());
1643         GetSymbolVendorInstances ().push_back (instance);
1644     }
1645     return false;
1646 }
1647 
1648 bool
1649 PluginManager::UnregisterPlugin (SymbolVendorCreateInstance create_callback)
1650 {
1651     if (create_callback)
1652     {
1653         Mutex::Locker locker (GetSymbolVendorMutex ());
1654         SymbolVendorInstances &instances = GetSymbolVendorInstances ();
1655 
1656         SymbolVendorInstances::iterator pos, end = instances.end();
1657         for (pos = instances.begin(); pos != end; ++ pos)
1658         {
1659             if (pos->create_callback == create_callback)
1660             {
1661                 instances.erase(pos);
1662                 return true;
1663             }
1664         }
1665     }
1666     return false;
1667 }
1668 
1669 SymbolVendorCreateInstance
1670 PluginManager::GetSymbolVendorCreateCallbackAtIndex (uint32_t idx)
1671 {
1672     Mutex::Locker locker (GetSymbolVendorMutex ());
1673     SymbolVendorInstances &instances = GetSymbolVendorInstances ();
1674     if (idx < instances.size())
1675         return instances[idx].create_callback;
1676     return NULL;
1677 }
1678 
1679 
1680 SymbolVendorCreateInstance
1681 PluginManager::GetSymbolVendorCreateCallbackForPluginName (const char *name)
1682 {
1683     if (name && name[0])
1684     {
1685         llvm::StringRef name_sref(name);
1686         Mutex::Locker locker (GetSymbolVendorMutex ());
1687         SymbolVendorInstances &instances = GetSymbolVendorInstances ();
1688 
1689         SymbolVendorInstances::iterator pos, end = instances.end();
1690         for (pos = instances.begin(); pos != end; ++ pos)
1691         {
1692             if (name_sref.equals (pos->name))
1693                 return pos->create_callback;
1694         }
1695     }
1696     return NULL;
1697 }
1698 
1699 
1700 #pragma mark UnwindAssembly
1701 
1702 struct UnwindAssemblyInstance
1703 {
1704     UnwindAssemblyInstance() :
1705         name(),
1706         description(),
1707         create_callback(NULL)
1708     {
1709     }
1710 
1711     std::string name;
1712     std::string description;
1713     UnwindAssemblyCreateInstance create_callback;
1714 };
1715 
1716 typedef std::vector<UnwindAssemblyInstance> UnwindAssemblyInstances;
1717 
1718 static Mutex &
1719 GetUnwindAssemblyMutex ()
1720 {
1721     static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive);
1722     return g_instances_mutex;
1723 }
1724 
1725 static UnwindAssemblyInstances &
1726 GetUnwindAssemblyInstances ()
1727 {
1728     static UnwindAssemblyInstances g_instances;
1729     return g_instances;
1730 }
1731 
1732 bool
1733 PluginManager::RegisterPlugin
1734 (
1735     const char *name,
1736     const char *description,
1737     UnwindAssemblyCreateInstance create_callback
1738 )
1739 {
1740     if (create_callback)
1741     {
1742         UnwindAssemblyInstance instance;
1743         assert (name && name[0]);
1744         instance.name = name;
1745         if (description && description[0])
1746             instance.description = description;
1747         instance.create_callback = create_callback;
1748         Mutex::Locker locker (GetUnwindAssemblyMutex ());
1749         GetUnwindAssemblyInstances ().push_back (instance);
1750     }
1751     return false;
1752 }
1753 
1754 bool
1755 PluginManager::UnregisterPlugin (UnwindAssemblyCreateInstance create_callback)
1756 {
1757     if (create_callback)
1758     {
1759         Mutex::Locker locker (GetUnwindAssemblyMutex ());
1760         UnwindAssemblyInstances &instances = GetUnwindAssemblyInstances ();
1761 
1762         UnwindAssemblyInstances::iterator pos, end = instances.end();
1763         for (pos = instances.begin(); pos != end; ++ pos)
1764         {
1765             if (pos->create_callback == create_callback)
1766             {
1767                 instances.erase(pos);
1768                 return true;
1769             }
1770         }
1771     }
1772     return false;
1773 }
1774 
1775 UnwindAssemblyCreateInstance
1776 PluginManager::GetUnwindAssemblyCreateCallbackAtIndex (uint32_t idx)
1777 {
1778     Mutex::Locker locker (GetUnwindAssemblyMutex ());
1779     UnwindAssemblyInstances &instances = GetUnwindAssemblyInstances ();
1780     if (idx < instances.size())
1781         return instances[idx].create_callback;
1782     return NULL;
1783 }
1784 
1785 
1786 UnwindAssemblyCreateInstance
1787 PluginManager::GetUnwindAssemblyCreateCallbackForPluginName (const char *name)
1788 {
1789     if (name && name[0])
1790     {
1791         llvm::StringRef name_sref(name);
1792         Mutex::Locker locker (GetUnwindAssemblyMutex ());
1793         UnwindAssemblyInstances &instances = GetUnwindAssemblyInstances ();
1794 
1795         UnwindAssemblyInstances::iterator pos, end = instances.end();
1796         for (pos = instances.begin(); pos != end; ++ pos)
1797         {
1798             if (name_sref.equals (pos->name))
1799                 return pos->create_callback;
1800         }
1801     }
1802     return NULL;
1803 }
1804 
1805