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