1 //===-- PluginManager.cpp ---------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "lldb/Core/PluginManager.h"
11 
12 #include <string>
13 #include <vector>
14 
15 using namespace lldb_private;
16 
17 enum PluginAction
18 {
19     ePluginRegisterInstance,
20     ePluginUnregisterInstance,
21     ePluginGetInstanceAtIndex
22 };
23 
24 
25 #pragma mark ABI
26 
27 
28 struct ABIInstance
29 {
30     ABIInstance() :
31         name(),
32         description(),
33         create_callback(NULL)
34     {
35     }
36 
37     std::string name;
38     std::string description;
39     ABICreateInstance create_callback;
40 };
41 
42 typedef std::vector<ABIInstance> ABIInstances;
43 
44 static bool
45 AccessABIInstances (PluginAction action, ABIInstance &instance, uint32_t index)
46 {
47     static ABIInstances g_plugin_instances;
48 
49     switch (action)
50     {
51         case ePluginRegisterInstance:
52             if (instance.create_callback)
53             {
54                 g_plugin_instances.push_back (instance);
55                 return true;
56             }
57             break;
58 
59         case ePluginUnregisterInstance:
60             if (instance.create_callback)
61             {
62                 ABIInstances::iterator pos, end = g_plugin_instances.end();
63                 for (pos = g_plugin_instances.begin(); pos != end; ++ pos)
64                 {
65                     if (pos->create_callback == instance.create_callback)
66                     {
67                         g_plugin_instances.erase(pos);
68                         return true;
69                     }
70                 }
71             }
72             break;
73 
74         case ePluginGetInstanceAtIndex:
75             if (index < g_plugin_instances.size())
76             {
77                 instance = g_plugin_instances[index];
78                 return true;
79             }
80             break;
81 
82         default:
83             break;
84     }
85     return false;
86 }
87 
88 
89 bool
90 PluginManager::RegisterPlugin
91     (
92         const char *name,
93         const char *description,
94         ABICreateInstance create_callback
95      )
96 {
97     if (create_callback)
98     {
99         ABIInstance instance;
100         assert (name && name[0]);
101         instance.name = name;
102         if (description && description[0])
103             instance.description = description;
104         instance.create_callback = create_callback;
105         return AccessABIInstances (ePluginRegisterInstance, instance, 0);
106     }
107     return false;
108 }
109 
110 bool
111 PluginManager::UnregisterPlugin (ABICreateInstance create_callback)
112 {
113     if (create_callback)
114     {
115         ABIInstance instance;
116         instance.create_callback = create_callback;
117         return AccessABIInstances (ePluginUnregisterInstance, instance, 0);
118     }
119     return false;
120 }
121 
122 ABICreateInstance
123 PluginManager::GetABICreateCallbackAtIndex (uint32_t idx)
124 {
125     ABIInstance instance;
126     if (AccessABIInstances (ePluginGetInstanceAtIndex, instance, idx))
127         return instance.create_callback;
128     return NULL;
129 }
130 
131 ABICreateInstance
132 PluginManager::GetABICreateCallbackForPluginName (const char *name)
133 {
134     if (name && name[0])
135     {
136         ABIInstance instance;
137         std::string ss_name(name);
138         for (uint32_t idx = 0; AccessABIInstances (ePluginGetInstanceAtIndex, instance, idx); ++idx)
139         {
140             if (instance.name == ss_name)
141                 return instance.create_callback;
142         }
143     }
144     return NULL;
145 }
146 
147 
148 #pragma mark Disassembler
149 
150 
151 struct DisassemblerInstance
152 {
153     DisassemblerInstance() :
154         name(),
155         description(),
156         create_callback(NULL)
157     {
158     }
159 
160     std::string name;
161     std::string description;
162     DisassemblerCreateInstance create_callback;
163 };
164 
165 typedef std::vector<DisassemblerInstance> DisassemblerInstances;
166 
167 static bool
168 AccessDisassemblerInstances (PluginAction action, DisassemblerInstance &instance, uint32_t index)
169 {
170     static DisassemblerInstances g_plugin_instances;
171 
172     switch (action)
173     {
174     case ePluginRegisterInstance:
175         if (instance.create_callback)
176         {
177             g_plugin_instances.push_back (instance);
178             return true;
179         }
180         break;
181 
182     case ePluginUnregisterInstance:
183         if (instance.create_callback)
184         {
185             DisassemblerInstances::iterator pos, end = g_plugin_instances.end();
186             for (pos = g_plugin_instances.begin(); pos != end; ++ pos)
187             {
188                 if (pos->create_callback == instance.create_callback)
189                 {
190                     g_plugin_instances.erase(pos);
191                     return true;
192                 }
193             }
194         }
195         break;
196 
197     case ePluginGetInstanceAtIndex:
198         if (index < g_plugin_instances.size())
199         {
200             instance = g_plugin_instances[index];
201             return true;
202         }
203         break;
204 
205     default:
206         break;
207     }
208     return false;
209 }
210 
211 
212 bool
213 PluginManager::RegisterPlugin
214 (
215     const char *name,
216     const char *description,
217     DisassemblerCreateInstance create_callback
218 )
219 {
220     if (create_callback)
221     {
222         DisassemblerInstance instance;
223         assert (name && name[0]);
224         instance.name = name;
225         if (description && description[0])
226             instance.description = description;
227         instance.create_callback = create_callback;
228         return AccessDisassemblerInstances (ePluginRegisterInstance, instance, 0);
229     }
230     return false;
231 }
232 
233 bool
234 PluginManager::UnregisterPlugin (DisassemblerCreateInstance create_callback)
235 {
236     if (create_callback)
237     {
238         DisassemblerInstance instance;
239         instance.create_callback = create_callback;
240         return AccessDisassemblerInstances (ePluginUnregisterInstance, instance, 0);
241     }
242     return false;
243 }
244 
245 DisassemblerCreateInstance
246 PluginManager::GetDisassemblerCreateCallbackAtIndex (uint32_t idx)
247 {
248     DisassemblerInstance instance;
249     if (AccessDisassemblerInstances (ePluginGetInstanceAtIndex, instance, idx))
250         return instance.create_callback;
251     return NULL;
252 }
253 
254 DisassemblerCreateInstance
255 PluginManager::GetDisassemblerCreateCallbackForPluginName (const char *name)
256 {
257     if (name && name[0])
258     {
259         DisassemblerInstance instance;
260         std::string ss_name(name);
261         for (uint32_t idx = 0; AccessDisassemblerInstances (ePluginGetInstanceAtIndex, instance, idx); ++idx)
262         {
263             if (instance.name == ss_name)
264                 return instance.create_callback;
265         }
266     }
267     return NULL;
268 }
269 
270 
271 
272 #pragma mark DynamicLoader
273 
274 
275 struct DynamicLoaderInstance
276 {
277     DynamicLoaderInstance() :
278         name(),
279         description(),
280         create_callback(NULL)
281     {
282     }
283 
284     std::string name;
285     std::string description;
286     DynamicLoaderCreateInstance create_callback;
287 };
288 
289 typedef std::vector<DynamicLoaderInstance> DynamicLoaderInstances;
290 
291 static bool
292 AccessDynamicLoaderInstances (PluginAction action, DynamicLoaderInstance &instance, uint32_t index)
293 {
294     static DynamicLoaderInstances g_plugin_instances;
295 
296     switch (action)
297     {
298     case ePluginRegisterInstance:
299         if (instance.create_callback)
300         {
301             g_plugin_instances.push_back (instance);
302             return true;
303         }
304         break;
305 
306     case ePluginUnregisterInstance:
307         if (instance.create_callback)
308         {
309             DynamicLoaderInstances::iterator pos, end = g_plugin_instances.end();
310             for (pos = g_plugin_instances.begin(); pos != end; ++ pos)
311             {
312                 if (pos->create_callback == instance.create_callback)
313                 {
314                     g_plugin_instances.erase(pos);
315                     return true;
316                 }
317             }
318         }
319         break;
320 
321     case ePluginGetInstanceAtIndex:
322         if (index < g_plugin_instances.size())
323         {
324             instance = g_plugin_instances[index];
325             return true;
326         }
327         break;
328 
329     default:
330         break;
331     }
332     return false;
333 }
334 
335 
336 bool
337 PluginManager::RegisterPlugin
338 (
339     const char *name,
340     const char *description,
341     DynamicLoaderCreateInstance create_callback
342 )
343 {
344     if (create_callback)
345     {
346         DynamicLoaderInstance instance;
347         assert (name && name[0]);
348         instance.name = name;
349         if (description && description[0])
350             instance.description = description;
351         instance.create_callback = create_callback;
352         return AccessDynamicLoaderInstances (ePluginRegisterInstance, instance, 0);
353     }
354     return false;
355 }
356 
357 bool
358 PluginManager::UnregisterPlugin (DynamicLoaderCreateInstance create_callback)
359 {
360     if (create_callback)
361     {
362         DynamicLoaderInstance instance;
363         instance.create_callback = create_callback;
364         return AccessDynamicLoaderInstances (ePluginUnregisterInstance, instance, 0);
365     }
366     return false;
367 }
368 
369 DynamicLoaderCreateInstance
370 PluginManager::GetDynamicLoaderCreateCallbackAtIndex (uint32_t idx)
371 {
372     DynamicLoaderInstance instance;
373     if (AccessDynamicLoaderInstances (ePluginGetInstanceAtIndex, instance, idx))
374         return instance.create_callback;
375     return NULL;
376 }
377 
378 DynamicLoaderCreateInstance
379 PluginManager::GetDynamicLoaderCreateCallbackForPluginName (const char *name)
380 {
381     if (name && name[0])
382     {
383         DynamicLoaderInstance instance;
384         std::string ss_name(name);
385         for (uint32_t idx = 0; AccessDynamicLoaderInstances (ePluginGetInstanceAtIndex, instance, idx); ++idx)
386         {
387             if (instance.name == ss_name)
388                 return instance.create_callback;
389         }
390     }
391     return NULL;
392 }
393 
394 
395 #pragma mark LanguageRuntime
396 
397 
398 struct LanguageRuntimeInstance
399 {
400     LanguageRuntimeInstance() :
401         name(),
402         description(),
403         create_callback(NULL)
404     {
405     }
406 
407     std::string name;
408     std::string description;
409     LanguageRuntimeCreateInstance create_callback;
410 };
411 
412 typedef std::vector<LanguageRuntimeInstance> LanguageRuntimeInstances;
413 
414 static bool
415 AccessLanguageRuntimeInstances (PluginAction action, LanguageRuntimeInstance &instance, uint32_t index)
416 {
417     static LanguageRuntimeInstances g_plugin_instances;
418 
419     switch (action)
420     {
421         case ePluginRegisterInstance:
422             if (instance.create_callback)
423             {
424                 g_plugin_instances.push_back (instance);
425                 return true;
426             }
427             break;
428 
429         case ePluginUnregisterInstance:
430             if (instance.create_callback)
431             {
432                 LanguageRuntimeInstances::iterator pos, end = g_plugin_instances.end();
433                 for (pos = g_plugin_instances.begin(); pos != end; ++ pos)
434                 {
435                     if (pos->create_callback == instance.create_callback)
436                     {
437                         g_plugin_instances.erase(pos);
438                         return true;
439                     }
440                 }
441             }
442             break;
443 
444         case ePluginGetInstanceAtIndex:
445             if (index < g_plugin_instances.size())
446             {
447                 instance = g_plugin_instances[index];
448                 return true;
449             }
450             break;
451 
452         default:
453             break;
454     }
455     return false;
456 }
457 
458 
459 bool
460 PluginManager::RegisterPlugin
461     (
462         const char *name,
463         const char *description,
464         LanguageRuntimeCreateInstance create_callback
465      )
466 {
467     if (create_callback)
468     {
469         LanguageRuntimeInstance instance;
470         assert (name && name[0]);
471         instance.name = name;
472         if (description && description[0])
473             instance.description = description;
474         instance.create_callback = create_callback;
475         return AccessLanguageRuntimeInstances (ePluginRegisterInstance, instance, 0);
476     }
477     return false;
478 }
479 
480 bool
481 PluginManager::UnregisterPlugin (LanguageRuntimeCreateInstance create_callback)
482 {
483     if (create_callback)
484     {
485         LanguageRuntimeInstance instance;
486         instance.create_callback = create_callback;
487         return AccessLanguageRuntimeInstances (ePluginUnregisterInstance, instance, 0);
488     }
489     return false;
490 }
491 
492 LanguageRuntimeCreateInstance
493 PluginManager::GetLanguageRuntimeCreateCallbackAtIndex (uint32_t idx)
494 {
495     LanguageRuntimeInstance instance;
496     if (AccessLanguageRuntimeInstances (ePluginGetInstanceAtIndex, instance, idx))
497         return instance.create_callback;
498     return NULL;
499 }
500 
501 LanguageRuntimeCreateInstance
502 PluginManager::GetLanguageRuntimeCreateCallbackForPluginName (const char *name)
503 {
504     if (name && name[0])
505     {
506         LanguageRuntimeInstance instance;
507         std::string ss_name(name);
508         for (uint32_t idx = 0; AccessLanguageRuntimeInstances (ePluginGetInstanceAtIndex, instance, idx); ++idx)
509         {
510             if (instance.name == ss_name)
511                 return instance.create_callback;
512         }
513     }
514     return NULL;
515 }
516 
517 #pragma mark ObjectFile
518 
519 struct ObjectFileInstance
520 {
521     ObjectFileInstance() :
522         name(),
523         description(),
524         create_callback(NULL)
525     {
526     }
527 
528     std::string name;
529     std::string description;
530     ObjectFileCreateInstance create_callback;
531 };
532 
533 typedef std::vector<ObjectFileInstance> ObjectFileInstances;
534 
535 static bool
536 AccessObjectFileInstances (PluginAction action, ObjectFileInstance &instance, uint32_t index)
537 {
538     static ObjectFileInstances g_plugin_instances;
539 
540     switch (action)
541     {
542     case ePluginRegisterInstance:
543         if (instance.create_callback)
544         {
545             g_plugin_instances.push_back (instance);
546             return true;
547         }
548         break;
549 
550     case ePluginUnregisterInstance:
551         if (instance.create_callback)
552         {
553             ObjectFileInstances::iterator pos, end = g_plugin_instances.end();
554             for (pos = g_plugin_instances.begin(); pos != end; ++ pos)
555             {
556                 if (pos->create_callback == instance.create_callback)
557                 {
558                     g_plugin_instances.erase(pos);
559                     return true;
560                 }
561             }
562         }
563         break;
564 
565     case ePluginGetInstanceAtIndex:
566         if (index < g_plugin_instances.size())
567         {
568             instance = g_plugin_instances[index];
569             return true;
570         }
571         break;
572 
573     default:
574         break;
575     }
576     return false;
577 }
578 
579 
580 bool
581 PluginManager::RegisterPlugin
582 (
583     const char *name,
584     const char *description,
585     ObjectFileCreateInstance create_callback
586 )
587 {
588     if (create_callback)
589     {
590         ObjectFileInstance instance;
591         assert (name && name[0]);
592         instance.name = name;
593         if (description && description[0])
594             instance.description = description;
595         instance.create_callback = create_callback;
596         return AccessObjectFileInstances (ePluginRegisterInstance, instance, 0);
597     }
598     return false;
599 }
600 
601 bool
602 PluginManager::UnregisterPlugin (ObjectFileCreateInstance create_callback)
603 {
604     if (create_callback)
605     {
606         ObjectFileInstance instance;
607         instance.create_callback = create_callback;
608         return AccessObjectFileInstances (ePluginUnregisterInstance, instance, 0);
609     }
610     return false;
611 }
612 
613 ObjectFileCreateInstance
614 PluginManager::GetObjectFileCreateCallbackAtIndex (uint32_t idx)
615 {
616     ObjectFileInstance instance;
617     if (AccessObjectFileInstances (ePluginGetInstanceAtIndex, instance, idx))
618         return instance.create_callback;
619     return NULL;
620 }
621 ObjectFileCreateInstance
622 PluginManager::GetObjectFileCreateCallbackForPluginName (const char *name)
623 {
624     if (name && name[0])
625     {
626         ObjectFileInstance instance;
627         std::string ss_name(name);
628         for (uint32_t idx = 0; AccessObjectFileInstances (ePluginGetInstanceAtIndex, instance, idx); ++idx)
629         {
630             if (instance.name == ss_name)
631                 return instance.create_callback;
632         }
633     }
634     return NULL;
635 }
636 
637 
638 
639 #pragma mark ObjectContainer
640 
641 struct ObjectContainerInstance
642 {
643     ObjectContainerInstance() :
644         name(),
645         description(),
646         create_callback(NULL)
647     {
648     }
649 
650     std::string name;
651     std::string description;
652     ObjectContainerCreateInstance create_callback;
653 };
654 
655 typedef std::vector<ObjectContainerInstance> ObjectContainerInstances;
656 
657 static bool
658 AccessObjectContainerInstances (PluginAction action, ObjectContainerInstance &instance, uint32_t index)
659 {
660     static ObjectContainerInstances g_plugin_instances;
661 
662     switch (action)
663     {
664     case ePluginRegisterInstance:
665         if (instance.create_callback)
666         {
667             g_plugin_instances.push_back (instance);
668             return true;
669         }
670         break;
671 
672     case ePluginUnregisterInstance:
673         if (instance.create_callback)
674         {
675             ObjectContainerInstances::iterator pos, end = g_plugin_instances.end();
676             for (pos = g_plugin_instances.begin(); pos != end; ++ pos)
677             {
678                 if (pos->create_callback == instance.create_callback)
679                 {
680                     g_plugin_instances.erase(pos);
681                     return true;
682                 }
683             }
684         }
685         break;
686 
687     case ePluginGetInstanceAtIndex:
688         if (index < g_plugin_instances.size())
689         {
690             instance = g_plugin_instances[index];
691             return true;
692         }
693         break;
694 
695     default:
696         break;
697     }
698     return false;
699 }
700 
701 
702 bool
703 PluginManager::RegisterPlugin
704 (
705     const char *name,
706     const char *description,
707     ObjectContainerCreateInstance create_callback
708 )
709 {
710     if (create_callback)
711     {
712         ObjectContainerInstance instance;
713         assert (name && name[0]);
714         instance.name = name;
715         if (description && description[0])
716             instance.description = description;
717         instance.create_callback = create_callback;
718         return AccessObjectContainerInstances (ePluginRegisterInstance, instance, 0);
719     }
720     return false;
721 }
722 
723 bool
724 PluginManager::UnregisterPlugin (ObjectContainerCreateInstance create_callback)
725 {
726     if (create_callback)
727     {
728         ObjectContainerInstance instance;
729         instance.create_callback = create_callback;
730         return AccessObjectContainerInstances (ePluginUnregisterInstance, instance, 0);
731     }
732     return false;
733 }
734 
735 ObjectContainerCreateInstance
736 PluginManager::GetObjectContainerCreateCallbackAtIndex (uint32_t idx)
737 {
738     ObjectContainerInstance instance;
739     if (AccessObjectContainerInstances (ePluginGetInstanceAtIndex, instance, idx))
740         return instance.create_callback;
741     return NULL;
742 }
743 ObjectContainerCreateInstance
744 PluginManager::GetObjectContainerCreateCallbackForPluginName (const char *name)
745 {
746     if (name && name[0])
747     {
748         ObjectContainerInstance instance;
749         std::string ss_name(name);
750         for (uint32_t idx = 0; AccessObjectContainerInstances (ePluginGetInstanceAtIndex, instance, idx); ++idx)
751         {
752             if (instance.name == ss_name)
753                 return instance.create_callback;
754         }
755     }
756     return NULL;
757 }
758 
759 #pragma mark LogChannel
760 
761 struct LogChannelInstance
762 {
763     LogChannelInstance() :
764         name(),
765         description(),
766         create_callback(NULL)
767     {
768     }
769 
770     std::string name;
771     std::string description;
772     LogChannelCreateInstance create_callback;
773 };
774 
775 typedef std::vector<LogChannelInstance> LogChannelInstances;
776 
777 static bool
778 AccessLogChannelInstances (PluginAction action, LogChannelInstance &instance, uint32_t index)
779 {
780     static LogChannelInstances g_plugin_instances;
781 
782     switch (action)
783     {
784     case ePluginRegisterInstance:
785         if (instance.create_callback)
786         {
787             g_plugin_instances.push_back (instance);
788             return true;
789         }
790         break;
791 
792     case ePluginUnregisterInstance:
793         if (instance.create_callback)
794         {
795             LogChannelInstances::iterator pos, end = g_plugin_instances.end();
796             for (pos = g_plugin_instances.begin(); pos != end; ++ pos)
797             {
798                 if (pos->create_callback == instance.create_callback)
799                 {
800                     g_plugin_instances.erase(pos);
801                     return true;
802                 }
803             }
804         }
805         break;
806 
807     case ePluginGetInstanceAtIndex:
808         if (index < g_plugin_instances.size())
809         {
810             instance = g_plugin_instances[index];
811             return true;
812         }
813         break;
814 
815     default:
816         break;
817     }
818     return false;
819 }
820 
821 
822 bool
823 PluginManager::RegisterPlugin
824 (
825     const char *name,
826     const char *description,
827     LogChannelCreateInstance create_callback
828 )
829 {
830     if (create_callback)
831     {
832         LogChannelInstance instance;
833         assert (name && name[0]);
834         instance.name = name;
835         if (description && description[0])
836             instance.description = description;
837         instance.create_callback = create_callback;
838         return AccessLogChannelInstances (ePluginRegisterInstance, instance, 0);
839     }
840     return false;
841 }
842 
843 bool
844 PluginManager::UnregisterPlugin (LogChannelCreateInstance create_callback)
845 {
846     if (create_callback)
847     {
848         LogChannelInstance instance;
849         instance.create_callback = create_callback;
850         return AccessLogChannelInstances (ePluginUnregisterInstance, instance, 0);
851     }
852     return false;
853 }
854 
855 const char *
856 PluginManager::GetLogChannelCreateNameAtIndex (uint32_t idx)
857 {
858     LogChannelInstance instance;
859     if (AccessLogChannelInstances (ePluginGetInstanceAtIndex, instance, idx))
860         return instance.name.c_str();
861     return NULL;
862 }
863 
864 
865 LogChannelCreateInstance
866 PluginManager::GetLogChannelCreateCallbackAtIndex (uint32_t idx)
867 {
868     LogChannelInstance instance;
869     if (AccessLogChannelInstances (ePluginGetInstanceAtIndex, instance, idx))
870         return instance.create_callback;
871     return NULL;
872 }
873 
874 LogChannelCreateInstance
875 PluginManager::GetLogChannelCreateCallbackForPluginName (const char *name)
876 {
877     if (name && name[0])
878     {
879         LogChannelInstance instance;
880         std::string ss_name(name);
881         for (uint32_t idx = 0; AccessLogChannelInstances (ePluginGetInstanceAtIndex, instance, idx); ++idx)
882         {
883             if (instance.name == ss_name)
884                 return instance.create_callback;
885         }
886     }
887     return NULL;
888 }
889 
890 #pragma mark Process
891 
892 struct ProcessInstance
893 {
894     ProcessInstance() :
895         name(),
896         description(),
897         create_callback(NULL)
898     {
899     }
900 
901     std::string name;
902     std::string description;
903     ProcessCreateInstance create_callback;
904 };
905 
906 typedef std::vector<ProcessInstance> ProcessInstances;
907 
908 static bool
909 AccessProcessInstances (PluginAction action, ProcessInstance &instance, uint32_t index)
910 {
911     static ProcessInstances g_plugin_instances;
912 
913     switch (action)
914     {
915     case ePluginRegisterInstance:
916         if (instance.create_callback)
917         {
918             g_plugin_instances.push_back (instance);
919             return true;
920         }
921         break;
922 
923     case ePluginUnregisterInstance:
924         if (instance.create_callback)
925         {
926             ProcessInstances::iterator pos, end = g_plugin_instances.end();
927             for (pos = g_plugin_instances.begin(); pos != end; ++ pos)
928             {
929                 if (pos->create_callback == instance.create_callback)
930                 {
931                     g_plugin_instances.erase(pos);
932                     return true;
933                 }
934             }
935         }
936         break;
937 
938     case ePluginGetInstanceAtIndex:
939         if (index < g_plugin_instances.size())
940         {
941             instance = g_plugin_instances[index];
942             return true;
943         }
944         break;
945 
946     default:
947         break;
948     }
949     return false;
950 }
951 
952 
953 bool
954 PluginManager::RegisterPlugin
955 (
956     const char *name,
957     const char *description,
958     ProcessCreateInstance create_callback
959 )
960 {
961     if (create_callback)
962     {
963         ProcessInstance instance;
964         assert (name && name[0]);
965         instance.name = name;
966         if (description && description[0])
967             instance.description = description;
968         instance.create_callback = create_callback;
969         return AccessProcessInstances (ePluginRegisterInstance, instance, 0);
970     }
971     return false;
972 }
973 
974 bool
975 PluginManager::UnregisterPlugin (ProcessCreateInstance create_callback)
976 {
977     if (create_callback)
978     {
979         ProcessInstance instance;
980         instance.create_callback = create_callback;
981         return AccessProcessInstances (ePluginUnregisterInstance, instance, 0);
982     }
983     return false;
984 }
985 
986 ProcessCreateInstance
987 PluginManager::GetProcessCreateCallbackAtIndex (uint32_t idx)
988 {
989     ProcessInstance instance;
990     if (AccessProcessInstances (ePluginGetInstanceAtIndex, instance, idx))
991         return instance.create_callback;
992     return NULL;
993 }
994 
995 ProcessCreateInstance
996 PluginManager::GetProcessCreateCallbackForPluginName (const char *name)
997 {
998     if (name && name[0])
999     {
1000         ProcessInstance instance;
1001         std::string ss_name(name);
1002         for (uint32_t idx = 0; AccessProcessInstances (ePluginGetInstanceAtIndex, instance, idx); ++idx)
1003         {
1004             if (instance.name == ss_name)
1005                 return instance.create_callback;
1006         }
1007     }
1008     return NULL;
1009 }
1010 
1011 #pragma mark SymbolFile
1012 
1013 struct SymbolFileInstance
1014 {
1015     SymbolFileInstance() :
1016         name(),
1017         description(),
1018         create_callback(NULL)
1019     {
1020     }
1021 
1022     std::string name;
1023     std::string description;
1024     SymbolFileCreateInstance create_callback;
1025 };
1026 
1027 typedef std::vector<SymbolFileInstance> SymbolFileInstances;
1028 
1029 static bool
1030 AccessSymbolFileInstances (PluginAction action, SymbolFileInstance &instance, uint32_t index)
1031 {
1032     static SymbolFileInstances g_plugin_instances;
1033 
1034     switch (action)
1035     {
1036     case ePluginRegisterInstance:
1037         if (instance.create_callback)
1038         {
1039             g_plugin_instances.push_back (instance);
1040             return true;
1041         }
1042         break;
1043 
1044     case ePluginUnregisterInstance:
1045         if (instance.create_callback)
1046         {
1047             SymbolFileInstances::iterator pos, end = g_plugin_instances.end();
1048             for (pos = g_plugin_instances.begin(); pos != end; ++ pos)
1049             {
1050                 if (pos->create_callback == instance.create_callback)
1051                 {
1052                     g_plugin_instances.erase(pos);
1053                     return true;
1054                 }
1055             }
1056         }
1057         break;
1058 
1059     case ePluginGetInstanceAtIndex:
1060         if (index < g_plugin_instances.size())
1061         {
1062             instance = g_plugin_instances[index];
1063             return true;
1064         }
1065         break;
1066 
1067     default:
1068         break;
1069     }
1070     return false;
1071 }
1072 
1073 
1074 bool
1075 PluginManager::RegisterPlugin
1076 (
1077     const char *name,
1078     const char *description,
1079     SymbolFileCreateInstance create_callback
1080 )
1081 {
1082     if (create_callback)
1083     {
1084         SymbolFileInstance instance;
1085         assert (name && name[0]);
1086         instance.name = name;
1087         if (description && description[0])
1088             instance.description = description;
1089         instance.create_callback = create_callback;
1090         return AccessSymbolFileInstances (ePluginRegisterInstance, instance, 0);
1091     }
1092     return false;
1093 }
1094 
1095 bool
1096 PluginManager::UnregisterPlugin (SymbolFileCreateInstance create_callback)
1097 {
1098     if (create_callback)
1099     {
1100         SymbolFileInstance instance;
1101         instance.create_callback = create_callback;
1102         return AccessSymbolFileInstances (ePluginUnregisterInstance, instance, 0);
1103     }
1104     return false;
1105 }
1106 
1107 SymbolFileCreateInstance
1108 PluginManager::GetSymbolFileCreateCallbackAtIndex (uint32_t idx)
1109 {
1110     SymbolFileInstance instance;
1111     if (AccessSymbolFileInstances (ePluginGetInstanceAtIndex, instance, idx))
1112         return instance.create_callback;
1113     return NULL;
1114 }
1115 SymbolFileCreateInstance
1116 PluginManager::GetSymbolFileCreateCallbackForPluginName (const char *name)
1117 {
1118     if (name && name[0])
1119     {
1120         SymbolFileInstance instance;
1121         std::string ss_name(name);
1122         for (uint32_t idx = 0; AccessSymbolFileInstances (ePluginGetInstanceAtIndex, instance, idx); ++idx)
1123         {
1124             if (instance.name == ss_name)
1125                 return instance.create_callback;
1126         }
1127     }
1128     return NULL;
1129 }
1130 
1131 
1132 
1133 #pragma mark SymbolVendor
1134 
1135 struct SymbolVendorInstance
1136 {
1137     SymbolVendorInstance() :
1138         name(),
1139         description(),
1140         create_callback(NULL)
1141     {
1142     }
1143 
1144     std::string name;
1145     std::string description;
1146     SymbolVendorCreateInstance create_callback;
1147 };
1148 
1149 typedef std::vector<SymbolVendorInstance> SymbolVendorInstances;
1150 
1151 static bool
1152 AccessSymbolVendorInstances (PluginAction action, SymbolVendorInstance &instance, uint32_t index)
1153 {
1154     static SymbolVendorInstances g_plugin_instances;
1155 
1156     switch (action)
1157     {
1158     case ePluginRegisterInstance:
1159         if (instance.create_callback)
1160         {
1161             g_plugin_instances.push_back (instance);
1162             return true;
1163         }
1164         break;
1165 
1166     case ePluginUnregisterInstance:
1167         if (instance.create_callback)
1168         {
1169             SymbolVendorInstances::iterator pos, end = g_plugin_instances.end();
1170             for (pos = g_plugin_instances.begin(); pos != end; ++ pos)
1171             {
1172                 if (pos->create_callback == instance.create_callback)
1173                 {
1174                     g_plugin_instances.erase(pos);
1175                     return true;
1176                 }
1177             }
1178         }
1179         break;
1180 
1181     case ePluginGetInstanceAtIndex:
1182         if (index < g_plugin_instances.size())
1183         {
1184             instance = g_plugin_instances[index];
1185             return true;
1186         }
1187         break;
1188 
1189     default:
1190         break;
1191     }
1192     return false;
1193 }
1194 
1195 bool
1196 PluginManager::RegisterPlugin
1197 (
1198     const char *name,
1199     const char *description,
1200     SymbolVendorCreateInstance create_callback
1201 )
1202 {
1203     if (create_callback)
1204     {
1205         SymbolVendorInstance instance;
1206         assert (name && name[0]);
1207         instance.name = name;
1208         if (description && description[0])
1209             instance.description = description;
1210         instance.create_callback = create_callback;
1211         return AccessSymbolVendorInstances (ePluginRegisterInstance, instance, 0);
1212     }
1213     return false;
1214 }
1215 
1216 bool
1217 PluginManager::UnregisterPlugin (SymbolVendorCreateInstance create_callback)
1218 {
1219     if (create_callback)
1220     {
1221         SymbolVendorInstance instance;
1222         instance.create_callback = create_callback;
1223         return AccessSymbolVendorInstances (ePluginUnregisterInstance, instance, 0);
1224     }
1225     return false;
1226 }
1227 
1228 SymbolVendorCreateInstance
1229 PluginManager::GetSymbolVendorCreateCallbackAtIndex (uint32_t idx)
1230 {
1231     SymbolVendorInstance instance;
1232     if (AccessSymbolVendorInstances (ePluginGetInstanceAtIndex, instance, idx))
1233         return instance.create_callback;
1234     return NULL;
1235 }
1236 
1237 SymbolVendorCreateInstance
1238 PluginManager::GetSymbolVendorCreateCallbackForPluginName (const char *name)
1239 {
1240     if (name && name[0])
1241     {
1242         SymbolVendorInstance instance;
1243         std::string ss_name(name);
1244         for (uint32_t idx = 0; AccessSymbolVendorInstances (ePluginGetInstanceAtIndex, instance, idx); ++idx)
1245         {
1246             if (instance.name == ss_name)
1247                 return instance.create_callback;
1248         }
1249     }
1250     return NULL;
1251 }
1252 
1253 
1254 #pragma mark UnwindAssemblyProfiler
1255 
1256 struct UnwindAssemblyProfilerInstance
1257 {
1258     UnwindAssemblyProfilerInstance() :
1259         name(),
1260         description(),
1261         create_callback(NULL)
1262     {
1263     }
1264 
1265     std::string name;
1266     std::string description;
1267     UnwindAssemblyProfilerCreateInstance create_callback;
1268 };
1269 
1270 typedef std::vector<UnwindAssemblyProfilerInstance> UnwindAssemblyProfilerInstances;
1271 
1272 static bool
1273 AccessUnwindAssemblyProfilerInstances (PluginAction action, UnwindAssemblyProfilerInstance &instance, uint32_t index)
1274 {
1275     static UnwindAssemblyProfilerInstances g_plugin_instances;
1276 
1277     switch (action)
1278     {
1279     case ePluginRegisterInstance:
1280         if (instance.create_callback)
1281         {
1282             g_plugin_instances.push_back (instance);
1283             return true;
1284         }
1285         break;
1286 
1287     case ePluginUnregisterInstance:
1288         if (instance.create_callback)
1289         {
1290             UnwindAssemblyProfilerInstances::iterator pos, end = g_plugin_instances.end();
1291             for (pos = g_plugin_instances.begin(); pos != end; ++ pos)
1292             {
1293                 if (pos->create_callback == instance.create_callback)
1294                 {
1295                     g_plugin_instances.erase(pos);
1296                     return true;
1297                 }
1298             }
1299         }
1300         break;
1301 
1302     case ePluginGetInstanceAtIndex:
1303         if (index < g_plugin_instances.size())
1304         {
1305             instance = g_plugin_instances[index];
1306             return true;
1307         }
1308         break;
1309 
1310     default:
1311         break;
1312     }
1313     return false;
1314 }
1315 
1316 bool
1317 PluginManager::RegisterPlugin
1318 (
1319     const char *name,
1320     const char *description,
1321     UnwindAssemblyProfilerCreateInstance create_callback
1322 )
1323 {
1324     if (create_callback)
1325     {
1326         UnwindAssemblyProfilerInstance instance;
1327         assert (name && name[0]);
1328         instance.name = name;
1329         if (description && description[0])
1330             instance.description = description;
1331         instance.create_callback = create_callback;
1332         return AccessUnwindAssemblyProfilerInstances (ePluginRegisterInstance, instance, 0);
1333     }
1334     return false;
1335 }
1336 
1337 bool
1338 PluginManager::UnregisterPlugin (UnwindAssemblyProfilerCreateInstance create_callback)
1339 {
1340     if (create_callback)
1341     {
1342         UnwindAssemblyProfilerInstance instance;
1343         instance.create_callback = create_callback;
1344         return AccessUnwindAssemblyProfilerInstances (ePluginUnregisterInstance, instance, 0);
1345     }
1346     return false;
1347 }
1348 
1349 UnwindAssemblyProfilerCreateInstance
1350 PluginManager::GetUnwindAssemblyProfilerCreateCallbackAtIndex (uint32_t idx)
1351 {
1352     UnwindAssemblyProfilerInstance instance;
1353     if (AccessUnwindAssemblyProfilerInstances (ePluginGetInstanceAtIndex, instance, idx))
1354         return instance.create_callback;
1355     return NULL;
1356 }
1357 
1358 UnwindAssemblyProfilerCreateInstance
1359 PluginManager::GetUnwindAssemblyProfilerCreateCallbackForPluginName (const char *name)
1360 {
1361     if (name && name[0])
1362     {
1363         UnwindAssemblyProfilerInstance instance;
1364         std::string ss_name(name);
1365         for (uint32_t idx = 0; AccessUnwindAssemblyProfilerInstances (ePluginGetInstanceAtIndex, instance, idx); ++idx)
1366         {
1367             if (instance.name == ss_name)
1368                 return instance.create_callback;
1369         }
1370     }
1371     return NULL;
1372 }
1373 
1374 #pragma mark ArchDefaultUnwindPlan
1375 
1376 struct ArchDefaultUnwindPlanInstance
1377 {
1378     ArchDefaultUnwindPlanInstance() :
1379         name(),
1380         description(),
1381         create_callback(NULL)
1382     {
1383     }
1384 
1385     std::string name;
1386     std::string description;
1387     ArchDefaultUnwindPlanCreateInstance create_callback;
1388 };
1389 
1390 typedef std::vector<ArchDefaultUnwindPlanInstance> ArchDefaultUnwindPlanInstances;
1391 
1392 static bool
1393 AccessArchDefaultUnwindPlanInstances (PluginAction action, ArchDefaultUnwindPlanInstance &instance, uint32_t index)
1394 {
1395     static ArchDefaultUnwindPlanInstances g_plugin_instances;
1396 
1397     switch (action)
1398     {
1399     case ePluginRegisterInstance:
1400         if (instance.create_callback)
1401         {
1402             g_plugin_instances.push_back (instance);
1403             return true;
1404         }
1405         break;
1406 
1407     case ePluginUnregisterInstance:
1408         if (instance.create_callback)
1409         {
1410             ArchDefaultUnwindPlanInstances::iterator pos, end = g_plugin_instances.end();
1411             for (pos = g_plugin_instances.begin(); pos != end; ++ pos)
1412             {
1413                 if (pos->create_callback == instance.create_callback)
1414                 {
1415                     g_plugin_instances.erase(pos);
1416                     return true;
1417                 }
1418             }
1419         }
1420         break;
1421 
1422     case ePluginGetInstanceAtIndex:
1423         if (index < g_plugin_instances.size())
1424         {
1425             instance = g_plugin_instances[index];
1426             return true;
1427         }
1428         break;
1429 
1430     default:
1431         break;
1432     }
1433     return false;
1434 }
1435 
1436 bool
1437 PluginManager::RegisterPlugin
1438 (
1439     const char *name,
1440     const char *description,
1441     ArchDefaultUnwindPlanCreateInstance create_callback
1442 )
1443 {
1444     if (create_callback)
1445     {
1446         ArchDefaultUnwindPlanInstance instance;
1447         assert (name && name[0]);
1448         instance.name = name;
1449         if (description && description[0])
1450             instance.description = description;
1451         instance.create_callback = create_callback;
1452         return AccessArchDefaultUnwindPlanInstances (ePluginRegisterInstance, instance, 0);
1453     }
1454     return false;
1455 }
1456 
1457 bool
1458 PluginManager::UnregisterPlugin (ArchDefaultUnwindPlanCreateInstance create_callback)
1459 {
1460     if (create_callback)
1461     {
1462         ArchDefaultUnwindPlanInstance instance;
1463         instance.create_callback = create_callback;
1464         return AccessArchDefaultUnwindPlanInstances (ePluginUnregisterInstance, instance, 0);
1465     }
1466     return false;
1467 }
1468 
1469 ArchDefaultUnwindPlanCreateInstance
1470 PluginManager::GetArchDefaultUnwindPlanCreateCallbackAtIndex (uint32_t idx)
1471 {
1472     ArchDefaultUnwindPlanInstance instance;
1473     if (AccessArchDefaultUnwindPlanInstances (ePluginGetInstanceAtIndex, instance, idx))
1474         return instance.create_callback;
1475     return NULL;
1476 }
1477 
1478 ArchDefaultUnwindPlanCreateInstance
1479 PluginManager::GetArchDefaultUnwindPlanCreateCallbackForPluginName (const char *name)
1480 {
1481     if (name && name[0])
1482     {
1483         ArchDefaultUnwindPlanInstance instance;
1484         std::string ss_name(name);
1485         for (uint32_t idx = 0; AccessArchDefaultUnwindPlanInstances (ePluginGetInstanceAtIndex, instance, idx); ++idx)
1486         {
1487             if (instance.name == ss_name)
1488                 return instance.create_callback;
1489         }
1490     }
1491     return NULL;
1492 }
1493 
1494 #pragma mark ArchVolatileRegs
1495 
1496 struct ArchVolatileRegsInstance
1497 {
1498     ArchVolatileRegsInstance() :
1499         name(),
1500         description(),
1501         create_callback(NULL)
1502     {
1503     }
1504 
1505     std::string name;
1506     std::string description;
1507     ArchVolatileRegsCreateInstance create_callback;
1508 };
1509 
1510 typedef std::vector<ArchVolatileRegsInstance> ArchVolatileRegsInstances;
1511 
1512 static bool
1513 AccessArchVolatileRegsInstances (PluginAction action, ArchVolatileRegsInstance &instance, uint32_t index)
1514 {
1515     static ArchVolatileRegsInstances g_plugin_instances;
1516 
1517     switch (action)
1518     {
1519     case ePluginRegisterInstance:
1520         if (instance.create_callback)
1521         {
1522             g_plugin_instances.push_back (instance);
1523             return true;
1524         }
1525         break;
1526 
1527     case ePluginUnregisterInstance:
1528         if (instance.create_callback)
1529         {
1530             ArchVolatileRegsInstances::iterator pos, end = g_plugin_instances.end();
1531             for (pos = g_plugin_instances.begin(); pos != end; ++ pos)
1532             {
1533                 if (pos->create_callback == instance.create_callback)
1534                 {
1535                     g_plugin_instances.erase(pos);
1536                     return true;
1537                 }
1538             }
1539         }
1540         break;
1541 
1542     case ePluginGetInstanceAtIndex:
1543         if (index < g_plugin_instances.size())
1544         {
1545             instance = g_plugin_instances[index];
1546             return true;
1547         }
1548         break;
1549 
1550     default:
1551         break;
1552     }
1553     return false;
1554 }
1555 
1556 bool
1557 PluginManager::RegisterPlugin
1558 (
1559     const char *name,
1560     const char *description,
1561     ArchVolatileRegsCreateInstance create_callback
1562 )
1563 {
1564     if (create_callback)
1565     {
1566         ArchVolatileRegsInstance instance;
1567         assert (name && name[0]);
1568         instance.name = name;
1569         if (description && description[0])
1570             instance.description = description;
1571         instance.create_callback = create_callback;
1572         return AccessArchVolatileRegsInstances (ePluginRegisterInstance, instance, 0);
1573     }
1574     return false;
1575 }
1576 
1577 bool
1578 PluginManager::UnregisterPlugin (ArchVolatileRegsCreateInstance create_callback)
1579 {
1580     if (create_callback)
1581     {
1582         ArchVolatileRegsInstance instance;
1583         instance.create_callback = create_callback;
1584         return AccessArchVolatileRegsInstances (ePluginUnregisterInstance, instance, 0);
1585     }
1586     return false;
1587 }
1588 
1589 ArchVolatileRegsCreateInstance
1590 PluginManager::GetArchVolatileRegsCreateCallbackAtIndex (uint32_t idx)
1591 {
1592     ArchVolatileRegsInstance instance;
1593     if (AccessArchVolatileRegsInstances (ePluginGetInstanceAtIndex, instance, idx))
1594         return instance.create_callback;
1595     return NULL;
1596 }
1597 
1598 ArchVolatileRegsCreateInstance
1599 PluginManager::GetArchVolatileRegsCreateCallbackForPluginName (const char *name)
1600 {
1601     if (name && name[0])
1602     {
1603         ArchVolatileRegsInstance instance;
1604         std::string ss_name(name);
1605         for (uint32_t idx = 0; AccessArchVolatileRegsInstances (ePluginGetInstanceAtIndex, instance, idx); ++idx)
1606         {
1607             if (instance.name == ss_name)
1608                 return instance.create_callback;
1609         }
1610     }
1611     return NULL;
1612 }
1613 
1614