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);
Plugin representation for JSON transfer.
void set_name(const std::string &name)
Set name value.
Interface for configuration handling.
Base class for exceptions in Fawkes.
void copy_messages(const Exception &exc)
Copy messages from given exception.
void append(const char *format,...)
Append messages to the message list.
Dynamic module loader for Linux, FreeBSD, and MacOS X.
virtual void * get_symbol(const char *symbol_name)
Get a symbol from the module.
virtual bool has_symbol(const char *symbol_name)
Check if the module has the given symbol.
This exception is thrown if the requested plugin could not be loaded.
PluginLoadException(const char *plugin, const char *message)
Constructor.
~PluginLoadException()
Destructor.
std::string plugin_name() const
Get name of plugin which failed to load.
bool is_loaded(const char *plugin_name)
Check if a plugin is loaded.
ModuleManager * get_module_manager() const
Get module manager.
std::string get_description(const char *plugin_name)
Get plugin description.
Plugin * load(const char *plugin_name)
Load a specific plugin The plugin loader is clever and guarantees that every plugin is only loaded on...
void unload(Plugin *plugin)
Unload the given plugin This will unload the given plugin.
~PluginLoader()
Destructor.
PluginLoader(const char *plugin_base_dir, Configuration *config)
Constructor.
PluginUnloadException(const char *plugin_type, const char *add_msg=NULL)
Constructor.
Fawkes library namespace.
const char *(* PluginDescriptionFunc)()
Plugin description function for the shared library.