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 
644 
645 #pragma mark LanguageRuntime
646 
647 
648 struct LanguageRuntimeInstance
649 {
650     LanguageRuntimeInstance() :
651         name(),
652         description(),
653         create_callback(NULL)
654     {
655     }
656 
657     std::string name;
658     std::string description;
659     LanguageRuntimeCreateInstance create_callback;
660 };
661 
662 typedef std::vector<LanguageRuntimeInstance> LanguageRuntimeInstances;
663 
664 static Mutex &
665 GetLanguageRuntimeMutex ()
666 {
667     static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive);
668     return g_instances_mutex;
669 }
670 
671 static LanguageRuntimeInstances &
672 GetLanguageRuntimeInstances ()
673 {
674     static LanguageRuntimeInstances g_instances;
675     return g_instances;
676 }
677 
678 bool
679 PluginManager::RegisterPlugin
680 (
681     const char *name,
682     const char *description,
683     LanguageRuntimeCreateInstance create_callback
684 )
685 {
686     if (create_callback)
687     {
688         LanguageRuntimeInstance instance;
689         assert (name && name[0]);
690         instance.name = name;
691         if (description && description[0])
692             instance.description = description;
693         instance.create_callback = create_callback;
694         Mutex::Locker locker (GetLanguageRuntimeMutex ());
695         GetLanguageRuntimeInstances ().push_back (instance);
696     }
697     return false;
698 }
699 
700 bool
701 PluginManager::UnregisterPlugin (LanguageRuntimeCreateInstance create_callback)
702 {
703     if (create_callback)
704     {
705         Mutex::Locker locker (GetLanguageRuntimeMutex ());
706         LanguageRuntimeInstances &instances = GetLanguageRuntimeInstances ();
707 
708         LanguageRuntimeInstances::iterator pos, end = instances.end();
709         for (pos = instances.begin(); pos != end; ++ pos)
710         {
711             if (pos->create_callback == create_callback)
712             {
713                 instances.erase(pos);
714                 return true;
715             }
716         }
717     }
718     return false;
719 }
720 
721 LanguageRuntimeCreateInstance
722 PluginManager::GetLanguageRuntimeCreateCallbackAtIndex (uint32_t idx)
723 {
724     Mutex::Locker locker (GetLanguageRuntimeMutex ());
725     LanguageRuntimeInstances &instances = GetLanguageRuntimeInstances ();
726     if (idx < instances.size())
727         return instances[idx].create_callback;
728     return NULL;
729 }
730 
731 LanguageRuntimeCreateInstance
732 PluginManager::GetLanguageRuntimeCreateCallbackForPluginName (const char *name)
733 {
734     if (name && name[0])
735     {
736         llvm::StringRef name_sref(name);
737         Mutex::Locker locker (GetLanguageRuntimeMutex ());
738         LanguageRuntimeInstances &instances = GetLanguageRuntimeInstances ();
739 
740         LanguageRuntimeInstances::iterator pos, end = instances.end();
741         for (pos = instances.begin(); pos != end; ++ pos)
742         {
743             if (name_sref.equals (pos->name))
744                 return pos->create_callback;
745         }
746     }
747     return NULL;
748 }
749 
750 #pragma mark ObjectFile
751 
752 struct ObjectFileInstance
753 {
754     ObjectFileInstance() :
755         name(),
756         description(),
757         create_callback(NULL)
758     {
759     }
760 
761     std::string name;
762     std::string description;
763     ObjectFileCreateInstance create_callback;
764 };
765 
766 typedef std::vector<ObjectFileInstance> ObjectFileInstances;
767 
768 static Mutex &
769 GetObjectFileMutex ()
770 {
771     static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive);
772     return g_instances_mutex;
773 }
774 
775 static ObjectFileInstances &
776 GetObjectFileInstances ()
777 {
778     static ObjectFileInstances g_instances;
779     return g_instances;
780 }
781 
782 
783 bool
784 PluginManager::RegisterPlugin
785 (
786     const char *name,
787     const char *description,
788     ObjectFileCreateInstance create_callback
789 )
790 {
791     if (create_callback)
792     {
793         ObjectFileInstance instance;
794         assert (name && name[0]);
795         instance.name = name;
796         if (description && description[0])
797             instance.description = description;
798         instance.create_callback = create_callback;
799         Mutex::Locker locker (GetObjectFileMutex ());
800         GetObjectFileInstances ().push_back (instance);
801     }
802     return false;
803 }
804 
805 bool
806 PluginManager::UnregisterPlugin (ObjectFileCreateInstance create_callback)
807 {
808     if (create_callback)
809     {
810         Mutex::Locker locker (GetObjectFileMutex ());
811         ObjectFileInstances &instances = GetObjectFileInstances ();
812 
813         ObjectFileInstances::iterator pos, end = instances.end();
814         for (pos = instances.begin(); pos != end; ++ pos)
815         {
816             if (pos->create_callback == create_callback)
817             {
818                 instances.erase(pos);
819                 return true;
820             }
821         }
822     }
823     return false;
824 }
825 
826 ObjectFileCreateInstance
827 PluginManager::GetObjectFileCreateCallbackAtIndex (uint32_t idx)
828 {
829     Mutex::Locker locker (GetObjectFileMutex ());
830     ObjectFileInstances &instances = GetObjectFileInstances ();
831     if (idx < instances.size())
832         return instances[idx].create_callback;
833     return NULL;
834 }
835 
836 ObjectFileCreateInstance
837 PluginManager::GetObjectFileCreateCallbackForPluginName (const char *name)
838 {
839     if (name && name[0])
840     {
841         llvm::StringRef name_sref(name);
842         Mutex::Locker locker (GetObjectFileMutex ());
843         ObjectFileInstances &instances = GetObjectFileInstances ();
844 
845         ObjectFileInstances::iterator pos, end = instances.end();
846         for (pos = instances.begin(); pos != end; ++ pos)
847         {
848             if (name_sref.equals (pos->name))
849                 return pos->create_callback;
850         }
851     }
852     return NULL;
853 }
854 
855 
856 
857 #pragma mark ObjectContainer
858 
859 struct ObjectContainerInstance
860 {
861     ObjectContainerInstance() :
862         name(),
863         description(),
864         create_callback(NULL)
865     {
866     }
867 
868     std::string name;
869     std::string description;
870     ObjectContainerCreateInstance create_callback;
871 };
872 
873 typedef std::vector<ObjectContainerInstance> ObjectContainerInstances;
874 
875 static Mutex &
876 GetObjectContainerMutex ()
877 {
878     static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive);
879     return g_instances_mutex;
880 }
881 
882 static ObjectContainerInstances &
883 GetObjectContainerInstances ()
884 {
885     static ObjectContainerInstances g_instances;
886     return g_instances;
887 }
888 
889 bool
890 PluginManager::RegisterPlugin
891 (
892     const char *name,
893     const char *description,
894     ObjectContainerCreateInstance create_callback
895 )
896 {
897     if (create_callback)
898     {
899         ObjectContainerInstance instance;
900         assert (name && name[0]);
901         instance.name = name;
902         if (description && description[0])
903             instance.description = description;
904         instance.create_callback = create_callback;
905         Mutex::Locker locker (GetObjectContainerMutex ());
906         GetObjectContainerInstances ().push_back (instance);
907     }
908     return false;
909 }
910 
911 bool
912 PluginManager::UnregisterPlugin (ObjectContainerCreateInstance create_callback)
913 {
914     if (create_callback)
915     {
916         Mutex::Locker locker (GetObjectContainerMutex ());
917         ObjectContainerInstances &instances = GetObjectContainerInstances ();
918 
919         ObjectContainerInstances::iterator pos, end = instances.end();
920         for (pos = instances.begin(); pos != end; ++ pos)
921         {
922             if (pos->create_callback == create_callback)
923             {
924                 instances.erase(pos);
925                 return true;
926             }
927         }
928     }
929     return false;
930 }
931 
932 ObjectContainerCreateInstance
933 PluginManager::GetObjectContainerCreateCallbackAtIndex (uint32_t idx)
934 {
935     Mutex::Locker locker (GetObjectContainerMutex ());
936     ObjectContainerInstances &instances = GetObjectContainerInstances ();
937     if (idx < instances.size())
938         return instances[idx].create_callback;
939     return NULL;
940 }
941 
942 ObjectContainerCreateInstance
943 PluginManager::GetObjectContainerCreateCallbackForPluginName (const char *name)
944 {
945     if (name && name[0])
946     {
947         llvm::StringRef name_sref(name);
948         Mutex::Locker locker (GetObjectContainerMutex ());
949         ObjectContainerInstances &instances = GetObjectContainerInstances ();
950 
951         ObjectContainerInstances::iterator pos, end = instances.end();
952         for (pos = instances.begin(); pos != end; ++ pos)
953         {
954             if (name_sref.equals (pos->name))
955                 return pos->create_callback;
956         }
957     }
958     return NULL;
959 }
960 
961 #pragma mark LogChannel
962 
963 struct LogInstance
964 {
965     LogInstance() :
966         name(),
967         description(),
968         create_callback(NULL)
969     {
970     }
971 
972     std::string name;
973     std::string description;
974     LogChannelCreateInstance create_callback;
975 };
976 
977 typedef std::vector<LogInstance> LogInstances;
978 
979 static Mutex &
980 GetLogMutex ()
981 {
982     static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive);
983     return g_instances_mutex;
984 }
985 
986 static LogInstances &
987 GetLogInstances ()
988 {
989     static LogInstances g_instances;
990     return g_instances;
991 }
992 
993 
994 
995 bool
996 PluginManager::RegisterPlugin
997 (
998     const char *name,
999     const char *description,
1000     LogChannelCreateInstance create_callback
1001 )
1002 {
1003     if (create_callback)
1004     {
1005         LogInstance instance;
1006         assert (name && name[0]);
1007         instance.name = name;
1008         if (description && description[0])
1009             instance.description = description;
1010         instance.create_callback = create_callback;
1011         Mutex::Locker locker (GetLogMutex ());
1012         GetLogInstances ().push_back (instance);
1013     }
1014     return false;
1015 }
1016 
1017 bool
1018 PluginManager::UnregisterPlugin (LogChannelCreateInstance create_callback)
1019 {
1020     if (create_callback)
1021     {
1022         Mutex::Locker locker (GetLogMutex ());
1023         LogInstances &instances = GetLogInstances ();
1024 
1025         LogInstances::iterator pos, end = instances.end();
1026         for (pos = instances.begin(); pos != end; ++ pos)
1027         {
1028             if (pos->create_callback == create_callback)
1029             {
1030                 instances.erase(pos);
1031                 return true;
1032             }
1033         }
1034     }
1035     return false;
1036 }
1037 
1038 const char *
1039 PluginManager::GetLogChannelCreateNameAtIndex (uint32_t idx)
1040 {
1041     Mutex::Locker locker (GetLogMutex ());
1042     LogInstances &instances = GetLogInstances ();
1043     if (idx < instances.size())
1044         return instances[idx].name.c_str();
1045     return NULL;
1046 }
1047 
1048 
1049 LogChannelCreateInstance
1050 PluginManager::GetLogChannelCreateCallbackAtIndex (uint32_t idx)
1051 {
1052     Mutex::Locker locker (GetLogMutex ());
1053     LogInstances &instances = GetLogInstances ();
1054     if (idx < instances.size())
1055         return instances[idx].create_callback;
1056     return NULL;
1057 }
1058 
1059 LogChannelCreateInstance
1060 PluginManager::GetLogChannelCreateCallbackForPluginName (const char *name)
1061 {
1062     if (name && name[0])
1063     {
1064         llvm::StringRef name_sref(name);
1065         Mutex::Locker locker (GetLogMutex ());
1066         LogInstances &instances = GetLogInstances ();
1067 
1068         LogInstances::iterator pos, end = instances.end();
1069         for (pos = instances.begin(); pos != end; ++ pos)
1070         {
1071             if (name_sref.equals (pos->name))
1072                 return pos->create_callback;
1073         }
1074     }
1075     return NULL;
1076 }
1077 
1078 #pragma mark Platform
1079 
1080 struct PlatformInstance
1081 {
1082     PlatformInstance() :
1083         name(),
1084         description(),
1085         create_callback(NULL)
1086     {
1087     }
1088 
1089     std::string name;
1090     std::string description;
1091     PlatformCreateInstance create_callback;
1092 };
1093 
1094 typedef std::vector<PlatformInstance> PlatformInstances;
1095 
1096 static Mutex &
1097 GetPlatformInstancesMutex ()
1098 {
1099     static Mutex g_platform_instances_mutex (Mutex::eMutexTypeRecursive);
1100     return g_platform_instances_mutex;
1101 }
1102 
1103 static PlatformInstances &
1104 GetPlatformInstances ()
1105 {
1106     static PlatformInstances g_platform_instances;
1107     return g_platform_instances;
1108 }
1109 
1110 
1111 bool
1112 PluginManager::RegisterPlugin (const char *name,
1113                                const char *description,
1114                                PlatformCreateInstance create_callback)
1115 {
1116     if (create_callback)
1117     {
1118         Mutex::Locker locker (GetPlatformInstancesMutex ());
1119 
1120         PlatformInstance instance;
1121         assert (name && name[0]);
1122         instance.name = name;
1123         if (description && description[0])
1124             instance.description = description;
1125         instance.create_callback = create_callback;
1126         GetPlatformInstances ().push_back (instance);
1127         return true;
1128     }
1129     return false;
1130 }
1131 
1132 const char *
1133 PluginManager::GetPlatformPluginNameAtIndex (uint32_t idx)
1134 {
1135     Mutex::Locker locker (GetPlatformInstancesMutex ());
1136     PlatformInstances &instances = GetPlatformInstances ();
1137     if (idx < instances.size())
1138         return instances[idx].name.c_str();
1139     return NULL;
1140 }
1141 
1142 const char *
1143 PluginManager::GetPlatformPluginDescriptionAtIndex (uint32_t idx)
1144 {
1145     Mutex::Locker locker (GetPlatformInstancesMutex ());
1146     PlatformInstances &instances = GetPlatformInstances ();
1147     if (idx < instances.size())
1148         return instances[idx].description.c_str();
1149     return NULL;
1150 }
1151 
1152 bool
1153 PluginManager::UnregisterPlugin (PlatformCreateInstance create_callback)
1154 {
1155     if (create_callback)
1156     {
1157         Mutex::Locker locker (GetPlatformInstancesMutex ());
1158         PlatformInstances &instances = GetPlatformInstances ();
1159 
1160         PlatformInstances::iterator pos, end = instances.end();
1161         for (pos = instances.begin(); pos != end; ++ pos)
1162         {
1163             if (pos->create_callback == create_callback)
1164             {
1165                 instances.erase(pos);
1166                 return true;
1167             }
1168         }
1169     }
1170     return false;
1171 }
1172 
1173 PlatformCreateInstance
1174 PluginManager::GetPlatformCreateCallbackAtIndex (uint32_t idx)
1175 {
1176     Mutex::Locker locker (GetPlatformInstancesMutex ());
1177     PlatformInstances &instances = GetPlatformInstances ();
1178     if (idx < instances.size())
1179         return instances[idx].create_callback;
1180     return NULL;
1181 }
1182 
1183 PlatformCreateInstance
1184 PluginManager::GetPlatformCreateCallbackForPluginName (const char *name)
1185 {
1186     if (name && name[0])
1187     {
1188         Mutex::Locker locker (GetPlatformInstancesMutex ());
1189         PlatformInstances &instances = GetPlatformInstances ();
1190         llvm::StringRef name_sref(name);
1191 
1192         PlatformInstances::iterator pos, end = instances.end();
1193         for (pos = instances.begin(); pos != end; ++ pos)
1194         {
1195             if (name_sref.equals (name))
1196                 return pos->create_callback;
1197         }
1198     }
1199     return NULL;
1200 }
1201 
1202 uint32_t
1203 PluginManager::AutoCompletePlatformName (const char *name, StringList &matches)
1204 {
1205     if (name && name[0])
1206     {
1207         Mutex::Locker locker (GetPlatformInstancesMutex ());
1208         PlatformInstances &instances = GetPlatformInstances ();
1209         llvm::StringRef name_sref(name);
1210 
1211         PlatformInstances::iterator pos, end = instances.end();
1212         for (pos = instances.begin(); pos != end; ++ pos)
1213         {
1214             const char *plugin_name = pos->name.c_str();
1215             if (name_sref.startswith(plugin_name))
1216                 matches.AppendString (plugin_name);
1217         }
1218     }
1219     return matches.GetSize();
1220 }
1221 
1222 #pragma mark Process
1223 
1224 struct ProcessInstance
1225 {
1226     ProcessInstance() :
1227     name(),
1228     description(),
1229     create_callback(NULL)
1230     {
1231     }
1232 
1233     std::string name;
1234     std::string description;
1235     ProcessCreateInstance create_callback;
1236 };
1237 
1238 typedef std::vector<ProcessInstance> ProcessInstances;
1239 
1240 static Mutex &
1241 GetProcessMutex ()
1242 {
1243     static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive);
1244     return g_instances_mutex;
1245 }
1246 
1247 static ProcessInstances &
1248 GetProcessInstances ()
1249 {
1250     static ProcessInstances g_instances;
1251     return g_instances;
1252 }
1253 
1254 
1255 bool
1256 PluginManager::RegisterPlugin
1257 (
1258  const char *name,
1259  const char *description,
1260  ProcessCreateInstance create_callback
1261  )
1262 {
1263     if (create_callback)
1264     {
1265         ProcessInstance instance;
1266         assert (name && name[0]);
1267         instance.name = name;
1268         if (description && description[0])
1269             instance.description = description;
1270         instance.create_callback = create_callback;
1271         Mutex::Locker locker (GetProcessMutex ());
1272         GetProcessInstances ().push_back (instance);
1273     }
1274     return false;
1275 }
1276 
1277 const char *
1278 PluginManager::GetProcessPluginNameAtIndex (uint32_t idx)
1279 {
1280     Mutex::Locker locker (GetProcessMutex ());
1281     ProcessInstances &instances = GetProcessInstances ();
1282     if (idx < instances.size())
1283         return instances[idx].name.c_str();
1284     return NULL;
1285 }
1286 
1287 const char *
1288 PluginManager::GetProcessPluginDescriptionAtIndex (uint32_t idx)
1289 {
1290     Mutex::Locker locker (GetProcessMutex ());
1291     ProcessInstances &instances = GetProcessInstances ();
1292     if (idx < instances.size())
1293         return instances[idx].description.c_str();
1294     return NULL;
1295 }
1296 
1297 bool
1298 PluginManager::UnregisterPlugin (ProcessCreateInstance create_callback)
1299 {
1300     if (create_callback)
1301     {
1302         Mutex::Locker locker (GetProcessMutex ());
1303         ProcessInstances &instances = GetProcessInstances ();
1304 
1305         ProcessInstances::iterator pos, end = instances.end();
1306         for (pos = instances.begin(); pos != end; ++ pos)
1307         {
1308             if (pos->create_callback == create_callback)
1309             {
1310                 instances.erase(pos);
1311                 return true;
1312             }
1313         }
1314     }
1315     return false;
1316 }
1317 
1318 ProcessCreateInstance
1319 PluginManager::GetProcessCreateCallbackAtIndex (uint32_t idx)
1320 {
1321     Mutex::Locker locker (GetProcessMutex ());
1322     ProcessInstances &instances = GetProcessInstances ();
1323     if (idx < instances.size())
1324         return instances[idx].create_callback;
1325     return NULL;
1326 }
1327 
1328 
1329 ProcessCreateInstance
1330 PluginManager::GetProcessCreateCallbackForPluginName (const char *name)
1331 {
1332     if (name && name[0])
1333     {
1334         llvm::StringRef name_sref(name);
1335         Mutex::Locker locker (GetProcessMutex ());
1336         ProcessInstances &instances = GetProcessInstances ();
1337 
1338         ProcessInstances::iterator pos, end = instances.end();
1339         for (pos = instances.begin(); pos != end; ++ pos)
1340         {
1341             if (name_sref.equals (pos->name))
1342                 return pos->create_callback;
1343         }
1344     }
1345     return NULL;
1346 }
1347 
1348 #pragma mark SymbolFile
1349 
1350 struct SymbolFileInstance
1351 {
1352     SymbolFileInstance() :
1353         name(),
1354         description(),
1355         create_callback(NULL)
1356     {
1357     }
1358 
1359     std::string name;
1360     std::string description;
1361     SymbolFileCreateInstance create_callback;
1362 };
1363 
1364 typedef std::vector<SymbolFileInstance> SymbolFileInstances;
1365 
1366 static Mutex &
1367 GetSymbolFileMutex ()
1368 {
1369     static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive);
1370     return g_instances_mutex;
1371 }
1372 
1373 static SymbolFileInstances &
1374 GetSymbolFileInstances ()
1375 {
1376     static SymbolFileInstances g_instances;
1377     return g_instances;
1378 }
1379 
1380 
1381 bool
1382 PluginManager::RegisterPlugin
1383 (
1384     const char *name,
1385     const char *description,
1386     SymbolFileCreateInstance create_callback
1387 )
1388 {
1389     if (create_callback)
1390     {
1391         SymbolFileInstance instance;
1392         assert (name && name[0]);
1393         instance.name = name;
1394         if (description && description[0])
1395             instance.description = description;
1396         instance.create_callback = create_callback;
1397         Mutex::Locker locker (GetSymbolFileMutex ());
1398         GetSymbolFileInstances ().push_back (instance);
1399     }
1400     return false;
1401 }
1402 
1403 bool
1404 PluginManager::UnregisterPlugin (SymbolFileCreateInstance create_callback)
1405 {
1406     if (create_callback)
1407     {
1408         Mutex::Locker locker (GetSymbolFileMutex ());
1409         SymbolFileInstances &instances = GetSymbolFileInstances ();
1410 
1411         SymbolFileInstances::iterator pos, end = instances.end();
1412         for (pos = instances.begin(); pos != end; ++ pos)
1413         {
1414             if (pos->create_callback == create_callback)
1415             {
1416                 instances.erase(pos);
1417                 return true;
1418             }
1419         }
1420     }
1421     return false;
1422 }
1423 
1424 SymbolFileCreateInstance
1425 PluginManager::GetSymbolFileCreateCallbackAtIndex (uint32_t idx)
1426 {
1427     Mutex::Locker locker (GetSymbolFileMutex ());
1428     SymbolFileInstances &instances = GetSymbolFileInstances ();
1429     if (idx < instances.size())
1430         return instances[idx].create_callback;
1431     return NULL;
1432 }
1433 
1434 SymbolFileCreateInstance
1435 PluginManager::GetSymbolFileCreateCallbackForPluginName (const char *name)
1436 {
1437     if (name && name[0])
1438     {
1439         llvm::StringRef name_sref(name);
1440         Mutex::Locker locker (GetSymbolFileMutex ());
1441         SymbolFileInstances &instances = GetSymbolFileInstances ();
1442 
1443         SymbolFileInstances::iterator pos, end = instances.end();
1444         for (pos = instances.begin(); pos != end; ++ pos)
1445         {
1446             if (name_sref.equals (pos->name))
1447                 return pos->create_callback;
1448         }
1449     }
1450     return NULL;
1451 }
1452 
1453 
1454 
1455 #pragma mark SymbolVendor
1456 
1457 struct SymbolVendorInstance
1458 {
1459     SymbolVendorInstance() :
1460         name(),
1461         description(),
1462         create_callback(NULL)
1463     {
1464     }
1465 
1466     std::string name;
1467     std::string description;
1468     SymbolVendorCreateInstance create_callback;
1469 };
1470 
1471 typedef std::vector<SymbolVendorInstance> SymbolVendorInstances;
1472 
1473 static Mutex &
1474 GetSymbolVendorMutex ()
1475 {
1476     static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive);
1477     return g_instances_mutex;
1478 }
1479 
1480 static SymbolVendorInstances &
1481 GetSymbolVendorInstances ()
1482 {
1483     static SymbolVendorInstances g_instances;
1484     return g_instances;
1485 }
1486 
1487 bool
1488 PluginManager::RegisterPlugin
1489 (
1490     const char *name,
1491     const char *description,
1492     SymbolVendorCreateInstance create_callback
1493 )
1494 {
1495     if (create_callback)
1496     {
1497         SymbolVendorInstance instance;
1498         assert (name && name[0]);
1499         instance.name = name;
1500         if (description && description[0])
1501             instance.description = description;
1502         instance.create_callback = create_callback;
1503         Mutex::Locker locker (GetSymbolVendorMutex ());
1504         GetSymbolVendorInstances ().push_back (instance);
1505     }
1506     return false;
1507 }
1508 
1509 bool
1510 PluginManager::UnregisterPlugin (SymbolVendorCreateInstance create_callback)
1511 {
1512     if (create_callback)
1513     {
1514         Mutex::Locker locker (GetSymbolVendorMutex ());
1515         SymbolVendorInstances &instances = GetSymbolVendorInstances ();
1516 
1517         SymbolVendorInstances::iterator pos, end = instances.end();
1518         for (pos = instances.begin(); pos != end; ++ pos)
1519         {
1520             if (pos->create_callback == create_callback)
1521             {
1522                 instances.erase(pos);
1523                 return true;
1524             }
1525         }
1526     }
1527     return false;
1528 }
1529 
1530 SymbolVendorCreateInstance
1531 PluginManager::GetSymbolVendorCreateCallbackAtIndex (uint32_t idx)
1532 {
1533     Mutex::Locker locker (GetSymbolVendorMutex ());
1534     SymbolVendorInstances &instances = GetSymbolVendorInstances ();
1535     if (idx < instances.size())
1536         return instances[idx].create_callback;
1537     return NULL;
1538 }
1539 
1540 
1541 SymbolVendorCreateInstance
1542 PluginManager::GetSymbolVendorCreateCallbackForPluginName (const char *name)
1543 {
1544     if (name && name[0])
1545     {
1546         llvm::StringRef name_sref(name);
1547         Mutex::Locker locker (GetSymbolVendorMutex ());
1548         SymbolVendorInstances &instances = GetSymbolVendorInstances ();
1549 
1550         SymbolVendorInstances::iterator pos, end = instances.end();
1551         for (pos = instances.begin(); pos != end; ++ pos)
1552         {
1553             if (name_sref.equals (pos->name))
1554                 return pos->create_callback;
1555         }
1556     }
1557     return NULL;
1558 }
1559 
1560 
1561 #pragma mark UnwindAssemblyProfiler
1562 
1563 struct UnwindAssemblyProfilerInstance
1564 {
1565     UnwindAssemblyProfilerInstance() :
1566         name(),
1567         description(),
1568         create_callback(NULL)
1569     {
1570     }
1571 
1572     std::string name;
1573     std::string description;
1574     UnwindAssemblyProfilerCreateInstance create_callback;
1575 };
1576 
1577 typedef std::vector<UnwindAssemblyProfilerInstance> UnwindAssemblyProfilerInstances;
1578 
1579 static Mutex &
1580 GetUnwindAssemblyProfilerMutex ()
1581 {
1582     static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive);
1583     return g_instances_mutex;
1584 }
1585 
1586 static UnwindAssemblyProfilerInstances &
1587 GetUnwindAssemblyProfilerInstances ()
1588 {
1589     static UnwindAssemblyProfilerInstances g_instances;
1590     return g_instances;
1591 }
1592 
1593 bool
1594 PluginManager::RegisterPlugin
1595 (
1596     const char *name,
1597     const char *description,
1598     UnwindAssemblyProfilerCreateInstance create_callback
1599 )
1600 {
1601     if (create_callback)
1602     {
1603         UnwindAssemblyProfilerInstance instance;
1604         assert (name && name[0]);
1605         instance.name = name;
1606         if (description && description[0])
1607             instance.description = description;
1608         instance.create_callback = create_callback;
1609         Mutex::Locker locker (GetUnwindAssemblyProfilerMutex ());
1610         GetUnwindAssemblyProfilerInstances ().push_back (instance);
1611     }
1612     return false;
1613 }
1614 
1615 bool
1616 PluginManager::UnregisterPlugin (UnwindAssemblyProfilerCreateInstance create_callback)
1617 {
1618     if (create_callback)
1619     {
1620         Mutex::Locker locker (GetUnwindAssemblyProfilerMutex ());
1621         UnwindAssemblyProfilerInstances &instances = GetUnwindAssemblyProfilerInstances ();
1622 
1623         UnwindAssemblyProfilerInstances::iterator pos, end = instances.end();
1624         for (pos = instances.begin(); pos != end; ++ pos)
1625         {
1626             if (pos->create_callback == create_callback)
1627             {
1628                 instances.erase(pos);
1629                 return true;
1630             }
1631         }
1632     }
1633     return false;
1634 }
1635 
1636 UnwindAssemblyProfilerCreateInstance
1637 PluginManager::GetUnwindAssemblyProfilerCreateCallbackAtIndex (uint32_t idx)
1638 {
1639     Mutex::Locker locker (GetUnwindAssemblyProfilerMutex ());
1640     UnwindAssemblyProfilerInstances &instances = GetUnwindAssemblyProfilerInstances ();
1641     if (idx < instances.size())
1642         return instances[idx].create_callback;
1643     return NULL;
1644 }
1645 
1646 
1647 UnwindAssemblyProfilerCreateInstance
1648 PluginManager::GetUnwindAssemblyProfilerCreateCallbackForPluginName (const char *name)
1649 {
1650     if (name && name[0])
1651     {
1652         llvm::StringRef name_sref(name);
1653         Mutex::Locker locker (GetUnwindAssemblyProfilerMutex ());
1654         UnwindAssemblyProfilerInstances &instances = GetUnwindAssemblyProfilerInstances ();
1655 
1656         UnwindAssemblyProfilerInstances::iterator pos, end = instances.end();
1657         for (pos = instances.begin(); pos != end; ++ pos)
1658         {
1659             if (name_sref.equals (pos->name))
1660                 return pos->create_callback;
1661         }
1662     }
1663     return NULL;
1664 }
1665 
1666 #pragma mark ArchDefaultUnwindPlan
1667 
1668 struct ArchDefaultUnwindPlanInstance
1669 {
1670     ArchDefaultUnwindPlanInstance() :
1671         name(),
1672         description(),
1673         create_callback(NULL)
1674     {
1675     }
1676 
1677     std::string name;
1678     std::string description;
1679     ArchDefaultUnwindPlanCreateInstance create_callback;
1680 };
1681 
1682 typedef std::vector<ArchDefaultUnwindPlanInstance> ArchDefaultUnwindPlanInstances;
1683 
1684 static Mutex &
1685 GetArchDefaultUnwindPlanMutex ()
1686 {
1687     static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive);
1688     return g_instances_mutex;
1689 }
1690 
1691 static ArchDefaultUnwindPlanInstances &
1692 GetArchDefaultUnwindPlanInstances ()
1693 {
1694     static ArchDefaultUnwindPlanInstances g_instances;
1695     return g_instances;
1696 }
1697 
1698 
1699 bool
1700 PluginManager::RegisterPlugin
1701 (
1702     const char *name,
1703     const char *description,
1704     ArchDefaultUnwindPlanCreateInstance create_callback
1705 )
1706 {
1707     if (create_callback)
1708     {
1709         ArchDefaultUnwindPlanInstance instance;
1710         assert (name && name[0]);
1711         instance.name = name;
1712         if (description && description[0])
1713             instance.description = description;
1714         instance.create_callback = create_callback;
1715         Mutex::Locker locker (GetArchDefaultUnwindPlanMutex ());
1716         GetArchDefaultUnwindPlanInstances ().push_back (instance);
1717     }
1718     return false;
1719 }
1720 
1721 bool
1722 PluginManager::UnregisterPlugin (ArchDefaultUnwindPlanCreateInstance create_callback)
1723 {
1724     if (create_callback)
1725     {
1726         Mutex::Locker locker (GetArchDefaultUnwindPlanMutex ());
1727         ArchDefaultUnwindPlanInstances &instances = GetArchDefaultUnwindPlanInstances ();
1728 
1729         ArchDefaultUnwindPlanInstances::iterator pos, end = instances.end();
1730         for (pos = instances.begin(); pos != end; ++ pos)
1731         {
1732             if (pos->create_callback == create_callback)
1733             {
1734                 instances.erase(pos);
1735                 return true;
1736             }
1737         }
1738     }
1739     return false;
1740 }
1741 
1742 ArchDefaultUnwindPlanCreateInstance
1743 PluginManager::GetArchDefaultUnwindPlanCreateCallbackAtIndex (uint32_t idx)
1744 {
1745     Mutex::Locker locker (GetArchDefaultUnwindPlanMutex ());
1746     ArchDefaultUnwindPlanInstances &instances = GetArchDefaultUnwindPlanInstances ();
1747     if (idx < instances.size())
1748         return instances[idx].create_callback;
1749     return NULL;
1750 }
1751 
1752 
1753 ArchDefaultUnwindPlanCreateInstance
1754 PluginManager::GetArchDefaultUnwindPlanCreateCallbackForPluginName (const char *name)
1755 {
1756     if (name && name[0])
1757     {
1758         llvm::StringRef name_sref(name);
1759         Mutex::Locker locker (GetArchDefaultUnwindPlanMutex ());
1760         ArchDefaultUnwindPlanInstances &instances = GetArchDefaultUnwindPlanInstances ();
1761 
1762         ArchDefaultUnwindPlanInstances::iterator pos, end = instances.end();
1763         for (pos = instances.begin(); pos != end; ++ pos)
1764         {
1765             if (name_sref.equals (pos->name))
1766                 return pos->create_callback;
1767         }
1768     }
1769     return NULL;
1770 }
1771 
1772 #pragma mark ArchVolatileRegs
1773 
1774 struct ArchVolatileRegsInstance
1775 {
1776     ArchVolatileRegsInstance() :
1777         name(),
1778         description(),
1779         create_callback(NULL)
1780     {
1781     }
1782 
1783     std::string name;
1784     std::string description;
1785     ArchVolatileRegsCreateInstance create_callback;
1786 };
1787 
1788 typedef std::vector<ArchVolatileRegsInstance> ArchVolatileRegsInstances;
1789 
1790 static Mutex &
1791 GetArchVolatileRegsMutex ()
1792 {
1793     static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive);
1794     return g_instances_mutex;
1795 }
1796 
1797 static ArchVolatileRegsInstances &
1798 GetArchVolatileRegsInstances ()
1799 {
1800     static ArchVolatileRegsInstances g_instances;
1801     return g_instances;
1802 }
1803 
1804 bool
1805 PluginManager::RegisterPlugin
1806 (
1807     const char *name,
1808     const char *description,
1809     ArchVolatileRegsCreateInstance create_callback
1810 )
1811 {
1812     if (create_callback)
1813     {
1814         ArchVolatileRegsInstance instance;
1815         assert (name && name[0]);
1816         instance.name = name;
1817         if (description && description[0])
1818             instance.description = description;
1819         instance.create_callback = create_callback;
1820         Mutex::Locker locker (GetArchVolatileRegsMutex ());
1821         GetArchVolatileRegsInstances ().push_back (instance);
1822     }
1823     return false;
1824 }
1825 
1826 bool
1827 PluginManager::UnregisterPlugin (ArchVolatileRegsCreateInstance create_callback)
1828 {
1829     if (create_callback)
1830     {
1831         Mutex::Locker locker (GetArchVolatileRegsMutex ());
1832         ArchVolatileRegsInstances &instances = GetArchVolatileRegsInstances ();
1833 
1834         ArchVolatileRegsInstances::iterator pos, end = instances.end();
1835         for (pos = instances.begin(); pos != end; ++ pos)
1836         {
1837             if (pos->create_callback == create_callback)
1838             {
1839                 instances.erase(pos);
1840                 return true;
1841             }
1842         }
1843     }
1844     return false;
1845 }
1846 
1847 ArchVolatileRegsCreateInstance
1848 PluginManager::GetArchVolatileRegsCreateCallbackAtIndex (uint32_t idx)
1849 {
1850     Mutex::Locker locker (GetArchVolatileRegsMutex ());
1851     ArchVolatileRegsInstances &instances = GetArchVolatileRegsInstances ();
1852     if (idx < instances.size())
1853         return instances[idx].create_callback;
1854     return NULL;
1855 }
1856 
1857 ArchVolatileRegsCreateInstance
1858 PluginManager::GetArchVolatileRegsCreateCallbackForPluginName (const char *name)
1859 {
1860     if (name && name[0])
1861     {
1862         llvm::StringRef name_sref(name);
1863         Mutex::Locker locker (GetArchVolatileRegsMutex ());
1864         ArchVolatileRegsInstances &instances = GetArchVolatileRegsInstances ();
1865 
1866         ArchVolatileRegsInstances::iterator pos, end = instances.end();
1867         for (pos = instances.begin(); pos != end; ++ pos)
1868         {
1869             if (name_sref.equals (pos->name))
1870                 return pos->create_callback;
1871         }
1872     }
1873     return NULL;
1874 }
1875 
1876