24 #include <plugin/loader.h> 25 #include <utils/system/dynamic_module/module.h> 26 #include <utils/system/dynamic_module/module_manager.h> 42 class PluginLoader::Data
46 std::map<Plugin *, Module *> plugin_module_map;
47 std::map<std::string, Plugin *> name_plugin_map;
48 std::map<Plugin *, std::string> plugin_name_map;
63 append(
"Plugin '%s' could not be loaded: %s", plugin, message);
79 append(
"Plugin '%s' could not be loaded: %s", plugin, message);
103 append(
"Plugin '%s' could not be unloaded", plugin_name);
122 plugin_base_dir_ = plugin_base_dir;
147 PluginLoader::open_module(
const char *plugin_name)
149 std::string module_name = std::string(plugin_name) +
"." + d_->mm->get_module_file_extension();
152 return d_->mm->open_module(module_name.c_str());
153 }
catch (ModuleOpenException &e) {
154 throw PluginLoadException(plugin_name,
"failed to open module", e);
159 PluginLoader::create_instance(
const char *plugin_name, Module *module)
161 if (!module->has_symbol(
"plugin_factory")) {
162 throw PluginLoadException(plugin_name,
163 "Symbol 'plugin_factory' not found. Forgot EXPORT_PLUGIN?");
165 if (!module->has_symbol(
"plugin_description")) {
166 throw PluginLoadException(plugin_name,
167 "Symbol 'plugin_description' not found. Forgot PLUGIN_DESCRIPTION?");
170 PluginFactoryFunc pff = (PluginFactoryFunc)module->get_symbol(
"plugin_factory");
175 throw PluginLoadException(plugin_name,
"Plugin could not be instantiated");
202 std::string pn = plugin_name;
204 if (d_->name_plugin_map.find(pn) != d_->name_plugin_map.end()) {
205 return d_->name_plugin_map[pn];
209 Module *module = open_module(plugin_name);
210 Plugin *p = create_instance(plugin_name, module);
212 d_->plugin_module_map[p] = module;
213 d_->name_plugin_map[pn] = p;
214 d_->plugin_name_map[p] = pn;
230 PluginLoader::get_string_symbol(
const char *plugin_name,
231 const char *symbol_name,
232 const char *section_name)
235 GElf_Ehdr elf_header;
238 std::string module_name =
239 plugin_base_dir_ +
"/" + plugin_name +
"." + d_->mm->get_module_file_extension();
241 if (elf_version(EV_CURRENT) == EV_NONE) {
242 throw Exception(
"libelf library ELF version too old");
245 int fd = open(module_name.c_str(), O_RDONLY);
247 throw Exception(
"Failed to open file of plugin '%s'", plugin_name);
250 elf = elf_begin(fd, ELF_C_READ, NULL);
252 throw Exception(
"Cannot read elf file: %s", elf_errmsg(elf_errno()));
255 if (gelf_getehdr(elf, &elf_header) == NULL) {
257 throw Exception(
"Failed to read ELF header of plugin %s: %s",
259 elf_errmsg(elf_errno()));
263 while ((scn = elf_nextscn(elf, scn)) != 0) {
265 gelf_getshdr(scn, &shdr);
267 if (shdr.sh_type == SHT_SYMTAB) {
268 Elf_Data *edata = elf_getdata(scn, NULL);
269 size_t symbol_count = shdr.sh_size / shdr.sh_entsize;
271 for (
size_t i = 0; i < symbol_count; ++i) {
273 gelf_getsym(edata, i, &sym);
276 Elf_Scn * sym_scn = elf_getscn(elf, sym.st_shndx);
277 gelf_getshdr(sym_scn, &sym_shdr);
279 char *secname = elf_strptr(elf, elf_header.e_shstrndx, sym_shdr.sh_name);
280 char *symname = elf_strptr(elf, shdr.sh_link, sym.st_name);
282 if ((strcmp(secname, section_name) == 0) && (strcmp(symname, symbol_name) == 0)) {
284 Elf_Data * sym_data = elf_rawdata(sym_scn, NULL);
285 const char *start = (
const char *)sym_data->d_buf + (sym.st_value - sym_shdr.sh_offset);
286 const char *
const limit = start + sym.st_size;
287 const char * end = (
const char *)memchr(start,
'\0', limit - start);
291 std::string rv(start);
297 throw Exception(
"Failed to retrieve string for symbol '%s' in section '%s'" 309 throw Exception(
"Description for plugin %s not found. " 310 "Forgot PLUGIN_DESCRIPTION?",
313 throw Exception(
"libelf not supported at compile time");
326 return get_string_symbol(plugin_name,
"_plugin_description");
328 Module *module = open_module(plugin_name);
330 if (!module->
has_symbol(
"plugin_description")) {
332 "Symbol 'plugin_description' not found. Forgot PLUGIN_DESCRIPTION?");
336 std::string rv = pdf();
337 d_->mm->close_module(module);
350 return (d_->name_plugin_map.find(plugin_name) != d_->name_plugin_map.end());
367 if (d_->plugin_module_map.find(plugin) != d_->plugin_module_map.end()) {
368 PluginDestroyFunc pdf =
369 (PluginDestroyFunc)d_->plugin_module_map[plugin]->get_symbol(
"plugin_destroy");
373 d_->mm->close_module(d_->plugin_module_map[plugin]);
374 d_->plugin_module_map.erase(plugin);
376 d_->name_plugin_map.erase(d_->plugin_name_map[plugin]);
377 d_->plugin_name_map.erase(plugin);
PluginLoader(const char *plugin_base_dir, Configuration *config)
Constructor.
PluginUnloadException(const char *plugin_type, const char *add_msg=NULL)
Constructor.
Fawkes library namespace.
This exception is thrown if the requested plugin could not be loaded.
~PluginLoadException()
Destructor.
PluginLoadException(const char *plugin, const char *message)
Constructor.
void unload(Plugin *plugin)
Unload the given plugin This will unload the given plugin.
Plugin representation for JSON transfer.
Dynamic module loader for Linux, FreeBSD, and MacOS X.
Base class for exceptions in Fawkes.
std::string get_description(const char *plugin_name)
Get plugin description.
std::string plugin_name() const
Get name of plugin which failed to load.
const char *(* PluginDescriptionFunc)()
Plugin description function for the shared library.
virtual void * get_symbol(const char *symbol_name)
Get a symbol from the module.
void copy_messages(const Exception &exc)
Copy messages from given exception.
ModuleManager * get_module_manager() const
Get module manager.
bool is_loaded(const char *plugin_name)
Check if a plugin is loaded.
void set_name(const std::string &name)
Set name value.
~PluginLoader()
Destructor.
Interface for configuration handling.
void append(const char *format,...)
Append messages to the message list.
virtual bool has_symbol(const char *symbol_name)
Check if the module has the given symbol.
Plugin * load(const char *plugin_name)
Load a specific plugin The plugin loader is clever and guarantees that every plugin is only loaded on...