1 /*
2 * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
4 */
5
6 #include "add_ons.h"
7
8 #include <util/kernel_cpp.h>
9
10 #include "runtime_loader_private.h"
11
12
13 typedef DoublyLinkedList<RuntimeLoaderAddOn> AddOnList;
14
15
16 static status_t register_defined_symbol_patcher(struct image_t* image,
17 runtime_loader_symbol_patcher* _patcher, void* cookie);
18 static void unregister_defined_symbol_patcher(struct image_t* image,
19 runtime_loader_symbol_patcher* _patcher, void* cookie);
20 static status_t register_undefined_symbol_patcher(struct image_t* image,
21 runtime_loader_symbol_patcher* _patcher, void* cookie);
22 static void unregister_undefined_symbol_patcher(struct image_t* image,
23 runtime_loader_symbol_patcher* _patcher, void* cookie);
24
25
26 static AddOnList sAddOns;
27
28 static runtime_loader_add_on_export sRuntimeLoaderAddOnExport = {
29 register_defined_symbol_patcher,
30 unregister_defined_symbol_patcher,
31 register_undefined_symbol_patcher,
32 unregister_undefined_symbol_patcher
33 };
34
35
36 // #pragma mark - add-on support functions
37
38
39 static status_t
register_defined_symbol_patcher(struct image_t * image,runtime_loader_symbol_patcher * _patcher,void * cookie)40 register_defined_symbol_patcher(struct image_t* image,
41 runtime_loader_symbol_patcher* _patcher, void* cookie)
42 {
43 RuntimeLoaderSymbolPatcher* patcher
44 = new(mynothrow) RuntimeLoaderSymbolPatcher(_patcher, cookie);
45 if (patcher == NULL)
46 return B_NO_MEMORY;
47
48 patcher->next = image->defined_symbol_patchers;
49 image->defined_symbol_patchers = patcher;
50
51 return B_OK;
52 }
53
54
55 static void
unregister_defined_symbol_patcher(struct image_t * image,runtime_loader_symbol_patcher * _patcher,void * cookie)56 unregister_defined_symbol_patcher(struct image_t* image,
57 runtime_loader_symbol_patcher* _patcher, void* cookie)
58 {
59 RuntimeLoaderSymbolPatcher** patcher = &image->defined_symbol_patchers;
60 while (*patcher != NULL) {
61 if ((*patcher)->patcher == _patcher && (*patcher)->cookie == cookie) {
62 RuntimeLoaderSymbolPatcher* toDelete = *patcher;
63 *patcher = (*patcher)->next;
64 delete toDelete;
65 return;
66 }
67 patcher = &(*patcher)->next;
68 }
69 }
70
71
72 static status_t
register_undefined_symbol_patcher(struct image_t * image,runtime_loader_symbol_patcher * _patcher,void * cookie)73 register_undefined_symbol_patcher(struct image_t* image,
74 runtime_loader_symbol_patcher* _patcher, void* cookie)
75 {
76 RuntimeLoaderSymbolPatcher* patcher
77 = new(mynothrow) RuntimeLoaderSymbolPatcher(_patcher, cookie);
78 if (patcher == NULL)
79 return B_NO_MEMORY;
80
81 patcher->next = image->undefined_symbol_patchers;
82 image->undefined_symbol_patchers = patcher;
83
84 return B_OK;
85 }
86
87
88 static void
unregister_undefined_symbol_patcher(struct image_t * image,runtime_loader_symbol_patcher * _patcher,void * cookie)89 unregister_undefined_symbol_patcher(struct image_t* image,
90 runtime_loader_symbol_patcher* _patcher, void* cookie)
91 {
92 RuntimeLoaderSymbolPatcher** patcher = &image->undefined_symbol_patchers;
93 while (*patcher != NULL) {
94 if ((*patcher)->patcher == _patcher && (*patcher)->cookie == cookie) {
95 RuntimeLoaderSymbolPatcher* toDelete = *patcher;
96 *patcher = (*patcher)->next;
97 delete toDelete;
98 return;
99 }
100 patcher = &(*patcher)->next;
101 }
102 }
103
104
105 // #pragma mark -
106
107
108 void
init_add_ons()109 init_add_ons()
110 {
111 // invoke static constructors
112 new(&sAddOns) AddOnList;
113 }
114
115
116 status_t
add_add_on(image_t * image,runtime_loader_add_on * addOnStruct)117 add_add_on(image_t* image, runtime_loader_add_on* addOnStruct)
118 {
119 RuntimeLoaderAddOn* addOn = new(mynothrow) RuntimeLoaderAddOn(image,
120 addOnStruct);
121 if (addOn == NULL)
122 return B_NO_MEMORY;
123
124 sAddOns.Add(addOn);
125 addOnStruct->init(&gRuntimeLoader, &sRuntimeLoaderAddOnExport);
126
127 return B_OK;
128 }
129
130
131 void
image_event(image_t * image,uint32 event)132 image_event(image_t* image, uint32 event)
133 {
134 AddOnList::Iterator it = sAddOns.GetIterator();
135 while (RuntimeLoaderAddOn* addOn = it.Next()) {
136 void (*function)(image_t* image) = NULL;
137
138 switch (event) {
139 case IMAGE_EVENT_LOADED:
140 function = addOn->addOn->image_loaded;
141 break;
142 case IMAGE_EVENT_RELOCATED:
143 function = addOn->addOn->image_relocated;
144 break;
145 case IMAGE_EVENT_INITIALIZED:
146 function = addOn->addOn->image_initialized;
147 break;
148 case IMAGE_EVENT_UNINITIALIZING:
149 function = addOn->addOn->image_uninitializing;
150 break;
151 case IMAGE_EVENT_UNLOADING:
152 function = addOn->addOn->image_unloading;
153 break;
154 }
155
156 if (function != NULL)
157 function(image);
158 }
159 }
160