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