xref: /haiku/src/system/runtime_loader/add_ons.cpp (revision 1deede7388b04dbeec5af85cae7164735ea9e70d)
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
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
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
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
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
109 init_add_ons()
110 {
111 	// invoke static constructors
112 	new(&sAddOns) AddOnList;
113 }
114 
115 
116 status_t
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
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