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
13typedef DoublyLinkedList<RuntimeLoaderAddOn> AddOnList;
14
15
16static status_t register_defined_symbol_patcher(struct image_t* image,
17	runtime_loader_symbol_patcher* _patcher, void* cookie);
18static void unregister_defined_symbol_patcher(struct image_t* image,
19	runtime_loader_symbol_patcher* _patcher, void* cookie);
20static status_t register_undefined_symbol_patcher(struct image_t* image,
21	runtime_loader_symbol_patcher* _patcher, void* cookie);
22static void unregister_undefined_symbol_patcher(struct image_t* image,
23	runtime_loader_symbol_patcher* _patcher, void* cookie);
24
25
26static AddOnList sAddOns;
27
28static 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
39static status_t
40register_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
55static void
56unregister_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
72static status_t
73register_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
88static void
89unregister_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
108void
109init_add_ons()
110{
111	// invoke static constructors
112	new(&sAddOns) AddOnList;
113}
114
115
116status_t
117add_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
131void
132image_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