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 SystemRuntime
858
859
860struct SystemRuntimeInstance
861{
862    SystemRuntimeInstance() :
863        name(),
864        description(),
865        create_callback(NULL)
866    {
867    }
868
869    ConstString name;
870    std::string description;
871    SystemRuntimeCreateInstance create_callback;
872};
873
874typedef std::vector<SystemRuntimeInstance> SystemRuntimeInstances;
875
876static Mutex &
877GetSystemRuntimeMutex ()
878{
879    static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive);
880    return g_instances_mutex;
881}
882
883static SystemRuntimeInstances &
884GetSystemRuntimeInstances ()
885{
886    static SystemRuntimeInstances g_instances;
887    return g_instances;
888}
889
890bool
891PluginManager::RegisterPlugin
892(
893    const ConstString &name,
894    const char *description,
895    SystemRuntimeCreateInstance create_callback
896)
897{
898    if (create_callback)
899    {
900        SystemRuntimeInstance instance;
901        assert ((bool)name);
902        instance.name = name;
903        if (description && description[0])
904            instance.description = description;
905        instance.create_callback = create_callback;
906        Mutex::Locker locker (GetSystemRuntimeMutex ());
907        GetSystemRuntimeInstances ().push_back (instance);
908    }
909    return false;
910}
911
912bool
913PluginManager::UnregisterPlugin (SystemRuntimeCreateInstance create_callback)
914{
915    if (create_callback)
916    {
917        Mutex::Locker locker (GetSystemRuntimeMutex ());
918        SystemRuntimeInstances &instances = GetSystemRuntimeInstances ();
919
920        SystemRuntimeInstances::iterator pos, end = instances.end();
921        for (pos = instances.begin(); pos != end; ++ pos)
922        {
923            if (pos->create_callback == create_callback)
924            {
925                instances.erase(pos);
926                return true;
927            }
928        }
929    }
930    return false;
931}
932
933SystemRuntimeCreateInstance
934PluginManager::GetSystemRuntimeCreateCallbackAtIndex (uint32_t idx)
935{
936    Mutex::Locker locker (GetSystemRuntimeMutex ());
937    SystemRuntimeInstances &instances = GetSystemRuntimeInstances ();
938    if (idx < instances.size())
939        return instances[idx].create_callback;
940    return NULL;
941}
942
943SystemRuntimeCreateInstance
944PluginManager::GetSystemRuntimeCreateCallbackForPluginName (const ConstString &name)
945{
946    if (name)
947    {
948        Mutex::Locker locker (GetSystemRuntimeMutex ());
949        SystemRuntimeInstances &instances = GetSystemRuntimeInstances ();
950
951        SystemRuntimeInstances::iterator pos, end = instances.end();
952        for (pos = instances.begin(); pos != end; ++ pos)
953        {
954            if (name == pos->name)
955                return pos->create_callback;
956        }
957    }
958    return NULL;
959}
960
961
962#pragma mark ObjectFile
963
964struct ObjectFileInstance
965{
966    ObjectFileInstance() :
967        name(),
968        description(),
969        create_callback(NULL),
970        create_memory_callback (NULL),
971        get_module_specifications (NULL)
972    {
973    }
974
975    ConstString name;
976    std::string description;
977    ObjectFileCreateInstance create_callback;
978    ObjectFileCreateMemoryInstance create_memory_callback;
979    ObjectFileGetModuleSpecifications get_module_specifications;
980};
981
982typedef std::vector<ObjectFileInstance> ObjectFileInstances;
983
984static Mutex &
985GetObjectFileMutex ()
986{
987    static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive);
988    return g_instances_mutex;
989}
990
991static ObjectFileInstances &
992GetObjectFileInstances ()
993{
994    static ObjectFileInstances g_instances;
995    return g_instances;
996}
997
998
999bool
1000PluginManager::RegisterPlugin (const ConstString &name,
1001                               const char *description,
1002                               ObjectFileCreateInstance create_callback,
1003                               ObjectFileCreateMemoryInstance create_memory_callback,
1004                               ObjectFileGetModuleSpecifications get_module_specifications)
1005{
1006    if (create_callback)
1007    {
1008        ObjectFileInstance instance;
1009        assert ((bool)name);
1010        instance.name = name;
1011        if (description && description[0])
1012            instance.description = description;
1013        instance.create_callback = create_callback;
1014        instance.create_memory_callback = create_memory_callback;
1015        instance.get_module_specifications = get_module_specifications;
1016        Mutex::Locker locker (GetObjectFileMutex ());
1017        GetObjectFileInstances ().push_back (instance);
1018    }
1019    return false;
1020}
1021
1022bool
1023PluginManager::UnregisterPlugin (ObjectFileCreateInstance create_callback)
1024{
1025    if (create_callback)
1026    {
1027        Mutex::Locker locker (GetObjectFileMutex ());
1028        ObjectFileInstances &instances = GetObjectFileInstances ();
1029
1030        ObjectFileInstances::iterator pos, end = instances.end();
1031        for (pos = instances.begin(); pos != end; ++ pos)
1032        {
1033            if (pos->create_callback == create_callback)
1034            {
1035                instances.erase(pos);
1036                return true;
1037            }
1038        }
1039    }
1040    return false;
1041}
1042
1043ObjectFileCreateInstance
1044PluginManager::GetObjectFileCreateCallbackAtIndex (uint32_t idx)
1045{
1046    Mutex::Locker locker (GetObjectFileMutex ());
1047    ObjectFileInstances &instances = GetObjectFileInstances ();
1048    if (idx < instances.size())
1049        return instances[idx].create_callback;
1050    return NULL;
1051}
1052
1053
1054ObjectFileCreateMemoryInstance
1055PluginManager::GetObjectFileCreateMemoryCallbackAtIndex (uint32_t idx)
1056{
1057    Mutex::Locker locker (GetObjectFileMutex ());
1058    ObjectFileInstances &instances = GetObjectFileInstances ();
1059    if (idx < instances.size())
1060        return instances[idx].create_memory_callback;
1061    return NULL;
1062}
1063
1064ObjectFileGetModuleSpecifications
1065PluginManager::GetObjectFileGetModuleSpecificationsCallbackAtIndex (uint32_t idx)
1066{
1067    Mutex::Locker locker (GetObjectFileMutex ());
1068    ObjectFileInstances &instances = GetObjectFileInstances ();
1069    if (idx < instances.size())
1070        return instances[idx].get_module_specifications;
1071    return NULL;
1072}
1073
1074ObjectFileCreateInstance
1075PluginManager::GetObjectFileCreateCallbackForPluginName (const ConstString &name)
1076{
1077    if (name)
1078    {
1079        Mutex::Locker locker (GetObjectFileMutex ());
1080        ObjectFileInstances &instances = GetObjectFileInstances ();
1081
1082        ObjectFileInstances::iterator pos, end = instances.end();
1083        for (pos = instances.begin(); pos != end; ++ pos)
1084        {
1085            if (name == pos->name)
1086                return pos->create_callback;
1087        }
1088    }
1089    return NULL;
1090}
1091
1092
1093ObjectFileCreateMemoryInstance
1094PluginManager::GetObjectFileCreateMemoryCallbackForPluginName (const ConstString &name)
1095{
1096    if (name)
1097    {
1098        Mutex::Locker locker (GetObjectFileMutex ());
1099        ObjectFileInstances &instances = GetObjectFileInstances ();
1100
1101        ObjectFileInstances::iterator pos, end = instances.end();
1102        for (pos = instances.begin(); pos != end; ++ pos)
1103        {
1104            if (name == pos->name)
1105                return pos->create_memory_callback;
1106        }
1107    }
1108    return NULL;
1109}
1110
1111
1112
1113#pragma mark ObjectContainer
1114
1115struct ObjectContainerInstance
1116{
1117    ObjectContainerInstance() :
1118        name(),
1119        description(),
1120        create_callback (NULL),
1121        get_module_specifications (NULL)
1122    {
1123    }
1124
1125    ConstString name;
1126    std::string description;
1127    ObjectContainerCreateInstance create_callback;
1128    ObjectFileGetModuleSpecifications get_module_specifications;
1129
1130};
1131
1132typedef std::vector<ObjectContainerInstance> ObjectContainerInstances;
1133
1134static Mutex &
1135GetObjectContainerMutex ()
1136{
1137    static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive);
1138    return g_instances_mutex;
1139}
1140
1141static ObjectContainerInstances &
1142GetObjectContainerInstances ()
1143{
1144    static ObjectContainerInstances g_instances;
1145    return g_instances;
1146}
1147
1148bool
1149PluginManager::RegisterPlugin (const ConstString &name,
1150                               const char *description,
1151                               ObjectContainerCreateInstance create_callback,
1152                               ObjectFileGetModuleSpecifications get_module_specifications)
1153{
1154    if (create_callback)
1155    {
1156        ObjectContainerInstance instance;
1157        assert ((bool)name);
1158        instance.name = name;
1159        if (description && description[0])
1160            instance.description = description;
1161        instance.create_callback = create_callback;
1162        instance.get_module_specifications = get_module_specifications;
1163        Mutex::Locker locker (GetObjectContainerMutex ());
1164        GetObjectContainerInstances ().push_back (instance);
1165    }
1166    return false;
1167}
1168
1169bool
1170PluginManager::UnregisterPlugin (ObjectContainerCreateInstance create_callback)
1171{
1172    if (create_callback)
1173    {
1174        Mutex::Locker locker (GetObjectContainerMutex ());
1175        ObjectContainerInstances &instances = GetObjectContainerInstances ();
1176
1177        ObjectContainerInstances::iterator pos, end = instances.end();
1178        for (pos = instances.begin(); pos != end; ++ pos)
1179        {
1180            if (pos->create_callback == create_callback)
1181            {
1182                instances.erase(pos);
1183                return true;
1184            }
1185        }
1186    }
1187    return false;
1188}
1189
1190ObjectContainerCreateInstance
1191PluginManager::GetObjectContainerCreateCallbackAtIndex (uint32_t idx)
1192{
1193    Mutex::Locker locker (GetObjectContainerMutex ());
1194    ObjectContainerInstances &instances = GetObjectContainerInstances ();
1195    if (idx < instances.size())
1196        return instances[idx].create_callback;
1197    return NULL;
1198}
1199
1200ObjectContainerCreateInstance
1201PluginManager::GetObjectContainerCreateCallbackForPluginName (const ConstString &name)
1202{
1203    if (name)
1204    {
1205        Mutex::Locker locker (GetObjectContainerMutex ());
1206        ObjectContainerInstances &instances = GetObjectContainerInstances ();
1207
1208        ObjectContainerInstances::iterator pos, end = instances.end();
1209        for (pos = instances.begin(); pos != end; ++ pos)
1210        {
1211            if (name == pos->name)
1212                return pos->create_callback;
1213        }
1214    }
1215    return NULL;
1216}
1217
1218ObjectFileGetModuleSpecifications
1219PluginManager::GetObjectContainerGetModuleSpecificationsCallbackAtIndex (uint32_t idx)
1220{
1221    Mutex::Locker locker (GetObjectContainerMutex ());
1222    ObjectContainerInstances &instances = GetObjectContainerInstances ();
1223    if (idx < instances.size())
1224        return instances[idx].get_module_specifications;
1225    return NULL;
1226}
1227
1228#pragma mark LogChannel
1229
1230struct LogInstance
1231{
1232    LogInstance() :
1233        name(),
1234        description(),
1235        create_callback(NULL)
1236    {
1237    }
1238
1239    ConstString name;
1240    std::string description;
1241    LogChannelCreateInstance create_callback;
1242};
1243
1244typedef std::vector<LogInstance> LogInstances;
1245
1246static Mutex &
1247GetLogMutex ()
1248{
1249    static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive);
1250    return g_instances_mutex;
1251}
1252
1253static LogInstances &
1254GetLogInstances ()
1255{
1256    static LogInstances g_instances;
1257    return g_instances;
1258}
1259
1260
1261
1262bool
1263PluginManager::RegisterPlugin
1264(
1265    const ConstString &name,
1266    const char *description,
1267    LogChannelCreateInstance create_callback
1268)
1269{
1270    if (create_callback)
1271    {
1272        LogInstance instance;
1273        assert ((bool)name);
1274        instance.name = name;
1275        if (description && description[0])
1276            instance.description = description;
1277        instance.create_callback = create_callback;
1278        Mutex::Locker locker (GetLogMutex ());
1279        GetLogInstances ().push_back (instance);
1280    }
1281    return false;
1282}
1283
1284bool
1285PluginManager::UnregisterPlugin (LogChannelCreateInstance create_callback)
1286{
1287    if (create_callback)
1288    {
1289        Mutex::Locker locker (GetLogMutex ());
1290        LogInstances &instances = GetLogInstances ();
1291
1292        LogInstances::iterator pos, end = instances.end();
1293        for (pos = instances.begin(); pos != end; ++ pos)
1294        {
1295            if (pos->create_callback == create_callback)
1296            {
1297                instances.erase(pos);
1298                return true;
1299            }
1300        }
1301    }
1302    return false;
1303}
1304
1305const char *
1306PluginManager::GetLogChannelCreateNameAtIndex (uint32_t idx)
1307{
1308    Mutex::Locker locker (GetLogMutex ());
1309    LogInstances &instances = GetLogInstances ();
1310    if (idx < instances.size())
1311        return instances[idx].name.GetCString();
1312    return NULL;
1313}
1314
1315
1316LogChannelCreateInstance
1317PluginManager::GetLogChannelCreateCallbackAtIndex (uint32_t idx)
1318{
1319    Mutex::Locker locker (GetLogMutex ());
1320    LogInstances &instances = GetLogInstances ();
1321    if (idx < instances.size())
1322        return instances[idx].create_callback;
1323    return NULL;
1324}
1325
1326LogChannelCreateInstance
1327PluginManager::GetLogChannelCreateCallbackForPluginName (const ConstString &name)
1328{
1329    if (name)
1330    {
1331        Mutex::Locker locker (GetLogMutex ());
1332        LogInstances &instances = GetLogInstances ();
1333
1334        LogInstances::iterator pos, end = instances.end();
1335        for (pos = instances.begin(); pos != end; ++ pos)
1336        {
1337            if (name == pos->name)
1338                return pos->create_callback;
1339        }
1340    }
1341    return NULL;
1342}
1343
1344#pragma mark Platform
1345
1346struct PlatformInstance
1347{
1348    PlatformInstance() :
1349        name(),
1350        description(),
1351        create_callback(NULL),
1352        debugger_init_callback (NULL)
1353    {
1354    }
1355
1356    ConstString name;
1357    std::string description;
1358    PlatformCreateInstance create_callback;
1359    DebuggerInitializeCallback debugger_init_callback;
1360};
1361
1362typedef std::vector<PlatformInstance> PlatformInstances;
1363
1364static Mutex &
1365GetPlatformInstancesMutex ()
1366{
1367    static Mutex g_platform_instances_mutex (Mutex::eMutexTypeRecursive);
1368    return g_platform_instances_mutex;
1369}
1370
1371static PlatformInstances &
1372GetPlatformInstances ()
1373{
1374    static PlatformInstances g_platform_instances;
1375    return g_platform_instances;
1376}
1377
1378
1379bool
1380PluginManager::RegisterPlugin (const ConstString &name,
1381                               const char *description,
1382                               PlatformCreateInstance create_callback,
1383                               DebuggerInitializeCallback debugger_init_callback)
1384{
1385    if (create_callback)
1386    {
1387        Mutex::Locker locker (GetPlatformInstancesMutex ());
1388
1389        PlatformInstance instance;
1390        assert ((bool)name);
1391        instance.name = name;
1392        if (description && description[0])
1393            instance.description = description;
1394        instance.create_callback = create_callback;
1395        instance.debugger_init_callback = debugger_init_callback;
1396        GetPlatformInstances ().push_back (instance);
1397        return true;
1398    }
1399    return false;
1400}
1401
1402
1403const char *
1404PluginManager::GetPlatformPluginNameAtIndex (uint32_t idx)
1405{
1406    Mutex::Locker locker (GetPlatformInstancesMutex ());
1407    PlatformInstances &instances = GetPlatformInstances ();
1408    if (idx < instances.size())
1409        return instances[idx].name.GetCString();
1410    return NULL;
1411}
1412
1413const char *
1414PluginManager::GetPlatformPluginDescriptionAtIndex (uint32_t idx)
1415{
1416    Mutex::Locker locker (GetPlatformInstancesMutex ());
1417    PlatformInstances &instances = GetPlatformInstances ();
1418    if (idx < instances.size())
1419        return instances[idx].description.c_str();
1420    return NULL;
1421}
1422
1423bool
1424PluginManager::UnregisterPlugin (PlatformCreateInstance create_callback)
1425{
1426    if (create_callback)
1427    {
1428        Mutex::Locker locker (GetPlatformInstancesMutex ());
1429        PlatformInstances &instances = GetPlatformInstances ();
1430
1431        PlatformInstances::iterator pos, end = instances.end();
1432        for (pos = instances.begin(); pos != end; ++ pos)
1433        {
1434            if (pos->create_callback == create_callback)
1435            {
1436                instances.erase(pos);
1437                return true;
1438            }
1439        }
1440    }
1441    return false;
1442}
1443
1444PlatformCreateInstance
1445PluginManager::GetPlatformCreateCallbackAtIndex (uint32_t idx)
1446{
1447    Mutex::Locker locker (GetPlatformInstancesMutex ());
1448    PlatformInstances &instances = GetPlatformInstances ();
1449    if (idx < instances.size())
1450        return instances[idx].create_callback;
1451    return NULL;
1452}
1453
1454PlatformCreateInstance
1455PluginManager::GetPlatformCreateCallbackForPluginName (const ConstString &name)
1456{
1457    if (name)
1458    {
1459        Mutex::Locker locker (GetPlatformInstancesMutex ());
1460        PlatformInstances &instances = GetPlatformInstances ();
1461
1462        PlatformInstances::iterator pos, end = instances.end();
1463        for (pos = instances.begin(); pos != end; ++ pos)
1464        {
1465            if (name == pos->name)
1466                return pos->create_callback;
1467        }
1468    }
1469    return NULL;
1470}
1471
1472size_t
1473PluginManager::AutoCompletePlatformName (const char *name, StringList &matches)
1474{
1475    if (name)
1476    {
1477        Mutex::Locker locker (GetPlatformInstancesMutex ());
1478        PlatformInstances &instances = GetPlatformInstances ();
1479        llvm::StringRef name_sref(name);
1480
1481        PlatformInstances::iterator pos, end = instances.end();
1482        for (pos = instances.begin(); pos != end; ++ pos)
1483        {
1484            llvm::StringRef plugin_name (pos->name.GetCString());
1485            if (plugin_name.startswith(name_sref))
1486                matches.AppendString (plugin_name.data());
1487        }
1488    }
1489    return matches.GetSize();
1490}
1491#pragma mark Process
1492
1493struct ProcessInstance
1494{
1495    ProcessInstance() :
1496        name(),
1497        description(),
1498        create_callback(NULL),
1499        debugger_init_callback(NULL)
1500    {
1501    }
1502
1503    ConstString name;
1504    std::string description;
1505    ProcessCreateInstance create_callback;
1506    DebuggerInitializeCallback debugger_init_callback;
1507};
1508
1509typedef std::vector<ProcessInstance> ProcessInstances;
1510
1511static Mutex &
1512GetProcessMutex ()
1513{
1514    static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive);
1515    return g_instances_mutex;
1516}
1517
1518static ProcessInstances &
1519GetProcessInstances ()
1520{
1521    static ProcessInstances g_instances;
1522    return g_instances;
1523}
1524
1525
1526bool
1527PluginManager::RegisterPlugin (const ConstString &name,
1528                               const char *description,
1529                               ProcessCreateInstance create_callback,
1530                               DebuggerInitializeCallback debugger_init_callback)
1531{
1532    if (create_callback)
1533    {
1534        ProcessInstance instance;
1535        assert ((bool)name);
1536        instance.name = name;
1537        if (description && description[0])
1538            instance.description = description;
1539        instance.create_callback = create_callback;
1540        instance.debugger_init_callback = debugger_init_callback;
1541        Mutex::Locker locker (GetProcessMutex ());
1542        GetProcessInstances ().push_back (instance);
1543    }
1544    return false;
1545}
1546
1547const char *
1548PluginManager::GetProcessPluginNameAtIndex (uint32_t idx)
1549{
1550    Mutex::Locker locker (GetProcessMutex ());
1551    ProcessInstances &instances = GetProcessInstances ();
1552    if (idx < instances.size())
1553        return instances[idx].name.GetCString();
1554    return NULL;
1555}
1556
1557const char *
1558PluginManager::GetProcessPluginDescriptionAtIndex (uint32_t idx)
1559{
1560    Mutex::Locker locker (GetProcessMutex ());
1561    ProcessInstances &instances = GetProcessInstances ();
1562    if (idx < instances.size())
1563        return instances[idx].description.c_str();
1564    return NULL;
1565}
1566
1567bool
1568PluginManager::UnregisterPlugin (ProcessCreateInstance create_callback)
1569{
1570    if (create_callback)
1571    {
1572        Mutex::Locker locker (GetProcessMutex ());
1573        ProcessInstances &instances = GetProcessInstances ();
1574
1575        ProcessInstances::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
1588ProcessCreateInstance
1589PluginManager::GetProcessCreateCallbackAtIndex (uint32_t idx)
1590{
1591    Mutex::Locker locker (GetProcessMutex ());
1592    ProcessInstances &instances = GetProcessInstances ();
1593    if (idx < instances.size())
1594        return instances[idx].create_callback;
1595    return NULL;
1596}
1597
1598
1599ProcessCreateInstance
1600PluginManager::GetProcessCreateCallbackForPluginName (const ConstString &name)
1601{
1602    if (name)
1603    {
1604        Mutex::Locker locker (GetProcessMutex ());
1605        ProcessInstances &instances = GetProcessInstances ();
1606
1607        ProcessInstances::iterator pos, end = instances.end();
1608        for (pos = instances.begin(); pos != end; ++ pos)
1609        {
1610            if (name == pos->name)
1611                return pos->create_callback;
1612        }
1613    }
1614    return NULL;
1615}
1616
1617#pragma mark SymbolFile
1618
1619struct SymbolFileInstance
1620{
1621    SymbolFileInstance() :
1622        name(),
1623        description(),
1624        create_callback(NULL)
1625    {
1626    }
1627
1628    ConstString name;
1629    std::string description;
1630    SymbolFileCreateInstance create_callback;
1631};
1632
1633typedef std::vector<SymbolFileInstance> SymbolFileInstances;
1634
1635static Mutex &
1636GetSymbolFileMutex ()
1637{
1638    static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive);
1639    return g_instances_mutex;
1640}
1641
1642static SymbolFileInstances &
1643GetSymbolFileInstances ()
1644{
1645    static SymbolFileInstances g_instances;
1646    return g_instances;
1647}
1648
1649
1650bool
1651PluginManager::RegisterPlugin
1652(
1653    const ConstString &name,
1654    const char *description,
1655    SymbolFileCreateInstance create_callback
1656)
1657{
1658    if (create_callback)
1659    {
1660        SymbolFileInstance 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 (GetSymbolFileMutex ());
1667        GetSymbolFileInstances ().push_back (instance);
1668    }
1669    return false;
1670}
1671
1672bool
1673PluginManager::UnregisterPlugin (SymbolFileCreateInstance create_callback)
1674{
1675    if (create_callback)
1676    {
1677        Mutex::Locker locker (GetSymbolFileMutex ());
1678        SymbolFileInstances &instances = GetSymbolFileInstances ();
1679
1680        SymbolFileInstances::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
1693SymbolFileCreateInstance
1694PluginManager::GetSymbolFileCreateCallbackAtIndex (uint32_t idx)
1695{
1696    Mutex::Locker locker (GetSymbolFileMutex ());
1697    SymbolFileInstances &instances = GetSymbolFileInstances ();
1698    if (idx < instances.size())
1699        return instances[idx].create_callback;
1700    return NULL;
1701}
1702
1703SymbolFileCreateInstance
1704PluginManager::GetSymbolFileCreateCallbackForPluginName (const ConstString &name)
1705{
1706    if (name)
1707    {
1708        Mutex::Locker locker (GetSymbolFileMutex ());
1709        SymbolFileInstances &instances = GetSymbolFileInstances ();
1710
1711        SymbolFileInstances::iterator pos, end = instances.end();
1712        for (pos = instances.begin(); pos != end; ++ pos)
1713        {
1714            if (name == pos->name)
1715                return pos->create_callback;
1716        }
1717    }
1718    return NULL;
1719}
1720
1721
1722
1723#pragma mark SymbolVendor
1724
1725struct SymbolVendorInstance
1726{
1727    SymbolVendorInstance() :
1728        name(),
1729        description(),
1730        create_callback(NULL)
1731    {
1732    }
1733
1734    ConstString name;
1735    std::string description;
1736    SymbolVendorCreateInstance create_callback;
1737};
1738
1739typedef std::vector<SymbolVendorInstance> SymbolVendorInstances;
1740
1741static Mutex &
1742GetSymbolVendorMutex ()
1743{
1744    static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive);
1745    return g_instances_mutex;
1746}
1747
1748static SymbolVendorInstances &
1749GetSymbolVendorInstances ()
1750{
1751    static SymbolVendorInstances g_instances;
1752    return g_instances;
1753}
1754
1755bool
1756PluginManager::RegisterPlugin
1757(
1758    const ConstString &name,
1759    const char *description,
1760    SymbolVendorCreateInstance create_callback
1761)
1762{
1763    if (create_callback)
1764    {
1765        SymbolVendorInstance 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 (GetSymbolVendorMutex ());
1772        GetSymbolVendorInstances ().push_back (instance);
1773    }
1774    return false;
1775}
1776
1777bool
1778PluginManager::UnregisterPlugin (SymbolVendorCreateInstance create_callback)
1779{
1780    if (create_callback)
1781    {
1782        Mutex::Locker locker (GetSymbolVendorMutex ());
1783        SymbolVendorInstances &instances = GetSymbolVendorInstances ();
1784
1785        SymbolVendorInstances::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
1798SymbolVendorCreateInstance
1799PluginManager::GetSymbolVendorCreateCallbackAtIndex (uint32_t idx)
1800{
1801    Mutex::Locker locker (GetSymbolVendorMutex ());
1802    SymbolVendorInstances &instances = GetSymbolVendorInstances ();
1803    if (idx < instances.size())
1804        return instances[idx].create_callback;
1805    return NULL;
1806}
1807
1808
1809SymbolVendorCreateInstance
1810PluginManager::GetSymbolVendorCreateCallbackForPluginName (const ConstString &name)
1811{
1812    if (name)
1813    {
1814        Mutex::Locker locker (GetSymbolVendorMutex ());
1815        SymbolVendorInstances &instances = GetSymbolVendorInstances ();
1816
1817        SymbolVendorInstances::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
1827
1828#pragma mark UnwindAssembly
1829
1830struct UnwindAssemblyInstance
1831{
1832    UnwindAssemblyInstance() :
1833        name(),
1834        description(),
1835        create_callback(NULL)
1836    {
1837    }
1838
1839    ConstString name;
1840    std::string description;
1841    UnwindAssemblyCreateInstance create_callback;
1842};
1843
1844typedef std::vector<UnwindAssemblyInstance> UnwindAssemblyInstances;
1845
1846static Mutex &
1847GetUnwindAssemblyMutex ()
1848{
1849    static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive);
1850    return g_instances_mutex;
1851}
1852
1853static UnwindAssemblyInstances &
1854GetUnwindAssemblyInstances ()
1855{
1856    static UnwindAssemblyInstances g_instances;
1857    return g_instances;
1858}
1859
1860bool
1861PluginManager::RegisterPlugin
1862(
1863    const ConstString &name,
1864    const char *description,
1865    UnwindAssemblyCreateInstance create_callback
1866)
1867{
1868    if (create_callback)
1869    {
1870        UnwindAssemblyInstance instance;
1871        assert ((bool)name);
1872        instance.name = name;
1873        if (description && description[0])
1874            instance.description = description;
1875        instance.create_callback = create_callback;
1876        Mutex::Locker locker (GetUnwindAssemblyMutex ());
1877        GetUnwindAssemblyInstances ().push_back (instance);
1878    }
1879    return false;
1880}
1881
1882bool
1883PluginManager::UnregisterPlugin (UnwindAssemblyCreateInstance create_callback)
1884{
1885    if (create_callback)
1886    {
1887        Mutex::Locker locker (GetUnwindAssemblyMutex ());
1888        UnwindAssemblyInstances &instances = GetUnwindAssemblyInstances ();
1889
1890        UnwindAssemblyInstances::iterator pos, end = instances.end();
1891        for (pos = instances.begin(); pos != end; ++ pos)
1892        {
1893            if (pos->create_callback == create_callback)
1894            {
1895                instances.erase(pos);
1896                return true;
1897            }
1898        }
1899    }
1900    return false;
1901}
1902
1903UnwindAssemblyCreateInstance
1904PluginManager::GetUnwindAssemblyCreateCallbackAtIndex (uint32_t idx)
1905{
1906    Mutex::Locker locker (GetUnwindAssemblyMutex ());
1907    UnwindAssemblyInstances &instances = GetUnwindAssemblyInstances ();
1908    if (idx < instances.size())
1909        return instances[idx].create_callback;
1910    return NULL;
1911}
1912
1913
1914UnwindAssemblyCreateInstance
1915PluginManager::GetUnwindAssemblyCreateCallbackForPluginName (const ConstString &name)
1916{
1917    if (name)
1918    {
1919        Mutex::Locker locker (GetUnwindAssemblyMutex ());
1920        UnwindAssemblyInstances &instances = GetUnwindAssemblyInstances ();
1921
1922        UnwindAssemblyInstances::iterator pos, end = instances.end();
1923        for (pos = instances.begin(); pos != end; ++ pos)
1924        {
1925            if (name == pos->name)
1926                return pos->create_callback;
1927        }
1928    }
1929    return NULL;
1930}
1931
1932void
1933PluginManager::DebuggerInitialize (Debugger &debugger)
1934{
1935    // Initialize the DynamicLoader plugins
1936    {
1937        Mutex::Locker locker (GetDynamicLoaderMutex ());
1938        DynamicLoaderInstances &instances = GetDynamicLoaderInstances ();
1939
1940        DynamicLoaderInstances::iterator pos, end = instances.end();
1941        for (pos = instances.begin(); pos != end; ++ pos)
1942        {
1943            if (pos->debugger_init_callback)
1944                pos->debugger_init_callback (debugger);
1945        }
1946    }
1947
1948    // Initialize the Platform plugins
1949    {
1950        Mutex::Locker locker (GetPlatformInstancesMutex ());
1951        PlatformInstances &instances = GetPlatformInstances ();
1952
1953        PlatformInstances::iterator pos, end = instances.end();
1954        for (pos = instances.begin(); pos != end; ++ pos)
1955        {
1956            if (pos->debugger_init_callback)
1957                pos->debugger_init_callback (debugger);
1958        }
1959    }
1960
1961    // Initialize the Process plugins
1962    {
1963        Mutex::Locker locker (GetProcessMutex());
1964        ProcessInstances &instances = GetProcessInstances();
1965
1966        ProcessInstances::iterator pos, end = instances.end();
1967        for (pos = instances.begin(); pos != end; ++ pos)
1968        {
1969            if (pos->debugger_init_callback)
1970                pos->debugger_init_callback (debugger);
1971        }
1972    }
1973
1974}
1975
1976// This is the preferred new way to register plugin specific settings.  e.g.
1977// This will put a plugin's settings under e.g. "plugin.<plugin_type_name>.<plugin_type_desc>.SETTINGNAME".
1978static lldb::OptionValuePropertiesSP
1979GetDebuggerPropertyForPlugins (Debugger &debugger,
1980                                       const ConstString &plugin_type_name,
1981                                       const ConstString &plugin_type_desc,
1982                                       bool can_create)
1983{
1984    lldb::OptionValuePropertiesSP parent_properties_sp (debugger.GetValueProperties());
1985    if (parent_properties_sp)
1986    {
1987        static ConstString g_property_name("plugin");
1988
1989        OptionValuePropertiesSP plugin_properties_sp = parent_properties_sp->GetSubProperty (NULL, g_property_name);
1990        if (!plugin_properties_sp && can_create)
1991        {
1992            plugin_properties_sp.reset (new OptionValueProperties (g_property_name));
1993            parent_properties_sp->AppendProperty (g_property_name,
1994                                                  ConstString("Settings specify to plugins."),
1995                                                  true,
1996                                                  plugin_properties_sp);
1997        }
1998
1999        if (plugin_properties_sp)
2000        {
2001            lldb::OptionValuePropertiesSP plugin_type_properties_sp = plugin_properties_sp->GetSubProperty (NULL, plugin_type_name);
2002            if (!plugin_type_properties_sp && can_create)
2003            {
2004                plugin_type_properties_sp.reset (new OptionValueProperties (plugin_type_name));
2005                plugin_properties_sp->AppendProperty (plugin_type_name,
2006                                                      plugin_type_desc,
2007                                                      true,
2008                                                      plugin_type_properties_sp);
2009            }
2010            return plugin_type_properties_sp;
2011        }
2012    }
2013    return lldb::OptionValuePropertiesSP();
2014}
2015
2016// This is deprecated way to register plugin specific settings.  e.g.
2017// "<plugin_type_name>.plugin.<plugin_type_desc>.SETTINGNAME"
2018// and Platform generic settings would be under "platform.SETTINGNAME".
2019static lldb::OptionValuePropertiesSP
2020GetDebuggerPropertyForPluginsOldStyle (Debugger &debugger,
2021                                       const ConstString &plugin_type_name,
2022                                       const ConstString &plugin_type_desc,
2023                                       bool can_create)
2024{
2025    static ConstString g_property_name("plugin");
2026    lldb::OptionValuePropertiesSP parent_properties_sp (debugger.GetValueProperties());
2027    if (parent_properties_sp)
2028    {
2029        OptionValuePropertiesSP plugin_properties_sp = parent_properties_sp->GetSubProperty (NULL, plugin_type_name);
2030        if (!plugin_properties_sp && can_create)
2031        {
2032            plugin_properties_sp.reset (new OptionValueProperties (plugin_type_name));
2033            parent_properties_sp->AppendProperty (plugin_type_name,
2034                                                  plugin_type_desc,
2035                                                  true,
2036                                                  plugin_properties_sp);
2037        }
2038
2039        if (plugin_properties_sp)
2040        {
2041            lldb::OptionValuePropertiesSP plugin_type_properties_sp = plugin_properties_sp->GetSubProperty (NULL, g_property_name);
2042            if (!plugin_type_properties_sp && can_create)
2043            {
2044                plugin_type_properties_sp.reset (new OptionValueProperties (g_property_name));
2045                plugin_properties_sp->AppendProperty (g_property_name,
2046                                                      ConstString("Settings specific to plugins"),
2047                                                      true,
2048                                                      plugin_type_properties_sp);
2049            }
2050            return plugin_type_properties_sp;
2051        }
2052    }
2053    return lldb::OptionValuePropertiesSP();
2054}
2055
2056
2057lldb::OptionValuePropertiesSP
2058PluginManager::GetSettingForDynamicLoaderPlugin (Debugger &debugger, const ConstString &setting_name)
2059{
2060    lldb::OptionValuePropertiesSP properties_sp;
2061    lldb::OptionValuePropertiesSP plugin_type_properties_sp (GetDebuggerPropertyForPlugins (debugger,
2062                                                                                            ConstString("dynamic-loader"),
2063                                                                                            ConstString(), // not creating to so we don't need the description
2064                                                                                            false));
2065    if (plugin_type_properties_sp)
2066        properties_sp = plugin_type_properties_sp->GetSubProperty (NULL, setting_name);
2067    return properties_sp;
2068}
2069
2070bool
2071PluginManager::CreateSettingForDynamicLoaderPlugin (Debugger &debugger,
2072                                                    const lldb::OptionValuePropertiesSP &properties_sp,
2073                                                    const ConstString &description,
2074                                                    bool is_global_property)
2075{
2076    if (properties_sp)
2077    {
2078        lldb::OptionValuePropertiesSP plugin_type_properties_sp (GetDebuggerPropertyForPlugins (debugger,
2079                                                                                                ConstString("dynamic-loader"),
2080                                                                                                ConstString("Settings for dynamic loader plug-ins"),
2081                                                                                                true));
2082        if (plugin_type_properties_sp)
2083        {
2084            plugin_type_properties_sp->AppendProperty (properties_sp->GetName(),
2085                                                       description,
2086                                                       is_global_property,
2087                                                       properties_sp);
2088            return true;
2089        }
2090    }
2091    return false;
2092}
2093
2094
2095lldb::OptionValuePropertiesSP
2096PluginManager::GetSettingForPlatformPlugin (Debugger &debugger, const ConstString &setting_name)
2097{
2098    lldb::OptionValuePropertiesSP properties_sp;
2099    lldb::OptionValuePropertiesSP plugin_type_properties_sp (GetDebuggerPropertyForPluginsOldStyle (debugger,
2100                                                                                                    ConstString("platform"),
2101                                                                                                    ConstString(), // not creating to so we don't need the description
2102                                                                                                    false));
2103    if (plugin_type_properties_sp)
2104        properties_sp = plugin_type_properties_sp->GetSubProperty (NULL, setting_name);
2105    return properties_sp;
2106}
2107
2108bool
2109PluginManager::CreateSettingForPlatformPlugin (Debugger &debugger,
2110                                                    const lldb::OptionValuePropertiesSP &properties_sp,
2111                                                    const ConstString &description,
2112                                                    bool is_global_property)
2113{
2114    if (properties_sp)
2115    {
2116        lldb::OptionValuePropertiesSP plugin_type_properties_sp (GetDebuggerPropertyForPluginsOldStyle (debugger,
2117                                                                                                        ConstString("platform"),
2118                                                                                                        ConstString("Settings for platform plug-ins"),
2119                                                                                                        true));
2120        if (plugin_type_properties_sp)
2121        {
2122            plugin_type_properties_sp->AppendProperty (properties_sp->GetName(),
2123                                                       description,
2124                                                       is_global_property,
2125                                                       properties_sp);
2126            return true;
2127        }
2128    }
2129    return false;
2130}
2131
2132
2133lldb::OptionValuePropertiesSP
2134PluginManager::GetSettingForProcessPlugin (Debugger &debugger, const ConstString &setting_name)
2135{
2136    lldb::OptionValuePropertiesSP properties_sp;
2137    lldb::OptionValuePropertiesSP plugin_type_properties_sp (GetDebuggerPropertyForPlugins (debugger,
2138                                                                                            ConstString("process"),
2139                                                                                            ConstString(), // not creating to so we don't need the description
2140                                                                                            false));
2141    if (plugin_type_properties_sp)
2142        properties_sp = plugin_type_properties_sp->GetSubProperty (NULL, setting_name);
2143    return properties_sp;
2144}
2145
2146bool
2147PluginManager::CreateSettingForProcessPlugin (Debugger &debugger,
2148                                              const lldb::OptionValuePropertiesSP &properties_sp,
2149                                              const ConstString &description,
2150                                              bool is_global_property)
2151{
2152    if (properties_sp)
2153    {
2154        lldb::OptionValuePropertiesSP plugin_type_properties_sp (GetDebuggerPropertyForPlugins (debugger,
2155                                                                                                ConstString("process"),
2156                                                                                                ConstString("Settings for process plug-ins"),
2157                                                                                                true));
2158        if (plugin_type_properties_sp)
2159        {
2160            plugin_type_properties_sp->AppendProperty (properties_sp->GetName(),
2161                                                       description,
2162                                                       is_global_property,
2163                                                       properties_sp);
2164            return true;
2165        }
2166    }
2167    return false;
2168}
2169
2170