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